Pol  Revision:cb584c9
polsem.cpp
Go to the documentation of this file.
1 
7 #include "polsem.h"
8 
9 #include <time.h>
10 
11 #include "../clib/logfacility.h"
12 #include "../clib/passert.h"
13 #include "../clib/threadhelp.h"
14 #include "../clib/tracebuf.h"
15 
16 #ifdef _WIN32
17 #include <process.h>
18 #else
19 #include <pthread.h>
20 #include <sys/time.h>
21 #endif
22 
23 namespace Pol
24 {
25 namespace Core
26 {
27 size_t locker;
28 #ifdef _WIN32
29 void polsem_lock()
30 {
31  size_t tid = threadhelp::thread_pid();
32  EnterCriticalSection( &cs );
33  passert_always( locker == 0 );
34  locker = tid;
35 }
36 
37 void polsem_unlock()
38 {
39  size_t tid = GetCurrentThreadId();
40  passert_always( locker == tid );
41  locker = 0;
42  LeaveCriticalSection( &cs );
43 }
44 #else
46 {
47  size_t tid = threadhelp::thread_pid();
48  int res = pthread_mutex_lock( &polsem );
49  if ( res != 0 || locker != 0 )
50  {
51  POLLOG.Format( "pthread_mutex_lock: res={}, tid={}, locker={}\n" ) << res << tid << locker;
52  }
53  passert_always( res == 0 );
54  passert_always( locker == 0 );
55  locker = tid;
56 }
58 {
59  size_t tid = threadhelp::thread_pid();
60  passert_always( locker == tid );
61  locker = 0;
62  int res = pthread_mutex_unlock( &polsem );
63  if ( res != 0 )
64  {
65  POLLOG.Format( "pthread_mutex_unlock: res={},tid={}" ) << res << tid;
66  }
67  passert_always( res == 0 );
68 }
69 
70 #endif
71 
72 
73 #ifdef _WIN32
74 CRITICAL_SECTION cs;
75 HANDLE hEvPulse;
76 
77 HANDLE hEvTasksThread;
78 HANDLE hEvClientTransmit;
79 
80 CRITICAL_SECTION csThread;
81 HANDLE hSemThread;
82 
83 void init_ipc_vars()
84 {
85  InitializeCriticalSection( &cs );
86  hEvPulse = CreateEvent( nullptr, TRUE, FALSE, nullptr );
87 
88  hEvTasksThread = CreateEvent( nullptr, FALSE, FALSE, nullptr );
89 
90  hEvClientTransmit = CreateEvent( nullptr, TRUE, FALSE, nullptr );
91 
92  InitializeCriticalSection( &csThread );
93  hSemThread = CreateSemaphore( nullptr, 0, 1, nullptr );
94 }
95 
96 void deinit_ipc_vars()
97 {
98  CloseHandle( hSemThread );
99  DeleteCriticalSection( &csThread );
100 
101  CloseHandle( hEvTasksThread );
102  hEvTasksThread = nullptr;
103 
104  CloseHandle( hEvPulse );
105  CloseHandle( hEvClientTransmit );
106  DeleteCriticalSection( &cs );
107 }
108 void send_pulse()
109 {
110  TRACEBUF_ADDELEM( "Pulse", 1 );
111  PulseEvent( hEvPulse );
112 }
113 
114 void wait_for_pulse( unsigned int millis )
115 {
116  WaitForSingleObject( hEvPulse, millis );
117 }
118 
119 void wake_tasks_thread()
120 {
121  SetEvent( hEvTasksThread );
122 }
123 
124 void tasks_thread_sleep( unsigned int millis )
125 {
126  WaitForSingleObject( hEvTasksThread, millis );
127 }
128 
130 {
131  TRACEBUF_ADDELEM( "ClientTransmitPulse", 1 );
132  PulseEvent( hEvClientTransmit );
133 }
134 
135 void wait_for_ClientTransmit_pulse( unsigned int millis )
136 {
137  WaitForSingleObject( hEvClientTransmit, millis );
138 }
139 #else
140 
141 pthread_mutexattr_t polsem_attr;
142 pthread_mutex_t polsem;
143 // pthread_mutex_t polsem = PTHREAD_MUTEX_INITIALIZER;
144 // pthread_mutex_t polsem = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
145 
146 pthread_mutex_t pulse_mut = PTHREAD_MUTEX_INITIALIZER;
147 pthread_cond_t pulse_cond = PTHREAD_COND_INITIALIZER;
148 
149 pthread_mutex_t clienttransmit_pulse_mut = PTHREAD_MUTEX_INITIALIZER;
150 pthread_cond_t clienttransmit_pulse_cond = PTHREAD_COND_INITIALIZER;
151 
152 pthread_mutex_t task_pulse_mut = PTHREAD_MUTEX_INITIALIZER;
153 pthread_cond_t task_pulse_cond = PTHREAD_COND_INITIALIZER;
154 
155 pthread_mutex_t threadstart_mut = PTHREAD_MUTEX_INITIALIZER;
156 pthread_mutex_t threadstart_pulse_mut = PTHREAD_MUTEX_INITIALIZER;
157 pthread_cond_t threadstart_pulse_cond = PTHREAD_COND_INITIALIZER;
159 
160 
161 pthread_mutex_t polsemdbg_mut = PTHREAD_MUTEX_INITIALIZER;
162 
163 pthread_attr_t thread_attr;
164 
166 {
167  int res;
168  res = pthread_mutexattr_init( &polsem_attr );
169  passert_always( res == 0 );
170 
171  /*
172  res = pthread_mutexattr_setkind_np( &polsem_attr, PTHREAD_MUTEX_ERRORCHECK_NP );
173  passert_always( res == 0 );
174 
175  res = pthread_mutexattr_settype( &polsem_attr, PTHREAD_MUTEX_ERRORCHECK );
176  passert_always( res == 0 );
177  */
178 
179  res = pthread_mutex_init( &polsem, &polsem_attr );
180  passert_always( res == 0 );
181 
182  pthread_attr_init( &thread_attr );
183  pthread_attr_setdetachstate( &thread_attr, PTHREAD_CREATE_DETACHED );
184 }
185 
187 
189 {
190  pthread_mutex_lock( &pulse_mut );
191  pthread_cond_broadcast( &pulse_cond );
192  pthread_mutex_unlock( &pulse_mut );
193 }
194 
195 void calc_abs_timeout( struct timespec* ptimeout, unsigned int millis )
196 {
197  struct timeval now;
198  struct timezone tz;
199 
200  gettimeofday( &now, &tz );
201  int add_sec = 0;
202  if ( millis > 1000 )
203  {
204  add_sec = millis / 1000;
205  millis -= ( add_sec * 1000 );
206  }
207  ptimeout->tv_sec = now.tv_sec + add_sec;
208 
209  ptimeout->tv_nsec = now.tv_usec * 1000 + millis * 1000000L;
210  if ( ptimeout->tv_nsec >= 1000000000 )
211  {
212  ++ptimeout->tv_sec;
213  ptimeout->tv_nsec -= 1000000000;
214  }
215 }
216 
217 void wait_for_pulse( unsigned int millis )
218 {
219  struct timespec timeout;
220 
221  pthread_mutex_lock( &pulse_mut );
222 
223  calc_abs_timeout( &timeout, millis );
224 
225  pthread_cond_timedwait( &pulse_cond, &pulse_mut, &timeout );
226 
227  pthread_mutex_unlock( &pulse_mut );
228 }
229 
231 {
232  pthread_mutex_lock( &task_pulse_mut );
233  pthread_cond_broadcast( &task_pulse_cond );
234  pthread_mutex_unlock( &task_pulse_mut );
235 }
236 
237 void tasks_thread_sleep( unsigned int millis )
238 {
239  struct timespec timeout;
240 
241  pthread_mutex_lock( &task_pulse_mut );
242 
243  calc_abs_timeout( &timeout, millis );
244 
245  pthread_cond_timedwait( &task_pulse_cond, &task_pulse_mut, &timeout );
246 
247  pthread_mutex_unlock( &task_pulse_mut );
248 }
249 
251 {
252  pthread_mutex_lock( &clienttransmit_pulse_mut );
253  pthread_cond_broadcast( &clienttransmit_pulse_cond );
254  pthread_mutex_unlock( &clienttransmit_pulse_mut );
255 }
256 
257 void wait_for_ClientTransmit_pulse( unsigned int millis )
258 {
259  struct timespec timeout;
260 
261  pthread_mutex_lock( &clienttransmit_pulse_mut );
262 
263  calc_abs_timeout( &timeout, millis );
264 
265  pthread_cond_timedwait( &clienttransmit_pulse_cond, &clienttransmit_pulse_mut, &timeout );
266 
267  pthread_mutex_unlock( &clienttransmit_pulse_mut );
268 }
269 
270 #endif
271 }
272 }
pthread_mutex_t clienttransmit_pulse_mut
Definition: polsem.cpp:149
pthread_cond_t clienttransmit_pulse_cond
Definition: polsem.cpp:150
pthread_mutex_t polsem
Definition: polsem.cpp:142
void polsem_unlock()
Definition: polsem.cpp:57
pthread_mutex_t task_pulse_mut
Definition: polsem.cpp:152
void send_pulse()
Definition: polsem.cpp:188
void wake_tasks_thread()
Definition: polsem.cpp:230
size_t thread_pid()
Definition: threadhelp.cpp:107
void send_ClientTransmit_pulse()
Definition: polsem.cpp:250
#define TRACEBUF_ADDELEM(tag, value)
Definition: tracebuf.h:45
void init_ipc_vars()
Definition: polsem.cpp:165
void wait_for_ClientTransmit_pulse(unsigned int millis)
Definition: polsem.cpp:257
pthread_cond_t threadstart_pulse_cond
Definition: polsem.cpp:157
size_t locker
Definition: polsem.cpp:27
void polsem_lock()
Definition: polsem.cpp:45
bool thread_started
Definition: polsem.cpp:158
#define POLLOG
Definition: logfacility.h:219
void deinit_ipc_vars()
Definition: polsem.cpp:186
void calc_abs_timeout(struct timespec *ptimeout, unsigned int millis)
Definition: polsem.cpp:195
pthread_mutex_t polsemdbg_mut
Definition: polsem.cpp:161
pthread_cond_t task_pulse_cond
Definition: polsem.cpp:153
pthread_cond_t pulse_cond
Definition: polsem.cpp:147
pthread_mutex_t pulse_mut
Definition: polsem.cpp:146
#define passert_always(exp)
Definition: passert.h:80
pthread_attr_t thread_attr
Definition: polsem.cpp:163
void tasks_thread_sleep(unsigned int millis)
Definition: polsem.cpp:237
pthread_mutex_t threadstart_pulse_mut
Definition: polsem.cpp:156
pthread_mutex_t threadstart_mut
Definition: polsem.cpp:155
pthread_mutexattr_t polsem_attr
Definition: polsem.cpp:141
Definition: berror.cpp:12
void wait_for_pulse(unsigned int millis)
Definition: polsem.cpp:217