PUBLIC void cm_PWR_DisableMPC( t_mpc_power_request request, t_nmf_core_id coreId) { switch(request) { case MPC_PWR_CLOCK: LOG_INTERNAL(__PWR_DEBUG_TRACE_LEVEL, "[Pwr] MPC %s disable clock\n",cm_getDspName(coreId), 0, 0, 0, 0, 0); OSAL_DisablePwrRessource(CM_OSAL_POWER_SxA_CLOCK, coreId, 0); break; case MPC_PWR_AUTOIDLE: OSAL_DisablePwrRessource(CM_OSAL_POWER_SxA_AUTOIDLE, coreId, 0); break; case MPC_PWR_HWIP: if(--_pwrMPCHWIPCountT[coreId] == 0) { LOG_INTERNAL(__PWR_DEBUG_TRACE_LEVEL, "[Pwr] MPC %s HW IP disable clock\n",cm_getDspName(coreId), 0, 0, 0, 0, 0); // The PRCMU seem not supporting the transition of asking HW IP on while DSP in retention // -> Thus force wake up of the MMDSP before asking the transition if (cm_EEM_ForceWakeup(coreId) != CM_OK) return; OSAL_DisablePwrRessource(CM_OSAL_POWER_SxA_HARDWARE, coreId, 0); cm_EEM_AllowSleep(coreId); } break; } }
t_bool cm_unregisterSingletonBinding( t_component_instance* component, t_interface_require_description* itfRequire, t_interface_provide_description* itfProvide, t_nmf_client_id clientId) { if(component->Template->classe == SINGLETON) { struct t_client_of_singleton* cl = cm_getClientOfSingleton(component, FALSE, clientId); if(cl != NULL) cl->numberOfBind--; if(itfProvide->server == (t_component_instance *)NMF_VOID_COMPONENT) LOG_INTERNAL(1, " -> Singleton[%d] : Unregister binding %s/%x.%s -> ARM/VOID\n", clientId, itfRequire->client->pathname, itfRequire->client, itfRequire->origName, 0, 0); else if(itfProvide->server == NULL) LOG_INTERNAL(1, " -> Singleton[%d] : Unregister binding %s/%x.%s -> ?? <already unbound>\n", clientId, itfRequire->client->pathname, itfRequire->client, itfRequire->origName, 0, 0); else LOG_INTERNAL(1, " -> Singleton[%d] : Unregister binding %s/%x.%s -> %s/%x\n", clientId, itfRequire->client->pathname, itfRequire->client, itfRequire->origName, itfProvide->server->pathname, itfProvide->server); if(getNumberOfBind(component) == 0) { LOG_INTERNAL(1, " -> Singleton[%d] : All required of %s/%x logically unbound, perform physical unbind\n", clientId, itfRequire->client->pathname, itfRequire->client, 0, 0, 0); (void)cm_EEM_ForceWakeup(component->Template->dspId); // This is the last binding unbind all !!! cm_destroyRequireInterface(component, clientId); cm_EEM_AllowSleep(component->Template->dspId); } else if(itfProvide->server != NULL) { t_interface_require* itfReq; itfReq = &itfRequire->client->Template->requires[itfRequire->requireIndex]; if((itfReq->requireTypes & OPTIONAL_REQUIRE) != 0x0) return TRUE; } return FALSE; } return TRUE; }
/*! * */ void cm_unbindInterfaceDistributed( const t_interface_require_description *itfRequire, t_mpc2mpc_bf_info *bfInfo) { LOG_INTERNAL(1, "\n##### UnBind distributed %s/%x.%s #####\n", itfRequire->client->pathname, itfRequire->client, itfRequire->origName, 0, 0, 0); cm_TRC_traceBinding(TRACE_BIND_COMMAND_UNBIND_ASYNCHRONOUS, itfRequire->client, NULL, itfRequire->client->Template->requires[itfRequire->requireIndex].name, NULL); /* Unbind virtual interface */ cm_unbindVirtualInterface(bfInfo->dspstub.stubInstance); // Destroy FIFO params cm_destroyParamsFifo(bfInfo->fifo); // Destroy DSP Stub cm_destroyDSPStub(itfRequire, &bfInfo->dspstub); // Destory DSP Skeleton cm_destroyDSPSkeleton(&bfInfo->dspskeleton); // Destroy BF Info OSAL_Free(bfInfo); }
void cm_unbindInterfaceAsynchronous( const t_interface_require_description *itfRequire, t_async_bf_info *bfInfo) { t_interface_require_description eventitfRequire; LOG_INTERNAL(1, "\n##### UnBind asynchronous %s/%x.%s #####\n", itfRequire->client->pathname, itfRequire->client, itfRequire->origName, 0, 0, 0); cm_TRC_traceBinding(TRACE_BIND_COMMAND_UNBIND_ASYNCHRONOUS, itfRequire->client, NULL, itfRequire->client->Template->requires[itfRequire->requireIndex].name, NULL); /* Unbind Client from Event Binding Component */ cm_bindLowLevelInterfaceToConst(itfRequire, 0x0, NULL); /* Unbind explicitly Event from Server Binding Component */ /* This is mandatory to fix the providedItfUsedCount of the server */ CM_ASSERT(cm_getRequiredInterface(bfInfo->eventInstance, "target", &eventitfRequire) == CM_OK); cm_registerLowLevelInterfaceToConst(&eventitfRequire, NULL); /* Destroy Event fifo */ dspevent_destroyDspEventFifo(bfInfo->dspfifoHandle); /* Destroy Event Binding Component */ cm_destroyInstance(bfInfo->eventInstance, DESTROY_WITHOUT_CHECK); /* Free BF info */ OSAL_Free(bfInfo); }
PUBLIC t_cm_error cm_PWR_EnableMPC( t_mpc_power_request request, t_nmf_core_id coreId) { t_cm_error error; switch(request) { case MPC_PWR_CLOCK: LOG_INTERNAL(__PWR_DEBUG_TRACE_LEVEL, "[Pwr] MPC %s enable clock\n", cm_getDspName(coreId), 0, 0, 0, 0, 0); if((error = OSAL_EnablePwrRessource(CM_OSAL_POWER_SxA_CLOCK, coreId, 0)) != CM_OK) { ERROR("[Pwr] MPC %s clock can't be enabled\n", cm_getDspName(coreId), 0, 0, 0, 0, 0); return error; } break; case MPC_PWR_AUTOIDLE: if((error = OSAL_EnablePwrRessource(CM_OSAL_POWER_SxA_AUTOIDLE, coreId, 0)) != CM_OK) { ERROR("[Pwr] MPC %s clock can't be auto-idle\n", cm_getDspName(coreId), 0, 0, 0, 0, 0); return error; } break; case MPC_PWR_HWIP: if(_pwrMPCHWIPCountT[coreId]++ == 0) { LOG_INTERNAL(__PWR_DEBUG_TRACE_LEVEL, "[Pwr] MPC %s HW IP enable clock\n",cm_getDspName(coreId), 0, 0, 0, 0, 0); // The PRCMU seem not supporting the transition of asking HW IP on while DSP in retention // -> Thus force wake up of the MMDSP before asking the transition if ((error = cm_EEM_ForceWakeup(coreId)) != CM_OK) return error; if((error = OSAL_EnablePwrRessource(CM_OSAL_POWER_SxA_HARDWARE, coreId, 0)) != CM_OK) { ERROR("[Pwr] MPC %s HW IP clock can't be enabled\n", cm_getDspName(coreId), 0, 0, 0, 0, 0); cm_EEM_AllowSleep(coreId); return error; } cm_EEM_AllowSleep(coreId); } break; } return CM_OK; }
t_cm_error cm_bindInterfaceTrace( const t_interface_require_description *itfRequire, const t_interface_provide_description *itfProvide, t_elfdescription *elfhandleTrace) { t_interface_require *require = &itfRequire->client->Template->requires[itfRequire->requireIndex]; t_interface_require_description bcitfRequire; t_interface_provide_description bcitfProvide; t_trace_bf_info *bfInfo; t_cm_error error; LOG_INTERNAL(1, "\n##### Bind Synchronous Trace %s/%x.%s -> %s/%x.%s #####\n", itfRequire->client->pathname, itfRequire->client, itfRequire->origName, itfProvide->server->pathname, itfProvide->server, itfProvide->origName); /* Allocate aynchronous binding factory information */ bfInfo = (t_trace_bf_info*)OSAL_Alloc(sizeof(t_trace_bf_info)); if(bfInfo == 0) return CM_NO_MORE_MEMORY; /* * Instantiate related trace on dsp */ { char traceTemplateName[4 + MAX_INTERFACE_TYPE_NAME_LENGTH + 1]; cm_StringCopy(traceTemplateName,"_tr.", sizeof(traceTemplateName)); cm_StringConcatenate(traceTemplateName, require->interface->type, MAX_INTERFACE_TYPE_NAME_LENGTH); if ((error = cm_instantiateComponent( traceTemplateName, itfRequire->client->domainId, itfProvide->server->priority, traceDup, elfhandleTrace, &bfInfo->traceInstance)) != CM_OK) { OSAL_Free(bfInfo); return (error == CM_COMPONENT_NOT_FOUND)?CM_BINDING_COMPONENT_NOT_FOUND : error; } } /* Bind event to server interface (Error must not occure) */ CM_ASSERT(cm_getRequiredInterface(bfInfo->traceInstance, "target", &bcitfRequire) == CM_OK); cm_bindLowLevelInterface(&bcitfRequire, itfProvide, BF_SYNCHRONOUS, NULL); /* Get the event interface (Error must not occure) */ CM_ASSERT(cm_getProvidedInterface(bfInfo->traceInstance, "target", &bcitfProvide) == CM_OK); /* Bind client to event (Error must not occure) */ cm_bindLowLevelInterface(itfRequire, &bcitfProvide, BF_TRACE, bfInfo); cm_TRC_traceBinding(TRACE_BIND_COMMAND_BIND_SYNCHRONOUS, itfRequire->client, itfProvide->server, itfRequire->client->Template->requires[itfRequire->requireIndex].name, itfProvide->server->Template->provides[itfProvide->provideIndex].name); return CM_OK; }
/*! * Create Shared FIFO and set stub and skeleton to it */ PRIVATE t_cm_error cm_createParamsFifo(t_component_instance *stub, t_component_instance *skeleton, t_cm_domain_id domainId, t_uint32 fifosize, t_nmf_fifo_arm_desc **fifo, t_uint32 *fifoElemSize, t_uint32 bcDescSize) { t_nmf_core_id stubcore = (stub != NULL) ?(stub->Template->dspId): ARM_CORE_ID; t_nmf_core_id skelcore = (skeleton != NULL) ?(skeleton->Template->dspId) : ARM_CORE_ID; t_component_instance *bcnotnull = (stub != NULL) ? stub : skeleton; int _fifoelemsize; CM_ASSERT(bcnotnull != NULL); /* Get fifo param elem size (which was store in FIFO by convention) */ _fifoelemsize = cm_readAttributeNoError(bcnotnull, "FIFO"); LOG_INTERNAL(3, "Fifo Params element size = %d\n", _fifoelemsize, 0, 0, 0, 0, 0); if(fifoElemSize != NULL) *fifoElemSize = _fifoelemsize; /* Allocation of the fifo params */ *fifo = fifo_alloc(stubcore, skelcore, _fifoelemsize, fifosize, 1+bcDescSize, paramsLocation, extendedFieldLocation, domainId); /* 1+nbMethods fro hostBCThis_or_TOP space */ if(*fifo == NULL) { ERROR("CM_NO_MORE_MEMORY: fifo_alloc() failed in cm_createParamsFifo()\n", 0, 0, 0, 0, 0, 0); return CM_NO_MORE_MEMORY; } if(stub != NULL) { /* Set stub FIFO attribute (Error mut not occure) */ cm_writeAttribute(stub, "FIFO", (*fifo)->dspAdress); LOG_INTERNAL(2, " FIFO param %x:%x\n", *fifo, (*fifo)->dspAdress, 0, 0, 0, 0); } if(skeleton != NULL) { /* Set Skeleton FIFO attribute (Error mut not occure) */ cm_writeAttribute(skeleton, "FIFO", (*fifo)->dspAdress); LOG_INTERNAL(2, " FIFO param %x:%x\n", *fifo, (*fifo)->dspAdress, 0, 0, 0, 0); } return CM_OK; }
/*! * Create DSP skeleton */ PRIVATE t_cm_error cm_createDSPSkeleton( const t_interface_provide_description *itfProvide, t_uint32 fifosize, t_dsp_memory_type_id dspEventMemType, //INTERNAL_XRAM24 t_elfdescription *elfhandleSkeleton, t_dspskel_bf_info *bfInfo) { t_interface_provide *provide = &itfProvide->server->Template->provides[itfProvide->provideIndex]; t_interface_require_description skelitfRequire; t_cm_error error; unsigned int fifoeventsize = 0; /* Instantiate related stub on dsp */ { char stubTemplateName[4 + MAX_INTERFACE_TYPE_NAME_LENGTH + 1]; cm_StringCopy(stubTemplateName,"_sk.", sizeof(stubTemplateName)); cm_StringConcatenate(stubTemplateName, provide->interface->type, MAX_INTERFACE_TYPE_NAME_LENGTH); if ((error = cm_instantiateComponent( stubTemplateName, itfProvide->server->domainId, itfProvide->server->priority, skeletonDup, elfhandleSkeleton, &bfInfo->skelInstance)) != CM_OK) { return ((error == CM_COMPONENT_NOT_FOUND)?CM_BINDING_COMPONENT_NOT_FOUND:error); } } /* Get fifo elem size (which was store in TOP by convention) */ fifoeventsize = cm_readAttributeNoError(bfInfo->skelInstance, "TOP"); LOG_INTERNAL(3, "DspEvent Fifo element size = %d\n", fifoeventsize, 0, 0, 0, 0, 0); /* Allocation of the itf event dsp fifo */ if ((error = dspevent_createDspEventFifo( bfInfo->skelInstance, "TOP", fifosize, fifoeventsize, dspEventMemType, &bfInfo->dspfifoHandle)) != CM_OK) { cm_destroyInstance(bfInfo->skelInstance, DESTROY_WITHOUT_CHECK); return error; } /* Bind stub to server component (Error must not occure) */ CM_ASSERT(cm_getRequiredInterface(bfInfo->skelInstance, "target", &skelitfRequire) == CM_OK); cm_bindLowLevelInterface(&skelitfRequire, itfProvide, BF_SYNCHRONOUS, NULL); return CM_OK; }
PUBLIC t_cm_error cm_PWR_EnableHSEM(void) { t_cm_error error; LOG_INTERNAL(__PWR_DEBUG_TRACE_LEVEL, "[Pwr] HSEM enable clock\n",0 , 0, 0, 0, 0, 0); if((error = OSAL_EnablePwrRessource(CM_OSAL_POWER_HSEM, 0, 0)) != CM_OK) { ERROR("[Pwr] HSEM clock can't be enabled\n", 0, 0, 0, 0, 0, 0); return error; } return CM_OK; }
void cm_registerSingletonBinding( t_component_instance* component, t_interface_require_description* itfRequire, t_interface_provide_description* itfProvide, t_nmf_client_id clientId) { if(component->Template->classe == SINGLETON) { struct t_client_of_singleton* cl = cm_getClientOfSingleton(component, FALSE, clientId); if(cl != NULL) cl->numberOfBind++; if(itfProvide != NULL) LOG_INTERNAL(1, " -> Singleton[%d] : Register binding %s/%x.%s -> %s/%x\n", clientId, itfRequire->client->pathname, itfRequire->client, itfRequire->origName, itfProvide->server->pathname, itfProvide->server); else LOG_INTERNAL(1, " -> Singleton[%d] : Register binding %s/%x.%s -> ARM/VOID\n", clientId, itfRequire->client->pathname, itfRequire->client, itfRequire->origName, 0, 0); } }
void cm_unbindInterface( const t_interface_require_description *itfRequire) { LOG_INTERNAL(1, "\n##### UnBind synchronous %s/%x.%s #####\n", itfRequire->client->pathname, itfRequire->client, itfRequire->origName, 0, 0, 0); cm_TRC_traceBinding(TRACE_BIND_COMMAND_UNBIND_SYNCHRONOUS, itfRequire->client, NULL, itfRequire->client->Template->requires[itfRequire->requireIndex].name, NULL); cm_bindLowLevelInterfaceToConst(itfRequire, 0x0, NULL); }
t_cm_error cm_bindInterfaceToVoid( const t_interface_require_description *itfRequire) { LOG_INTERNAL(1, "\n##### Bind %s/%x.%s -> Void #####\n", itfRequire->client->pathname, itfRequire->client, itfRequire->origName, 0, 0, 0); cm_bindLowLevelInterfaceToConst(itfRequire, cm_EEM_getExecutiveEngine(itfRequire->client->Template->dspId)->voidAddr, (t_component_instance*)NMF_VOID_COMPONENT); cm_TRC_traceBinding(TRACE_BIND_COMMAND_BIND_SYNCHRONOUS, itfRequire->client, NULL, itfRequire->client->Template->requires[itfRequire->requireIndex].name, NULL); return CM_OK; }
/* * Bind User component though primitive binding factory */ t_cm_error cm_bindInterface( const t_interface_require_description *itfRequire, const t_interface_provide_description *itfProvide) { LOG_INTERNAL(1, "\n##### Bind Synchronous %s/%x.%s -> %s/%x.%s #####\n", itfRequire->client->pathname, itfRequire->client, itfRequire->origName, itfProvide->server->pathname, itfProvide->server, itfProvide->origName); cm_bindLowLevelInterface( itfRequire, itfProvide, BF_SYNCHRONOUS, NULL); cm_TRC_traceBinding(TRACE_BIND_COMMAND_BIND_SYNCHRONOUS, itfRequire->client, itfProvide->server, itfRequire->client->Template->requires[itfRequire->requireIndex].name, itfProvide->server->Template->provides[itfProvide->provideIndex].name); return CM_OK; }
void cm_unbindComponentFromCMCore( t_host2mpc_bf_info* bfInfo) { t_component_instance *skel = bfInfo->dspskeleton.skelInstance; t_interface_reference* itfProvide = &skel->interfaceReferences[0][0]; t_interface_provide *provide = &itfProvide->instance->Template->provides[itfProvide->provideIndex]; LOG_INTERNAL(1, "\n##### UnBind HOST -> %s/%x.%s #####\n", itfProvide->instance->pathname, itfProvide->instance, provide->name, 0, 0, 0); cm_TRC_traceBinding(TRACE_BIND_COMMAND_UNBIND_ASYNCHRONOUS, ARM_TRACE_COMPONENT, itfProvide->instance, NULL, itfProvide->instance->Template->provides[itfProvide->provideIndex].name); // Destroy FIFO params cm_destroyParamsFifo(bfInfo->fifo); // Destory Skeleton cm_destroyDSPSkeleton(&bfInfo->dspskeleton); // Free BF info (which contains bcDecr(==dspfct) and arm This) OSAL_Free(bfInfo); }
void cm_unbindComponentToCMCore( const t_interface_require_description *itfRequire, t_mpc2host_bf_info *bfInfo) { LOG_INTERNAL(1, "\n##### UnBind %s/%x.%s -> HOST #####\n", itfRequire->client->pathname, itfRequire->client, itfRequire->origName, 0, 0, 0); cm_TRC_traceBinding(TRACE_BIND_COMMAND_UNBIND_ASYNCHRONOUS, itfRequire->client, ARM_TRACE_COMPONENT, itfRequire->client->Template->requires[itfRequire->requireIndex].name, NULL); /* Unbind virtual interface coms */ cm_unbindVirtualInterface(bfInfo->dspstub.stubInstance); // Destroy FIFO params cm_destroyParamsFifo(bfInfo->fifo); // Destroy DSP Stub cm_destroyDSPStub(itfRequire, &bfInfo->dspstub); /* Free BF info */ OSAL_Free(bfInfo); }
t_cm_error cm_bindComponentToCMCore( const t_interface_require_description *itfRequire, t_uint32 fifosize, t_uint32 context, t_elfdescription *elfhandleStub, t_mpc2host_bf_info ** bfInfo) { t_interface_require *require = &itfRequire->client->Template->requires[itfRequire->requireIndex]; t_interface_provide_description itfstubProvide; t_cm_error error; t_uint32 fifoelemsize; LOG_INTERNAL(1, "\n##### Bind %s/%x.%s -> HOST #####\n", itfRequire->client->pathname, itfRequire->client, itfRequire->origName, 0, 0, 0); /* Allocate dsp2host binding factory information */ *bfInfo = (t_mpc2host_bf_info*)OSAL_Alloc(sizeof(t_mpc2host_bf_info)); if(*bfInfo == 0) return CM_NO_MORE_MEMORY; (*bfInfo)->context = context; if ((error = cm_createDSPStub(itfRequire, require->interface->type, &(*bfInfo)->dspstub, elfhandleStub, &itfstubProvide)) != CM_OK) { OSAL_Free(*bfInfo); return error; } /* Create the FIFO Params */ if ((error = cm_createParamsFifo( (*bfInfo)->dspstub.stubInstance, NULL, itfRequire->client->domainId, fifosize, &(*bfInfo)->fifo, &fifoelemsize, 1)) != CM_OK) /* 1 => we used first field as max params size */ { cm_destroyDSPStub(itfRequire, &(*bfInfo)->dspstub); OSAL_Free(*bfInfo); return error; } /* Bind client to stub component (Error must not occure) */ cm_bindLowLevelInterface(itfRequire, &itfstubProvide, BF_DSP2HOST, *bfInfo); /* Bind stub component to host (virtual bind) */ cm_bindVirtualInterface((*bfInfo)->dspstub.stubInstance, (t_component_instance*)NMF_HOST_COMPONENT); /* * Set Target info in FIFO param to armThis * Initialise FIFO Param bcDesc with Jumptable * Should not return any error */ fifo_params_setSharedField((*bfInfo)->fifo, 0, (t_shared_field)context /* ArmBCThis_or_TOP */); fifo_params_setSharedField((*bfInfo)->fifo, 1, (t_shared_field)fifoelemsize * 2/* bcDescRef */); cm_TRC_traceBinding(TRACE_BIND_COMMAND_BIND_ASYNCHRONOUS, itfRequire->client, ARM_TRACE_COMPONENT, itfRequire->client->Template->requires[itfRequire->requireIndex].name, NULL); return error; }
t_cm_error cm_bindComponentFromCMCore( const t_interface_provide_description *itfProvide, t_uint32 fifosize, t_dsp_memory_type_id dspEventMemType, t_elfdescription *elfhandleSkeleton, t_host2mpc_bf_info **bfInfo) { t_interface_provide *provide = &itfProvide->server->Template->provides[itfProvide->provideIndex]; t_dsp_offset shareVarOffset; t_cm_error error; LOG_INTERNAL(1, "\n##### Bind HOST -> %s/%x.%s #####\n", itfProvide->server->pathname, itfProvide->server, itfProvide->origName, 0, 0, 0); /* Allocate host2dsp binding factory information */ *bfInfo = (t_host2mpc_bf_info*)OSAL_Alloc(sizeof(t_host2mpc_bf_info)); if((*bfInfo) == 0) return CM_NO_MORE_MEMORY; /* Create the Skeleton */ if ((error = cm_createDSPSkeleton(itfProvide, fifo_normalizeDepth(fifosize), /* We SHALL create DSP Skeleton before creating the Params Fifo, but we need in advance the real depth of this fifo */ dspEventMemType, elfhandleSkeleton, &(*bfInfo)->dspskeleton)) != CM_OK) { OSAL_Free((*bfInfo)); return error; } /* Create the FIFO Params */ if ((error = cm_createParamsFifo(NULL, (*bfInfo)->dspskeleton.skelInstance, itfProvide->server->domainId, fifosize, &(*bfInfo)->fifo, NULL, provide->interface->methodNumber)) != CM_OK) { cm_destroyDSPSkeleton(&(*bfInfo)->dspskeleton); OSAL_Free((*bfInfo)); return error; } /* Set Target info in FIFO param to TOP */ shareVarOffset = cm_getAttributeMpcAddress((*bfInfo)->dspskeleton.skelInstance, "TOP"); /* * Set Target info in FIFO param to armThis * Should not return any error */ fifo_params_setSharedField((*bfInfo)->fifo, 0, (t_shared_field)shareVarOffset /* ArmBCThis_or_TOP */); /* Initialise FIFO Param bcDesc with Skeleton methods */ { int i; t_component_instance *skel = (*bfInfo)->dspskeleton.skelInstance; for (i=0; i < provide->interface->methodNumber; i++) { /* should not return error */ fifo_params_setSharedField( (*bfInfo)->fifo, 1+i, skel->Template->providesLoaded[0].indexesLoaded[0][i].methodAddresses ); } } cm_TRC_traceBinding(TRACE_BIND_COMMAND_BIND_ASYNCHRONOUS, ARM_TRACE_COMPONENT, itfProvide->server, NULL, itfProvide->server->Template->provides[itfProvide->provideIndex].name); return CM_OK; }
/* * Bind component */ static void cm_bindLowLevelInterface( const t_interface_require_description *itfRequire, const t_interface_provide_description *itfLocalBC, /* On the same DSP */ t_bf_info_ID bfInfoID, void* bfInfo) { const t_component_instance* client = itfRequire->client; t_component_instance* server = (t_component_instance*)itfLocalBC->server; t_interface_require *require = &client->Template->requires[itfRequire->requireIndex]; t_interface_provide* provide = &server->Template->provides[itfLocalBC->provideIndex]; t_interface_provide_loaded* provideLoaded = &server->Template->providesLoaded[itfLocalBC->provideIndex]; int k, j; if(require->indexes != NULL) { t_interface_require_index *requireindex = &require->indexes[itfRequire->collectionIndex]; for(k = 0; k < requireindex->numberOfClient; k++) { t_uint32 *hostAddr; hostAddr = (t_uint32*)( cm_DSP_GetHostLogicalAddress(client->memories[requireindex->memories[k].memory->id]) + requireindex->memories[k].offset * requireindex->memories[k].memory->memEntSize); LOG_INTERNAL(2, "Fill ItfRef %s.%s mem=%s Off=%x @=%x\n", client->pathname, require->name, requireindex->memories[k].memory->memoryName, requireindex->memories[k].offset, hostAddr, 0); /* * Fill the interface references. We start by This then methods in order to keep * Unbinded panic as long as possible and not used method with wrong This. This is * relevent only for optional since we must go in stop state before rebinding other * required interface. * * Direct write to DSP memory without go through DSP abstraction since we know we are in 24bits */ // Write THIS reference into the Data field of the interface reference // Write the interface methods reference if(((t_uint32)hostAddr & 0x7) == 0 && require->interface->methodNumber > 0) { // We are 64word byte aligned, combine this write with first method *(volatile t_uint64*)hostAddr = ((t_uint64)server->thisAddress << 0) | ((t_uint64)provideLoaded->indexesLoaded[itfLocalBC->collectionIndex][0].methodAddresses << 32); hostAddr += 2; j = 1; } else { // We are not, write this which will align us *hostAddr++ = (t_uint32)server->thisAddress; j = 0; } // Word align copy for(; j < require->interface->methodNumber - 1; j+=2) { *(volatile t_uint64*)hostAddr = ((t_uint64)provideLoaded->indexesLoaded[itfLocalBC->collectionIndex][j].methodAddresses << 0) | ((t_uint64)provideLoaded->indexesLoaded[itfLocalBC->collectionIndex][j+1].methodAddresses << 32); hostAddr += 2; } // Last word align if required if(j < require->interface->methodNumber) *hostAddr = provideLoaded->indexesLoaded[itfLocalBC->collectionIndex][j].methodAddresses; } } else { t_function_relocation *reloc = client->Template->delayedRelocation; while(reloc != NULL) { for(j = 0; j < provide->interface->methodNumber; j++) { if(provide->interface->methodNames[j] == reloc->symbol_name) { cm_ELF_performRelocation( reloc->type, reloc->symbol_name, provideLoaded->indexesLoaded[itfLocalBC->collectionIndex][j].methodAddresses, reloc->reloc_addr); break; } } reloc = reloc -> next; } } /* * Memorise this reference */ { t_interface_reference* itfRef = &client->interfaceReferences[itfRequire->requireIndex][itfRequire->collectionIndex]; itfRef->provideIndex = itfLocalBC->provideIndex; itfRef->collectionIndex = itfLocalBC->collectionIndex; itfRef->instance = itfLocalBC->server; itfRef->bfInfoID = bfInfoID; itfRef->bfInfo = bfInfo; /* * Do not count binding from EE (ie interrupt line), as this will prevent * cm_destroyInstance() of server to succeed (interrupt line bindings are * destroyed after the check in cm_destroyInstance() */ if (client->Template->classe != FIRMWARE) server->providedItfUsedCount++; } }
PUBLIC void cm_PWR_DisableHSEM(void) { LOG_INTERNAL(__PWR_DEBUG_TRACE_LEVEL, "[Pwr] HSEM disable clock\n",0 , 0, 0, 0, 0, 0); OSAL_DisablePwrRessource(CM_OSAL_POWER_HSEM, 0, 0); }
PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_FlushComponents(t_nmf_client_id clientId) { t_cm_error error = CM_OK; t_component_instance *instance; t_uint32 i; if (clientId == 0) return CM_INVALID_PARAMETER; OSAL_LOCK_API(); // We don't know exactly where components will be, wake up everybody !! (void)cm_EEM_ForceWakeup(SVA_CORE_ID); (void)cm_EEM_ForceWakeup(SIA_CORE_ID); /* Destroy all host2mpc bindings */ OSAL_LOCK_COM(); for (i=0; i<Host2MpcBindingTable.idxMax; i++) { t_host2mpc_bf_info* bfInfo; bfInfo = Host2MpcBindingTable.entries[i]; if ((bfInfo != NULL) && (bfInfo->clientId == clientId)) { cm_delEntry(&Host2MpcBindingTable, i); OSAL_UNLOCK_COM(); cm_unbindComponentFromCMCore(bfInfo); OSAL_LOCK_COM(); } } OSAL_UNLOCK_COM(); /* First, stop all remaining components for this client */ for (i=0; i<ComponentTable.idxMax; i++) { if ((instance = componentEntry(i)) == NULL) continue; if (/* skip EE */ (instance->Template->classe == FIRMWARE) || /* Skip all binding components */ (cm_StringCompare(instance->Template->name, "_ev.", 4) == 0) || (cm_StringCompare(instance->Template->name, "_st.", 4) == 0) || (cm_StringCompare(instance->Template->name, "_sk.", 4) == 0) || (cm_StringCompare(instance->Template->name, "_tr.", 4) == 0)) continue; /* * Special code for SINGLETON handling */ if(instance->Template->classe == SINGLETON) { struct t_client_of_singleton* cl = cm_getClientOfSingleton(instance, FALSE, clientId); if(cl == NULL) continue; cl->numberOfStart = 1; // == 1 since it will go to 0 in cm_stopComponent cl->numberOfInstance = 1; // == 1 since it will go to 0 in cm_destroyInstanceForClient cl->numberOfBind = 0; // == 0 since we don't want anymore binding for this component } else if(domainDesc[instance->domainId].client != clientId) /* Skip all components not belonging to our client */ continue; // Stop the component error = cm_stopComponent(instance, clientId); if (error != CM_OK && error != CM_COMPONENT_NOT_STARTED) LOG_INTERNAL(0, "Error stopping component %s/%x (%s, error=%d, client=%u)\n", instance->pathname, instance, instance->Template->name, error, clientId, 0); // Destroy dependencies cm_destroyRequireInterface(instance, clientId); } /* Destroy all remaining components for this client */ for (i=0; i<ComponentTable.idxMax; i++) { if ((instance = componentEntry(i)) == NULL) continue; if (/* skip EE */ (instance->Template->classe == FIRMWARE) || /* Skip all binding components */ (cm_StringCompare(instance->Template->name, "_ev.", 4) == 0) || (cm_StringCompare(instance->Template->name, "_st.", 4) == 0) || (cm_StringCompare(instance->Template->name, "_sk.", 4) == 0) || (cm_StringCompare(instance->Template->name, "_tr.", 4) == 0)) { continue; } /* * Special code for SINGLETON handling */ if(instance->Template->classe == SINGLETON) { struct t_client_of_singleton* cl = cm_getClientOfSingleton(instance, FALSE, clientId); if(cl == NULL) continue; } else if(domainDesc[instance->domainId].client != clientId) /* Skip all components not belonging to our client */ continue; // Destroy the component error = cm_destroyInstanceForClient(instance, DESTROY_WITHOUT_CHECK, clientId); if (error != CM_OK) { /* FIXME : add component name instance in log message but need to make a copy before cm_flushComponent() * because it's no more available after. */ LOG_INTERNAL(0, "Error flushing component (error=%d, client=%u)\n", error, clientId, 0, 0, 0, 0); } } cm_CFG_ReleaseMpc(SVA_CORE_ID); cm_CFG_ReleaseMpc(SIA_CORE_ID); cm_EEM_AllowSleep(SVA_CORE_ID); cm_EEM_AllowSleep(SIA_CORE_ID); OSAL_UNLOCK_API(); return error; }
PUBLIC void CM_ENGINE_Destroy(void) { t_component_instance *instance; t_cm_error error; t_uint32 i; /* PP: Well, on Linux (and probably on Symbian too), this is called when driver is removed * => the module (driver) can't be removed if there are some pending clients * => all remaining components should have been destroyed in CM_ENGINE_FlushClient() * => So, if we found some components here, we are in BIG trouble ... */ /* First, stop all remaining components */ for (i=0; i<ComponentTable.idxMax; i++) { t_nmf_client_id clientId; if ((instance = componentEntry(i)) == NULL) continue; clientId = domainDesc[instance->domainId].client; LOG_INTERNAL(0, "Found a remaining component %s (%s) when destroying the CM !!!\n", instance->pathname, instance->Template->name, 0, 0, 0, 0); if (/* skip EE */ (instance->Template->classe == FIRMWARE) || /* Skip all binding components */ (cm_StringCompare(instance->Template->name, "_ev.", 4) == 0) || (cm_StringCompare(instance->Template->name, "_st.", 4) == 0) || (cm_StringCompare(instance->Template->name, "_sk.", 4) == 0) || (cm_StringCompare(instance->Template->name, "_tr.", 4) == 0)) continue; /* * Special code for SINGLETON handling */ if(instance->Template->classe == SINGLETON) { struct t_client_of_singleton* cl = instance->clientOfSingleton; clientId = instance->clientOfSingleton->clientId; for( ; cl != NULL ; cl = cl->next) { if(cl == instance->clientOfSingleton) { cl->numberOfStart = 1; // == 1 since it will go to 0 in cm_stopComponent cl->numberOfInstance = 1; // == 1 since it will go to 0 in cm_destroyInstanceForClient } else { cl->numberOfStart = 0; cl->numberOfInstance = 0; } cl->numberOfBind = 0; } } // Stop the component error = cm_stopComponent(instance, clientId); if (error != CM_OK && error != CM_COMPONENT_NOT_STARTED) LOG_INTERNAL(0, "Error stopping component %s/%x (%s, error=%d, client=%u)\n", instance->pathname, instance, instance->Template->name, error, clientId, 0); // Destroy dependencies cm_destroyRequireInterface(instance, clientId); } /* Destroy all remaining components */ for (i=0; i<ComponentTable.idxMax; i++) { t_nmf_client_id clientId; if ((instance = componentEntry(i)) == NULL) continue; clientId = domainDesc[instance->domainId].client; if (/* skip EE */ (instance->Template->classe == FIRMWARE) || /* Skip all binding components */ (cm_StringCompare(instance->Template->name, "_ev.", 4) == 0) || (cm_StringCompare(instance->Template->name, "_st.", 4) == 0) || (cm_StringCompare(instance->Template->name, "_sk.", 4) == 0) || (cm_StringCompare(instance->Template->name, "_tr.", 4) == 0)) { continue; } if(instance->Template->classe == SINGLETON) { clientId = instance->clientOfSingleton->clientId; } // Destroy the component error = cm_destroyInstanceForClient(instance, DESTROY_WITHOUT_CHECK, clientId); if (error != CM_OK) { /* FIXME : add component name instance in log message but need to make a copy before cm_flushComponent() * because it's no more available after. */ LOG_INTERNAL(0, "Error flushing component (error=%d, client=%u)\n", error, clientId, 0, 0, 0, 0); } } /* This will power off all ressources and destroy EE */ cm_PWR_SetMode(NORMAL_PWR_MODE); cm_DSP_Destroy(); cm_DM_Destroy(); /* Nothing to do about SEM */ //cm_MM_Destroy(); cm_REP_Destroy(); cm_COMP_Destroy(); cm_OSAL_Destroy(); cm_StringRelease(traceDup); cm_StringRelease(stubDup); cm_StringRelease(skeletonDup); cm_StringRelease(eventDup); cm_StringRelease(anonymousDup); }
t_cm_error cm_bindInterfaceAsynchronous( const t_interface_require_description *itfRequire, const t_interface_provide_description *itfProvide, t_uint32 fifosize, t_dsp_memory_type_id dspEventMemType, t_elfdescription *elfhandleEvent) { t_interface_require *require = &itfRequire->client->Template->requires[itfRequire->requireIndex]; t_interface_require_description eventitfRequire; t_interface_provide_description eventitfProvide; t_async_bf_info *bfInfo; t_cm_error error; LOG_INTERNAL(1, "\n##### Bind Asynchronous %s/%x.%s -> %s/%x.%s #####\n", itfRequire->client->pathname, itfRequire->client, itfRequire->origName, itfProvide->server->pathname, itfProvide->server, itfProvide->origName); /* Allocate aynchronous binding factory information */ bfInfo = (t_async_bf_info*)OSAL_Alloc(sizeof(t_async_bf_info)); if(bfInfo == 0) return CM_NO_MORE_MEMORY; /* * Instantiate related event on dsp */ { char eventTemplateName[4 + MAX_INTERFACE_TYPE_NAME_LENGTH + 1]; cm_StringCopy(eventTemplateName,"_ev.", sizeof(eventTemplateName)); cm_StringConcatenate(eventTemplateName, require->interface->type, MAX_INTERFACE_TYPE_NAME_LENGTH); if ((error = cm_instantiateComponent( eventTemplateName, itfRequire->client->domainId, itfProvide->server->priority, eventDup, elfhandleEvent, &bfInfo->eventInstance)) != CM_OK) { OSAL_Free(bfInfo); return (error == CM_COMPONENT_NOT_FOUND)?CM_BINDING_COMPONENT_NOT_FOUND : error; } } /* * Initialize the event component */ { unsigned int size; // Get fifo elem size (which was store in TOP by convention) size = cm_readAttributeNoError(bfInfo->eventInstance, "TOP"); LOG_INTERNAL(3, "DspEvent Fifo element size = %d\n", size, 0, 0, 0, 0, 0); // Allocate fifo if ((error = dspevent_createDspEventFifo(bfInfo->eventInstance, "TOP", fifosize, size, dspEventMemType, &bfInfo->dspfifoHandle)) != CM_OK) { cm_destroyInstance(bfInfo->eventInstance, DESTROY_WITHOUT_CHECK); OSAL_Free(bfInfo); return error; } } /* Bind event to server interface (Error must not occure) */ CM_ASSERT(cm_getRequiredInterface(bfInfo->eventInstance, "target", &eventitfRequire) == CM_OK); cm_bindLowLevelInterface(&eventitfRequire, itfProvide, BF_SYNCHRONOUS, NULL); /* Get the event interface (Error must not occure) */ CM_ASSERT(cm_getProvidedInterface(bfInfo->eventInstance, "target", &eventitfProvide) == CM_OK); /* Bind client to event (Error must not occure) */ cm_bindLowLevelInterface(itfRequire, &eventitfProvide, BF_ASYNCHRONOUS, bfInfo); cm_TRC_traceBinding(TRACE_BIND_COMMAND_BIND_ASYNCHRONOUS, itfRequire->client, itfProvide->server, itfRequire->client->Template->requires[itfRequire->requireIndex].name, itfProvide->server->Template->provides[itfProvide->provideIndex].name); return CM_OK; }
/*! * */ t_cm_error cm_bindInterfaceDistributed( const t_interface_require_description *itfRequire, const t_interface_provide_description *itfProvide, t_uint32 fifosize, t_dsp_memory_type_id dspEventMemType, t_elfdescription *elfhandleSkeleton, t_elfdescription *elfhandleStub) { t_interface_require *require = &itfRequire->client->Template->requires[itfRequire->requireIndex]; t_interface_provide_description itfstubProvide; t_cm_error error; t_mpc2mpc_bf_info *bfInfo; t_dsp_offset shareVarOffset; LOG_INTERNAL(1, "\n##### Bind Distributed %s/%x.%s -> %s/%x.%s #####\n", itfRequire->client->pathname, itfRequire->client, itfRequire->origName, itfProvide->server->pathname, itfProvide->server, itfProvide->origName); /* Allocate aynchronous binding factory information */ bfInfo = (t_mpc2mpc_bf_info*)OSAL_Alloc(sizeof(t_mpc2mpc_bf_info)); if(bfInfo == 0) return CM_NO_MORE_MEMORY; /* Create the Skeleton */ if ((error = cm_createDSPSkeleton(itfProvide, fifo_normalizeDepth(fifosize), /* We SHALL create DSP Skeleton before creating the Params Fifo, but we need in advance the real depth of this fifo */ dspEventMemType, elfhandleSkeleton, &bfInfo->dspskeleton)) != CM_OK) { OSAL_Free(bfInfo); return error; } // Create DSP Stub if ((error = cm_createDSPStub(itfRequire, require->interface->type, &bfInfo->dspstub, elfhandleStub, &itfstubProvide)) != CM_OK) { cm_destroyDSPSkeleton(&bfInfo->dspskeleton); OSAL_Free(bfInfo); return error; } /* Bind client to stub component (Error must not occure) */ cm_bindLowLevelInterface(itfRequire, &itfstubProvide, BF_DSP2DSP, bfInfo); /* Create the FIFO Params */ if ((error = cm_createParamsFifo( bfInfo->dspstub.stubInstance, bfInfo->dspskeleton.skelInstance, itfProvide->server->domainId, fifosize, &bfInfo->fifo, NULL, require->interface->methodNumber)) != CM_OK) { cm_destroyDSPStub(itfRequire, &bfInfo->dspstub); cm_destroyDSPSkeleton(&bfInfo->dspskeleton); OSAL_Free(bfInfo); return error; } /* Bind stub component to host (virtual bind) */ cm_bindVirtualInterface(bfInfo->dspstub.stubInstance, bfInfo->dspskeleton.skelInstance); /* Set Target info in FIFO param to TOP */ shareVarOffset = cm_getAttributeMpcAddress(bfInfo->dspskeleton.skelInstance, "TOP"); /* * Set Target info in FIFO param to armThis * Should not return any error */ fifo_params_setSharedField(bfInfo->fifo, 0, (t_shared_field)shareVarOffset /* ArmBCThis_or_TOP */); /* Initialise FIFO Param bcDesc with Skeleton methods */ { int i; t_component_instance *skel = bfInfo->dspskeleton.skelInstance; for (i=0; i < require->interface->methodNumber; i++) { /* should not return error */ fifo_params_setSharedField( bfInfo->fifo, 1+i, skel->Template->providesLoaded[0].indexesLoaded[0][i].methodAddresses ); } } cm_TRC_traceBinding(TRACE_BIND_COMMAND_BIND_ASYNCHRONOUS, itfRequire->client, itfProvide->server, itfRequire->client->Template->requires[itfRequire->requireIndex].name, itfProvide->server->Template->provides[itfProvide->provideIndex].name); return CM_OK; }
PUBLIC EXPORT_SHARED t_cm_error CM_getServiceDescription( t_nmf_core_id coreId, t_cm_service_type *srcType, t_cm_service_description *srcDescr) { t_uint32 serviceReason; t_component_instance *ee; // Acknowledge interrupt (do it before resetting panicReason) cm_DSP_AcknowledgeDspIrq(coreId, DSP2ARM_IRQ_1); ee = cm_EEM_getExecutiveEngine(coreId)->instance; // Read panicReason serviceReason = cm_readAttributeNoError(ee, "rtos/commonpart/serviceReason"); if(serviceReason == MPC_SERVICE_PRINT) { *srcType = CM_MPC_SERVICE_PRINT; srcDescr->u.print.dspAddress = cm_readAttributeNoError(ee, "rtos/commonpart/serviceInfo0"); srcDescr->u.print.value1 = cm_readAttributeNoError(ee, "rtos/commonpart/serviceInfo1"); srcDescr->u.print.value2 = cm_readAttributeNoError(ee, "rtos/commonpart/serviceInfo2"); } else if(serviceReason != MPC_SERVICE_NONE) { t_uint32 panicThis; t_dup_char itfName; t_component_instance *instance; *srcType = CM_MPC_SERVICE_PANIC; srcDescr->u.panic.panicReason = (t_panic_reason)serviceReason; srcDescr->u.panic.panicSource = MPC_EE; srcDescr->u.panic.info.mpc.coreid = coreId; // Read panicThis panicThis = cm_readAttributeNoError(ee, "rtos/commonpart/serviceInfo0"); instance = getCorrespondingInstance(srcDescr->u.panic.panicReason, panicThis, &itfName, &srcDescr->u.panic.info.mpc.faultingComponent); LOG_INTERNAL(0, "Error: Panic(%s, %s), This=%x", cm_getDspName(coreId), reason_descrs[srcDescr->u.panic.panicReason].name, (void*)panicThis, 0, 0, 0); if(reason_descrs[srcDescr->u.panic.panicReason].interface != 0) { LOG_INTERNAL(0, ", interface=%s", itfName, 0, 0, 0, 0, 0); } if(reason_descrs[srcDescr->u.panic.panicReason].info1 != 0) { // Info 1 srcDescr->u.panic.info.mpc.panicInfo1 = cm_readAttributeNoError(ee, "rtos/commonpart/serviceInfo1"); LOG_INTERNAL(0, ", Info=%x", srcDescr->u.panic.info.mpc.panicInfo1, 0, 0, 0, 0, 0); } if(reason_descrs[srcDescr->u.panic.panicReason].PC != 0) { t_uint32 DspAddress = 0xFFFFFFFF; t_uint32 DspSize = 0x0; // PC need to be read in rtos/commonpart/serviceInfo1 srcDescr->u.panic.info.mpc.panicInfo1 = cm_readAttributeNoError(ee, "rtos/commonpart/serviceInfo1"); if(instance != 0) { cm_DSP_GetDspAddress(instance->memories[instance->Template->codeMemory->id], &DspAddress); cm_DSP_GetDspMemoryHandleSize(instance->memories[instance->Template->codeMemory->id], &DspSize); } if(DspAddress <= srcDescr->u.panic.info.mpc.panicInfo1 && srcDescr->u.panic.info.mpc.panicInfo1 < (DspAddress + DspSize)) LOG_INTERNAL(0, ", PC:off=%x <abs=%x>", srcDescr->u.panic.info.mpc.panicInfo1 - DspAddress, srcDescr->u.panic.info.mpc.panicInfo1, 0, 0, 0, 0); else LOG_INTERNAL(0, ", PC:<abs=%x>", srcDescr->u.panic.info.mpc.panicInfo1, 0, 0, 0, 0, 0); } if(reason_descrs[srcDescr->u.panic.panicReason].SP != 0) { srcDescr->u.panic.info.mpc.panicInfo2 = cm_readAttributeNoError(ee, "rtos/commonpart/serviceInfo2"); LOG_INTERNAL(0, ", SP=%x", srcDescr->u.panic.info.mpc.panicInfo2, 0, 0, 0, 0, 0); } LOG_INTERNAL(0, "\n", 0, 0, 0, 0, 0, 0); if(instance != 0) { LOG_INTERNAL(0, "Error: Component=%s<%s>\n", instance->pathname, instance->Template->name, 0, 0, 0, 0); } // We don't set rtos/commonpart/serviceReason = MPC_SERVICE_NONE, since we don't want the // MMDSP to continue execution, and we put in in Panic state cm_DSP_SetStatePanic(coreId); } else { *srcType = CM_MPC_SERVICE_NONE; } return CM_OK; }
/*********************************************************************************************************************************** Do cleanup and return result code ***********************************************************************************************************************************/ int exitSafe(int result, bool error, SignalType signalType) { FUNCTION_LOG_BEGIN(logLevelDebug); FUNCTION_LOG_PARAM(INT, result); FUNCTION_LOG_PARAM(BOOL, error); FUNCTION_LOG_PARAM(ENUM, signalType); FUNCTION_LOG_END(); // Report error if one was thrown if (error) { // Don't log the error if it has already been logged by Perl #ifdef HAVE_LIBPERL if (strcmp(errorMessage(), PERL_EMBED_ERROR) != 0) { #endif LogLevel logLevel = errorCode() == errorTypeCode(&AssertError) ? logLevelAssert : logLevelError; // Assert errors always output a stack trace if (logLevel == logLevelAssert) LOG(logLevel, errorCode(), "%s\nSTACK TRACE:\n%s", errorMessage(), errorStackTrace()); else { // Log just the error to non-debug levels LOG_INTERNAL(logLevel, LOG_LEVEL_MIN, logLevelDetail, 0, errorCode(), errorMessage()); // Log the stack trace debug levels if (logAny(logLevelDebug)) { LOG_INTERNAL( logLevel, logLevelDebug, LOG_LEVEL_MAX, 0, errorCode(), "%s\nSTACK TRACE:\n%s", errorMessage(), errorStackTrace()); } } #ifdef HAVE_LIBPERL } #endif result = errorCode(); } // Free protocol objects but ignore errors TRY_BEGIN() { protocolFree(); } TRY_END(); // Free Perl but ignore errors #ifdef HAVE_LIBPERL TRY_BEGIN() { perlFree(result); } TRY_END(); #endif // Log command end if a command is set if (cfgCommand() != cfgCmdNone) { String *errorMessage = NULL; // On error generate an error message if (result != 0) { // On process terminate if (result == errorTypeCode(&TermError)) { errorMessage = strNew("terminated on signal "); // Terminate from a child if (signalType == signalTypeNone) strCat(errorMessage, "from child process"); // Else terminated directly else strCatFmt(errorMessage, "[SIG%s]", exitSignalName(signalType)); } // Standard error exit message else if (error) errorMessage = strNewFmt("aborted with exception [%03d]", result); } cmdEnd(result, errorMessage); } // Release any locks but ignore errors TRY_BEGIN() { lockRelease(false); } TRY_END(); // Return result - caller should immediate pass this result to exit() FUNCTION_LOG_RETURN(INT, result); }