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