//------------------------------------------------------------------------------ // Function: ShbIpcAllocBuffer // // Description: Allocates memory for the shared buffers // // Parameters: // ulBufferSize_p size of the shared buffer to allocate // pszBufferId_p string containing the shared buffer identifier // ppShbInstance_p pointer to store the instance of this shared // buffer // pfShbNewCreated_p pointer to store the buffer creation flag // // Return: tShbError = error //------------------------------------------------------------------------------ tShbError ShbIpcAllocBuffer (ULONG ulBufferSize_p, const char* pszBufferID_p, tShbInstance* ppShbInstance_p, UINT* pfShbNewCreated_p) { tShbError ShbError; UINT uiBufferKey; BOOL fShbNewCreated; ULONG ulShMemSize; tShbMemHeader* pShbMemHeader; tShbMemInst* pShbMemInst = NULL; tShbInstance pShbInstance; ulShMemSize = ulBufferSize_p + sizeof(tShbMemHeader); //create Buffer Key uiBufferKey = ShbIpcCrc32GetCrc(pszBufferID_p); EPL_DBGLVL_SHB_TRACE("%s() Allocate %lu Bytes, sBufferID:%s BufferKey:%08x\n", __func__, ulShMemSize, pszBufferID_p, (key_t)uiBufferKey); //--------------------------------------------------------------- // (1) open an existing or create a new shared memory //--------------------------------------------------------------- // try to create shared memory if ((pShbMemHeader = ShbIpcFindMem(uiBufferKey)) == NULL) { fShbNewCreated = TRUE; if ((pShbMemHeader = ShbIpcAlloc(uiBufferKey, ulShMemSize)) == NULL) { //unable to create mem EPL_DBGLVL_ERROR_TRACE("%s() Shared memory allocation error!\n", __func__); ShbError = kShbOutOfMem; goto Exit; } else { EPL_DBGLVL_SHB_TRACE("%s() Shared memory allocated, Addr:%p Key:%08x size:%ld\n", __func__, (void *)pShbMemHeader, uiBufferKey, ulShMemSize); } } else { EPL_DBGLVL_SHB_TRACE("%s() Attached to shared memory, Addr:%p Key:%08x size:%ld\n", __func__, (void *)pShbMemHeader, uiBufferKey, ulShMemSize); fShbNewCreated = FALSE; } //--------------------------------------------------------------- // (2) setup or update header and management information //--------------------------------------------------------------- // allocate a memory block from process specific mempool to save // process local information to administrate/manage the shared buffer if ((pShbMemInst = (tShbMemInst*)ShbIpcAllocPrivateMem(sizeof(tShbMemInst))) == NULL) { EPL_DBGLVL_ERROR_TRACE("%s() Couldn't alloc private mem!\n", __func__); ShbError = kShbOutOfMem; goto Exit; } memset(pShbMemInst, 0, sizeof(tShbMemInst)); // reset complete header to default values pShbMemInst->m_SbiMagicID = SBI_MAGIC_ID; pShbMemInst->m_uiSharedMemId = uiBufferKey; strncpy(pShbMemInst->m_sBufId, pszBufferID_p, MAX_LEN_BUFFER_ID - 1); pShbMemInst->m_pfnSigHndlrNewData = NULL; pShbMemInst->m_fNewDataThreadStarted = FALSE; pShbMemInst->m_ulTimeOutMsJobReady = 0; pShbMemInst->m_pfnSigHndlrJobReady = NULL; pShbMemInst->m_pShbMemHeader = pShbMemHeader; pShbMemInst->m_fThreadTermFlag = FALSE; ShbError = kShbOk; if (fShbNewCreated) { memset (pShbMemHeader, 0, sizeof(tShbMemHeader)); // this process was the first who wanted to use the shared memory, // so a new shared memory was created // -> setup new header information inside the shared memory region // itself pShbMemHeader->m_ulShMemSize = ulShMemSize; pShbMemHeader->m_ulRefCount = 1; pShbMemHeader->m_uiBufferKey = uiBufferKey; //create semaphores for buffer access and signal new data if ((pShbMemHeader->m_mutexBuffAccess = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE)) == NULL) { ShbError = kShbOutOfMem; goto Exit; } if ((pShbMemHeader->m_semNewData = semCCreate(SEM_Q_PRIORITY, 0)) == NULL) { ShbError = kShbOutOfMem; goto Exit; } if ((pShbMemHeader->m_semStopSignalingNewData = semCCreate(SEM_Q_PRIORITY, 0)) == NULL) { ShbError = kShbOutOfMem; goto Exit; } if ((pShbMemHeader->m_semJobReady = semCCreate(SEM_Q_PRIORITY, 0)) == NULL) { ShbError = kShbOutOfMem; goto Exit; } } else { // any other process has created the shared memory and this // process has only attached to it // -> check and update existing header information inside the // shared memory region itself if (pShbMemHeader->m_uiBufferKey != uiBufferKey) { EPL_DBGLVL_ERROR_TRACE("%s() Shared Mem mismatch buffer key %x:%x!\n", __func__, uiBufferKey, pShbMemHeader->m_uiBufferKey); ShbError = kShbOpenMismatch; goto Exit; } //TRACEX("%s() Check mem size is:%ld should be:%ld \n", __func__, // pShbMemHeader->m_ulShMemSize, ulShMemSize); if (pShbMemHeader->m_ulShMemSize != ulShMemSize) { EPL_DBGLVL_ERROR_TRACE("%s() Shared Mem mismatch size! %ld:%ld\n", __func__, ulShMemSize, pShbMemHeader->m_ulShMemSize); ShbError = kShbOpenMismatch; goto Exit; } pShbMemHeader->m_ulRefCount++; } Exit: if (ShbError != kShbOk) { EPL_DBGLVL_ERROR_TRACE("%s() allocating shared buf failed!\n (%d)", __func__, ShbError); if (pShbMemInst != NULL) { ShbIpcReleasePrivateMem (pShbMemInst); } if ((pShbMemHeader != NULL) && (fShbNewCreated)) { ShbIpcFree(uiBufferKey); } } pShbInstance = (tShbInstance*)pShbMemInst; *pfShbNewCreated_p = fShbNewCreated; *ppShbInstance_p = pShbInstance; return (ShbError); }
tShbError ShbIpcAllocBuffer ( unsigned long ulBufferSize_p, const char* pszBufferID_p, tShbInstance* ppShbInstance_p, unsigned int* pfShbNewCreated_p) { tShbError ShbError; int iBufferId=0; unsigned long ulCrc32=0; unsigned int uiFirstProcess=0; unsigned long ulShMemSize; tShbMemHeader* pShbMemHeader; tShbMemInst* pShbMemInst=NULL; tShbInstance pShbInstance; unsigned int fShMemNewCreated=FALSE; void *pSharedMem=NULL; struct sShbMemTable *psMemTableElement; DEBUG_LVL_29_TRACE0("ShbIpcAllocBuffer \n"); ulShMemSize = ulBufferSize_p + sizeof(tShbMemHeader); //create Buffer ID #ifndef CONFIG_CRC32 { unsigned long aulCrcTable[256]; ShbIpcCrc32GenTable(aulCrcTable); ulCrc32 = ShbIpcCrc32GetCrc(pszBufferID_p, aulCrcTable); } #else ulCrc32 = crc32(0xFFFFFFFF, pszBufferID_p, strlen(pszBufferID_p)); #endif iBufferId=ulCrc32; DEBUG_LVL_29_TRACE2("ShbIpcAllocBuffer BufferSize:%d sizeof(tShb..):%d\n",ulBufferSize_p,sizeof(tShbMemHeader)); DEBUG_LVL_29_TRACE2("ShbIpcAllocBuffer BufferId:%d MemSize:%d\n",iBufferId,ulShMemSize); //--------------------------------------------------------------- // (1) open an existing or create a new shared memory //--------------------------------------------------------------- //test if buffer already exists if (ShbIpcFindListElement(iBufferId, &psMemTableElement) == 0) { //Buffer already exists fShMemNewCreated=FALSE; pSharedMem = psMemTableElement->m_pBuffer; DEBUG_LVL_29_TRACE1("ShbIpcAllocBuffer attach Buffer at:%p Id:%d\n",pSharedMem); uiFirstProcess=1; } else { //create new Buffer fShMemNewCreated = TRUE; uiFirstProcess=0; pSharedMem = kmalloc(ulShMemSize,GFP_KERNEL); DEBUG_LVL_29_TRACE2("ShbIpcAllocBuffer Create New Buffer at:%p Id:%d\n",pSharedMem,iBufferId); if (pSharedMem == NULL) { //unable to create mem ShbError = kShbOutOfMem; goto Exit; } DEBUG_LVL_29_TRACE0("ShbIpcAllocBuffer create semas\n"); // append Element to Mem Table psMemTableElement = kmalloc(sizeof(struct sShbMemTable),GFP_KERNEL); psMemTableElement->m_iBufferId = iBufferId; psMemTableElement->m_pBuffer = pSharedMem; psMemTableElement->m_psNextMemTableElement = NULL; ShbIpcAppendListElement (psMemTableElement); } DEBUG_LVL_29_TRACE0("ShbIpcAllocBuffer update header\n"); //update header pShbMemHeader = (tShbMemHeader*)pSharedMem; DEBUG_LVL_29_TRACE1("ShbIpcAllocBuffer 0 pShbMemHeader->m_ulShMemSize: %d\n",pShbMemHeader->m_ulShMemSize); // allocate a memory block from process specific mempool to save // process local information to administrate/manage the shared buffer DEBUG_LVL_29_TRACE0("ShbIpcAllocBuffer alloc private mem\n"); pShbMemInst = (tShbMemInst*) ShbIpcAllocPrivateMem (sizeof(tShbMemInst)); if (pShbMemInst == NULL) { ShbError = kShbOutOfMem; goto Exit; } // reset complete header to default values //pShbMemInst->m_SbiMagicID = SBI_MAGIC_ID; // pShbMemInst->m_pSharedMem = pSharedMem; pShbMemInst->m_tThreadNewDataId = INVALID_ID; pShbMemInst->m_tThreadJobReadyId = INVALID_ID; pShbMemInst->m_pfnSigHndlrNewData = NULL; pShbMemInst->m_ulTimeOutMsJobReady = 0; pShbMemInst->m_pfnSigHndlrJobReady = NULL; sema_init(&pShbMemInst->m_SemaphoreStopThreadJobReady, 1); pShbMemInst->m_pShbMemHeader = pShbMemHeader; ShbError = kShbOk; if ( fShMemNewCreated ) { // this process was the first who wanted to use the shared memory, // so a new shared memory was created // -> setup new header information inside the shared memory region // itself pShbMemHeader->m_ulShMemSize = ulShMemSize; pShbMemHeader->m_ulRefCount = 1; pShbMemHeader->m_iBufferId=iBufferId; pShbMemHeader->m_pShbInstMaster = NULL; // initialize spinlock spin_lock_init(&pShbMemHeader->m_SpinlockBuffAccess); // initialize wait queues init_waitqueue_head(&pShbMemHeader->m_WaitQueueNewData); init_waitqueue_head(&pShbMemHeader->m_WaitQueueJobReady); } else { // any other process has created the shared memory and this // process only has to attach to it // -> check and update existing header information inside the // shared memory region itself if (pShbMemHeader->m_ulShMemSize != ulShMemSize) { ShbError = kShbOpenMismatch; goto Exit; } pShbMemHeader->m_ulRefCount++; } Exit: pShbInstance = (tShbInstance*)pShbMemInst; *pfShbNewCreated_p = fShMemNewCreated; *ppShbInstance_p = pShbInstance; return (ShbError); }
tShbError ShbIpcAllocBuffer ( unsigned long ulBufferSize_p, const char* pszBufferID_p, tShbInstance* ppShbInstance_p, unsigned int* pfShbNewCreated_p) { HANDLE hSharedMem; LPVOID pSharedMem; unsigned long ulShMemSize; tShbMemInst* pShbMemInst = NULL; tShbMemHeader* pShbMemHeader; tShbInstance pShbInstance; unsigned int fShMemNewCreated; const char* pszObjectName; HANDLE hMutexBuffAccess; HANDLE hEventNewData; HANDLE hEventJobReady; tShbError ShbError; ulShMemSize = ulBufferSize_p + sizeof(tShbMemHeader); pSharedMem = NULL; pShbInstance = NULL; fShMemNewCreated = FALSE; ShbError = kShbOk; //--------------------------------------------------------------- // (1) open an existing or create a new shared memory //--------------------------------------------------------------- // try to open an already existing shared memory // (created by an another process) hSharedMem = OpenFileMapping (FILE_MAP_ALL_ACCESS, // DWORD dwDesiredAccess FALSE, // BOOL bInheritHandle pszBufferID_p); // LPCTSTR lpName if (hSharedMem != NULL) { // a shared memory already exists fShMemNewCreated = FALSE; } else { // it seams that this process is the first who wants to use the // shared memory, so it has to create a new shared memory hSharedMem = CreateFileMapping(INVALID_HANDLE_VALUE,// HANDLE hFile NULL, // LPSECURITY_ATTRIBUTES lpAttributes PAGE_READWRITE, // DWORD flProtect 0, // DWORD dwMaximumSizeHigh ulShMemSize, // DWORD dwMaximumSizeLow pszBufferID_p); // LPCTSTR lpName fShMemNewCreated = TRUE; } if (hSharedMem == NULL) { ShbError = kShbOutOfMem; goto Exit; } //--------------------------------------------------------------- // (2) get the pointer to the shared memory //--------------------------------------------------------------- pSharedMem = MapViewOfFile (hSharedMem, // HANDLE hFileMappingObject FILE_MAP_ALL_ACCESS, // DWORD dwDesiredAccess, 0, // DWORD dwFileOffsetHigh, 0, // DWORD dwFileOffsetLow, ulShMemSize); // SIZE_T dwNumberOfBytesToMap if (pSharedMem == NULL) { ShbError = kShbOutOfMem; goto Exit; } //--------------------------------------------------------------- // (3) setup or update header and management information //--------------------------------------------------------------- pShbMemHeader = (tShbMemHeader*)pSharedMem; // allocate a memory block from process specific mempool to save // process local information to administrate/manage the shared buffer pShbMemInst = (tShbMemInst*) ShbIpcAllocPrivateMem (sizeof(tShbMemInst)); if (pShbMemInst == NULL) { ShbError = kShbOutOfMem; goto Exit; } // reset complete header to default values pShbMemInst->m_SbiMagicID = SBI_MAGIC_ID; pShbMemInst->m_hSharedMem = hSharedMem; pShbMemInst->m_hMutexBuffAccess = INVALID_HANDLE_VALUE; pShbMemInst->m_hThreadNewData = INVALID_HANDLE_VALUE; pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA] = INVALID_HANDLE_VALUE; pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU] = INVALID_HANDLE_VALUE; pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] = INVALID_HANDLE_VALUE; pShbMemInst->m_pfnSigHndlrNewData = NULL; pShbMemInst->m_hThreadJobReady = INVALID_HANDLE_VALUE; pShbMemInst->m_hEventJobReady = INVALID_HANDLE_VALUE; pShbMemInst->m_ulTimeOutMsJobReady = 0; pShbMemInst->m_pfnSigHndlrJobReady = NULL; pShbMemInst->m_pShbMemHeader = pShbMemHeader; #ifndef NDEBUG { pShbMemInst->m_ulThreadIDNewData = 0; pShbMemInst->m_ulThreadIDJobReady = 0; } #endif // create mutex for buffer access pszObjectName = ShbIpcGetUniformObjectName (NAME_MUTEX_BUFF_ACCESS, pszBufferID_p, TRUE); hMutexBuffAccess = CreateMutex (NULL, // LPSECURITY_ATTRIBUTES lpMutexAttributes FALSE, // BOOL bInitialOwner pszObjectName); // LPCTSTR lpName pShbMemInst->m_hMutexBuffAccess = hMutexBuffAccess; ASSERT(pShbMemInst->m_hMutexBuffAccess != NULL); // The EventNewData is used for signaling of new data after a write // operation (SetEvent) as well as for waiting for new data on the // reader side (WaitForMultipleObjects). Because it's not known if // this process will be read or write data, the event will be // always created here. pszObjectName = ShbIpcGetUniformObjectName (NAME_EVENT_NEW_DATA, pszBufferID_p, TRUE); hEventNewData = CreateEvent (NULL, // LPSECURITY_ATTRIBUTES lpEventAttributes FALSE, // BOOL bManualReset FALSE, // BOOL bInitialState pszObjectName); // LPCTSTR lpName pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA] = hEventNewData; ASSERT(pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA] != NULL); // The EventJobReady is used for signaling that a job is done (SetEvent) // as well as for waiting for finishing of a job (WaitForMultipleObjects). // Because it's not known if this process will signal or wait, the event // will be always created here. pszObjectName = ShbIpcGetUniformObjectName (NAME_EVENT_JOB_READY, pszBufferID_p, TRUE); hEventJobReady = CreateEvent (NULL, // LPSECURITY_ATTRIBUTES lpEventAttributes FALSE, // BOOL bManualReset FALSE, // BOOL bInitialState pszObjectName); // LPCTSTR lpName pShbMemInst->m_hEventJobReady = hEventJobReady; ASSERT(pShbMemInst->m_hEventJobReady != NULL); if ( fShMemNewCreated ) { // this process was the first who wanted to use the shared memory, // so a new shared memory was created // -> setup new header information inside the shared memory region // itself pShbMemHeader->m_SbhMagicID = SBH_MAGIC_ID; pShbMemHeader->m_ulShMemSize = ulShMemSize; pShbMemHeader->m_ulRefCount = 1; pShbMemHeader->m_pShbInstMaster = NULL; strcpy_s (pShbMemHeader->m_szBufferID, sizeof(pShbMemHeader->m_szBufferID), pszBufferID_p); #ifndef NDEBUG { pShbMemHeader->m_ulOwnerProcID = GetCurrentProcessId(); } #endif } else { // any other process has created the shared memory and this // process has only attached to it // -> check and update existing header information inside the // shared memory region itself if (pShbMemHeader->m_ulShMemSize != ulShMemSize) { ShbError = kShbOpenMismatch; goto Exit; } #ifndef NDEBUG { if ( strncmp(pShbMemHeader->m_szBufferID, pszBufferID_p, sizeof(pShbMemHeader->m_szBufferID)-1) ) { ShbError = kShbOpenMismatch; goto Exit; } } #endif pShbMemHeader->m_ulRefCount++; } // set abstarct "handle" for returning to application pShbInstance = (tShbInstance*)pShbMemInst; Exit: if (ShbError != kShbOk) { if (pShbMemInst != NULL) { ShbIpcReleasePrivateMem (pShbMemInst); } if (pSharedMem != NULL) { UnmapViewOfFile (pSharedMem); } if (hSharedMem != NULL) { CloseHandle (hSharedMem); } } *pfShbNewCreated_p = fShMemNewCreated; *ppShbInstance_p = pShbInstance; return (ShbError); }