PAL_ERROR CorUnix::InternalReleaseSemaphore( CPalThread *pthr, HANDLE hSemaphore, LONG lReleaseCount, LPLONG lpPreviousCount ) { PAL_ERROR palError = NO_ERROR; IPalObject *pobjSemaphore = NULL; ISynchStateController *pssc = NULL; SemaphoreImmutableData *pSemaphoreData; LONG lOldCount; _ASSERTE(NULL != pthr); ENTRY("InternalReleaseSempahore(pthr=%p, hSemaphore=%p, lReleaseCount=%d, " "lpPreviousCount=%p)\n", pthr, hSemaphore, lReleaseCount, lpPreviousCount ); if (0 >= lReleaseCount) { palError = ERROR_INVALID_PARAMETER; goto InternalReleaseSemaphoreExit; } palError = g_pObjectManager->ReferenceObjectByHandle( pthr, hSemaphore, &aotSempahore, 0, // Should be SEMAPHORE_MODIFY_STATE; currently ignored (no Win32 security) &pobjSemaphore ); if (NO_ERROR != palError) { ERROR("Unable to obtain object for handle %p (error %d)!\n", hSemaphore, palError); goto InternalReleaseSemaphoreExit; } palError = pobjSemaphore->GetImmutableData(reinterpret_cast<void**>(&pSemaphoreData)); if (NO_ERROR != palError) { ASSERT("Error %d obtaining object data\n", palError); goto InternalReleaseSemaphoreExit; } palError = pobjSemaphore->GetSynchStateController( pthr, &pssc ); if (NO_ERROR != palError) { ASSERT("Error %d obtaining synch state controller\n", palError); goto InternalReleaseSemaphoreExit; } palError = pssc->GetSignalCount(&lOldCount); if (NO_ERROR != palError) { ASSERT("Error %d obtaining current signal count\n", palError); goto InternalReleaseSemaphoreExit; } _ASSERTE(lOldCount <= pSemaphoreData->lMaximumCount); if (lReleaseCount > pSemaphoreData->lMaximumCount - lOldCount) { palError = ERROR_INVALID_PARAMETER; goto InternalReleaseSemaphoreExit; } palError = pssc->IncrementSignalCount(lReleaseCount); if (NO_ERROR != palError) { ASSERT("Error %d incrementing signal count\n", palError); goto InternalReleaseSemaphoreExit; } if (NULL != lpPreviousCount) { *lpPreviousCount = lOldCount; } InternalReleaseSemaphoreExit: if (NULL != pssc) { pssc->ReleaseController(); } if (NULL != pobjSemaphore) { pobjSemaphore->ReleaseReference(pthr); } LOGEXIT("InternalReleaseSemaphore returns %d\n", palError); return palError; }
PAL_ERROR CorUnix::InternalCreateSemaphore( CPalThread *pthr, LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount, LPCWSTR lpName, HANDLE *phSemaphore ) { CObjectAttributes oa(lpName, lpSemaphoreAttributes); PAL_ERROR palError = NO_ERROR; IPalObject *pobjSemaphore = NULL; IPalObject *pobjRegisteredSemaphore = NULL; SemaphoreImmutableData *pSemaphoreData; _ASSERTE(NULL != pthr); _ASSERTE(NULL != phSemaphore); ENTRY("InternalCreateSemaphore(pthr=%p, lpSemaphoreAttributes=%p, " "lInitialCount=%d, lMaximumCount=%d, lpName=%p, phSemaphore=%p)\n", pthr, lpSemaphoreAttributes, lInitialCount, lMaximumCount, lpName, phSemaphore ); if (lpName != nullptr) { ASSERT("lpName: Cross-process named objects are not supported in PAL"); palError = ERROR_NOT_SUPPORTED; goto InternalCreateSemaphoreExit; } if (lMaximumCount <= 0) { ERROR("lMaximumCount is invalid (%d)\n", lMaximumCount); palError = ERROR_INVALID_PARAMETER; goto InternalCreateSemaphoreExit; } if ((lInitialCount < 0) || (lInitialCount > lMaximumCount)) { ERROR("lInitialCount is invalid (%d)\n", lInitialCount); palError = ERROR_INVALID_PARAMETER; goto InternalCreateSemaphoreExit; } palError = g_pObjectManager->AllocateObject( pthr, &otSemaphore, &oa, &pobjSemaphore ); if (NO_ERROR != palError) { goto InternalCreateSemaphoreExit; } palError = pobjSemaphore->GetImmutableData(reinterpret_cast<void**>(&pSemaphoreData)); if (NO_ERROR != palError) { ASSERT("Error %d obtaining object data\n", palError); goto InternalCreateSemaphoreExit; } pSemaphoreData->lMaximumCount = lMaximumCount; if (0 != lInitialCount) { ISynchStateController *pssc; palError = pobjSemaphore->GetSynchStateController( pthr, &pssc ); if (NO_ERROR == palError) { palError = pssc->SetSignalCount(lInitialCount); pssc->ReleaseController(); } if (NO_ERROR != palError) { ASSERT("Unable to set new semaphore state (%d)\n", palError); goto InternalCreateSemaphoreExit; } } palError = g_pObjectManager->RegisterObject( pthr, pobjSemaphore, &aotSempahore, 0, // Should be SEMAPHORE_ALL_ACCESS; currently ignored (no Win32 security) phSemaphore, &pobjRegisteredSemaphore ); // // pobjSemaphore is invalidated by the call to RegisterObject, so NULL it // out here to ensure that we don't try to release a reference on // it down the line. // pobjSemaphore = NULL; InternalCreateSemaphoreExit: if (NULL != pobjSemaphore) { pobjSemaphore->ReleaseReference(pthr); } if (NULL != pobjRegisteredSemaphore) { pobjRegisteredSemaphore->ReleaseReference(pthr); } LOGEXIT("InternalCreateSemaphore returns %d\n", palError); return palError; }
PAL_ERROR CorUnix::InternalReleaseMutex( CPalThread *pthr, HANDLE hMutex ) { PAL_ERROR palError = NO_ERROR; IPalObject *pobjMutex = NULL; ISynchStateController *pssc = NULL; PalObjectTypeId objectTypeId; _ASSERTE(NULL != pthr); ENTRY("InternalReleaseMutex(pthr=%p, hMutex=%p)\n", pthr, hMutex ); palError = g_pObjectManager->ReferenceObjectByHandle( pthr, hMutex, &aotAnyMutex, 0, // should be MUTEX_MODIFY_STATE -- current ignored (no Win32 security) &pobjMutex ); if (NO_ERROR != palError) { ERROR("Unable to obtain object for handle %p (error %d)!\n", hMutex, palError); goto InternalReleaseMutexExit; } objectTypeId = pobjMutex->GetObjectType()->GetId(); if (objectTypeId == otiMutex) { palError = pobjMutex->GetSynchStateController( pthr, &pssc ); if (NO_ERROR != palError) { ASSERT("Error %d obtaining synch state controller\n", palError); goto InternalReleaseMutexExit; } palError = pssc->DecrementOwnershipCount(); if (NO_ERROR != palError) { ERROR("Error %d decrementing mutex ownership count\n", palError); goto InternalReleaseMutexExit; } } else { _ASSERTE(objectTypeId == otiNamedMutex); SharedMemoryProcessDataHeader *processDataHeader = SharedMemoryProcessDataHeader::PalObject_GetProcessDataHeader(pobjMutex); _ASSERTE(processDataHeader != nullptr); try { static_cast<NamedMutexProcessData *>(processDataHeader->GetData())->ReleaseLock(); } catch (SharedMemoryException ex) { palError = ex.GetErrorCode(); goto InternalReleaseMutexExit; } } InternalReleaseMutexExit: if (NULL != pssc) { pssc->ReleaseController(); } if (NULL != pobjMutex) { pobjMutex->ReleaseReference(pthr); } LOGEXIT("InternalReleaseMutex returns %i\n", palError); return palError; }
PAL_ERROR CorUnix::InternalCreateMutex( CPalThread *pthr, LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, LPCSTR lpName, HANDLE *phMutex ) { CObjectAttributes oa(nullptr, lpMutexAttributes); PAL_ERROR palError = NO_ERROR; IPalObject *pobjMutex = NULL; IPalObject *pobjRegisteredMutex = NULL; ISynchStateController *pssc = NULL; HANDLE hMutex = nullptr; _ASSERTE(NULL != pthr); _ASSERTE(NULL != phMutex); ENTRY("InternalCreateMutex(pthr=%p, lpMutexAttributes=%p, bInitialOwner=%d" ", lpName=%p, phMutex=%p)\n", pthr, lpMutexAttributes, bInitialOwner, lpName, phMutex ); if (lpName != nullptr && lpName[0] == '\0') { // Empty name is treated as a request for an unnamed process-local mutex lpName = nullptr; } CObjectType *ot = lpName == nullptr ? &otMutex : &otNamedMutex; CAllowedObjectTypes *aot = lpName == nullptr ? &aotMutex : &aotNamedMutex; palError = g_pObjectManager->AllocateObject( pthr, ot, &oa, &pobjMutex ); if (NO_ERROR != palError) { goto InternalCreateMutexExit; } if (lpName == nullptr) { palError = pobjMutex->GetSynchStateController( pthr, &pssc ); if (NO_ERROR != palError) { ASSERT("Unable to create state controller (%d)\n", palError); goto InternalCreateMutexExit; } if (bInitialOwner) { palError = pssc->SetOwner(pthr); } else { palError = pssc->SetSignalCount(1); } pssc->ReleaseController(); if (NO_ERROR != palError) { ASSERT("Unable to set initial mutex state (%d)\n", palError); goto InternalCreateMutexExit; } } palError = g_pObjectManager->RegisterObject( pthr, pobjMutex, aot, 0, // should be MUTEX_ALL_ACCESS -- currently ignored (no Win32 security) &hMutex, &pobjRegisteredMutex ); if (palError != NO_ERROR) { _ASSERTE(palError != ERROR_ALREADY_EXISTS); // PAL's naming infrastructure is not used for named mutexes _ASSERTE(pobjRegisteredMutex == nullptr); _ASSERTE(hMutex == nullptr); goto InternalCreateMutexExit; } // Now that the object has been registered successfully, it would have a reference associated with the handle, so release // the initial reference. Any errors from now on need to revoke the handle. _ASSERTE(pobjRegisteredMutex == pobjMutex); _ASSERTE(hMutex != nullptr); pobjMutex->ReleaseReference(pthr); pobjRegisteredMutex = nullptr; if (lpName != nullptr) { SharedMemoryProcessDataHeader *processDataHeader; bool created = false; try { processDataHeader = NamedMutexProcessData::CreateOrOpen(lpName, !!bInitialOwner, &created); } catch (SharedMemoryException ex) { palError = ex.GetErrorCode(); goto InternalCreateMutexExit; } SharedMemoryProcessDataHeader::PalObject_SetProcessDataHeader(pobjMutex, processDataHeader); if (!created) { // Indicate to the caller that an existing mutex was opened, and hence the caller will not have initial ownership // of the mutex if requested through bInitialOwner palError = ERROR_ALREADY_EXISTS; } } *phMutex = hMutex; hMutex = nullptr; pobjMutex = nullptr; InternalCreateMutexExit: _ASSERTE(pobjRegisteredMutex == nullptr); if (hMutex != nullptr) { g_pObjectManager->RevokeHandle(pthr, hMutex); } else if (NULL != pobjMutex) { pobjMutex->ReleaseReference(pthr); } LOGEXIT("InternalCreateMutex returns %i\n", palError); return palError; }
PAL_ERROR CorUnix::InternalReleaseMutex( CPalThread *pthr, HANDLE hMutex ) { PAL_ERROR palError = NO_ERROR; IPalObject *pobjMutex = NULL; ISynchStateController *pssc = NULL; _ASSERTE(NULL != pthr); ENTRY("InternalReleaseMutex(pthr=%p, hMutex=%p)\n", pthr, hMutex ); palError = g_pObjectManager->ReferenceObjectByHandle( pthr, hMutex, &aotMutex, 0, // should be MUTEX_MODIFY_STATE -- current ignored (no Win32 security) &pobjMutex ); if (NO_ERROR != palError) { ERROR("Unable to obtain object for handle %p (error %d)!\n", hMutex, palError); goto InternalReleaseMutexExit; } palError = pobjMutex->GetSynchStateController( pthr, &pssc ); if (NO_ERROR != palError) { ASSERT("Error %d obtaining synch state controller\n", palError); goto InternalReleaseMutexExit; } palError = pssc->DecrementOwnershipCount(); if (NO_ERROR != palError) { ERROR("Error %d decrementing mutex ownership count\n", palError); goto InternalReleaseMutexExit; } InternalReleaseMutexExit: if (NULL != pssc) { pssc->ReleaseController(); } if (NULL != pobjMutex) { pobjMutex->ReleaseReference(pthr); } LOGEXIT("InternalReleaseMutex returns %i\n", palError); return palError; }
PAL_ERROR CorUnix::InternalCreateMutex( CPalThread *pthr, LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, LPCWSTR lpName, HANDLE *phMutex ) { CObjectAttributes oa(lpName, lpMutexAttributes); PAL_ERROR palError = NO_ERROR; IPalObject *pobjMutex = NULL; IPalObject *pobjRegisteredMutex = NULL; ISynchStateController *pssc = NULL; _ASSERTE(NULL != pthr); _ASSERTE(NULL != phMutex); ENTRY("InternalCreateMutex(pthr=%p, lpMutexAttributes=%p, bInitialOwner=%d" ", lpName=%p, phMutex=%p)\n", pthr, lpMutexAttributes, bInitialOwner, lpName, phMutex ); if (lpName != nullptr) { ASSERT("lpName: Cross-process named objects are not supported in PAL"); palError = ERROR_NOT_SUPPORTED; goto InternalCreateMutexExit; } palError = g_pObjectManager->AllocateObject( pthr, &otMutex, &oa, &pobjMutex ); if (NO_ERROR != palError) { goto InternalCreateMutexExit; } palError = pobjMutex->GetSynchStateController( pthr, &pssc ); if (NO_ERROR != palError) { ASSERT("Unable to create state controller (%d)\n", palError); goto InternalCreateMutexExit; } if (bInitialOwner) { palError = pssc->SetOwner(pthr); } else { palError = pssc->SetSignalCount(1); } pssc->ReleaseController(); if (NO_ERROR != palError) { ASSERT("Unable to set initial mutex state (%d)\n", palError); goto InternalCreateMutexExit; } palError = g_pObjectManager->RegisterObject( pthr, pobjMutex, &aotMutex, 0, // should be MUTEX_ALL_ACCESS -- currently ignored (no Win32 security) phMutex, &pobjRegisteredMutex ); // // pobjMutex is invalidated by the call to RegisterObject, so NULL it // out here to ensure that we don't try to release a reference on // it down the line. // pobjMutex = NULL; InternalCreateMutexExit: if (NULL != pobjMutex) { pobjMutex->ReleaseReference(pthr); } if (NULL != pobjRegisteredMutex) { pobjRegisteredMutex->ReleaseReference(pthr); } LOGEXIT("InternalCreateMutex returns %i\n", palError); return palError; }