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.
 
 
 
 
 
 

482 lines
12 KiB

//*************************************************************
//
// File name: TSrvWork.c
//
// Description: Contains routines to support TShareSRV
// work queue interaction
//
// Microsoft Confidential
// Copyright (c) Microsoft Corporation 1991-1997
// All rights reserved
//
//*************************************************************
#include <TSrv.h>
#include <TSrvInfo.h>
#include <TSrvWork.h>
#include <_TSrvWork.h>
// Data declarations
WORKQUEUE g_MainWorkQueue;
//*************************************************************
//
// TSrvInitWorkQueue()
//
// Purpose: Initializes the given work queue
//
// Parameters: IN [pWorkQueue] -- Work queue
//
// Return: TRUE if successful
// FALSE if not
//
// History: 07-17-97 BrianTa Created
//
//*************************************************************
BOOL
TSrvInitWorkQueue(IN PWORKQUEUE pWorkQueue)
{
BOOL fSuccess;
TRACE((DEBUG_TSHRSRV_FLOW,
"TShrSRV: TSrvInitWorkQueue entry\n"));
fSuccess = TRUE;
if (pWorkQueue == NULL)
pWorkQueue = &g_MainWorkQueue;
pWorkQueue->pHead = NULL;
pWorkQueue->pTail = NULL;
if (RtlInitializeCriticalSection(&pWorkQueue->cs) == STATUS_SUCCESS) {
// Create a worker event to be used to signal that
// a new work item has been placed in the queue
pWorkQueue->hWorkEvent = CreateEvent(NULL, // security attributes
FALSE, // manual-reset event
FALSE, // initial state
NULL); // pointer to event-object name
if (pWorkQueue->hWorkEvent == NULL)
{
TRACE((DEBUG_TSHRSRV_WARN,
"TShrSRV: Can't allocate hWorkEvent - 0x%x\n",
GetLastError()));
fSuccess = FALSE;
}
}
else {
TRACE((DEBUG_TSHRSRV_WARN,
"TShrSRV: Can't initialize pWorkQueue->cs\n"));
fSuccess = FALSE;
}
TRACE((DEBUG_TSHRSRV_FLOW,
"TShrSRV: TSrvInitWorkQueue exit - 0x%x\n", fSuccess));
return (fSuccess);
}
//*************************************************************
//
// TSrvFreeWorkQueue()
//
// Purpose: Frees the given work queue
//
// Parameters: IN [pWorkQueue] -- Work queue
//
// Return: void
//
// History: 07-17-97 BrianTa Created
//
//*************************************************************
void
TSrvFreeWorkQueue(IN PWORKQUEUE pWorkQueue)
{
TRACE((DEBUG_TSHRSRV_FLOW,
"TShrSRV: TSrvFreeWorkQueue entry\n"));
if (pWorkQueue == NULL)
pWorkQueue = &g_MainWorkQueue;
EnterCriticalSection(&pWorkQueue->cs);
// We should not have any work items in the queue
TS_ASSERT(pWorkQueue->pHead == NULL);
// Release the worker event
if (pWorkQueue->hWorkEvent)
{
CloseHandle(pWorkQueue->hWorkEvent);
pWorkQueue->hWorkEvent = NULL;
}
LeaveCriticalSection(&pWorkQueue->cs);
TRACE((DEBUG_TSHRSRV_FLOW,
"TShrSRV: TSrvFreeWorkQueue exit\n"));
}
//*************************************************************
//
// TSrvWaitForWork()
//
// Purpose: Called by the work queue processing routine
// to wait for posted work
//
// Parameters: IN [pWorkQueue] -- Work queue
//
// Return: void
//
// History: 07-17-97 BrianTa Created
//
//*************************************************************
void
TSrvWaitForWork(IN PWORKQUEUE pWorkQueue)
{
MSG msg;
DWORD rc;
TRACE((DEBUG_TSHRSRV_FLOW,
"TShrSRV: TSrvWaitForWork entry\n"));
if (pWorkQueue == NULL)
pWorkQueue = &g_MainWorkQueue;
TRACE((DEBUG_TSHRSRV_DEBUG, "TShrSRV: Waiting for work\n"));
// FUTURE: PeekMessage mechanism ultimately needs removed when event based
// callback is instrumented in GCC.
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
// FUTURE: Add another object to the "wait" when GCC callback
// mechanism is changed
rc = MsgWaitForMultipleObjects(1,
&pWorkQueue->hWorkEvent,
FALSE,
INFINITE,
QS_ALLINPUT);
if (rc != WAIT_OBJECT_0 &&
rc != WAIT_OBJECT_0 + 1)
{
TRACE((DEBUG_TSHRSRV_ERROR,
"TShrSRV: TSrvWaitForWork default case hit. rc 0x%x, GLE 0x%x\n",
rc, GetLastError()));
}
}
TRACE((DEBUG_TSHRSRV_DEBUG, "TShrSRV: Revived for work\n"));
TRACE((DEBUG_TSHRSRV_FLOW,
"TShrSRV: TSrvWaitForWork exit\n"));
}
//*************************************************************
//
// TSrvWorkToDo()
//
// Purpose: Determines if there is work to do
//
// Parameters: IN [pWorkQueue] -- Work queue
//
// Return: TRUE if successful
// FALSE if not
//
// History: 07-17-97 BrianTa Created
//
//*************************************************************
BOOL
TSrvWorkToDo(IN PWORKQUEUE pWorkQueue)
{
if (pWorkQueue == NULL)
pWorkQueue = &g_MainWorkQueue;
return (pWorkQueue->pHead ? TRUE : FALSE);
}
//*************************************************************
//
// TSrvDoWork()
//
// Purpose: Processes work queue items
//
// Parameters: IN [pWorkQueue] -- Work queue
//
// Return: TRUE if successful
// FALSE if not
//
// History: 07-17-97 BrianTa Created
//
//*************************************************************
BOOL
TSrvDoWork(IN PWORKQUEUE pWorkQueue)
{
PWORKITEM pWorkItem;
BOOL fSuccess;
TRACE((DEBUG_TSHRSRV_FLOW,
"TShrSRV: TSrvDoWork entry\n"));
fSuccess = FALSE;
if (pWorkQueue == NULL)
pWorkQueue = &g_MainWorkQueue;
pWorkItem = TSrvDequeueWorkItem(pWorkQueue);
// If we were able to dequeue a workitem, then (if defined) call
// out to supplied worker routine to process the item
if (pWorkItem)
{
if (pWorkItem->pfnCallout)
{
TRACE((DEBUG_TSHRSRV_DEBUG, "TShrSRV: Performing work callout\n"));
(*pWorkItem->pfnCallout)(pWorkItem);
}
// Done with the work item
TSrvFreeWorkItem(pWorkItem);
fSuccess = TRUE;
}
TRACE((DEBUG_TSHRSRV_FLOW,
"TShrSRV: TSrvDoWork exit - 0x%x\n", fSuccess));
return (fSuccess);
}
//*************************************************************
//
// TSrvEnqueueWorkItem()
//
// Purpose: Enqueues a work item to a work queue
//
// Parameters: IN [pWorkQueue] -- Work queue
// IN [pWorkItem] -- Work item
// IN [pfnCallout] -- Worker callout
// IN [ulParam] -- Worker callout param
//
// Return: TRUE if successful
// FALSE if not
//
// History: 07-17-97 BrianTa Created
//
//*************************************************************
BOOL
TSrvEnqueueWorkItem(IN PWORKQUEUE pWorkQueue,
IN PWORKITEM pWorkItem,
IN PFI_WI_CALLOUT pfnCallout,
IN ULONG ulParam)
{
BOOL fPosted;
TRACE((DEBUG_TSHRSRV_FLOW,
"TShrSRV: TSrvEnqueueWorkItem entry\n"));
if (pWorkQueue == NULL)
pWorkQueue = &g_MainWorkQueue;
fPosted = FALSE;
pWorkItem->pNext = NULL;
pWorkItem->ulParam = ulParam;
pWorkItem->pfnCallout = pfnCallout;
EnterCriticalSection(&pWorkQueue->cs);
// Add the workitem on the tail of the workqueue and
// then signal the queue processing thread to wake up
// and process the item
if (pWorkQueue->hWorkEvent)
{
TRACE((DEBUG_TSHRSRV_DEBUG, "TShrSRV: Workitem enqueued\n"));
fPosted = TRUE;
if (pWorkQueue->pHead != NULL)
pWorkQueue->pTail->pNext = pWorkItem;
else
pWorkQueue->pHead = pWorkItem;
pWorkQueue->pTail = pWorkItem;
SetEvent(pWorkQueue->hWorkEvent);
}
LeaveCriticalSection(&pWorkQueue->cs);
TRACE((DEBUG_TSHRSRV_FLOW,
"TShrSRV: TSrvEnqueueWorkItem exit - 0x%x\n", fPosted));
return (fPosted);
}
//*************************************************************
//
// TSrvDequeueWorkItem()
//
// Purpose: Dequeues a work item from a work queue
//
// Parameters: IN [pTSrvInfo] -- TSrv instance object
// IN [ulReason] -- Reason for disconnection
//
// Return: Ptr to dequeued work item if successful
// NULL if not
//
// History: 07-17-97 BrianTa Created
//
//*************************************************************
PWORKITEM
TSrvDequeueWorkItem(IN PWORKQUEUE pWorkQueue)
{
PWORKITEM pWorkItem;
TRACE((DEBUG_TSHRSRV_FLOW,
"TShrSRV: TSrvDequeueWorkItem entry\n"));
if (pWorkQueue == NULL)
pWorkQueue = &g_MainWorkQueue;
EnterCriticalSection(&pWorkQueue->cs);
// If there is an item in the queue, remove it and
// return it to the caller
pWorkItem = pWorkQueue->pHead;
if (pWorkItem)
{
pWorkQueue->pHead = pWorkItem->pNext;
if (pWorkQueue->pHead == NULL)
pWorkQueue->pTail = NULL;
TRACE((DEBUG_TSHRSRV_DEBUG, "TShrSRV: Workitem dequeued\n"));
}
LeaveCriticalSection(&pWorkQueue->cs);
if (pWorkItem)
TS_ASSERT(pWorkItem->CheckMark == TSRVWORKITEM_CHECKMARK);
TRACE((DEBUG_TSHRSRV_FLOW,
"TShrSRV: TSrvDequeueWorkItem exit - %p\n", pWorkItem));
return (pWorkItem);
}
//*************************************************************
//
// TSrvAllocWorkItem()
//
// Purpose: Allocates a new workitem
//
// Parameters: IN [pTSrvInfo] -- TSrv instance object
//
// Return: Ptr to dequeued work item if successful
// NULL if not
//
// History: 07-17-97 BrianTa Created
//
//*************************************************************
PWORKITEM
TSrvAllocWorkItem(IN PTSRVINFO pTSrvInfo)
{
PWORKITEM pWorkItem;
TRACE((DEBUG_TSHRSRV_FLOW,
"TShrSRV: TSrvAllocWorkItem entry\n"));
pWorkItem = TSHeapAlloc(HEAP_ZERO_MEMORY,
sizeof(WORKITEM),
TS_HTAG_TSS_WORKITEM);
if (pWorkItem)
{
pWorkItem->pTSrvInfo = pTSrvInfo;
#if DBG
pWorkItem->CheckMark = TSRVWORKITEM_CHECKMARK;
#endif
TSrvReferenceInfo(pTSrvInfo);
}
TRACE((DEBUG_TSHRSRV_FLOW,
"TShrSRV: TSrvAllocWorkItem exit - %p\n", pWorkItem));
return (pWorkItem);
}
//*************************************************************
//
// TSrvFreeWorkItem()
//
// Purpose: Frees the given workitem
//
// Parameters: IN [pWorkItem] -- Workitem
//
// Return: void
//
// History: 07-17-97 BrianTa Created
//
//*************************************************************
void
TSrvFreeWorkItem(IN PWORKITEM pWorkItem)
{
TRACE((DEBUG_TSHRSRV_FLOW,
"TShrSRV: TSrvFreeWorkItem entry\n"));
TS_ASSERT(pWorkItem);
TS_ASSERT(pWorkItem->pTSrvInfo);
TSrvDereferenceInfo(pWorkItem->pTSrvInfo);
TShareFree(pWorkItem);
TRACE((DEBUG_TSHRSRV_FLOW,
"TShrSRV: TSrvFreeWorkItem exit\n"));
}