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 #ifdef __APPLE__
45 #ifndef CLOCK_REALTIME
46 #include <mach/clock.h>
47 #include <mach/mach.h>
48 #endif
49 namespace
50 {
51  template< typename TYPE >
52  void get_apple_realtime( TYPE & wait )
53  {
54 #ifdef CLOCK_REALTIME
55  clock_gettime(CLOCK_REALTIME, &wait);
56 #else
57  clock_serv_t cclock;
58  mach_timespec_t mts;
59  host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
60  clock_get_time(cclock, &mts);
61  mach_port_deallocate(mach_task_self(), cclock);
62  wait.tv_sec = mts.tv_sec;
63  wait.tv_nsec = mts.tv_nsec;
64 #endif
65  }
66 }
67 #endif
68 
69 #include "XrdSys/XrdSysError.hh"
70 
71 /******************************************************************************/
72 /* X r d S y s C o n d V a r */
73 /******************************************************************************/
74 
75 // XrdSysCondVar implements the standard POSIX-compliant condition variable.
76 // Methods correspond to the equivalent pthread condvar functions.
77 
79 {
80 public:
81 
82 inline void Lock() {pthread_mutex_lock(&cmut);}
83 
84 inline void Signal() {if (relMutex) pthread_mutex_lock(&cmut);
85  pthread_cond_signal(&cvar);
86  if (relMutex) pthread_mutex_unlock(&cmut);
87  }
88 
89 inline void Broadcast() {if (relMutex) pthread_mutex_lock(&cmut);
90  pthread_cond_broadcast(&cvar);
91  if (relMutex) pthread_mutex_unlock(&cmut);
92  }
93 
94 inline void UnLock() {pthread_mutex_unlock(&cmut);}
95 
96  int Wait();
97  int Wait(int sec);
98  int WaitMS(int msec);
99 
100  XrdSysCondVar( int relm=1, // 0->Caller will handle lock/unlock
101  const char *cid=0 // ID string for debugging only
102  ) {pthread_cond_init(&cvar, NULL);
103  pthread_mutex_init(&cmut, NULL);
104  relMutex = relm; condID = (cid ? cid : "unk");
105  }
106  ~XrdSysCondVar() {pthread_cond_destroy(&cvar);
107  pthread_mutex_destroy(&cmut);
108  }
109 private:
110 
111 pthread_cond_t cvar;
112 pthread_mutex_t cmut;
114 const char *condID;
115 };
116 
117 
118 
119 /******************************************************************************/
120 /* X r d S y s C o n d V a r H e l p e r */
121 /******************************************************************************/
122 
123 // XrdSysCondVarHelper is used to implement monitors with the Lock of a a condvar.
124 // Monitors are used to lock
125 // whole regions of code (e.g., a method) and automatically
126 // unlock with exiting the region (e.g., return). The
127 // methods should be self-evident.
128 
130 {
131 public:
132 
133 inline void Lock(XrdSysCondVar *CndVar)
134  {if (cnd) {if (cnd != CndVar) cnd->UnLock();
135  else return;
136  }
137  CndVar->Lock();
138  cnd = CndVar;
139  };
140 
141 inline void UnLock() {if (cnd) {cnd->UnLock(); cnd = 0;}}
142 
144  {if (CndVar) CndVar->Lock();
145  cnd = CndVar;
146  }
148  {CndVar.Lock();
149  cnd = &CndVar;
150  }
151 
153 private:
155 };
156 
157 
158 /******************************************************************************/
159 /* X r d S y s M u t e x */
160 /******************************************************************************/
161 
162 // XrdSysMutex implements the standard POSIX mutex. The methods correspond
163 // to the equivalent pthread mutex functions.
164 
166 {
167 public:
168 
169 inline int CondLock()
170  {if (pthread_mutex_trylock( &cs )) return 0;
171  return 1;
172  }
173 #ifdef __APPLE__
174 inline int TimedLock( int wait_ms )
175 {
176  struct timespec wait, cur, dur;
177  get_apple_realtime(wait);
178  wait.tv_sec += (wait_ms / 1000);
179  wait.tv_nsec += (wait_ms % 1000) * 1000000;
180  wait.tv_sec += (wait.tv_nsec / 1000000000);
181  wait.tv_nsec = wait.tv_nsec % 1000000000;
182 
183  int rc;
184  while( ( rc = pthread_mutex_trylock( &cs ) ) == EBUSY )
185  {
186  get_apple_realtime(cur);
187  if( ( cur.tv_sec > wait.tv_sec ) ||
188  ( ( cur.tv_sec == wait.tv_sec ) && ( cur.tv_nsec >= wait.tv_nsec ) ) )
189  return 0;
190 
191  dur.tv_sec = wait.tv_sec - cur.tv_sec;
192  dur.tv_nsec = wait.tv_nsec - cur.tv_nsec;
193  if( dur.tv_nsec < 0 )
194  {
195  --dur.tv_sec;
196  dur.tv_nsec += 1000000000;
197  }
198 
199  if( ( dur.tv_sec != 0 ) || ( dur.tv_nsec > 1000000 ) )
200  {
201  dur.tv_sec = 0;
202  dur.tv_nsec = 1000000;
203  }
204 
205  nanosleep( &dur, 0 );
206  }
207 
208  return !rc;
209 }
210 #else
211 inline int TimedLock(int wait_ms)
212  {struct timespec wait;
213  clock_gettime(CLOCK_REALTIME, &wait);
214  wait.tv_sec += (wait_ms / 1000);
215  wait.tv_nsec += (wait_ms % 1000) * 1000000;
216  wait.tv_sec += (wait.tv_nsec / 1000000000);
217  wait.tv_nsec = wait.tv_nsec % 1000000000;
218  return !pthread_mutex_timedlock(&cs, &wait);
219  }
220 #endif
221 
222 inline void Lock() {pthread_mutex_lock(&cs);}
223 
224 inline void UnLock() {pthread_mutex_unlock(&cs);}
225 
226  XrdSysMutex() {pthread_mutex_init(&cs, NULL);}
227  ~XrdSysMutex() {pthread_mutex_destroy(&cs);}
228 
229 protected:
230 
231 pthread_mutex_t cs;
232 };
233 
234 /******************************************************************************/
235 /* X r d S y s R e c M u t e x */
236 /******************************************************************************/
237 
238 // XrdSysRecMutex implements the recursive POSIX mutex. The methods correspond
239 // to the equivalent pthread mutex functions.
240 
242 {
243 public:
244 
246 
247 int InitRecMutex();
248 int ReInitRecMutex();
249 
250 };
251 
252 
253 /******************************************************************************/
254 /* X r d S y s M u t e x H e l p e r */
255 /******************************************************************************/
256 
257 // XrdSysMutexHelper us ised to implement monitors. Monitors are used to lock
258 // whole regions of code (e.g., a method) and automatically
259 // unlock with exiting the region (e.g., return). The
260 // methods should be self-evident.
261 
263 {
264 public:
265 
266 inline void Lock(XrdSysMutex *Mutex)
267  {if (mtx) {if (mtx != Mutex) mtx->UnLock();
268  else return;
269  }
270  Mutex->Lock();
271  mtx = Mutex;
272  };
273 
274 inline void UnLock() {if (mtx) {mtx->UnLock(); mtx = 0;}}
275 
277  {if (mutex) mutex->Lock();
278  mtx = mutex;
279  }
281  {mutex.Lock();
282  mtx = &mutex;
283  }
284 
286 private:
288 };
289 
290 /******************************************************************************/
291 /* X r d S y s R W L o c k */
292 /******************************************************************************/
293 
294 // XrdSysRWLock implements the standard POSIX wrlock mutex. The methods correspond
295 // to the equivalent pthread wrlock functions.
296 
298 {
299 public:
300 
301 inline int CondReadLock()
302  {if (pthread_rwlock_tryrdlock( &lock )) return 0;
303  return 1;
304  }
305 inline int CondWriteLock()
306  {if (pthread_rwlock_trywrlock( &lock )) return 0;
307  return 1;
308  }
309 
310 inline void ReadLock() {pthread_rwlock_rdlock(&lock);}
311 inline void WriteLock() {pthread_rwlock_wrlock(&lock);}
312 
313 inline void ReadLock( int &status ) {status = pthread_rwlock_rdlock(&lock);}
314 inline void WriteLock( int &status ) {status = pthread_rwlock_wrlock(&lock);}
315 
316 inline void UnLock() {pthread_rwlock_unlock(&lock);}
317 
318  XrdSysRWLock() {pthread_rwlock_init(&lock, NULL);}
319  ~XrdSysRWLock() {pthread_rwlock_destroy(&lock);}
320 
321 inline void ReInitialize()
322 {
323  pthread_rwlock_destroy(&lock);
324  pthread_rwlock_init(&lock, NULL);
325 }
326 
327 protected:
328 
329 pthread_rwlock_t lock;
330 };
331 
332 /******************************************************************************/
333 /* X r d S y s W R L o c k H e l p e r */
334 /******************************************************************************/
335 
336 // XrdSysWRLockHelper : helper class for XrdSysRWLock
337 
339 {
340 public:
341 
342 inline void Lock(XrdSysRWLock *lock, bool rd = 1)
343  {if (lck) {if (lck != lock) lck->UnLock();
344  else return;
345  }
346  if (rd) lock->ReadLock();
347  else lock->WriteLock();
348  lck = lock;
349  };
350 
351 inline void UnLock() {if (lck) {lck->UnLock(); lck = 0;}}
352 
353  XrdSysRWLockHelper(XrdSysRWLock *l=0, bool rd = 1)
354  { if (l) {if (rd) l->ReadLock();
355  else l->WriteLock();
356  }
357  lck = l;
358  }
360  { if (rd) l.ReadLock();
361  else l.WriteLock();
362  lck = &l;
363  }
364 
366 private:
368 };
369 
370 /******************************************************************************/
371 /* X r d S y s S e m a p h o r e */
372 /******************************************************************************/
373 
374 // XrdSysSemaphore implements the classic counting semaphore. The methods
375 // should be self-evident. Note that on certain platforms
376 // semaphores need to be implemented based on condition
377 // variables since no native implementation is available.
378 
379 #if defined(__APPLE__) || defined(__GNU__)
380 class XrdSysSemaphore
381 {
382 public:
383 
384  int CondWait();
385 
386  void Post();
387 
388  void Wait();
389 
390 static void CleanUp(void *semVar);
391 
392  XrdSysSemaphore(int semval=1,const char *cid=0) : semVar(0, cid)
393  {semVal = semval; semWait = 0;}
394  ~XrdSysSemaphore() {}
395 
396 private:
397 
398 XrdSysCondVar semVar;
399 int semVal;
400 int semWait;
401 };
402 
403 #else
404 
406 {
407 public:
408 
409 inline int CondWait()
410  {while(sem_trywait( &h_semaphore ))
411  {if (errno == EAGAIN) return 0;
412  if (errno != EINTR) { throw "sem_CondWait() failed";}
413  }
414  return 1;
415  }
416 
417 inline void Post() {if (sem_post(&h_semaphore))
418  {throw "sem_post() failed";}
419  }
420 
421 inline void Wait() {while (sem_wait(&h_semaphore))
422  {if (EINTR != errno)
423  {throw "sem_wait() failed";}
424  }
425  }
426 
427  XrdSysSemaphore(int semval=1, const char * =0)
428  {if (sem_init(&h_semaphore, 0, semval))
429  {throw "sem_init() failed";}
430  }
431  ~XrdSysSemaphore() {if (sem_destroy(&h_semaphore))
432  {abort();}
433  }
434 
435 private:
436 
438 };
439 #endif
440 
441 /******************************************************************************/
442 /* X r d S y s T h r e a d */
443 /******************************************************************************/
444 
445 // The C++ standard makes it impossible to link extern "C" methods with C++
446 // methods. Thus, making a full thread object is nearly impossible. So, this
447 // object is used as the thread manager. Since it is static for all intense
448 // and purposes, one does not need to create an instance of it.
449 //
450 
451 // Options to Run()
452 //
453 // BIND creates threads that are bound to a kernel thread.
454 //
455 #define XRDSYSTHREAD_BIND 0x001
456 
457 // HOLD creates a thread that needs to be joined to get its ending value.
458 // Otherwise, a detached thread is created.
459 //
460 #define XRDSYSTHREAD_HOLD 0x002
461 
463 {
464 public:
465 
466 static int Cancel(pthread_t tid) {return pthread_cancel(tid);}
467 
468 static int Detach(pthread_t tid) {return pthread_detach(tid);}
469 
470 
471 static int SetCancelOff() {
472  return pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 0);
473  };
474 
475 static int Join(pthread_t tid, void **ret) {
476  return pthread_join(tid, ret);
477  };
478 
479 static int SetCancelOn() {
480  return pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0);
481  };
482 
483 static int SetCancelAsynchronous() {
484  return pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
485  };
486 
487 static int SetCancelDeferred() {
488  return pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, 0);
489  };
490 
491 static void CancelPoint() {
492  pthread_testcancel();
493  };
494 
495 
496 static pthread_t ID(void) {return pthread_self();}
497 
498 static int Kill(pthread_t tid) {return pthread_cancel(tid);}
499 
500 static unsigned long Num(void);
501 
502 static int Run(pthread_t *, void *(*proc)(void *), void *arg,
503  int opts=0, const char *desc = 0);
504 
505 static int Same(pthread_t t1, pthread_t t2)
506  {return pthread_equal(t1, t2);}
507 
508 static void setDebug(XrdSysError *erp) {eDest = erp;}
509 
510 static void setStackSize(size_t stsz, bool force=false);
511 
512 static int Signal(pthread_t tid, int snum)
513  {return pthread_kill(tid, snum);}
514 
515 static int Wait(pthread_t tid);
516 
519 
520 private:
522 static size_t stackSize;
523 };
524 #endif
XrdSysRWLockHelper(XrdSysRWLock &l, bool rd=1)
Definition: XrdSysPthread.hh:359
void UnLock()
Definition: XrdSysPthread.hh:141
XrdSysMutex * mtx
Definition: XrdSysPthread.hh:287
Definition: XrdSysPthread.hh:241
XrdSysCondVar(int relm=1, const char *cid=0)
Definition: XrdSysPthread.hh:100
pthread_cond_t cvar
Definition: XrdSysPthread.hh:111
void UnLock()
Definition: XrdSysPthread.hh:351
void ReadLock(int &status)
Definition: XrdSysPthread.hh:313
Definition: XrdSysPthread.hh:297
sem_t h_semaphore
Definition: XrdSysPthread.hh:437
pthread_rwlock_t lock
Definition: XrdSysPthread.hh:329
XrdSysRWLock * lck
Definition: XrdSysPthread.hh:367
int CondWait()
Definition: XrdSysPthread.hh:409
static void setStackSize(size_t stsz, bool force=false)
static void setDebug(XrdSysError *erp)
Definition: XrdSysPthread.hh:508
static int Kill(pthread_t tid)
Definition: XrdSysPthread.hh:498
void ReInitialize()
Definition: XrdSysPthread.hh:321
void UnLock()
Definition: XrdSysPthread.hh:274
static int Detach(pthread_t tid)
Definition: XrdSysPthread.hh:468
void ReadLock()
Definition: XrdSysPthread.hh:310
void Signal()
Definition: XrdSysPthread.hh:84
void Wait()
Definition: XrdSysPthread.hh:421
XrdSysRWLock()
Definition: XrdSysPthread.hh:318
static int Run(pthread_t *, void *(*proc)(void *), void *arg, int opts=0, const char *desc=0)
int relMutex
Definition: XrdSysPthread.hh:113
Definition: XrdSysPthread.hh:462
Definition: XrdSysError.hh:89
pthread_mutex_t cmut
Definition: XrdSysPthread.hh:112
static int Cancel(pthread_t tid)
Definition: XrdSysPthread.hh:466
~XrdSysMutex()
Definition: XrdSysPthread.hh:227
static int Signal(pthread_t tid, int snum)
Definition: XrdSysPthread.hh:512
Definition: XrdSysPthread.hh:165
void Lock(XrdSysMutex *Mutex)
Definition: XrdSysPthread.hh:266
void Lock(XrdSysRWLock *lock, bool rd=1)
Definition: XrdSysPthread.hh:342
void WriteLock()
Definition: XrdSysPthread.hh:311
Definition: XrdSysPthread.hh:338
XrdSysRWLockHelper(XrdSysRWLock *l=0, bool rd=1)
Definition: XrdSysPthread.hh:353
static int Wait(pthread_t tid)
Definition: XrdSysPthread.hh:78
void Post()
Definition: XrdSysPthread.hh:417
int CondReadLock()
Definition: XrdSysPthread.hh:301
pthread_mutex_t cs
Definition: XrdSysPthread.hh:231
Definition: XrdSysPthread.hh:405
static void CancelPoint()
Definition: XrdSysPthread.hh:491
int CondWriteLock()
Definition: XrdSysPthread.hh:305
static pthread_t ID(void)
Definition: XrdSysPthread.hh:496
~XrdSysThread()
Definition: XrdSysPthread.hh:518
~XrdSysRWLock()
Definition: XrdSysPthread.hh:319
void Lock(XrdSysCondVar *CndVar)
Definition: XrdSysPthread.hh:133
static int SetCancelDeferred()
Definition: XrdSysPthread.hh:487
void Broadcast()
Definition: XrdSysPthread.hh:89
Definition: XrdSysPthread.hh:129
~XrdSysCondVarHelper()
Definition: XrdSysPthread.hh:152
XrdSysThread()
Definition: XrdSysPthread.hh:517
static int Join(pthread_t tid, void **ret)
Definition: XrdSysPthread.hh:475
void Lock()
Definition: XrdSysPthread.hh:222
static int SetCancelAsynchronous()
Definition: XrdSysPthread.hh:483
~XrdSysMutexHelper()
Definition: XrdSysPthread.hh:285
~XrdSysRWLockHelper()
Definition: XrdSysPthread.hh:365
int ReInitRecMutex()
~XrdSysSemaphore()
Definition: XrdSysPthread.hh:431
XrdSysCondVarHelper(XrdSysCondVar &CndVar)
Definition: XrdSysPthread.hh:147
int TimedLock(int wait_ms)
Definition: XrdSysPthread.hh:211
const char * condID
Definition: XrdSysPthread.hh:114
int CondLock()
Definition: XrdSysPthread.hh:169
void WriteLock(int &status)
Definition: XrdSysPthread.hh:314
int WaitMS(int msec)
void UnLock()
Definition: XrdSysPthread.hh:94
static int Same(pthread_t t1, pthread_t t2)
Definition: XrdSysPthread.hh:505
XrdSysMutex()
Definition: XrdSysPthread.hh:226
static int SetCancelOn()
Definition: XrdSysPthread.hh:479
XrdSysSemaphore(int semval=1, const char *=0)
Definition: XrdSysPthread.hh:427
static int SetCancelOff()
Definition: XrdSysPthread.hh:471
void UnLock()
Definition: XrdSysPthread.hh:224
static XrdSysError * eDest
Definition: XrdSysPthread.hh:521
XrdSysCondVarHelper(XrdSysCondVar *CndVar=0)
Definition: XrdSysPthread.hh:143
XrdSysMutexHelper(XrdSysMutex *mutex=0)
Definition: XrdSysPthread.hh:276
XrdSysMutexHelper(XrdSysMutex &mutex)
Definition: XrdSysPthread.hh:280
void UnLock()
Definition: XrdSysPthread.hh:316
static size_t stackSize
Definition: XrdSysPthread.hh:522
Definition: XrdSysPthread.hh:262
~XrdSysCondVar()
Definition: XrdSysPthread.hh:106
void Lock()
Definition: XrdSysPthread.hh:82
XrdSysCondVar * cnd
Definition: XrdSysPthread.hh:154
static unsigned long Num(void)