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::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; }