Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

483 lines
12 KiB

/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
dllsem.c
Abstract:
This module implements common routines to support the OS/2 V2.0
Semaphore API Calls. See dllevent.c, dllmutex.c and dllmuxwt.c for
the implementations of the API calls.
Author:
Steve Wood (stevewo) 02-Nov-1989
Revision History:
--*/
#define INCL_OS2V20_SEMAPHORES
#define INCL_OS2V20_ERRORS
#include "os2dll.h"
POR2_HANDLE_TABLE
Od2GetSemaphoreTable(
BOOLEAN SharedSem,
BOOLEAN CreateOkay
)
/*++
Routine Description:
This function returns a pointer to the appropriate OS/2 Semaphore table,
either shared or private, based on the value of the first parameter. The
second parameter specifies if the table should be created and initialized
if it does not already exist for the current process. Returns null if
table does not exist and the second parameter is FALSE or if the second
parameter is TRUE and this function is unable to create the table.
Semaphore tables are essentially handle tables. They are an array of
fixed size structures (OD2_SEMAPHORE) indexed by the low order 16 bits
of an OS/2 semaphore handle.
Arguments:
SharedSem - If this parameter is TRUE, then a pointer to shared semaphore
table is returned. Otherwise a pointer to the private semaphore
table is returned.
CreateOkay - If this parameter is TRUE, then an attempt is made to create
and initialize the requested semaphore table if it does not already
exist. Returns NULL if unable to create.
Return Value:
Pointer to the requested semaphore table or NULL.
--*/
{
POR2_HANDLE_TABLE *SemaphoreTablePointer;
POR2_HANDLE_TABLE SemaphoreTable;
if (!CreateOkay) {
if (SharedSem) {
return( Od2Process->SharedSemaphoreTable );
}
else {
return( Od2Process->PrivateSemaphoreTable );
}
}
//
// We are querying/modifying process state, so don't let others in while
// we are about it.
//
AcquireTaskLock();
//
// Compute pointer to the requested semaphore table pointer.
//
if (SharedSem) {
SemaphoreTablePointer = &Od2Process->SharedSemaphoreTable;
}
else {
SemaphoreTablePointer = &Od2Process->PrivateSemaphoreTable;
}
//
// If the requested semaphore table has not been created yet, and the
// caller said it was okay to create it, then attempt to do so, using
// a default initial size of 5 entries.
//
if ((SemaphoreTable = *SemaphoreTablePointer) == NULL) {
SemaphoreTable = Or2CreateHandleTable( Od2Heap,
sizeof( OD2_SEMAPHORE ),
5
);
//
// Update the appropriate field in the process structure with the
// address of the newly created semaphore table, or NULL if the
// create failed.
//
*SemaphoreTablePointer = SemaphoreTable;
}
//
// Done mucking about, release the process structure lock.
//
ReleaseTaskLock();
return( SemaphoreTable );
}
HSEM
Od2ConstructSemaphoreHandle(
IN BOOLEAN SharedSem,
IN ULONG Index
)
/*++
Routine Description:
This function constructs an OS/2 Semaphore handle. The format of
an OS/2 2.0 Semaphore handle is:
3322222222221111111111
10987654321098765432109876543210
Ssssssssssssssssiiiiiiiiiiiiiiii
where:
S - Shared semaphore bit (DC_SEM_SHARED)
s - 15 bit semaphore signature field (DC_SEM_SIGBITS). For OS/2 2.0
these were always equal to 0x1 (DC_SEM_HANDLESIG). This allows
the kernel named pipe code distinguish between 16:16 system
semaphores and 32 bit event semaphores.
i - 16 bit index field.
None of this was documented to the ISV for OS/2 2.0, but we maintain it
just out of paranoia.
Arguments:
SharedSem - If this parameter is set, then the S bit in the returned
handle is also set.
Index - The lower order 16 bits of this parameter are stored in the Index
field of the returned handle.
Return Value:
An OS/2 2.0 Semaphore handle, in the same format as defined by the
implementation of OS/2 2.0. No error return is possible, since it is
assumed the the Index parameter does not exceed 16 bits of significance.
--*/
{
if (SharedSem) {
return( (HSEM)(SEM_SHARED | SEM_HANDLESIG | (Index & SEM_INDEX)) );
}
else {
return( (HSEM)(SEM_HANDLESIG | (Index & SEM_INDEX)) );
}
}
APIRET
Od2ValidateSemaphoreHandle(
IN HSEM SemaphoreHandle,
OUT PBOOLEAN SharedSem,
OUT PULONG Index
)
/*++
Routine Description:
This function validates an OS/2 2.0 Semaphore handle and breaks it up
into its constituent parts.
Arguments:
SemaphoreHandle - OS/2 2.0 32 bit semaphore handle. See description
of Od2ConstructSemaphoreHandle for format.
SharedSem - Pointer a boolean variable that is set to TRUE or FALSE
depending upon whether the S bit in the input handle it set or not.
Index - Pointer to a variable that is set to the contents of the Index
field of the input handle.
Return Value:
OS/2 Error Code - one of the following:
NO_ERROR - success
ERROR_INVALID_HANDLE - if the signature field does not match the value
defined by the OS/2 2.0 implementation (SEM_HANDLESIG).
--*/
{
if (((ULONG)SemaphoreHandle & SEM_SIGBITS) != SEM_HANDLESIG) {
return( ERROR_INVALID_HANDLE );
}
if (((ULONG)SemaphoreHandle & SEM_SHARED) != 0) {
*SharedSem = TRUE;
}
else {
*SharedSem = FALSE;
}
*Index = (ULONG)SemaphoreHandle & SEM_INDEX;
return( NO_ERROR );
}
POD2_SEMAPHORE
Od2ReferenceSemaphore(
IN POD2_SEMAPHORE Semaphore
)
{
Semaphore->PointerCount++;
return( Semaphore );
}
VOID
Od2DereferenceSemaphore(
IN POD2_SEMAPHORE Semaphore
)
{
Semaphore->PointerCount--;
return;
}
VOID
Od2ThreadWaitingOnSemaphore(
IN POR2_HANDLE_TABLE SemaphoreTable,
IN POD2_SEMAPHORE Semaphore,
IN BOOLEAN AboutToWait
)
{
PTEB Teb;
POD2_THREAD Thread;
Teb = NtCurrentTeb();
Thread = (POD2_THREAD)Teb->EnvironmentPointer;
if (AboutToWait) {
Thread->WaitingForSemaphore = Od2ReferenceSemaphore( Semaphore );
ReleaseHandleTableLock( SemaphoreTable );
}
else {
AcquireHandleTableLock( SemaphoreTable );
Thread->WaitingForSemaphore = NULL;
Od2DereferenceSemaphore( Semaphore );
ReleaseHandleTableLock( SemaphoreTable );
}
}
POD2_THREAD
Od2SearchForWaitingThread(
IN POD2_SEMAPHORE Semaphore
)
{
PLIST_ENTRY ListHead, ListNext;
POD2_THREAD Thread;
POD2_MUXWAIT_SEMAPHORE MuxWait;
POD2_MUXWAIT_RECORD MuxWaitRecord;
USHORT i;
//
// If pointer count is zero then no waits can be outstanding.
//
if (Semaphore->PointerCount == 0) {
return( NULL );
}
//
// Walk the list of threads to see if any are waiting for the passed
// semaphore, either directly or indirectly via a MuxWait semaphore.
//
ListHead = &Od2Process->ThreadList;
ListNext = ListHead->Flink;
while (ListNext != ListHead) {
Thread = CONTAINING_RECORD( ListNext, OD2_THREAD, Link );
if (Thread->WaitingForSemaphore != NULL) {
if (Thread->WaitingForSemaphore == Semaphore) {
return( Thread );
}
else
if (Thread->WaitingForSemaphore->Type == Od2MuxWaitSem) {
MuxWait = Thread->WaitingForSemaphore->u.MuxWait;
if (MuxWait->Type == Semaphore->Type) {
MuxWaitRecord = &MuxWait->MuxWaitRecords[ 0 ];
for (i=0; i<MuxWait->CountMuxWaitRecords; i++) {
if (MuxWaitRecord->Semaphore == Semaphore) {
return( Thread );
}
MuxWaitRecord++;
}
}
}
}
ListNext = ListNext->Flink;
}
return( NULL );
}
VOID
Od2SemaphoreDestroyProcedure(
IN POD2_SEMAPHORE Semaphore,
IN ULONG HandleIndex
)
{
HSEM SemaphoreHandle;
APIRET rc;
SemaphoreHandle = Od2ConstructSemaphoreHandle( (BOOLEAN)Semaphore->Shared,
HandleIndex
);
rc = NO_ERROR;
while (rc == NO_ERROR && Semaphore->OpenCount != 0) {
switch ((ULONG)Semaphore->Type) {
case Od2EventSem:
#if DBG
IF_OD2_DEBUG( CLEANUP ) {
DbgPrint( "OS2DLL: Pid: %lX - DosCloseEventSem( %lX )\n",
Od2Process->Pib.ProcessId,
SemaphoreHandle
);
}
#endif
rc = DosCloseEventSem( SemaphoreHandle );
break;
/*
case Od2MutexSem:
#if DBG
IF_OD2_DEBUG( CLEANUP ) {
DbgPrint( "OS2DLL: Pid: %lX - DosCloseMutexSem( %lX )\n",
Od2Process->Pib.ProcessId,
SemaphoreHandle
);
}
#endif
rc = DosCloseMutexSem( SemaphoreHandle );
break;
case Od2MuxWaitSem:
#if DBG
IF_OD2_DEBUG( CLEANUP ) {
DbgPrint( "OS2DLL: Pid: %lX - DosCloseMuxWaitSem( %lX )\n",
Od2Process->Pib.ProcessId,
SemaphoreHandle
);
}
#endif
rc = DosCloseMuxWaitSem( SemaphoreHandle );
break;
*/
default:
return;
}
}
return;
}
VOID
Od2CloseAllSemaphores( VOID )
{
if (Od2Process->PrivateSemaphoreTable != NULL) {
Or2DestroyHandleTable(
Od2Process->PrivateSemaphoreTable,
(OR2_DESTROY_HANDLE_ROUTINE)Od2SemaphoreDestroyProcedure
);
Od2Process->PrivateSemaphoreTable = NULL;
}
if (Od2Process->SharedSemaphoreTable != NULL) {
Or2DestroyHandleTable(
Od2Process->SharedSemaphoreTable,
(OR2_DESTROY_HANDLE_ROUTINE)Od2SemaphoreDestroyProcedure
);
Od2Process->SharedSemaphoreTable = NULL;
}
}
#if DBG
VOID
Od2SemaphoreDumpProcedure(
IN POD2_SEMAPHORE Semaphore,
IN ULONG HandleIndex,
IN PVOID DumpParameter
)
{
UNREFERENCED_PARAMETER(DumpParameter);
DbgPrint( " %3ld %2ld %4ld %4ld %8lx %s\n",
HandleIndex,
(ULONG)Semaphore->Type,
(ULONG)Semaphore->OpenCount,
(ULONG)Semaphore->PointerCount,
(ULONG)Semaphore->u.Value,
Semaphore->Shared ? "Yes" : "No"
);
return;
}
VOID
Od2DumpAllSemaphores(
IN PCHAR Title
)
{
ULONG n;
if (Od2Process->PrivateSemaphoreTable != NULL &&
(Od2Process->PrivateSemaphoreTable->CountEntries >
Od2Process->PrivateSemaphoreTable->CountFreeEntries
)
) {
DbgPrint( "\nDump Of OS/2 Client Private Semaphore Table: %s\n", Title );
DbgPrint( "Index Type Ocnt Pcnt Value Shared\n" );
n = Or2DumpHandleTable(
Od2Process->PrivateSemaphoreTable,
(OR2_DUMP_HANDLE_ROUTINE)Od2SemaphoreDumpProcedure,
NULL
);
DbgPrint( "Total number of valid private semaphores: %ld\n", n );
}
if (Od2Process->SharedSemaphoreTable != NULL &&
(Od2Process->SharedSemaphoreTable->CountEntries >
Od2Process->SharedSemaphoreTable->CountFreeEntries
)
) {
DbgPrint( "\nDump Of OS/2 Client Shared Semaphore Table: %s\n", Title );
DbgPrint( "Index Type Ocnt Pcnt Value Shared\n" );
n = Or2DumpHandleTable(
Od2Process->SharedSemaphoreTable,
(OR2_DUMP_HANDLE_ROUTINE)Od2SemaphoreDumpProcedure,
NULL
);
DbgPrint( "\nTotal number of valid shared semaphores: %ld\n", n );
}
}
#endif // DBG