/** * @file rm.c * * @brief * This is the Resource Manager source. * * \par * ============================================================================ * @n (C) Copyright 2012, Texas Instruments, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * \par */ /* RM Types */ #include /* RM external includes */ #include #include #include #include /* RM internal includes */ #include #include #include #include /* RM OSAL layer */ #include /********************************************************************** ************************** Globals *********************************** **********************************************************************/ #if 0 /* Place QMSS PDSP permissions array */ #pragma DATA_SECTION (rmQmssPdspFirmwarePerms, ".rm"); #pragma DATA_ALIGN (rmQmssPdspFirmwarePerms, 128) Rm_Perms rmQmssPdspFirmwarePerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_QMSS_FIRMWARE_PDSPS, Rm_Perms)]; #endif /** @brief Global Variable which describes the RM Version Information */ const char rmVersionStr[] = RM_VERSION_STR ":" __DATE__ ":" __TIME__; /********************************************************************** ********************** Internal Functions **************************** **********************************************************************/ /* At the very least the transaction ID needs to be provided to create a transaction */ Rm_Transaction *Rm_transactionQueueAdd(Rm_Inst *rmInst, uint32_t transactionId) { Rm_Transaction *transactionQueue = (Rm_Transaction *)rmInst->transactionQueue; Rm_Transaction *newTransaction = NULL; void *key; /* Lock access to the RM instance's transaction queue */ key = Rm_osalCsEnter(); /* Get memory for a new transaction from local memory */ newTransaction = Rm_osalMalloc(sizeof(Rm_Transaction), false); /* Return if the memory allocated for the transaction entry is NULL */ if (newTransaction == NULL) { Rm_osalCsExit(key); return(newTransaction); } /* Clear the transaction */ memset((void *)newTransaction, 0, sizeof(Rm_Transaction)); /* Populate transaction with the provided ID */ newTransaction->id = transactionId; /* New transaction's nextTransaction pointer will always be NULL */ newTransaction->nextTransaction = NULL; /* Check if there are any transactions in the transaction queue */ if (transactionQueue) { /* At least one transaction in the transaction queue. Add the new entry to the * end of the transaction queue */ while (transactionQueue->nextTransaction != NULL) { /* Traverse the list until arriving at the last transaction */ transactionQueue = transactionQueue->nextTransaction; } /* Add the new transaction to the end of the queue */ transactionQueue->nextTransaction = newTransaction; } else { /* The transaction queue does not currently exist. The new transaction is the * first transaction */ rmInst->transactionQueue = newTransaction; } Rm_osalCsExit(key); return (newTransaction); } Rm_Transaction *Rm_transactionQueueFind(Rm_Inst *rmInst, uint32_t transactionId) { Rm_Transaction *transaction = (Rm_Transaction *)rmInst->transactionQueue; /* Make sure there is at least one transaction in the transaction queue */ if (transaction != NULL) { /* Find the transaction ID within the specified RM instance's transaction queue. * If the end of the transaction queue is reached without finding the transaction the * transaction pointer will be NULL */ while (transaction != NULL) { if (transaction->id == transactionId) { /* Match: break out of loop and return the transaction */ break; } transaction = transaction->nextTransaction; } } return (transaction); } int32_t Rm_transactionQueueDelete(Rm_Inst *rmInst, uint32_t transactionId) { Rm_Transaction *transaction = (Rm_Transaction *) rmInst->transactionQueue; Rm_Transaction *prevTransaction = NULL; void *key; /* Lock access to the RM instance's transaction queue */ key = Rm_osalCsEnter(); /* Make sure there is at least one entry in the transaction queue */ if (transaction == NULL) { Rm_osalCsExit(key); return (RM_SERVICE_ERROR_NO_TRANSACTIONS_IN_QUEUE); } /* Find the transaction ID within the specified RM instance's transaction queue. */ while (transaction != NULL) { if (transaction->id == transactionId) { /* Match: break out of loop and delete the transaction */ break; } prevTransaction = transaction; transaction = transaction->nextTransaction; } /* Traversed entire queue but did not find transaction */ if (transaction == NULL) { Rm_osalCsExit(key); return (RM_SERVICE_ERROR_SERVICE_TRANSACTION_DOES_NOT_EXIST); } else { /* Delete the transaction */ if ((prevTransaction == NULL) && transaction->nextTransaction) { /* Transaction to be deleted exists at start of transaction queue. Map second * transaction to be start of transaction queue as long as there are more than * one transactions */ rmInst->transactionQueue = transaction->nextTransaction; } else { /* Transaction to be deleted is in the middle or at end of the queue. Adjust * adjacent transaction pointers. This covers the case where the transaction to be * removed is at the end of the queue. */ prevTransaction->nextTransaction = transaction->nextTransaction; } /* Free the memory associated with the transaction. */ Rm_osalFree((void *)transaction, sizeof(Rm_Transaction), false); } Rm_osalCsExit(key); return (RM_SERVICE_ACTION_OKAY); } uint32_t Rm_transactionGetSequenceNum(Rm_Inst *rmInst) { uint32_t sequenceNum = 0; void *key; /* Lock access to the RM instance */ key = Rm_osalCsEnter(); /* Get the next sequence number and then incement. Overflow is okay since * it just restarts the sequence number count. */ sequenceNum = rmInst->transactionSeqNum++; Rm_osalCsExit(key); return (sequenceNum); } /* Function used to send RM response transactions to lower level agents */ void Rm_transactionResponder (Rm_Inst *rmInst, Rm_Transaction *transaction, Rm_TransactionReceipt *receipt) { Rm_TransportNode *dstTransportNode = NULL; Rm_Packet *rmPkt = NULL; /* Find the transport for the RM instance that sent the request. */ dstTransportNode = Rm_transportNodeFindRemoteName(rmInst, transaction->sourceInstName); /* Create a RM packet using the service information */ switch (transaction->type) { case Rm_service_RESOURCE_ALLOCATE: case Rm_service_RESOURCE_BLOCK_ALLOCATE: case Rm_service_RESOURCE_ALLOCATE_BY_NAME: case Rm_service_RESOURCE_FREE: case Rm_service_RESOURCE_BLOCK_FREE: case Rm_service_RESOURCE_FREE_BY_NAME: rmPkt = Rm_transportCreateResourceResponsePkt(rmInst, dstTransportNode, transaction, receipt); break; case Rm_service_RESOURCE_MAP_TO_NAME: case Rm_service_RESOURCE_UNMAP_NAME: rmPkt = Rm_transportCreateNsResponsePkt(rmInst, dstTransportNode, transaction, receipt); break; default: /* Invalid service type. Flag the error and return */ receipt->serviceResult = RM_SERVICE_ERROR_INVALID_SERVICE_TYPE; break; } if (receipt->serviceResult <= RM_SERVICE_ERROR_BASE) { /* Delete the transaction and return immediately because an error occurred * allocating the packet */ Rm_transactionQueueDelete(rmInst, transaction->id); return; } /* Send the RM packet to the application transport */ if (rmInst->transport.rmSend((Rm_TransportHandle) dstTransportNode, rmPkt) < RM_TRANSPORT_SUCCESSFUL) { /* Negative value returned by transport send. An error occurred * in the transport while attempting to send the packet.*/ receipt->serviceResult = RM_SERVICE_ERROR_TRANPSPORT_SEND_ERROR; /* Clean up the packet */ if (rmInst->transport.rmFreePkt((Rm_TransportHandle) dstTransportNode, rmPkt)) { /* Non-NULL value returned by transport packet free. Flag the * error */ receipt->serviceResult = RM_SERVICE_ERROR_TRANSPORT_FREE_PKT_ERROR; } return; } /* Fill out the receipt information and delete the transaction */ receipt->serviceResult = transaction->details; Rm_transactionQueueDelete(rmInst, transaction->id); } void Rm_allocationHandler (Rm_Inst *rmInst, Rm_Transaction *transaction, Rm_TransactionReceipt *receipt) { if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) { #if 0 /* Check local policy to see if the request can be satisfied with the * resources stored locally */ Rm_policy...API() if (policy check approves the resource) { /* call the allocator to allocate the resource */ if (allocator returns resource) { /* Populate the receipt with the allocated resources and the result */ receipt->serviceResult = approve reason; receipt->serviceId = transaction->id; return ... } else { /* allocator ran out of resources, need to contact Server for more * resources */ Rm_resourcePoolModRequest(...); } } else if (policy check denies resource) { /* Policy check denied resource. */ receipt->serviceResult = deny reason; receipt->serviceId = transaction->id; return ... } else if (policy check says forward to Server for validation) { /* Forward the transaction to the Server */ Rm_transactionForwarder(rmInst, transaction, receipt); } #endif } else if (rmInst->instType == Rm_instType_SERVER) { #if 0 /* Check global policy to see if resource can be allocated. return result * no matter what */ Rm_policy...API() if (policy approves) { /* call allocator to allocate resource */ } receipt->serviceResult = approve or deny reason; receipt->serviceId = transaction->id; receipt->resourceBase = ...; receipt->resourceRange = ...; /* If source instance name does not match the current instance * name the allocation request came from a client. The result * must be sent back to the Client */ if (strcmp(transaction->sourceInstName, rmInst->name)) { /* Names don't match. Copy the allocation response resource data * into the original transaction and send it back to the Client */ transaction->details = transaction->details; transaction->resourceInfo.base = receipt->resourceBase; transaction->resourceInfo.range = receipt->resourceRange; Rm_transactionResponder(rmInst, transaction, receipt); } else { /* Resource allocation request originated locally on the active * instance. Send the response via the service responder. */ transaction->details = transaction->details; transaction->resourceInfo.base = receipt->resourceBase; transaction->resourceInfo.range = receipt->resourceRange; Rm_serviceResponder(rmInst, transaction, NULL, receipt); } #endif } } void Rm_freeHandler (Rm_Inst *rmInst, Rm_Transaction *transaction, Rm_TransactionReceipt *receipt) { if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) { #if 0 /* Check local policy to see if the request can be satisfied with the * resources stored locally */ Rm_policy...API() if (policy check approves the free) { /* call the allocator to free the resource */ /* Run a resource pool check to see if the free combined a resource block * that can be returned to the server */ if (resource block has been combined) { /* allocator ran out of resources, need to contact Server for more * resources */ Rm_resourcePoolModRequest(free pool block to server...); } else { /* Populate the receipt with the freed resources and the result */ receipt->serviceResult = approve reason; receipt->serviceId = transaction->id; return ... } } else if (policy check denies resource free) { /* Policy check denied resource. */ receipt->serviceResult = deny reason; receipt->serviceId = transaction->id; return ... } else if (policy check says forward to Server for validation) { /* Forward the transaction to the Server */ Rm_transactionForwarder(rmInst, transaction, receipt); } #endif } else if (rmInst->instType == Rm_instType_SERVER) { #if 0 /* Check global policy to see if resource can be freed. return result * no matter what */ Rm_policy...API() if (policy approves) { /* call allocator to free resources */ } receipt->serviceResult = approve or deny reason; receipt->serviceId = transaction->id; receipt->resourceBase = ...; receipt->resourceRange = ...; /* If source instance name does not match the current instance * name the allocation request came from a client. The result * must be sent back to the Client */ if (strcmp(transaction->sourceInstName, rmInst->name)) { /* Names don't match. Copy the free response resource data * into the original transaction and send it back to the Client Delegate or Client */ transaction->details = transaction->details; transaction->resourceInfo.base = receipt->resourceBase; transaction->resourceInfo.range = receipt->resourceRange; Rm_transactionResponder(rmInst, transaction, receipt); } else { /* Resource allocation request originated locally on the active * instance. Send the response via the service responder. */ transaction->details = transaction->details; transaction->resourceInfo.base = receipt->resourceBase; transaction->resourceInfo.range = receipt->resourceRange; Rm_serviceResponder(rmInst, transaction, NULL, receipt); } #endif } } /* Function used to forward RM transactions to higher level agents */ void Rm_transactionForwarder (Rm_Inst *rmInst, Rm_Transaction *transaction, Rm_TransactionReceipt *receipt) { Rm_TransportNode *dstTransportNode = NULL; Rm_Packet *rmPkt = NULL; /* Make sure the RM instance has a transport registered with a higher level agent */ if (rmInst->registeredWithDelegateOrServer == false) { receipt->serviceResult = RM_SERVICE_ERROR_NOT_REGISTERED_WITH_DEL_OR_SERVER; return; } /* Find the transport for the higher level agent. Check for a connection to a Client Delegate * or a Server. Clients will be connected to either a Client Delegate or a Server. Client * Delegates will be connected to a Server. */ if (rmInst->instType == Rm_instType_CLIENT) { dstTransportNode = Rm_transportNodeFindRemoteInstType(rmInst, Rm_instType_CLIENT_DELEGATE); } else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) { dstTransportNode = Rm_transportNodeFindRemoteInstType(rmInst, Rm_instType_SERVER); } /* Create a RM packet using the service information */ switch (transaction->type) { case Rm_service_RESOURCE_ALLOCATE: case Rm_service_RESOURCE_BLOCK_ALLOCATE: case Rm_service_RESOURCE_ALLOCATE_BY_NAME: case Rm_service_RESOURCE_FREE: case Rm_service_RESOURCE_BLOCK_FREE: case Rm_service_RESOURCE_FREE_BY_NAME: rmPkt = Rm_transportCreateResourceReqPkt(rmInst, dstTransportNode, transaction, receipt); break; case Rm_service_RESOURCE_MAP_TO_NAME: case Rm_service_RESOURCE_UNMAP_NAME: rmPkt = Rm_transportCreateNsRequestPkt(rmInst, dstTransportNode, transaction, receipt); break; default: /* Invalid service type. Flag the error and return */ receipt->serviceResult = RM_SERVICE_ERROR_INVALID_SERVICE_TYPE; break; } if (receipt->serviceResult <= RM_SERVICE_ERROR_BASE) { /* Return immediately because an error occurred allocating the packet */ return; } /* Switch the queued transaction to the awaiting response state */ transaction->state = Rm_transactionState_AWAITING_RESPONSE; /* Send the RM packet to the application transport */ if (rmInst->transport.rmSend((Rm_TransportHandle) dstTransportNode, rmPkt) < RM_TRANSPORT_SUCCESSFUL) { /* Negative value returned by transport send. An error occurred * in the transport while attempting to send the packet.*/ receipt->serviceResult = RM_SERVICE_ERROR_TRANPSPORT_SEND_ERROR; /* Clean up the packet */ if (rmInst->transport.rmFreePkt((Rm_TransportHandle) dstTransportNode, rmPkt)) { /* Non-NULL value returned by transport packet free. Flag the * error */ receipt->serviceResult = RM_SERVICE_ERROR_TRANSPORT_FREE_PKT_ERROR; } return; } /* Inform requesting component that the service is being forwarded to a higher lever * RM agent for processing. The result of the service will be provided to the * component via the specified callback function */ receipt->serviceResult = RM_SERVICE_PROCESSING; receipt->serviceId = transaction->id; } void Rm_transactionProcessor (Rm_Inst *rmInst, Rm_Transaction *transaction, Rm_TransactionReceipt *receipt) { Rm_Transaction *queuedTransaction = NULL; /* Handle auto-forwarded transactions. These transactions include: * - All request transactions received on Clients are forwarded to the Client Delegate * - NameServer requests received on the Client Delegate are forwarded to the Server */ if ((rmInst->instType == Rm_instType_CLIENT) || ((rmInst->instType == Rm_instType_CLIENT_DELEGATE) && (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) || (transaction->type == Rm_service_RESOURCE_UNMAP_NAME))) { /* Check if the new transaction's ID matches any transactions waiting for * responses. A transaction received as a response will have an ID that * matches the transaction that originated the request packet */ if (queuedTransaction = Rm_transactionQueueFind(rmInst, transaction->id)) { if (queuedTransaction->state == Rm_transactionState_AWAITING_RESPONSE) { if (rmInst->instType == Rm_instType_CLIENT) { /* Client found a transaction awaiting a response. Pass both transactions * to the service responder for response processing */ Rm_serviceResponder(rmInst, transaction, queuedTransaction, receipt); } else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) { /* Client Delegate found a NameServer transaction awaiting a response. Send the * response to either the transaction or service responder based on the * source instance */ if (strcmp(queuedTransaction->sourceInstName, rmInst->name)) { /* NameServer transaction originated from another instance. Use the * transaction responder to send the NameServer result to the source instance. * Need to transfer the NameServer result details to the request transaction * which will be reused for the response. */ queuedTransaction->details = transaction->details; Rm_transactionResponder(rmInst, queuedTransaction, receipt); /* Delete the response transaction */ Rm_transactionQueueDelete(rmInst, transaction->id); } else { /* NameServer request originated on the Client Delegate instance. Send to the * service responder */ Rm_serviceResponder(rmInst, transaction, queuedTransaction, receipt); } } } else { /* Request transaction was not in the awaiting response state. Flag the * error in the receipt and return */ receipt->serviceResult = RM_SERVICE_ERROR_INVALID_REQUEST_TRANSACTION_STATE_UPON_RESPONSE; } } else { /* This is a new transaction. Make sure the transaction is not a * response transaction sent to the wrong RM instance */ if ((transaction->state == Rm_transactionState_RESOURCE_APPROVED) || (transaction->state == Rm_transactionState_RESOURCE_DENIED)) { /* No matching request transaction. This transaction result was sent to the * wrong RM instance. Flag the error in the receipt and return */ receipt->serviceResult = RM_SERVICE_ERROR_INVALID_TRANSACTION_RECEIVED_ON_CLIENT; } else { /* All service requests on Clients are forwarded to the higher level RM Client * Delegate. NameServer requests on Client Delegates are forwarded to the Server. */ Rm_transactionForwarder(rmInst, transaction, receipt); } } } else { /* Client Delegate and Server transaction processors. */ switch (transaction->type) { case Rm_service_RESOURCE_ALLOCATE: case Rm_service_RESOURCE_BLOCK_ALLOCATE: case Rm_service_RESOURCE_ALLOCATE_BY_NAME: /* Run the transaction through the response handler to take care of any * transactions that are responses to sent allocation requests. */ if (queuedTransaction = Rm_transactionQueueFind(rmInst, transaction->id)) { if (queuedTransaction->state == Rm_transactionState_AWAITING_RESPONSE) { /* If source instance name does not match the current instance * name the allocation request came from a client. The result * must be sent back to the Client */ if (strcmp(queuedTransaction->sourceInstName, rmInst->name)) { /* Names don't match. Copy the allocation response resource data * into the original transaction and send it back to the Client */ queuedTransaction->details = transaction->details; memcpy ((void *)&(queuedTransaction->resourceInfo), (void *)&(transaction->resourceInfo), sizeof(Rm_ResourceInfo)); Rm_transactionResponder(rmInst, queuedTransaction, receipt); /* Delete the response transaction */ Rm_transactionQueueDelete(rmInst, transaction->id); } else { /* Resource allocation request originated locally on Client Delegate * instance. Send the response via the service responder. */ Rm_serviceResponder(rmInst, transaction, queuedTransaction, receipt); } } else { /* Request transaction was not in the awaiting response state. Flag the * error in the receipt and return */ receipt->serviceResult = RM_SERVICE_ERROR_INVALID_REQUEST_TRANSACTION_STATE_UPON_RESPONSE; } } else { /* This is a new transaction request originating from an RM instance with fewer * allocate/free privileges. Run the allocation handler to see if the resource * request can be handled locally or if it needs to be forwarded to a higher level * agent */ Rm_allocationHandler(rmInst, transaction, receipt); } break; case Rm_service_RESOURCE_FREE: case Rm_service_RESOURCE_BLOCK_FREE: case Rm_service_RESOURCE_FREE_BY_NAME: /* Run the transaction through the response handler to take care of any * transactions that are responses to sent free requests. */ if (queuedTransaction = Rm_transactionQueueFind(rmInst, transaction->id)) { if (queuedTransaction->state == Rm_transactionState_AWAITING_RESPONSE) { /* If source instance name does not match the current instance * name the allocation request came from a client. The result * must be sent back to the Client */ if (strcmp(queuedTransaction->sourceInstName, rmInst->name)) { /* Names don't match. Copy the free response resource data * into the original transaction and send it back to the Client */ queuedTransaction->details = transaction->details; memcpy ((void *)&(queuedTransaction->resourceInfo), (void *)&(transaction->resourceInfo), sizeof(Rm_ResourceInfo)); Rm_transactionResponder(rmInst, queuedTransaction, receipt); /* Delete the response transaction */ Rm_transactionQueueDelete(rmInst, transaction->id); } else { /* Resource free request originated locally on Client Delegate * instance. Send the response via the service responder. */ Rm_serviceResponder(rmInst, transaction, queuedTransaction, receipt); } } else { /* Request transaction was not in the awaiting response state. Flag the * error in the receipt and return */ receipt->serviceResult = RM_SERVICE_ERROR_INVALID_REQUEST_TRANSACTION_STATE_UPON_RESPONSE; } } else { /* This is a new transaction request originating from an RM instance with fewer * allocate/free privileges. Run the free handler to see if the resource * request can be handled locally or if it needs to be forwarded to a higher level * agent */ Rm_freeHandler(rmInst, transaction, receipt); } break; case Rm_service_RESOURCE_MAP_TO_NAME: /* Server is the only RM instance capable of adding NameServer objects */ if (rmInst->instType == Rm_instType_SERVER) { /* Create a new NameServer object with the request transaction information */ Rm_nsAddObject(rmInst, transaction, receipt); /* Return the result of the NameServer addition to the RM instance * that requested it */ transaction->details = receipt->serviceResult; /* If source instance name does not match the current instance * name the NameServer request came from a Client or Client Delegate. The * result must be sent back to the Client or Client Delegate */ if (strcmp(transaction->sourceInstName, rmInst->name)) { Rm_transactionResponder(rmInst, queuedTransaction, receipt); } else { /* NameServer addition request originated locally on Server * instance. Send the response via the service responder. In this case * the request transaction will be passed as NULL since the request * is being reused as the response */ Rm_serviceResponder(rmInst, transaction, NULL, receipt); } } else { receipt->serviceResult = RM_SERVICE_ERROR_NAMESERVER_OBJECT_CREATE_ON_INVALID_INSTANCE; } break; case Rm_service_RESOURCE_UNMAP_NAME: /* Server is the only RM instance capable of deleting NameServer objects */ if (rmInst->instType == Rm_instType_SERVER) { /* Delete an existing NameServer object with the request transaction information */ Rm_nsDeleteObject(rmInst, transaction, receipt); /* Return the result of the NameServer deletion to the RM instance * that requested it */ transaction->details = receipt->serviceResult; /* If source instance name does not match the current instance * name the NameServer request came from a Client or Client Delegate. The * result must be sent back to the Client or Client Delegate */ if (strcmp(transaction->sourceInstName, rmInst->name)) { Rm_transactionResponder(rmInst, queuedTransaction, receipt); } else { /* NameServer delete request originated locally on Server * instance. Send the response via the service responder. In this case * the request transaction will be passed as NULL since the request * is being reused as the response */ Rm_serviceResponder(rmInst, transaction, NULL, receipt); } } else { receipt->serviceResult = RM_SERVICE_ERROR_NAMESERVER_OBJECT_DELETE_ON_INVALID_INSTANCE; } break; } } } /********************************************************************** ********************** Application visible APIs ********************** **********************************************************************/ Rm_Handle Rm_init(Rm_InitCfg *initCfg) { Rm_Inst *rmInst; /* Instance creation checks. Add one to strlen calculation for null character */ if ((strlen(initCfg->instName) + 1) > RM_INSTANCE_NAME_MAX_CHARS) { /* Failure: Instance name is too big */ return (NULL); } /* Get memory for RM instance from local memory */ rmInst = Rm_osalMalloc (sizeof(Rm_Inst), false); /* Populate instance based on input parameters */ strcpy (&rmInst->name[0], initCfg->instName); rmInst->instType = initCfg->instType; rmInst->instState = RM_state_IDLE; rmInst->registeredWithDelegateOrServer = false; /* Initialize the transport routing map linked list pointer to NULL. The linked list * nodes will be created when the application registers transports */ rmInst->routeMap = NULL; /* Initialize the transaction queue elements. The linked list pointer is set to NULL * and the transaction sequence number is initialized to 0. */ rmInst->transactionSeqNum = 0; rmInst->transactionQueue= NULL; /* RM Server specific actions */ if (rmInst->instType == Rm_instType_SERVER) { /* parse DTB, etc */ } /* Instance startup policies are only used for Servers and Client Delegates */ if (rmInst->instType != Rm_instType_CLIENT) { rmInst->instPolicy = initCfg->startupPolicy; /* Store policy via policy APIs ... */ } /* Return the RM Handle */ return ((Rm_Handle) rmInst); } uint32_t Rm_getVersion (void) { return RM_VERSION_ID; } const char* Rm_getVersionStr (void) { return rmVersionStr; } /** @} */