/* * ======== ListMP_prev ======== */ Ptr ListMP_prev(ListMP_Handle handle, ListMP_Elem *elem) { ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle; ListMP_Elem *retElem; /* returned elem */ Bool elemIsCached; /* elem == NULL -> start at the head */ if (elem == NULL) { elemIsCached = obj->cacheEnabled; elem = (ListMP_Elem *)&(obj->attrs->head); } else { elemIsCached = SharedRegion_isCacheEnabled(SharedRegion_getId(elem)); } if (elemIsCached) { Cache_inv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE); } retElem = SharedRegion_getPtr(elem->prev); if (retElem == (ListMP_Elem *)(&(obj->attrs->head))) { retElem = NULL; } if (elemIsCached) { /* Invalidate because elem pulled into cache && elem != head. */ Cache_inv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE); } return (retElem); }
/* * ======== Ipc_readConfig ======== */ Int Ipc_readConfig(UInt16 remoteProcId, UInt32 tag, Ptr cfg, SizeT size) { Int status = Ipc_E_FAIL; UInt16 clusterId = ti_sdo_utils_MultiProc_getClusterId(remoteProcId); volatile ti_sdo_ipc_Ipc_ConfigEntry *entry; Bool cacheEnabled = SharedRegion_isCacheEnabled(0); /* Assert that the remoteProc in our cluster and isn't our own */ Assert_isTrue(clusterId < ti_sdo_utils_MultiProc_numProcsInCluster, ti_sdo_utils_MultiProc_A_invalidMultiProcId); if (cacheEnabled) { Cache_inv(Ipc_module->procEntry[clusterId].remoteConfigList, SharedRegion_getCacheLineSize(0), Cache_Type_ALL, TRUE); } entry = (ti_sdo_ipc_Ipc_ConfigEntry *) *Ipc_module->procEntry[clusterId].remoteConfigList; while ((SharedRegion_SRPtr)entry != ti_sdo_ipc_SharedRegion_INVALIDSRPTR) { entry = (ti_sdo_ipc_Ipc_ConfigEntry *) SharedRegion_getPtr((SharedRegion_SRPtr)entry); /* Traverse the list to find the tag */ if (cacheEnabled) { Cache_inv((Ptr)entry, size + sizeof(ti_sdo_ipc_Ipc_ConfigEntry), Cache_Type_ALL, TRUE); } if ((entry->remoteProcId == MultiProc_self()) && (entry->localProcId == remoteProcId) && (entry->tag == tag)) { if (size == entry->size) { memcpy(cfg, (Ptr)((UInt32)entry + sizeof(ti_sdo_ipc_Ipc_ConfigEntry)), entry->size); return (Ipc_S_SUCCESS); } else { return (Ipc_E_FAIL); } } entry = (ti_sdo_ipc_Ipc_ConfigEntry *)entry->next; } return (status); }
/* * ======== 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); }
void CacheInvalShrinkData(const uint8_T *Img, const uint8_T *ImgSmall, const uint32_t yStart, const uint32_t yEnd, const uint32_t yEvenOdd, const uint32_t xWidth, const uint32_t xWidthSmall) { if (0 != MultiProc_self()) //skip on main core { #if 0 //Invalidate input image data uint8_T* in_buf_start; uint32_T in_buf_size; CalcInputBufferPos(Img, yStart, yEnd, yEvenOdd, xWidth, in_buf_start, in_buf_size); Cache_inv((xdc_Ptr*) in_buf_start, in_buf_size, Cache_Type_ALL, CACHE_BLOCKING); //Blocking because we will process the data immediately #endif //Invalidate parts of the output cache, because the main core zeroed memory after boot (or after the last calculation was finished when the DSP was idle) //In CacheWriteBackShrinkData() we push all image data, the data we wrote to and also the end of the lines which we didn't touch here. Because we didn't //touch the end of the lines (and left it black) we have to cacheinval it here to be sure its blackness is known to this core). /* Should be unnecessary since I introduced CacheInvalShrinkData() uint8_T* out_buf_start; uint32_T out_buf_size; CalcOutputBufferPos(ImgSmall, yStart, yEnd, xWidthSmall, out_buf_start, out_buf_size); Cache_inv((xdc_Ptr*) out_buf_start, out_buf_size, Cache_Type_ALL, CACHE_BLOCKING); //Blocking because we will process the data immediately */ } }
/* Function to write back invalidate the Cache module */ Void Cache_wbInv(Ptr blockPtr, UInt32 byteCnt, Bits16 type, Bool wait) { GT_4trace (curTrace, GT_ENTER, "Cache_wbInv", blockPtr, byteCnt, type, wait); #if 0 /* * It appears that this #if 0'ed code doesn't actually perform the * invalidate part of the wbInv, and it appears that Cache_wb() and Cache_inv() * work properly, so for now we implement wbInv as a combination of the two * individual functions. */ #ifdef USE_CACHE_VOID_ARG #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34) dmac_map_area(blockPtr, (size_t)byteCnt, DMA_BIDIRECTIONAL); outer_flush_range(__pa((UInt32)blockPtr), __pa((UInt32)(blockPtr+byteCnt)) ); #else dmac_flush_range(blockPtr, (blockPtr+byteCnt) ); #endif #else dmac_flush_range( (UInt32)blockPtr, (UInt32)(blockPtr + byteCnt) ); #endif #else Cache_wb(blockPtr, byteCnt, type, wait); Cache_inv(blockPtr, byteCnt, type, wait); #endif GT_0trace (curTrace, GT_LEAVE, "Cache_wbInv"); }
/* * ======== 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); }
/** * Cache invalidate image data if necessary */ void CacheInvalImageData(process_message_t* p_msg) { if(0 != p_msg->info.NewImageDataArrived) { if (0 != MultiProc_self()) { #ifdef _TRACE_MC_ logout("[core_%u] CACHE INVALIDATE IMAGE DATA ON SLAVE CORE (T %u bytes, R %u bytes)\n", p_msg->core_id, p_msg->info.Tsize, p_msg->info.Rsize); #endif Cache_inv((xdc_Ptr*) p_msg->info.Tvec, p_msg->info.Tsize , Cache_Type_ALL, CACHE_BLOCKING); Cache_inv((xdc_Ptr*) p_msg->info.Rvec, p_msg->info.Rsize , Cache_Type_ALL, CACHE_BLOCKING); } else { #ifdef _TRACE_MC_ logout("[core_%u] CACHE INVALIDATE SKIPPED ON MAIN CORE (T %u bytes, R %u bytes)\n", p_msg->core_id, p_msg->info.Tsize, p_msg->info.Rsize); #endif } } }
/* * ======== 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); }
/* * ======== Memory_cacheInv ======== */ Void Memory_cacheInv(Ptr addr, Int sizeInBytes) { Log_print2(Diags_ENTRY, "[+E] Memory_cacheInv> " "Enter(addr=0x%x, sizeInBytes=%d)", (IArg)addr, (IArg)sizeInBytes); Cache_inv(addr, sizeInBytes, Cache_Type_ALL, TRUE); Log_print0(Diags_EXIT, "[+X] Memory_cacheInv> return"); }
/* * ======== ListMP_openByAddr ======== */ Int ListMP_openByAddr(Ptr sharedAddr, ListMP_Handle *handlePtr) { ti_sdo_ipc_ListMP_Params params; ti_sdo_ipc_ListMP_Attrs *attrs; Error_Block eb; Int status; UInt16 id; Error_init(&eb); ti_sdo_ipc_ListMP_Params_init(¶ms); /* Tell Instance_init() that we're opening */ params.openFlag = TRUE; attrs = (ti_sdo_ipc_ListMP_Attrs *)sharedAddr; params.sharedAddr = sharedAddr; id = SharedRegion_getId(sharedAddr); if (SharedRegion_isCacheEnabled(id)) { Cache_inv(attrs, sizeof(ti_sdo_ipc_ListMP_Attrs), Cache_Type_ALL, TRUE); } if (attrs->status != ti_sdo_ipc_ListMP_CREATED) { *handlePtr = NULL; status = ListMP_E_NOTFOUND; } else { /* Create the object */ *handlePtr = (ListMP_Handle)ti_sdo_ipc_ListMP_create(¶ms, &eb); if (*handlePtr == NULL) { status = ListMP_E_FAIL; } else { status = ListMP_S_SUCCESS; } } if (SharedRegion_isCacheEnabled(id)) { Cache_inv(attrs, sizeof(ti_sdo_ipc_ListMP_Attrs), Cache_Type_ALL, TRUE); } return (status); }
/* * ======== TransportShm_openByAddr ======== */ Int TransportShm_openByAddr(Ptr sharedAddr, TransportShm_Handle *handlePtr, Error_Block *eb) { TransportShm_Params params; TransportShm_Attrs *attrs; Int status; UInt16 id; if (sharedAddr == NULL) { return (MessageQ_E_FAIL); } TransportShm_Params_init(¶ms); /* Tell Instance_init() that we're opening */ params.openFlag = TRUE; attrs = (TransportShm_Attrs *)sharedAddr; id = SharedRegion_getId(sharedAddr); /* Assert that the region is valid */ Assert_isTrue(id != SharedRegion_INVALIDREGIONID, ti_sdo_ipc_Ipc_A_addrNotInSharedRegion); /* invalidate the attrs before using it */ if (SharedRegion_isCacheEnabled(id)) { Cache_inv(attrs, sizeof(TransportShm_Attrs), Cache_Type_ALL, TRUE); } /* set params field */ params.sharedAddr = sharedAddr; params.priority = attrs->priority; if (attrs->flag != TransportShm_UP) { /* make sure transport is up */ *handlePtr = NULL; status = MessageQ_E_NOTFOUND; } else { /* Create the object */ *handlePtr = TransportShm_create(attrs->creatorProcId, ¶ms, eb); if (*handlePtr == NULL) { status = MessageQ_E_FAIL; } else { status = MessageQ_S_SUCCESS; } } return (status); }
/** * Cache invalidate the total image memory (happens after the main core zeroizes all memory (at boot time and after/between the calculations) */ void CacheInvalTotalMemory(process_message_t* p_msg) { if (0 != MultiProc_self()) { #ifdef _TRACE_MC_ logout("[core_%u] CACHE INVALIDATE ZEROIZRD DATA ON SLAVE CORE (T %u bytes, R %u bytes)\n", p_msg->core_id, p_msg->info.Tsize, p_msg->info.Rsize); #endif Cache_inv((xdc_Ptr*) p_msg->info.Tvec, p_msg->info.Tsize , Cache_Type_ALL, CACHE_BLOCKING); } else { #ifdef _TRACE_MC_ //The following shouldn't happen ... logout("[core_%u] CACHE INVALIDATE ZEROIZRD DATA SKIPPED ON MAIN CORE (T %u bytes, R %u bytes)\n", p_msg->core_id, p_msg->info.Tsize, p_msg->info.Rsize); #endif } }
/** * Public, called from shrinkImageDSP (on the main core) after entering shrinkImage_on_core() */ void CacheInvalReadyShrinkedData(const uint8_T *ImgSmall, const uint32_t yStart, const uint32_t yEnd, const uint32_t xWidthSmall) { #ifdef _NO_IPC_TEST_ if (0 == MultiProc_self()) //skip on main core return; #else //ASSERT(0 == MultiProc_self()); #endif #if 0 //Invalidate the output cache, we need the data the other cores wrote to. uint8_T* out_buf_start; uint32_T out_buf_size; CalcOutputBufferPos(ImgSmall, yStart, yEnd, xWidthSmall, out_buf_start, out_buf_size); Cache_inv((xdc_Ptr*) out_buf_start, out_buf_size, Cache_Type_ALL, CACHE_BLOCKING); //Blocking because we will process the data immediately #endif }
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); }
/* * ======== SemaphoreMP_openByAddr ======== */ Int SemaphoreMP_openByAddr(Ptr sharedAddr, SemaphoreMP_Handle *handlePtr) { SemaphoreMP_Params params; SemaphoreMP_Attrs *attrs; Int status; Error_Block eb; Error_init(&eb); SemaphoreMP_Params_init(¶ms); /* Tell Instance_init() that we're opening */ params.openFlag = TRUE; params.sharedAddr = sharedAddr; attrs = (SemaphoreMP_Attrs *)sharedAddr; if (SharedRegion_isCacheEnabled(SharedRegion_getId(sharedAddr))) { Cache_inv(attrs, sizeof(SemaphoreMP_Attrs), Cache_Type_ALL, TRUE); } if (attrs->status != SemaphoreMP_CREATED) { *handlePtr = NULL; status = -1; //SemaphoreMP_E_NOTFOUND; } else { *handlePtr = SemaphoreMP_create(0, ¶ms, &eb); if (*handlePtr == NULL) { status = -1; //SemaphoreMP_E_FAIL; } else { status = 0; //SemaphoreMP_S_SUCCESS; } } return (status); }
/* * ======== ListMP_empty ======== */ Bool ListMP_empty(ListMP_Handle handle) { ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle; Bool flag = FALSE; IArg key; SharedRegion_SRPtr sharedHead; /* prevent another thread or processor from modifying the ListMP */ key = GateMP_enter((GateMP_Handle)obj->gate); if (ti_sdo_ipc_SharedRegion_translate == FALSE) { /* get the SRPtr for the head */ sharedHead = (SharedRegion_SRPtr)&(obj->attrs->head); } else { /* get the SRPtr for the head */ sharedHead = SharedRegion_getSRPtr(&(obj->attrs->head), obj->regionId); } /* if 'next' is ourself, then the ListMP must be empty */ if (obj->attrs->head.next == sharedHead) { flag = TRUE; } if (obj->cacheEnabled) { /* invalidate the head to make sure we are not getting stale data */ Cache_inv(&(obj->attrs->head), sizeof(ListMP_Elem), Cache_Type_ALL, TRUE); } /* leave the gate */ GateMP_leave((GateMP_Handle)obj->gate, key); return (flag); }
/* * ======== 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); }
/* * ======== 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); }
/* * ======== Ipc_start ======== */ Int Ipc_start() { Int i; UInt16 baseId = MultiProc_getBaseIdOfCluster(); SharedRegion_Entry entry; Ptr ipcSharedAddr; Ptr gateMPSharedAddr; GateMP_Params gateMPParams; Int status; /* Check whether Ipc_start has been called. If so, succeed. */ if (Ipc_module->ipcSharedAddr != NULL) { return (Ipc_S_ALREADYSETUP); } if (ti_sdo_ipc_Ipc_generateSlaveDataForHost) { /* get Ipc_sr0MemorySetup out of the cache */ Cache_inv(&Ipc_sr0MemorySetup, sizeof(Ipc_sr0MemorySetup), Cache_Type_ALL, TRUE); /* check Ipc_sr0MemorySetup variable */ if (Ipc_sr0MemorySetup == 0x0) { return (Ipc_E_NOTREADY); } } /* get region 0 information */ SharedRegion_getEntry(0, &entry); /* if entry is not valid then return */ if (entry.isValid == FALSE) { return (Ipc_E_NOTREADY); } /* * Need to reserve memory in region 0 for processor synchronization. * This must done before SharedRegion_start(). */ ipcSharedAddr = ti_sdo_ipc_SharedRegion_reserveMemory( 0, Ipc_getRegion0ReservedSize()); /* must reserve memory for GateMP before SharedRegion_start() */ gateMPSharedAddr = ti_sdo_ipc_SharedRegion_reserveMemory(0, ti_sdo_ipc_GateMP_getRegion0ReservedSize()); /* Init params for default gate (must match those in GateMP_start()) */ GateMP_Params_init(&gateMPParams); gateMPParams.localProtect = GateMP_LocalProtect_TASKLET; if (ti_sdo_utils_MultiProc_numProcessors > 1) { gateMPParams.remoteProtect = GateMP_RemoteProtect_SYSTEM; } else { gateMPParams.remoteProtect = GateMP_RemoteProtect_NONE; } /* reserve memory for default gate before SharedRegion_start() */ ti_sdo_ipc_SharedRegion_reserveMemory(0, GateMP_sharedMemReq(&gateMPParams)); /* clear the reserved memory */ ti_sdo_ipc_SharedRegion_clearReservedMemory(); /* Set shared addresses */ Ipc_module->ipcSharedAddr = ipcSharedAddr; Ipc_module->gateMPSharedAddr = gateMPSharedAddr; /* create default GateMP, must be called before SharedRegion start */ status = ti_sdo_ipc_GateMP_start(Ipc_module->gateMPSharedAddr); if (status < 0) { return (status); } /* create HeapMemMP in each SharedRegion */ status = ti_sdo_ipc_SharedRegion_start(); if (status < 0) { return (status); } /* Call attach for all procs if procSync is ALL */ if (ti_sdo_ipc_Ipc_procSync == ti_sdo_ipc_Ipc_ProcSync_ALL) { /* Must attach to owner first to get default GateMP and HeapMemMP */ if (MultiProc_self() != entry.ownerProcId) { do { status = Ipc_attach(entry.ownerProcId); } while (status == Ipc_E_NOTREADY); if (status < 0) { /* Ipc_attach failed. Get out of Ipc_start */ return (status); } } /* Loop to attach to all other processors in cluster */ for (i = 0; i < ti_sdo_utils_MultiProc_numProcsInCluster; i++, baseId++) { if ((baseId == MultiProc_self()) || (baseId == entry.ownerProcId)) { continue; } /* Skip the processor if there are no interrupt lines to it */ if (Notify_numIntLines(baseId) == 0) { continue; } /* call Ipc_attach for every remote processor */ do { status = Ipc_attach(baseId); } while (status == Ipc_E_NOTREADY); if (status < 0) { /* Ipc_attach failed. Get out of Ipc_start */ return (status); } } } return (status); }
/* * ======== SemaphoreMP_pend ======== */ Bool SemaphoreMP_pend(SemaphoreMP_Object *obj) { UInt tskKey; SemaphoreMP_PendElem *elem; IArg gateMPKey; /* Check for correct calling context */ Assert_isTrue((BIOS_getThreadType() == BIOS_ThreadType_Task), SemaphoreMP_A_badContext); elem = ThreadLocal_getspecific(SemaphoreMP_pendElemKey); if (elem == NULL) { /* * Choose region zero (instead of the region that contains the * SemaphoreMP) since region zero is always accessible by all cores */ elem = Memory_alloc(SharedRegion_getHeap(0), sizeof(SemaphoreMP_PendElem), 0, NULL); ThreadLocal_setspecific(SemaphoreMP_pendElemKey, elem); } /* Enter the gate */ gateMPKey = GateMP_enter((GateMP_Handle)obj->gate); if (obj->cacheEnabled) { Cache_inv(obj->attrs, sizeof(SemaphoreMP_Attrs), Cache_Type_ALL, TRUE); } /* check semaphore count */ if (obj->attrs->count == 0) { /* lock task scheduler */ tskKey = Task_disable(); /* get task handle and block tsk */ elem->task = (Bits32)Task_self(); elem->procId = MultiProc_self(); Task_block((Task_Handle)elem->task); if (obj->cacheEnabled) { Cache_wbInv(elem, sizeof(SemaphoreMP_PendElem), Cache_Type_ALL, TRUE); } /* add it to pendQ */ ListMP_putTail((ListMP_Handle)obj->pendQ, (ListMP_Elem *)elem); /* Leave the gate */ GateMP_leave((GateMP_Handle)obj->gate, gateMPKey); Task_restore(tskKey);/* the calling task will switch out here */ return (TRUE); } 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 (TRUE); } }
/* * ======== 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); }
/* * ======== 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); }
/* * ======== 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); }
/* * ======== 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); }
/* * ======== 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)); }
/* * ======== 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); }