INLINE_FUNCTION tShbError ShbIpcSignalJobReady ( tShbInstance pShbInstance_p) { tShbMemInst* pShbMemInst; HANDLE hEventJobReady; BOOL fRes; // TRACE("\nShbIpcSignalJobReady(): enter\n"); if (pShbInstance_p == NULL) { return (kShbInvalidArg); } pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p); ASSERT(pShbMemInst->m_hEventJobReady != INVALID_HANDLE_VALUE); hEventJobReady = pShbMemInst->m_hEventJobReady; if (hEventJobReady != INVALID_HANDLE_VALUE) { fRes = SetEvent (hEventJobReady); // TRACE("\nShbIpcSignalJobReady(): EventJobReady set (Result=%d)\n", (int)fRes); ASSERT( fRes ); } // TRACE("\nShbIpcSignalJobReady(): leave\n"); return (kShbOk); }
//------------------------------------------------------------------------------ // Function: ShbIpcThreadSignalNewData // // Description: Thread for new data signaling // // Parameters: // pvThreadParam_p user parameters for thread // // Return: void * thread exit value (not used) //------------------------------------------------------------------------------ int ShbIpcThreadSignalNewData (int pvThreadParam_p) { tShbInstance pShbInstance; tShbMemInst* pShbMemInst; tShbMemHeader* pShbMemHeader; INT iRetVal; /* thread parameter contains pointer to shared memory */ pShbInstance = (tShbMemInst*)pvThreadParam_p; pShbMemInst = ShbIpcGetShbMemInst (pShbInstance); pShbMemHeader = ShbIpcGetShbMemHeader (pShbInstance); /* signal that thread is running */ pShbMemInst->m_fNewDataThreadStarted = TRUE; do { if ((iRetVal = semTake(pShbMemHeader->m_semNewData, TIMEOUT_CANCEL_THREAD)) == OK) { //check terminate flag if (!pShbMemInst->m_fThreadTermFlag) { pShbMemInst->m_pfnSigHndlrNewData(pShbInstance); } } } while(!pShbMemInst->m_fThreadTermFlag); //set sem thread terminated pShbMemInst->m_fNewDataThreadStarted = FALSE; semGive(pShbMemHeader->m_semStopSignalingNewData); return 0; }
INLINE_FUNCTION tShbError ShbIpcStartSignalingJobReady ( tShbInstance pShbInstance_p, unsigned long ulTimeOutMs_p, tSigHndlrJobReady pfnSignalHandlerJobReady_p) { tShbMemInst* pShbMemInst; tShbMemHeader* pShbMemHeader; tShbError ShbError; if ((pShbInstance_p == NULL) || (pfnSignalHandlerJobReady_p == NULL)) { return (kShbInvalidArg); } pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p); pShbMemHeader = ShbIpcGetShbMemHeader (pShbMemInst); ShbError = kShbOk; if ((pShbMemInst->m_tThreadJobReadyId != INVALID_ID) || (pShbMemInst->m_pfnSigHndlrJobReady != NULL)) { ShbError = kShbAlreadySignaling; goto Exit; } pShbMemInst->m_ulTimeOutMsJobReady = ulTimeOutMs_p; pShbMemInst->m_pfnSigHndlrJobReady = pfnSignalHandlerJobReady_p; pShbMemHeader->m_fJobReady = FALSE; //create thread for signalling new data pShbMemInst->m_tThreadJobReadyId = kthread_run(ShbIpcThreadSignalJobReady, pShbInstance_p, "ShbJR%p", pShbInstance_p); Exit: return ShbError; }
INLINE_FUNCTION tShbError ShbIpcLeaveAtomicSection ( tShbInstance pShbInstance_p) { tShbMemInst* pShbMemInst; HANDLE hMutexBuffAccess; BOOL fRes; tShbError ShbError; if (pShbInstance_p == NULL) { return (kShbInvalidArg); } pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p); ShbError = kShbOk; hMutexBuffAccess = pShbMemInst->m_hMutexBuffAccess; if (hMutexBuffAccess != INVALID_HANDLE_VALUE) { fRes = ReleaseMutex (hMutexBuffAccess); ASSERT( fRes ); } else { ShbError = kShbBufferInvalid; } return (ShbError); }
//------------------------------------------------------------------------------ // Function: ShbIpcEnterAtomicSection // // Description: Enter atomic section for Shared Buffer access // // Parameters: pShbInstance_p pointer to shared buffer instance // // Return: tShbError = error code //------------------------------------------------------------------------------ tShbError ShbIpcEnterAtomicSection (tShbInstance pShbInstance_p) { tShbMemInst *pShbMemInst; tShbMemHeader *pShbMemHeader; tShbError ShbError; struct timespec curTime, timeout; if (pShbInstance_p == NULL) { return (kShbInvalidArg); } pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p); pShbMemHeader = ShbIpcGetShbMemHeader (pShbMemInst); clock_gettime(CLOCK_REALTIME, &curTime); timeout.tv_sec = 0; timeout.tv_nsec = TIMEOUT_ENTER_ATOMIC * 1000; timespecadd(&timeout, &curTime); if (pthread_mutex_timedlock(&pShbMemHeader->m_mutexBuffAccess, &timeout) == 0) { ShbError = kShbOk; } else { ShbError = kShbBufferInvalid; } return (ShbError); }
//------------------------------------------------------------------------------ // Function: ShbIpcSignalNewData // // Description: Signal new data (called from writing process) // // Parameters: pShbInstance_p pointer to shared buffer instance // // Return: tShbError = error code //------------------------------------------------------------------------------ tShbError ShbIpcSignalNewData(tShbInstance pShbInstance_p) { tShbMemInst* pShbMemInst; tShbMemHeader* pShbMemHeader; tShbError ShbError; //TRACEX("%s() pShbInstance_p=%p\n", __func__, pShbInstance_p); if (pShbInstance_p == NULL) { //TRACEX("%s() Invalid instance!\n", __func__); return (kShbInvalidArg); } pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p); pShbMemHeader = ShbIpcGetShbMemHeader (pShbMemInst); ShbError = kShbOk; //set semaphore if (semGive(pShbMemHeader->m_semNewData) < 0) { EPL_DBGLVL_ERROR_TRACE("%s() sem_post failed! (%s)\n", __func__, strerror(errno)); } /* if this shared buffer is connected to a master buffer, signal the * data also to the master buffer. */ if (pShbMemHeader->m_pShbInstMaster != NULL) { return ShbIpcSignalNewData(pShbMemHeader->m_pShbInstMaster); } return ShbError; }
INLINE_FUNCTION tShbError ShbIpcStopSignalingNewData ( tShbInstance pShbInstance_p) { tShbMemInst* pShbMemInst; tShbMemHeader* pShbMemHeader; tShbError ShbError; DEBUG_LVL_29_TRACE0("------->ShbIpcStopSignalingNewData\n"); if (pShbInstance_p == NULL) { return (kShbInvalidArg); } ShbError = kShbOk; pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p); pShbMemHeader = ShbIpcGetShbMemHeader (pShbMemInst); DEBUG_LVL_26_TRACE2("ShbIpcStopSignalingNewData(%p) pfnSignHndlrNewData=%p\n", pShbInstance_p, pShbMemInst->m_pfnSigHndlrNewData); if (pShbMemInst->m_pfnSigHndlrNewData != NULL) { // signal handler was set before kthread_stop(pShbMemInst->m_tThreadNewDataId); pShbMemInst->m_pfnSigHndlrNewData = NULL; pShbMemInst->m_tThreadNewDataId = INVALID_ID; } return ShbError; }
//------------------------------------------------------------------------------ // Function: ShbIpcEnterAtomicSection // // Description: Enter atomic section for Shared Buffer access // // Parameters: pShbInstance_p pointer to shared buffer instance // // Return: tShbError = error code //------------------------------------------------------------------------------ tShbError ShbIpcEnterAtomicSection (tShbInstance pShbInstance_p) { tShbMemInst *pShbMemInst; tShbMemHeader *pShbMemHeader; tShbError ShbError; if (pShbInstance_p == NULL) { return (kShbInvalidArg); } pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p); pShbMemHeader = ShbIpcGetShbMemHeader (pShbMemInst); if (semTake (pShbMemHeader->m_mutexBuffAccess, TIMEOUT_ENTER_ATOMIC) == OK) { ShbError = kShbOk; } else { ShbError = kShbBufferInvalid; } return (ShbError); }
int ShbIpcThreadSignalJobReady (void *pvThreadParam_p) { tShbInstance pShbInstance; tShbMemInst* pShbMemInst; tShbMemHeader* pShbMemHeader; long lTimeOutJiffies; int iRetVal=-1; pShbInstance = (tShbMemInst*)pvThreadParam_p; pShbMemInst = ShbIpcGetShbMemInst (pShbInstance); pShbMemHeader = ShbIpcGetShbMemHeader (pShbMemInst); DEBUG_LVL_29_TRACE0("ShbIpcThreadSignalJobReady wait for job ready Sem\n"); if (pShbMemInst->m_ulTimeOutMsJobReady != 0) { lTimeOutJiffies = (long) pShbMemInst->m_ulTimeOutMsJobReady / (1000 / HZ); if (lTimeOutJiffies <= 0) { // wait at least 1 jiffy lTimeOutJiffies = 1; } //wait for job ready semaphore iRetVal = wait_event_timeout(pShbMemHeader->m_WaitQueueJobReady, kthread_should_stop() || (pShbMemHeader->m_fJobReady != FALSE), lTimeOutJiffies); } else { //wait for job ready semaphore wait_event_interruptible(pShbMemHeader->m_WaitQueueJobReady, kthread_should_stop() || (pShbMemHeader->m_fJobReady != FALSE)); } if (pShbMemInst->m_pfnSigHndlrJobReady != NULL) { //call Handler pShbMemInst->m_pfnSigHndlrJobReady(pShbInstance, !pShbMemHeader->m_fJobReady); } pShbMemInst->m_pfnSigHndlrJobReady = NULL; if (down_trylock(&pShbMemInst->m_SemaphoreStopThreadJobReady)) { // lock failed wait_event_interruptible(pShbMemHeader->m_WaitQueueJobReady, kthread_should_stop()); pShbMemInst->m_tThreadJobReadyId = INVALID_ID; } else { pShbMemInst->m_tThreadJobReadyId = INVALID_ID; up(&pShbMemInst->m_SemaphoreStopThreadJobReady); } DEBUG_LVL_29_TRACE0("ShbIpcThreadSignalJobReady terminated\n"); return 0; }
//------------------------------------------------------------------------------ // Function: ShbIpcGetShbMemHeader // // Description: Get pointer to shared memory header // // Parameters: // pShbInstance_p pointer to shared buffer instance // // Return: tShbMemHeader* pointer to shared memory header //------------------------------------------------------------------------------ static inline tShbMemHeader* ShbIpcGetShbMemHeader (tShbInstance pShbInstance_p) { tShbMemInst* pShbMemInst; tShbMemHeader* pShbMemHeader; pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p); pShbMemHeader = pShbMemInst->m_pShbMemHeader; return (pShbMemHeader); }
//------------------------------------------------------------------------------ // Function: ShbIpcStartSignalingNewData // // Description: Start signaling of new data (called from reading process) // // Parameters: pShbInstance_p pointer to shared buffer instance // pfnSignalHandlerNewData_p pointer to master buffer instance // // Return: tShbError = error code //------------------------------------------------------------------------------ tShbError ShbIpcStartSignalingNewData(tShbInstance pShbInstance_p, tSigHndlrNewData pfnSignalHandlerNewData_p, tShbPriority ShbPriority_p) { tShbMemInst* pShbMemInst; tShbMemHeader* pShbMemHeader; tShbError ShbError; INT iSchedPriority; if ((pShbInstance_p == NULL) || (pfnSignalHandlerNewData_p == NULL)) { return (kShbInvalidArg); } pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p); pShbMemHeader = ShbIpcGetShbMemHeader (pShbInstance_p); ShbError = kShbOk; if ((pShbMemInst->m_fNewDataThreadStarted) || (pShbMemInst->m_pfnSigHndlrNewData != NULL)) { ShbError = kShbAlreadySignaling; EPL_DBGLVL_ERROR_TRACE("%s() Thread already started!\n", __func__); goto Exit; } pShbMemInst->m_pfnSigHndlrNewData = pfnSignalHandlerNewData_p; iSchedPriority = EPL_TASK_PRIORITY_SHB; switch (ShbPriority_p) { case kShbPriorityLow: iSchedPriority += 5; break; case kShbPriorityNormal: iSchedPriority += 0; break; case kShbPriorityHigh: iSchedPriority -= 5; break; } if ((pShbMemInst->m_tThreadNewDataId = taskSpawn ("tShbIpc", iSchedPriority, 0, EPL_TASK_STACK_SIZE, &ShbIpcThreadSignalNewData, (int)pShbInstance_p, 0, 0, 0, 0, 0, 0, 0, 0, 0)) == ERROR) { pShbMemInst->m_pfnSigHndlrNewData = NULL; ShbError = kShbInvalidSigHndlr; goto Exit; } Exit: return (ShbError); }
INLINE_FUNCTION tShbError ShbIpcStartSignalingNewData ( tShbInstance pShbInstance_p, tSigHndlrNewData pfnSignalHandlerNewData_p, tShbPriority ShbPriority_p) { tShbMemInst* pShbMemInst; tShbMemHeader* pShbMemHeader; tShbError ShbError; DEBUG_LVL_29_TRACE0("------->ShbIpcStartSignalingNewData\n"); if ((pShbInstance_p == NULL) || (pfnSignalHandlerNewData_p == NULL)) { return (kShbInvalidArg); } pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p); pShbMemHeader = ShbIpcGetShbMemHeader (pShbMemInst); ShbError = kShbOk; if ((pShbMemInst->m_tThreadNewDataId != INVALID_ID) || (pShbMemInst->m_pfnSigHndlrNewData != NULL)) { ShbError = kShbAlreadySignaling; goto Exit; } DEBUG_LVL_26_TRACE2("ShbIpcStartSignalingNewData(%p) m_pfnSigHndlrNewData = %p\n", pShbInstance_p, pfnSignalHandlerNewData_p); pShbMemInst->m_pfnSigHndlrNewData = pfnSignalHandlerNewData_p; pShbMemHeader->m_fNewData = FALSE; switch (ShbPriority_p) { case kShbPriorityLow: pShbMemInst->m_lThreadNewDataNice = -2; break; case kShbPriorityNormal: pShbMemInst->m_lThreadNewDataNice = -9; break; case kShbPriorityHigh: pShbMemInst->m_lThreadNewDataNice = -20; break; } //create thread for signalling new data pShbMemInst->m_tThreadNewDataId = kthread_run(ShbIpcThreadSignalNewData, pShbInstance_p, "ShbND%p", pShbInstance_p); Exit: return ShbError; }
INLINE_FUNCTION tShbError ShbIpcStartSignalingNewData ( tShbInstance pShbInstance_p, tSigHndlrNewData pfnSignalHandlerNewData_p, tShbPriority ShbPriority_p) { tShbMemInst* pShbMemInst; tShbMemInst** ppShbMemInst; tShbMemHeader* pShbMemHeader; tShbError ShbError; DEBUG_LVL_29_TRACE("------->ShbIpcStartSignalingNewData\n"); if (ShbTgtIsInterruptContext()) { return (kShbInterruptContextNotAllowed); } if ((pShbInstance_p == NULL) || (pfnSignalHandlerNewData_p == NULL)) { return (kShbInvalidArg); } pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p); pShbMemHeader = ShbIpcGetShbMemHeader(pShbMemInst); ShbError = kShbOk; if (pShbMemInst->m_pfnSigHndlrNewData != NULL) { ShbError = kShbAlreadySignaling; goto Exit; } DEBUG_LVL_26_TRACE("ShbIpcStartSignalingNewData(%p) m_pfnSigHndlrNewData = %p\n", pShbInstance_p, pfnSignalHandlerNewData_p); pShbMemInst->m_pfnSigHndlrNewData = pfnSignalHandlerNewData_p; pShbMemInst->m_PriorityNewData = ShbPriority_p; pShbMemHeader->m_fNewData = FALSE; // insert ShbMemInst into NewData process list // higher priority entries first ppShbMemInst = &pShbIpcProcessListNewDataFirst_g; while (*ppShbMemInst != NULL) { if ((*ppShbMemInst)->m_PriorityNewData < pShbMemInst->m_PriorityNewData) { break; } ppShbMemInst = &(*ppShbMemInst)->m_pProcessListNewDataNext; } pShbMemInst->m_pProcessListNewDataNext = *ppShbMemInst; *ppShbMemInst = pShbMemInst; Exit: return ShbError; }
//------------------------------------------------------------------------------ // Function: ShbIpcThreadSignalJobReady // // Description: Thread for new data Job Ready signaling // // Parameters: // pvThreadParam_p user parameters for thread // // Return: void * thread exit value (not used) //------------------------------------------------------------------------------ void *ShbIpcThreadSignalJobReady (void *pvThreadParam_p) { tShbInstance pShbInstance; tShbMemInst *pShbMemInst; tShbMemHeader* pShbMemHeader; DWORD ulTimeOut; INT iRetVal; UINT fTimeOut; struct timespec timeout; EPL_DBGLVL_SHB_TRACE2("%s(): ThreadId:%ld\n", __func__, syscall(SYS_gettid)); pShbInstance = (tShbMemInst*)pvThreadParam_p; pShbMemInst = ShbIpcGetShbMemInst (pShbInstance); pShbMemHeader = ShbIpcGetShbMemHeader (pShbInstance); pShbMemInst->m_fJobReadyThreadStarted = TRUE; if (pShbMemInst->m_ulTimeOutMsJobReady != 0) { ulTimeOut = pShbMemInst->m_ulTimeOutMsJobReady; clock_gettime(CLOCK_REALTIME, &timeout); timeout.tv_sec += ulTimeOut; iRetVal = sem_timedwait(&pShbMemHeader->m_semJobReady, &timeout); } else { iRetVal = sem_wait(&pShbMemHeader->m_semJobReady); } if (iRetVal == 0) { fTimeOut = FALSE; } else { /* timeout or error */ fTimeOut = TRUE; } if (pShbMemInst->m_pfnSigHndlrJobReady != NULL) { //call Handler pShbMemInst->m_pfnSigHndlrJobReady(pShbInstance, fTimeOut); } pShbMemInst->m_pfnSigHndlrJobReady = NULL; pShbMemInst->m_fJobReadyThreadStarted = FALSE; return NULL; }
INLINE_FUNCTION tShbError ShbIpcStopSignalingNewData ( tShbInstance pShbInstance_p) { tShbMemInst* pShbMemInst; tShbMemInst** ppShbMemInst; tShbMemHeader* pShbMemHeader; tShbError ShbError; DEBUG_LVL_29_TRACE("------->ShbIpcStopSignalingNewData\n"); if (ShbTgtIsInterruptContext()) { return (kShbInterruptContextNotAllowed); } if (pShbInstance_p == NULL) { return (kShbInvalidArg); } ShbError = kShbOk; pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p); pShbMemHeader = ShbIpcGetShbMemHeader (pShbMemInst); DEBUG_LVL_26_TRACE("ShbIpcStopSignalingNewData(%p) pfnSignHndlrNewData=%p\n", pShbInstance_p, pShbMemInst->m_pfnSigHndlrNewData); if (pShbMemInst->m_pfnSigHndlrNewData != NULL) { // signal handler was set before // remove pShbMemInst from NewData process list ShbError = kShbInvalidSigHndlr; ppShbMemInst = &pShbIpcProcessListNewDataFirst_g; while (*ppShbMemInst != NULL) { if (*ppShbMemInst == pShbMemInst) { *ppShbMemInst = pShbMemInst->m_pProcessListNewDataNext; pShbMemInst->m_pProcessListNewDataNext = NULL; pShbMemInst->m_pfnSigHndlrNewData = NULL; if (ppShbIpcProcessListNewDataCurrent_g == &pShbMemInst->m_pProcessListNewDataNext) { ppShbIpcProcessListNewDataCurrent_g = ppShbMemInst; } ShbError = kShbOk; break; } ppShbMemInst = &(*ppShbMemInst)->m_pProcessListNewDataNext; } } return ShbError; }
//------------------------------------------------------------------------------ // Function: ShbIpcThreadSignalNewData // // Description: Thread for new data signaling // // Parameters: // pvThreadParam_p user parameters for thread // // Return: void * thread exit value (not used) //------------------------------------------------------------------------------ void *ShbIpcThreadSignalNewData (void *pvThreadParam_p) { tShbInstance pShbInstance; tShbMemInst* pShbMemInst; tShbMemHeader* pShbMemHeader; sem_t* pSemNewData; sem_t* pSemStopSignalingNewData; struct timespec curTime, timeout; INT iRetVal; EPL_DBGLVL_SHB_TRACE2("%s(): ThreadId:%ld\n", __func__, syscall(SYS_gettid)); /* thread parameter contains pointer to shared memory */ pShbInstance = (tShbMemInst*)pvThreadParam_p; pShbMemInst = ShbIpcGetShbMemInst (pShbInstance); pShbMemHeader = ShbIpcGetShbMemHeader (pShbInstance); /* signal that thread is running */ pShbMemInst->m_fNewDataThreadStarted = TRUE; pSemNewData = &pShbMemHeader->m_semNewData; pSemStopSignalingNewData = &pShbMemHeader->m_semStopSignalingNewData; do { clock_gettime(CLOCK_REALTIME, &curTime); timeout.tv_sec = 0; timeout.tv_nsec = TIMEOUT_CANCEL_THREAD * 1000; timespecadd(&timeout, &curTime); if ((iRetVal = sem_timedwait(pSemNewData, &timeout)) == 0) { //check terminate flag if (!pShbMemInst->m_fThreadTermFlag) { //call Rx Handler //TRACEX("%s() ShbIpcThreadSignalNewData call Rx Handler (%s) sem:%08x instance:%08x\n", __func__, pShbMemInst->m_bufName, (unsigned int)iSemNewDataId, (unsigned int)pShbInstance); pShbMemInst->m_pfnSigHndlrNewData(pShbInstance); } } } while(!pShbMemInst->m_fThreadTermFlag); //set sem thread terminated pShbMemInst->m_fNewDataThreadStarted = FALSE; sem_post(pSemStopSignalingNewData); return NULL; }
//------------------------------------------------------------------------------ // Function: ShbIpcStartSignalingJobReady // // Description: Start signaling for job ready (called from waiting process) // // Parameters: // pShbInstance_p pointer to shared buffer instance // ulTimeOut_p job ready timeout // pfnSignalHandlerJobReady_p function pointer to callback function // // Return: tShbError = error code //------------------------------------------------------------------------------ tShbError ShbIpcStartSignalingJobReady(tShbInstance pShbInstance_p, unsigned long ulTimeOut_p, tSigHndlrJobReady pfnSignalHandlerJobReady_p) { tShbMemInst* pShbMemInst; tShbMemHeader* pShbMemHeader; tShbError ShbError; struct sched_param schedParam; if ((pShbInstance_p == NULL) || (pfnSignalHandlerJobReady_p == NULL)) { return (kShbInvalidArg); } pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p); pShbMemHeader = ShbIpcGetShbMemHeader (pShbInstance_p); ShbError = kShbOk; if ((pShbMemInst->m_fJobReadyThreadStarted) || (pShbMemInst->m_pfnSigHndlrJobReady != NULL)) { ShbError = kShbAlreadySignaling; goto Exit; } pShbMemInst->m_ulTimeOutMsJobReady = ulTimeOut_p; pShbMemInst->m_pfnSigHndlrJobReady = pfnSignalHandlerJobReady_p; //create thread for job ready signaling if (pthread_create(&pShbMemInst->m_tThreadJobReadyId, NULL, &ShbIpcThreadSignalJobReady, pShbInstance_p) != 0) { pShbMemInst->m_pfnSigHndlrJobReady = NULL; ShbError = kShbInvalidSigHndlr; goto Exit; } schedParam.__sched_priority = EPL_THREAD_PRIORITY_LOW; if (pthread_setschedparam(pShbMemInst->m_tThreadNewDataId, SCHED_FIFO, &schedParam) != 0) { EPL_DBGLVL_ERROR_TRACE2("%s(): couldn't set thread scheduling parameters! %d\n", __func__, schedParam.__sched_priority); } Exit: return ShbError; }
//------------------------------------------------------------------------------ // Function: ShbIpcReleaseBuffer // // Description: Releases a shared buffer // // Parameters: pShbInstance_p pointer to shared buffer instance // // Return: tShbError = error code //------------------------------------------------------------------------------ tShbError ShbIpcReleaseBuffer (tShbInstance pShbInstance_p) { tShbMemInst* pShbMemInst; tShbMemHeader* pShbMemHeader; tShbError ShbError; if (pShbInstance_p == NULL) { return (kShbInvalidArg); } pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p); pShbMemHeader = ShbIpcGetShbMemHeader(pShbInstance_p); EPL_DBGLVL_SHB_TRACE("%s() pShbInstance=%p pShbMemHeader=%p\n", __func__, (void *)pShbInstance_p, (void *)pShbMemHeader); // stop threads in any case, because they are bound to that specific instance ShbIpcStopSignalingNewData (pShbInstance_p); pShbMemHeader->m_ulRefCount--; if(pShbMemHeader->m_ulRefCount == 0) { EPL_DBGLVL_SHB_TRACE("%s() refCount = 0, destroy shared mem\n", __func__); //delete semaphores semDelete(pShbMemHeader->m_mutexBuffAccess); semDelete(pShbMemHeader->m_semNewData); semDelete(pShbMemHeader->m_semJobReady); semDelete(pShbMemHeader->m_semStopSignalingNewData); //destroy Buffer ShbIpcFree(pShbMemHeader->m_uiBufferKey); ShbError = kShbOk; } else { EPL_DBGLVL_SHB_TRACE("%s() refCount > 0, detach from shared mem\n", __func__); ShbError = kShbMemUsedByOtherProcs; } //delete privat mem ShbIpcReleasePrivateMem (pShbMemInst); return (ShbError); }
INLINE_FUNCTION tShbMemHeader* ShbIpcGetShbMemHeader ( tShbInstance pShbInstance_p) { tShbMemInst* pShbMemInst; tShbMemHeader* pShbMemHeader; pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p); pShbMemHeader = pShbMemInst->m_pShbMemHeader; ASSERT(pShbMemHeader->m_SbhMagicID == SBH_MAGIC_ID); return (pShbMemHeader); }
//------------------------------------------------------------------------------ // Function: ShbIpcThreadSignalJobReady // // Description: Thread for new data Job Ready signaling // // Parameters: // pvThreadParam_p user parameters for thread // // Return: void * thread exit value (not used) //------------------------------------------------------------------------------ int ShbIpcThreadSignalJobReady (int pvThreadParam_p) { tShbInstance pShbInstance; tShbMemInst *pShbMemInst; tShbMemHeader* pShbMemHeader; INT iRetVal; UINT fTimeOut; EPL_DBGLVL_SHB_TRACE("%s(): ThreadId:%ld\n", __func__); pShbInstance = (tShbMemInst*)pvThreadParam_p; pShbMemInst = ShbIpcGetShbMemInst (pShbInstance); pShbMemHeader = ShbIpcGetShbMemHeader (pShbInstance); pShbMemInst->m_fJobReadyThreadStarted = TRUE; if (pShbMemInst->m_ulTimeOutMsJobReady != 0) { // todo: timeout is in ticks!! iRetVal = semTake(pShbMemHeader->m_semJobReady, pShbMemInst->m_ulTimeOutMsJobReady); } else { iRetVal = semTake(pShbMemHeader->m_semJobReady, WAIT_FOREVER); } if (iRetVal == OK) { fTimeOut = FALSE; } else { /* timeout or error */ fTimeOut = TRUE; } if (pShbMemInst->m_pfnSigHndlrJobReady != NULL) { //call Handler pShbMemInst->m_pfnSigHndlrJobReady(pShbInstance, fTimeOut); } pShbMemInst->m_pfnSigHndlrJobReady = NULL; pShbMemInst->m_fJobReadyThreadStarted = FALSE; return 0; }
INLINE_FUNCTION tShbError ShbIpcSignalNewData ( tShbInstance pShbInstance_p) { tShbMemHeader* pShbMemHeader; if (pShbInstance_p == NULL) { return (kShbInvalidArg); } pShbMemHeader = ShbIpcGetShbMemHeader (ShbIpcGetShbMemInst (pShbInstance_p)); //set semaphore pShbMemHeader->m_fNewData = TRUE; DEBUG_LVL_29_TRACE0("ShbIpcSignalNewData set Sem -> New Data\n"); return (kShbOk); }
int ShbIpcThreadSignalNewData (void *pvThreadParam_p) { tShbInstance pShbInstance; tShbMemInst* pShbMemInst; tShbMemHeader* pShbMemHeader; int fCallAgain; pShbInstance = (tShbMemInst*)pvThreadParam_p; pShbMemInst = ShbIpcGetShbMemInst (pShbInstance); pShbMemHeader = ShbIpcGetShbMemHeader (pShbMemInst); DEBUG_LVL_26_TRACE1("ShbIpcThreadSignalNewData(%p)\n",pvThreadParam_p); set_user_nice(current, pShbMemInst->m_lThreadNewDataNice); #ifdef CONFIG_PREEMPT_RT if (pShbMemInst->m_lThreadNewDataNice == -20) // highest priority { struct sched_param rt_prio; rt_prio.sched_priority = 79; sched_setscheduler(current, SCHED_FIFO, &rt_prio); } #endif // DEBUG_LVL_29_TRACE1("ShbIpcThreadSignalNewData wait for New Data Sem %p\n",pShbMemInst->m_pSemNewData); while (!kthread_should_stop()) { wait_event_interruptible(pShbMemHeader->m_WaitQueueNewData, kthread_should_stop() || (pShbMemHeader->m_fNewData != FALSE)); if (pShbMemHeader->m_fNewData != FALSE) { pShbMemHeader->m_fNewData = FALSE; do { fCallAgain = pShbMemInst->m_pfnSigHndlrNewData(pShbInstance); // call scheduler, which will execute any task with higher priority schedule(); } while (fCallAgain != FALSE); } } DEBUG_LVL_29_TRACE0("ShbIpcThreadSignalNewData terminated \n"); return 0; }
INLINE_FUNCTION tShbError ShbIpcStartSignalingJobReady ( tShbInstance pShbInstance_p, unsigned long ulTimeOutMs_p, tSigHndlrJobReady pfnSignalHandlerJobReady_p) { tShbMemInst* pShbMemInst; tShbMemInst** ppShbMemInst; tShbMemHeader* pShbMemHeader; tShbError ShbError; if ((pShbInstance_p == NULL) || (pfnSignalHandlerJobReady_p == NULL)) { return (kShbInvalidArg); } pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p); pShbMemHeader = ShbIpcGetShbMemHeader (pShbMemInst); ShbError = kShbOk; if (pShbMemInst->m_pfnSigHndlrJobReady != NULL) { ShbError = kShbAlreadySignaling; goto Exit; } pShbMemInst->m_ulTimeOutMsJobReady = ulTimeOutMs_p; pShbMemInst->m_ulStartTimeMsJobReady = ShbTgtGetTickCountMs(); pShbMemInst->m_pfnSigHndlrJobReady = pfnSignalHandlerJobReady_p; pShbMemInst->m_pProcessListNewDataNext = NULL; pShbMemHeader->m_fJobReady = FALSE; // insert ShbMemInst at the end of JobReady list // thus other operations on the list are not disturbed ppShbMemInst = &pShbIpcProcessListJobReadyFirst_g; while (*ppShbMemInst != NULL) { ppShbMemInst = &(*ppShbMemInst)->m_pProcessListJobReadyNext; } ShbIpcEnterAtomicSection(NULL); while (*ppShbMemInst != NULL) { ppShbMemInst = &(*ppShbMemInst)->m_pProcessListJobReadyNext; } *ppShbMemInst = pShbMemInst; ShbIpcLeaveAtomicSection(NULL); Exit: return ShbError; }
//------------------------------------------------------------------------------ // Function: ShbIpcStopSignalingNewData // // Description: Stop signaling of new data (called from reading process) // // Parameters: pShbInstance_p pointer to shared buffer instance // // Return: tShbError = error code //------------------------------------------------------------------------------ tShbError ShbIpcStopSignalingNewData(tShbInstance pShbInstance_p) { tShbMemInst *pShbMemInst; tShbMemHeader *pShbMemHeader; tShbError ShbError; INT iRetVal = -1; sem_t* pSemStopSignalingNewData; sem_t* pSemNewData; struct timespec curTime, timeout; if (pShbInstance_p == NULL) { return (kShbInvalidArg); } pShbMemHeader = ShbIpcGetShbMemHeader (pShbInstance_p); pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p); pSemNewData = &pShbMemHeader->m_semNewData; pSemStopSignalingNewData = &pShbMemHeader->m_semStopSignalingNewData; ShbError = kShbOk; if (!pShbMemInst->m_fNewDataThreadStarted) { ShbError = kShbBufferAlreadyCompleted; goto Exit; } //set termination flag and signal new data to terminate thread pShbMemInst->m_fThreadTermFlag = TRUE; sem_post(pSemNewData); // waiting for thread to terminate clock_gettime(CLOCK_REALTIME, &curTime); timeout.tv_sec = 1; timeout.tv_nsec = TIMEOUT_WAITING_THREAD * 1000; timespecadd(&timeout, &curTime); iRetVal = sem_timedwait(pSemStopSignalingNewData, &timeout); if (iRetVal != 0) { EPL_DBGLVL_ERROR_TRACE3("%s() Stop Sem TIMEOUT %d (%s)\n", __func__, iRetVal, strerror(errno)); } Exit: return (ShbError); }
//------------------------------------------------------------------------------ // Function: ShbIpcLeaveAtomicSection // // Description: Leave atomic section for Shared Buffer access // // Parameters: pShbInstance_p pointer to shared buffer instance // // Return: tShbError = error code //------------------------------------------------------------------------------ tShbError ShbIpcLeaveAtomicSection(tShbInstance pShbInstance_p) { tShbMemInst* pShbMemInst; tShbMemHeader* pShbMemHeader; if (pShbInstance_p == NULL) { return (kShbInvalidArg); } pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p); pShbMemHeader = ShbIpcGetShbMemHeader (pShbMemInst); semGive(pShbMemHeader->m_mutexBuffAccess); return (kShbOk); }
INLINE_FUNCTION tShbError ShbIpcSignalJobReady ( tShbInstance pShbInstance_p) { tShbMemHeader* pShbMemHeader; DEBUG_LVL_29_TRACE("ShbIpcSignalJobReady\n"); if (pShbInstance_p == NULL) { return (kShbInvalidArg); } pShbMemHeader = ShbIpcGetShbMemHeader (ShbIpcGetShbMemInst (pShbInstance_p)); //set semaphore pShbMemHeader->m_fJobReady = TRUE; DEBUG_LVL_29_TRACE("ShbIpcSignalJobReady set Sem -> Job Ready \n"); return (kShbOk); }
//------------------------------------------------------------------------------ // Function: ShbIpcStartSignalingJobReady // // Description: Start signaling for job ready (called from waiting process) // // Parameters: // pShbInstance_p pointer to shared buffer instance // ulTimeOut_p job ready timeout // pfnSignalHandlerJobReady_p function pointer to callback function // // Return: tShbError = error code //------------------------------------------------------------------------------ tShbError ShbIpcStartSignalingJobReady(tShbInstance pShbInstance_p, unsigned long ulTimeOut_p, tSigHndlrJobReady pfnSignalHandlerJobReady_p) { tShbMemInst* pShbMemInst; tShbMemHeader* pShbMemHeader; tShbError ShbError; if ((pShbInstance_p == NULL) || (pfnSignalHandlerJobReady_p == NULL)) { return (kShbInvalidArg); } pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p); pShbMemHeader = ShbIpcGetShbMemHeader (pShbInstance_p); ShbError = kShbOk; if ((pShbMemInst->m_fJobReadyThreadStarted) || (pShbMemInst->m_pfnSigHndlrJobReady != NULL)) { ShbError = kShbAlreadySignaling; goto Exit; } pShbMemInst->m_ulTimeOutMsJobReady = ulTimeOut_p; pShbMemInst->m_pfnSigHndlrJobReady = pfnSignalHandlerJobReady_p; //create thread for job ready signaling if ((pShbMemInst->m_tThreadJobReadyId = taskSpawn ("tShbJobReady", EPL_TASK_PRIORITY_SHB_JOB, 0, EPL_TASK_STACK_SIZE, &ShbIpcThreadSignalJobReady, (int)pShbInstance_p, 0, 0, 0, 0, 0, 0, 0, 0, 0)) == ERROR) { pShbMemInst->m_pfnSigHndlrJobReady = NULL; ShbError = kShbInvalidSigHndlr; goto Exit; } Exit: return ShbError; }
tShbError ShbIpcReleaseBuffer (tShbInstance pShbInstance_p) { tShbMemInst* pShbMemInst; tShbMemHeader* pShbMemHeader; tShbError ShbError; tShbError ShbError2; DEBUG_LVL_26_TRACE1("ShbIpcReleaseBuffer(%p)\n", pShbInstance_p); if (pShbInstance_p == NULL) { return (kShbOk); } pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p); pShbMemHeader = ShbIpcGetShbMemHeader (pShbMemInst); // stop threads in any case, because they are bound to that specific instance ShbError2 = ShbIpcStopSignalingNewData (pShbInstance_p); down(&pShbMemInst->m_SemaphoreStopThreadJobReady); if (pShbMemInst->m_tThreadJobReadyId != INVALID_ID) { kthread_stop(pShbMemInst->m_tThreadJobReadyId); } up(&pShbMemInst->m_SemaphoreStopThreadJobReady); if ( !--pShbMemHeader->m_ulRefCount ) { ShbError = kShbOk; // delete mem table element ShbIpcDeleteListElement(pShbMemHeader->m_iBufferId); // delete shared mem kfree(pShbMemInst->m_pShbMemHeader); } else { ShbError = kShbMemUsedByOtherProcs; } //delete privat mem kfree(pShbMemInst); return (ShbError); }
INLINE_FUNCTION void* ShbIpcGetShMemPtr (tShbInstance pShbInstance_p) { tShbMemHeader* pShbMemHeader; void* pShbShMemPtr; pShbMemHeader = ShbIpcGetShbMemHeader (ShbIpcGetShbMemInst (pShbInstance_p)); if (pShbMemHeader != NULL) { pShbShMemPtr = (BYTE*)pShbMemHeader + sizeof(tShbMemHeader); } else { pShbShMemPtr = NULL; } return (pShbShMemPtr); }
//------------------------------------------------------------------------------ // Function: ShbIpcSignalJobReady // // Description: Signal job ready (called from executing process) // // Parameters: // pShbInstance_p pointer to shared buffer instance // // Return: tShbError = error code //------------------------------------------------------------------------------ tShbError ShbIpcSignalJobReady(tShbInstance pShbInstance_p) { tShbMemInst* pShbMemInst; tShbMemHeader* pShbMemHeader; tShbError ShbError; if (pShbInstance_p == NULL) { return (kShbInvalidArg); } ShbError = kShbOk; pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p); pShbMemHeader = ShbIpcGetShbMemHeader (pShbInstance_p); //set semaphore semGive(pShbMemHeader->m_semJobReady); return ShbError; }