/**
 * 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
}
Exemple #2
0
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;
}
Exemple #3
0
/*
 * @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 );
}
Exemple #5
0
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);
  }
}
Exemple #6
0
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 () */
Exemple #7
0
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;
    }
}