1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/ossrv/genericopenlibs/openenvcore/libpthread/src/mutex.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,340 @@
1.4 +// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// Name : mutex.cpp
1.18 +// Part of : pthread
1.19 +// Interface : POSIX, pthread
1.20 +// POSIX implementation of mutexes on Symbian
1.21 +// Version :
1.22 +//
1.23 +
1.24 +
1.25 +
1.26 +#include "mutextypes.h"
1.27 +
1.28 +/*
1.29 +This function waits on the aLock semaphore.
1.30 +*/
1.31 +int _doWait(RSemaphore* aLock, const struct timespec *abstime)
1.32 +{
1.33 + int retval = 0;
1.34 + if(!abstime)
1.35 + {
1.36 + aLock->Wait();
1.37 + }
1.38 + else
1.39 + {
1.40 + long lSleepTime = _microsleeptime(abstime);
1.41 + if(lSleepTime <0)
1.42 + {
1.43 + if (EINVAL == errno)
1.44 + {
1.45 + errno = 0;
1.46 + return EINVAL;
1.47 + }
1.48 + else if(ETIMEDOUT == errno)
1.49 + {
1.50 + errno = 0;
1.51 + return ETIMEDOUT;
1.52 + }
1.53 +
1.54 + }
1.55 +
1.56 + retval = aLock->Wait(lSleepTime);
1.57 + if(retval != KErrNone)
1.58 + {
1.59 + return ETIMEDOUT;
1.60 + }
1.61 +
1.62 + }
1.63 + return 0;
1.64 +}
1.65 +
1.66 +/*
1.67 +This internal function destroys the mutex object.
1.68 +*/
1.69 +void _closeMutex(pthread_mutex_t* mutex)
1.70 +{
1.71 + _pthread_mutex_t* pMutex = mutex->iPtr;
1.72 + if(pMutex)
1.73 + {
1.74 + if(pMutex->iSemaphoreCreated)
1.75 + {
1.76 + pMutex->iSignalSemaphore.Close();
1.77 + }
1.78 + if(pMutex->iDataLockCreated)
1.79 + {
1.80 + pMutex->iDataLock.Close();
1.81 + }
1.82 + mutex->iPtr = NULL;
1.83 + delete pMutex;
1.84 + }
1.85 + return;
1.86 +}
1.87 +
1.88 +int _mutexCreate (pthread_mutex_t * mutex,
1.89 + const pthread_mutexattr_t* attr)
1.90 +{
1.91 +
1.92 + if( attr->iSharedType != PTHREAD_PROCESS_PRIVATE)
1.93 + {
1.94 + return ENOSYS;
1.95 + }
1.96 +
1.97 + mutex->iState = _EInvalid;
1.98 + _pthread_mutex_t* pMutex = new _pthread_mutex_t;
1.99 + mutex->iPtr = pMutex;
1.100 + if(!pMutex)
1.101 + {
1.102 + return ENOMEM;
1.103 + }
1.104 +
1.105 + pMutex->iSharedType = attr->iSharedType;
1.106 + pMutex->iMutexType = attr->iMutexType;
1.107 + pMutex->iDataLockCreated = false;
1.108 + pMutex->iSemaphoreCreated = false;
1.109 +
1.110 + if(pMutex->iSignalSemaphore.CreateLocal(1) != KErrNone)
1.111 + {
1.112 + _closeMutex(mutex);
1.113 + return EAGAIN;
1.114 + }
1.115 + pMutex->iSemaphoreCreated = true;
1.116 +
1.117 + if(pMutex->iDataLock.CreateLocal() != KErrNone)
1.118 + {
1.119 + _closeMutex(mutex);
1.120 + return EAGAIN;
1.121 + }
1.122 + pMutex->iDataLockCreated = true;
1.123 +
1.124 + pMutex->iCount = 0;
1.125 + pMutex->iSemaphoreState = SEM_FREE;
1.126 + pMutex->iLockingThread = 0;
1.127 + mutex->iState = _EInitialized;
1.128 + return 0;
1.129 +}
1.130 +
1.131 +
1.132 +/*
1.133 +This function is an internal harness function used to resolve the race to dynamically initialize a static mutex
1.134 +*/
1.135 +bool _InitOnce(pthread_mutex_t* mutex)
1.136 +{
1.137 +
1.138 + pthread_mutexattr_t defaultattributes =
1.139 + PTHREAD_MUTEX_ATTRIBUTE_DEFAULT_INITIALIZER;
1.140 + pthread_mutexattr_t recursiveattributes =
1.141 + PTHREAD_MUTEX_ATTRIBUTE_RECURSIVE_INITIALIZER;
1.142 + pthread_mutexattr_t errorcheckattributes =
1.143 + PTHREAD_MUTEX_ATTRIBUTE_ERRORCHECK_INITIALIZER;
1.144 +
1.145 + if(mutex->iState == _EInitialized)
1.146 + {
1.147 + return true;
1.148 + }
1.149 +
1.150 + mutex->iReentry = 0xBABA;
1.151 +
1.152 + pthread_mutexattr_t* attr;
1.153 + switch(mutex->iState)
1.154 + {
1.155 + case _ENeedsNormalInit:
1.156 + {
1.157 + attr = &defaultattributes;
1.158 + break;
1.159 + }
1.160 +
1.161 + case _ENeedsRecursiveInit:
1.162 + {
1.163 + attr = &recursiveattributes;
1.164 + break;
1.165 + }
1.166 +
1.167 + case _ENeedsErrorCheckInit:
1.168 + {
1.169 + attr = &errorcheckattributes;
1.170 + break;
1.171 + }
1.172 +
1.173 + default:
1.174 + return false;
1.175 + }
1.176 +
1.177 +#ifndef NOUSE_INTERNALS
1.178 + void* tlsPtr;
1.179 +
1.180 + // Get the TLS pointer
1.181 + tlsPtr = _pthread_getTls();
1.182 +
1.183 + if(!tlsPtr)
1.184 + {
1.185 + return false;
1.186 + }
1.187 +#endif
1.188 +
1.189 + int retval=0;
1.190 +#ifndef NOUSE_INTERNALS
1.191 + _pthread_atomicMutexLock(tlsPtr);
1.192 +#endif
1.193 + if(mutex->iState != _EInitialized)
1.194 + {
1.195 + retval = _mutexCreate(mutex,attr);
1.196 + }
1.197 +#ifndef NOUSE_INTERNALS
1.198 + _pthread_atomicMutexUnlock(tlsPtr);
1.199 +#endif
1.200 +
1.201 + if(retval == 0)
1.202 + {
1.203 + return true;
1.204 + }
1.205 + else
1.206 + {
1.207 + return false;
1.208 + }
1.209 +}
1.210 +
1.211 +
1.212 +/*
1.213 +This function is an internal function used to provide the POSIX mutex lock
1.214 +functionality.
1.215 +*/
1.216 +int _internalMutexLock(pthread_mutex_t * mutex,const struct timespec *abstime)
1.217 +{
1.218 + if( !VALID_MUTEX(mutex) )
1.219 + {
1.220 + return EINVAL;
1.221 + }
1.222 +
1.223 + _pthread_mutex_t* pMutex = mutex->iPtr;
1.224 +
1.225 +
1.226 + int retval = 0;
1.227 + pthread_t self;
1.228 + switch(pMutex->iMutexType)
1.229 + {
1.230 + case PTHREAD_MUTEX_NORMAL:
1.231 + {
1.232 + self = pthread_self();
1.233 + pMutex->iDataLock.Wait();
1.234 + if(mutex->iState == _EDestroyed)
1.235 + {
1.236 + pMutex->iDataLock.Signal();
1.237 + return EINVAL;
1.238 + }
1.239 + pMutex->iSemaphoreState++;
1.240 + pMutex->iDataLock.Signal();
1.241 +
1.242 + retval = _doWait(&pMutex->iSignalSemaphore,abstime);
1.243 + if(retval == 0)
1.244 + {
1.245 + pMutex->iDataLock.Wait();
1.246 + if(mutex->iState == _EDestroyed)
1.247 + {
1.248 + pMutex->iDataLock.Signal();
1.249 + return EINVAL;
1.250 + }
1.251 + pMutex->iLockingThread = self;
1.252 + pMutex->iDataLock.Signal();
1.253 + }
1.254 + break;
1.255 + }
1.256 +
1.257 + case PTHREAD_MUTEX_RECURSIVE:
1.258 +
1.259 + {
1.260 + self = pthread_self();
1.261 + if(pMutex->iLockingThread == self)
1.262 + {
1.263 + pMutex->iDataLock.Wait();
1.264 + if(mutex->iState == _EDestroyed)
1.265 + {
1.266 + pMutex->iDataLock.Signal();
1.267 + return EINVAL;
1.268 + }
1.269 + pMutex->iCount++;
1.270 + pMutex->iDataLock.Signal();
1.271 + }
1.272 + else
1.273 + {
1.274 + pMutex->iDataLock.Wait();
1.275 + if(mutex->iState == _EDestroyed)
1.276 + {
1.277 + pMutex->iDataLock.Signal();
1.278 + return EINVAL;
1.279 + }
1.280 + pMutex->iSemaphoreState++;
1.281 + pMutex->iDataLock.Signal();
1.282 +
1.283 + retval = _doWait(&pMutex->iSignalSemaphore,abstime);
1.284 + if(retval == 0)
1.285 + {
1.286 + pMutex->iDataLock.Wait();
1.287 + if(mutex->iState == _EDestroyed)
1.288 + {
1.289 + pMutex->iDataLock.Signal();
1.290 + return EINVAL;
1.291 + }
1.292 + pMutex->iCount = 1;
1.293 + pMutex->iLockingThread = self;
1.294 + pMutex->iDataLock.Signal();
1.295 + }
1.296 + }
1.297 + break;
1.298 + }
1.299 +
1.300 + case PTHREAD_MUTEX_ERRORCHECK:
1.301 + {
1.302 + self = pthread_self();
1.303 + if(pMutex->iLockingThread == self)
1.304 + {
1.305 + return EDEADLK;
1.306 + }
1.307 + else
1.308 + {
1.309 + pMutex->iDataLock.Wait();
1.310 + if(mutex->iState == _EDestroyed)
1.311 + {
1.312 + pMutex->iDataLock.Signal();
1.313 + return EINVAL;
1.314 + }
1.315 + pMutex->iSemaphoreState++;
1.316 + pMutex->iDataLock.Signal();
1.317 +
1.318 + retval = _doWait(&pMutex->iSignalSemaphore,abstime);
1.319 + if(retval == 0)
1.320 + {
1.321 + pMutex->iDataLock.Wait();
1.322 + if(mutex->iState == _EDestroyed)
1.323 + {
1.324 + pMutex->iDataLock.Signal();
1.325 + return EINVAL;
1.326 + }
1.327 + pMutex->iLockingThread = self;
1.328 + pMutex->iDataLock.Signal();
1.329 + }
1.330 + }
1.331 + break;
1.332 + }
1.333 +
1.334 + default:
1.335 + retval = ENOSYS;
1.336 + break;
1.337 +
1.338 + }
1.339 + return retval;
1.340 +
1.341 +}
1.342 +
1.343 +//End of File