mirror of
https://github.com/decompals/wibo.git
synced 2025-12-12 14:46:09 +00:00
Support TlsExpansionSlots (>64 TLS slots)
This commit is contained in:
@@ -16,7 +16,9 @@ static void **tls_slots(void) {
|
||||
|
||||
typedef struct {
|
||||
DWORD tlsIndex;
|
||||
DWORD tlsExpansionIndex;
|
||||
int threadValue;
|
||||
int expansionValue;
|
||||
HANDLE readyEvent;
|
||||
HANDLE continueEvent;
|
||||
} ThreadCtx;
|
||||
@@ -34,12 +36,23 @@ static DWORD WINAPI tls_thread_proc(LPVOID param) {
|
||||
TEST_CHECK_EQ(threadPtr, TlsGetValue(ctx->tlsIndex));
|
||||
TEST_CHECK_EQ(threadPtr, tls_slots()[ctx->tlsIndex]);
|
||||
|
||||
if (ctx->tlsExpansionIndex != TLS_OUT_OF_INDEXES) {
|
||||
DWORD expansionIndex = ctx->tlsExpansionIndex;
|
||||
TEST_CHECK(expansionIndex >= TLS_MINIMUM_AVAILABLE);
|
||||
void *expansionPtr = &ctx->expansionValue;
|
||||
TEST_CHECK(TlsSetValue(expansionIndex, expansionPtr));
|
||||
TEST_CHECK_EQ(expansionPtr, TlsGetValue(expansionIndex));
|
||||
}
|
||||
|
||||
TEST_CHECK(SetEvent(ctx->readyEvent));
|
||||
|
||||
TEST_CHECK_EQ(WAIT_OBJECT_0, WaitForSingleObject(ctx->continueEvent, 1000));
|
||||
|
||||
/* Clear before exit */
|
||||
TEST_CHECK(TlsSetValue(ctx->tlsIndex, NULL));
|
||||
if (ctx->tlsExpansionIndex != TLS_OUT_OF_INDEXES) {
|
||||
TEST_CHECK(TlsSetValue(ctx->tlsExpansionIndex, NULL));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -58,9 +71,11 @@ int main(void) {
|
||||
TEST_CHECK_EQ(mainPtr, TlsGetValue(tlsIndex));
|
||||
TEST_CHECK_EQ(mainPtr, tlsArray[tlsIndex]);
|
||||
|
||||
ThreadCtx ctx;
|
||||
ThreadCtx ctx = {0};
|
||||
ctx.tlsIndex = tlsIndex;
|
||||
ctx.tlsExpansionIndex = TLS_OUT_OF_INDEXES;
|
||||
ctx.threadValue = 0x4242;
|
||||
ctx.expansionValue = 0;
|
||||
ctx.readyEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
|
||||
ctx.continueEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
|
||||
TEST_CHECK(ctx.readyEvent != NULL);
|
||||
@@ -76,20 +91,82 @@ int main(void) {
|
||||
TEST_CHECK_EQ(mainPtr, tlsArray[tlsIndex]);
|
||||
|
||||
TEST_CHECK(SetEvent(ctx.continueEvent));
|
||||
|
||||
TEST_CHECK_EQ(WAIT_OBJECT_0, WaitForSingleObject(thread, 1000));
|
||||
TEST_CHECK(CloseHandle(thread));
|
||||
|
||||
TEST_CHECK(CloseHandle(ctx.readyEvent));
|
||||
TEST_CHECK(CloseHandle(ctx.continueEvent));
|
||||
|
||||
/* Ensure worker cleanup didn't disturb main thread */
|
||||
tlsArray = tls_slots();
|
||||
TEST_CHECK_EQ(mainPtr, TlsGetValue(tlsIndex));
|
||||
TEST_CHECK_EQ(mainPtr, tlsArray[tlsIndex]);
|
||||
|
||||
/* Allocate additional slots to cross the TLS_MINIMUM_AVAILABLE boundary */
|
||||
const size_t extraCount = 80;
|
||||
DWORD extraSlots[extraCount];
|
||||
size_t extraUsed = 0;
|
||||
DWORD expansionIndex = TLS_OUT_OF_INDEXES;
|
||||
|
||||
for (; extraUsed < extraCount; ++extraUsed) {
|
||||
DWORD index = TlsAlloc();
|
||||
TEST_CHECK(index != TLS_OUT_OF_INDEXES);
|
||||
extraSlots[extraUsed] = index;
|
||||
if (index >= TLS_MINIMUM_AVAILABLE) {
|
||||
expansionIndex = index;
|
||||
++extraUsed;
|
||||
break;
|
||||
}
|
||||
}
|
||||
TEST_CHECK(expansionIndex != TLS_OUT_OF_INDEXES);
|
||||
|
||||
tlsArray = tls_slots();
|
||||
|
||||
int mainExpansionValue = 0x5678;
|
||||
void *mainExpansionPtr = &mainExpansionValue;
|
||||
TEST_CHECK(TlsSetValue(expansionIndex, mainExpansionPtr));
|
||||
TEST_CHECK_EQ(mainExpansionPtr, TlsGetValue(expansionIndex));
|
||||
|
||||
ThreadCtx expansionCtx = {0};
|
||||
expansionCtx.tlsIndex = tlsIndex;
|
||||
expansionCtx.tlsExpansionIndex = expansionIndex;
|
||||
expansionCtx.threadValue = 0x3535;
|
||||
expansionCtx.expansionValue = 0x2626;
|
||||
expansionCtx.readyEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
|
||||
expansionCtx.continueEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
|
||||
TEST_CHECK(expansionCtx.readyEvent != NULL);
|
||||
TEST_CHECK(expansionCtx.continueEvent != NULL);
|
||||
|
||||
thread = CreateThread(NULL, 0, tls_thread_proc, &expansionCtx, 0, NULL);
|
||||
TEST_CHECK(thread != NULL);
|
||||
TEST_CHECK_EQ(WAIT_OBJECT_0, WaitForSingleObject(expansionCtx.readyEvent, 1000));
|
||||
|
||||
tlsArray = tls_slots();
|
||||
TEST_CHECK_EQ(mainPtr, TlsGetValue(tlsIndex));
|
||||
TEST_CHECK_EQ(mainPtr, tlsArray[tlsIndex]);
|
||||
TEST_CHECK_EQ(mainExpansionPtr, TlsGetValue(expansionIndex));
|
||||
|
||||
TEST_CHECK(SetEvent(expansionCtx.continueEvent));
|
||||
TEST_CHECK_EQ(WAIT_OBJECT_0, WaitForSingleObject(thread, 1000));
|
||||
TEST_CHECK(CloseHandle(thread));
|
||||
TEST_CHECK(CloseHandle(expansionCtx.readyEvent));
|
||||
TEST_CHECK(CloseHandle(expansionCtx.continueEvent));
|
||||
|
||||
/* Ensure worker cleanup didn't disturb main thread values */
|
||||
tlsArray = tls_slots();
|
||||
TEST_CHECK_EQ(mainPtr, TlsGetValue(tlsIndex));
|
||||
TEST_CHECK_EQ(mainPtr, tlsArray[tlsIndex]);
|
||||
TEST_CHECK_EQ(mainExpansionPtr, TlsGetValue(expansionIndex));
|
||||
|
||||
/* Clear and free all slots */
|
||||
TEST_CHECK(TlsSetValue(tlsIndex, NULL));
|
||||
TEST_CHECK_EQ(NULL, TlsGetValue(tlsIndex));
|
||||
TEST_CHECK(TlsSetValue(expansionIndex, NULL));
|
||||
|
||||
for (size_t i = 0; i < extraUsed; ++i) {
|
||||
TEST_CHECK(TlsFree(extraSlots[i]));
|
||||
}
|
||||
TEST_CHECK(TlsFree(tlsIndex));
|
||||
|
||||
tlsArray = tls_slots();
|
||||
TEST_CHECK_EQ(NULL, tlsArray[tlsIndex]);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
Reference in New Issue
Block a user