os/ossrv/genericopenlibs/openenvcore/libpthread/src/mutex.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // Name        : mutex.cpp
    15 // Part of     : pthread
    16 // Interface   : POSIX, pthread
    17 // POSIX implementation of mutexes on Symbian
    18 // Version     :
    19 //
    20 
    21 
    22 
    23 #include "mutextypes.h"
    24 
    25 /*
    26 This function waits on the aLock semaphore. 
    27 */
    28 int _doWait(RSemaphore* aLock, const struct timespec *abstime)
    29 {
    30     int retval = 0;
    31     if(!abstime)
    32     {
    33         aLock->Wait();
    34     }
    35     else
    36     {
    37         long lSleepTime = _microsleeptime(abstime);
    38         if(lSleepTime <0)
    39         {
    40             if (EINVAL == errno)
    41             {
    42                 errno = 0;
    43                 return EINVAL;    
    44             }
    45             else if(ETIMEDOUT == errno)
    46             {
    47                 errno = 0;
    48                 return ETIMEDOUT;
    49             }
    50             
    51         }
    52 
    53         retval = aLock->Wait(lSleepTime);
    54         if(retval != KErrNone)
    55         {
    56             return  ETIMEDOUT;
    57         }
    58 
    59     }
    60     return 0;
    61 }
    62 
    63 /*
    64 This internal function destroys the mutex object.
    65 */
    66 void _closeMutex(pthread_mutex_t* mutex)
    67 {
    68     _pthread_mutex_t* pMutex = mutex->iPtr;
    69     if(pMutex)
    70     {
    71         if(pMutex->iSemaphoreCreated)
    72         {
    73             pMutex->iSignalSemaphore.Close();       
    74         }
    75         if(pMutex->iDataLockCreated)
    76         {
    77             pMutex->iDataLock.Close();  
    78         }
    79         mutex->iPtr = NULL;
    80         delete pMutex; 
    81     }
    82     return;
    83 }
    84 
    85 int _mutexCreate (pthread_mutex_t * mutex, 
    86                   const pthread_mutexattr_t* attr)
    87 {
    88 
    89     if( attr->iSharedType != PTHREAD_PROCESS_PRIVATE)
    90     {
    91         return ENOSYS;
    92     }
    93 
    94     mutex->iState = _EInvalid;
    95     _pthread_mutex_t* pMutex = new _pthread_mutex_t; 
    96     mutex->iPtr = pMutex;
    97     if(!pMutex)
    98     {
    99         return ENOMEM;
   100     }
   101 
   102     pMutex->iSharedType = attr->iSharedType;
   103     pMutex->iMutexType = attr->iMutexType;
   104     pMutex->iDataLockCreated = false;
   105     pMutex->iSemaphoreCreated = false;
   106 
   107     if(pMutex->iSignalSemaphore.CreateLocal(1) != KErrNone)
   108     {
   109         _closeMutex(mutex);
   110         return EAGAIN;
   111     }
   112     pMutex->iSemaphoreCreated = true;
   113 
   114     if(pMutex->iDataLock.CreateLocal() != KErrNone)
   115     {
   116         _closeMutex(mutex);
   117         return EAGAIN;
   118     }
   119     pMutex->iDataLockCreated = true;
   120 
   121     pMutex->iCount = 0;
   122     pMutex->iSemaphoreState = SEM_FREE;
   123     pMutex->iLockingThread = 0;
   124     mutex->iState = _EInitialized;
   125     return 0;
   126 }
   127 
   128 
   129 /*
   130 This function is an internal  harness function used to resolve the race to dynamically initialize a static mutex
   131 */
   132 bool _InitOnce(pthread_mutex_t* mutex)
   133 {
   134 
   135     pthread_mutexattr_t defaultattributes = 
   136                             PTHREAD_MUTEX_ATTRIBUTE_DEFAULT_INITIALIZER;
   137     pthread_mutexattr_t recursiveattributes = 
   138                             PTHREAD_MUTEX_ATTRIBUTE_RECURSIVE_INITIALIZER;
   139     pthread_mutexattr_t errorcheckattributes = 
   140                             PTHREAD_MUTEX_ATTRIBUTE_ERRORCHECK_INITIALIZER;
   141 
   142     if(mutex->iState == _EInitialized)
   143     {
   144         return true;
   145     }
   146    
   147     mutex->iReentry = 0xBABA;
   148 
   149     pthread_mutexattr_t* attr;
   150     switch(mutex->iState)
   151     {
   152         case _ENeedsNormalInit:
   153         {
   154             attr = &defaultattributes;
   155             break;
   156         }
   157 
   158         case _ENeedsRecursiveInit:
   159         {
   160             attr = &recursiveattributes;
   161             break;
   162         }
   163 
   164         case _ENeedsErrorCheckInit:
   165         {
   166             attr = &errorcheckattributes;
   167             break;
   168         }
   169 
   170         default:
   171             return false;
   172     }
   173 
   174 #ifndef NOUSE_INTERNALS
   175     void* tlsPtr;
   176 
   177     // Get the TLS pointer
   178     tlsPtr = _pthread_getTls(); 
   179 
   180     if(!tlsPtr)
   181     {
   182         return false;
   183     }
   184 #endif    
   185 
   186     int retval=0;
   187 #ifndef NOUSE_INTERNALS
   188     _pthread_atomicMutexLock(tlsPtr);
   189 #endif
   190     if(mutex->iState != _EInitialized)
   191     {
   192         retval = _mutexCreate(mutex,attr);
   193     }
   194 #ifndef NOUSE_INTERNALS   
   195     _pthread_atomicMutexUnlock(tlsPtr);
   196 #endif   
   197      
   198     if(retval == 0)
   199     {
   200         return true;
   201     }
   202     else 
   203     {
   204         return false;
   205     }
   206 }
   207 
   208 
   209 /*
   210 This function is an internal function used to provide the POSIX mutex lock 
   211 functionality.
   212 */
   213 int _internalMutexLock(pthread_mutex_t * mutex,const struct timespec *abstime)
   214 {
   215     if( !VALID_MUTEX(mutex) )
   216     {
   217         return EINVAL;
   218     }
   219 
   220     _pthread_mutex_t* pMutex = mutex->iPtr;
   221 
   222 
   223     int retval = 0;
   224     pthread_t self;
   225     switch(pMutex->iMutexType)
   226     {
   227         case  PTHREAD_MUTEX_NORMAL:
   228         	{
   229         	  self = pthread_self();          
   230         	  pMutex->iDataLock.Wait();
   231         	  if(mutex->iState == _EDestroyed)
   232         	  {
   233         	     pMutex->iDataLock.Signal();
   234         	     return EINVAL;
   235         	  }
   236         	  pMutex->iSemaphoreState++;   
   237         	  pMutex->iDataLock.Signal();
   238         	           
   239         	  retval = _doWait(&pMutex->iSignalSemaphore,abstime);
   240         	  if(retval == 0)
   241         	  {
   242         	     pMutex->iDataLock.Wait();
   243         	     if(mutex->iState == _EDestroyed)
   244         	     {
   245         	        pMutex->iDataLock.Signal();
   246         	        return EINVAL;
   247         	     }
   248         	     pMutex->iLockingThread  = self;
   249         	     pMutex->iDataLock.Signal();
   250                }
   251         	   break;
   252         	 }
   253 
   254         case  PTHREAD_MUTEX_RECURSIVE:
   255         	
   256         {
   257             self = pthread_self();
   258             if(pMutex->iLockingThread == self)
   259             {
   260                 pMutex->iDataLock.Wait();
   261                 if(mutex->iState == _EDestroyed)
   262                 {
   263                    pMutex->iDataLock.Signal();
   264                    return EINVAL;
   265                 }
   266                 pMutex->iCount++;
   267                 pMutex->iDataLock.Signal();
   268             }
   269             else
   270             {
   271                 pMutex->iDataLock.Wait();
   272                 if(mutex->iState == _EDestroyed)
   273                 {
   274                    pMutex->iDataLock.Signal();
   275                    return EINVAL;
   276                 }
   277                 pMutex->iSemaphoreState++;   
   278                 pMutex->iDataLock.Signal();
   279                 
   280                 retval = _doWait(&pMutex->iSignalSemaphore,abstime);
   281                 if(retval == 0)
   282                 {
   283                     pMutex->iDataLock.Wait();
   284                     if(mutex->iState == _EDestroyed)
   285                     {
   286                       pMutex->iDataLock.Signal();
   287                       return EINVAL;
   288                     }
   289                     pMutex->iCount = 1;
   290                     pMutex->iLockingThread = self;
   291                     pMutex->iDataLock.Signal();
   292                 }
   293             }
   294             break;
   295         }                          
   296 
   297         case  PTHREAD_MUTEX_ERRORCHECK:
   298         {
   299             self = pthread_self();
   300             if(pMutex->iLockingThread == self)
   301             {
   302                 return EDEADLK;
   303             }
   304             else
   305             {
   306                 pMutex->iDataLock.Wait();
   307                 if(mutex->iState == _EDestroyed)
   308                 {
   309                    pMutex->iDataLock.Signal();
   310                    return EINVAL;
   311                 }
   312                 pMutex->iSemaphoreState++;     
   313                 pMutex->iDataLock.Signal();
   314                 
   315                 retval = _doWait(&pMutex->iSignalSemaphore,abstime);
   316                 if(retval == 0)
   317                 {
   318                   pMutex->iDataLock.Wait();
   319                   if(mutex->iState == _EDestroyed)
   320                   {
   321                      pMutex->iDataLock.Signal();
   322                      return EINVAL;
   323                   }
   324                   pMutex->iLockingThread  = self;
   325                   pMutex->iDataLock.Signal();
   326                 }
   327             }
   328             break;
   329         }
   330 
   331         default:
   332         retval = ENOSYS;
   333         break;
   334 
   335     }
   336     return retval;
   337 
   338 }
   339 
   340 //End of File