diff options
Diffstat (limited to 'private/os2/client/dllsem.c')
-rw-r--r-- | private/os2/client/dllsem.c | 483 |
1 files changed, 483 insertions, 0 deletions
diff --git a/private/os2/client/dllsem.c b/private/os2/client/dllsem.c new file mode 100644 index 000000000..4f84bfa25 --- /dev/null +++ b/private/os2/client/dllsem.c @@ -0,0 +1,483 @@ +/*++ + +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 |