/** * Initializes a work queue. * * \param WorkQueue A work queue object. * \param MinimumThreads The suggested minimum number of threads to keep alive, even * when there is no work to be performed. * \param MaximumThreads The suggested maximum number of threads to create. * \param NoWorkTimeout The number of milliseconds after which threads without work * will terminate. */ VOID PhInitializeWorkQueue( __out PPH_WORK_QUEUE WorkQueue, __in ULONG MinimumThreads, __in ULONG MaximumThreads, __in ULONG NoWorkTimeout ) { PhInitializeRundownProtection(&WorkQueue->RundownProtect); WorkQueue->Terminating = FALSE; InitializeListHead(&WorkQueue->QueueListHead); PhInitializeQueuedLock(&WorkQueue->QueueLock); WorkQueue->MinimumThreads = MinimumThreads; WorkQueue->MaximumThreads = MaximumThreads; WorkQueue->NoWorkTimeout = NoWorkTimeout; PhInitializeQueuedLock(&WorkQueue->StateLock); NtCreateSemaphore(&WorkQueue->SemaphoreHandle, SEMAPHORE_ALL_ACCESS, NULL, 0, MAXLONG); WorkQueue->CurrentThreads = 0; WorkQueue->BusyThreads = 0; #ifdef DEBUG PhAcquireQueuedLockExclusive(&PhDbgWorkQueueListLock); InsertTailList(&PhDbgWorkQueueListHead, &WorkQueue->DbgListEntry); PhReleaseQueuedLockExclusive(&PhDbgWorkQueueListLock); #endif }
HANDLE PhpGetSemaphoreWorkQueue( _Inout_ PPH_WORK_QUEUE WorkQueue ) { HANDLE semaphoreHandle; semaphoreHandle = WorkQueue->SemaphoreHandle; if (!semaphoreHandle) { NtCreateSemaphore(&semaphoreHandle, SEMAPHORE_ALL_ACCESS, NULL, 0, MAXLONG); assert(semaphoreHandle); if (_InterlockedCompareExchangePointer( &WorkQueue->SemaphoreHandle, semaphoreHandle, NULL ) != NULL) { // Someone else created the semaphore before we did. NtClose(semaphoreHandle); semaphoreHandle = WorkQueue->SemaphoreHandle; } } return semaphoreHandle; }
/* * @implemented */ HANDLE WINAPI CreateSemaphoreExW(IN LPSECURITY_ATTRIBUTES lpSemaphoreAttributes OPTIONAL, IN LONG lInitialCount, IN LONG lMaximumCount, IN LPCWSTR lpName OPTIONAL, IN DWORD dwFlags, IN DWORD dwDesiredAccess) { NTSTATUS Status; OBJECT_ATTRIBUTES LocalAttributes; POBJECT_ATTRIBUTES ObjectAttributes; HANDLE Handle; UNICODE_STRING ObjectName; /* Now check if we got a name */ if (lpName) RtlInitUnicodeString(&ObjectName, lpName); if (dwFlags != 0) { SetLastError(ERROR_INVALID_PARAMETER); return NULL; } /* Now convert the object attributes */ ObjectAttributes = BasepConvertObjectAttributes(&LocalAttributes, lpSemaphoreAttributes, lpName ? &ObjectName : NULL); /* Create the semaphore */ Status = NtCreateSemaphore(&Handle, (ACCESS_MASK)dwDesiredAccess, ObjectAttributes, lInitialCount, lMaximumCount); if (NT_SUCCESS(Status)) { /* Check if the object already existed */ if (Status == STATUS_OBJECT_NAME_EXISTS) { /* Set distinguished Win32 error code */ SetLastError(ERROR_ALREADY_EXISTS); } else { /* Otherwise, set success */ SetLastError(ERROR_SUCCESS); } /* Return the handle */ return Handle; } else { /* Convert the NT Status and fail */ SetLastErrorByStatus(Status); return NULL; } }
/*********************************************************************** * MakeCriticalSectionGlobal (KERNEL32.@) */ void WINAPI MakeCriticalSectionGlobal( CRITICAL_SECTION *crit ) { /* let's assume that only one thread at a time will try to do this */ HANDLE sem = crit->LockSemaphore; if (!sem) NtCreateSemaphore( &sem, SEMAPHORE_ALL_ACCESS, NULL, 0, 1 ); crit->LockSemaphore = ConvertToGlobalHandle( sem ); free_debug_info( crit ); }
static void wine_cond_real_init(pthread_cond_t *cond) { wine_cond_detail *detail = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(wine_cond_detail)); detail->waiters_count = 0; detail->was_broadcast = 0; NtCreateSemaphore( &detail->sema, SEMAPHORE_ALL_ACCESS, NULL, 0, 0x7fffffff ); NtCreateEvent( &detail->waiters_done, EVENT_ALL_ACCESS, NULL, FALSE, FALSE ); RtlInitializeCriticalSection (&detail->waiters_count_lock); if (interlocked_cmpxchg_ptr((void**)&(((wine_cond)cond)->cond), detail, NULL) != NULL) { /* too late, some other thread already did it */ P_OUTPUT("FIXME:pthread_cond_init:expect troubles...\n"); NtClose(detail->sema); RtlDeleteCriticalSection(&detail->waiters_count_lock); NtClose(detail->waiters_done); RtlFreeHeap(GetProcessHeap(), 0, detail); } }
void ApfInitDll () { NTSTATUS Status; DWORD ulInitElapsedTime; SHORT sInitTimerHandle; DWORD ARGS64; #ifdef CALIBDBG SHORT sTimerHandle; ULONG ulElapsedTime; #endif #ifdef ERRORDBG DWORD Error; #endif int i; STRING DataSemName; UNICODE_STRING DataSemUnicodeName; OBJECT_ATTRIBUTES DataSemAttributes; // Create public share security descriptor for all the named objects // Status = RtlCreateSecurityDescriptor ( &SecDescriptor, SECURITY_DESCRIPTOR_REVISION1 ); #ifdef ERRORDBG if (!NT_SUCCESS(Status)) { KdPrint (("WAP: RtlCreateSecurityDescriptor falied - 0x%lx\n", Status)); } #endif Status = RtlSetDaclSecurityDescriptor ( &SecDescriptor, // SecurityDescriptor TRUE, // DaclPresent NULL, // Dacl FALSE // DaclDefaulted ); #ifdef ERRORDBG if (!NT_SUCCESS(Status)) { KdPrint (("WAP: RtlSetDaclSecurityDescriptor falied - 0x%lx\n", Status)); } #endif // Create sections for data and api arrays // if ( NT_SUCCESS(ApfCreateDataSection(&ApfControl)) ) { // Leave room for control flag // ApfData = (PAPFDATA)(ApfControl+1); // Initialization for semaphore creation // RtlInitString(&DataSemName, DATA_SEM_NAME); Status = RtlAnsiStringToUnicodeString( &DataSemUnicodeName, &DataSemName, TRUE); if (NT_SUCCESS(Status)) { InitializeObjectAttributes( &DataSemAttributes, &DataSemUnicodeName, OBJ_OPENIF | OBJ_CASE_INSENSITIVE, NULL, &SecDescriptor); } // Create semaphores // Status = NtCreateSemaphore( &hDataSem, SEMAPHORE_QUERY_STATE | SEMAPHORE_MODIFY_STATE | SYNCHRONIZE, &DataSemAttributes, 1L, 1L); #ifdef ERRORDBG if (!NT_SUCCESS(Status)) { KdPrint (("WAP: Data semaphore creation falied %lx\n", Status)); } #endif // Get semaphores // Status = NtWaitForSingleObject(hDataSem,FALSE,NULL); #ifdef ERRORDBG if (!NT_SUCCESS(Status)) { KdPrint (("WAP: Could not wait for Dsemaphore in ApfInitDll, %lx\n", Status)); } #endif // // Do timer calibration if not already done. // if (!ApfControl->fCalibrate) { ApfControl->fCalibrate = TRUE; // // Calibrate time overheads: // we get the minimum time here, to avoid extra time from // interrupts etc. // the tedious approach has two benefits // - duplicate generated code as accurately as possible // - pick up timer overhead, that isn't handled correctly // in timer // NOTE: ApfData[I_CALIBRATE].ulMinTime contains the // timer overhead, while ApfData[I_CALIBRATE].cCalls // contains the number of processess accessing this // DLL. // ApfData[I_CALIBRATE].cCalls = 0L; ApfData[I_CALIBRATE].cTimingErrors = 0L; ApfData[I_CALIBRATE].ulTotalTime = 0L; ApfData[I_CALIBRATE].ulFirstTime = MAX_LONG; ApfData[I_CALIBRATE].ulMaxTime = MAX_LONG; ApfData[I_CALIBRATE].ulMinTime = MAX_LONG; ApfClearData(); TimerOpen(&sInitTimerHandle, MICROSECONDS); #ifdef CALIBDBG // Release semaphore // Status = NtReleaseSemaphore(hDataSem,1,NULL); #ifdef ERRORDBG if (!NT_SUCCESS(Status)) { KdPrint (("WAP: DSemaphore Not Released in ApfInitDll!! %lx\n", Status)); } #endif // // Overhead for all the API wrapper code // Stored in ApfData[I_CALIBRATE].ulMaxTime // Used for debugging - for WOW profiling overhead. // for (i=0; i<NUM_ITRATIONS; i++) { TimerInit(sInitTimerHandle); if (fInitDone == FALSE) { } TimerOpen(&sTimerHandle, MICROSECONDS); TimerInit(sTimerHandle); // // Get the elapsed time // ulElapsedTime = TimerRead(sTimerHandle); ApfRecordInfo(1, ulElapsedTime); TimerClose(sTimerHandle); ulInitElapsedTime = TimerRead(sInitTimerHandle); if ((ulInitElapsedTime < ApfData[I_CALIBRATE].ulMaxTime) && (ulInitElapsedTime > MIN_ACCEPTABLEOVERHEAD)) { ApfData[I_CALIBRATE].ulMaxTime = ulInitElapsedTime; } } // Get semaphores // Status = NtWaitForSingleObject(hDataSem,FALSE,NULL); #ifdef ERRORDBG if (!NT_SUCCESS(Status)) { KdPrint (("WAP: Could not wait for Dsemaphore in ApfInitDll, %lx\n", Status)); } #endif #endif // // Excess overhead for TimerInit() followed by TimerREad() calls // Stored in ApfData[I_CALIBRATE].ulMinTime // Used by all APIs // for (i=0; i<NUM_ITRATIONS; i++) { TimerInit(sInitTimerHandle); ulInitElapsedTime = TimerRead(sInitTimerHandle); if ((ulInitElapsedTime < ApfData[I_CALIBRATE].ulMinTime) && (ulInitElapsedTime > MIN_ACCEPTABLEOVERHEAD)) { ApfData[I_CALIBRATE].ulMinTime = ulInitElapsedTime; } } // // Oerhead for calling cdecl APIs with 64 DWORD arguments // Stored in ApfData[I_CALIBRATE].ulFirstTime // Used by all variable argument cdecl APIs such as wsprintf() // for (i=0; i<NUM_ITRATIONS; i++) { TimerInit(sInitTimerHandle); CalibCdeclApi (ARGS64); ulInitElapsedTime = TimerRead(sInitTimerHandle); if ((ulInitElapsedTime < ApfData[I_CALIBRATE].ulFirstTime) && (ulInitElapsedTime > MIN_ACCEPTABLEOVERHEAD)) { ApfData[I_CALIBRATE].ulFirstTime = ulInitElapsedTime; } } ApfData[I_CALIBRATE].ulFirstTime -= ApfData[I_CALIBRATE].ulMinTime; TimerClose(sInitTimerHandle); } // Increment the number of active processes on this DLL // ApfData[I_CALIBRATE].cCalls++; // Load the module being profiled // hModule=GetModuleHandle(MODULE_NAME); #ifdef ERRORDBG if (hModule==NULL) { Error=GetLastError(); KdPrint (("WAP: Module Handle is null - %lx\n",Error)); } #endif // Release semaphore // Status = NtReleaseSemaphore(hDataSem,1,NULL); #ifdef ERRORDBG if (!NT_SUCCESS(Status)) { KdPrint (("WAP: DSemaphore Not Released in ApfInitDll!! %lx\n", Status)); } #endif fInitDone = TRUE; } #ifdef ERRORDBG else { KdPrint (("WAP: Couldn't create DATA section in ApfInitDll\n")); } #endif } /* ApfInitDll () */
HANDLE APIENTRY CreateSemaphoreW( LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount, LPCWSTR lpName ) /*++ Routine Description: A semaphore object is created and a handle opened for access to the object with the CreateSemaphore function. The CreateSemaphore function causes a semaphore object to be created which contains the specified initial and maximum counts. In addition to the STANDARD_RIGHTS_REQUIRED access flags, the following object type specific access flags are valid for semaphore objects: - SEMAPHORE_MODIFY_STATE - Modify state access (release) to the semaphore is desired. - SYNCHRONIZE - Synchronization access (wait) to the semaphore is desired. - SEMAPHORE_ALL_ACCESS - This set of access flags specifies all of the possible access flags for a semaphore object. Arguments: lpSemaphoreAttributes - An optional parameter that may be used to specify the attributes of the new semaphore. If the parameter is not specified, then the semaphore is created without a security descriptor, , and the resulting handle is not inherited on process creation. lInitialCount - The initial count for the semaphore, this value must be positive and less than or equal to the maximum count. lMaximumCount - The maximum count for the semaphore, this value must be greater than zero.. lpName - Supplies an optional unicode name for the object. Return Value: NON-NULL - Returns a handle to the new semaphore. The handle has full access to the new semaphore and may be used in any API that requires a handle to a semaphore object. FALSE/NULL - The operation failed. Extended error status is available using GetLastError. --*/ { NTSTATUS Status; OBJECT_ATTRIBUTES Obja; POBJECT_ATTRIBUTES pObja; HANDLE Handle; UNICODE_STRING ObjectName; if ( ARGUMENT_PRESENT(lpName) ) { RtlInitUnicodeString(&ObjectName,lpName); pObja = BaseFormatObjectAttributes(&Obja,lpSemaphoreAttributes,&ObjectName); } else { pObja = BaseFormatObjectAttributes(&Obja,lpSemaphoreAttributes,NULL); } Status = NtCreateSemaphore( &Handle, SEMAPHORE_ALL_ACCESS, pObja, lInitialCount, lMaximumCount ); if ( NT_SUCCESS(Status) ) { if ( Status == STATUS_OBJECT_NAME_EXISTS ) { SetLastError(ERROR_ALREADY_EXISTS); } else { SetLastError(0); } return Handle; } else { BaseSetLastNTError(Status); return NULL; } }