1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/ossrv/genericopenlibs/openenvcore/libpthread/src/condvar.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,301 @@
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 : condvar.cpp
1.18 +// Part of : pthread
1.19 +// Interface : POSIX, pthread
1.20 +// POSIX implementation of pthread on Symbian
1.21 +// Version :
1.22 +//
1.23 +
1.24 +
1.25 +
1.26 +#include "condvartypes.h"
1.27 +
1.28 +/*
1.29 +This internal function initializes the passed queue to be an empty queue
1.30 +*/
1.31 +bool _QueueInit(_CondQueue* aQueue)
1.32 +{
1.33 + if(!aQueue)
1.34 + {
1.35 + return false;
1.36 + }
1.37 + pthread_mutex_init(&aQueue->iMutex,NULL);
1.38 + aQueue->iHead = aQueue->iTail = NULL;
1.39 + return true;
1.40 +}
1.41 +
1.42 +/*
1.43 +This internal function destroys the passed
1.44 +*/
1.45 +int _QueueDestroy(_CondQueue* aQueue)
1.46 +{
1.47 + if(!aQueue)
1.48 + {
1.49 + return EINVAL;
1.50 + }
1.51 + pthread_mutex_lock(&aQueue->iMutex);
1.52 + _CondNode* head = aQueue->iHead;
1.53 + pthread_mutex_unlock(&aQueue->iMutex);
1.54 + if (head)
1.55 + {
1.56 + return EBUSY;
1.57 + }
1.58 + else
1.59 + {
1.60 + return pthread_mutex_destroy(&aQueue->iMutex);
1.61 + }
1.62 +}
1.63 +
1.64 +
1.65 +/*
1.66 +This internal function atomically adds a element
1.67 +to the passed queue
1.68 +*/
1.69 +bool _QueueAdd(_CondQueue* aQueue, _CondNode* aNode)
1.70 +{
1.71 + if( (!aQueue) || (!aNode) )
1.72 + {
1.73 + return false;
1.74 + }
1.75 + aNode->iNext = NULL;
1.76 + pthread_mutex_lock(&aQueue->iMutex);
1.77 + if(!(aQueue->iHead))
1.78 + {
1.79 + aQueue->iHead = aQueue->iTail = aNode;
1.80 + }
1.81 + else
1.82 + {
1.83 + aQueue->iTail->iNext = aNode;
1.84 + aQueue->iTail = aNode;
1.85 + }
1.86 + pthread_mutex_unlock(&aQueue->iMutex);
1.87 + return true;
1.88 +}
1.89 +
1.90 +
1.91 +/*
1.92 +This internal function atomically removes the pased element
1.93 +from the queue
1.94 +*/
1.95 +bool _QueueRemove(_CondQueue* aQueue, _CondNode* aNode)
1.96 +{
1.97 + if( (!aQueue) || (!aNode) )
1.98 + {
1.99 + return false;
1.100 + }
1.101 + pthread_mutex_lock(&aQueue->iMutex);
1.102 +
1.103 + _CondNode* prev = NULL;
1.104 + _CondNode* node = aQueue->iHead;
1.105 + for(; node; node = node->iNext)
1.106 + {
1.107 + if(node == aNode)
1.108 + {
1.109 + break;
1.110 + }
1.111 + prev = node;
1.112 + }
1.113 + if(node)
1.114 + {
1.115 + if(node == aQueue->iHead)
1.116 + {
1.117 + aQueue->iHead = node->iNext;
1.118 + }
1.119 + if(node == aQueue->iTail)
1.120 + {
1.121 + aQueue->iTail = prev;
1.122 + }
1.123 + if(prev)
1.124 + {
1.125 + prev->iNext = node->iNext;
1.126 + }
1.127 + }// node found
1.128 + pthread_mutex_unlock(&aQueue->iMutex);
1.129 + return (node) ? true : false;
1.130 +}
1.131 +
1.132 +/*
1.133 +This internal function atomically removes the head of the queue, and
1.134 +returns a pointer to this node
1.135 +*/
1.136 +_CondNode* _QueueRemoveHead(_CondQueue* aQueue)
1.137 +{
1.138 + _CondNode* retNode = NULL;
1.139 + pthread_mutex_lock(&aQueue->iMutex);
1.140 + retNode = aQueue->iHead;
1.141 + if(retNode)
1.142 + {
1.143 + aQueue->iHead = retNode->iNext;
1.144 + if(aQueue->iTail == retNode)
1.145 + {
1.146 + aQueue->iTail = aQueue->iHead = NULL;
1.147 + }
1.148 + }
1.149 + pthread_mutex_unlock(&aQueue->iMutex);
1.150 + return retNode;
1.151 +}
1.152 +
1.153 +
1.154 +/*
1.155 +This internal function removes the head of the queue, and
1.156 +returns a pointer to this node WITHOUT locking the associated mutex
1.157 +*/
1.158 +_CondNode* _QueueRemoveHeadNoLock(_CondQueue* aQueue)
1.159 +{
1.160 + _CondNode* retNode = NULL;
1.161 + retNode = aQueue->iHead;
1.162 + if(retNode)
1.163 + {
1.164 + aQueue->iHead = retNode->iNext;
1.165 + if(aQueue->iTail == retNode)
1.166 + {
1.167 + aQueue->iTail = aQueue->iHead = NULL;
1.168 + }
1.169 + }
1.170 + return retNode;
1.171 +}
1.172 +
1.173 +/*
1.174 +This internal function locks the queue mutex
1.175 +*/
1.176 +void _QueueLock(_CondQueue* aQueue)
1.177 +{
1.178 + pthread_mutex_lock(&aQueue->iMutex);
1.179 +}
1.180 +
1.181 +/*
1.182 +This internal function unlocks the queue mutex
1.183 +*/
1.184 +void _QueueUnlock(_CondQueue* aQueue)
1.185 +{
1.186 + pthread_mutex_unlock(&aQueue->iMutex);
1.187 +}
1.188 +
1.189 +/*
1.190 +This internal function atomically resolves the race to dynamically initialize a static cond var
1.191 +*/
1.192 +bool _staticCondInit(pthread_cond_t* cond)
1.193 +{
1.194 + if(!cond)
1.195 + {
1.196 + return false;
1.197 + }
1.198 + if(cond->iState == _EInitialized)
1.199 + {
1.200 + return true;
1.201 + }
1.202 +
1.203 +
1.204 + if(cond->iState != _ENeedsNormalInit)
1.205 + {
1.206 + return false;
1.207 + }
1.208 + int retval=0;
1.209 +
1.210 + #ifndef NOUSE_INTERNALS
1.211 + void* tlsPtr;
1.212 +
1.213 + // Get the TLS pointer
1.214 + tlsPtr = _pthread_getTls();
1.215 + if(NULL == tlsPtr)
1.216 + {
1.217 + return false;
1.218 + }
1.219 + _pthread_atomicMutexLock(tlsPtr);
1.220 + #endif
1.221 +
1.222 + //another thread might win race
1.223 + if(cond->iState != _EInitialized)
1.224 + {
1.225 + retval = pthread_cond_init(cond,NULL);
1.226 + }
1.227 +
1.228 + #ifndef NOUSE_INTERNALS
1.229 + _pthread_atomicMutexUnlock(tlsPtr);
1.230 + #endif
1.231 + if(retval == 0)
1.232 + {
1.233 + return true;
1.234 + }
1.235 + else
1.236 + {
1.237 + return false;
1.238 + }
1.239 +}
1.240 +
1.241 +/*
1.242 +This internal function provides the functionality to wait on a condition variable,
1.243 +*/
1.244 +int _internalCondWait(pthread_cond_t *cond, pthread_mutex_t *mutex,const struct timespec *abstime)
1.245 +{
1.246 + if(!_staticCondInit(cond))
1.247 + {
1.248 + return EINVAL;
1.249 + }
1.250 +
1.251 + _CondNode* newNode = new _CondNode;
1.252 + if(!newNode)
1.253 + {
1.254 + return ENOMEM;
1.255 + }
1.256 + sem_init(&newNode->iSemaphore,0,0);
1.257 +
1.258 + _QueueAdd(&cond->iQueue,newNode);
1.259 +
1.260 + int retval=0;
1.261 +
1.262 + //unlock passed mutex
1.263 + retval = pthread_mutex_unlock(mutex);
1.264 + if(retval != 0)
1.265 + {
1.266 + _QueueRemove(&cond->iQueue,newNode);
1.267 + sem_destroy(&newNode->iSemaphore);
1.268 + delete newNode;
1.269 + errno = 0; // Condition variables should not set errno
1.270 + return retval;
1.271 + }
1.272 +
1.273 + //node removed from queue by pthread_cond_signal or pthread_cond_broadcast
1.274 + //by timeout below
1.275 + if(abstime)
1.276 + {
1.277 + retval = sem_timedwait(&newNode->iSemaphore,abstime);
1.278 + if(retval != 0)
1.279 + {
1.280 + _QueueRemove(&cond->iQueue,newNode);
1.281 + }//timed_wait timedout
1.282 + }
1.283 + else
1.284 + {
1.285 + retval = sem_wait(&newNode->iSemaphore);
1.286 + }
1.287 + if(retval != 0)
1.288 + {
1.289 + retval = errno;
1.290 + }
1.291 + sem_destroy(&newNode->iSemaphore);
1.292 + delete newNode;
1.293 + /* This is a cancellation point */
1.294 + //test for cancel
1.295 + pthread_testcancel();
1.296 +
1.297 + //lock the passed mutex
1.298 + pthread_mutex_lock(mutex);
1.299 +
1.300 + errno = 0; // Condition variables should not set errno
1.301 + return retval;
1.302 +}
1.303 +
1.304 +//End of File