XRootD
Loading...
Searching...
No Matches
XrdSysPthread.cc
Go to the documentation of this file.
1/******************************************************************************/
2/* */
3/* X r d S y s P t h r e a d . c c */
4/* */
5/* (c) 2004 by the Board of Trustees of the Leland Stanford, Jr., University */
6/* Produced by Andrew Hanushevsky for Stanford University under contract */
7/* DE-AC02-76-SFO0515 with the Department of Energy */
8/* */
9/* This file is part of the XRootD software suite. */
10/* */
11/* XRootD is free software: you can redistribute it and/or modify it under */
12/* the terms of the GNU Lesser General Public License as published by the */
13/* Free Software Foundation, either version 3 of the License, or (at your */
14/* option) any later version. */
15/* */
16/* XRootD is distributed in the hope that it will be useful, but WITHOUT */
17/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
18/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
19/* License for more details. */
20/* */
21/* You should have received a copy of the GNU Lesser General Public License */
22/* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
23/* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
24/* */
25/* The copyright holder's institutional names and contributor's names may not */
26/* be used to endorse or promote products derived from this software without */
27/* specific prior written permission of the institution or contributor. */
28/******************************************************************************/
29
30#include <cerrno>
31#include <pthread.h>
32#ifndef WIN32
33#include <unistd.h>
34#include <sys/time.h>
35#else
36#undef ETIMEDOUT // Make sure that the definition from Winsock2.h is used ...
37#include <Winsock2.h>
38#include <ctime>
39#include "XrdSys/XrdWin32.hh"
40#endif
41#include <sys/types.h>
42#if defined(__linux__)
43#include <sys/syscall.h>
44#endif
45
47
48/******************************************************************************/
49/* L o c a l S t r u c t s */
50/******************************************************************************/
51
53 {
55 const char *tDesc;
56 void *(*proc)(void *);
57 void *arg;
58
59 XrdSysThreadArgs(XrdSysError *ed, const char *td,
60 void *(*p)(void *), void *a)
61 : eDest(ed), tDesc(td), proc(p), arg(a) {}
63 };
64
65/******************************************************************************/
66/* G l o b a l D a t a */
67/******************************************************************************/
68
69XrdSysError *XrdSysThread::eDest = 0;
70
71size_t XrdSysThread::stackSize = 0;
72
73/******************************************************************************/
74/* T h r e a d I n t e r f a c e P r o g r a m s */
75/******************************************************************************/
76
77extern "C"
78{
79void *XrdSysThread_Xeq(void *myargs)
80{
81 XrdSysThreadArgs *ap = (XrdSysThreadArgs *)myargs;
82 void *retc;
83
84 if (ap->eDest && ap->tDesc)
85 ap->eDest->Emsg("Xeq", ap->tDesc, "thread started");
86 retc = ap->proc(ap->arg);
87 delete ap;
88 return retc;
89}
90}
91
92/******************************************************************************/
93/* X r d S y s C o n d V a r */
94/******************************************************************************/
95/******************************************************************************/
96/* W a i t */
97/******************************************************************************/
98
100{
101 int retc;
102
103// Wait for the condition
104//
105 if (relMutex) Lock();
106 retc = pthread_cond_wait(&cvar, &cmut);
107 if (relMutex) UnLock();
108 return retc;
109}
110
111/******************************************************************************/
112
113int XrdSysCondVar::Wait(int sec) {return WaitMS(sec*1000);}
114
115/******************************************************************************/
116/* W a i t M S */
117/******************************************************************************/
118
120{
121 int sec, retc, usec;
122 struct timeval tnow;
123 struct timespec tval;
124
125// Adjust millseconds
126//
127 if (msec < 1000) sec = 0;
128 else {sec = msec / 1000; msec = msec % 1000;}
129 usec = msec * 1000;
130
131// Get the mutex before getting the time
132//
133 if (relMutex) Lock();
134
135// Get current time of day
136//
137 gettimeofday(&tnow, 0);
138
139// Add the second and microseconds
140//
141 tval.tv_sec = tnow.tv_sec + sec;
142 tval.tv_nsec = tnow.tv_usec + usec;
143 if (tval.tv_nsec >= 1000000)
144 {tval.tv_sec += tval.tv_nsec / 1000000;
145 tval.tv_nsec = tval.tv_nsec % 1000000;
146 }
147 tval.tv_nsec *= 1000;
148
149
150// Now wait for the condition or timeout
151//
152 do {retc = pthread_cond_timedwait(&cvar, &cmut, &tval);}
153 while (retc && (retc == EINTR));
154
155 if (relMutex) UnLock();
156
157// Determine how to return
158//
159 if (retc && retc != ETIMEDOUT) {throw "cond_timedwait() failed";}
160 return retc == ETIMEDOUT;
161}
162
163/******************************************************************************/
164/* X r d S y s C o n d V a r 2 */
165/******************************************************************************/
166/******************************************************************************/
167/* W a i t M S */
168/******************************************************************************/
169
171{
172 int sec, retc, usec;
173 struct timeval tnow;
174 struct timespec tval;
175
176// Adjust millseconds
177//
178 if (msec < 1000) sec = 0;
179 else {sec = msec / 1000; msec = msec % 1000;}
180 usec = msec * 1000;
181
182// Get current time of day
183//
184 gettimeofday(&tnow, 0);
185
186// Add the second and microseconds
187//
188 tval.tv_sec = tnow.tv_sec + sec;
189 tval.tv_nsec = tnow.tv_usec + usec;
190 if (tval.tv_nsec >= 1000000)
191 {tval.tv_sec += tval.tv_nsec / 1000000;
192 tval.tv_nsec = tval.tv_nsec % 1000000;
193 }
194 tval.tv_nsec *= 1000;
195
196
197// Now wait for the condition or timeout
198//
199 do {retc = pthread_cond_timedwait(&cvar, mtxP, &tval);}
200 while (retc && (retc == EINTR));
201
202// Determine how to return
203//
204 if (retc && retc != ETIMEDOUT) {throw "cond_timedwait() failed";}
205 return retc == ETIMEDOUT;
206}
207
208/******************************************************************************/
209/* X r d S y s S e m a p h o r e */
210/******************************************************************************/
211/******************************************************************************/
212/* C o n d W a i t */
213/******************************************************************************/
214
215#if defined(__APPLE__) || defined(__GNU__)
216
218{
219 int rc;
220
221// Get the semaphore only we can get it without waiting
222//
223 semVar.Lock();
224 if ((rc = (semVal > 0) && !semWait)) semVal--;
225 semVar.UnLock();
226 return rc;
227}
228
229/******************************************************************************/
230/* P o s t */
231/******************************************************************************/
232
234{
235// Add one to the semaphore counter. If we the value is > 0 and there is a
236// thread waiting for the semaphore, signal it to get the semaphore.
237//
238 semVar.Lock();
239 semVal++;
240 if (semVal && semWait) semVar.Signal();
241 semVar.UnLock();
242}
243
244/******************************************************************************/
245/* W a i t */
246/******************************************************************************/
247
249{
250
251// Wait until the semaphore value is positive. This will not be starvation
252// free if the OS implements an unfair mutex.
253// Adding a cleanup handler to the stack here enables threads using this OSX
254// semaphore to be canceled (which is rare). A scoped lock won't work here
255// because OSX is broken and doesn't call destructors properly.
256//
257 semVar.Lock();
258 pthread_cleanup_push(&XrdSysSemaphore::CleanUp, (void *) &semVar);
259 if (semVal < 1 || semWait)
260 while(semVal < 1)
261 {semWait++;
262 semVar.Wait();
263 semWait--;
264 }
265
266// Decrement the semaphore value, unlock the underlying cond var and return
267//
268 semVal--;
269 pthread_cleanup_pop(1);
270}
271
272/******************************************************************************/
273/* C l e a n U p */
274/******************************************************************************/
275
276void XrdSysSemaphore::CleanUp(void *semVar)
277{
278 XrdSysCondVar *sv = (XrdSysCondVar *) semVar;
279 sv->UnLock();
280}
281#endif
282
283/******************************************************************************/
284/* T h r e a d M e t h o d s */
285/******************************************************************************/
286/******************************************************************************/
287/* N u m */
288/******************************************************************************/
289
290unsigned long XrdSysThread::Num()
291{
292#if defined(__linux__)
293 return static_cast<unsigned long>(syscall(SYS_gettid));
294#elif defined(__solaris__)
295 return static_cast<unsigned long>(pthread_self());
296#elif defined(__APPLE__)
297 return static_cast<unsigned long>(pthread_mach_thread_np(pthread_self()));
298#else
299 return static_cast<unsigned long>(getpid());
300#endif
301}
302
303/******************************************************************************/
304/* R u n */
305/******************************************************************************/
306
307int XrdSysThread::Run(pthread_t *tid, void *(*proc)(void *), void *arg,
308 int opts, const char *tDesc)
309{
310 pthread_attr_t tattr;
311 XrdSysThreadArgs *myargs;
312
313 myargs = new XrdSysThreadArgs(eDest, tDesc, proc, arg);
314
315 pthread_attr_init(&tattr);
316 if ( opts & XRDSYSTHREAD_BIND)
317 pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM);
318 if (!(opts & XRDSYSTHREAD_HOLD))
319 pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
320 if (stackSize)
321 pthread_attr_setstacksize(&tattr, stackSize);
322 return pthread_create(tid, &tattr, XrdSysThread_Xeq,
323 static_cast<void *>(myargs));
324}
325
326/******************************************************************************/
327/* s e t S t a c k S i z e */
328/******************************************************************************/
329
330void XrdSysThread::setStackSize(size_t stksz, bool force)
331{
332// If not being forced, then we set the stacksize only if the requested
333// size is greater than the default size.
334//
335if (!force)
336 {pthread_attr_t tattr;
337 size_t dflt_stk_sz;
338 pthread_attr_init(&tattr);
339 if (pthread_attr_getstacksize(&tattr, &dflt_stk_sz) || stksz <= dflt_stk_sz)
340 {stackSize = 0;
341 return;
342 }
343 }
344
345// Record the stack size for future use
346//
347 stackSize = stksz;
348}
349
350/******************************************************************************/
351/* W a i t */
352/******************************************************************************/
353
354int XrdSysThread::Wait(pthread_t tid)
355{
356 int retc, *tstat;
357 if ((retc = pthread_join(tid, reinterpret_cast<void **>(&tstat)))) return retc;
358 return *tstat;
359}
360
361
362
363/******************************************************************************/
364/* X r d S y s R e c M u t e x */
365/******************************************************************************/
367{
368 InitRecMutex();
369}
370
372{
373 int rc;
374 pthread_mutexattr_t attr;
375
376 rc = pthread_mutexattr_init( &attr );
377
378 if( !rc )
379 {
380 pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE );
381 pthread_mutex_destroy( &cs );
382 rc = pthread_mutex_init( &cs, &attr );
383 }
384
385 pthread_mutexattr_destroy(&attr);
386 return rc;
387}
388
390{
391 pthread_mutex_destroy( &cs );
392 return InitRecMutex();
393}
static XrdSysError eDest(0,"crypto_")
struct myOpts opts
void * XrdSysThread_Xeq(void *myargs)
#define XRDSYSTHREAD_BIND
#define XRDSYSTHREAD_HOLD
bool WaitMS(int msec)
pthread_mutex_t * mtxP
pthread_cond_t cvar
int WaitMS(int msec)
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
pthread_mutex_t cs
static int Wait(pthread_t tid)
static int Run(pthread_t *, void *(*proc)(void *), void *arg, int opts=0, const char *desc=0)
static void setStackSize(size_t stsz, bool force=false)
static unsigned long Num(void)
XrdSysError * eDest
const char * tDesc
XrdSysThreadArgs(XrdSysError *ed, const char *td, void *(*p)(void *), void *a)
void *(* proc)(void *)