static void increment_pop_count(void * arg) { sharedInt_t * sI = (sharedInt_t *) arg; pte_osMutexLock(sI->cs); sI->i++; pte_osMutexUnlock(sI->cs); }
int pte_cond_check_need_init (pthread_cond_t * cond) { int result = 0; /* * The following guarded test is specifically for statically * initialised condition variables (via PTHREAD_OBJECT_INITIALIZER). * * Note that by not providing this synchronisation we risk * introducing race conditions into applications which are * correctly written. * * Approach * -------- * We know that static condition variables will not be PROCESS_SHARED * so we can serialise access to internal state using * Win32 Critical Sections rather than Win32 Mutexes. * * If using a single global lock slows applications down too much, * multiple global locks could be created and hashed on some random * value associated with each mutex, the pointer perhaps. At a guess, * a good value for the optimal number of global locks might be * the number of processors + 1. * */ pte_osMutexLock (pte_cond_test_init_lock); /* * We got here possibly under race * conditions. Check again inside the critical section. * If a static cv has been destroyed, the application can * re-initialise it only by calling pthread_cond_init() * explicitly. */ if (*cond == PTHREAD_COND_INITIALIZER) { result = pthread_cond_init (cond, NULL); } else if (*cond == NULL) { /* * The cv has been destroyed while we were waiting to * initialise it, so the operation that caused the * auto-initialisation should fail. */ result = EINVAL; } pte_osMutexUnlock(pte_cond_test_init_lock); return result; }
int pthread_mutex_destroy (pthread_mutex_t * mutex) { int result = 0; pthread_mutex_t mx; /* * Let the system deal with invalid pointers. */ /* * Check to see if we have something to delete. */ if (*mutex < PTHREAD_ERRORCHECK_MUTEX_INITIALIZER) { mx = *mutex; result = pthread_mutex_trylock (&mx); /* * If trylock succeeded and the mutex is not recursively locked it * can be destroyed. */ if (result == 0) { if (mx->kind != PTHREAD_MUTEX_RECURSIVE || 1 == mx->recursive_count) { /* * FIXME!!! * The mutex isn't held by another thread but we could still * be too late invalidating the mutex below since another thread * may already have entered mutex_lock and the check for a valid * *mutex != NULL. * * Note that this would be an unusual situation because it is not * common that mutexes are destroyed while they are still in * use by other threads. */ *mutex = NULL; result = pthread_mutex_unlock (&mx); if (result == 0) { pte_osSemaphoreDelete(mx->handle); free(mx); } else { /* * Restore the mutex before we return the error. */ *mutex = mx; } } else /* mx->recursive_count > 1 */ { /* * The mutex must be recursive and already locked by us (this thread). */ mx->recursive_count--; /* Undo effect of pthread_mutex_trylock() above */ result = EBUSY; } } } else { /* * See notes in pte_mutex_check_need_init() above also. */ pte_osMutexLock (pte_mutex_test_init_lock); /* * Check again. */ if (*mutex >= PTHREAD_ERRORCHECK_MUTEX_INITIALIZER) { /* * This is all we need to do to destroy a statically * initialised mutex that has not yet been used (initialised). * If we get to here, another thread * waiting to initialise this mutex will get an EINVAL. */ *mutex = NULL; } else { /* * The mutex has been initialised while we were waiting * so assume it's in use. */ result = EBUSY; } pte_osMutexUnlock(pte_mutex_test_init_lock); } return (result); }
int pthread_rwlock_destroy (pthread_rwlock_t * rwlock) { pthread_rwlock_t rwl; int result = 0, result1 = 0, result2 = 0; if (rwlock == NULL || *rwlock == NULL) return EINVAL; if (*rwlock != PTHREAD_RWLOCK_INITIALIZER) { rwl = *rwlock; if (rwl->nMagic != PTE_RWLOCK_MAGIC) return EINVAL; if ((result = pthread_mutex_lock (&(rwl->mtxExclusiveAccess))) != 0) return result; if ((result = pthread_mutex_lock (&(rwl->mtxSharedAccessCompleted))) != 0) { (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess)); return result; } /* * Check whether any threads own/wait for the lock (wait for ex.access); * report "BUSY" if so. */ if (rwl->nExclusiveAccessCount > 0 || rwl->nSharedAccessCount > rwl->nCompletedSharedAccessCount) { result = pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted)); result1 = pthread_mutex_unlock (&(rwl->mtxExclusiveAccess)); result2 = EBUSY; } else { rwl->nMagic = 0; if ((result = pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted))) != 0) { pthread_mutex_unlock (&rwl->mtxExclusiveAccess); return result; } if ((result = pthread_mutex_unlock (&(rwl->mtxExclusiveAccess))) != 0) return result; *rwlock = NULL; /* Invalidate rwlock before anything else */ result = pthread_cond_destroy (&(rwl->cndSharedAccessCompleted)); result1 = pthread_mutex_destroy (&(rwl->mtxSharedAccessCompleted)); result2 = pthread_mutex_destroy (&(rwl->mtxExclusiveAccess)); (void) free (rwl); } } else { /* * See notes in pte_rwlock_check_need_init() above also. */ pte_osMutexLock (pte_rwlock_test_init_lock); /* * Check again. */ if (*rwlock == PTHREAD_RWLOCK_INITIALIZER) { /* * This is all we need to do to destroy a statically * initialised rwlock that has not yet been used (initialised). * If we get to here, another thread * waiting to initialise this rwlock will get an EINVAL. */ *rwlock = NULL; } /* * The rwlock has been initialised while we were waiting * so assume it's in use. */ else result = EBUSY; pte_osMutexUnlock(pte_rwlock_test_init_lock); } return ((result != 0) ? result : ((result1 != 0) ? result1 : result2)); }
int pthread_detach (pthread_t thread) /* * ------------------------------------------------------ * DOCPUBLIC * This function detaches the given thread. * * PARAMETERS * thread * an instance of a pthread_t * * * DESCRIPTION * This function detaches the given thread. You may use it to * detach the main thread or to detach a joinable thread. * NOTE: detached threads cannot be joined; * storage is freed immediately on termination. * * RESULTS * 0 successfully detached the thread, * EINVAL thread is not a joinable thread, * ENOSPC a required resource has been exhausted, * ESRCH no thread could be found for 'thread', * * ------------------------------------------------------ */ { int result; unsigned char destroyIt = PTE_FALSE; pte_thread_t * tp = (pte_thread_t *) thread.p; pte_osMutexLock (pte_thread_reuse_lock); if (NULL == tp || thread.x != tp->ptHandle.x) { result = ESRCH; } else if (PTHREAD_CREATE_DETACHED == tp->detachState) { result = EINVAL; } else { /* * Joinable pte_thread_t structs are not scavenged until * a join or detach is done. The thread may have exited already, * but all of the state and locks etc are still there. */ result = 0; if (pthread_mutex_lock (&tp->cancelLock) == 0) { if (tp->state != PThreadStateLast) { tp->detachState = PTHREAD_CREATE_DETACHED; } else if (tp->detachState != PTHREAD_CREATE_DETACHED) { /* * Thread is joinable and has exited or is exiting. */ destroyIt = PTE_TRUE; } (void) pthread_mutex_unlock (&tp->cancelLock); } else { /* cancelLock shouldn't fail, but if it does ... */ result = ESRCH; } } pte_osMutexUnlock(pte_thread_reuse_lock); if (result == 0) { /* Thread is joinable */ if (destroyIt) { /* The thread has exited or is exiting but has not been joined or * detached. Need to wait in case it's still exiting. */ pte_osThreadWaitForEnd(tp->threadId); pte_threadDestroy (thread); } } return (result); } /* pthread_detach */