Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

412 lines
8.8 KiB

#pragma include_alias("clist.h", "..\newjob\clist.h")
#include "qmgrlib.h"
#include "locks.hxx"
#include "..\newjob\csd.h"
#include "..\newjob\tasksched.h"
//
// Following items are needed to link properly.
//
HINSTANCE g_hInstance;
SERVICE_STATUS_HANDLE ghServiceHandle;
unsigned long g_LastServiceControl;
bool IsServiceShuttingDown()
{
return false;
}
long SetServiceStartup( bool ignore )
{
return 0;
}
int InitializeBitsAllocator()
{
return 0;
}
SidHandle
BITSAllocateAndInitializeSid(
BYTE nSubAuthorityCount, // count of subauthorities
DWORD dwSubAuthority0, // subauthority 0
DWORD dwSubAuthority1 ); // subauthority 1
//
// Preceding items are needed to link properly.
//
#define MAX_QUEUED_WORK_ITEMS 30
SidHandle g_NetworkUsersSid;
long g_ThreadCount;
long g_CancelCount;
HANDLE * g_hThreads;
HANDLE g_hWorkItemCreationThread;
TaskScheduler * g_Lock;
class TestWorkItem : public TaskSchedulerWorkItem
{
public:
TestWorkItem( long index )
{
m_index = index;
}
virtual SidHandle GetSid() {
return g_NetworkUsersSid;
}
virtual void OnDispatch();
long m_index;
};
bool TakeAndReleaseLock( bool fWrite, long Delay, bool fComplete );
struct
{
TestWorkItem * item;
long complete;
long cancelled;
}
g_PendingWorkItems[ MAX_QUEUED_WORK_ITEMS ];
//------------------------------------------------------------------------
void TestWorkItem::OnDispatch()
{
static int i;
bool fWrite;
if ((i % 7) == 0)
{
fWrite = true;
}
else
{
fWrite = false;
}
long Delay = -1;
long SleepChoice = (i % 10);
if (SleepChoice == 0)
{
// printf("Sleep 10\n");
Delay = 10;
}
else if (SleepChoice == 5)
{
// printf("Sleep 0\n");
Delay = 0;
}
bool fCancel;
if ((i % 3) == 1)
{
fCancel = true;
}
else
{
fCancel = false;
}
long PreLockSleep = (i % 5);
if (PreLockSleep < 3)
{
Sleep(10);
}
if (!TakeAndReleaseLock( fWrite, Delay, fCancel))
{
//
// The work-item was cancelled.
//
g_Lock->AcknowledgeWorkItemCancel();
InterlockedIncrement( &g_CancelCount );
}
else if (!fCancel)
{
g_Lock->CompleteWorkItem();
}
//
// Mark the item complete.
//
if (m_index >= 0)
{
if (g_PendingWorkItems[m_index].item != this)
{
printf("error: index mismatch\n");
exit(1);
}
// printf("completing item %p index %d\n", this, m_index);
g_PendingWorkItems[m_index].complete = 1;
}
//
// if ((i % 100000) == 0)
{
// printf("%d work items\n", i);
}
// if ((i % 1000) == 0)
{
// putchar('W');
}
++i;
}
bool TakeAndReleaseLock( bool fWrite, long Delay, bool fComplete )
{
if (fWrite)
{
// printf("lock writer\n");
if (g_Lock->LockWriter())
{
// cancelled
return false;
}
}
else
{
// printf("lock reader\n");
if (g_Lock->LockReader())
{
// cancelled
return false;
}
}
if (Delay != -1)
{
Sleep(Delay);
}
if (fComplete)
{
g_Lock->CompleteWorkItem();
}
if (fWrite)
{
// printf("unlock writer\n");
g_Lock->UnlockWriter();
}
else
{
// printf("unlock reader\n");
g_Lock->UnlockReader();
}
return true;
}
DWORD WINAPI ThreadProc( LPVOID arg )
{
long index = long(arg);
long i =0;
do
{
bool fWrite;
if ((i % 9) == index)
{
fWrite = true;
}
else
{
fWrite = false;
}
long Delay = -1;
long SleepChoice = (i % 10);
if (SleepChoice == 0)
{
// printf("Sleep 10\n");
Delay = 10;
}
else if (SleepChoice == 5)
{
// printf("Sleep 0\n");
Delay = 0;
}
if (!TakeAndReleaseLock( fWrite, Delay, false ))
{
printf("thread %d: cancel detected!", DWORD(arg));
exit(1);
}
if ((i % 100000) == 0)
{
printf("thread %d: %d iterations\n", DWORD(arg), i);
}
if ((i % 1000) == 0)
{
putchar('0'+DWORD(arg));
}
++i;
}
while ( 1 );
}
DWORD WINAPI WorkItemCreatorProc( LPVOID arg )
{
int i = 0;
for (;;)
{
int index;
if ((i % 1000) == 0)
{
putchar('w');
}
//
// Clean out completed work items
//
for (index = 0; index < RTL_NUMBER_OF( g_PendingWorkItems ); ++index)
{
if (g_PendingWorkItems[index].complete)
{
// printf("clearing index %d\n", index);
delete g_PendingWorkItems[index].item;
g_PendingWorkItems[index].item = 0;
g_PendingWorkItems[index].complete = 0;
g_PendingWorkItems[index].cancelled = 0;
}
}
//
// Fill up the queue.
//
do
{
// find a spot
for (index = 0; index < RTL_NUMBER_OF( g_PendingWorkItems ); ++index)
{
if (g_PendingWorkItems[index].item == 0)
{
break;
}
}
//
// A slot is available; create a new workitem for it.
//
if (index < RTL_NUMBER_OF( g_PendingWorkItems ))
{
TestWorkItem * item = new TestWorkItem( index );
g_PendingWorkItems[index].item = item;
g_Lock->InsertWorkItem( item, NULL );
}
}
while ( index < RTL_NUMBER_OF( g_PendingWorkItems ) );
//
// let them drain away
//
do
{
for (index = RTL_NUMBER_OF( g_PendingWorkItems )-1; index >=0; --index)
{
if (g_PendingWorkItems[index].item != 0 &&
g_PendingWorkItems[index].complete == 0 &&
g_PendingWorkItems[index].cancelled == 0)
{
g_Lock->CancelWorkItem( g_PendingWorkItems[index].item );
g_PendingWorkItems[index].cancelled = 1;
break;
}
}
Sleep(1);
}
while ( index >= 0 );
++i;
}
}
void __cdecl wmain (int argc, wchar_t *argv[])
{
if (argc < 2)
{
printf("arg1 should be a thread count\n");
return;
}
g_ThreadCount = _wtol( argv[1] );
g_hThreads = new HANDLE[ g_ThreadCount ];
if (!InitCompilerLibrary())
{
printf("init STL failed");
return;
}
if ( !DetectProductVersion() )
{
printf("version detect failed");
return;
}
if (0 != InitializeBitsAllocator())
{
printf("allocator init failed");
return;
}
Log_Init();
Log_StartLogger();
g_NetworkUsersSid = BITSAllocateAndInitializeSid( 1, SECURITY_NETWORK_RID, 0);
g_Lock = new TaskScheduler;
for (int index = 0; index < RTL_NUMBER_OF( g_PendingWorkItems ); ++index)
{
g_PendingWorkItems[index].item = 0;
g_PendingWorkItems[index].complete = 0;
g_PendingWorkItems[index].cancelled = 0;
}
DWORD id;
for (int i=0; i < g_ThreadCount; ++i)
{
g_hThreads[i] = CreateThread( NULL, 0, ThreadProc, LPVOID(i), 0, &id );
if (0 == g_hThreads[i])
{
printf("error %d creating thread\n", GetLastError());
}
}
g_hWorkItemCreationThread = CreateThread( NULL, 0, WorkItemCreatorProc, 0, 0, &id );
if (0 == g_hWorkItemCreationThread)
{
printf("error %d creating thread\n", GetLastError());
}
Sleep( 1000 * 1000 );
}