173 lines
3.7 KiB
C++
173 lines
3.7 KiB
C++
/*++
|
||
|
||
Copyright (c) 1994 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
THREADS.C
|
||
|
||
Abstract:
|
||
|
||
This file contains thread management routines. Callers can register
|
||
waitable object handles and the functions to be called when a handle
|
||
becomes signaled. Also, work items can be queued, and operated on when
|
||
threads become free.
|
||
|
||
The implementation of the CWorkItemContext class resides in this file
|
||
|
||
Author:
|
||
|
||
Dan Lafferty (danl) 10-Jan-1994
|
||
|
||
Environment:
|
||
|
||
User Mode - Win32
|
||
|
||
Revision History:
|
||
|
||
21-Jan-1999 jschwart
|
||
Removed -- Service Controller and intrinsic services now use
|
||
NT thread pool APIs.
|
||
|
||
27-Jun-1997 anirudhs
|
||
SvcObjectWatcher: Fixed bug that sent WAIT_OBJECT_0 to all timed-
|
||
out work items even when only one was signaled.
|
||
Made global arrays static instead of heap-allocated.
|
||
|
||
04-Dec-1996 anirudhs
|
||
Added CWorkItemContext, a higher-level wrapper for SvcAddWorkItem.
|
||
|
||
01-Nov-1995 anirudhs
|
||
SvcAddWorkItem: Fixed race condition wherein a DLL could add a
|
||
work item and another thread would execute the work item, decrement
|
||
the DLL ref count and unload the DLL before its ref count was
|
||
incremented.
|
||
|
||
18-Jul-1994 danl
|
||
TmWorkerThread: Fixed Access Violation problem which will occur
|
||
if pWorkItem is NULL and we go on to see if the DLL should be
|
||
free'd. Now we check to see if pWorkItem is NULL first.
|
||
|
||
10-Jan-1994 danl
|
||
Created
|
||
|
||
--*/
|
||
#include <nt.h>
|
||
#include <ntrtl.h>
|
||
#include <nturtl.h>
|
||
#include <windows.h>
|
||
#include <scdebug.h>
|
||
#include <svcslib.h> // CWorkItemContext
|
||
|
||
|
||
//----------
|
||
// GLOBALS
|
||
//----------
|
||
|
||
HANDLE CWorkItemContext::s_hNeverSignaled;
|
||
|
||
|
||
VOID
|
||
CWorkItemContext::CallBack(
|
||
IN PVOID pContext
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Wrapper function for the Perform method that is supplied by derived classes.
|
||
|
||
--*/
|
||
{
|
||
//
|
||
// Timeout value is meaningless in this case, so tell the
|
||
// derived class it was signaled
|
||
//
|
||
(((CWorkItemContext *) pContext)->Perform(FALSE));
|
||
}
|
||
|
||
|
||
VOID
|
||
CWorkItemContext::DelayCallBack(
|
||
IN PVOID pContext,
|
||
IN BOOLEAN fWaitStatus
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Wrapper function for the Perform method that is supplied by derived classes.
|
||
|
||
--*/
|
||
{
|
||
(((CWorkItemContext *) pContext)->Perform(fWaitStatus));
|
||
}
|
||
|
||
|
||
BOOL
|
||
CWorkItemContext::Init(
|
||
)
|
||
{
|
||
ASSERT(s_hNeverSignaled == NULL);
|
||
s_hNeverSignaled = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||
if (s_hNeverSignaled == NULL)
|
||
{
|
||
SC_LOG(ERROR, "Couldn't create never-signaled event, %lu\n", GetLastError());
|
||
return FALSE;
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
void
|
||
CWorkItemContext::UnInit(
|
||
)
|
||
{
|
||
if (s_hNeverSignaled != NULL)
|
||
{
|
||
CloseHandle(s_hNeverSignaled);
|
||
}
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
CWorkItemContext::AddDelayedWorkItem(
|
||
IN DWORD dwTimeout,
|
||
IN DWORD dwFlags
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Queues a work item to take the action after the delay has elapsed.
|
||
|
||
--*/
|
||
{
|
||
//
|
||
// Give RtlRegisterWait a waitable handle that will never get signaled
|
||
// to force it to timeout. (Hack!)
|
||
//
|
||
// CODEWORK Use an RtlTimerQueue instead
|
||
//
|
||
if (s_hNeverSignaled == NULL)
|
||
{
|
||
SC_LOG0(ERROR, "Never-signaled event wasn't created\n");
|
||
return STATUS_UNSUCCESSFUL;
|
||
}
|
||
|
||
//
|
||
// The timeout mustn't be infinite
|
||
//
|
||
SC_ASSERT(dwTimeout != INFINITE);
|
||
|
||
return (RtlRegisterWait(&m_hWorkItem, // work item handle
|
||
s_hNeverSignaled, // waitable handle
|
||
DelayCallBack, // callback
|
||
this, // pContext;
|
||
dwTimeout, // timeout
|
||
dwFlags)); // flags
|
||
} |