PTHREADDATA GetThreadData(void) { PTHREADDATA ThreadData; DWORD LastError; LastError = GetLastError(); ThreadData = TlsGetValue(TlsIndex); if (ThreadData == NULL) { ThreadData = (PTHREADDATA)calloc(1, sizeof(THREADDATA)); if (ThreadData != NULL) { TlsSetValue(TlsIndex, (LPVOID)ThreadData); InitThreadData(ThreadData); } else { _amsg_exit(_RT_THREAD); /* write message and die */ } } SetLastError(LastError); return ThreadData; }
void WINAPI _export ShowInfoMenu(void) { FarDialogItem DialogItems[1]; memset(DialogItems,0,sizeof(DialogItems)); DialogItems[0].Type=DI_LISTBOX; DialogItems[0].Flags=DIF_LISTWRAPMODE; ThreadData Thread={FALSE,NULL,NULL,NULL,PlgOpt.RefreshInterval}; InitThreadData(&Thread); InfoMenuData params={{&Thread,0,{-1,-1},{L"",L""},INVALID_HANDLE_VALUE,false,InfoMenuDialogKeyProc,MACRO_INFO_MENU,true,false},0,NULL,true,true}; CFarDialog dialog; dialog.Execute(Info.ModuleNumber,-1,-1,0,0,_T("InfoMenu"),DialogItems,sizeofa(DialogItems),0,0,InfoMenuProc,(LONG_PTR)¶ms); FreeThreadData(&Thread); free(params.id); }
int CreateThreadData(void) { PTHREADDATA ThreadData; TlsIndex = TlsAlloc(); if (TlsIndex == (unsigned long)-1) return FALSE; ThreadData = (PTHREADDATA)calloc(1, sizeof(THREADDATA)); if (ThreadData == NULL) return FALSE; if(!TlsSetValue(TlsIndex, (LPVOID)ThreadData)) return FALSE; InitThreadData(ThreadData); return TRUE; }
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); }