xrootd
XrdSysPthread.hh
Go to the documentation of this file.
1 #ifndef __SYS_PTHREAD__
2 #define __SYS_PTHREAD__
3 /******************************************************************************/
4 /* */
5 /* X r d S y s P t h r e a d . h h */
6 /* */
7 /* (c) 2004 by the Board of Trustees of the Leland Stanford, Jr., University */
8 /* Produced by Andrew Hanushevsky for Stanford University under contract */
9 /* DE-AC02-76-SFO0515 with the Department of Energy */
10 /* */
11 /* This file is part of the XRootD software suite. */
12 /* */
13 /* XRootD is free software: you can redistribute it and/or modify it under */
14 /* the terms of the GNU Lesser General Public License as published by the */
15 /* Free Software Foundation, either version 3 of the License, or (at your */
16 /* option) any later version. */
17 /* */
18 /* XRootD is distributed in the hope that it will be useful, but WITHOUT */
19 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
20 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
21 /* License for more details. */
22 /* */
23 /* You should have received a copy of the GNU Lesser General Public License */
24 /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
25 /* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
26 /* */
27 /* The copyright holder's institutional names and contributor's names may not */
28 /* be used to endorse or promote products derived from this software without */
29 /* specific prior written permission of the institution or contributor. */
30 /******************************************************************************/
31 
32 #include <errno.h>
33 #ifdef WIN32
34 #define HAVE_STRUCT_TIMESPEC 1
35 #endif
36 #include <pthread.h>
37 #include <signal.h>
38 #ifdef AIX
39 #include <sys/sem.h>
40 #else
41 #include <semaphore.h>
42 #endif
43 
44 #include "XrdSys/XrdSysError.hh"
45 
46 /******************************************************************************/
47 /* X r d S y s C o n d V a r */
48 /******************************************************************************/
49 
50 // XrdSysCondVar implements the standard POSIX-compliant condition variable.
51 // Methods correspond to the equivalent pthread condvar functions.
52 
54 {
55 public:
56 
57 inline void Lock() {pthread_mutex_lock(&cmut);}
58 
59 inline void Signal() {if (relMutex) pthread_mutex_lock(&cmut);
60  pthread_cond_signal(&cvar);
61  if (relMutex) pthread_mutex_unlock(&cmut);
62  }
63 
64 inline void Broadcast() {if (relMutex) pthread_mutex_lock(&cmut);
65  pthread_cond_broadcast(&cvar);
66  if (relMutex) pthread_mutex_unlock(&cmut);
67  }
68 
69 inline void UnLock() {pthread_mutex_unlock(&cmut);}
70 
71  int Wait();
72  int Wait(int sec);
73  int WaitMS(int msec);
74 
75  XrdSysCondVar( int relm=1, // 0->Caller will handle lock/unlock
76  const char *cid=0 // ID string for debugging only
77  ) {pthread_cond_init(&cvar, NULL);
78  pthread_mutex_init(&cmut, NULL);
79  relMutex = relm; condID = (cid ? cid : "unk");
80  }
81  ~XrdSysCondVar() {pthread_cond_destroy(&cvar);
82  pthread_mutex_destroy(&cmut);
83  }
84 private:
85 
86 pthread_cond_t cvar;
87 pthread_mutex_t cmut;
89 const char *condID;
90 };
91 
92 
93 
94 /******************************************************************************/
95 /* X r d S y s C o n d V a r H e l p e r */
96 /******************************************************************************/
97 
98 // XrdSysCondVarHelper is used to implement monitors with the Lock of a a condvar.
99 // Monitors are used to lock
100 // whole regions of code (e.g., a method) and automatically
101 // unlock with exiting the region (e.g., return). The
102 // methods should be self-evident.
103 
105 {
106 public:
107 
108 inline void Lock(XrdSysCondVar *CndVar)
109  {if (cnd) {if (cnd != CndVar) cnd->UnLock();
110  else return;
111  }
112  CndVar->Lock();
113  cnd = CndVar;
114  };
115 
116 inline void UnLock() {if (cnd) {cnd->UnLock(); cnd = 0;}}
117 
119  {if (CndVar) CndVar->Lock();
120  cnd = CndVar;
121  }
123  {CndVar.Lock();
124  cnd = &CndVar;
125  }
126 
128 private:
130 };
131 
132 
133 /******************************************************************************/
134 /* X r d S y s M u t e x */
135 /******************************************************************************/
136 
137 // XrdSysMutex implements the standard POSIX mutex. The methods correspond
138 // to the equivalent pthread mutex functions.
139 
141 {
142 public:
143 
144 inline int CondLock()
145  {if (pthread_mutex_trylock( &cs )) return 0;
146  return 1;
147  }
148 #ifdef __APPLE__
149 inline int TimedLock( int wait_ms )
150 {
151  struct timespec wait, cur, dur;
152  clock_gettime(CLOCK_REALTIME, &wait);
153  wait.tv_nsec += wait_ms * 100000;
154  wait.tv_sec += (wait.tv_nsec / 100000000);
155  wait.tv_nsec = wait.tv_nsec % 100000000;
156 
157  int rc;
158  while( ( rc = pthread_mutex_trylock( &cs ) ) == EBUSY )
159  {
160  clock_gettime( CLOCK_REALTIME, &cur );
161  if( ( cur.tv_sec > wait.tv_sec ) ||
162  ( ( cur.tv_sec == wait.tv_sec ) && ( cur.tv_nsec >= wait.tv_nsec ) ) )
163  return 0;
164 
165  dur.tv_sec = wait.tv_sec - cur.tv_sec;
166  dur.tv_nsec = wait.tv_nsec - cur.tv_nsec;
167  if( dur.tv_nsec < 0 )
168  {
169  --dur.tv_sec;
170  dur.tv_nsec += 1000000000;
171  }
172 
173  if( ( dur.tv_sec != 0 ) || ( dur.tv_nsec > 1000000 ) )
174  {
175  dur.tv_sec = 0;
176  dur.tv_nsec = 1000000;
177  }
178 
179  nanosleep( &dur, 0 );
180  }
181 
182  return !rc;
183 }
184 #else
185 inline int TimedLock(int wait_ms)
186  {struct timespec wait;
187  clock_gettime(CLOCK_REALTIME, &wait);
188  wait.tv_nsec += wait_ms * 100000;
189  wait.tv_sec += (wait.tv_nsec / 100000000);
190  wait.tv_nsec = wait.tv_nsec % 100000000;
191  return !pthread_mutex_timedlock(&cs, &wait);
192  }
193 #endif
194 
195 inline void Lock() {pthread_mutex_lock(&cs);}
196 
197 inline void UnLock() {pthread_mutex_unlock(&cs);}
198 
199  XrdSysMutex() {pthread_mutex_init(&cs, NULL);}
200  ~XrdSysMutex() {pthread_mutex_destroy(&cs);}
201 
202 protected:
203 
204 pthread_mutex_t cs;
205 };
206 
207 /******************************************************************************/
208 /* X r d S y s R e c M u t e x */
209 /******************************************************************************/
210 
211 // XrdSysRecMutex implements the recursive POSIX mutex. The methods correspond
212 // to the equivalent pthread mutex functions.
213 
215 {
216 public:
217 
219 
220 int InitRecMutex();
221 int ReInitRecMutex();
222 
223 };
224 
225 
226 /******************************************************************************/
227 /* X r d S y s M u t e x H e l p e r */
228 /******************************************************************************/
229 
230 // XrdSysMutexHelper us ised to implement monitors. Monitors are used to lock
231 // whole regions of code (e.g., a method) and automatically
232 // unlock with exiting the region (e.g., return). The
233 // methods should be self-evident.
234 
236 {
237 public:
238 
239 inline void Lock(XrdSysMutex *Mutex)
240  {if (mtx) {if (mtx != Mutex) mtx->UnLock();
241  else return;
242  }
243  Mutex->Lock();
244  mtx = Mutex;
245  };
246 
247 inline void UnLock() {if (mtx) {mtx->UnLock(); mtx = 0;}}
248 
250  {if (mutex) mutex->Lock();
251  mtx = mutex;
252  }
254  {mutex.Lock();
255  mtx = &mutex;
256  }
257 
259 private:
261 };
262 
263 /******************************************************************************/
264 /* X r d S y s R W L o c k */
265 /******************************************************************************/
266 
267 // XrdSysRWLock implements the standard POSIX wrlock mutex. The methods correspond
268 // to the equivalent pthread wrlock functions.
269 
271 {
272 public:
273 
274 inline int CondReadLock()
275  {if (pthread_rwlock_tryrdlock( &lock )) return 0;
276  return 1;
277  }
278 inline int CondWriteLock()
279  {if (pthread_rwlock_trywrlock( &lock )) return 0;
280  return 1;
281  }
282 
283 inline void ReadLock() {pthread_rwlock_rdlock(&lock);}
284 inline void WriteLock() {pthread_rwlock_wrlock(&lock);}
285 
286 inline void ReadLock( int &status ) {status = pthread_rwlock_rdlock(&lock);}
287 inline void WriteLock( int &status ) {status = pthread_rwlock_wrlock(&lock);}
288 
289 inline void UnLock() {pthread_rwlock_unlock(&lock);}
290 
291  XrdSysRWLock() {pthread_rwlock_init(&lock, NULL);}
292  ~XrdSysRWLock() {pthread_rwlock_destroy(&lock);}
293 
294 inline void ReInitialize()
295 {
296  pthread_rwlock_destroy(&lock);
297  pthread_rwlock_init(&lock, NULL);
298 }
299 
300 protected:
301 
302 pthread_rwlock_t lock;
303 };
304 
305 /******************************************************************************/
306 /* X r d S y s W R L o c k H e l p e r */
307 /******************************************************************************/
308 
309 // XrdSysWRLockHelper : helper class for XrdSysRWLock
310 
312 {
313 public:
314 
315 inline void Lock(XrdSysRWLock *lock, bool rd = 1)
316  {if (lck) {if (lck != lock) lck->UnLock();
317  else return;
318  }
319  if (rd) lock->ReadLock();
320  else lock->WriteLock();
321  lck = lock;
322  };
323 
324 inline void UnLock() {if (lck) {lck->UnLock(); lck = 0;}}
325 
326  XrdSysRWLockHelper(XrdSysRWLock *l=0, bool rd = 1)
327  { if (l) {if (rd) l->ReadLock();
328  else l->WriteLock();
329  }
330  lck = l;
331  }
333  { if (rd) l.ReadLock();
334  else l.WriteLock();
335  lck = &l;
336  }
337 
339 private:
341 };
342 
343 /******************************************************************************/
344 /* X r d S y s S e m a p h o r e */
345 /******************************************************************************/
346 
347 // XrdSysSemaphore implements the classic counting semaphore. The methods
348 // should be self-evident. Note that on certain platforms
349 // semaphores need to be implemented based on condition
350 // variables since no native implementation is available.
351 
352 #ifdef __APPLE__
353 class XrdSysSemaphore
354 {
355 public:
356 
357  int CondWait();
358 
359  void Post();
360 
361  void Wait();
362 
363 static void CleanUp(void *semVar);
364 
365  XrdSysSemaphore(int semval=1,const char *cid=0) : semVar(0, cid)
366  {semVal = semval; semWait = 0;}
367  ~XrdSysSemaphore() {}
368 
369 private:
370 
371 XrdSysCondVar semVar;
372 int semVal;
373 int semWait;
374 };
375 
376 #else
377 
379 {
380 public:
381 
382 inline int CondWait()
383  {while(sem_trywait( &h_semaphore ))
384  {if (errno == EAGAIN) return 0;
385  if (errno != EINTR) { throw "sem_CondWait() failed";}
386  }
387  return 1;
388  }
389 
390 inline void Post() {if (sem_post(&h_semaphore))
391  {throw "sem_post() failed";}
392  }
393 
394 inline void Wait() {while (sem_wait(&h_semaphore))
395  {if (EINTR != errno)
396  {throw "sem_wait() failed";}
397  }
398  }
399 
400  XrdSysSemaphore(int semval=1, const char * =0)
401  {if (sem_init(&h_semaphore, 0, semval))
402  {throw "sem_init() failed";}
403  }
404  ~XrdSysSemaphore() {if (sem_destroy(&h_semaphore))
405  {abort();}
406  }
407 
408 private:
409 
411 };
412 #endif
413 
414 /******************************************************************************/
415 /* X r d S y s T h r e a d */
416 /******************************************************************************/
417 
418 // The C++ standard makes it impossible to link extern "C" methods with C++
419 // methods. Thus, making a full thread object is nearly impossible. So, this
420 // object is used as the thread manager. Since it is static for all intense
421 // and purposes, one does not need to create an instance of it.
422 //
423 
424 // Options to Run()
425 //
426 // BIND creates threads that are bound to a kernel thread.
427 //
428 #define XRDSYSTHREAD_BIND 0x001
429 
430 // HOLD creates a thread that needs to be joined to get its ending value.
431 // Otherwise, a detached thread is created.
432 //
433 #define XRDSYSTHREAD_HOLD 0x002
434 
436 {
437 public:
438 
439 static int Cancel(pthread_t tid) {return pthread_cancel(tid);}
440 
441 static int Detach(pthread_t tid) {return pthread_detach(tid);}
442 
443 
444 static int SetCancelOff() {
445  return pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 0);
446  };
447 
448 static int Join(pthread_t tid, void **ret) {
449  return pthread_join(tid, ret);
450  };
451 
452 static int SetCancelOn() {
453  return pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0);
454  };
455 
456 static int SetCancelAsynchronous() {
457  return pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
458  };
459 
460 static int SetCancelDeferred() {
461  return pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, 0);
462  };
463 
464 static void CancelPoint() {
465  pthread_testcancel();
466  };
467 
468 
469 static pthread_t ID(void) {return pthread_self();}
470 
471 static int Kill(pthread_t tid) {return pthread_cancel(tid);}
472 
473 static unsigned long Num(void);
474 
475 static int Run(pthread_t *, void *(*proc)(void *), void *arg,
476  int opts=0, const char *desc = 0);
477 
478 static int Same(pthread_t t1, pthread_t t2)
479  {return pthread_equal(t1, t2);}
480 
481 static void setDebug(XrdSysError *erp) {eDest = erp;}
482 
483 static void setStackSize(size_t stsz) {stackSize = stsz;}
484 
485 static int Signal(pthread_t tid, int snum)
486  {return pthread_kill(tid, snum);}
487 
488 static int Wait(pthread_t tid);
489 
492 
493 private:
495 static size_t stackSize;
496 };
497 #endif
XrdSysRWLockHelper(XrdSysRWLock &l, bool rd=1)
Definition: XrdSysPthread.hh:332
void UnLock()
Definition: XrdSysPthread.hh:116
XrdSysMutex * mtx
Definition: XrdSysPthread.hh:260
Definition: XrdSysPthread.hh:214
XrdSysCondVar(int relm=1, const char *cid=0)
Definition: XrdSysPthread.hh:75
pthread_cond_t cvar
Definition: XrdSysPthread.hh:86
void UnLock()
Definition: XrdSysPthread.hh:324
void ReadLock(int &status)
Definition: XrdSysPthread.hh:286
Definition: XrdSysPthread.hh:270
sem_t h_semaphore
Definition: XrdSysPthread.hh:410
pthread_rwlock_t lock
Definition: XrdSysPthread.hh:302
XrdSysRWLock * lck
Definition: XrdSysPthread.hh:340
int CondWait()
Definition: XrdSysPthread.hh:382
static void setDebug(XrdSysError *erp)
Definition: XrdSysPthread.hh:481
static int Kill(pthread_t tid)
Definition: XrdSysPthread.hh:471
void ReInitialize()
Definition: XrdSysPthread.hh:294
void UnLock()
Definition: XrdSysPthread.hh:247
static int Detach(pthread_t tid)
Definition: XrdSysPthread.hh:441
void ReadLock()
Definition: XrdSysPthread.hh:283
void Signal()
Definition: XrdSysPthread.hh:59
void Wait()
Definition: XrdSysPthread.hh:394
XrdSysRWLock()
Definition: XrdSysPthread.hh:291
static int Run(pthread_t *, void *(*proc)(void *), void *arg, int opts=0, const char *desc=0)
int relMutex
Definition: XrdSysPthread.hh:88
Definition: XrdSysPthread.hh:435
Definition: XrdSysError.hh:89
pthread_mutex_t cmut
Definition: XrdSysPthread.hh:87
static int Cancel(pthread_t tid)
Definition: XrdSysPthread.hh:439
~XrdSysMutex()
Definition: XrdSysPthread.hh:200
static int Signal(pthread_t tid, int snum)
Definition: XrdSysPthread.hh:485
Definition: XrdSysPthread.hh:140
void Lock(XrdSysMutex *Mutex)
Definition: XrdSysPthread.hh:239
void Lock(XrdSysRWLock *lock, bool rd=1)
Definition: XrdSysPthread.hh:315
void WriteLock()
Definition: XrdSysPthread.hh:284
Definition: XrdSysPthread.hh:311
XrdSysRWLockHelper(XrdSysRWLock *l=0, bool rd=1)
Definition: XrdSysPthread.hh:326
static void setStackSize(size_t stsz)
Definition: XrdSysPthread.hh:483
static int Wait(pthread_t tid)
Definition: XrdSysPthread.hh:53
void Post()
Definition: XrdSysPthread.hh:390
int CondReadLock()
Definition: XrdSysPthread.hh:274
pthread_mutex_t cs
Definition: XrdSysPthread.hh:204
Definition: XrdSysPthread.hh:378
static void CancelPoint()
Definition: XrdSysPthread.hh:464
int CondWriteLock()
Definition: XrdSysPthread.hh:278
static pthread_t ID(void)
Definition: XrdSysPthread.hh:469
~XrdSysThread()
Definition: XrdSysPthread.hh:491
~XrdSysRWLock()
Definition: XrdSysPthread.hh:292
void Lock(XrdSysCondVar *CndVar)
Definition: XrdSysPthread.hh:108
static int SetCancelDeferred()
Definition: XrdSysPthread.hh:460
void Broadcast()
Definition: XrdSysPthread.hh:64
Definition: XrdSysPthread.hh:104
~XrdSysCondVarHelper()
Definition: XrdSysPthread.hh:127
XrdSysThread()
Definition: XrdSysPthread.hh:490
static int Join(pthread_t tid, void **ret)
Definition: XrdSysPthread.hh:448
void Lock()
Definition: XrdSysPthread.hh:195
static int SetCancelAsynchronous()
Definition: XrdSysPthread.hh:456
~XrdSysMutexHelper()
Definition: XrdSysPthread.hh:258
~XrdSysRWLockHelper()
Definition: XrdSysPthread.hh:338
int ReInitRecMutex()
~XrdSysSemaphore()
Definition: XrdSysPthread.hh:404
XrdSysCondVarHelper(XrdSysCondVar &CndVar)
Definition: XrdSysPthread.hh:122
int TimedLock(int wait_ms)
Definition: XrdSysPthread.hh:185
const char * condID
Definition: XrdSysPthread.hh:89
int CondLock()
Definition: XrdSysPthread.hh:144
void WriteLock(int &status)
Definition: XrdSysPthread.hh:287
int WaitMS(int msec)
void UnLock()
Definition: XrdSysPthread.hh:69
static int Same(pthread_t t1, pthread_t t2)
Definition: XrdSysPthread.hh:478
XrdSysMutex()
Definition: XrdSysPthread.hh:199
static int SetCancelOn()
Definition: XrdSysPthread.hh:452
XrdSysSemaphore(int semval=1, const char *=0)
Definition: XrdSysPthread.hh:400
static int SetCancelOff()
Definition: XrdSysPthread.hh:444
void UnLock()
Definition: XrdSysPthread.hh:197
static XrdSysError * eDest
Definition: XrdSysPthread.hh:494
XrdSysCondVarHelper(XrdSysCondVar *CndVar=0)
Definition: XrdSysPthread.hh:118
XrdSysMutexHelper(XrdSysMutex *mutex=0)
Definition: XrdSysPthread.hh:249
XrdSysMutexHelper(XrdSysMutex &mutex)
Definition: XrdSysPthread.hh:253
void UnLock()
Definition: XrdSysPthread.hh:289
static size_t stackSize
Definition: XrdSysPthread.hh:495
Definition: XrdSysPthread.hh:235
~XrdSysCondVar()
Definition: XrdSysPthread.hh:81
void Lock()
Definition: XrdSysPthread.hh:57
XrdSysCondVar * cnd
Definition: XrdSysPthread.hh:129
static unsigned long Num(void)