static int ThreadHelper (void *startInfo) { ThreadFunction func; void *data; SDL_sem *sem; TrueThread thread; int result; func = ((struct ThreadStartInfo *) startInfo)->func; data = ((struct ThreadStartInfo *) startInfo)->data; sem = ((struct ThreadStartInfo *) startInfo)->sem; // Wait until the Thread structure is available. SDL_SemWait (sem); SDL_DestroySemaphore (sem); thread = ((struct ThreadStartInfo *) startInfo)->thread; HFree (startInfo); result = (*func) (data); #ifdef DEBUG_THREADS log_add (log_Debug, "Thread '%s' done (returned %d).", thread->name, result); fflush (stderr); #endif UnQueueThread (thread); DestroyThreadLocal (thread->localData); FinishThread (thread); /* Destroying the thread is the responsibility of ProcessThreadLifecycles() */ return result; }
static void * ThreadHelper (void *startInfo) { ThreadFunction func; void *data; sem_t *sem; TrueThread thread; int result; //log_add (log_Debug, "ThreadHelper()"); func = ((struct ThreadStartInfo *) startInfo)->func; data = ((struct ThreadStartInfo *) startInfo)->data; sem = &((struct ThreadStartInfo *) startInfo)->sem; // Wait until the Thread structure is available. if (sem_wait (sem)) { log_add(log_Fatal, "ThreadHelper sem_wait fail"); exit(EXIT_FAILURE); } if (sem_destroy (sem)) { log_add(log_Fatal, "ThreadHelper sem_destroy fail"); exit(EXIT_FAILURE); } thread = ((struct ThreadStartInfo *) startInfo)->thread; HFree (startInfo); result = (*func) (data); #ifdef DEBUG_THREADS log_add (log_Debug, "Thread '%s' done (returned %d).", thread->name, result); fflush (stderr); #endif UnQueueThread (thread); DestroyThreadLocal (thread->localData); FinishThread (thread); /* Destroying the thread is the responsibility of ProcessThreadLifecycles() */ return (void*)result; }
void BaseService::Stop() { FinishThread(); }
static VOID TestResourceWithThreads( IN PERESOURCE Res) { NTSTATUS Status = STATUS_SUCCESS; THREAD_DATA ThreadDataShared; THREAD_DATA ThreadDataShared2; THREAD_DATA ThreadDataExclusive; THREAD_DATA ThreadDataSharedStarve; THREAD_DATA ThreadDataSharedWait; LARGE_INTEGER Timeout; Timeout.QuadPart = -10 * 1000 * 10; /* 10 ms */ InitThreadData(&ThreadDataShared, Res, ExAcquireResourceSharedLite); InitThreadData(&ThreadDataShared2, Res, ExAcquireResourceSharedLite); InitThreadData(&ThreadDataExclusive, Res, ExAcquireResourceExclusiveLite); InitThreadData(&ThreadDataSharedStarve, Res, ExAcquireSharedStarveExclusive); InitThreadData(&ThreadDataSharedWait, Res, ExAcquireSharedWaitForExclusive); /* have a thread acquire the resource shared */ Status = StartThread(&ThreadDataShared, NULL, FALSE, TRUE); ok_eq_hex(Status, STATUS_SUCCESS); CheckResourceStatus(Res, FALSE, 0LU, 0LU, 0LU); ok_eq_int(Res->ActiveCount, 1); /* a second thread should be able to acquire the resource shared */ Status = StartThread(&ThreadDataShared2, NULL, FALSE, TRUE); ok_eq_hex(Status, STATUS_SUCCESS); CheckResourceStatus(Res, FALSE, 0LU, 0LU, 0LU); ok_eq_int(Res->ActiveCount, 2); FinishThread(&ThreadDataShared2); CheckResourceStatus(Res, FALSE, 0LU, 0LU, 0LU); ok_eq_int(Res->ActiveCount, 1); /* now have a thread that tries to acquire the resource exclusive -- it should fail */ Status = StartThread(&ThreadDataExclusive, NULL, FALSE, FALSE); ok_eq_hex(Status, STATUS_SUCCESS); CheckResourceStatus(Res, FALSE, 0LU, 0LU, 0LU); ok_eq_int(Res->ActiveCount, 1); FinishThread(&ThreadDataExclusive); CheckResourceStatus(Res, FALSE, 0LU, 0LU, 0LU); ok_eq_int(Res->ActiveCount, 1); /* as above, but this time it should block */ Status = StartThread(&ThreadDataExclusive, &Timeout, TRUE, TRUE); ok_eq_hex(Status, STATUS_TIMEOUT); CheckResourceStatus(Res, FALSE, 0LU, 1LU, 0LU); ok_eq_int(Res->ActiveCount, 1); /* now try another shared one -- it should fail */ Status = StartThread(&ThreadDataShared2, NULL, FALSE, FALSE); ok_eq_hex(Status, STATUS_SUCCESS); CheckResourceStatus(Res, FALSE, 0LU, 1LU, 0LU); ok_eq_int(Res->ActiveCount, 1); FinishThread(&ThreadDataShared2); /* same for ExAcquireSharedWaitForExclusive */ Status = StartThread(&ThreadDataSharedWait, NULL, FALSE, FALSE); ok_eq_hex(Status, STATUS_SUCCESS); CheckResourceStatus(Res, FALSE, 0LU, 1LU, 0LU); ok_eq_int(Res->ActiveCount, 1); FinishThread(&ThreadDataSharedWait); /* ExAcquireSharedStarveExclusive must get access though! */ Status = StartThread(&ThreadDataSharedStarve, NULL, TRUE, TRUE); ok_eq_hex(Status, STATUS_SUCCESS); CheckResourceStatus(Res, FALSE, 0LU, 1LU, 0LU); ok_eq_int(Res->ActiveCount, 2); FinishThread(&ThreadDataSharedStarve); CheckResourceStatus(Res, FALSE, 0LU, 1LU, 0LU); ok_eq_int(Res->ActiveCount, 1); /* block another shared one */ Status = StartThread(&ThreadDataShared2, &Timeout, TRUE, TRUE); ok_eq_hex(Status, STATUS_TIMEOUT); CheckResourceStatus(Res, FALSE, 0LU, 1LU, 1LU); ok_eq_int(Res->ActiveCount, 1); /* finish the very first one */ FinishThread(&ThreadDataShared); /* now the blocked exclusive one should get the resource */ Status = KeWaitForSingleObject(&ThreadDataExclusive.OutEvent, Executive, KernelMode, FALSE, NULL); ok_eq_hex(Status, STATUS_SUCCESS); CheckResourceStatus(Res, FALSE, 0LU, 0LU, 1LU); ok_eq_int(Res->ActiveCount, 1); ok_eq_uint((Res->Flag & ResourceOwnedExclusive) != 0, 1); FinishThread(&ThreadDataExclusive); CheckResourceStatus(Res, FALSE, 0LU, 0LU, 0LU); /* now the blocked shared one should resume */ Status = KeWaitForSingleObject(&ThreadDataShared2.OutEvent, Executive, KernelMode, FALSE, NULL); ok_eq_hex(Status, STATUS_SUCCESS); CheckResourceStatus(Res, FALSE, 0LU, 0LU, 0LU); ok_eq_int(Res->ActiveCount, 1); FinishThread(&ThreadDataShared2); CheckResourceStatus(Res, FALSE, 0LU, 0LU, 0LU); ok_eq_int(Res->ActiveCount, 0); }
static VOID TestFastMutexConcurrent( PFAST_MUTEX Mutex) { NTSTATUS Status; THREAD_DATA ThreadData; THREAD_DATA ThreadData2; THREAD_DATA ThreadDataUnsafe; THREAD_DATA ThreadDataTry; LARGE_INTEGER Timeout; Timeout.QuadPart = -10 * 1000 * 10; /* 10 ms */ InitThreadData(&ThreadData, Mutex, ExAcquireFastMutex, NULL, ExReleaseFastMutex); InitThreadData(&ThreadData2, Mutex, ExAcquireFastMutex, NULL, ExReleaseFastMutex); InitThreadData(&ThreadDataUnsafe, Mutex, ExAcquireFastMutexUnsafe, NULL, ExReleaseFastMutexUnsafe); InitThreadData(&ThreadDataTry, Mutex, NULL, ExTryToAcquireFastMutex, ExReleaseFastMutex); /* have a thread acquire the mutex */ Status = StartThread(&ThreadData, NULL, PASSIVE_LEVEL, FALSE, FALSE); ok_eq_hex(Status, STATUS_SUCCESS); CheckMutex(Mutex, 0L, ThreadData.Thread, 0LU, PASSIVE_LEVEL, PASSIVE_LEVEL); /* have a second thread try to acquire it -- should fail */ Status = StartThread(&ThreadDataTry, NULL, PASSIVE_LEVEL, TRUE, FALSE); ok_eq_hex(Status, STATUS_SUCCESS); CheckMutex(Mutex, 0L, ThreadData.Thread, 0LU, PASSIVE_LEVEL, PASSIVE_LEVEL); FinishThread(&ThreadDataTry); /* have another thread acquire it -- should block */ Status = StartThread(&ThreadData2, &Timeout, APC_LEVEL, FALSE, FALSE); ok_eq_hex(Status, STATUS_TIMEOUT); CheckMutex(Mutex, -1L, ThreadData.Thread, 1LU, PASSIVE_LEVEL, PASSIVE_LEVEL); /* finish the first thread -- now the second should become available */ FinishThread(&ThreadData); Status = KeWaitForSingleObject(&ThreadData2.OutEvent, Executive, KernelMode, FALSE, NULL); ok_eq_hex(Status, STATUS_SUCCESS); CheckMutex(Mutex, 0L, ThreadData2.Thread, 1LU, APC_LEVEL, PASSIVE_LEVEL); /* block two more threads */ Status = StartThread(&ThreadDataUnsafe, &Timeout, APC_LEVEL, FALSE, FALSE); ok_eq_hex(Status, STATUS_TIMEOUT); CheckMutex(Mutex, -1L, ThreadData2.Thread, 2LU, APC_LEVEL, PASSIVE_LEVEL); Status = StartThread(&ThreadData, &Timeout, PASSIVE_LEVEL, FALSE, FALSE); ok_eq_hex(Status, STATUS_TIMEOUT); CheckMutex(Mutex, -2L, ThreadData2.Thread, 3LU, APC_LEVEL, PASSIVE_LEVEL); /* finish 1 */ FinishThread(&ThreadData2); Status = KeWaitForSingleObject(&ThreadDataUnsafe.OutEvent, Executive, KernelMode, FALSE, NULL); ok_eq_hex(Status, STATUS_SUCCESS); CheckMutex(Mutex, -1L, ThreadDataUnsafe.Thread, 3LU, APC_LEVEL, PASSIVE_LEVEL); /* finish 2 */ FinishThread(&ThreadDataUnsafe); Status = KeWaitForSingleObject(&ThreadData.OutEvent, Executive, KernelMode, FALSE, NULL); ok_eq_hex(Status, STATUS_SUCCESS); CheckMutex(Mutex, 0L, ThreadData.Thread, 3LU, PASSIVE_LEVEL, PASSIVE_LEVEL); /* finish 3 */ FinishThread(&ThreadData); CheckMutex(Mutex, 1L, NULL, 3LU, PASSIVE_LEVEL, PASSIVE_LEVEL); }