From dda1640a541e3c1307ca63d1b570a0282988707f Mon Sep 17 00:00:00 2001 From: gbalykov Date: Tue, 25 Jul 2017 01:37:38 +0300 Subject: [PATCH 18/32] Simplify SHM-allocator (#12815) * Simplify SHM-allocator * Remove SHMNULL and NULLSharedID --- src/pal/src/file/shmfilelockmgr.cpp | 40 +- src/pal/src/include/pal/shm.hpp | 45 +- src/pal/src/include/pal/shmemory.h | 212 +---- src/pal/src/include/pal/synchcache.hpp | 16 +- src/pal/src/include/pal/synchobjects.hpp | 5 - src/pal/src/objmgr/shmobject.cpp | 70 +- src/pal/src/objmgr/shmobject.hpp | 5 +- src/pal/src/objmgr/shmobjectmanager.cpp | 14 +- src/pal/src/shmemory/shmemory.cpp | 1342 +---------------------------- src/pal/src/synchmgr/synchcontrollers.cpp | 20 +- src/pal/src/synchmgr/synchmanager.cpp | 33 +- src/pal/src/synchmgr/synchmanager.hpp | 2 +- 12 files changed, 124 insertions(+), 1680 deletions(-) diff --git a/src/pal/src/file/shmfilelockmgr.cpp b/src/pal/src/file/shmfilelockmgr.cpp index a586abd..6deed61 100644 --- a/src/pal/src/file/shmfilelockmgr.cpp +++ b/src/pal/src/file/shmfilelockmgr.cpp @@ -102,7 +102,7 @@ CSharedMemoryFileLockMgr::GetLockControllerForFile( ) { PAL_ERROR palError = NO_ERROR; - SHMPTR shmFileLocks = SHMNULL; + SHMPTR shmFileLocks = NULL; SHMFILELOCKS* fileLocks = NULL; CSharedMemoryFileLockController *pController = NULL; @@ -214,7 +214,7 @@ CSharedMemoryFileLockMgr::GetLockControllerForFile( // don't attempt to free it below. // - shmFileLocks = SHMNULL; + shmFileLocks = NULL; /* set the share mode again, it's possible that the share mode is now more restrictive than the previous mode set. */ @@ -247,7 +247,7 @@ GetLockControllerForFileExit: pController->ReleaseController(); } - if (SHMNULL != shmFileLocks) + if (NULL != shmFileLocks) { FILECleanUpLockedRgn( shmFileLocks, @@ -269,13 +269,13 @@ CSharedMemoryFileLockMgr::GetFileShareModeForFile( { PAL_ERROR palError = NO_ERROR; *pdwShareMode = SHARE_MODE_NOT_INITALIZED; - SHMPTR shmFileLocks = SHMNULL; + SHMPTR shmFileLocks = NULL; SHMFILELOCKS* fileLocks = NULL; SHMLock(); palError = FILEGetSHMFileLocks(szFileName, &shmFileLocks, TRUE); - if (NO_ERROR != palError || shmFileLocks == SHMNULL) + if (NO_ERROR != palError || shmFileLocks == NULL) { goto GetLockControllerForFileExit; } @@ -291,7 +291,7 @@ CSharedMemoryFileLockMgr::GetFileShareModeForFile( GetLockControllerForFileExit: - if (SHMNULL != shmFileLocks) + if (NULL != shmFileLocks) { FILECleanUpLockedRgn( shmFileLocks, @@ -425,7 +425,7 @@ CSharedMemoryFileLockController::ReleaseFileLock( void CSharedMemoryFileLockController::ReleaseController() { - if (SHMNULL != m_shmFileLocks) + if (NULL != m_shmFileLocks) { FILECleanUpLockedRgn( m_shmFileLocks, @@ -667,7 +667,7 @@ FILEUnlockFileRegion( { prevLock->next = curLockRgn->next; } - SHMfree(shmcurLockRgn); + free(shmcurLockRgn); } else { @@ -735,7 +735,7 @@ FILEGetSHMFileLocks( TRACE("Create a new entry in the file lock list in SHM\n"); /* Create a new entry in the file lock list in SHM */ - if ((shmPtrRet = SHMalloc(sizeof(SHMFILELOCKS))) == 0) + if ((shmPtrRet = malloc(sizeof(SHMFILELOCKS))) == 0) { ERROR("Can't allocate SHMFILELOCKS structure\n"); palError = ERROR_NOT_ENOUGH_MEMORY; @@ -749,7 +749,7 @@ FILEGetSHMFileLocks( goto CLEANUP1; } - filelocksPtr->unix_filename = SHMStrDup(filename); + filelocksPtr->unix_filename = strdup(filename); if (filelocksPtr->unix_filename == 0) { ERROR("Can't allocate shared memory for filename\n"); @@ -781,9 +781,9 @@ FILEGetSHMFileLocks( goto EXIT; CLEANUP2: - SHMfree(filelocksPtr->unix_filename); + free(filelocksPtr->unix_filename); CLEANUP1: - SHMfree(shmPtrRet); + free(shmPtrRet); shmPtrRet = 0; EXIT: SHMRelease(); @@ -808,7 +808,7 @@ FILEAddNewLockedRgn( { PAL_ERROR palError = NO_ERROR; SHMFILELOCKRGNS *newLockRgn, *lockRgnPtr; - SHMPTR shmNewLockRgn = SHMNULL; + SHMPTR shmNewLockRgn = NULL; if ((fileLocks == NULL) || (pvControllerInstance == NULL)) { @@ -822,7 +822,7 @@ FILEAddNewLockedRgn( TRACE("Create a new entry for the new lock region (%I64u %I64u)\n", lockRgnStart, nbBytesToLock); - if ((shmNewLockRgn = SHMalloc(sizeof(SHMFILELOCKRGNS))) == SHMNULL) + if ((shmNewLockRgn = malloc(sizeof(SHMFILELOCKRGNS))) == NULL) { ERROR("Can't allocate SHMFILELOCKRGNS structure\n"); palError = ERROR_NOT_ENOUGH_MEMORY; @@ -897,9 +897,9 @@ FILEAddNewLockedRgn( EXIT: - if (NO_ERROR != palError && SHMNULL != shmNewLockRgn) + if (NO_ERROR != palError && NULL != shmNewLockRgn) { - SHMfree(shmNewLockRgn); + free(shmNewLockRgn); } SHMRelease(); @@ -950,7 +950,7 @@ FILECleanUpLockedRgn( { /* removing the first lock */ fileLocks->fileLockedRgns = curLockRgn->next; - SHMfree(shmcurLockRgn); + free(shmcurLockRgn); shmcurLockRgn = fileLocks->fileLockedRgns; if (SHMPTR_TO_TYPED_PTR_BOOL(SHMFILELOCKRGNS, curLockRgn, shmcurLockRgn) == FALSE) { @@ -961,7 +961,7 @@ FILECleanUpLockedRgn( else { prevLock->next = curLockRgn->next; - SHMfree(shmcurLockRgn); + free(shmcurLockRgn); shmcurLockRgn = prevLock->next; if (SHMPTR_TO_TYPED_PTR_BOOL(SHMFILELOCKRGNS, curLockRgn, shmcurLockRgn) == FALSE) { @@ -1020,9 +1020,9 @@ FILECleanUpLockedRgn( } if (fileLocks->unix_filename) - SHMfree(fileLocks->unix_filename); + free(fileLocks->unix_filename); - SHMfree(shmFileLocks); + free(shmFileLocks); } } EXIT: diff --git a/src/pal/src/include/pal/shm.hpp b/src/pal/src/include/pal/shm.hpp index de1d09e..36d6fd4 100644 --- a/src/pal/src/include/pal/shm.hpp +++ b/src/pal/src/include/pal/shm.hpp @@ -28,47 +28,7 @@ Abstract: // isn't considered a pointer type... // -#define SHMNULL 0 - -#ifndef _DEBUG - -inline -void * -ShmPtrToPtrFast(SHMPTR shmptr) -{ - void *pv = NULL; - - if (SHMNULL != shmptr) - { - int segment = shmptr >> 24; - - if (segment < shm_numsegments) - { - pv = reinterpret_cast( - reinterpret_cast(shm_segment_bases[(uint)segment].Load()) - + (shmptr & 0x00FFFFFF) - ); - } - else - { - pv = SHMPtrToPtr(shmptr); - } - } - - return pv; -} - -// -// We could use a function template here to avoid the cast / macro -// - -#define SHMPTR_TO_TYPED_PTR(type, shmptr) reinterpret_cast(ShmPtrToPtrFast((shmptr))) - -#else - -#define SHMPTR_TO_TYPED_PTR(type, shmptr) reinterpret_cast(SHMPtrToPtr((shmptr))) - -#endif +#define SHMPTR_TO_TYPED_PTR(type, shmptr) reinterpret_cast(shmptr) /* Set ptr to NULL if shmPtr == 0, else set ptr to SHMPTR_TO_TYPED_PTR(type, shmptr) return FALSE if SHMPTR_TO_TYPED_PTR returns NULL ptr from non null shmptr, @@ -76,8 +36,5 @@ ShmPtrToPtrFast(SHMPTR shmptr) #define SHMPTR_TO_TYPED_PTR_BOOL(type, ptr, shmptr) \ ((shmptr != 0) ? ((ptr = SHMPTR_TO_TYPED_PTR(type, shmptr)) != NULL) : ((ptr = NULL) == NULL)) - - - #endif // _SHM_HPP_ diff --git a/src/pal/src/include/pal/shmemory.h b/src/pal/src/include/pal/shmemory.h index 5ca8481..bf12de1 100644 --- a/src/pal/src/include/pal/shmemory.h +++ b/src/pal/src/include/pal/shmemory.h @@ -15,56 +15,7 @@ Abstract: How to use : -The SHMalloc function can be used to allocate memory in the shared memory area. -It returns a value of type SHMPTR, which will be useable in all participating -processes. The SHMPTR_TO_PTR macro can be used to convert a SHMPTR value into -an address valid *only* within the current process. Do NOT store pointers in -shared memory, since those will not be valid for other processes. If you need -to construct linked lists or other strctures that usually use pointers, use -SHMPTR values instead of pointers. In addition, Lock/Release functions must be -used when manipulating data in shared memory, to ensure inter-process synchronization. - -Example : - -//a simple linked list type -typedef struct -{ -int count; -SHMPTR string; -SHMPTR next; -}SHMLIST; - -// Allocate a new list item -SHMPTR new_item = SHMalloc(sizeof(SHMLIST)); - -// get a pointer to it -SHMLIST *item_ptr = (SHMLIST *)SHMPTR_TO_PTR(new_item); - -// Allocate memory for the "string" member, initialize it -item_ptr->string = SHMalloc(strlen("string")); -LPSTR str_ptr = (LPSTR)SHMPTR_TO_PTR(item_ptr->string); -strcpy(str_ptr, "string"); - -//Take the shared memory lock to prevent anyone from modifying the linked list -SHMLock(); - -//get the list's head from somewhere -SHMPTR list_head = get_list_head(); - -//link the list to our new item -item_ptr->next = list_head - -//get a pointer to the list head's structure -SHMLIST *head_ptr = (SHMLIST *)SHMPTR_TO_PTR(list_head); - -//set the new item's count value based on the head's count value -item_ptr->count = head_ptr->count + 1; - -//save the new item as the new head of the list -set_list_head(new_item); - -//We're done modifying the list, release the lock -SHMRelease +Lock/Release functions must be used when manipulating data in shared memory, to ensure inter-process synchronization. @@ -79,86 +30,17 @@ extern "C" #endif // __cplusplus /* -Type for shared memory blocks. use SHMPTR_TO_PTR to get a useable address. +Type for shared memory blocks */ -typedef DWORD_PTR SHMPTR; - -#define MAX_SEGMENTS 256 - +typedef LPVOID SHMPTR; typedef enum { - SIID_PROCESS_INFO,/* pointers to PROCESS structures? */ SIID_NAMED_OBJECTS, SIID_FILE_LOCKS, SIID_LAST } SHM_INFO_ID; -typedef enum -{ - SHM_NAMED_MAPPINGS, /* structs with map name, file name & flags? */ - SHM_NAMED_EVENTS, /* structs with event names & ThreadWaitingList struct? */ - SHM_NAMED_MUTEXS, /* structs with mutext names, and ThreadWaitingList struct */ - - SHM_NAMED_LAST -} SHM_NAMED_OBJECTS_ID; - -typedef struct _SMNO -{ - SHM_NAMED_OBJECTS_ID ObjectType; - SHMPTR ShmNext; - SHMPTR ShmObjectName; - SHMPTR ShmSelf; - -}SHM_NAMED_OBJECTS, * PSHM_NAMED_OBJECTS; - - -/* -SHMPTR_TO_PTR - -Macro to convert a SHMPTR value into a valid (for this process) pointer. - -In debug builds, we always call the function to do full checks. -In release builds, check if the segment is known, and if it is, do only minimal -validation (if segment is unknown, we have to call the function) - */ -#if _DEBUG - -#define SHMPTR_TO_PTR(shmptr) \ - SHMPtrToPtr(shmptr) - -#else /* !_DEBUG */ - -extern int shm_numsegments; - -/* array containing the base address of each segment */ -extern Volatile shm_segment_bases[MAX_SEGMENTS]; - -#define SHMPTR_TO_PTR(shmptr)\ - ((shmptr)?(((static_cast(shmptr)>>24)(reinterpret_cast(shm_segment_bases[static_cast(shmptr)>>24].Load())+(static_cast(shmptr)&0x00FFFFFF)):\ - SHMPtrToPtr(shmptr)): static_cast(NULL)) - - -#endif /* _DEBUG */ - -/* Set ptr to NULL if shmPtr == 0, else set ptr to SHMPTR_TO_PTR(shmptr) - return FALSE if SHMPTR_TO_PTR returns NULL ptr from non null shmptr, - TRUE otherwise */ -#define SHMPTR_TO_PTR_BOOL(ptr, shmptr) \ - ((shmptr != 0) ? ((ptr = SHMPTR_TO_PTR(shmptr)) != NULL) : ((ptr = NULL) == NULL)) - -/*++ -SHMPtrToPtr - -Convert a SHMPTR value into a useable pointer. - -Unlike the macro defined above, this function performs as much validation as -possible, and can handle cases when the SHMPTR is located in an aread of shared -memory the process doesn't yet know about. ---*/ -LPVOID SHMPtrToPtr(SHMPTR shmptr); - /*++ SHMInitialize @@ -176,37 +58,6 @@ registered processes, and remove all shared memory files if no process remains void SHMCleanup(void); /*++ -SHMalloc - -Allocate a block of memory of the specified size - -Parameters : - size_t size : size of block required - -Return value : - A SHMPTR identifying the new block, or 0 on failure. Use SHMPtrToPtr to - convert a SHMPTR into a useable pointer (but remember to lock the shared - memory first!) - -Notes : - SHMalloc will fail if the requested size is larger than a certain maximum. - At the moment, the maximum is 520 bytes (MAX_PATH_FNAME*2). ---*/ -SHMPTR SHMalloc(size_t size); - -/*++ -SHMfree - -Release a block of shared memory and put it back in the shared memory pool - -Parameters : - SHMPTR shmptr : identifier of block to release - -(no return value) ---*/ -void SHMfree(SHMPTR shmptr); - -/*++ SHMLock Restrict shared memory access to the current thread of the current process @@ -266,63 +117,6 @@ Notes : --*/ BOOL SHMSetInfo(SHM_INFO_ID element, SHMPTR value); - -/********************** Shared memory help functions ********************/ - -/*++ -SHMStrDup - -Duplicates the string in shared memory. - -Returns the new address as SHMPTR on success. -Returns (SHMPTR)NULL on failure. ---*/ -SHMPTR SHMStrDup( LPCSTR string ); - -/*++ -SHMWStrDup - -Duplicates the wide string in shared memory. - -Returns the new address as SHMPTR on success. -Returns (SHMPTR)NULL on failure. ---*/ -SHMPTR SHMWStrDup( LPCWSTR string ); - - -/*++ -SHMFindNamedObjectByName - -Searches for an object whose name matches the name and ID passed in. - -Returns a SHMPTR to its location in shared memory. If no object -matches the name, the function returns NULL and sets pbNameExists to FALSE. -If an object matches the name but is of a different type, the function -returns NULL and sets pbNameExists to TRUE. - ---*/ -SHMPTR SHMFindNamedObjectByName( LPCWSTR lpName, SHM_NAMED_OBJECTS_ID oid, - BOOL *pbNameExists ); - -/*++ -SHMRemoveNamedObject - -Removes the specified named object from the list - -No return. - -note : the caller is reponsible for releasing all associated memory ---*/ -void SHMRemoveNamedObject( SHMPTR shmNamedObject ); - -/*++ SHMAddNamedObject - -Adds the specified named object to the list. - -No return. ---*/ -void SHMAddNamedObject( SHMPTR shmNewNamedObject ); - #ifdef __cplusplus } #endif // __cplusplus diff --git a/src/pal/src/include/pal/synchcache.hpp b/src/pal/src/include/pal/synchcache.hpp index c172842..0abc7dd 100644 --- a/src/pal/src/include/pal/synchcache.hpp +++ b/src/pal/src/include/pal/synchcache.hpp @@ -252,7 +252,7 @@ namespace CorUnix SharedID Get(CPalThread * pthrCurrent) { - SharedID shridObj = NULLSharedID; + SharedID shridObj = NULL; Get(pthrCurrent, 1, &shridObj); return shridObj; @@ -291,8 +291,8 @@ namespace CorUnix { for (k=0; kpointers.pNext; shridTemp = pTemp->pointers.shrid; - RawSharedObjectFree(shridTemp); + free(shridTemp); } } }; diff --git a/src/pal/src/include/pal/synchobjects.hpp b/src/pal/src/include/pal/synchobjects.hpp index aa3a8f1..62f4017 100644 --- a/src/pal/src/include/pal/synchobjects.hpp +++ b/src/pal/src/include/pal/synchobjects.hpp @@ -29,13 +29,8 @@ Abstract: #include #define SharedID SHMPTR -#define SharedPoolId ULONG_PTR -#define DefaultSharedPool ((ULONG_PTR)0) -#define NULLSharedID ((SHMPTR)NULL) #define SharedIDToPointer(shID) SHMPTR_TO_TYPED_PTR(PVOID, shID) #define SharedIDToTypePointer(TYPE,shID) SHMPTR_TO_TYPED_PTR(TYPE, shID) -#define RawSharedObjectAlloc(szSize, shPoolId) SHMalloc(szSize) -#define RawSharedObjectFree(shID) SHMfree(shID) namespace CorUnix { diff --git a/src/pal/src/objmgr/shmobject.cpp b/src/pal/src/objmgr/shmobject.cpp index 1435d5d..2692554 100644 --- a/src/pal/src/objmgr/shmobject.cpp +++ b/src/pal/src/objmgr/shmobject.cpp @@ -180,7 +180,7 @@ CSharedMemoryObject::InitializeFromExistingSharedData( m_ObjectDomain = SharedObject; - _ASSERTE(SHMNULL != m_shmod); + _ASSERTE(NULL != m_shmod); psmod = SHMPTR_TO_TYPED_PTR(SHMObjData, m_shmod); if (NULL == psmod) @@ -236,7 +236,7 @@ CSharedMemoryObject::InitializeFromExistingSharedData( goto InitializeFromExistingSharedDataExit; } - if (SHMNULL != psmod->shmObjImmutableData) + if (NULL != psmod->shmObjImmutableData) { VOID *pv = SHMPTR_TO_TYPED_PTR(VOID, psmod->shmObjImmutableData); if (NULL != pv) @@ -251,7 +251,7 @@ CSharedMemoryObject::InitializeFromExistingSharedData( } } - if (SHMNULL != psmod->shmObjSharedData) + if (NULL != psmod->shmObjSharedData) { m_pvSharedData = SHMPTR_TO_TYPED_PTR(VOID, psmod->shmObjSharedData); if (NULL == m_pvSharedData) @@ -301,7 +301,7 @@ CSharedMemoryObject::AllocateSharedDataItems( ) { PAL_ERROR palError = NO_ERROR; - SHMPTR shmod = SHMNULL; + SHMPTR shmod = NULL; SHMObjData *psmod = NULL; _ASSERTE(NULL != pshmObjData); @@ -321,8 +321,8 @@ CSharedMemoryObject::AllocateSharedDataItems( SHMLock(); - shmod = SHMalloc(sizeof(SHMObjData)); - if (SHMNULL == shmod) + shmod = malloc(sizeof(SHMObjData)); + if (NULL == shmod) { ERROR("Unable to allocate m_shmod for new object\n"); palError = ERROR_OUTOFMEMORY; @@ -339,9 +339,19 @@ CSharedMemoryObject::AllocateSharedDataItems( if (0 != m_oa.sObjectName.GetStringLength()) { + LPCWSTR str = m_oa.sObjectName.GetString(); + _ASSERTE(str); + psmod->dwNameLength = m_oa.sObjectName.GetStringLength(); - psmod->shmObjName = SHMWStrDup(m_oa.sObjectName.GetString()); - if (SHMNULL == psmod->shmObjName) + + UINT length = (PAL_wcslen(str) + 1) * sizeof(WCHAR); + psmod->shmObjName = malloc(length); + + if (psmod->shmObjName != 0) + { + memcpy(psmod->shmObjName, str, length); + } + else { ERROR("Unable to allocate psmod->shmObjName for new object\n"); palError = ERROR_OUTOFMEMORY; @@ -356,8 +366,8 @@ CSharedMemoryObject::AllocateSharedDataItems( // by CSharedMemoryObjectManager::RegisterObject or PromoteSharedData // - psmod->shmObjImmutableData = SHMalloc(m_pot->GetImmutableDataSize()); - if (SHMNULL == psmod->shmObjImmutableData) + psmod->shmObjImmutableData = malloc(m_pot->GetImmutableDataSize()); + if (NULL == psmod->shmObjImmutableData) { ERROR("Unable to allocate psmod->shmObjImmutableData for new object\n"); palError = ERROR_OUTOFMEMORY; @@ -367,8 +377,8 @@ CSharedMemoryObject::AllocateSharedDataItems( if (0 != m_pot->GetSharedDataSize()) { - psmod->shmObjSharedData = SHMalloc(m_pot->GetSharedDataSize()); - if (SHMNULL == psmod->shmObjSharedData) + psmod->shmObjSharedData = malloc(m_pot->GetSharedDataSize()); + if (NULL == psmod->shmObjSharedData) { ERROR("Unable to allocate psmod->shmObjSharedData for new object\n"); palError = ERROR_OUTOFMEMORY; @@ -381,7 +391,7 @@ CSharedMemoryObject::AllocateSharedDataItems( AllocateSharedDataItemsExit: - if (NO_ERROR != palError && SHMNULL != shmod) + if (NO_ERROR != palError && NULL != shmod) { FreeSharedDataAreas(shmod); } @@ -412,7 +422,7 @@ CSharedMemoryObject::FreeSharedDataAreas( { SHMObjData *psmod; - _ASSERTE(SHMNULL != shmObjData); + _ASSERTE(NULL != shmObjData); ENTRY("CSharedMemoryObject::FreeSharedDataAreas" "(shmObjData = %p)\n", @@ -424,22 +434,22 @@ CSharedMemoryObject::FreeSharedDataAreas( psmod = SHMPTR_TO_TYPED_PTR(SHMObjData, shmObjData); _ASSERTE(NULL != psmod); - if (SHMNULL != psmod->shmObjImmutableData) + if (NULL != psmod->shmObjImmutableData) { - SHMfree(psmod->shmObjImmutableData); + free(psmod->shmObjImmutableData); } - if (SHMNULL != psmod->shmObjSharedData) + if (NULL != psmod->shmObjSharedData) { - SHMfree(psmod->shmObjSharedData); + free(psmod->shmObjSharedData); } - if (SHMNULL != psmod->shmObjName) + if (NULL != psmod->shmObjName) { - SHMfree(psmod->shmObjName); + free(psmod->shmObjName); } - SHMfree(shmObjData); + free(shmObjData); SHMRelease(); @@ -463,7 +473,7 @@ CSharedMemoryObject::PromoteSharedData( SHMObjData *psmod ) { - _ASSERTE(SHMNULL != shmObjData); + _ASSERTE(NULL != shmObjData); _ASSERTE(NULL != psmod); ENTRY("CSharedMemoryObject::PromoteSharedData" @@ -760,7 +770,7 @@ CSharedMemoryObject::DereferenceSharedData() if (!fSharedDataAlreadDereferenced) { - if (SHMNULL != m_shmod) + if (NULL != m_shmod) { SHMObjData *psmod; @@ -789,7 +799,7 @@ CSharedMemoryObject::DereferenceSharedData() _ASSERTE(0 != psmod->dwNameLength); - if (SHMNULL != psmod->shmPrevObj) + if (NULL != psmod->shmPrevObj) { SHMObjData *psmodPrevious = SHMPTR_TO_TYPED_PTR(SHMObjData, psmod->shmPrevObj); _ASSERTE(NULL != psmodPrevious); @@ -809,7 +819,7 @@ CSharedMemoryObject::DereferenceSharedData() } } - if (SHMNULL != psmod->shmNextObj) + if (NULL != psmod->shmNextObj) { SHMObjData *psmodNext = SHMPTR_TO_TYPED_PTR(SHMObjData, psmod->shmNextObj); _ASSERTE(NULL != psmodNext); @@ -820,8 +830,8 @@ CSharedMemoryObject::DereferenceSharedData() #if _DEBUG else { - _ASSERTE(SHMNULL == psmod->shmPrevObj); - _ASSERTE(SHMNULL == psmod->shmNextObj); + _ASSERTE(NULL == psmod->shmPrevObj); + _ASSERTE(NULL == psmod->shmNextObj); } #endif } @@ -871,7 +881,7 @@ CSharedMemoryObject::~CSharedMemoryObject() { free(m_pvSharedData); } - else if (SHMNULL != m_shmod && m_fDeleteSharedData) + else if (NULL != m_shmod && m_fDeleteSharedData) { FreeSharedDataAreas(m_shmod); } @@ -1195,7 +1205,7 @@ CSharedMemoryWaitableObject::EnsureObjectIsShared( { PAL_ERROR palError = NO_ERROR; IDataLock *pDataLock = NULL; - SHMPTR shmObjData = SHMNULL; + SHMPTR shmObjData = NULL; SHMObjData *psmod; VOID *pvSharedSynchData; @@ -1278,7 +1288,7 @@ EnsureObjectIsSharedExitNoSHMLockRelease: g_pSynchronizationManager->ReleaseProcessLock(pthr); - if (NO_ERROR != palError && SHMNULL != shmObjData) + if (NO_ERROR != palError && NULL != shmObjData) { // // Since shmObjdData is local to this function there's no diff --git a/src/pal/src/objmgr/shmobject.hpp b/src/pal/src/objmgr/shmobject.hpp index addfda5..66b9ea9 100644 --- a/src/pal/src/objmgr/shmobject.hpp +++ b/src/pal/src/objmgr/shmobject.hpp @@ -121,8 +121,7 @@ namespace CorUnix // m_fSharedDataDereferenced will be TRUE if DereferenceSharedData // has already been called. (N.B. -- this is a LONG instead of a bool // because it is passed to InterlockedExchange). If the shared data blob - // should be freed in the object's destructor (i.e., SHMfree should be - // called on the appropriate SHMPTRs) DereferenceSharedData will + // should be freed in the object's destructor DereferenceSharedData will // set m_fDeleteSharedData to TRUE. // @@ -178,7 +177,7 @@ namespace CorUnix : CPalObjectBase(pot), m_pcsObjListLock(pcsObjListLock), - m_shmod(SHMNULL), + m_shmod(NULL), m_pvSharedData(NULL), m_ObjectDomain(ProcessLocalObject), m_fSharedDataDereferenced(FALSE), diff --git a/src/pal/src/objmgr/shmobjectmanager.cpp b/src/pal/src/objmgr/shmobjectmanager.cpp index 4275421..755fa46 100644 --- a/src/pal/src/objmgr/shmobjectmanager.cpp +++ b/src/pal/src/objmgr/shmobjectmanager.cpp @@ -277,7 +277,7 @@ CSharedMemoryObjectManager::RegisterObject( if (0 != poa->sObjectName.GetStringLength()) { - SHMPTR shmObjectListHead = SHMNULL; + SHMPTR shmObjectListHead = NULL; // // The object must be shared @@ -352,7 +352,7 @@ CSharedMemoryObjectManager::RegisterObject( } shmObjectListHead = SHMGetInfo(SIID_NAMED_OBJECTS); - if (SHMNULL != shmObjectListHead) + if (NULL != shmObjectListHead) { SHMObjData *psmodListHead; @@ -505,8 +505,8 @@ CSharedMemoryObjectManager::LocateObject( { PAL_ERROR palError = NO_ERROR; IPalObject *pobjExisting = NULL; - SHMPTR shmSharedObjectData = SHMNULL; - SHMPTR shmObjectListEntry = SHMNULL; + SHMPTR shmSharedObjectData = NULL; + SHMPTR shmObjectListEntry = NULL; SHMObjData *psmod = NULL; LPWSTR pwsz = NULL; @@ -598,7 +598,7 @@ CSharedMemoryObjectManager::LocateObject( SHMLock(); shmObjectListEntry = SHMGetInfo(SIID_NAMED_OBJECTS); - while (SHMNULL != shmObjectListEntry) + while (NULL != shmObjectListEntry) { psmod = SHMPTR_TO_TYPED_PTR(SHMObjData, shmObjectListEntry); if (NULL != psmod) @@ -634,7 +634,7 @@ CSharedMemoryObjectManager::LocateObject( } } - if (SHMNULL != shmSharedObjectData) + if (NULL != shmSharedObjectData) { CSharedMemoryObject *pshmobj = NULL; CObjectAttributes oa(pwsz, NULL); @@ -1094,7 +1094,7 @@ CSharedMemoryObjectManager::ImportSharedObjectIntoProcess( _ASSERTE(NULL != pthr); _ASSERTE(NULL != pot); _ASSERTE(NULL != poa); - _ASSERTE(SHMNULL != shmSharedObjectData); + _ASSERTE(NULL != shmSharedObjectData); _ASSERTE(NULL != psmod); _ASSERTE(NULL != ppshmobj); diff --git a/src/pal/src/shmemory/shmemory.cpp b/src/pal/src/shmemory/shmemory.cpp index 35dadd6..a12bd29 100644 --- a/src/pal/src/shmemory/shmemory.cpp +++ b/src/pal/src/shmemory/shmemory.cpp @@ -14,165 +14,14 @@ Abstract: Implementation of shared memory infrastructure for IPC -Issues : - - Interprocess synchronization - - -There doesn't seem to be ANY synchronization mechanism that will work -inter-process AND be pthread-safe. FreeBSD's pthread implementation has no -support for inter-process synchronization (PTHREAD_PROCESS_SHARED); -"traditionnal" inter-process syncronization functions, on the other hand, are -not pthread-aware, and thus will block entire processes instead of only the -calling thread. - -From suggestions and information obtained on the freebsd-hackers mailing list, -I have come up with 2 possible strategies to ensure serialized access to our -shared memory region - -Note that the estimates of relative efficiency are wild guesses; my assumptions -are that blocking entire processes is least efficient, busy wait somewhat -better, and anything that does neither is preferable. However, the overhead of -complex solutions is likely to have an important impact on performance - -Option 1 : very simple; possibly less efficient. in 2 words : "busy wait" -Basically, - -while(InterlockedCompareExchange(spinlock_in_shared_memory, 1, 0) - sched_yield(); - -In other words, if a value is 0, set it to 1; otherwise, try again until we -succeed. use shed_yield to give the system a chance to schedule other threads -while we wait. (once a thread succeeds at this, it does its work, then sets -the value back to 0) -One inconvenient : threads will not unblock in the order they are blocked; -once a thread releases the mutex, whichever waiting thread is scheduled next -will be unblocked. This is what is called the "thundering herd" problem, and in -extreme cases, can lead to starvation -Update : we'll set the spinlock to our PID instead of 1, that way we can find -out if the lock is held by a dead process. - -Option 2 : possibly more efficient, much more complex, borders on -"over-engineered". I'll explain it in stages, in the same way I deduced it. - -Option 2.1 : probably less efficient, reasonably simple. stop at step 2) - -1) The minimal, original idea was to use SysV semaphores for synchronization. -This didn't work, because semaphores block the entire process, which can easily -lead to deadlocks (thread 1 takes sem, thread 2 tries to take sem, blocks -process, thread 1 is blocked and never releases sem) - -2) (this is option 2.1) Protect the use of the semaphores in critical sections. -Enter the critical section before taking the semaphore, leave the section after -releasing the semaphore. This ensures that 2 threads of the same process will -never try to acquire the semaphore at the same time, which avoids deadlocks. -However, the entire process still blocks if another process has the semaphore. -Here, unblocking order should match blocking order (assuming the semaphores work -properly); therefore, no risk of starvation. - -3) This is where it gets complicated. To avoid blocking whole processes, we -can't use semaphores. One suggestion I got was to use multi-ended FIFOs, here's -how it would work. - --as in option 1, use InterlockedCompareExchange on a value in shared memory. --if this was not succesful (someone else has locked the shared memory), then : - -open a special FIFO for reading; try to read 1 byte. This will block until - someone writes to it, and *should* only block the current thread. (note : - more than one thread/process can open the same FIFO and block on read(), - in this case, only one gets woken up when someone writes to it. - *which* one is, again, not predictable; this may lead to starvation) - -once we are unblocked, we have the lock. --once we have the lock (either from Interlocked...() or from read()), - we can do our work --once the work is done, we open the FIFO for writing. this will fail if no one - is listening. --if no one is listening, release the lock by setting the shared memory value - back to 0 --if someone is listening, write 1 byte to the FIFO to wake someone, then close - the FIFO. the value in shared memory will remain nonzero until a thread tries - to wake the next one and sees no one is listening. - -problem with this option : it is possible for a thread to call Interlocked...() -BETWEEN the failed "open for write" attempt and the subsequent restoration of -the SHM value back to zero. In this case, that thread will go to sleep and will -not wake up until *another* thread asks for the lock, takes it and releases it. - -so to fix that, we come to step - -4) Instead of using InterlockedCompareExchange, use a SysV semaphore : --when taking the lock : - -take the semaphore - -try to take the lock (check if value is zero, change it to 1 if it is) - -if we fail : open FIFO for reading, release the semaphore, read() and block - -if we succeed : release the semaphore --when releasing the lock : - -take the semaphore - -open FIFO for write - -if we succeed, release semaphore, then write value - -if we fail, reset SHM value to 0, then release semaphore. - -Yes, using a SysV semaphore will block the whole process, but for a very short -time (unlike option 2.1) -problem with this : again, we get deadlocks if 2 threads from a single process -try to take the semaphore. So like in option 2.1, we ave to wrap the semaphore -usage in a critical section. (complex enough yet?) - -so the locking sequence becomes EnterCriticalSection - take semaphore - try to - lock - open FIFO - release semaphore - LeaveCriticalSection - read -and the unlocking sequence becomes EnterCS - take sem - open FIFO - release - sem - LeaveCS - write - -Once again, the unblocking order probably won't match the blocking order. -This could be fixed by using multiple FIFOs : waiting thread open their own -personal FIFO, write the ID of their FIFO to another FIFO. The thread that wants -to release the lock reads ID from that FIFO, determines which FIFO to open for -writing and writes a byte to it. This way, whoever wrote its ID to the FIFO -first will be first to awake. How's that for complexity? - -So to summarize, the options are -1 - busy wait -2.1 - semaphores + critical sections (whole process blocks) -2 - semaphores + critical sections + FIFOs (minimal process blocking) -2.2 - option 2 with multiple FIFOs (minimal process blocking, order preserved) - -Considering the overhead involved in options 2 & 2.2, it is our guess that -option 1 may in fact be more efficient, and this is how we'll implement it for -the moment. Note that other platforms may not present the same difficulties -(i.e. other pthread implementations may support inter-process mutexes), and may -be able to use a simpler, more efficient approach. - -B] Reliability. -It is important for the shared memory implementation to be as foolproof as -possible. Since more than one process will be able to modify the shared data, -it becomes possible for one unstable process to destabilize the others. The -simplest example is a process that dies while modifying shared memory : if -it doesn't release its lock, we're in trouble. (this case will be taken care -of by using PIDs in the spinlock; this we we can check if the locking process -is still alive). - --*/ -#include "config.h" -#include "pal/palinternal.h" #include "pal/dbgmsg.h" #include "pal/shmemory.h" #include "pal/critsect.h" -#include "pal/shmemory.h" -#include "pal/init.h" #include "pal/process.h" -#include "pal/misc.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include #if HAVE_YIELD_SYSCALL #include @@ -180,155 +29,25 @@ is still alive). SET_DEFAULT_DEBUG_CHANNEL(SHMEM); -/* Macro-definitions **********************************************************/ - -/* rounds 'val' up to be divisible by 'r'. 'r' must be a power of two. */ -#ifndef roundup -#define roundup(val, r) ( ((val)+(r)-1) & ~( (r)-1 ) ) -#endif - -#define SEGMENT_NAME_SUFFIX_LENGTH 10 - -/* -SHMPTR structure : -High byte is SHM segment number -Low bytes are offset in the segment - */ -#define SHMPTR_SEGMENT(shmptr) \ - (((shmptr)>>24)&0xFF) - -#define SHMPTR_OFFSET(shmptr) \ - ((shmptr)&0x00FFFFFF) - -#define MAKE_SHMPTR(segment,offset) \ - ((SHMPTR)((((segment)&0xFF)<<24)|((offset)&0x00FFFFFF))) - -/*#define MAX_SEGMENTS 256*//*definition is now in shmemory.h*/ - -/* Use MAP_NOSYNC to improve performance if it's available */ -#if defined(MAP_NOSYNC) -#define MAPFLAGS MAP_NOSYNC|MAP_SHARED -#else -#define MAPFLAGS MAP_SHARED -#endif - - /* Type definitions ***********************************************************/ -enum SHM_POOL_SIZES -{ - SPS_16 = 0, /* 16 bytes */ - SPS_32, /* 32 bytes */ - SPS_64, /* 64 bytes */ - SPS_MAXPATHx2, /* 520 bytes, for long Unicode paths */ - - SPS_LAST -}; -/* Block size associated to each SPS identifier */ -static const int block_sizes[SPS_LAST] = {16,32,64,roundup((MAX_LONGPATH+1)*2, sizeof(INT64))}; - -/* -SHM_POOL_INFO -Description of a shared memory pool for a specific block size. - -Note on pool structure : -first_free identifies the first available SHMPTR in the block. Free blocks are -arranged in a linked list, each free block indicating the location of the next -one. To walk the list, do something like this : -SHMPTR *shmptr_ptr=(SHMPTR *)SHMPTR_TO_PTR(pool->first_free) -while(shm_ptr) -{ - SHMPTR next = *shmptr_ptr; - shmptr_ptr = (SHMPTR *)SHMPTR_TO_PTR(next) -} - */ -typedef struct -{ - int item_size; /* size of 1 block, in bytes */ - int num_items; /* total number of blocks in the pool */ - int free_items; /* number of unused items in the pool */ - SHMPTR first_free; /* location of first available block in the pool */ -}SHM_POOL_INFO; - /* -SHM_SEGMENT_HEADER -Description of a single shared memory segment - -Notes on segment names : -next_semgent contains the string generated by mkstemp() when a new segment is -generated. This allows processes to map segment files created by other -processes. To get the file name of a segment file, concatenate -"segment_name_prefix" and "next_segment". - -Notes on pool segments : -Each segment is divided into one pool for each defined block size (SPS_*). -These pools are linked with pools in other segment to form one large pool for -each block size, so that SHMAlloc() doesn't have to search each segment to find -an available block. -the first_ and last_pool_blocks indicate the first and last block in a single -segment for each block size. This allows SHMFree() to determine the size of a -block by comparing its value with these boundaries. (note that within each -segment, each pool is composed of a single contiguous block of memory) -*/ -typedef struct -{ - Volatile first_pool_blocks[SPS_LAST]; - Volatile last_pool_blocks[SPS_LAST]; -} SHM_SEGMENT_HEADER; - -/* -SHM_FIRST_HEADER +SHM_HEADER Global information about the shared memory system -In addition to the standard SHM_SEGGMENT_HEADER, the first segment contains some -information required to properly use the shared memory system. The spinlock is used to ensure that only one process accesses shared memory at the same time. A process can only take the spinlock if its contents is 0, and it takes the spinlock by placing its PID in it. (this allows a process to catch the special case where it tries to take a spinlock it already owns. - -The first_* members will contain the location of the first element in the -various linked lists of shared information - */ - -#ifdef TRACK_SHMLOCK_OWNERSHIP - -#define SHMLOCK_OWNERSHIP_HISTORY_ARRAY_SIZE 5 - -#define CHECK_CANARIES(header) \ - _ASSERTE(HeadSignature == header->dwHeadCanaries[0]); \ - _ASSERTE(HeadSignature == header->dwHeadCanaries[1]); \ - _ASSERTE(TailSignature == header->dwTailCanaries[0]); \ - _ASSERTE(TailSignature == header->dwTailCanaries[1]) - -typedef struct _pid_and_tid -{ - Volatile pid; - Volatile tid; -} pid_and_tid; - -const DWORD HeadSignature = 0x48454144; -const DWORD TailSignature = 0x5441494C; - -#endif // TRACK_SHMLOCK_OWNERSHIP +*/ typedef struct { - SHM_SEGMENT_HEADER header; -#ifdef TRACK_SHMLOCK_OWNERSHIP - Volatile dwHeadCanaries[2]; -#endif // TRACK_SHMLOCK_OWNERSHIP Volatile spinlock; -#ifdef TRACK_SHMLOCK_OWNERSHIP - Volatile dwTailCanaries[2]; - pid_and_tid pidtidCurrentOwner; - pid_and_tid pidtidOwners[SHMLOCK_OWNERSHIP_HISTORY_ARRAY_SIZE]; - Volatile ulOwnersIdx; -#endif // TRACK_SHMLOCK_OWNERSHIP - SHM_POOL_INFO pools[SPS_LAST]; /* information about each memory pool */ Volatile shm_info[SIID_LAST]; /* basic blocks of shared information.*/ -} SHM_FIRST_HEADER; +} SHM_HEADER; +static SHM_HEADER shm_header; /* Static variables ***********************************************************/ @@ -343,12 +62,6 @@ memory. Rationale : */ static CRITICAL_SECTION shm_critsec; -/* number of segments the current process knows about */ -int shm_numsegments; - -/* array containing the base address of each segment */ -Volatile shm_segment_bases[MAX_SEGMENTS]; - /* number of locks the process currently holds (SHMLock calls without matching SHMRelease). Because we take the critical section while inside a SHMLock/SHMRelease pair, this is actually the number of locks held by a single @@ -359,24 +72,6 @@ static Volatile lock_count; SHMGet/SetInfo will verify that the calling thread holds the lock */ static Volatile locking_thread; -/* Constants ******************************************************************/ - -/* size of a single segment : 256KB */ -static const int segment_size = 0x40000; - -/* Static function prototypes *************************************************/ - -static SHMPTR SHMInitPool(SHMPTR first, int block_size, int pool_size, - SHM_POOL_INFO *pool); -static SHMPTR SHMLinkPool(SHMPTR first, int block_size, int num_blocks); -static BOOL SHMMapUnknownSegments(void); -static BOOL SHMAddSegment(void); - - -#define init_waste() -#define log_waste(x,y) -#define save_waste() - /* Public function implementations ********************************************/ /*++ @@ -390,94 +85,18 @@ BOOL SHMInitialize(void) { InternalInitializeCriticalSection(&shm_critsec); - init_waste(); - - int size; - SHM_FIRST_HEADER *header; - SHMPTR pool_start; - SHMPTR pool_end; - enum SHM_POOL_SIZES sps; - TRACE("Now initializing global shared memory system\n"); - - // Not really shared in CoreCLR; we don't try to talk to other CoreCLRs. - shm_segment_bases[0] = mmap(NULL, segment_size,PROT_READ|PROT_WRITE, - MAP_ANON|MAP_PRIVATE, -1, 0); - if(shm_segment_bases[0] == MAP_FAILED) - { - ERROR("mmap() failed; error is %d (%s)\n", errno, strerror(errno)); - return FALSE; - } - TRACE("Mapped first SHM segment at %p\n",shm_segment_bases[0].Load()); - - /* Initialize first segment's header */ - header = (SHM_FIRST_HEADER *)shm_segment_bases[0].Load(); - InterlockedExchange((LONG *)&header->spinlock, 0); - -#ifdef TRACK_SHMLOCK_OWNERSHIP - header->dwHeadCanaries[0] = HeadSignature; - header->dwHeadCanaries[1] = HeadSignature; - header->dwTailCanaries[0] = TailSignature; - header->dwTailCanaries[1] = TailSignature; - - // Check spinlock size - _ASSERTE(sizeof(DWORD) == sizeof(header->spinlock)); - // Check spinlock alignment - _ASSERTE(0 == ((DWORD_PTR)&header->spinlock % (DWORD_PTR)sizeof(void *))); -#endif // TRACK_SHMLOCK_OWNERSHIP - -#ifdef TRACK_SHMLOCK_OWNERSHIP - header->pidtidCurrentOwner.pid = 0; - header->pidtidCurrentOwner.tid = 0; - memset((void *)header->pidtidOwners, 0, sizeof(header->pidtidOwners)); - header->ulOwnersIdx = 0; -#endif // TRACK_SHMLOCK_OWNERSHIP + InterlockedExchange((LONG *)&shm_header.spinlock, 0); /* SHM information array starts with NULLs */ - memset((void *)header->shm_info, 0, SIID_LAST*sizeof(SHMPTR)); - - /* Initialize memory pools */ - - /* first pool starts right after header */ - pool_start = roundup(sizeof(SHM_FIRST_HEADER), sizeof(INT64)); - - /* Same size for each pool, ensuring alignment is correct */ - size = ((segment_size-pool_start)/SPS_LAST) & ~(sizeof(INT64)-1); - - for (sps = static_cast(0); sps < SPS_LAST; - sps = static_cast(sps + 1)) - { - pool_end = SHMInitPool(pool_start, block_sizes[sps], size, - (SHM_POOL_INFO *)&header->pools[sps]); - - if(pool_end ==0) - { - ERROR("SHMInitPool failed.\n"); - munmap(shm_segment_bases[0],segment_size); - return FALSE; - } - /* save first and last element of each pool for this segment */ - header->header.first_pool_blocks[sps] = pool_start; - header->header.last_pool_blocks[sps] = pool_end; - - /* next pool starts immediately after this one */ - pool_start +=size; - } + memset((void *)shm_header.shm_info, 0, SIID_LAST*sizeof(SHMPTR)); TRACE("Global shared memory initialization complete.\n"); - shm_numsegments = 1; lock_count = 0; locking_thread = 0; - /* hook into all SHM segments */ - if(!SHMMapUnknownSegments()) - { - ERROR("Error while mapping segments!\n"); - SHMCleanup(); - return FALSE; - } return TRUE; } @@ -494,7 +113,6 @@ in PALCommonCleanup. --*/ void SHMCleanup(void) { - SHM_FIRST_HEADER *header; pid_t my_pid; TRACE("Starting shared memory cleanup\n"); @@ -505,9 +123,8 @@ void SHMCleanup(void) /* We should not be holding the spinlock at this point. If we are, release the spinlock. by setting it to 0 */ my_pid = gPID; - header = (SHM_FIRST_HEADER *)shm_segment_bases[0].Load(); - _ASSERT_MSG(header->spinlock != my_pid, + _ASSERT_MSG(shm_header.spinlock != my_pid, "SHMCleanup called while the current process still owns the lock " "[owner thread=%u, current thread: %u]\n", locking_thread.Load(), THREADSilentGetCurrentThreadId()); @@ -515,237 +132,10 @@ void SHMCleanup(void) /* Now for the interprocess stuff. */ DeleteCriticalSection(&shm_critsec); - - /* Unmap memory segments */ - while(shm_numsegments) - { - shm_numsegments--; - if ( -1 == munmap( shm_segment_bases[ shm_numsegments ], - segment_size ) ) - { - ASSERT( "munmap() failed; errno is %d (%s).\n", - errno, strerror( errno ) ); - } - } - - save_waste(); TRACE("SHMCleanup complete!\n"); } /*++ -SHMalloc - -Allocate a block of memory of the specified size - -Parameters : - size_t size : size of block required - -Return value : - A SHMPTR identifying the new block, or 0 on failure. Use SHMPTR_TO_PTR to - convert a SHMPTR into a useable pointer (but remember to lock the shared - memory first!) - -Notes : - SHMalloc will fail if the requested size is larger than a certain maximum. - At the moment, the maximum is 520 bytes (MAX_LONGPATH*2). ---*/ -SHMPTR SHMalloc(size_t size) -{ - enum SHM_POOL_SIZES sps; - SHMPTR first_free; - SHMPTR next_free; - SHM_FIRST_HEADER *header; - SHMPTR *shmptr_ptr; - - TRACE("SHMalloc() called; requested size is %u\n", size); - - if(0 == size) - { - WARN("Got a request for a 0-byte block! returning 0\n"); - return 0; - } - - /* Find the first block size >= requested size */ - for (sps = static_cast(0); sps < SPS_LAST; - sps = static_cast(sps + 1)) - { - if (size <= static_cast(block_sizes[sps])) - { - break; - } - } - - /* If no block size is found, requested size was too large. */ - if( SPS_LAST == sps ) - { - ASSERT("Got request for shared memory block of %u bytes; maximum block " - "size is %d.\n", size, block_sizes[SPS_LAST-1]); - return 0; - } - - TRACE("Best block size is %d (%d bytes wasted)\n", - block_sizes[sps], block_sizes[sps]-size ); - - log_waste(sps, block_sizes[sps]-size); - - SHMLock(); - header = (SHM_FIRST_HEADER *)shm_segment_bases[0].Load(); - - /* If there are no free items of the specified size left, it's time to - allocate a new shared memory segment.*/ - if(header->pools[sps].free_items == 0) - { - TRACE("No blocks of %d bytes left; allocating new segment.\n", - block_sizes[sps]); - if(!SHMAddSegment()) - { - ERROR("Unable to allocate new shared memory segment!\n"); - SHMRelease(); - return 0; - } - } - - /* Remove the first free block from the pool */ - first_free = header->pools[sps].first_free; - shmptr_ptr = static_cast(SHMPTR_TO_PTR(first_free)); - - if( 0 == first_free ) - { - ASSERT("First free block in %d-byte pool (%08x) was invalid!\n", - block_sizes[sps], first_free); - SHMRelease(); - return 0; - } - - /* the block "first_free" is the head of a linked list of free blocks; - take the next link in the list and set it as new head of list. */ - next_free = *shmptr_ptr; - header->pools[sps].first_free = next_free; - header->pools[sps].free_items--; - - /* make sure we're still in a sane state */ - if(( 0 == header->pools[sps].free_items && 0 != next_free) || - ( 0 != header->pools[sps].free_items && 0 == next_free)) - { - ASSERT("free block count is %d, but next free block is %#x\n", - header->pools[sps].free_items, next_free); - /* assume all remaining blocks in the pool are corrupt */ - header->pools[sps].first_free = 0; - header->pools[sps].free_items = 0; - } - else if (0 != next_free && 0 == SHMPTR_TO_PTR(next_free) ) - { - ASSERT("Next free block (%#x) in %d-byte pool is invalid!\n", - next_free, block_sizes[sps]); - /* assume all remaining blocks in the pool are corrupt */ - header->pools[sps].first_free = 0; - header->pools[sps].free_items = 0; - } - - SHMRelease(); - - TRACE("Allocation successful; %d blocks of %d bytes left. Returning %08x\n", - header->pools[sps].free_items, block_sizes[sps], first_free); - return first_free; -} - -/*++ -SHMfree - -Release a block of shared memory and put it back in the shared memory pool - -Parameters : - SHMPTR shmptr : identifier of block to release - -(no return value) ---*/ -void SHMfree(SHMPTR shmptr) -{ - int segment; - int offset; - SHM_SEGMENT_HEADER *header; - SHM_FIRST_HEADER *first_header; - enum SHM_POOL_SIZES sps; - SHMPTR *shmptr_ptr; - - if(0 == shmptr) - { - WARN("can't SHMfree() a NULL SHMPTR!\n"); - return; - } - SHMLock(); - - TRACE("Releasing SHMPTR 0x%08x\n", shmptr); - - shmptr_ptr = static_cast(SHMPTR_TO_PTR(shmptr)); - - if(!shmptr_ptr) - { - ASSERT("Tried to free an invalid shared memory pointer 0x%08x\n", shmptr); - SHMRelease(); - return; - } - - /* note : SHMPTR_TO_PTR has already validated the segment/offset pair */ - segment = SHMPTR_SEGMENT(shmptr); - header = (SHM_SEGMENT_HEADER *)shm_segment_bases[segment].Load(); - - /* Find out the size of this block. Each segment tells where are its first - and last blocks for each block size, so we simply need to check in which - interval the block fits */ - for (sps = static_cast(0); sps < SPS_LAST; - sps = static_cast(sps + 1)) - { - if(header->first_pool_blocks[sps]<=shmptr && - header->last_pool_blocks[sps]>=shmptr) - { - break; - } - } - - /* If we didn't find an interval, then the block doesn't really belong in - this segment (shouldn't happen, the offset check in SHMPTR_TO_PTR should - have caught this.) */ - if(sps == SPS_LAST) - { - ASSERT("Shared memory pointer 0x%08x is out of bounds!\n", shmptr); - SHMRelease(); - return; - } - - TRACE("SHMPTR 0x%08x is a %d-byte block located in segment %d\n", - shmptr, block_sizes[sps], segment); - - /* Determine the offset of this block (in bytes) relative to the first - block of the same size in this segment */ - offset = shmptr - header->first_pool_blocks[sps]; - - /* Make sure that the offset is a multiple of the block size; otherwise, - this isn't a real SHMPTR */ - if( 0 != ( offset % block_sizes[sps] ) ) - { - ASSERT("Shared memory pointer 0x%08x is misaligned!\n", shmptr); - SHMRelease(); - return; - } - - /* Put the SHMPTR back in its pool. */ - first_header = (SHM_FIRST_HEADER *)shm_segment_bases[0].Load(); - - /* first_free is the head of a linked list of free SHMPTRs. All we need to - do is make shmptr point to first_free, and set shmptr as the new head - of the list. */ - *shmptr_ptr = first_header->pools[sps].first_free; - first_header->pools[sps].first_free = shmptr; - first_header->pools[sps].free_items++; - - TRACE("SHMPTR 0x%08x released; there are now %d blocks of %d bytes " - "available\n", shmptr, first_header->pools[sps].free_items, - block_sizes[sps]); - SHMRelease(); -} - -/*++ SHMLock Restrict shared memory access to the current thread of the current process @@ -769,17 +159,11 @@ int SHMLock(void) if(lock_count == 0) { - SHM_FIRST_HEADER *header; pid_t my_pid, tmp_pid; int spincount = 1; -#ifdef TRACK_SHMLOCK_OWNERSHIP - ULONG ulIdx; -#endif // TRACK_SHMLOCK_OWNERSHIP TRACE("First-level SHM lock : taking spinlock\n"); - header = (SHM_FIRST_HEADER *)shm_segment_bases[0].Load(); - // Store the id of the current thread as the (only) one that is // trying to grab the spinlock from the current process locking_thread = (HANDLE)pthread_self(); @@ -788,21 +172,10 @@ int SHMLock(void) while(TRUE) { -#ifdef TRACK_SHMLOCK_OWNERSHIP - _ASSERTE(0 != my_pid); - _ASSERTE(getpid() == my_pid); - _ASSERTE(my_pid != header->spinlock); - CHECK_CANARIES(header); -#endif // TRACK_SHMLOCK_OWNERSHIP - // // Try to grab the spinlock // - tmp_pid = InterlockedCompareExchange((LONG *) &header->spinlock, my_pid,0); - -#ifdef TRACK_SHMLOCK_OWNERSHIP - CHECK_CANARIES(header); -#endif // TRACK_SHMLOCK_OWNERSHIP + tmp_pid = InterlockedCompareExchange((LONG *) &shm_header.spinlock, my_pid,0); if (0 == tmp_pid) { @@ -821,7 +194,7 @@ int SHMLock(void) TRACE("SHM spinlock owner (%08x) is dead; releasing its lock\n", tmp_pid); - InterlockedCompareExchange((LONG *) &header->spinlock, 0, tmp_pid); + InterlockedCompareExchange((LONG *) &shm_header.spinlock, 0, tmp_pid); } else { @@ -856,31 +229,15 @@ int SHMLock(void) spincount++; } - _ASSERT_MSG(my_pid == header->spinlock, + _ASSERT_MSG(my_pid == shm_header.spinlock, "\n(my_pid = %u) != (header->spinlock = %u)\n" "tmp_pid = %u\n" "spincount = %d\n" "locking_thread = %u\n", - (DWORD)my_pid, (DWORD)header->spinlock, + (DWORD)my_pid, (DWORD)shm_header.spinlock, (DWORD)tmp_pid, (int)spincount, (HANDLE)locking_thread); - -#ifdef TRACK_SHMLOCK_OWNERSHIP - _ASSERTE(0 == header->pidtidCurrentOwner.pid); - _ASSERTE(0 == header->pidtidCurrentOwner.tid); - - header->pidtidCurrentOwner.pid = my_pid; - header->pidtidCurrentOwner.tid = locking_thread; - - ulIdx = header->ulOwnersIdx % (sizeof(header->pidtidOwners) / sizeof(header->pidtidOwners[0])); - - header->pidtidOwners[ulIdx].pid = my_pid; - header->pidtidOwners[ulIdx].tid = locking_thread; - - header->ulOwnersIdx += 1; -#endif // TRACK_SHMLOCK_OWNERSHIP - } lock_count++; @@ -919,32 +276,15 @@ int SHMRelease(void) set the spinlock back to 0. */ if(lock_count == 0) { - SHM_FIRST_HEADER *header; pid_t my_pid, tmp_pid; TRACE("Releasing first-level SHM lock : resetting spinlock\n"); my_pid = gPID; - - header = (SHM_FIRST_HEADER *)shm_segment_bases[0].Load(); - -#ifdef TRACK_SHMLOCK_OWNERSHIP - CHECK_CANARIES(header); - _ASSERTE(0 != my_pid); - _ASSERTE(getpid() == my_pid); - _ASSERTE(my_pid == header->spinlock); - _ASSERTE(header->pidtidCurrentOwner.pid == my_pid); - _ASSERTE(pthread_self() == header->pidtidCurrentOwner.tid); - _ASSERTE((pthread_t)locking_thread == header->pidtidCurrentOwner.tid); - - header->pidtidCurrentOwner.pid = 0; - header->pidtidCurrentOwner.tid = 0; -#endif // TRACK_SHMLOCK_OWNERSHIP - /* Make sure we don't touch the spinlock if we don't own it. We're supposed to own it if we get here, but just in case... */ - tmp_pid = InterlockedCompareExchange((LONG *) &header->spinlock, 0, my_pid); + tmp_pid = InterlockedCompareExchange((LONG *) &shm_header.spinlock, 0, my_pid); if (tmp_pid != my_pid) { @@ -956,10 +296,6 @@ int SHMRelease(void) /* indicate no thread (in this process) holds the SHM lock */ locking_thread = 0; - -#ifdef TRACK_SHMLOCK_OWNERSHIP - CHECK_CANARIES(header); -#endif // TRACK_SHMLOCK_OWNERSHIP } TRACE("SHM lock level is now %d\n", lock_count.Load()); @@ -974,99 +310,6 @@ int SHMRelease(void) } /*++ -SHMPtrToPtr - -Convert a SHMPTR value to a valid pointer within the address space of the -current process - -Parameters : - SHMPTR shmptr : SHMPTR value to convert into a pointer - -Return value : - Address corresponding to the given SHMPTR, valid for the current process - -Notes : -(see notes for SHMPTR_SEGMENT macro for details on SHMPTR structure) - -It is possible for the segment index to be greater than the known total number -of segments (shm_numsegments); this means that the SHMPTR points to a memory -block in a shared memory segment this process doesn't know about. In this case, -we must obtain an address for that new segment and add it to our array -(see SHMMapUnknownSegments for details) - -In the simplest case (no need to map new segments), there is no need to hold -the lock, since we don't access any information that can change ---*/ -LPVOID SHMPtrToPtr(SHMPTR shmptr) -{ - void *retval; - int segment; - int offset; - - TRACE("Converting SHMPTR 0x%08x to a valid pointer...\n", shmptr); - if(!shmptr) - { - WARN("Got SHMPTR \"0\"; returning NULL pointer\n"); - return NULL; - } - - segment = SHMPTR_SEGMENT(shmptr); - - /* If segment isn't known, it may have been added by another process. We - need to map all new segments into our address space. */ - if(segment>= shm_numsegments) - { - TRACE("SHMPTR is in segment %d, we know only %d. We must now map all " - "unknowns.\n", segment, shm_numsegments); - SHMMapUnknownSegments(); - - /* if segment is still unknown, then it doesn't exist */ - if(segment>=shm_numsegments) - { - ASSERT("Segment %d still unknown; returning NULL\n", segment); - return NULL; - } - TRACE("Segment %d found; continuing\n", segment); - } - - /* Make sure the offset doesn't point outside the segment */ - offset = SHMPTR_OFFSET(shmptr); - if(offset>=segment_size) - { - ASSERT("Offset %d is larger than segment size (%d)! returning NULL\n", - offset, segment_size); - return NULL; - - } - - /* Make sure the offset doesn't point in the segment's header */ - if(segment == 0) - { - if (static_cast(offset) < roundup(sizeof(SHM_FIRST_HEADER), sizeof(INT64))) - { - ASSERT("Offset %d is in segment header! returning NULL\n", offset); - return NULL; - } - } - else - { - if (static_cast(offset) < sizeof(SHM_SEGMENT_HEADER)) - { - ASSERT("Offset %d is in segment header! returning NULL\n", offset); - return NULL; - } - } - - retval = shm_segment_bases[segment]; - retval = static_cast(retval) + offset; - - TRACE("SHMPTR %#x is at offset %d in segment %d; maps to address %p\n", - shmptr, offset, segment, retval); - return retval; -} - - -/*++ Function : SHMGetInfo @@ -1083,7 +326,6 @@ Notes : --*/ SHMPTR SHMGetInfo(SHM_INFO_ID element) { - SHM_FIRST_HEADER *header = NULL; SHMPTR retval = 0; if(element < 0 || element >= SIID_LAST) @@ -1099,9 +341,7 @@ SHMPTR SHMGetInfo(SHM_INFO_ID element) ASSERT("SHMGetInfo called while thread does not hold the SHM lock!\n"); } - header = (SHM_FIRST_HEADER *)shm_segment_bases[0].Load(); - - retval = header->shm_info[element]; + retval = shm_header.shm_info[element]; TRACE("SHM info element %d is %08x\n", element, retval ); return retval; @@ -1126,8 +366,6 @@ Notes : --*/ BOOL SHMSetInfo(SHM_INFO_ID element, SHMPTR value) { - SHM_FIRST_HEADER *header; - if(element < 0 || element >= SIID_LAST) { ASSERT("Invalid SHM info element %d\n", element); @@ -1141,558 +379,10 @@ BOOL SHMSetInfo(SHM_INFO_ID element, SHMPTR value) ASSERT("SHMGetInfo called while thread does not hold the SHM lock!\n"); } - header = (SHM_FIRST_HEADER*)shm_segment_bases[0].Load(); - TRACE("Setting SHM info element %d to %08x; used to be %08x\n", - element, value, header->shm_info[element].Load() ); + element, value, shm_header.shm_info[element].Load() ); - header->shm_info[element] = value; + shm_header.shm_info[element] = value; return TRUE; -} - - -/* Static function implementations ********************************************/ - -/*++ -SHMInitPool - -Perform one-time initialization for a shared memory pool. - -Parameters : - SHMPTR first : SHMPTR of first memory block in the pool - int block_size : size (in bytes) of a memory block in this pool - int pool_size : total size (in bytes) of this pool - SHM_POOL_INFO *pool : pointer to initialize with information about the pool - -Return value : - SHMPTR of last memory block in the pool - -Notes : -This function is used to initialize the memory pools of the first SHM segment. -In addition to creating a linked list of SHMPTRs, it initializes the given -SHM_POOL_INFO based on the given information. ---*/ -static SHMPTR SHMInitPool(SHMPTR first, int block_size, int pool_size, - SHM_POOL_INFO *pool) -{ - int num_blocks; - SHMPTR last; - - TRACE("Initializing SHM pool for %d-byte blocks\n", block_size); - - /* Number of memory blocks of size "block_size" that can fit in "pool_size" - bytes (rounded down) */ - num_blocks = pool_size/block_size; - - /* Create the initial linked list of free blocks */ - last = SHMLinkPool(first, block_size, num_blocks); - if( 0 == last ) - { - ERROR("Failed to create linked list of free blocks!\n"); - return 0; - } - - /* Initialize SHM_POOL_INFO */ - pool->first_free = first; - pool->free_items = num_blocks; - pool->item_size = block_size; - pool->num_items = num_blocks; - - TRACE("New SHM pool extends from SHMPTR 0x%08x to 0x%08x\n", first, last); - return last; -} - -/*++ -SHMLinkPool - -Joins contiguous blocks of memory into a linked list.. - -Parameters : - SHMPTR first : First SHMPTR in the memory pool; first link in the list - int block_size : size (in bytes) of the memory blocks - int num_blocks : number of contiguous blocks to link - -Return value : - SHMPTR of last memory block in the pool - -Notes : -The linked list is created by saving the value of the next SHMPTR in the list -in the memory location corresponding to the previous SHMPTR : -*(SHMPTR *)SHMPTR_TO_PTR(previous) = previous + block_size ---*/ -static SHMPTR SHMLinkPool(SHMPTR first, int block_size, int num_blocks) -{ - LPBYTE item_ptr; - SHMPTR *shmptr_ptr; - SHMPTR next_shmptr; - int i; - - TRACE("Linking %d blocks of %d bytes, starting at 0x%08x\n", - num_blocks, block_size, first); - - item_ptr = static_cast( - static_cast(shm_segment_bases[SHMPTR_SEGMENT(first)].Load()) + - (SHMPTR_OFFSET(first))); - next_shmptr = first/*+block_size*/; - - /* Link blocks together */ - for(i=0; ipools[sps].num_items*block_sizes[sps]; - - /* Remove unused size of this pool */ - used_size -= first_header->pools[sps].free_items*block_sizes[sps]; - } - - /* Determine how to divide the new segment between the pools for the - different block sizes, then update the pool inforamtion accordingly - Allocation strategy : - 1) Calculate the proportion of used memory used by each pool - 2) Allocate this proportion of the new segment to each pool - */ - - /* Add the new segment to the total amount of SHM memory */ - new_size = segment_size-roundup(sizeof(SHM_SEGMENT_HEADER), sizeof(INT64)); - - /* Calculate value of first SHMPTR in the new segment : segment is - shm_numsegments (not yet incremented); offset is the first byte after - the segment header */ - first_shmptr = MAKE_SHMPTR(shm_numsegments,roundup(sizeof(SHM_SEGMENT_HEADER), sizeof(INT64))); - - TRACE("Updating SHM pool information; Total memory used is %d bytes; " - "we are adding %d bytes\n", used_size, new_size); - - /* We want to allocate at least 1 block of each size (to avoid adding - special cases everywhere). We remove the required space for these blocks - from the size used in the calculations, then add 1 to each block count */ - for(sps=0;spspools[sps].num_items*block_sizes[sps]; - - /* how much of that is actually used? */ - used_pool_size = current_pool_size - - first_header->pools[sps].free_items*block_sizes[sps]; - - DBGOUT("%d bytes of %d bytes used (%d%%)\n", used_pool_size, - current_pool_size, (used_pool_size*100)/current_pool_size); - - /* amount of memory we want to add to the pool for this block size : - amount used by this pool/total amount used * new segment's size */ - new_pool_size = (((LONGLONG)used_pool_size)*new_size)/used_size; - - DBGOUT("Allocating %d bytes of %d to %d-byte pool\n", - new_pool_size, new_size, block_sizes[sps]); - - /* determine the number of blocks that can fit in the chosen amount */ - num_new_items = new_pool_size/block_sizes[sps]; - - /* make sure we allocate at least 1 block of each size */ - num_new_items +=1; - - DBGOUT("Adding %d new blocks\n", num_new_items); - - /* Save the first and last block of the current block size in the new - segment; join all blocks in between in a linked list */ - header->first_pool_blocks[sps] = first_shmptr; - header->last_pool_blocks[sps] = SHMLinkPool(first_shmptr, - block_sizes[sps], - num_new_items); - - /* Link the last block in the new linked list to the first block of the - old global linked list. We don't use SHMPTR_TO_PTR because the pool - data isn't updated yet */ - shmptr_ptr = reinterpret_cast( - static_cast(shm_segment_bases[SHMPTR_SEGMENT(header->last_pool_blocks[sps])].Load()) + - SHMPTR_OFFSET(header->last_pool_blocks[sps])); - - *shmptr_ptr = first_header->pools[sps].first_free; - - /* Save the first block of the new linked list as the new beginning of - the global linked list; the global list now contains all new blocks - AND all blocks that were already free */ - first_header->pools[sps].first_free = header->first_pool_blocks[sps]; - - /* Update block counts to include new blocks */ - first_header->pools[sps].free_items+=num_new_items; - first_header->pools[sps].num_items+=num_new_items; - - DBGOUT("There are now %d %d-byte blocks, %d are free\n", - first_header->pools[sps].num_items, block_sizes[sps], - first_header->pools[sps].free_items); - - /* Update first_shmptr to first byte after the new pool */ - first_shmptr+=num_new_items*block_sizes[sps]; - } - shm_numsegments++; - - return TRUE; -} - -/*++ -SHMStrDup - -Duplicates the string in shared memory. - -Returns the new address as SHMPTR on success. -Returns (SHMPTR)NULL on failure. ---*/ -SHMPTR SHMStrDup( LPCSTR string ) -{ - UINT length = 0; - SHMPTR retVal = 0; - - if ( string ) - { - length = strlen( string ); - - retVal = SHMalloc( ++length ); - - if ( retVal != 0 ) - { - LPVOID ptr = SHMPTR_TO_PTR( retVal ); - _ASSERT_MSG(ptr != NULL, "SHMPTR_TO_PTR returned NULL.\n"); - if (ptr != NULL) - { - memcpy( ptr, string, length ); - } - else - { - // This code should never be reached. If a valid pointer - // is passed to SHMPTR_TO_PTR and NULL is returned, then - // there's a problem in either the macro, or the underlying - // call to SHMPtrToPtr. In case the impossible happens, - // though, free the memory and return NULL rather than - // returning uninitialized memory. - SHMfree( retVal ); - retVal = NULL; - } - } - } - return retVal; -} - -/*++ -SHMWStrDup - -Duplicates the wide string in shared memory. - -Returns the new address as SHMPTR on success. -Returns (SHMPTR)NULL on failure. ---*/ -SHMPTR SHMWStrDup( LPCWSTR string ) -{ - UINT length = 0; - SHMPTR retVal = 0; - - if ( string ) - { - length = ( PAL_wcslen( string ) + 1 ) * sizeof( WCHAR ); - - retVal = SHMalloc( length ); - - if ( retVal != 0 ) - { - LPVOID ptr = SHMPTR_TO_PTR(retVal); - _ASSERT_MSG(ptr != NULL, "SHMPTR_TO_PTR returned NULL.\n"); - if (ptr != NULL) - { - memcpy( ptr, string, length ); - } - else - { - // This code should never be reached. If a valid pointer - // is passed to SHMPTR_TO_PTR and NULL is returned, then - // there's a problem in either the macro, or the underlying - // call to SHMPtrToPtr. In case the impossible happens, - // though, free the memory and return NULL rather than - // returning uninitialized memory. - SHMfree( retVal ); - retVal = NULL; - } - } - } - return retVal; -} - - - -/*++ -SHMFindNamedObjectByName - -Searches for an object whose name matches the name and ID passed in. - -Returns a SHMPTR to its location in shared memory. If no object -matches the name, the function returns NULL and sets pbNameExists to FALSE. -If an object matches the name but is of a different type, the function -returns NULL and sets pbNameExists to TRUE. - ---*/ -SHMPTR SHMFindNamedObjectByName( LPCWSTR lpName, SHM_NAMED_OBJECTS_ID oid, - BOOL *pbNameExists ) -{ - PSHM_NAMED_OBJECTS pNamedObject = NULL; - SHMPTR shmNamedObject = 0; - LPWSTR object_name = NULL; - - if(oid==SHM_NAMED_LAST) - { - ASSERT("Invalid named object type.\n"); - return 0; - } - - if (pbNameExists == NULL) - { - ASSERT("pbNameExists must be non-NULL.\n"); - } - - SHMLock(); - - *pbNameExists = FALSE; - shmNamedObject = SHMGetInfo( SIID_NAMED_OBJECTS ); - - TRACE( "Entering SHMFindNamedObjectByName looking for %S .\n", - lpName?lpName:W16_NULLSTRING ); - - while ( shmNamedObject ) - { - pNamedObject = (PSHM_NAMED_OBJECTS)SHMPTR_TO_PTR( shmNamedObject ); - if(NULL == pNamedObject) - { - ASSERT("Got invalid SHMPTR value; list of named objects is " - "corrupted.\n"); - break; - } - - if ( pNamedObject->ShmObjectName ) - { - object_name = (LPWSTR)SHMPTR_TO_PTR( pNamedObject->ShmObjectName ); - } - - if ( object_name && - PAL_wcscmp( lpName, object_name ) == 0 ) - { - if(oid == pNamedObject->ObjectType) - { - TRACE( "Returning the kernel object %p.\n", pNamedObject ); - } - else - { - shmNamedObject = 0; - *pbNameExists = TRUE; - } - goto Exit; - } - shmNamedObject = pNamedObject->ShmNext; - } - - shmNamedObject = 0; - TRACE( "No matching kernel object was found.\n" ); - -Exit: - SHMRelease(); - return shmNamedObject; - -} - -/*++ -SHMRemoveNamedObject - -Removes the specified named object from the list - -No return. - -note : the caller is reponsible for releasing all associated memory ---*/ -void SHMRemoveNamedObject( SHMPTR shmNamedObject ) -{ - PSHM_NAMED_OBJECTS pshmLast = 0; - PSHM_NAMED_OBJECTS pshmCurrent = 0; - - TRACE( "Entered SHMDeleteNamedObject shmNamedObject = %d\n", shmNamedObject ); - SHMLock(); - - pshmCurrent = - (PSHM_NAMED_OBJECTS)SHMPTR_TO_PTR( SHMGetInfo( SIID_NAMED_OBJECTS ) ); - pshmLast = pshmCurrent; - - while ( pshmCurrent ) - { - if ( pshmCurrent->ShmSelf == shmNamedObject ) - { - TRACE( "Patching the list.\n" ); - - /* Patch the list, and delete the object. */ - if ( pshmLast->ShmSelf == pshmCurrent->ShmSelf ) - { - /* Either the first element or no elements left. */ - SHMSetInfo( SIID_NAMED_OBJECTS, pshmCurrent->ShmNext ); - } - else if ( (PSHM_NAMED_OBJECTS)SHMPTR_TO_PTR( pshmCurrent->ShmNext ) ) - { - pshmLast->ShmNext = pshmCurrent->ShmNext; - } - else - { - /* Only one left. */ - pshmLast->ShmNext = 0; - } - - break; - } - else - { - pshmLast = pshmCurrent; - pshmCurrent = (PSHM_NAMED_OBJECTS)SHMPTR_TO_PTR( pshmCurrent->ShmNext ); - } - } - - SHMRelease(); - return; -} - -/*++ SHMAddNamedObject - -Adds the specified named object to the list. - -No return. ---*/ -void SHMAddNamedObject( SHMPTR shmNewNamedObject ) -{ - PSHM_NAMED_OBJECTS pshmNew = 0; - - pshmNew = (PSHM_NAMED_OBJECTS)SHMPTR_TO_PTR( shmNewNamedObject ); - - if ( pshmNew == NULL ) - { - ASSERT( "pshmNew should not be NULL\n" ); - } - - SHMLock(); - - pshmNew->ShmNext = SHMGetInfo( SIID_NAMED_OBJECTS ); - - if ( !SHMSetInfo( SIID_NAMED_OBJECTS, shmNewNamedObject ) ) - { - ASSERT( "Unable to add the mapping object to shared memory.\n" ); - } - - SHMRelease(); - return; -} +} \ No newline at end of file diff --git a/src/pal/src/synchmgr/synchcontrollers.cpp b/src/pal/src/synchmgr/synchcontrollers.cpp index f7df5ea..68fe429 100644 --- a/src/pal/src/synchmgr/synchcontrollers.cpp +++ b/src/pal/src/synchmgr/synchcontrollers.cpp @@ -268,7 +268,7 @@ namespace CorUnix PAL_ERROR palErr = NO_ERROR; WaitingThreadsListNode * pwtlnNewNode = NULL; - SharedID shridNewNode = NULLSharedID; + SharedID shridNewNode = NULL; ThreadWaitInfo * ptwiWaitInfo; DWORD * pdwWaitState; bool fSharedObject = (SharedObject == m_odObjectDomain); @@ -299,7 +299,7 @@ namespace CorUnix if (!pwtlnNewNode) { - if (fSharedObject && (NULLSharedID != shridNewNode)) + if (fSharedObject && (NULL != shridNewNode)) { ASSERT("Bad Shared Memory ptr %p\n", shridNewNode); palErr = ERROR_INTERNAL_ERROR; @@ -335,7 +335,7 @@ namespace CorUnix } } - pwtlnNewNode->shridSHRThis = NULLSharedID; + pwtlnNewNode->shridSHRThis = NULL; pwtlnNewNode->ptwiWaitInfo = ptwiWaitInfo; pwtlnNewNode->dwObjIndex = dwIndex; pwtlnNewNode->dwProcessId = gPID; @@ -442,7 +442,7 @@ namespace CorUnix { m_psdSynchData->Release(m_pthrOwner); } - if ((fSharedObject) && (NULLSharedID != shridNewNode)) + if ((fSharedObject) && (NULL != shridNewNode)) { pSynchManager->CacheAddSharedWTListNode(m_pthrOwner, shridNewNode); } @@ -781,7 +781,7 @@ namespace CorUnix CPalSynchronizationManager::GetInstance(); bool fSharedObject = (SharedObject == m_odObjectDomain); - _ASSERT_MSG((fSharedObject && (NULLSharedID == m_ptrWTLHead.shrid)) || + _ASSERT_MSG((fSharedObject && (NULL == m_ptrWTLHead.shrid)) || (!fSharedObject && (NULL == m_ptrWTLHead.ptr)), "Final Release on CSynchData with threads still in " "the waiting list\n"); @@ -1082,7 +1082,7 @@ namespace CorUnix bool fDelegatedSignaling = false; DWORD * pdwWaitState; DWORD dwObjIdx; - SharedID shridItem = NULLSharedID, shridNextItem = NULLSharedID; + SharedID shridItem = NULL, shridNextItem = NULL; WaitingThreadsListNode * pwtlnItem, * pwtlnNextItem; DWORD dwPid = gPID; CPalSynchronizationManager * pSynchManager = @@ -1400,7 +1400,7 @@ namespace CorUnix bool fSharedObject = (SharedObject == GetObjectDomain()); DWORD * pdwWaitState; DWORD dwObjIdx; - SharedID shridItem = NULLSharedID, shridNextItem = NULLSharedID; + SharedID shridItem = NULL, shridNextItem = NULL; WaitingThreadsListNode * pwtlnItem, * pwtlnNextItem; DWORD dwPid = gPID; CPalSynchronizationManager * pSynchManager = @@ -1893,14 +1893,14 @@ namespace CorUnix VALIDATEOBJECT(pwtlnNewNode); - pwtlnNewNode->ptrNext.shrid = NULLSharedID; + pwtlnNewNode->ptrNext.shrid = NULL; if (NULL == pwtlnCurrLast) { - _ASSERT_MSG(NULLSharedID == m_ptrWTLHead.shrid, + _ASSERT_MSG(NULL == m_ptrWTLHead.shrid, "Corrupted waiting list on shared CSynchData at " "{shrid=%p, p=%p}\n", m_shridThis, this); - pwtlnNewNode->ptrPrev.shrid = NULLSharedID; + pwtlnNewNode->ptrPrev.shrid = NULL; m_ptrWTLHead.shrid = shridNewNode; m_ptrWTLTail.shrid = shridNewNode; } diff --git a/src/pal/src/synchmgr/synchmanager.cpp b/src/pal/src/synchmgr/synchmanager.cpp index 73b5644..a683255 100644 --- a/src/pal/src/synchmgr/synchmanager.cpp +++ b/src/pal/src/synchmgr/synchmanager.cpp @@ -949,7 +949,7 @@ namespace CorUnix if (SharedObject == odObjectDomain) { SharedID shridSynchData = m_cacheSHRSynchData.Get(pthrCurrent); - if (NULLSharedID == shridSynchData) + if (NULL == shridSynchData) { ERROR("Unable to allocate shared memory\n"); return ERROR_NOT_ENOUGH_MEMORY; @@ -962,8 +962,8 @@ namespace CorUnix _ASSERT_MSG(NULL != psdSynchData, "Bad shared memory pointer\n"); // Initialize waiting list pointers - psdSynchData->SetWTLHeadShrPtr(NULLSharedID); - psdSynchData->SetWTLTailShrPtr(NULLSharedID); + psdSynchData->SetWTLHeadShrPtr(NULL); + psdSynchData->SetWTLTailShrPtr(NULL); // Store shared pointer to this object psdSynchData->SetSharedThis(shridSynchData); @@ -984,7 +984,7 @@ namespace CorUnix psdSynchData->SetWTLTailPtr(NULL); // Set shared this pointer to NULL - psdSynchData->SetSharedThis(NULLSharedID); + psdSynchData->SetSharedThis(NULL); *ppvSynchData = static_cast(psdSynchData); } @@ -2019,7 +2019,7 @@ namespace CorUnix if (SynchWorkerCmdRemoteSignal == swcWorkerCmd || SynchWorkerCmdDelegatedObjectSignaling == swcWorkerCmd) { - SharedID shridMarshaledId = NULLSharedID; + SharedID shridMarshaledId = NULL; TRACE("Received %s cmd\n", (swcWorkerCmd == SynchWorkerCmdRemoteSignal) ? @@ -2499,7 +2499,7 @@ namespace CorUnix WaitingThreadsListNode * pWLNode = SharedIDToTypePointer(WaitingThreadsListNode, shridWLNode); _ASSERT_MSG(gPID != pWLNode->dwProcessId, "WakeUpRemoteThread called on local thread\n"); - _ASSERT_MSG(NULLSharedID != shridWLNode, "NULL shared identifier\n"); + _ASSERT_MSG(NULL != shridWLNode, "NULL shared identifier\n"); _ASSERT_MSG(NULL != pWLNode, "Bad shared wait list node identifier (%p)\n", (VOID*)shridWLNode); _ASSERT_MSG(MsgSize <= PIPE_BUF, "Message too long [MsgSize=%d PIPE_BUF=%d]\n", MsgSize, (int)PIPE_BUF); @@ -2556,7 +2556,7 @@ namespace CorUnix SharedIDToTypePointer(CSynchData, shridSynchData); _ASSERT_MSG(gPID != dwTargetProcessId, " called on local thread\n"); - _ASSERT_MSG(NULLSharedID != shridSynchData, "NULL shared identifier\n"); + _ASSERT_MSG(NULL != shridSynchData, "NULL shared identifier\n"); _ASSERT_MSG(NULL != psdSynchData, "Bad shared SynchData identifier (%p)\n", (VOID*)shridSynchData); _ASSERT_MSG(MsgSize <= PIPE_BUF, "Message too long [MsgSize=%d PIPE_BUF=%d]\n", MsgSize, (int)PIPE_BUF); @@ -3737,7 +3737,7 @@ namespace CorUnix PAL_ERROR palError = NO_ERROR; CSynchData *psdLocal = reinterpret_cast(pvLocalSynchData); CSynchData *psdShared = NULL; - SharedID shridSynchData = NULLSharedID; + SharedID shridSynchData = NULL; SharedID *rgshridWTLNodes = NULL; CObjectType *pot = NULL; ULONG ulcWaitingThreads; @@ -3759,7 +3759,7 @@ namespace CorUnix // shridSynchData = m_cacheSHRSynchData.Get(pthrCurrent); - if (NULLSharedID == shridSynchData) + if (NULL == shridSynchData) { ERROR("Unable to allocate shared memory\n"); palError = ERROR_NOT_ENOUGH_MEMORY; @@ -3837,8 +3837,8 @@ namespace CorUnix // for the waiting threads // - psdShared->SetWTLHeadShrPtr(NULLSharedID); - psdShared->SetWTLTailShrPtr(NULLSharedID); + psdShared->SetWTLHeadShrPtr(NULL); + psdShared->SetWTLTailShrPtr(NULL); if (0 < ulcWaitingThreads) { @@ -4020,7 +4020,7 @@ namespace CorUnix CThreadSynchronizationInfo::CThreadSynchronizationInfo() : m_tsThreadState(TS_IDLE), - m_shridWaitAwakened(NULLSharedID), + m_shridWaitAwakened(NULL), m_lLocalSynchLockCount(0), m_lSharedSynchLockCount(0), m_ownedNamedMutexListHead(nullptr) @@ -4037,9 +4037,9 @@ namespace CorUnix CThreadSynchronizationInfo::~CThreadSynchronizationInfo() { DeleteCriticalSection(&m_ownedNamedMutexListLock); - if (NULLSharedID != m_shridWaitAwakened) + if (NULL != m_shridWaitAwakened) { - RawSharedObjectFree(m_shridWaitAwakened); + free(m_shridWaitAwakened); } } @@ -4091,9 +4091,8 @@ namespace CorUnix pthread_condattr_t attrs; pthread_condattr_t *attrsPtr = nullptr; - m_shridWaitAwakened = RawSharedObjectAlloc(sizeof(DWORD), - DefaultSharedPool); - if (NULLSharedID == m_shridWaitAwakened) + m_shridWaitAwakened = malloc(sizeof(DWORD)); + if (NULL == m_shridWaitAwakened) { ERROR("Fail allocating thread wait status shared object\n"); palErr = ERROR_NOT_ENOUGH_MEMORY; diff --git a/src/pal/src/synchmgr/synchmanager.hpp b/src/pal/src/synchmgr/synchmanager.hpp index 883d5b8..b0cc2e7 100644 --- a/src/pal/src/synchmgr/synchmanager.hpp +++ b/src/pal/src/synchmgr/synchmanager.hpp @@ -172,7 +172,7 @@ namespace CorUnix public: CSynchData() - : m_ulcWaitingThreads(0), m_shridThis(NULLSharedID), m_lRefCount(1), + : m_ulcWaitingThreads(0), m_shridThis(NULL), m_lRefCount(1), m_lSignalCount(0), m_lOwnershipCount(0), m_dwOwnerPid(0), m_dwOwnerTid(0), m_pOwnerThread(NULL), m_poolnOwnedObjectListNode(NULL), m_fAbandoned(false) -- 2.7.4