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; }
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; }
INLINE_FUNCTION tShbError ShbIpcSignalJobReady ( tShbInstance pShbInstance_p) { tShbMemHeader* pShbMemHeader; DEBUG_LVL_29_TRACE0("ShbIpcSignalJobReady\n"); if (pShbInstance_p == NULL) { return (kShbInvalidArg); } pShbMemHeader = ShbIpcGetShbMemHeader (ShbIpcGetShbMemInst (pShbInstance_p)); //set semaphore pShbMemHeader->m_fJobReady = TRUE; DEBUG_LVL_29_TRACE0("ShbIpcSignalJobReady set Sem -> Job Ready \n"); return (kShbOk); }
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_TRACE0("------->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_TRACE2("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; }
INLINE_FUNCTION tShbError ShbIpcStopSignalingNewData ( tShbInstance pShbInstance_p) { tShbMemInst* pShbMemInst; tShbMemInst** ppShbMemInst; tShbMemHeader* pShbMemHeader; tShbError ShbError; DEBUG_LVL_29_TRACE0("------->ShbIpcStopSignalingNewData\n"); if (ShbTgtIsInterruptContext()) { return (kShbInterruptContextNotAllowed); } 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 // 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; }
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; }
static void* ShbIpcAllocPrivateMem (unsigned long ulMemSize_p) { tShbError ShbError; void* pMem; DEBUG_LVL_29_TRACE0("ShbIpcAllocPrivateMem \n"); //get private mem pMem = kmalloc(ulMemSize_p, GFP_KERNEL); if (pMem == NULL) { //unable to create mem ShbError = kShbOutOfMem; goto Exit; } Exit: return (pMem); }
INLINE_FUNCTION tShbError ShbIpcLeaveAtomicSection ( tShbInstance pShbInstance_p) { tShbMemInst* pShbMemInst; tShbMemHeader* pShbMemHeader; tShbError ShbError = kShbOk; if (pShbInstance_p == NULL) { ShbError = kShbInvalidArg; goto Exit; } pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p); pShbMemHeader = ShbIpcGetShbMemHeader (pShbMemInst); // unlock interrupts spin_unlock_irqrestore(&pShbMemHeader->m_SpinlockBuffAccess, pShbMemInst->m_ulFlagsBuffAccess); Exit: DEBUG_LVL_29_TRACE0("Leave Atomic \n"); return ShbError; }
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"); wake_up(&pShbMemHeader->m_WaitQueueNewData); if (pShbMemHeader->m_pShbInstMaster != NULL) { return ShbIpcSignalNewData(pShbMemHeader->m_pShbInstMaster); } return (kShbOk); }
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) { 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; unsigned long aulCrcTable[256]; DEBUG_LVL_29_TRACE0("ShbIpcAllocBuffer \n"); if (ShbTgtIsInterruptContext()) { ShbError = kShbInterruptContextNotAllowed; goto Exit; } ulShMemSize = ulBufferSize_p + sizeof(tShbMemHeader); //create Buffer ID ShbIpcCrc32GenTable(aulCrcTable); ulCrc32 = ShbIpcCrc32GetCrc(pszBufferID_p, aulCrcTable); 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_TRACE2("ShbIpcAllocBuffer attach Buffer at:%p Id:%d\n",pSharedMem, iBufferId); uiFirstProcess=1; } else { //create new Buffer fShMemNewCreated = TRUE; uiFirstProcess=0; pSharedMem = malloc(ulShMemSize); 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; } // append Element to Mem Table psMemTableElement = malloc(sizeof(struct sShbMemTable)); 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 for instance local information // to administrate/manage the shared buffer DEBUG_LVL_29_TRACE0("ShbIpcAllocBuffer alloc private mem\n"); pShbMemInst = (tShbMemInst*) malloc(sizeof(tShbMemInst)); if (pShbMemInst == NULL) { ShbError = kShbOutOfMem; goto Exit; } // reset complete header to default values //pShbMemInst->m_SbiMagicID = SBI_MAGIC_ID; pShbMemInst->m_pfnSigHndlrNewData = NULL; pShbMemInst->m_ulTimeOutMsJobReady = 0; pShbMemInst->m_ulStartTimeMsJobReady = 0; pShbMemInst->m_pfnSigHndlrJobReady = NULL; pShbMemInst->m_pShbMemHeader = pShbMemHeader; pShbMemInst->m_pProcessListNewDataNext = NULL; pShbMemInst->m_pProcessListJobReadyNext = NULL; // initialize 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; } 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); }