void common_wrapper(UArg arg0, UArg arg1) { taskArgs* t = (taskArgs*)arg0 ; int tid = (int)arg1 ; int i, j, k ; for(i=0 ; i<NUM_ITER ; i++) { if(tid == 0) { callBarrier(0, /*lock_id=*/4) ; } callLocalBarrier() ; compute_histo(t->buffer1, t->buffer2, t->start_indx, t->end_indx) ; Cache_wbInv (t->buffer2, HISTO_SIZE*4, Cache_Type_ALL, FALSE) ; callLocalBarrier() ; if(tid == 0) { callBarrier(1, /*lock_id=*/4) ; compute_gray_level_mapping() ; } callLocalBarrier() ; compute_image(t->buffer1, m3_gray_level_mapping, t->start_indx, t->end_indx) ; if(tid == 0) Cache_wbInv (t->buffer1, IMG_SIZE*IMG_SIZE*4, Cache_Type_ALL, FALSE); } if(tid == 0) Event_post(edgeDetectEvent, Event_Id_00) ; else Event_post(edgeDetectEvent, Event_Id_01) ; }
/* * ======== NotifyDriverShm_unregisterEvent ======== */ Void NotifyDriverShm_unregisterEvent(NotifyDriverShm_Object *obj, UInt32 eventId) { NotifyDriverShm_EventEntry *eventEntry; Int i, j; /* * Disable interrupt line to ensure that NotifyDriverShm_isr doesn't * preempt registerEvent and encounter corrupt state */ NotifyDriverShm_disable(obj); /* * First unset the registered bit in shared memory so no notifications * arrive after this point */ CLEAR_BIT(obj->selfProcCtrl->eventRegMask, eventId); if (obj->cacheEnabled) { Cache_wbInv(obj->selfProcCtrl, sizeof(NotifyDriverShm_ProcCtrl), Cache_Type_ALL, TRUE); } /* * Clear any pending unserviced event as there are no listeners * for the pending event. This should be done only after the event * is unregistered from shared memory so the other processor doesn't * successfully send an event our way immediately after unflagging this * event. */ eventEntry = EVENTENTRY(obj->selfEventChart, obj->eventEntrySize, eventId); eventEntry->flag = NotifyDriverShm_DOWN; /* Write back both the flag and the reg mask */ if (obj->cacheEnabled) { Cache_wbInv(eventEntry, sizeof(NotifyDriverShm_EventEntry), Cache_Type_ALL, TRUE); } /* * Re-arrange eventIds in the Event Registration Chart so there is * no gap caused by the removal of this eventId * * There is no need to make this atomic since Notify_exec cannot preempt: * the event has already been disabled in shared memory (see above) */ for (i = 0; i < ti_sdo_ipc_Notify_numEvents; i++) { if (eventId == obj->regChart[i]) { obj->regChart[i] = (UInt32)-1; for (j = i + 1; (j != ti_sdo_ipc_Notify_numEvents) && (obj->regChart[j] != (UInt32)-1); j++) { obj->regChart[j - 1] = obj->regChart[j]; obj->regChart[j] = (UInt32)-1; } break; } } /* Restore the interrupt line */ NotifyDriverShm_enable(obj); }
/* * ======== ListMP_putTail ======== */ Int ListMP_putTail(ListMP_Handle handle, ListMP_Elem *elem) { ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle; UInt key; UInt16 id; ListMP_Elem *localPrevElem; SharedRegion_SRPtr sharedElem; SharedRegion_SRPtr sharedHead; Bool localPrevElemIsCached; /* prevent another thread or processor from modifying the ListMP */ key = GateMP_enter((GateMP_Handle)obj->gate); id = SharedRegion_getId(elem); if (ti_sdo_ipc_SharedRegion_translate == FALSE) { sharedElem = (SharedRegion_SRPtr)elem; sharedHead = (SharedRegion_SRPtr)&(obj->attrs->head); localPrevElem = (ListMP_Elem *)obj->attrs->head.prev; } else { sharedElem = SharedRegion_getSRPtr(elem, id); sharedHead = SharedRegion_getSRPtr(&(obj->attrs->head), obj->regionId); localPrevElem = SharedRegion_getPtr(obj->attrs->head.prev); } /* Assert that pointer is not NULL */ Assert_isTrue(localPrevElem != NULL, ti_sdo_ipc_Ipc_A_nullPointer); localPrevElemIsCached = SharedRegion_isCacheEnabled( SharedRegion_getId(localPrevElem)); if (localPrevElemIsCached) { Cache_inv(localPrevElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE); } /* add the new elem into the list */ elem->next = sharedHead; elem->prev = obj->attrs->head.prev; localPrevElem->next = sharedElem; obj->attrs->head.prev = sharedElem; if (localPrevElemIsCached) { /* Write-back because localPrevElem->next changed */ Cache_wbInv(localPrevElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE); } if (obj->cacheEnabled) { /* Write-back because obj->attrs->head.prev changed */ Cache_wbInv(&(obj->attrs->head), sizeof(ListMP_Elem), Cache_Type_ALL, TRUE); } if (SharedRegion_isCacheEnabled(id)) { /* Write-back because elem->next & elem->prev changed */ Cache_wbInv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE); } GateMP_leave((GateMP_Handle)obj->gate, key); return (ListMP_S_SUCCESS); }
/* * ======== NotifyDriverShm_registerEvent ======== */ Void NotifyDriverShm_registerEvent(NotifyDriverShm_Object *obj, UInt32 eventId) { NotifyDriverShm_EventEntry *eventEntry; Int i, j; /* * Disable interrupt line to ensure that NotifyDriverShm_isr doesn't * preempt registerEvent and encounter corrupt state */ NotifyDriverShm_disable(obj); /* * Add an entry for the registered event into the Event Registration * Chart, in ascending order of event numbers (and decreasing * priorities). */ for (i = 0; i < ti_sdo_ipc_Notify_numEvents; i++) { /* Find the correct slot in the registration array.*/ if (obj->regChart[i] == (UInt32)-1) { for (j = i - 1; j >= 0; j--) { if (eventId < obj->regChart[j]) { obj->regChart[j + 1] = obj->regChart[j]; i = j; } else { /* End the loop, slot found.*/ j = -1; } } obj->regChart[i] = eventId; break; } } /* * Clear any pending unserviced event as there are no listeners * for the pending event */ eventEntry = EVENTENTRY(obj->selfEventChart, obj->eventEntrySize, eventId) eventEntry->flag = NotifyDriverShm_DOWN; if (obj->cacheEnabled) { Cache_wbInv(eventEntry, sizeof(NotifyDriverShm_EventEntry), Cache_Type_ALL, TRUE); } /* Set the 'registered' bit in shared memory and write back */ SET_BIT(obj->selfProcCtrl->eventRegMask, eventId); if (obj->cacheEnabled) { Cache_wbInv(obj->selfProcCtrl, sizeof(NotifyDriverShm_ProcCtrl), Cache_Type_ALL, TRUE); } /* Restore the interrupt line */ NotifyDriverShm_enable(obj); }
/* * ======== GateAAMonitor_Instance_init ======== */ Int GateAAMonitor_Instance_init(GateAAMonitor_Object *obj, IGateProvider_Handle localGate, const GateAAMonitor_Params *params, Error_Block *eb) { /* Assert that params->sharedAddr is valid */ Assert_isTrue( (UInt32)params->sharedAddr >= GateAAMonitor_SL2_RANGE_BASE && (UInt32)params->sharedAddr < GateAAMonitor_SL2_RANGE_MAX, GateAAMonitor_A_invSharedAddr); obj->localGate = localGate; obj->sharedAddr = (Ptr)_Ipc_roundup(params->sharedAddr, GateAAMonitor_CACHELINE_SIZE); obj->nested = 0; if (!params->openFlag) { /* * The processor that inits the AAM initializes the value * to zero (e.g. no one is using it). The other processors * must invalidate the memory in case it is in cache. */ *(obj->sharedAddr) = 0; Cache_wbInv((Ptr)obj->sharedAddr, GateAAMonitor_CACHELINE_SIZE, Cache_Type_ALL, TRUE); } else { /* Opening. */ Cache_inv((Ptr)obj->sharedAddr, GateAAMonitor_CACHELINE_SIZE, Cache_Type_ALL, TRUE); } return (0); }
/* * ======== Ipc_stop ======== */ Int Ipc_stop() { Int status; /* clear local module state */ Ipc_module->gateMPSharedAddr = NULL; Ipc_module->ipcSharedAddr = NULL; /* reset Shared Region 0 reservedSize and heap handle */ ti_sdo_ipc_SharedRegion_resetInternalFields(0); /* delete any HeapMemMP created by owner of SR0 */ status = ti_sdo_ipc_SharedRegion_stop(); if (status < 0) { return (status); } /* delete default GateMP created by owner of SR0 */ status = ti_sdo_ipc_GateMP_stop(); if (status < 0) { return (status); } /* set sr0MemorySetup back to 0 if needed by Host */ if ((ti_sdo_ipc_Ipc_generateSlaveDataForHost) && !(ti_sdo_ipc_Ipc_sr0MemorySetup)) { Ipc_sr0MemorySetup = 0; Cache_wbInv(&Ipc_sr0MemorySetup, sizeof(Ipc_sr0MemorySetup), Cache_Type_ALL, TRUE); } return (Ipc_S_SUCCESS); }
/* * ======== ti_sdo_ipc_Ipc_procSyncFinish ======== * Each processor writes its reserve memory address in SharedRegion 0 * to let the other processors know its finished the process of * synchronization. */ Int ti_sdo_ipc_Ipc_procSyncFinish(UInt16 remoteProcId, Ptr sharedAddr) { volatile ti_sdo_ipc_Ipc_Reserved *self, *remote; SizeT reservedSize = ti_sdo_ipc_Ipc_reservedSizePerProc(); Bool cacheEnabled = SharedRegion_isCacheEnabled(0); UInt oldPri; /* don't do any synchronization if procSync is NONE */ if (ti_sdo_ipc_Ipc_procSync == ti_sdo_ipc_Ipc_ProcSync_NONE) { return (Ipc_S_SUCCESS); } /* determine self and remote pointers */ if (MultiProc_self() < remoteProcId) { self = Ipc_getSlaveAddr(remoteProcId, sharedAddr); remote = ti_sdo_ipc_Ipc_getMasterAddr(remoteProcId, sharedAddr); } else { self = ti_sdo_ipc_Ipc_getMasterAddr(remoteProcId, sharedAddr); remote = Ipc_getSlaveAddr(remoteProcId, sharedAddr); } /* set my processor's reserved key to finish */ self->startedKey = ti_sdo_ipc_Ipc_PROCSYNCFINISH; /* write back my processor's reserve key */ if (cacheEnabled) { Cache_wbInv((Ptr)self, reservedSize, Cache_Type_ALL, TRUE); } /* if slave processor, wait for remote to finish sync */ if (MultiProc_self() < remoteProcId) { if (BIOS_getThreadType() == BIOS_ThreadType_Task) { oldPri = Task_getPri(Task_self()); } /* wait for remote processor to finish */ while (remote->startedKey != ti_sdo_ipc_Ipc_PROCSYNCFINISH && remote->startedKey != ti_sdo_ipc_Ipc_PROCSYNCDETACH) { /* Set self priority to 1 [lowest] and yield cpu */ if (BIOS_getThreadType() == BIOS_ThreadType_Task) { Task_setPri(Task_self(), 1); Task_yield(); } /* Check the remote's sync flag */ if (cacheEnabled) { Cache_inv((Ptr)remote, reservedSize, Cache_Type_ALL, TRUE); } } /* Restore self priority */ if (BIOS_getThreadType() == BIOS_ThreadType_Task) { Task_setPri(Task_self(), oldPri); } } return (Ipc_S_SUCCESS); }
/* * ======== ListMP_remove ======== */ Int ListMP_remove(ListMP_Handle handle, ListMP_Elem *elem) { ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle; UInt key; ListMP_Elem *localPrevElem; ListMP_Elem *localNextElem; Bool localPrevElemIsCached, localNextElemIsCached; /* Prevent another thread or processor from modifying the ListMP */ key = GateMP_enter((GateMP_Handle)obj->gate); if (ti_sdo_ipc_SharedRegion_translate == FALSE) { localPrevElem = (ListMP_Elem *)(elem->prev); localNextElem = (ListMP_Elem *)(elem->next); } else { localPrevElem = SharedRegion_getPtr(elem->prev); localNextElem = SharedRegion_getPtr(elem->next); } localPrevElemIsCached = SharedRegion_isCacheEnabled( SharedRegion_getId(localPrevElem)); localNextElemIsCached = SharedRegion_isCacheEnabled( SharedRegion_getId(localNextElem)); if (localPrevElemIsCached) { Cache_inv(localPrevElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE); } if (localNextElemIsCached) { Cache_inv(localNextElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE); } localPrevElem->next = elem->next; localNextElem->prev = elem->prev; if (localPrevElemIsCached) { Cache_wbInv(localPrevElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE); } if (localNextElemIsCached) { Cache_wbInv(localNextElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE); } GateMP_leave((GateMP_Handle)obj->gate, key); return (ListMP_S_SUCCESS); }
/* * ======== Memory_cacheWbInv ======== */ Void Memory_cacheWbInv(Ptr addr, Int sizeInBytes) { Log_print2(Diags_ENTRY, "[+E] Memory_cacheWbInv> " "Enter(addr=0x%x, sizeInBytes=%d)", (IArg)addr, (IArg)sizeInBytes); Cache_wbInv(addr, sizeInBytes, Cache_Type_ALL, TRUE); Log_print0(Diags_EXIT, "[+X] Memory_cacheWbInv> return"); }
/* * ======== ti_sdo_ipc_ListMP_elemClear ======== */ Void ti_sdo_ipc_ListMP_elemClear(ti_sdo_ipc_ListMP_Elem *elem) { SharedRegion_SRPtr sharedElem; UInt16 id; id = SharedRegion_getId(elem); sharedElem = SharedRegion_getSRPtr(elem, id); elem->next = elem->prev = sharedElem; if (SharedRegion_isCacheEnabled(id)) { Cache_wbInv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE); } }
/* * ======== GatePetersonN_postInit ======== * Function to be called during * 1. module startup to complete the initialization of all static instances * 2. instance_init to complete the initialization of a dynamic instance * * Main purpose is to set up shared memory */ Void GatePetersonN_postInit(GatePetersonN_Object *obj) { UInt16 i; /* Set up shared memory */ for (i=0; i < obj->numProcessors; i++) { *(obj->enteredStage[i]) = GatePetersonN_NOT_INTERESTED; } for (i=0; i < obj->numProcessors - 1; i++) { *(obj->lastProcEnteringStage[i]) = 0; } /* * Write everything back to shared memory. */ if (obj->cacheEnabled) { Cache_wbInv((Ptr)(obj->enteredStage[0]), obj->cacheLineSize * obj->numProcessors, Cache_Type_ALL, FALSE); Cache_wbInv((Ptr)(obj->lastProcEnteringStage[0]), obj->cacheLineSize * obj->numProcessors-1, Cache_Type_ALL, TRUE); } }
/* * ======== SemaphoreMP_post ======== */ Void SemaphoreMP_post(SemaphoreMP_Object *obj) { UInt tskKey; SemaphoreMP_PendElem *elem; IArg gateMPKey; Int status; /* Enter the gate */ gateMPKey = GateMP_enter((GateMP_Handle)obj->gate); if (ListMP_empty((ListMP_Handle)obj->pendQ)) { if (obj->mode == SemaphoreMP_Mode_BINARY) { obj->attrs->count = 1; } else { obj->attrs->count++; } if (obj->cacheEnabled) { Cache_wbInv(obj->attrs, sizeof(SemaphoreMP_Attrs), Cache_Type_ALL, TRUE); } /* Leave the gate */ GateMP_leave((GateMP_Handle)obj->gate, gateMPKey); return; } /* lock task scheduler */ tskKey = Task_disable(); /* dequeue tsk from semaphore queue */ elem = (SemaphoreMP_PendElem *)ListMP_getHead((ListMP_Handle)obj->pendQ); if (elem->procId != MultiProc_self()) { /* Unblock remote task */ status = Notify_sendEvent(elem->procId, 0, SemaphoreMP_notifyEventId, elem->task, TRUE); Assert_isTrue(status >= 0, ti_sdo_ipc_Ipc_A_internal); } else { /* put task back into readyQ */ Task_unblock((Task_Handle)elem->task); } /* Leave the gate */ GateMP_leave((GateMP_Handle)obj->gate, gateMPKey); Task_restore(tskKey); }
/* * ======== NotifyDriverShm_setNotifyHandle ======== */ Void NotifyDriverShm_setNotifyHandle(NotifyDriverShm_Object *obj, Ptr notifyHandle) { /* Internally used, so no Assert needed */ obj->notifyHandle = (ti_sdo_ipc_Notify_Handle)notifyHandle; /* Indicate that the driver is initialized for this processor */ obj->selfProcCtrl->recvInitStatus = NotifyDriverShm_INIT_STAMP; obj->selfProcCtrl->sendInitStatus = NotifyDriverShm_INIT_STAMP; /* Write back our own ProcCtrl */ if (obj->cacheEnabled) { Cache_wbInv(obj->selfProcCtrl, sizeof(NotifyDriverShm_ProcCtrl), Cache_Type_ALL, TRUE); } }
/* * ======== GatePetersonN_leave ======== */ Void GatePetersonN_leave(GatePetersonN_Object *obj, IArg key) { /* Release the resource and leave system gate. */ obj->nested--; if (obj->nested == 0) { *(obj->enteredStage[obj->selfId]) = GatePetersonN_NOT_INTERESTED; if (obj->cacheEnabled) { Cache_wbInv((Ptr)obj->enteredStage[obj->selfId], obj->cacheLineSize, Cache_Type_ALL, TRUE); } } /* Leave local gate */ IGateProvider_leave(obj->localGate, key); }
/* * ======== SemaphoreMP_Instance_finalize ======== */ Void SemaphoreMP_Instance_finalize(SemaphoreMP_Object *obj, Int status) { if (obj->objType & (ti_sdo_ipc_Ipc_ObjType_CREATEDYNAMIC | ti_sdo_ipc_Ipc_ObjType_CREATEDYNAMIC_REGION)) { /* SemaphoreMP is being deleted */ /* Remove entry from NameServer */ if (obj->nsKey != NULL) { NameServer_removeEntry((NameServer_Handle) SemaphoreMP_module->nameServer, obj->nsKey); } /* Set status to 'not created' */ obj->attrs->status = 0; if (obj->cacheEnabled) { Cache_wbInv(obj->attrs, sizeof(SemaphoreMP_Attrs), Cache_Type_ALL, TRUE); } /* Delete the pendQ. If NULL, then ListMP_create failed. */ if (obj->pendQ != NULL) { ListMP_delete((ListMP_Handle *)&(obj->pendQ)); } /* * Free the shared memory back to the region SemaphoreMP. If NULL, then * the Memory_alloc failed. */ if (obj->objType == ti_sdo_ipc_Ipc_ObjType_CREATEDYNAMIC_REGION && obj->attrs != NULL) { Memory_free(SharedRegion_getHeap(obj->regionId), obj->attrs, obj->allocSize); } } else { /* SemaphoreMP is being closed */ /* Close the pendQ. If NULL, then ListMP_openByAddr failed. */ if (obj->pendQ != NULL) { ListMP_close((ListMP_Handle *)&(obj->pendQ)); } /* Close the gate. If NULL, then GateMP_openByAddr failed. */ if (obj->gate != NULL) { GateMP_close((GateMP_Handle *)&(obj->gate)); } } }
/* * ======== NotifyDriverShm_Instance_finalize ======== */ Void NotifyDriverShm_Instance_finalize(NotifyDriverShm_Object *obj, int status) { if (status == 0) { /* Indicate that driver is no longer ready to send/receive events */ obj->selfProcCtrl->recvInitStatus = 0; obj->selfProcCtrl->sendInitStatus = 0; Cache_wbInv(obj->selfProcCtrl, sizeof(NotifyDriverShm_ProcCtrl), Cache_Type_ALL, TRUE); /* Unregister interrupt */ NotifyDriverShm_InterruptProxy_intUnregister(obj->remoteProcId, &(obj->intInfo)); /* Free memory alloc'ed for regChart */ Memory_free(NotifyDriverShm_Object_heap(), obj->regChart, sizeof(UInt32) * ti_sdo_ipc_Notify_numEvents); } }
static RPC_OMX_ERRORTYPE RPC_SKEL_ShareRegion(UInt32 size, UInt32 *data) { buffer_one *buffer_args; Frame_dsp *pFrame = NULL; buffer_args = (buffer_one *)((UInt32)data + sizeof(map_info_type) + sizeof(int)); pFrame = (Frame_dsp*)buffer_args->addr; Cache_inv(pFrame, buffer_args->size, Cache_Type_ALL, TRUE); BRIEF_match(pFrame->kpoint_left, pFrame->n_kpoint_left, pFrame->kpoint_right, pFrame->n_kpoint_right, pFrame->range, pFrame->best_choice, IMG_WIDTH, IMG_HEIGHT); Cache_wbInv(pFrame, buffer_args->size, Cache_Type_ALL, TRUE); return(0); }
/* * ======== NotifyDriverShm_enableEvent ======== */ Void NotifyDriverShm_enableEvent(NotifyDriverShm_Object *obj, UInt32 eventId) { UInt sysKey; Assert_isTrue(eventId < ti_sdo_ipc_Notify_numEvents, ti_sdo_ipc_Ipc_A_invArgument); /* * Atomically set the corresponding bit in the processor's * eventEnableMask */ sysKey = Hwi_disable(); SET_BIT(obj->selfProcCtrl->eventEnableMask, eventId); Hwi_restore(sysKey); if (obj->cacheEnabled) { Cache_wbInv(obj->selfProcCtrl, sizeof(NotifyDriverShm_ProcCtrl), Cache_Type_ALL, TRUE); } }
/* * ======== TransportShm_put ======== * Assuming MessageQ_put is making sure that the arguments are ok */ Bool TransportShm_put(TransportShm_Object *obj, Ptr msg) { Int32 status; Bool retval = TRUE; IArg key; UInt16 id = SharedRegion_getId(msg); /* This transport only deals with messages allocated from SR's */ Assert_isTrue(id != SharedRegion_INVALIDREGIONID, ti_sdo_ipc_SharedRegion_A_regionInvalid); /* writeback invalidate the message */ if (SharedRegion_isCacheEnabled(id)) { Cache_wbInv(msg, ((MessageQ_Msg)(msg))->msgSize, Cache_Type_ALL, TRUE); } /* make sure ListMP_put and sendEvent are done before remote executes */ key = GateMP_enter((GateMP_Handle)obj->gate); /* Put the message on the remoteList */ ListMP_putTail((ListMP_Handle)obj->remoteList, (ListMP_Elem *)msg); /* Notify the remote processor */ status = Notify_sendEvent(obj->remoteProcId, 0, TransportShm_notifyEventId, 0, FALSE); /* check the status of the sendEvent */ if (status < 0) { /* remove the message from the List and return 'FALSE' */ ListMP_remove((ListMP_Handle)obj->remoteList, (ListMP_Elem *)msg); retval = FALSE; } /* leave the gate */ GateMP_leave((GateMP_Handle)obj->gate, key); return (retval); }
/* * ======== Ipc_attach ======== */ Int Ipc_attach(UInt16 remoteProcId) { Int i; Ptr sharedAddr; SizeT memReq; volatile ti_sdo_ipc_Ipc_Reserved *slave; ti_sdo_ipc_Ipc_ProcEntry *ipc; Error_Block eb; SharedRegion_Entry entry; SizeT reservedSize = ti_sdo_ipc_Ipc_reservedSizePerProc(); Bool cacheEnabled = SharedRegion_isCacheEnabled(0); UInt16 clusterId = ti_sdo_utils_MultiProc_getClusterId(remoteProcId); Int status; UInt hwiKey; /* Assert remoteProcId is in our cluster and isn't our own */ Assert_isTrue(clusterId < ti_sdo_utils_MultiProc_numProcsInCluster, ti_sdo_utils_MultiProc_A_invalidMultiProcId); Assert_isTrue(remoteProcId != MultiProc_self(), ti_sdo_ipc_Ipc_A_invArgument); /* Check whether Ipc_start has been called. If not, fail. */ if (Ipc_module->ipcSharedAddr == NULL) { return (Ipc_E_FAIL); } /* for checking and incrementing attached below */ hwiKey = Hwi_disable(); /* Make sure its not already attached */ if (Ipc_module->procEntry[clusterId].attached) { Ipc_module->procEntry[clusterId].attached++; /* restore interrupts and return */ Hwi_restore(hwiKey); return (Ipc_S_ALREADYSETUP); } /* restore interrupts */ Hwi_restore(hwiKey); /* get region 0 information */ SharedRegion_getEntry(0, &entry); /* Make sure we've attached to owner of SR0 if we're not owner */ if ((MultiProc_self() != entry.ownerProcId) && (remoteProcId != entry.ownerProcId) && !(Ipc_module->procEntry[ti_sdo_utils_MultiProc_getClusterId( entry.ownerProcId)].attached)) { return (Ipc_E_FAIL); } /* Init error block */ Error_init(&eb); /* determine the slave's slot */ slave = Ipc_getSlaveAddr(remoteProcId, Ipc_module->ipcSharedAddr); if (cacheEnabled) { Cache_inv((Ptr)slave, reservedSize, Cache_Type_ALL, TRUE); } /* Synchronize the processors. */ status = Ipc_procSyncStart(remoteProcId, Ipc_module->ipcSharedAddr); if (status < 0) { return (status); } /* must be called before SharedRegion_attach */ status = ti_sdo_ipc_GateMP_attach(remoteProcId, Ipc_module->gateMPSharedAddr); if (status < 0) { return (status); } /* retrieves the SharedRegion Heap handles */ status = ti_sdo_ipc_SharedRegion_attach(remoteProcId); if (status < 0) { return (status); } /* get the attach parameters associated with remoteProcId */ ipc = &(Ipc_module->procEntry[clusterId]); /* attach Notify if not yet attached and specified to set internal setup */ if (!(Notify_intLineRegistered(remoteProcId, 0)) && (ipc->entry.setupNotify)) { /* call Notify_attach */ memReq = Notify_sharedMemReq(remoteProcId, Ipc_module->ipcSharedAddr); if (memReq != 0) { if (MultiProc_self() < remoteProcId) { /* * calloc required here due to race condition. Its possible * that the slave, who creates the instance, tries a sendEvent * before the master has created its instance because the * state of memory was enabled from a previous run. */ sharedAddr = Memory_calloc(SharedRegion_getHeap(0), memReq, SharedRegion_getCacheLineSize(0), &eb); /* make sure alloc did not fail */ if (sharedAddr == NULL) { return (Ipc_E_MEMORY); } /* if cache enabled, wbInv the calloc above */ if (cacheEnabled) { Cache_wbInv(sharedAddr, memReq, Cache_Type_ALL, TRUE); } /* set the notify SRPtr */ slave->notifySRPtr = SharedRegion_getSRPtr(sharedAddr, 0); } else { /* get the notify SRPtr */ sharedAddr = SharedRegion_getPtr(slave->notifySRPtr); } } else { sharedAddr = NULL; slave->notifySRPtr = 0; } /* call attach to remote processor */ status = Notify_attach(remoteProcId, sharedAddr); if (status < 0) { if (MultiProc_self() < remoteProcId && sharedAddr != NULL) { /* free the memory back to SharedRegion 0 heap */ Memory_free(SharedRegion_getHeap(0), sharedAddr, memReq); } return (Ipc_E_FAIL); } } /* Must come after GateMP_start because depends on default GateMP */ if (!(ti_sdo_utils_NameServer_isRegistered(remoteProcId)) && (ipc->entry.setupNotify)) { memReq = ti_sdo_utils_NameServer_SetupProxy_sharedMemReq( Ipc_module->ipcSharedAddr); if (memReq != 0) { if (MultiProc_self() < remoteProcId) { sharedAddr = Memory_alloc(SharedRegion_getHeap(0), memReq, SharedRegion_getCacheLineSize(0), &eb); /* make sure alloc did not fail */ if (sharedAddr == NULL) { return (Ipc_E_MEMORY); } /* set the NSRN SRPtr */ slave->nsrnSRPtr = SharedRegion_getSRPtr(sharedAddr, 0); } else { /* get the NSRN SRPtr */ sharedAddr = SharedRegion_getPtr(slave->nsrnSRPtr); } } else { sharedAddr = NULL; slave->nsrnSRPtr = 0; } /* call attach to remote processor */ status = ti_sdo_utils_NameServer_SetupProxy_attach(remoteProcId, sharedAddr); if (status < 0) { if (MultiProc_self() < remoteProcId && sharedAddr != NULL) { /* free the memory back to SharedRegion 0 heap */ Memory_free(SharedRegion_getHeap(0), sharedAddr, memReq); } return (Ipc_E_FAIL); } } /* Must come after GateMP_start because depends on default GateMP */ if (!(ti_sdo_ipc_MessageQ_SetupTransportProxy_isRegistered(remoteProcId)) && (ipc->entry.setupMessageQ)) { memReq = ti_sdo_ipc_MessageQ_SetupTransportProxy_sharedMemReq( Ipc_module->ipcSharedAddr); if (memReq != 0) { if (MultiProc_self() < remoteProcId) { sharedAddr = Memory_alloc(SharedRegion_getHeap(0), memReq, SharedRegion_getCacheLineSize(0), &eb); /* make sure alloc did not fail */ if (sharedAddr == NULL) { return (Ipc_E_MEMORY); } /* set the transport SRPtr */ slave->transportSRPtr = SharedRegion_getSRPtr(sharedAddr, 0); } else { /* get the transport SRPtr */ sharedAddr = SharedRegion_getPtr(slave->transportSRPtr); } } else { sharedAddr = NULL; slave->transportSRPtr = 0; } /* call attach to remote processor */ status = ti_sdo_ipc_MessageQ_SetupTransportProxy_attach(remoteProcId, sharedAddr); if (status < 0) { if (MultiProc_self() < remoteProcId && sharedAddr != NULL) { /* free the memory back to SharedRegion 0 heap */ Memory_free(SharedRegion_getHeap(0), sharedAddr, memReq); } return (Ipc_E_FAIL); } } /* writeback invalidate slave's shared memory if cache enabled */ if (cacheEnabled) { if (MultiProc_self() < remoteProcId) { Cache_wbInv((Ptr)slave, reservedSize, Cache_Type_ALL, TRUE); } } /* Call user attach fxns */ for (i = 0; i < ti_sdo_ipc_Ipc_numUserFxns; i++) { if (ti_sdo_ipc_Ipc_userFxns[i].userFxn.attach) { status = ti_sdo_ipc_Ipc_userFxns[i].userFxn.attach( ti_sdo_ipc_Ipc_userFxns[i].arg, remoteProcId); if (status < 0) { return (status); } } } /* Finish the processor synchronization */ status = ti_sdo_ipc_Ipc_procSyncFinish(remoteProcId, Ipc_module->ipcSharedAddr); if (status < 0) { return (status); } /* for atomically incrementing attached */ hwiKey = Hwi_disable(); /* now attached to remote processor */ Ipc_module->procEntry[clusterId].attached++; /* restore interrupts */ Hwi_restore(hwiKey); return (status); }
/* * ======== ListMP_insert ======== */ Int ListMP_insert(ListMP_Handle handle, ListMP_Elem *newElem, ListMP_Elem *curElem) { ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle; UInt key; Int id; ListMP_Elem *localPrevElem; SharedRegion_SRPtr sharedNewElem; SharedRegion_SRPtr sharedCurElem; Bool curElemIsCached, localPrevElemIsCached; /* prevent another thread or processor from modifying the ListMP */ key = GateMP_enter((GateMP_Handle)obj->gate); if (ti_sdo_ipc_SharedRegion_translate == FALSE) { sharedNewElem = (SharedRegion_SRPtr)newElem; sharedCurElem = (SharedRegion_SRPtr)curElem; localPrevElem = (ListMP_Elem *)(curElem->prev); } else { /* get SRPtr for newElem */ id = SharedRegion_getId(newElem); sharedNewElem = SharedRegion_getSRPtr(newElem, id); /* get SRPtr for curElem */ id = SharedRegion_getId(curElem); sharedCurElem = SharedRegion_getSRPtr(curElem, id); } curElemIsCached = SharedRegion_isCacheEnabled(SharedRegion_getId(curElem)); if (curElemIsCached) { Cache_inv(curElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE); } /* get Ptr for curElem->prev */ localPrevElem = SharedRegion_getPtr(curElem->prev); localPrevElemIsCached = SharedRegion_isCacheEnabled( SharedRegion_getId(localPrevElem)); if (localPrevElemIsCached) { Cache_inv(localPrevElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE); } newElem->next = sharedCurElem; newElem->prev = curElem->prev; localPrevElem->next = sharedNewElem; curElem->prev = sharedNewElem; if (localPrevElemIsCached) { Cache_wbInv(localPrevElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE); } /* * The next two Cache_wbInv needs to be done because curElem * and newElem are passed in and maybe already in the cache */ if (curElemIsCached) { /* writeback invalidate current elem structure */ Cache_wbInv(curElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE); } if (SharedRegion_isCacheEnabled(SharedRegion_getId(newElem))) { /* writeback invalidate new elem structure */ Cache_wbInv(newElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE); } GateMP_leave((GateMP_Handle)obj->gate, key); return (ListMP_S_SUCCESS); }
/* * ======== Ipc_detach ======== */ Int Ipc_detach(UInt16 remoteProcId) { Int i; UInt16 baseId = MultiProc_getBaseIdOfCluster(); UInt16 clusterId = ti_sdo_utils_MultiProc_getClusterId(remoteProcId); Ptr notifySharedAddr; Ptr nsrnSharedAddr; Ptr msgqSharedAddr; volatile ti_sdo_ipc_Ipc_Reserved *slave, *master; SharedRegion_Entry entry; ti_sdo_ipc_Ipc_ProcEntry *ipc; SizeT reservedSize = ti_sdo_ipc_Ipc_reservedSizePerProc(); Bool cacheEnabled = SharedRegion_isCacheEnabled(0); Int status = Ipc_S_SUCCESS; UInt hwiKey; /* Assert remoteProcId is in our cluster and isn't our own */ Assert_isTrue(clusterId < ti_sdo_utils_MultiProc_numProcsInCluster, ti_sdo_utils_MultiProc_A_invalidMultiProcId); Assert_isTrue(remoteProcId != MultiProc_self(), ti_sdo_ipc_Ipc_A_invArgument); /* for checking and incrementing attached below */ hwiKey = Hwi_disable(); if (Ipc_module->procEntry[clusterId].attached > 1) { /* only detach if attach count reaches 1 */ Ipc_module->procEntry[clusterId].attached--; Hwi_restore(hwiKey); return (Ipc_S_BUSY); } else if (Ipc_module->procEntry[clusterId].attached == 0) { /* already detached, restore interrupts and return success */ Hwi_restore(hwiKey); return (Ipc_S_SUCCESS); } /* restore interrupts */ Hwi_restore(hwiKey); /* get region 0 information */ SharedRegion_getEntry(0, &entry); /* * Make sure we detach from all other procs in cluster before * detaching from owner of SR 0. */ if (remoteProcId == entry.ownerProcId) { for (i = 0; i < ti_sdo_utils_MultiProc_numProcsInCluster; i++, baseId++) { if ((baseId != MultiProc_self()) && (baseId != entry.ownerProcId) && (Ipc_module->procEntry[i].attached)) { return (Ipc_E_FAIL); } } } /* get the paramters associated with remoteProcId */ ipc = &(Ipc_module->procEntry[clusterId]); /* determine the slave's slot */ slave = Ipc_getSlaveAddr(remoteProcId, Ipc_module->ipcSharedAddr); /* determine the master's slot */ master = ti_sdo_ipc_Ipc_getMasterAddr(remoteProcId, Ipc_module->ipcSharedAddr); if (cacheEnabled) { Cache_inv((Ptr)slave, reservedSize, Cache_Type_ALL, TRUE); Cache_inv((Ptr)master, reservedSize, Cache_Type_ALL, TRUE); } if (MultiProc_self() < remoteProcId) { /* check to make sure master is not trying to attach */ if (master->startedKey == ti_sdo_ipc_Ipc_PROCSYNCSTART) { return (Ipc_E_NOTREADY); } } else { /* check to make sure slave is not trying to attach */ if (slave->startedKey == ti_sdo_ipc_Ipc_PROCSYNCSTART) { return (Ipc_E_NOTREADY); } } /* The slave processor waits for master to finish its detach sequence */ if (MultiProc_self() < remoteProcId) { if (master->startedKey != ti_sdo_ipc_Ipc_PROCSYNCDETACH) { return (Ipc_E_NOTREADY); } } /* Call user detach fxns */ for (i = 0; i < ti_sdo_ipc_Ipc_numUserFxns; i++) { if (ti_sdo_ipc_Ipc_userFxns[i].userFxn.detach) { status = ti_sdo_ipc_Ipc_userFxns[i].userFxn.detach( ti_sdo_ipc_Ipc_userFxns[i].arg, remoteProcId); if (status < 0) { return (status); } } } if ((ipc->entry.setupMessageQ) && (ti_sdo_ipc_MessageQ_SetupTransportProxy_isRegistered(remoteProcId))) { /* call MessageQ_detach for remote processor */ status = ti_sdo_ipc_MessageQ_SetupTransportProxy_detach(remoteProcId); if (status < 0) { return (Ipc_E_FAIL); } if (slave->transportSRPtr) { /* free the memory if slave processor */ if (MultiProc_self() < remoteProcId) { /* get the pointer to MessageQ transport instance */ msgqSharedAddr = SharedRegion_getPtr(slave->transportSRPtr); /* free the memory back to SharedRegion 0 heap */ Memory_free(SharedRegion_getHeap(0), msgqSharedAddr, ti_sdo_ipc_MessageQ_SetupTransportProxy_sharedMemReq( msgqSharedAddr)); /* set pointer for MessageQ transport instance back to NULL */ slave->transportSRPtr = NULL; } } } if ((ipc->entry.setupNotify) && (ti_sdo_utils_NameServer_isRegistered(remoteProcId))) { /* call NameServer_SetupProxy_detach for remote processor */ status = ti_sdo_utils_NameServer_SetupProxy_detach(remoteProcId); if (status < 0) { return (Ipc_E_FAIL); } if (slave->nsrnSRPtr) { /* free the memory if slave processor */ if (MultiProc_self() < remoteProcId) { /* get the pointer to NSRN instance */ nsrnSharedAddr = SharedRegion_getPtr(slave->nsrnSRPtr); /* free the memory back to SharedRegion 0 heap */ Memory_free(SharedRegion_getHeap(0), nsrnSharedAddr, ti_sdo_utils_NameServer_SetupProxy_sharedMemReq( nsrnSharedAddr)); /* set pointer for NSRN instance back to NULL */ slave->nsrnSRPtr = NULL; } } } if ((ipc->entry.setupNotify) && (Notify_intLineRegistered(remoteProcId, 0))) { /* call Notify_detach for remote processor */ status = ti_sdo_ipc_Notify_detach(remoteProcId); if (status < 0) { return (Ipc_E_FAIL); } if (slave->notifySRPtr) { /* free the memory if slave processor */ if (MultiProc_self() < remoteProcId) { /* get the pointer to Notify instance */ notifySharedAddr = SharedRegion_getPtr(slave->notifySRPtr); /* free the memory back to SharedRegion 0 heap */ Memory_free(SharedRegion_getHeap(0), notifySharedAddr, Notify_sharedMemReq(remoteProcId, notifySharedAddr)); /* set pointer for Notify instance back to NULL */ slave->notifySRPtr = NULL; } } } /* close any HeapMemMP which may have been opened */ status = ti_sdo_ipc_SharedRegion_detach(remoteProcId); if (status < 0) { return (status); } /* close any GateMP which may have been opened */ status = ti_sdo_ipc_GateMP_detach(remoteProcId); if (status < 0) { return (status); } if (MultiProc_self() < remoteProcId) { slave->configListHead = ti_sdo_ipc_SharedRegion_INVALIDSRPTR; slave->startedKey = ti_sdo_ipc_Ipc_PROCSYNCDETACH; if (cacheEnabled) { Cache_wbInv((Ptr)slave, reservedSize, Cache_Type_ALL, TRUE); } } else { master->configListHead = ti_sdo_ipc_SharedRegion_INVALIDSRPTR; master->startedKey = ti_sdo_ipc_Ipc_PROCSYNCDETACH; if (cacheEnabled) { Cache_wbInv((Ptr)master, reservedSize, Cache_Type_ALL, TRUE); } } /* attached must be decremented atomically */ hwiKey = Hwi_disable(); /* now detached from remote processor */ Ipc_module->procEntry[clusterId].attached--; /* restore interrupts */ Hwi_restore(hwiKey); return (status); }
/* * ======== NotifyDriverShm_sendEvent ======== */ Int NotifyDriverShm_sendEvent(NotifyDriverShm_Object *obj, UInt32 eventId, UInt32 payload, Bool waitClear) { NotifyDriverShm_EventEntry *eventEntry; UInt32 i; UInt sysKey; eventEntry = EVENTENTRY(obj->otherEventChart, obj->eventEntrySize, eventId); /* Check whether driver on other processor is initialized */ if (obj->cacheEnabled) { Cache_inv(obj->otherProcCtrl, sizeof(NotifyDriverShm_ProcCtrl), Cache_Type_ALL, TRUE); } if (obj->otherProcCtrl->recvInitStatus != NotifyDriverShm_INIT_STAMP) { /* * This may be used for polling till the other driver is ready, so * do not assert or error */ return (Notify_E_NOTINITIALIZED); } /* Check to see if the remote event is enabled */ if (!TEST_BIT(obj->otherProcCtrl->eventEnableMask, eventId)) { return (Notify_E_EVTDISABLED); } /* Check to see if the remote event is registered */ if (!TEST_BIT(obj->otherProcCtrl->eventRegMask, eventId)) { return (Notify_E_EVTNOTREGISTERED); } if (waitClear) { i = 0; if (obj->cacheEnabled) { Cache_inv(eventEntry, sizeof(NotifyDriverShm_EventEntry), Cache_Type_ALL, TRUE); } /* * The system gate is needed to ensure that checking eventEntry->flag * is atomic with the eventEntry modifications (flag/payload). */ sysKey = Hwi_disable(); /* Wait for completion of previous event from other side. */ while ((eventEntry->flag != NotifyDriverShm_DOWN)) { /* * Leave critical section protection. Create a window * of opportunity for other interrupts to be handled. */ Hwi_restore(sysKey); i++; if ((i != (UInt32)-1) && (i == ti_sdo_ipc_Notify_sendEventPollCount)) { return (Notify_E_TIMEOUT); } if (obj->cacheEnabled) { Cache_inv(eventEntry, sizeof(NotifyDriverShm_EventEntry), Cache_Type_ALL, TRUE); } /* Re-enter the system gate */ sysKey = Hwi_disable(); } } else { /* * The system gate is needed to ensure that checking eventEntry->flag * is atomic with the eventEntry modifications (flag/payload). */ sysKey = Hwi_disable(); } /* Set the event bit field and payload.*/ eventEntry->payload = payload; eventEntry->flag = NotifyDriverShm_UP; if (obj->cacheEnabled) { Cache_wbInv(eventEntry, sizeof(NotifyDriverShm_EventEntry), Cache_Type_ALL, TRUE); } /* Send an interrupt to the Remote Processor */ NotifyDriverShm_InterruptProxy_intSend(obj->remoteProcId, &(obj->intInfo), eventId); /* must not restore interrupts before sending the interrupt */ Hwi_restore(sysKey); return (Notify_S_SUCCESS); }
/* * ======== ti_sdo_ipc_Ipc_procSyncStart ======== * The owner of SharedRegion 0 writes to its reserve memory address * in region 0 to let the other processors know it has started. * It then spins until the other processors start. * The other processors write their reserve memory address in * region 0 to let the owner processor know they've started. * The other processors then spin until the owner processor writes * to let them know that its finished the process of synchronization * before continuing. */ Int ti_sdo_ipc_Ipc_procSyncStart(UInt16 remoteProcId, Ptr sharedAddr) { volatile ti_sdo_ipc_Ipc_Reserved *self, *remote; ti_sdo_ipc_Ipc_ProcEntry *ipc; UInt16 clusterId = ti_sdo_utils_MultiProc_getClusterId(remoteProcId); SizeT reservedSize = ti_sdo_ipc_Ipc_reservedSizePerProc(); Bool cacheEnabled = SharedRegion_isCacheEnabled(0); /* don't do any synchronization if procSync is NONE */ if (ti_sdo_ipc_Ipc_procSync == ti_sdo_ipc_Ipc_ProcSync_NONE) { return (Ipc_S_SUCCESS); } /* determine self and remote pointers */ if (MultiProc_self() < remoteProcId) { self = Ipc_getSlaveAddr(remoteProcId, sharedAddr); remote = ti_sdo_ipc_Ipc_getMasterAddr(remoteProcId, sharedAddr); } else { self = ti_sdo_ipc_Ipc_getMasterAddr(remoteProcId, sharedAddr); remote = Ipc_getSlaveAddr(remoteProcId, sharedAddr); } /* construct the config list */ ipc = &(Ipc_module->procEntry[clusterId]); ipc->localConfigList = (Ptr)&self->configListHead; ipc->remoteConfigList = (Ptr)&remote->configListHead; *ipc->localConfigList = ti_sdo_ipc_SharedRegion_INVALIDSRPTR; if (cacheEnabled) { Cache_wbInv(ipc->localConfigList, reservedSize, Cache_Type_ALL, TRUE); } if (MultiProc_self() < remoteProcId) { /* set my processor's reserved key to start */ self->startedKey = ti_sdo_ipc_Ipc_PROCSYNCSTART; /* write back my processor's reserve key */ if (cacheEnabled) { Cache_wbInv((Ptr)self, reservedSize, Cache_Type_ALL, TRUE); } /* wait for remote processor to start */ if (cacheEnabled) { Cache_inv((Ptr)remote, reservedSize, Cache_Type_ALL, TRUE); } if (remote->startedKey != ti_sdo_ipc_Ipc_PROCSYNCSTART) { return (Ipc_E_NOTREADY); } } else { /* wait for remote processor to start */ if (cacheEnabled) { Cache_inv((Ptr)remote, reservedSize, Cache_Type_ALL, TRUE); } if ((self->startedKey != ti_sdo_ipc_Ipc_PROCSYNCSTART) && (remote->startedKey != ti_sdo_ipc_Ipc_PROCSYNCSTART)) { return (Ipc_E_NOTREADY); } /* set my processor's reserved key to start */ self->startedKey = ti_sdo_ipc_Ipc_PROCSYNCSTART; /* write my processor's reserve key back */ if (cacheEnabled) { Cache_wbInv((Ptr)self, reservedSize, Cache_Type_ALL, TRUE); /* wait for remote processor to finish */ Cache_inv((Ptr)remote, reservedSize, Cache_Type_ALL, TRUE); } if (remote->startedKey != ti_sdo_ipc_Ipc_PROCSYNCFINISH) { return (Ipc_E_NOTREADY); } } return (Ipc_S_SUCCESS); }
/* * ======== NotifyDriverShm_disableEvent ======== */ Void NotifyDriverShm_disableEvent(NotifyDriverShm_Object *obj, UInt32 eventId) { UInt sysKey; NotifyDriverShm_EventEntry *eventEntry; Assert_isTrue(eventId < ti_sdo_ipc_Notify_numEvents, ti_sdo_ipc_Ipc_A_invArgument); /* * Atomically unset the corresponding bit in the processor's * eventEnableMask */ sysKey = Hwi_disable(); CLEAR_BIT(obj->selfProcCtrl->eventEnableMask, eventId); Hwi_restore(sysKey); if (obj->cacheEnabled) { Cache_wbInv(obj->selfProcCtrl, sizeof(NotifyDriverShm_ProcCtrl), Cache_Type_ALL, TRUE); } eventEntry = EVENTENTRY(obj->selfEventChart, obj->eventEntrySize, eventId); if (obj->cacheEnabled) { Cache_inv(eventEntry, sizeof(NotifyDriverShm_EventEntry), Cache_Type_ALL, TRUE); } /* * Disable incoming Notify interrupts. This is done to ensure that the * eventEntry->flag is read atomically with any write back to shared * memory */ NotifyDriverShm_disable(obj); /* * Is the local NotifyDriverShm_disableEvent happening between the * following two NotifyDriverShm_sendEvent operations on the remote * processor? * 1. Writing NotifyDriverShm_UP to shared memory * 2. Sending the interrupt across * If so, we should handle this event so the other core isn't left spinning * until the event is re-enabled and the next NotifyDriverShm_isr executes * This race condition is very rare but we need to account for it: */ if (eventEntry->flag == NotifyDriverShm_UP) { /* * Acknowledge the event. No need to store the payload. The other side * will not send this event again even though flag is down, because the * event is now disabled. So the payload within the eventChart will not * get overwritten. */ eventEntry->flag = NotifyDriverShm_DOWN; /* Write back acknowledgement */ if (obj->cacheEnabled) { Cache_wbInv(eventEntry, sizeof(NotifyDriverShm_EventEntry), Cache_Type_ALL, TRUE); } /* * Execute the callback function. This will execute in a Task * or Swi context (not Hwi!) */ ti_sdo_ipc_Notify_exec(obj->notifyHandle, eventId, eventEntry->payload); } /* Re-enable incoming Notify interrupts */ NotifyDriverShm_enable(obj); }
/* * ======== NotifyDriverShm_isr ======== */ Void NotifyDriverShm_isr(UArg arg) { UInt i; NotifyDriverShm_EventEntry *eventEntry; NotifyDriverShm_Object *obj; UInt32 eventId; UInt32 payload; obj = (NotifyDriverShm_Object *)arg; /* Make sure the NotifyDriverShm_Object is not NULL */ Assert_isTrue(obj != NULL, ti_sdo_ipc_Ipc_A_internal); /* Clear the remote interrupt */ NotifyDriverShm_InterruptProxy_intClear(obj->remoteProcId, &(obj->intInfo)); /* * Iterate till no asserted event is found for one complete loop * through all registered events. */ i = 0; do { eventId = obj->regChart[i]; /* Check if the entry is a valid registered event. */ if (eventId != (UInt32)-1) { /* * Check whether the event is disabled. If so, avoid the * unnecessary Cache invalidate. NOTE: selfProcCtrl does not have * to be cache-invalidated because: * 1) Whenever self is written to by the local processor its memory * is also invalidated * 2) 'selfProcCtrl' is never written to by the remote processor */ if (!TEST_BIT(obj->selfProcCtrl->eventEnableMask, (UInt32)eventId)) { i++; continue; } eventEntry = EVENTENTRY(obj->selfEventChart, obj->eventEntrySize, eventId); if (obj->cacheEnabled) { Cache_inv(eventEntry, sizeof(NotifyDriverShm_EventEntry), Cache_Type_ALL, TRUE); } /* Check if the event is set */ if (eventEntry->flag == NotifyDriverShm_UP) { /* * Save the payload since it may be overwritten before * Notify_exec is called */ payload = eventEntry->payload; /* Acknowledge the event. */ eventEntry->flag = NotifyDriverShm_DOWN; /* Write back acknowledgement */ if (obj->cacheEnabled) { Cache_wbInv(eventEntry, sizeof(NotifyDriverShm_EventEntry), Cache_Type_ALL, TRUE); } /* Execute the callback function */ ti_sdo_ipc_Notify_exec(obj->notifyHandle, eventId, payload); /* reinitialize the event check counter. */ i = 0; } else { /* check for next event. */ i++; } } } while ((eventId != (UInt32)-1) && (i < ti_sdo_ipc_Notify_numEvents)); }
/* * ======== NotifyDriverShm_Instance_init ======== */ Int NotifyDriverShm_Instance_init(NotifyDriverShm_Object *obj, const NotifyDriverShm_Params *params, Error_Block *eb) { UInt16 regionId; SizeT regionCacheSize, minAlign, procCtrlSize; /* * Check whether remote proc ID has been set and isn't the same as the * local proc ID */ Assert_isTrue ((params->remoteProcId != MultiProc_INVALIDID) && (params->remoteProcId != MultiProc_self()), ti_sdo_ipc_Ipc_A_invParam); /* * Determine obj->cacheEnabled using params->cacheEnabled and SharedRegion * cache flag setting, if applicable. */ obj->cacheEnabled = params->cacheEnabled; minAlign = params->cacheLineSize; if (minAlign == 0) { /* Fix alignment of zero */ minAlign = sizeof(Ptr); } regionId = SharedRegion_getId(params->sharedAddr); if (regionId != SharedRegion_INVALIDREGIONID) { /* * Override the user cacheEnabled setting if the region * cacheEnabled is FALSE. */ if (!SharedRegion_isCacheEnabled(regionId)) { obj->cacheEnabled = FALSE; } regionCacheSize = SharedRegion_getCacheLineSize(regionId); /* * Override the user cache line size setting if the region * cache line size is smaller. */ if (regionCacheSize < minAlign) { minAlign = regionCacheSize; } } /* Check if shared memory base addr is aligned to cache line boundary.*/ Assert_isTrue ((UInt32)params->sharedAddr % minAlign == 0, ti_sdo_ipc_Ipc_A_addrNotCacheAligned); obj->remoteProcId = params->remoteProcId; /* * Store all interrupt information so it may be used (if neccessary) by * the IInterrupt delegates */ obj->intInfo.remoteIntId = params->remoteIntId; obj->intInfo.localIntId = params->localIntId; obj->intInfo.intVectorId = params->intVectorId; obj->nesting = 0; if (params->remoteProcId > MultiProc_self()) { obj->selfId = 0; obj->otherId = 1; } else { obj->selfId = 1; obj->otherId = 0; } /* Initialize pointers to shared memory regions */ procCtrlSize = _Ipc_roundup(sizeof(NotifyDriverShm_ProcCtrl), minAlign); /* * Save the eventEntrySize in obj since we will need it at runtime to * index the event charts */ obj->eventEntrySize = _Ipc_roundup(sizeof(NotifyDriverShm_EventEntry), minAlign); obj->selfProcCtrl = (NotifyDriverShm_ProcCtrl *) ((UInt32)params->sharedAddr + (obj->selfId * procCtrlSize)); obj->otherProcCtrl = (NotifyDriverShm_ProcCtrl *) ((UInt32)params->sharedAddr + (obj->otherId * procCtrlSize)); obj->selfEventChart = (NotifyDriverShm_EventEntry *) ((UInt32)params->sharedAddr + (2 * procCtrlSize) + (obj->eventEntrySize * ti_sdo_ipc_Notify_numEvents * obj->selfId)); obj->otherEventChart = (NotifyDriverShm_EventEntry *) ((UInt32)params->sharedAddr + (2 * procCtrlSize) + (obj->eventEntrySize * ti_sdo_ipc_Notify_numEvents * obj->otherId)); /* Allocate memory for regChart and init to (UInt32)-1 (unregistered) */ obj->regChart = Memory_valloc( NotifyDriverShm_Object_heap(), (sizeof(UInt32) * ti_sdo_ipc_Notify_numEvents), NULL, ~0, eb); if (obj->regChart == NULL) { return (1); } /* Enable all events initially.*/ obj->selfProcCtrl->eventEnableMask = 0xFFFFFFFF; /* Write back our own ProcCtrl */ if (obj->cacheEnabled) { Cache_wbInv(obj->selfProcCtrl, sizeof(NotifyDriverShm_ProcCtrl), Cache_Type_ALL, TRUE); } /* Register the incoming interrupt */ NotifyDriverShm_InterruptProxy_intRegister(obj->remoteProcId, &(obj->intInfo), (Fxn)NotifyDriverShm_isr, (UArg)obj); return (0); }
/* * ======== GatePetersonN_enter ======== */ IArg GatePetersonN_enter(GatePetersonN_Object *obj) { IArg key; SizeT numProcessors; SizeT myProcId; Int32 curStage; SizeT proc; /* Enter local gate */ key = IGateProvider_enter(obj->localGate); /* If the gate object has already been entered, return the key */ obj->nested++; if (obj->nested > 1) { return (key); } numProcessors = obj->numProcessors; myProcId = obj->selfId; for (curStage=0; curStage < (numProcessors - 1); curStage++) { *(obj->enteredStage[myProcId]) = curStage; *(obj->lastProcEnteringStage[curStage]) = myProcId; if (obj->cacheEnabled) { Cache_wbInv((Ptr)obj->enteredStage[myProcId], obj->cacheLineSize, Cache_Type_ALL, FALSE); Cache_wbInv((Ptr)obj->lastProcEnteringStage[curStage], obj->cacheLineSize, Cache_Type_ALL, TRUE); } for (proc=0; proc < numProcessors; proc++) { if (proc != myProcId) { if (obj->cacheEnabled) { Cache_inv((Ptr)obj->enteredStage[proc], obj->cacheLineSize, Cache_Type_ALL, FALSE); Cache_inv((Ptr)obj->lastProcEnteringStage[curStage], obj->cacheLineSize, Cache_Type_ALL, TRUE); } while ((*(obj->enteredStage[proc]) >= curStage) && (*(obj->lastProcEnteringStage[curStage]) == myProcId)) { /* wait till 'proc' leaves or another 'proc' enters stage */ if (obj->cacheEnabled) { Cache_inv((Ptr)obj->enteredStage[proc], obj->cacheLineSize, Cache_Type_ALL, FALSE); Cache_inv((Ptr)obj->lastProcEnteringStage[curStage], obj->cacheLineSize, Cache_Type_ALL, TRUE); } } } } } /* stages */ return (key); }
/* * ======== ListMP_getTail ======== */ Ptr ListMP_getTail(ListMP_Handle handle) { ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle; ListMP_Elem *elem; ListMP_Elem *localHeadPrev; ListMP_Elem *localPrev; Bool localPrevIsCached; UInt key; /* prevent another thread or processor from modifying the ListMP */ key = GateMP_enter((GateMP_Handle)obj->gate); if (ti_sdo_ipc_SharedRegion_translate == FALSE) { localHeadPrev = (ListMP_Elem *)obj->attrs->head.prev; } else { localHeadPrev = SharedRegion_getPtr(obj->attrs->head.prev); } /* Assert that pointer is not NULL */ Assert_isTrue(localHeadPrev != NULL, ti_sdo_ipc_Ipc_A_nullPointer); /* See if the ListMP was empty */ if (localHeadPrev == (ListMP_Elem *)(&(obj->attrs->head))) { /* Empty, return NULL */ elem = NULL; } else { if (SharedRegion_isCacheEnabled(SharedRegion_getId(localHeadPrev))) { /* invalidate elem */ Cache_inv(localHeadPrev, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE); } if (ti_sdo_ipc_SharedRegion_translate == FALSE) { localPrev = (ListMP_Elem *)localHeadPrev->prev; } else { localPrev = SharedRegion_getPtr(localHeadPrev->prev); } /* Assert that pointer is not NULL */ Assert_isTrue(localPrev != NULL, ti_sdo_ipc_Ipc_A_nullPointer); /* Elem to return */ elem = localHeadPrev; localPrevIsCached = SharedRegion_isCacheEnabled( SharedRegion_getId(localPrev)); if (localPrevIsCached) { Cache_inv(localPrev, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE); } /* Fix the head of the list prev pointer */ obj->attrs->head.prev = elem->prev; /* Fix the next pointer of the new last elem on the list */ localPrev->next = localHeadPrev->next; if (localPrevIsCached) { Cache_wbInv(localPrev, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE); } } if (obj->cacheEnabled) { Cache_wbInv(&(obj->attrs->head), sizeof(ListMP_Elem), Cache_Type_ALL, TRUE); } GateMP_leave((GateMP_Handle)obj->gate, key); return (elem); }
/* * ======== ti_sdo_ipc_ListMP_Instance_init ======== */ Int ti_sdo_ipc_ListMP_Instance_init(ti_sdo_ipc_ListMP_Object *obj, const ti_sdo_ipc_ListMP_Params *params, Error_Block *eb) { SharedRegion_SRPtr sharedShmBase; Ptr localAddr; Int status; ListMP_Params sparams; IHeap_Handle regionHeap; if (params->openFlag == TRUE) { /* Open by sharedAddr */ obj->objType = ti_sdo_ipc_Ipc_ObjType_OPENDYNAMIC; obj->attrs = (ti_sdo_ipc_ListMP_Attrs *)params->sharedAddr; obj->regionId = SharedRegion_getId(&(obj->attrs->head)); obj->cacheEnabled = SharedRegion_isCacheEnabled(obj->regionId); obj->cacheLineSize = SharedRegion_getCacheLineSize(obj->regionId); /* get the local address of the SRPtr */ localAddr = SharedRegion_getPtr(obj->attrs->gateMPAddr); status = GateMP_openByAddr(localAddr, (GateMP_Handle *)&(obj->gate)); if (status != GateMP_S_SUCCESS) { Error_raise(eb, ti_sdo_ipc_Ipc_E_internal, 0, 0); return (1); } return (0); } /* init the gate */ if (params->gate != NULL) { obj->gate = params->gate; } else { obj->gate = (ti_sdo_ipc_GateMP_Handle)GateMP_getDefaultRemote(); } if (params->sharedAddr == NULL) { /* Creating using a shared region ID */ obj->objType = ti_sdo_ipc_Ipc_ObjType_CREATEDYNAMIC_REGION; obj->regionId = params->regionId; obj->cacheEnabled = SharedRegion_isCacheEnabled(obj->regionId); obj->cacheLineSize = SharedRegion_getCacheLineSize(obj->regionId); /* Need to allocate from the heap */ ListMP_Params_init(&sparams); sparams.regionId = params->regionId; obj->allocSize = ListMP_sharedMemReq(&sparams); regionHeap = SharedRegion_getHeap(obj->regionId); Assert_isTrue(regionHeap != NULL, ti_sdo_ipc_SharedRegion_A_noHeap); /* The region heap will take care of the alignment */ obj->attrs = Memory_alloc(regionHeap, obj->allocSize, 0, eb); if (obj->attrs == NULL) { return (2); } } else { /* Creating using sharedAddr */ obj->regionId = SharedRegion_getId(params->sharedAddr); /* Assert that the buffer is in a valid shared region */ Assert_isTrue(obj->regionId != SharedRegion_INVALIDREGIONID, ti_sdo_ipc_Ipc_A_addrNotInSharedRegion); /* set object's cacheEnabled, objType, and attrs */ obj->cacheEnabled = SharedRegion_isCacheEnabled(obj->regionId); obj->cacheLineSize = SharedRegion_getCacheLineSize(obj->regionId); obj->objType = ti_sdo_ipc_Ipc_ObjType_CREATEDYNAMIC; obj->attrs = (ti_sdo_ipc_ListMP_Attrs *)params->sharedAddr; /* Assert that sharedAddr is cache aligned */ Assert_isTrue((obj->cacheLineSize == 0) || ((UInt32)params->sharedAddr % obj->cacheLineSize == 0), ti_sdo_ipc_Ipc_A_addrNotCacheAligned); } /* init the head (to be empty) */ ListMP_elemClear(&(obj->attrs->head)); /* store the GateMP sharedAddr in the Attrs */ obj->attrs->gateMPAddr = ti_sdo_ipc_GateMP_getSharedAddr(obj->gate); /* last thing, set the status */ obj->attrs->status = ti_sdo_ipc_ListMP_CREATED; if (obj->cacheEnabled) { Cache_wbInv(obj->attrs, sizeof(ti_sdo_ipc_ListMP_Attrs), Cache_Type_ALL, TRUE); } /* add to NameServer if name not NULL */ if (params->name != NULL) { sharedShmBase = SharedRegion_getSRPtr(obj->attrs, obj->regionId); obj->nsKey = NameServer_addUInt32( (NameServer_Handle)ListMP_module->nameServer, params->name, (UInt32)sharedShmBase); if (obj->nsKey == NULL) { Error_raise(eb, ti_sdo_ipc_Ipc_E_nameFailed, params->name, 0); return (3); } } return (0); }