XrdSysPthread.cc

Go to the documentation of this file.
00001 /******************************************************************************/
00002 /*                                                                            */
00003 /*                      X r d S y s P t h r e a d . c c                       */
00004 /*                                                                            */
00005 /* (c) 2004 by the Board of Trustees of the Leland Stanford, Jr., University  */
00006 /*       All Rights Reserved. See XrdInfo.cc for complete License Terms       */
00007 /*   Produced by Andrew Hanushevsky for Stanford University under contract    */
00008 /*              DE-AC03-76-SFO0515 with the Department of Energy              */
00009 /******************************************************************************/
00010 
00011 //        $Id: XrdSysPthread.cc 36447 2010-10-28 14:43:40Z ganis $
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 /*                         L o c a l   S t r u c t s                          */
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 /*                           G l o b a l   D a t a                            */
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 /*             T h r e a d   I n t e r f a c e   P r o g r a m s              */
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 /*                         X r d S y s C o n d V a r                          */
00095 /******************************************************************************/
00096 /******************************************************************************/
00097 /*                                  W a i t                                   */
00098 /******************************************************************************/
00099   
00100 int XrdSysCondVar::Wait()
00101 {
00102  int retc;
00103 
00104 // Wait for the condition
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 // Get the mutex before calculating the time
00120 //
00121    if (relMutex) Lock();
00122 
00123 // Simply adjust the time in seconds
00124 //
00125    tval.tv_sec  = time(0) + sec;
00126    tval.tv_nsec = 0;
00127 
00128 // Wait for the condition or timeout
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 /*                                W a i t M S                                 */
00139 /******************************************************************************/
00140   
00141 int XrdSysCondVar::WaitMS(int msec)
00142 {
00143  int sec, retc, usec;
00144  struct timeval tnow;
00145  struct timespec tval;
00146 
00147 // Adjust millseconds
00148 //
00149    if (msec < 1000) sec = 0;
00150       else {sec = msec / 1000; msec = msec % 1000;}
00151    usec = msec * 1000;
00152 
00153 // Get the mutex before getting the time
00154 //
00155    if (relMutex) Lock();
00156 
00157 // Get current time of day
00158 //
00159    gettimeofday(&tnow, 0);
00160 
00161 // Add the second and microseconds
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 // Now wait for the condition or timeout
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 /*                       X r d S y s S e m a p h o r e                        */
00183 /******************************************************************************/
00184 /******************************************************************************/
00185 /*                              C o n d W a i t                               */
00186 /******************************************************************************/
00187   
00188 #ifdef __macos__
00189 
00190 int XrdSysSemaphore::CondWait()
00191 {
00192    int rc;
00193 
00194 // Get the semaphore only we can get it without waiting
00195 //
00196    semVar.Lock();
00197    if ((rc = (semVal > 0) && !semWait)) semVal--;
00198    semVar.UnLock();
00199    return rc;
00200 }
00201 
00202 /******************************************************************************/
00203 /*                                  P o s t                                   */
00204 /******************************************************************************/
00205   
00206 void XrdSysSemaphore::Post()
00207 {
00208 // Add one to the semaphore counter. If we the value is > 0 and there is a
00209 // thread waiting for the sempagore, signal it to get the semaphore.
00210 //
00211    semVar.Lock();
00212    semVal++;
00213    if (semVal && semWait) semVar.Signal();
00214    semVar.UnLock();
00215 }
00216 
00217 /******************************************************************************/
00218 /*                                  W a i t                                   */
00219 /******************************************************************************/
00220   
00221 void XrdSysSemaphore::Wait()
00222 {
00223 
00224 // Wait until the sempahore value is positive. This will not be starvation
00225 // free is the OS implements an unfair mutex;
00226 //
00227    semVar.Lock();
00228    if (semVal < 1 || semWait)
00229       while(semVal < 1)
00230            {semWait++;
00231             semVar.Wait();
00232             semWait--;
00233            }
00234 
00235 // Decrement the semaphore value and return
00236 //
00237    semVal--;
00238    semVar.UnLock();
00239 }
00240 #endif
00241  
00242 /******************************************************************************/
00243 /*                        T h r e a d   M e t h o d s                         */
00244 /******************************************************************************/
00245 /******************************************************************************/
00246 /*                                d o I n i t                                 */
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 /*                                   R u n                                    */
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 /*                                  W a i t                                   */
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 /*                         X r d S y s R e c M u t e x                        */
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  }

Generated on Tue Jul 5 14:47:03 2011 for ROOT_528-00b_version by  doxygen 1.5.1