#include <stdio.h>
#include <windows.h>
#include "Spin.h"
//#define TEST_QUEUED_SPINLOCKS
#ifndef TEST_QUEUED_SPINLOCKS
#define SPIN
#endif
#ifdef SPIN
#define ACQUIREQUEUEDSPINLOCK(x) AcquireSpinLock(x)
#define RELEASEQUEUEDSPINLOCK(x)
ReleaseSpinLock(x)
#else
#define ACQUIREQUEUEDSPINLOCK(x)
AcquireQueuedSpinLock(x)
#define
RELEASEQUEUEDSPINLOCK(x) ReleaseQueuedSpinLock(x)
#endif
DECLSPEC_CACHEALIGN SPIN_LOCK SpinLock;
SPIN_LOCK_QUEUE SpinLockQueue, SpinLockQueue_Thread;
typedef struct _THREAD_PARAM
{
UINT Cpu;
SPIN_LOCK_QUEUE
SpinLockQueue;
} THREAD_PARAM, *PTHREAD_PARAM;
#define MAX_CPU 8
PTHREAD_PARAM pThreadParamTable;
PHANDLE pThreads;
PUINT pHashTable;
HANDLE CloseEvent;
VOID
GetHashTable(PUINT Table, UINT Size);
DWORD WINAPI
ThreadStartAddress(LPVOID param)
{
/* We will save
ThreadParam on stack */
THREAD_PARAM
ThreadParam;
PTHREAD_PARAM
pThreadParam = (PTHREAD_PARAM)
&ThreadParam;
memcpy(pThreadParam, param,
sizeof(THREAD_PARAM));
pThreadParam->SpinLockQueue.Lock
= &SpinLock;
pThreadParam->SpinLockQueue.Next
= NULL;
#ifdef SPIN
printf("\t\t\tCPU[%d] - AcquireSpinLock\n", pThreadParam->Cpu);
ACQUIREQUEUEDSPINLOCK(&SpinLock);
printf("\t\t\tCPU[%d] - AcquireSpinLock ->
Acquired.\n", pThreadParam->Cpu);
#else
printf("\t\t\tCPU[%d] -
AcquireQueuedSpinLock\n", pThreadParam->Cpu);
ACQUIREQUEUEDSPINLOCK(&pThreadParam->SpinLockQueue);
printf("\t\t\tCPU[%d] -
AcquireQueueSpinLock -> Acquired.\n", pThreadParam->Cpu);
#endif
printf("\t\t\tCPU[%d] - Waiting for CloseEvent\n",
pThreadParam->Cpu);
WaitForSingleObject(CloseEvent, INFINITE);
printf("\t\t\tCPU[%d] - Received CloseEvent\n", pThreadParam->Cpu);
#ifdef SPIN
printf("\t\t\tCPU[%d] - ReleaseSpinLock\n", pThreadParam->Cpu);
RELEASEQUEUEDSPINLOCK(&SpinLock);
printf("\t\t\tCPU[%d] - ReleaseSpinLock ->
Released.\n\n", pThreadParam->Cpu);
#else
printf("\t\t\tCPU[%d] -
ReleaseQueuedSpinLock\n", pThreadParam->Cpu);
RELEASEQUEUEDSPINLOCK(&pThreadParam->SpinLockQueue);
printf("\t\t\tCPU[%d] -
ReleaseQueuedSpinLock -> Released.\n\n", pThreadParam->Cpu);
#endif
return 0;
}
int
main(int argc,
char *argv[])
{
int ch;
UINT i=0;
UINT CpuNo = MAX_CPU;
SpinLockQueue.Next = NULL;
SpinLockQueue.Lock = &SpinLock;
if(argc > 1)
{
CpuNo = atoi(argv[1]);
if(CpuNo == 0)
{
printf("atoi(%s) problems - using standard value.\n",
argv[1]);
CpuNo = MAX_CPU;
}
}
printf("<==== Simulate %d CPUs =====>\n", CpuNo);
pThreadParamTable
= (PTHREAD_PARAM) malloc(CpuNo * sizeof(THREAD_PARAM));
if(pThreadParamTable == NULL)
{
printf("malloc(pThreadParamTable) error\n");
return 1;
}
pThreads = (PHANDLE) malloc(CpuNo * sizeof(HANDLE));
if(pThreads == NULL)
{
printf("malloc(pThreads) error\n");
free(pThreadParamTable);
return 2;
}
pHashTable =
(PUINT) malloc(CpuNo * sizeof(UINT));
if(pHashTable == NULL)
{
printf("malloc(pHashTable) error\n");
free(pThreadParamTable);
free(pThreads);
return 3;
}
GetHashTable(pHashTable, CpuNo);
for(i=0; i<CpuNo; i++)
{
pThreads[i]=INVALID_HANDLE_VALUE;
}
CloseEvent =
CreateEvent(NULL,
TRUE, FALSE, NULL);
for(i=0; i<CpuNo; i++)
{
pThreadParamTable[i].Cpu = i;
pThreads[i]= CreateThread(NULL, 0, ThreadStartAddress,
&pThreadParamTable[i], CREATE_SUSPENDED, NULL);
if(INVALID_HANDLE_VALUE == pThreads[i])
{
printf("CreateThread(%i) error: 0x%X\n", i, GetLastError());
}
else
{
if(!SetThreadPriority(pThreads[i], THREAD_PRIORITY_IDLE))
{
printf("SetThreadPriority(%d) error: 0x%X\n", i, GetLastError());
}
}
}
#ifdef SPIN
printf("AcquireSpinLock - Main\n");
ACQUIREQUEUEDSPINLOCK(&SpinLock);
printf("AcquireSpinLock -
#else
printf("AcquireQueuedSpinLock -
Main\n");
ACQUIREQUEUEDSPINLOCK(&SpinLockQueue);
printf("AcquireQueuedSpinLock -
#endif
for(i=0; i<CpuNo; i++)
{
/* Random Threads
resume */
ResumeThread(pThreads[pHashTable[i]]);
Sleep(200);
}
printf("\nx == exit \n");
while( (ch=getchar()) != 'x')
{
;
}
printf("\nGet x
-> exit\n");
#ifdef SPIN
printf("ReleaseSpinLock - Main\n");
RELEASEQUEUEDSPINLOCK(&SpinLock);
printf("ReleaseSpinLock -
#else
printf("ReleaseQueuedSpinLock -
Main\n");
RELEASEQUEUEDSPINLOCK(&SpinLockQueue);
printf("ReleaseQueuedSpinLock -
#endif
SetEvent(CloseEvent);
printf("Waiting for Threads\n");
WaitForMultipleObjects(CpuNo, pThreads, TRUE, INFINITE);
printf("END\n");
CloseHandle(CloseEvent);
if(pThreads)
free(pThreads);
if(pThreadParamTable)
free(pThreadParamTable);
if(pHashTable)
free(pHashTable);
getchar();
getchar();
return 0;
}