00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 const char *XrdSysPthreadCVSID = "$Id: XrdSysPthread.cc 36447 2010-10-28 14:43:40Z ganis $";
00014
00015 #include <errno.h>
00016 #include <pthread.h>
00017 #ifndef WIN32
00018 #include <unistd.h>
00019 #include <sys/time.h>
00020 #else
00021 #undef ETIMEDOUT // Make sure that the definition from Winsock2.h is used ...
00022 #include <Winsock2.h>
00023 #include <time.h>
00024 #include "XrdSys/XrdWin32.hh"
00025 #endif
00026 #include <sys/types.h>
00027
00028 #include "XrdSys/XrdSysPthread.hh"
00029
00030
00031
00032
00033
00034 struct XrdSysThreadArgs
00035 {
00036 pthread_key_t numKey;
00037 XrdSysError *eDest;
00038 const char *tDesc;
00039 void *(*proc)(void *);
00040 void *arg;
00041
00042 XrdSysThreadArgs(pthread_key_t nk, XrdSysError *ed, const char *td,
00043 void *(*p)(void *), void *a)
00044 {numKey=nk; eDest=ed; tDesc=td, proc=p; arg=a;}
00045 ~XrdSysThreadArgs() {}
00046 };
00047
00048
00049
00050
00051
00052 pthread_key_t XrdSysThread::threadNumkey;
00053
00054 XrdSysError *XrdSysThread::eDest = 0;
00055
00056 size_t XrdSysThread::stackSize = 0;
00057
00058 int XrdSysThread::initDone = 0;
00059
00060
00061
00062
00063
00064 extern "C"
00065 {
00066 void *XrdSysThread_Xeq(void *myargs)
00067 {
00068 XrdSysThreadArgs *ap = (XrdSysThreadArgs *)myargs;
00069 unsigned long myNum;
00070 void *retc;
00071
00072 #if defined(__linux__)
00073 myNum = static_cast<unsigned int>(getpid());
00074 #elif defined(__solaris__)
00075 myNum = static_cast<unsigned int>(pthread_self());
00076 #elif defined(__macos__)
00077 myNum = static_cast<unsigned int>(pthread_mach_thread_np(pthread_self()));
00078 #else
00079 static XrdSysMutex numMutex;
00080 static unsigned long threadNum = 1;
00081 numMutex.Lock(); threadNum++; myNum = threadNum; numMutex.UnLock();
00082 #endif
00083
00084 pthread_setspecific(ap->numKey, reinterpret_cast<const void *>(myNum));
00085 if (ap->eDest && ap->tDesc)
00086 ap->eDest->Emsg("Xeq", ap->tDesc, "thread started");
00087 retc = ap->proc(ap->arg);
00088 delete ap;
00089 return retc;
00090 }
00091 }
00092
00093
00094
00095
00096
00097
00098
00099
00100 int XrdSysCondVar::Wait()
00101 {
00102 int retc;
00103
00104
00105
00106 if (relMutex) Lock();
00107 retc = pthread_cond_wait(&cvar, &cmut);
00108 if (relMutex) UnLock();
00109 return retc;
00110 }
00111
00112
00113
00114 int XrdSysCondVar::Wait(int sec)
00115 {
00116 struct timespec tval;
00117 int retc;
00118
00119
00120
00121 if (relMutex) Lock();
00122
00123
00124
00125 tval.tv_sec = time(0) + sec;
00126 tval.tv_nsec = 0;
00127
00128
00129
00130 do {retc = pthread_cond_timedwait(&cvar, &cmut, &tval);}
00131 while (retc && (retc != ETIMEDOUT));
00132
00133 if (relMutex) UnLock();
00134 return retc == ETIMEDOUT;
00135 }
00136
00137
00138
00139
00140
00141 int XrdSysCondVar::WaitMS(int msec)
00142 {
00143 int sec, retc, usec;
00144 struct timeval tnow;
00145 struct timespec tval;
00146
00147
00148
00149 if (msec < 1000) sec = 0;
00150 else {sec = msec / 1000; msec = msec % 1000;}
00151 usec = msec * 1000;
00152
00153
00154
00155 if (relMutex) Lock();
00156
00157
00158
00159 gettimeofday(&tnow, 0);
00160
00161
00162
00163 tval.tv_sec = tnow.tv_sec + sec;
00164 tval.tv_nsec = tnow.tv_usec + usec;
00165 if (tval.tv_nsec > 1000000)
00166 {tval.tv_sec += tval.tv_nsec / 1000000;
00167 tval.tv_nsec = tval.tv_nsec % 1000000;
00168 }
00169 tval.tv_nsec *= 1000;
00170
00171
00172
00173
00174 do {retc = pthread_cond_timedwait(&cvar, &cmut, &tval);}
00175 while (retc && (retc != ETIMEDOUT));
00176
00177 if (relMutex) UnLock();
00178 return retc == ETIMEDOUT;
00179 }
00180
00181
00182
00183
00184
00185
00186
00187
00188 #ifdef __macos__
00189
00190 int XrdSysSemaphore::CondWait()
00191 {
00192 int rc;
00193
00194
00195
00196 semVar.Lock();
00197 if ((rc = (semVal > 0) && !semWait)) semVal--;
00198 semVar.UnLock();
00199 return rc;
00200 }
00201
00202
00203
00204
00205
00206 void XrdSysSemaphore::Post()
00207 {
00208
00209
00210
00211 semVar.Lock();
00212 semVal++;
00213 if (semVal && semWait) semVar.Signal();
00214 semVar.UnLock();
00215 }
00216
00217
00218
00219
00220
00221 void XrdSysSemaphore::Wait()
00222 {
00223
00224
00225
00226
00227 semVar.Lock();
00228 if (semVal < 1 || semWait)
00229 while(semVal < 1)
00230 {semWait++;
00231 semVar.Wait();
00232 semWait--;
00233 }
00234
00235
00236
00237 semVal--;
00238 semVar.UnLock();
00239 }
00240 #endif
00241
00242
00243
00244
00245
00246
00247
00248
00249 void XrdSysThread::doInit()
00250 {
00251 static XrdSysMutex initMutex;
00252
00253 initMutex.Lock();
00254 if (!initDone)
00255 {pthread_key_create(&threadNumkey, 0);
00256 pthread_setspecific(threadNumkey, (const void *)1);
00257 initDone = 1;
00258 }
00259 initMutex.UnLock();
00260 }
00261
00262
00263
00264
00265
00266 int XrdSysThread::Run(pthread_t *tid, void *(*proc)(void *), void *arg,
00267 int opts, const char *tDesc)
00268 {
00269 pthread_attr_t tattr;
00270 XrdSysThreadArgs *myargs;
00271
00272 if (!initDone) doInit();
00273 myargs = new XrdSysThreadArgs(threadNumkey, eDest, tDesc, proc, arg);
00274
00275 pthread_attr_init(&tattr);
00276 if ( opts & XRDSYSTHREAD_BIND)
00277 pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM);
00278 if (!(opts & XRDSYSTHREAD_HOLD))
00279 pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
00280 if (stackSize)
00281 pthread_attr_setstacksize(&tattr, stackSize);
00282 return pthread_create(tid, &tattr, XrdSysThread_Xeq,
00283 static_cast<void *>(myargs));
00284 }
00285
00286
00287
00288
00289
00290 int XrdSysThread::Wait(pthread_t tid)
00291 {
00292 int retc, *tstat;
00293 if ((retc = pthread_join(tid, reinterpret_cast<void **>(&tstat)))) return retc;
00294 return *tstat;
00295 }
00296
00297
00298
00299
00300
00301
00302
00303 XrdSysRecMutex::XrdSysRecMutex() {
00304
00305 int rc;
00306 pthread_mutexattr_t attr;
00307
00308 rc = pthread_mutexattr_init(&attr);
00309
00310 if (!rc) {
00311 rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
00312 if (!rc)
00313 pthread_mutex_init(&cs, &attr);
00314 }
00315
00316 pthread_mutexattr_destroy(&attr);
00317
00318 }