Skip to content

Instantly share code, notes, and snippets.

@0ffffffffh
Created November 17, 2015 23:46
Show Gist options
  • Save 0ffffffffh/cf93ed82d86dffe8ddb8 to your computer and use it in GitHub Desktop.
Save 0ffffffffh/cf93ed82d86dffe8ddb8 to your computer and use it in GitHub Desktop.
Race condition test program
//Race condition demo program.
//Written by Oguz Kartal
//Date: 11/17/2015 7:21 PM
#include <Windows.h>
#include <stdio.h>
#define NVA(i) ( (i+1) >= argc ) ? "" : argv[i+1]
#define ONOFFSTR(b) b ? "on" : "off"
#define TRY_FAIL_OPT_ARG(cmp, opt) if (cmp) { printf("Expected option argument for %s",opt); return 1; }
LONG sharedValue = 0;
typedef struct _workerInfo
{
DWORD iteration;
LONG *pShared;
}workerInfo;
DWORD WINAPI workerMethod(void *p)
{
workerInfo *pWi = (workerInfo *)p;
LONG *pVal = pWi->pShared;
DWORD iteration = pWi->iteration;
while (iteration-- > 0)
{
(*pVal)++;
(*pVal)--;
}
return 0;
}
void startWorkers(DWORD id,DWORD workerCount, DWORD iterationPerWorker, BOOL simulateUniprocessor, BOOL coreAffinity)
{
DWORD processorCount,affMask, processorId=0, dummy;
workerInfo wi;
SYSTEM_INFO sysInfo;
HANDLE *threads = NULL;
GetSystemInfo(&sysInfo);
processorCount = simulateUniprocessor ? 1 : sysInfo.dwNumberOfProcessors;
if (simulateUniprocessor && !coreAffinity)
coreAffinity = TRUE;
threads = (HANDLE *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(HANDLE) * workerCount);
wi.iteration = iterationPerWorker;
wi.pShared = &sharedValue;
if (!threads)
{
printf("handle list could not allocated!\n");
return;
}
sharedValue = 0;
printf("\n=== Test#%d is staring ===\n", id);
for (int i = 0; i < workerCount;i++)
{
threads[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)workerMethod, &wi, 0, &dummy);
if (coreAffinity)
{
affMask = 1 << processorId;
if (processorId == processorCount - 1)
processorId = 0;
else
processorId++;
SetThreadAffinityMask(threads[i], affMask);
}
}
WaitForMultipleObjects(workerCount, (const HANDLE *)threads, TRUE, INFINITE);
for (int i = 0; i < workerCount; i++)
CloseHandle(threads[i]);
HeapFree(GetProcessHeap(), 0, threads);
printf("=== Test#%d finished. Expected Value: 0, Actual sharedValue : %d ===\n\n\n",id, sharedValue);
}
void pnOpt(const char *opt, const char *desc)
{
printf("\t%s: %s\n", opt, desc);
}
void printHelp()
{
printf("Race condition test program. Written by Oguz Kartal (Nov. 2015)\n");
printf("usage: rcDemo [options]\n");
printf("[options]\n");
pnOpt("-w [N]","Create N concurrent worker thread(s)");
pnOpt("-i [N]", "N iteration(s) per worker");
pnOpt("-su", "Simulate uniprocessor");
pnOpt("-wa", "Distribute worker threads fairly between each core (-su option overrides this)");
pnOpt("-tc [N]", "Repeat the test N times");
}
int main(int argc, char **argv)
{
int workerCount, iterCount, testCount = 1;
BOOL simUni = FALSE, setAff = FALSE;
int i;
if (argc < 2)
{
printf("Missing paramters\n\n");
printHelp();
return 1;
}
for (i = 1; i < argc; i++)
{
if (!stricmp(argv[i], "-w"))
{
workerCount = atoi(NVA(i));
TRY_FAIL_OPT_ARG(workerCount <= 0, "-w");
i++;
}
else if (!stricmp(argv[i], "-i"))
{
iterCount = atoi(NVA(i));
TRY_FAIL_OPT_ARG(iterCount <= 0, "-i");
i++;
}
else if (!stricmp(argv[i], "-tc"))
{
testCount = atoi(NVA(i));
TRY_FAIL_OPT_ARG(testCount <= 0, "-tc");
i++;
}
else if (!stricmp(argv[i], "-su"))
simUni = TRUE;
else if (!stricmp(argv[i], "-wa"))
setAff = TRUE;
}
printf("Test will be running using %d Worker Threads with %d iteration per worker.\n", workerCount, iterCount);
printf("Uniprocessor simulation is %s, and Worker distribution is %s\n\n", ONOFFSTR(simUni), ONOFFSTR(setAff));
for (i = 0; i < testCount; i++)
{
startWorkers(i+1, workerCount, iterCount, simUni, setAff);
}
printf("All done");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment