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