diff --git a/src/rm.c b/src/rm.c
index e546fc3f09be869737c996a1d0028a1394c1085e..273c1759364e535d3fc4f21255661f245c03af74 100644 (file)
--- a/src/rm.c
+++ b/src/rm.c
\r
/* RM external includes */\r
#include <ti/drv/rm/rm.h>\r
-#include <ti/drv/rm/rmservices.h>\r
-#include <ti/drv/rm/rmtransport.h>\r
-#include <ti/drv/rm/rmpolicy.h>\r
+#include <ti/drv/rm/rm_services.h>\r
+#include <ti/drv/rm/rm_transport.h>\r
+#include <ti/drv/rm/rm_policy.h>\r
\r
/* RM internal includes */\r
-#include <ti/drv/rm/include/rmloc.h>\r
+#include <ti/drv/rm/include/rm_loc.h>\r
+#include <ti/drv/rm/include/rm_transportloc.h>\r
+#include <ti/drv/rm/include/rm_servicesloc.h>\r
+#include <ti/drv/rm/include/rm_nameserverloc.h>\r
+#include <ti/drv/rm/include/rm_dtb_utilloc.h>\r
+#include <ti/drv/rm/include/rm_policyloc.h>\r
+\r
+/* RM LIBFDT includes */\r
+#include <ti/drv/rm/src/libfdt/libfdt.h>\r
+\r
+/* AVL BBST includes */\r
+#include <ti/drv/rm/include/tree.h>\r
\r
/* RM OSAL layer */\r
#include <rm_osal.h>\r
/**********************************************************************\r
************************** Globals ***********************************\r
**********************************************************************/\r
-\r
-/* Place QMSS PDSP permissions array */\r
-#pragma DATA_SECTION (rmQmssPdspFirmwarePerms, ".rm");\r
-#pragma DATA_ALIGN (rmQmssPdspFirmwarePerms, 128)\r
-Rm_Perms rmQmssPdspFirmwarePerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_QMSS_FIRMWARE_PDSPS, Rm_Perms)];\r
-\r
+extern char rmDtbStartingNode[];\r
\r
/** @brief Global Variable which describes the RM Version Information */\r
const char rmVersionStr[] = RM_VERSION_STR ":" __DATE__ ":" __TIME__;\r
\r
+/**********************************************************************\r
+ ************** Red-Black BBST Tree Allocator Functions ***************\r
+ **********************************************************************/\r
+\r
+\r
+Rm_ResourceNode *Rm_newResourceNode(uint32_t resourceBase, uint32_t resourceLength)\r
+{\r
+ Rm_ResourceNode *newNode = NULL;\r
+\r
+ newNode = Rm_osalMalloc(sizeof(Rm_ResourceNode));\r
+ memset((void *)newNode, 0, sizeof(Rm_ResourceNode));\r
+\r
+ newNode->base = resourceBase;\r
+ newNode->length = resourceLength;\r
+ newNode->allocationCount = 0;\r
+ newNode->allocatedTo = NULL;\r
+\r
+ return(newNode);\r
+}\r
+\r
+void Rm_freeResourceNode(Rm_ResourceNode *node)\r
+{\r
+ if (node->allocationCount == 0) {\r
+ Rm_osalFree((void *)node, sizeof(Rm_ResourceNode));\r
+ }\r
+}\r
+\r
+/* Prototype for tree node comparison function\r
+ * element1 < element2 --> return < 0\r
+ * element1 = element2 --> return 0\r
+ * element1 > element2 --> return > 0 */\r
+int Rm_ResourceNodeCompare(Rm_ResourceNode *element1, Rm_ResourceNode *element2)\r
+{\r
+ uint32_t element1End = element1->base + element1->length - 1;\r
+ uint32_t element2End = element2->base + element2->length - 1;\r
+\r
+ if (element1End < element2->base) {\r
+ /* End of element1 range is less than the start of element2's range. Return a negative\r
+ * value */\r
+ return (-1);\r
+ }\r
+ else if (element1->base > element2End) {\r
+ /* Start of element1 range is after end of element2's range. Return a positive value */\r
+ return (1);\r
+ }\r
+ else {\r
+ /* If neither of the latter conditions were satisfied there is some overlap between\r
+ * element1 and element2. Return 0 since the application must handle this overlap. */\r
+ return (0);\r
+ }\r
+}\r
+\r
+/* Generate the red-black tree manipulation functions */\r
+RB_GENERATE(_Rm_ResourceTree, _Rm_ResourceNode, linkage, Rm_ResourceNodeCompare);\r
+\r
/**********************************************************************\r
********************** Internal Functions ****************************\r
**********************************************************************/\r
\r
-/* At the very least the transaction ID needs to be provided to create a transaction */\r
-Rm_Transaction *Rm_transactionQueueAdd(Rm_Inst *rmInst, uint32_t transactionId)\r
+Rm_Transaction *Rm_transactionQueueAdd(Rm_Inst *rmInst)\r
{\r
Rm_Transaction *transactionQueue = (Rm_Transaction *)rmInst->transactionQueue;\r
- Rm_Transaction *newTransaction = NULL;\r
- void *key;\r
+ Rm_Transaction *newTransaction = NULL;\r
+ void *key;\r
\r
/* Lock access to the RM instance's transaction queue */\r
- key = Rm_osalLocalCsEnter();\r
+ key = Rm_osalMtCsEnter();\r
\r
/* Get memory for a new transaction from local memory */\r
- newTransaction = Rm_osalMalloc(sizeof(Rm_Transaction), false);\r
+ newTransaction = Rm_osalMalloc(sizeof(Rm_Transaction));\r
\r
/* Return if the memory allocated for the transaction entry is NULL */\r
- if (newTransaction == NULL)\r
- {\r
- Rm_osalLocalCsExit(key);\r
- return(newTransaction);\r
- }\r
+ if (newTransaction != NULL) {\r
+ /* Clear the transaction */\r
+ memset((void *)newTransaction, 0, sizeof(Rm_Transaction));\r
\r
- /* Clear the transaction */\r
- memset((void *)newTransaction, 0, sizeof(Rm_Transaction));\r
+ /* Create an ID for the new transaction. The ID will be used for two purposes:\r
+ * 1) Matching responses from higher level RM agents to requests\r
+ * 2) Provided to the component that requested the service so that it can match its\r
+ * request with the response it receives via its callback function it provided */\r
+ newTransaction->localId = Rm_transactionGetSequenceNum(rmInst);\r
+ /* New transaction's nextTransaction pointer will always be NULL */\r
+ newTransaction->nextTransaction = NULL; \r
\r
- /* Populate transaction with the provided ID */\r
- newTransaction->id = transactionId;\r
- /* New transaction's nextTransaction pointer will always be NULL */\r
- newTransaction->nextTransaction = NULL; \r
+ /* Check if there are any transactions in the transaction queue */\r
+ if (transactionQueue) {\r
+ /* At least one transaction in the transaction queue. Add the new entry to the \r
+ * end of the transaction queue */\r
+ while (transactionQueue->nextTransaction != NULL) {\r
+ /* Traverse the list until arriving at the last transaction */\r
+ transactionQueue = transactionQueue->nextTransaction;\r
+ }\r
\r
- /* Check if there are any transactions in the transaction queue */\r
- if (transactionQueue)\r
- {\r
- /* At least one transaction in the transaction queue. Add the new entry to the \r
- * end of the transaction queue */\r
- while (transactionQueue->nextTransaction != NULL)\r
- {\r
- /* Traverse the list until arriving at the last transaction */\r
- transactionQueue = transactionQueue->nextTransaction;\r
+ /* Add the new transaction to the end of the queue */\r
+ transactionQueue->nextTransaction = newTransaction;\r
+ }\r
+ else {\r
+ /* The transaction queue does not currently exist. The new transaction is the \r
+ * first transaction */\r
+ rmInst->transactionQueue = newTransaction;\r
}\r
-\r
- /* Add the new transaction to the end of the queue */\r
- transactionQueue->nextTransaction = newTransaction;\r
- }\r
- else\r
- {\r
- /* The transaction queue does not currently exist. The new transaction is the \r
- * first transaction */\r
- rmInst->transactionQueue = newTransaction;\r
}\r
\r
- Rm_osalLocalCsExit(key);\r
+ Rm_osalMtCsExit(key);\r
return (newTransaction);\r
}\r
\r
Rm_Transaction *Rm_transactionQueueFind(Rm_Inst *rmInst, uint32_t transactionId)\r
{\r
Rm_Transaction *transaction = (Rm_Transaction *)rmInst->transactionQueue;\r
- void *key;\r
\r
- /* Make sure there is at least one transaction in the transaction queue */\r
- if (transaction != NULL)\r
- {\r
- /* Find the transaction ID within the specified RM instance's transaction queue.\r
- * If the end of the transaction queue is reached without finding the transaction the \r
- * transaction pointer will be NULL */\r
- while (transaction != NULL)\r
- {\r
- if (transaction->transactionId == transactionId)\r
- {\r
- /* Match: break out of loop and return the transaction */\r
+ if (transaction != NULL) {\r
+ while (transaction != NULL) {\r
+ if (transaction->localId == transactionId) {\r
break; \r
}\r
transaction = transaction->nextTransaction;\r
}\r
}\r
-\r
return (transaction);\r
}\r
\r
int32_t Rm_transactionQueueDelete(Rm_Inst *rmInst, uint32_t transactionId)\r
{\r
- Rm_Transaction *transaction = (Rm_Transaction *) rmInst->transactionQueue;\r
+ Rm_Transaction *transaction = (Rm_Transaction *) rmInst->transactionQueue;\r
Rm_Transaction *prevTransaction = NULL;\r
- void *key;\r
+ int32_t retVal = RM_SERVICE_STATE_OKAY;\r
+ void *key;\r
\r
- /* Lock access to the RM instance's transaction queue */\r
- key = Rm_osalLocalCsEnter();\r
+ /* Lock access to the instance */\r
+ key = Rm_osalMtCsEnter();\r
\r
- /* Make sure there is at least one entry in the transaction queue */\r
- if (transaction == NULL)\r
- {\r
- Rm_osalLocalCsExit(key);\r
- return (RM_SERVICE_ERROR_NO_TRANSACTIONS_IN_QUEUE);\r
- }\r
-\r
- /* Find the transaction ID within the specified RM instance's transaction queue. */\r
- while (transaction != NULL)\r
- {\r
- if (transaction->transactionId == transactionId)\r
- {\r
- /* Match: break out of loop and delete the transaction */\r
+ /* Find transaction ID within transaction queue. */\r
+ while (transaction) {\r
+ if (transaction->localId == transactionId) {\r
break; \r
}\r
\r
prevTransaction = transaction;\r
- transaction = transaction->nextEntry;\r
+ transaction = transaction->nextTransaction;\r
}\r
\r
- /* Traversed entire queue but did not find transaction */\r
- if (transaction == NULL)\r
- {\r
- Rm_osalLocalCsExit(key);\r
- return (RM_SERVICE_ERROR_SERVICE_TRANSACTION_DOES_NOT_EXIST);\r
- }\r
- else\r
- {\r
- /* Delete the transaction */\r
- if ((prevTransaction == NULL) && transaction->nextTransaction)\r
- {\r
- /* Transaction to be deleted exists at start of transaction queue. Map second\r
- * transaction to be start of transaction queue as long as there are more than\r
- * one transactions */\r
+ if (transaction) {\r
+ if (prevTransaction == NULL) {\r
+ /* Transaction at start of queue. Map second transaction to start of queue \r
+ * as long as more than one transactions. */\r
rmInst->transactionQueue = transaction->nextTransaction;\r
}\r
- else\r
- {\r
- /* Transaction to be deleted is in the middle or at end of the queue. Adjust \r
- * adjacent transaction pointers. This covers the case where the transaction to be \r
- * removed is at the end of the queue. */\r
+ else {\r
+ /* Transaction in middle or end of queue. */\r
prevTransaction->nextTransaction = transaction->nextTransaction;\r
}\r
+ Rm_osalFree((void *)transaction, sizeof(Rm_Transaction));\r
+ }\r
+ else {\r
+ retVal = RM_SERVICE_ERROR_SERVICE_TRANSACTION_DOES_NOT_EXIST;\r
+ } \r
+\r
+ Rm_osalMtCsExit(key);\r
+ return (retVal);\r
+}\r
+\r
+uint32_t Rm_transactionInitSequenceNum(void)\r
+{\r
+ /* Sequence number can never have value of 0. Avoids conflicts\r
+ * with non-response transactions that have remoteOriginatingId of 0 */\r
+ return (1);\r
+}\r
+\r
+uint32_t Rm_transactionGetSequenceNum(Rm_Inst *rmInst)\r
+{\r
+ uint32_t sequenceNum = 0;\r
+\r
+ if (rmInst->transactionSeqNum + 1 < rmInst->transactionSeqNum) {\r
+ /* Overflow */\r
+ sequenceNum = rmInst->transactionSeqNum;\r
+ rmInst->transactionSeqNum = Rm_transactionInitSequenceNum();\r
+ }\r
+ else {\r
+ sequenceNum = rmInst->transactionSeqNum++;\r
+ } \r
+ return (sequenceNum);\r
+}\r
+\r
+Rm_Allocator *Rm_allocatorAdd(Rm_Inst *rmInst, const char *resourceName)\r
+{\r
+ Rm_Allocator *allocators = (Rm_Allocator *)rmInst->allocators;\r
+ Rm_Allocator *newAllocator = NULL;\r
+ void *key;\r
+\r
+ /* Lock access to the instance */\r
+ key = Rm_osalMtCsEnter();\r
+\r
+ newAllocator = Rm_osalMalloc(sizeof(Rm_Allocator));\r
+\r
+ if (newAllocator) {\r
+ memset((void *)newAllocator, 0, sizeof(Rm_Allocator));\r
+ strcpy(newAllocator->resourceName, resourceName);\r
+ newAllocator->allocatorRootEntry = NULL;\r
+ newAllocator->nextAllocator = NULL; \r
+\r
+ /* Add allocator to end of list */\r
+ if (allocators) {\r
+ while (allocators->nextAllocator != NULL) {\r
+ allocators = allocators->nextAllocator;\r
+ }\r
+ allocators->nextAllocator = newAllocator;\r
+ }\r
+ else {\r
+ rmInst->allocators = newAllocator;\r
+ }\r
+ }\r
+\r
+ Rm_osalMtCsExit(key);\r
+ return (newAllocator);\r
+}\r
+\r
+Rm_Allocator *Rm_allocatorFind(Rm_Allocator *allocatorList, char *resourceName)\r
+{\r
+ while (allocatorList) {\r
+ if (strcmp(allocatorList->resourceName, resourceName) == 0) {\r
+ break; \r
+ }\r
+ allocatorList = allocatorList->nextAllocator;\r
+ }\r
+\r
+ return (allocatorList);\r
+}\r
+\r
+int32_t Rm_allocatorDelete(Rm_Inst *rmInst, char *resourceName)\r
+{\r
+ Rm_Allocator *allocator = (Rm_Allocator *) rmInst->allocators;\r
+ Rm_Allocator *prevAllocator = NULL;\r
+ int32_t retVal = RM_SERVICE_STATE_OKAY;\r
+ void *key;\r
+\r
+ /* Lock access to instance */\r
+ key = Rm_osalMtCsEnter();\r
+\r
+ while (allocator) {\r
+ if (strcmp(allocator->resourceName, resourceName) == 0) {\r
+ break; \r
+ }\r
+ prevAllocator = allocator;\r
+ allocator = allocator->nextAllocator;\r
+ }\r
+\r
+ if (allocator) {\r
+ if (prevAllocator == NULL) {\r
+ /* Allocator at start of list. Map second allocator to start of list \r
+ * as long as more than one allocators. */\r
+ rmInst->allocators = allocator->nextAllocator;\r
+ }\r
+ else {\r
+ /* Allocator in middle or end of list. */\r
+ prevAllocator->nextAllocator = allocator->nextAllocator;\r
+ }\r
+ Rm_osalFree((void *)allocator, sizeof(Rm_Allocator));\r
+ }\r
+ else {\r
+ retVal = -22; /* TEMP ERROR: Can't conflict with LIBFDT errors */\r
+ }\r
+\r
+ Rm_osalMtCsExit(key);\r
+ return (retVal);\r
+}\r
+\r
+void Rm_addAllocatedTo(Rm_ResourceNode *node, void *serviceInstNode)\r
+{\r
+ Rm_AllocatedTo *allocatedToList = node->allocatedTo;\r
+ Rm_AllocatedTo *newAllocatedTo = NULL;\r
+\r
+ newAllocatedTo = Rm_osalMalloc(sizeof(Rm_AllocatedTo));\r
+\r
+ if (newAllocatedTo) {\r
+ newAllocatedTo->instNameNode = serviceInstNode;\r
+ newAllocatedTo->nextAllocatedTo = NULL; \r
+\r
+ /* Add allocatedTo entry to end of list */\r
+ if (allocatedToList) {\r
+ while (allocatedToList->nextAllocatedTo) {\r
+ allocatedToList = allocatedToList->nextAllocatedTo;\r
+ }\r
+ allocatedToList->nextAllocatedTo = newAllocatedTo;\r
+ }\r
+ else {\r
+ node->allocatedTo = newAllocatedTo;\r
+ }\r
+\r
+ node->allocationCount++;\r
+ newAllocatedTo->instNameNode->allocRefCount++;\r
+ }\r
+}\r
+\r
+bool Rm_isAllocatedTo(Rm_ResourceNode *node, void *serviceInstNode)\r
+{\r
+ Rm_AllocatedTo *allocatedTo = node->allocatedTo;\r
+\r
+ while (allocatedTo) {\r
+ if (allocatedTo->instNameNode == serviceInstNode) {\r
+ return(TRUE); \r
+ }\r
+ allocatedTo = allocatedTo->nextAllocatedTo;\r
+ }\r
+ return(FALSE);\r
+}\r
+\r
+bool Rm_compareResourceNodeAllocations(Rm_ResourceNode *nodeOne, Rm_ResourceNode *nodeTwo)\r
+{\r
+ Rm_AllocatedTo *nodeOneAllocs = nodeOne->allocatedTo;\r
+ Rm_AllocatedTo *nodeTwoAllocs = nodeTwo->allocatedTo;\r
+ bool matchedInst;\r
+\r
+ if (nodeOne->allocationCount == nodeTwo->allocationCount) {\r
+ while (nodeOneAllocs) {\r
+ matchedInst = FALSE;\r
+ while (nodeTwoAllocs) {\r
+ if (nodeOneAllocs->instNameNode == nodeTwoAllocs->instNameNode) {\r
+ matchedInst = TRUE;\r
+ break;\r
+ }\r
+ nodeTwoAllocs = nodeTwoAllocs->nextAllocatedTo;\r
+ }\r
+\r
+ if (matchedInst) {\r
+ nodeTwoAllocs = nodeTwo->allocatedTo;\r
+ nodeOneAllocs = nodeOneAllocs->nextAllocatedTo;\r
+ }\r
+ else {\r
+ return(FALSE);\r
+ } \r
+ }\r
+ }\r
+ else {\r
+ return(FALSE);\r
+ } \r
+ \r
+ return(TRUE);\r
+}\r
+\r
+void Rm_deleteAllocatedTo(Rm_ResourceNode *node, void *serviceInstNode)\r
+{\r
+ Rm_AllocatedTo *allocatedTo = node->allocatedTo;\r
+ Rm_AllocatedTo *prevAllocatedTo = NULL;\r
+\r
+ while (allocatedTo) {\r
+ if (allocatedTo->instNameNode == serviceInstNode) {\r
+ break; \r
+ }\r
+ prevAllocatedTo = allocatedTo;\r
+ allocatedTo = allocatedTo->nextAllocatedTo;\r
+ }\r
+\r
+ if (prevAllocatedTo == NULL) {\r
+ /* AllocatedTo entry at start of list. Map second allocatedTo entry to start of list \r
+ * as long as more than one allocatedTo entries. */\r
+ node->allocatedTo = allocatedTo->nextAllocatedTo;\r
+ }\r
+ else {\r
+ /* AllocatedTo entry in middle or end of list. */\r
+ prevAllocatedTo->nextAllocatedTo = allocatedTo->nextAllocatedTo;\r
+ }\r
+ \r
+ node->allocationCount--;\r
+ allocatedTo->instNameNode->allocRefCount--;\r
+ Rm_osalFree((void *)allocatedTo, sizeof(Rm_AllocatedTo));\r
+}\r
+\r
+void Rm_copyAllocatedTo(Rm_ResourceNode *dstNode, Rm_ResourceNode *srcNode)\r
+{\r
+ Rm_AllocatedTo *srcAllocs = srcNode->allocatedTo;\r
+ Rm_AllocatedTo *newDstAlloc;\r
+ Rm_AllocatedTo *prevDstAlloc;\r
+\r
+ dstNode->allocationCount = srcNode->allocationCount;\r
+\r
+ while (srcAllocs) {\r
+ newDstAlloc = Rm_osalMalloc(sizeof(Rm_AllocatedTo));\r
+ newDstAlloc->instNameNode = srcAllocs->instNameNode;\r
+ newDstAlloc->nextAllocatedTo = NULL;\r
+\r
+ if (dstNode->allocatedTo == NULL) {\r
+ dstNode->allocatedTo = newDstAlloc;\r
+ }\r
+ else {\r
+ prevDstAlloc->nextAllocatedTo = newDstAlloc;\r
+ }\r
+ prevDstAlloc = newDstAlloc;\r
+ srcAllocs = srcAllocs->nextAllocatedTo;\r
+ }\r
+}\r
+\r
+void Rm_clearAllocatedTo(Rm_ResourceNode *node)\r
+{\r
+ Rm_AllocatedTo *allocatedTo = node->allocatedTo;\r
+ Rm_AllocatedTo *nextAllocatedTo;\r
+\r
+ while (allocatedTo) {\r
+ nextAllocatedTo = allocatedTo->nextAllocatedTo;\r
+ node->allocationCount--;\r
+ Rm_osalFree((void *)allocatedTo, sizeof(Rm_AllocatedTo));\r
+ allocatedTo = nextAllocatedTo;\r
+ }\r
+}\r
+\r
+int32_t Rm_createTreeAllocator(Rm_Inst *rmInst, const char *resourceName, Rm_ResourceRange *range)\r
+{\r
+ Rm_Allocator *allocator = NULL;\r
+ Rm_ResourceTree *treeRootEntry = NULL;\r
+ Rm_ResourceNode *treeNode = NULL;\r
+ Rm_ResourceNode *collidingNode = NULL;\r
+\r
+ allocator = Rm_allocatorAdd(rmInst, resourceName);\r
+ treeRootEntry = Rm_osalMalloc(sizeof(Rm_ResourceTree));\r
+ RB_INIT(treeRootEntry);\r
+\r
+ while (range != NULL) {\r
+ treeNode = Rm_newResourceNode(range->base, range->length);\r
+ collidingNode = RB_INSERT(_Rm_ResourceTree, treeRootEntry, treeNode);\r
+\r
+ if (collidingNode) {\r
+ Rm_ResourceNode *nextNode = NULL;\r
+ \r
+ /* Node that was inserted collides with existing node. Destroy tree and return error */\r
+ for (treeNode = RB_MIN(_Rm_ResourceTree, treeRootEntry); treeNode != NULL; treeNode = nextNode) {\r
+ nextNode = RB_NEXT(_Rm_ResourceTree, treeRootEntry, treeNode);\r
+ RB_REMOVE(_Rm_ResourceTree, treeRootEntry, nextNode);\r
+ Rm_freeResourceNode(treeNode);\r
+ }\r
+ Rm_osalFree((void *)treeRootEntry, sizeof(Rm_ResourceTree));\r
+ Rm_allocatorDelete(rmInst, allocator->resourceName);\r
+ return (-24); /* TODO FIX RETURN */\r
+ }\r
+ range = range->nextRange;\r
+ }\r
+ \r
+ allocator->allocatorRootEntry = treeRootEntry;\r
+ return(0); /* TODO: FIX THIS RETURN */\r
+}\r
+\r
+/* Called when an allocate request is made but the base is unspecified. RM must preallocate\r
+ * resources which then must be checked against the RM policy for the instance. If the\r
+ * policy does not agree another resource(s) must be preallocated and tested against the \r
+ * policy. Policy will provide initialize the preallocate with the base that it allows\r
+ * for the rm instance for the specified resource. */\r
+int32_t Rm_treePreAllocate(Rm_Inst *rmInst, Rm_Allocator *allocator, int32_t resourcePolicy,\r
+ Rm_AllocatorOpInfo *opInfo)\r
+{\r
+ Rm_ResourceNode findNode;\r
+ Rm_ResourceNode *matchingNode = NULL;\r
+ uint32_t matchingEnd;\r
+ uint32_t rangeIndex;\r
+ bool resourceFound = FALSE;\r
+ Rm_PolicyCheckType policyCheckType;\r
+ Rm_PolicyCheckCfg policyCheckCfg;\r
+ bool nodePassesPolicy;\r
+ int32_t retVal = RM_SERVICE_PROCESSING; \r
+\r
+ opInfo->resourceInfo->base = Rm_policyGetResourceBase(rmInst->policy, opInfo->serviceSrcInstNode, \r
+ resourcePolicy, opInfo->allocType, \r
+ &retVal);\r
+ if (retVal != RM_SERVICE_PROCESSING) {\r
+ return (retVal);\r
+ }\r
+\r
+ if (opInfo->resourceInfo->alignment == RM_RESOURCE_ALIGNMENT_UNSPECIFIED) { \r
+ /* Get alignment from policy */\r
+ opInfo->resourceInfo->alignment = Rm_policyGetResourceAlignment(rmInst->policy, resourcePolicy);\r
+ }\r
+ \r
+ if (opInfo->resourceInfo->alignment == 0) {\r
+ opInfo->resourceInfo->alignment = 1;\r
+ } \r
+\r
+ memset((void *)&findNode, 0, sizeof(Rm_ResourceNode));\r
+ findNode.base = opInfo->resourceInfo->base;\r
+ findNode.length = opInfo->resourceInfo->length;\r
+\r
+ /* Configure policy checking structure */\r
+ memset((void *)&policyCheckCfg, 0, sizeof(Rm_PolicyCheckCfg));\r
+ if (RM_policy_GET_PERM(opInfo->allocType, RM_POLICY_PERM_INIT_SHIFT)) {\r
+ policyCheckType = Rm_policyCheck_INIT;\r
+ }\r
+ else if (RM_policy_GET_PERM(opInfo->allocType, RM_POLICY_PERM_USE_SHIFT)) {\r
+ policyCheckType = Rm_policyCheck_USE;\r
+ }\r
+ policyCheckCfg.policyDtb = rmInst->policy;\r
+ policyCheckCfg.resourceOffset = resourcePolicy;\r
+ \r
+ do {\r
+ matchingNode = RB_FIND(_Rm_ResourceTree, allocator->allocatorRootEntry, &findNode);\r
+ \r
+ if (matchingNode) {\r
+ nodePassesPolicy = FALSE;\r
+ policyCheckCfg.type = policyCheckType;\r
+ policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;\r
+ policyCheckCfg.resourceBase = findNode.base;\r
+ policyCheckCfg.resourceLength = findNode.length;\r
+ nodePassesPolicy = Rm_policyCheckPrivilege(&policyCheckCfg, &retVal); \r
+ \r
+ if (nodePassesPolicy && (matchingNode->allocationCount > 0)) {\r
+ /* Check exclusive privileges of instance requesting resource. Requesting\r
+ * instance with exclusive privileges can't reserve resource if already owned*/\r
+ policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;\r
+ policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;\r
+ nodePassesPolicy = !Rm_policyCheckPrivilege(&policyCheckCfg, &retVal);\r
+ }\r
+ \r
+ if (nodePassesPolicy && (matchingNode->allocationCount == 1)) {\r
+ /* Check exclusive privileges of instance that currently owns resource */\r
+ policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;\r
+ policyCheckCfg.validInstNode = matchingNode->allocatedTo->instNameNode;\r
+ nodePassesPolicy = !Rm_policyCheckPrivilege(&policyCheckCfg, &retVal);\r
+ }\r
+\r
+ if (retVal != RM_SERVICE_PROCESSING) {\r
+ break;\r
+ }\r
+\r
+ if (nodePassesPolicy) {\r
+ matchingEnd = matchingNode->base + matchingNode->length - 1;\r
+ /* Initialize indexer to be first resource value that alignment */\r
+ rangeIndex = findNode.base;\r
+ if (rangeIndex % opInfo->resourceInfo->alignment) {\r
+ rangeIndex += (opInfo->resourceInfo->alignment -\r
+ (rangeIndex % opInfo->resourceInfo->alignment));\r
+ }\r
+ \r
+ if ((rangeIndex + opInfo->resourceInfo->length - 1) <= matchingEnd) {\r
+ /* Block of unallocated resources within matchingNode that satisfies\r
+ * allocate requirements */\r
+ opInfo->resourceInfo->base = rangeIndex;\r
+ resourceFound = TRUE;\r
+ } \r
+ }\r
+ \r
+ if (!resourceFound) {\r
+ /* Check next resource node for available resources */\r
+ findNode.base = matchingNode->base + matchingNode->length;\r
+ }\r
+ }\r
+ else {\r
+ retVal = RM_SERVICE_DENIED_RESOURCE_ALLOCATION_REQUIREMENTS_COULD_NOT_BE_SATISFIED;\r
+ }\r
+ } while ((!resourceFound) && \r
+ (retVal != RM_SERVICE_DENIED_RESOURCE_ALLOCATION_REQUIREMENTS_COULD_NOT_BE_SATISFIED));\r
+\r
+ return(retVal); \r
+}\r
+\r
+int32_t Rm_treeAllocate(Rm_Inst *rmInst, Rm_Allocator *allocator, int32_t resourcePolicy,\r
+ Rm_AllocatorOpInfo *opInfo)\r
+{\r
+ Rm_ResourceNode findNode;\r
+ Rm_ResourceNode *matchingNode = NULL;\r
+ Rm_ResourceNode *leftNode = NULL;\r
+ Rm_ResourceNode *rightNode = NULL;\r
+ Rm_PolicyCheckType policyCheckType; \r
+ Rm_PolicyCheckCfg policyCheckCfg;\r
+ bool allocPassesPolicy;\r
+ bool combineLeft = FALSE;\r
+ bool combineRight = FALSE; \r
+ uint32_t findEnd;\r
+ uint32_t matchingEnd; \r
+ int32_t retVal = RM_SERVICE_PROCESSING;\r
+\r
+ memset((void *)&findNode, 0, sizeof(Rm_ResourceNode));\r
+ findNode.base = opInfo->resourceInfo->base;\r
+ findNode.length = opInfo->resourceInfo->length;\r
+ matchingNode = RB_FIND(_Rm_ResourceTree, allocator->allocatorRootEntry, &findNode);\r
+\r
+ /* Prepare privilege checks */\r
+ memset((void *)&policyCheckCfg, 0, sizeof(Rm_PolicyCheckCfg));\r
+ if (RM_policy_GET_PERM(opInfo->allocType, RM_POLICY_PERM_INIT_SHIFT)) {\r
+ policyCheckType = Rm_policyCheck_INIT;\r
+ }\r
+ else if (RM_policy_GET_PERM(opInfo->allocType, RM_POLICY_PERM_USE_SHIFT)) {\r
+ policyCheckType = Rm_policyCheck_USE;\r
+ }\r
+\r
+ if (matchingNode) {\r
+ findEnd = findNode.base + findNode.length - 1;\r
+ matchingEnd = matchingNode->base + matchingNode->length - 1;\r
+ \r
+ if ((findNode.base >= matchingNode->base) && (findEnd <= matchingEnd)) {\r
+ if (opInfo->serviceSrcInstNode == Rm_policyGetLinuxInstNode(rmInst->validInstances)) {\r
+ /* Bypass policy checks since Linux Kernel has full privileges */\r
+ allocPassesPolicy = TRUE;\r
+ }\r
+ else {\r
+ allocPassesPolicy = FALSE;\r
+ policyCheckCfg.policyDtb = rmInst->policy;\r
+ policyCheckCfg.resourceOffset = resourcePolicy; \r
+ policyCheckCfg.type = policyCheckType;\r
+ policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;\r
+ policyCheckCfg.resourceBase = findNode.base;\r
+ policyCheckCfg.resourceLength = findNode.length;\r
+ allocPassesPolicy = Rm_policyCheckPrivilege(&policyCheckCfg, &retVal);\r
+ if (!allocPassesPolicy) {\r
+ retVal = RM_SERVICE_DENIED_INIT_USE_PERMISSION_DENIED;\r
+ }\r
+ \r
+ if (allocPassesPolicy && (matchingNode->allocationCount > 0)) {\r
+ /* Check exclusive privileges of instance requesting resource. Requesting\r
+ * instance with exclusive privileges can't reserve resource if already owned*/\r
+ policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;\r
+ policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;\r
+ allocPassesPolicy = !Rm_policyCheckPrivilege(&policyCheckCfg, &retVal);\r
+ if (!allocPassesPolicy) {\r
+ retVal = RM_SERVICE_DENIED_REQUESTER_HAS_EXCLUSIVE_PRIV_BUT_RESOURCE_ALLOCATED;\r
+ }\r
+ }\r
+ if (allocPassesPolicy && (matchingNode->allocationCount == 1)) {\r
+ /* Check exclusive privileges of instance that currently owns resource */\r
+ policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;\r
+ policyCheckCfg.validInstNode = matchingNode->allocatedTo->instNameNode;\r
+ allocPassesPolicy = !Rm_policyCheckPrivilege(&policyCheckCfg, &retVal);\r
+ if (!allocPassesPolicy) {\r
+ retVal = RM_SERVICE_DENIED_RESOURCE_ALLOCATED_TO_INSTANCE_WITH_EXCLUSIVE_PRIV;\r
+ } \r
+ } \r
+ }\r
+ \r
+ if (allocPassesPolicy) { \r
+ if ((findNode.base == matchingNode->base) && (findEnd == matchingEnd)) {\r
+ /* findNode range matches matchingNode range\r
+ *\r
+ * |<--left node-->||<--matched node-->||<--right node-->| => existing node\r
+ * |<--alloc request-->| => requested resources\r
+ */ \r
+ leftNode = RB_PREV(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+ rightNode = RB_NEXT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+ RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+ Rm_addAllocatedTo(matchingNode, opInfo->serviceSrcInstNode);\r
+\r
+ if (leftNode && Rm_compareResourceNodeAllocations(leftNode, matchingNode)) {\r
+ RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
+ combineLeft = TRUE;\r
+ }\r
+ if (rightNode && Rm_compareResourceNodeAllocations(rightNode, matchingNode)) {\r
+ RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
+ combineRight = TRUE;\r
+ }\r
+\r
+ if (combineLeft && combineRight) {\r
+ /* Combine all three nodes into matchingNode */\r
+ matchingNode->base = leftNode->base;\r
+ matchingNode->length = leftNode->length + matchingNode->length + rightNode->length;\r
+\r
+ Rm_clearAllocatedTo(leftNode);\r
+ Rm_freeResourceNode(leftNode);\r
+ Rm_clearAllocatedTo(rightNode);\r
+ Rm_freeResourceNode(rightNode); \r
+ }\r
+ else if (combineLeft) {\r
+ /* Combine left and matching nodes. Reinsert right. */\r
+ matchingNode->base = leftNode->base;\r
+ matchingNode->length += leftNode->length;\r
+\r
+ Rm_clearAllocatedTo(leftNode);\r
+ Rm_freeResourceNode(leftNode);\r
+ RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode); \r
+ }\r
+ else if (combineRight) {\r
+ /* Combine right and matching nodes. Reinsert left. */\r
+ matchingNode->length += rightNode->length;\r
+\r
+ Rm_clearAllocatedTo(rightNode);\r
+ Rm_freeResourceNode(rightNode);\r
+ RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
+ }\r
+ else {\r
+ /* No combine. */\r
+ RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
+ RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
+ }\r
+\r
+ /* Always reinsert matchingNode */ \r
+ RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode); \r
+ } \r
+ else if ((findNode.base > matchingNode->base) && (findEnd < matchingEnd)) {\r
+ /* findNode range is subset of matchingNode range and neither boundary is\r
+ * equivalent.\r
+ *\r
+ * |<----------matched node---------->|\r
+ * |<---alloc request--->|\r
+ */ \r
+ RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+ leftNode = Rm_newResourceNode(matchingNode->base, findNode.base - matchingNode->base);\r
+ Rm_copyAllocatedTo(leftNode, matchingNode);\r
+ rightNode = Rm_newResourceNode(findNode.base + findNode.length, matchingEnd - findEnd);\r
+ Rm_copyAllocatedTo(rightNode, matchingNode);\r
+\r
+ matchingNode->base = findNode.base; \r
+ matchingNode->length = findNode.length;\r
+ Rm_addAllocatedTo(matchingNode, opInfo->serviceSrcInstNode);\r
+\r
+ /* Insert all the nodes */\r
+ RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+ RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
+ RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
+ } \r
+ else { \r
+ if (findNode.base == matchingNode->base) {\r
+ /* findNode base and matchingNode base are equivalent. May be combine\r
+ * possibilities to the left\r
+ *\r
+ * |<---left node (alloc'd)--->||<----------matched node---------->|\r
+ * |<---findNode (alloc req)--->|\r
+ */ \r
+ leftNode = RB_PREV(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+ RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+ /* Add allocating instance to allocatedTo list for compare with leftNode */\r
+ Rm_addAllocatedTo(matchingNode, opInfo->serviceSrcInstNode);\r
+ \r
+ if (leftNode && Rm_compareResourceNodeAllocations(leftNode, matchingNode)) {\r
+ RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
+ /* Combine leftNode and findNode */\r
+ leftNode->length += findNode.length;\r
+ }\r
+ else {\r
+ leftNode = Rm_newResourceNode(findNode.base, findNode.length);\r
+ Rm_copyAllocatedTo(leftNode, matchingNode);\r
+ }\r
+\r
+ /* Account for leftNode in matchingNode */\r
+ matchingNode->base = findNode.base + findNode.length;\r
+ matchingNode->length = matchingEnd - findEnd; \r
+\r
+ RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
+ }\r
+ else if (findEnd == matchingEnd) {\r
+ /* findNode end and matchingNode end are equivalent. May be combine\r
+ * possibilities to the right\r
+ *\r
+ * |<----------matched node---------->||<---right node (alloc'd)--->|\r
+ * |<---findNode (alloc req)--->| \r
+ */ \r
+ rightNode = RB_NEXT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+ RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+ /* Add allocating instance to allocatedTo list for compare with rightNode */\r
+ Rm_addAllocatedTo(matchingNode, opInfo->serviceSrcInstNode);\r
+ \r
+ if (rightNode && Rm_compareResourceNodeAllocations(rightNode, matchingNode)) {\r
+ RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
+ /* Combine rightNode and findNode */\r
+ rightNode->base = findNode.base;\r
+ rightNode->length += findNode.length;\r
+ }\r
+ else {\r
+ rightNode = Rm_newResourceNode(findNode.base, findNode.length);\r
+ Rm_copyAllocatedTo(rightNode, matchingNode);\r
+ }\r
+\r
+ /* Account for rightNode in matchingNode */\r
+ matchingNode->length -= findNode.length; \r
+\r
+ RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
+ }\r
+ /* Remove allocating instance from leftover matchingNode */\r
+ Rm_deleteAllocatedTo(matchingNode, opInfo->serviceSrcInstNode);\r
+ RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+ }\r
+ retVal = RM_SERVICE_APPROVED_AND_COMPLETED;\r
+ }\r
+ }\r
+ else {\r
+ retVal = RM_SERVICE_DENIED_RESOURCE_ALREADY_ALLOCATED;\r
+ }\r
+ }\r
+ else {\r
+ retVal = RM_SERVICE_DENIED_RESOURCE_VALUE_RANGE_DOES_NOT_EXIST;\r
+ }\r
+\r
+ return(retVal); \r
+}\r
+\r
+int32_t Rm_treeFree(Rm_Inst *rmInst, Rm_Allocator *allocator, int32_t resourcePolicy, Rm_AllocatorOpInfo *opInfo)\r
+{\r
+ Rm_ResourceNode findNode;\r
+ Rm_ResourceNode *matchingNode = NULL;\r
+ Rm_ResourceNode *leftNode = NULL;\r
+ Rm_ResourceNode *rightNode = NULL;\r
+ bool combineLeft = FALSE;\r
+ bool combineRight = FALSE;\r
+ uint32_t findEnd;\r
+ uint32_t matchingEnd;\r
+ int32_t retVal;\r
+\r
+ memset((void *)&findNode, 0, sizeof(Rm_ResourceNode));\r
+ findNode.base = opInfo->resourceInfo->base;\r
+ findNode.length = opInfo->resourceInfo->length;\r
+ matchingNode = RB_FIND(_Rm_ResourceTree, allocator->allocatorRootEntry, &findNode);\r
+\r
+ if (matchingNode) {\r
+ findEnd = findNode.base + findNode.length - 1;\r
+ matchingEnd = matchingNode->base + matchingNode->length - 1;\r
+ \r
+ if ((findNode.base >= matchingNode->base) && (findEnd <= matchingEnd)) { \r
+ if (matchingNode->allocationCount) {\r
+ if (Rm_isAllocatedTo(matchingNode, opInfo->serviceSrcInstNode)) {\r
+ if ((findNode.base == matchingNode->base) && (findEnd == matchingEnd))\r
+ {\r
+ /* Case 1: Free range equals allocated matched node exactly. Attempt to combine \r
+ * freed node with nodes to left and right.\r
+ *\r
+ * |<--left node-->||<---matched node--->||<--right node-->|\r
+ * |<---free request--->|\r
+ */ \r
+ leftNode = RB_PREV(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+ rightNode = RB_NEXT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+ RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+ Rm_deleteAllocatedTo(matchingNode, opInfo->serviceSrcInstNode);\r
+\r
+ if (leftNode && Rm_compareResourceNodeAllocations(leftNode, matchingNode)) {\r
+ RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
+ combineLeft = TRUE;\r
+ }\r
+ if (rightNode && Rm_compareResourceNodeAllocations(rightNode, matchingNode)) {\r
+ RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
+ combineRight = TRUE;\r
+ }\r
+\r
+ if (combineLeft && combineRight) {\r
+ /* Combine all three nodes into matchingNode */\r
+ matchingNode->base = leftNode->base;\r
+ matchingNode->length = leftNode->length + matchingNode->length + rightNode->length;\r
+\r
+ Rm_clearAllocatedTo(leftNode);\r
+ Rm_freeResourceNode(leftNode);\r
+ Rm_clearAllocatedTo(rightNode);\r
+ Rm_freeResourceNode(rightNode); \r
+ }\r
+ else if (combineLeft) {\r
+ /* Combine left and matching nodes. Reinsert right. */\r
+ matchingNode->base = leftNode->base;\r
+ matchingNode->length += leftNode->length;\r
+\r
+ Rm_clearAllocatedTo(leftNode);\r
+ Rm_freeResourceNode(leftNode);\r
+ RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode); \r
+ }\r
+ else if (combineRight) {\r
+ /* Combine right and matching nodes. Reinsert left. */\r
+ matchingNode->length += rightNode->length;\r
+\r
+ Rm_clearAllocatedTo(rightNode);\r
+ Rm_freeResourceNode(rightNode);\r
+ RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
+ }\r
+ else {\r
+ /* No combine. */\r
+ RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
+ RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
+ }\r
+\r
+ /* Always reinsert matchingNode */\r
+ RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode); \r
+ }\r
+ else if ((findNode.base > matchingNode->base) && (findEnd < matchingEnd)) {\r
+ /* Case 2: Free range is less than range in matched node. Split\r
+ * matched node into three nodes.\r
+ *\r
+ * |<----------matched node---------->|\r
+ * |<---free request--->|\r
+ *\r
+ * Remove instance from AllocatedTo list then add it back in for side nodes for\r
+ * proper accounting of allocations in validInstance list\r
+ */ \r
+ RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+ Rm_deleteAllocatedTo(matchingNode, opInfo->serviceSrcInstNode);\r
+ \r
+ leftNode = Rm_newResourceNode(matchingNode->base, findNode.base - matchingNode->base);\r
+ Rm_copyAllocatedTo(leftNode, matchingNode);\r
+ Rm_addAllocatedTo(leftNode, opInfo->serviceSrcInstNode);\r
+ RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
+ \r
+ rightNode = Rm_newResourceNode(findNode.base + findNode.length, matchingEnd - findEnd);\r
+ Rm_copyAllocatedTo(rightNode, matchingNode);\r
+ Rm_addAllocatedTo(rightNode, opInfo->serviceSrcInstNode);\r
+ RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
+\r
+ matchingNode->base = findNode.base; \r
+ matchingNode->length = findNode.length;\r
+ RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+ }\r
+ else { \r
+ if (findNode.base == matchingNode->base) {\r
+ /* Case 3: Free range is on left boundary of matched node. Try to \r
+ * combine free range with left node.\r
+ *\r
+ * |<---left node (free)--->||<----------matched node---------->|\r
+ * |<---findNode (free req)--->|\r
+ */ \r
+\r
+ leftNode = RB_PREV(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+ RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+ /* Remove freeing instance from allocatedTo list for compare with leftNode */\r
+ Rm_deleteAllocatedTo(matchingNode, opInfo->serviceSrcInstNode);\r
+ \r
+ if (leftNode && Rm_compareResourceNodeAllocations(leftNode, matchingNode)) {\r
+ RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
+ /* Combine leftNode and findNode */\r
+ leftNode->length += findNode.length;\r
+ }\r
+ else {\r
+ leftNode = Rm_newResourceNode(findNode.base, findNode.length);\r
+ Rm_copyAllocatedTo(leftNode, matchingNode);\r
+ }\r
+\r
+ /* Remove leftNode range from matchingNode */\r
+ matchingNode->base = findNode.base + findNode.length;\r
+ matchingNode->length = matchingEnd - findEnd; \r
+ RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
+ }\r
+ else if (findEnd == matchingEnd) {\r
+ /* Case 4: Free range is on right boundary of matched node. Try to \r
+ * combine free range with right node.\r
+ *\r
+ * |<----------matched node---------->||<---right node (free)--->|\r
+ * |<---findNode (free req)--->|\r
+ */ \r
+ \r
+ rightNode = RB_NEXT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+ RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode); \r
+ /* Remove freeing instance from allocatedTo list for compare with rightNode */\r
+ Rm_deleteAllocatedTo(matchingNode, opInfo->serviceSrcInstNode);\r
+ \r
+ if (rightNode && Rm_compareResourceNodeAllocations(rightNode, matchingNode)) {\r
+ RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
+ /* Combine rightNode and findNode */\r
+ rightNode->base = findNode.base;\r
+ rightNode->length += findNode.length;\r
+ }\r
+ else {\r
+ rightNode = Rm_newResourceNode(findNode.base, findNode.length);\r
+ Rm_copyAllocatedTo(rightNode, matchingNode);\r
+ }\r
+\r
+ /* Remove rightNode range from matchingNode */\r
+ matchingNode->length -= findNode.length; \r
+ RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
+ }\r
+\r
+ /* Add freeing instance back into matchingNode allocations */\r
+ Rm_addAllocatedTo(matchingNode, opInfo->serviceSrcInstNode);\r
+ RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+ }\r
+\r
+ retVal = RM_SERVICE_APPROVED_AND_COMPLETED;\r
+ }\r
+ else {\r
+ retVal = RM_SERVICE_DENIED_RESOURCE_NOT_ALLOCATED_TO_INSTANCE_REQUESTING_THE_SERVICE;\r
+ }\r
+ }\r
+ else {\r
+ retVal = RM_SERVICE_DENIED_RESOURCE_ALREADY_FREE;\r
+ }\r
+ }\r
+ else {\r
+ retVal = RM_SERVICE_DENIED_INVALID_RESOURCE_RANGE;\r
+ }\r
+ }\r
+ else {\r
+ retVal = RM_SERVICE_DENIED_RESOURCE_VALUE_RANGE_DOES_NOT_EXIST;\r
+ }\r
+ return(retVal); \r
+}\r
+\r
+int32_t Rm_allocatorOperation(Rm_Inst *rmInst, Rm_AllocatorOpInfo *opInfo)\r
+{\r
+ Rm_Allocator *allocator = NULL;\r
+ int32_t resourceOffsetInPolicy;\r
+ int32_t retVal;\r
+ void *key;\r
+\r
+ /* Lock access to the RM instance's transaction queue */\r
+ key = Rm_osalMtCsEnter();\r
+ \r
+ resourceOffsetInPolicy = Rm_policyGetResourceOffset(rmInst->policy, opInfo->resourceInfo->name);\r
+ allocator = Rm_allocatorFind(rmInst->allocators, opInfo->resourceInfo->name);\r
+ \r
+ if ((resourceOffsetInPolicy > 0) && allocator) {\r
+ if (opInfo->operation == Rm_allocatorOp_PRE_ALLOCATE) {\r
+ retVal = Rm_treePreAllocate(rmInst, allocator, resourceOffsetInPolicy, opInfo);\r
+ } \r
+ else if (opInfo->operation == Rm_allocatorOp_ALLOCATE) {\r
+ retVal = Rm_treeAllocate(rmInst, allocator, resourceOffsetInPolicy, opInfo);\r
+ }\r
+ else if (opInfo->operation == Rm_allocatorOp_FREE) {\r
+ retVal = Rm_treeFree(rmInst, allocator, resourceOffsetInPolicy, opInfo);\r
+ } \r
+ }\r
+ else {\r
+ /* Resource could not be found in policy and/or allocator */\r
+ retVal = RM_SERVICE_DENIED_RESOURCE_DOES_NOT_EXIST;\r
+ }\r
+\r
+ Rm_osalMtCsExit(key);\r
+ return(retVal);\r
+}\r
\r
- /* Free the memory associated with the transaction. */\r
- Rm_osalFree((void *)transaction, sizeof(Rm_Transaction), false);\r
+void Rm_allocationHandler (Rm_Inst *rmInst, Rm_Transaction *transaction, void *validInstNode,\r
+ uint32_t allocType)\r
+{\r
+ Rm_AllocatorOpInfo opInfo;\r
+ Rm_NameServerObjCfg nameServerObjCfg;\r
+ int32_t retVal = transaction->state;\r
+\r
+ memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));\r
+ \r
+ if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {\r
+ /* TEMP: For now forward all allocations to the RM Server */\r
+ Rm_transactionForwarder(rmInst, transaction);\r
+ \r
}\r
+ else if (rmInst->instType == Rm_instType_SERVER) {\r
+ opInfo.resourceInfo = &transaction->resourceInfo;\r
+ opInfo.serviceSrcInstNode = validInstNode;\r
+ opInfo.allocType = allocType;\r
+\r
+ if (strlen(transaction->resourceInfo.nameServerName) > 0) {\r
+ if (transaction->resourceInfo.base != 0) {\r
+ /* Both NameServer name and static value cannot be specified for the request */\r
+ retVal = RM_SERVICE_ERROR_NAMESERVER_NAME_AND_RESOURCE_RANGE_BOTH_DEFINED;\r
+ }\r
+ else {\r
+ memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));\r
+ nameServerObjCfg.nameServerTree = rmInst->nameServer;\r
+ nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;\r
+ if ((retVal = Rm_nameServerFindObject(&nameServerObjCfg)) == RM_SERVICE_PROCESSING) {\r
+ strcpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName);\r
+ transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;\r
+ transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;\r
+ } \r
+ }\r
+ }\r
\r
- Rm_osalLocalCsExit(key);\r
- return (RM_SERVICE_ACTION_OKAY);\r
+ if (retVal == RM_SERVICE_PROCESSING) { \r
+ if (transaction->resourceInfo.base == RM_RESOURCE_BASE_UNSPECIFIED) {\r
+ opInfo.operation = Rm_allocatorOp_PRE_ALLOCATE;\r
+ retVal = Rm_allocatorOperation(rmInst, &opInfo);\r
+ }\r
+ \r
+ if (retVal == RM_SERVICE_PROCESSING) {\r
+ opInfo.operation = Rm_allocatorOp_ALLOCATE;\r
+ retVal = Rm_allocatorOperation(rmInst, &opInfo);\r
+ } \r
+ }\r
+ \r
+ transaction->state = retVal;\r
+\r
+ if (strcmp(transaction->serviceSrcInstName, rmInst->instName)) {\r
+ /* Source of allocation was not the server instance, provide the transaction\r
+ * to the transaction responder */\r
+ Rm_transactionResponder(rmInst, transaction);\r
+ }\r
+ /* Otherwise let the return stack return the transaction to the serviceHandler */ \r
+ } \r
+}\r
+\r
+void Rm_freeHandler (Rm_Inst *rmInst, Rm_Transaction *transaction, void *validInstNode)\r
+{\r
+ Rm_AllocatorOpInfo opInfo; \r
+ Rm_NameServerObjCfg nameServerObjCfg; \r
+ int32_t retVal = transaction->state;\r
+\r
+ memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));\r
+ \r
+ if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {\r
+ /* TEMP: Forward all free requests to the Server */\r
+ Rm_transactionForwarder(rmInst, transaction); \r
+ }\r
+ else if (rmInst->instType == Rm_instType_SERVER) {\r
+ opInfo.resourceInfo = &transaction->resourceInfo;\r
+ opInfo.serviceSrcInstNode = validInstNode;\r
+\r
+ if (strlen(transaction->resourceInfo.nameServerName) > 0) {\r
+ if (transaction->resourceInfo.base != 0) {\r
+ /* Both a name and a value cannot be specified for the request */\r
+ retVal = RM_SERVICE_ERROR_NAMESERVER_NAME_AND_RESOURCE_RANGE_BOTH_DEFINED;\r
+ }\r
+ else {\r
+ memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));\r
+ nameServerObjCfg.nameServerTree = rmInst->nameServer;\r
+ nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;\r
+ if ((retVal = Rm_nameServerFindObject(&nameServerObjCfg)) == RM_SERVICE_PROCESSING) {\r
+ strcpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName);\r
+ transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;\r
+ transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;\r
+ } \r
+ }\r
+\r
+ }\r
+ \r
+ if(retVal == RM_SERVICE_PROCESSING) { \r
+ opInfo.operation = Rm_allocatorOp_FREE;\r
+ retVal = Rm_allocatorOperation(rmInst, &opInfo);\r
+ } \r
+\r
+ transaction->state = retVal;\r
+\r
+ if (strcmp(transaction->serviceSrcInstName, rmInst->instName)) {\r
+ /* Source of allocation was not the server instance, provide the transaction\r
+ * to the transaction responder */\r
+ Rm_transactionResponder(rmInst, transaction);\r
+ }\r
+ /* Otherwise let the return stack return the transaction to the serviceHandler */ \r
+ } \r
+}\r
+\r
+/* This function is executed when a RM instance receives a response to one of its requests\r
+ * and the information in the request must be provided to the original requesting component */\r
+void Rm_serviceResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
+{\r
+ Rm_ServiceRespInfo serviceResponse;\r
+\r
+ /* The responseTransaction will contain the resultant state details of\r
+ * the requestTransaction's service request */\r
+ serviceResponse.serviceState = transaction->state;\r
+ /* Pass back the ID that was provided to the component when it requested\r
+ * the service */\r
+ serviceResponse.serviceId = transaction->localId;\r
+\r
+ /* Service was approved and service was an allocate request. The resource\r
+ * data is passed back to the component */\r
+ if ((serviceResponse.serviceState == RM_SERVICE_APPROVED_AND_COMPLETED) &&\r
+ ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||\r
+ (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) ||\r
+ (transaction->type == Rm_service_RESOURCE_GET_BY_NAME)))\r
+ {\r
+ strcpy(serviceResponse.resourceName, transaction->resourceInfo.name);\r
+ serviceResponse.resourceBase = transaction->resourceInfo.base;\r
+ serviceResponse.resourceLength = transaction->resourceInfo.length;\r
+ }\r
+\r
+ /* Issue the callback to the requesting component with the response information */\r
+ transaction->callback.serviceCallback(&serviceResponse);\r
+\r
+ /* Delete the transaction from the transaction queue */\r
+ Rm_transactionQueueDelete(rmInst, transaction->localId);\r
+ return;\r
}\r
\r
/* Function used to send RM response transactions to lower level agents */\r
-void Rm_transactionResponder (Rm_Inst *rmInst, Rm_Transaction *transaction,\r
- Rm_TransactionReceipt *receipt)\r
+void Rm_transactionResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
{\r
Rm_TransportNode *dstTransportNode = NULL;\r
Rm_Packet *rmPkt = NULL;\r
\r
/* Find the transport for the RM instance that sent the request. */\r
- dstTransportNode = Rm_transportNodeFindRemoteName(rmInst, transaction->sourceInstName);\r
+ dstTransportNode = Rm_transportNodeFindRemoteName(rmInst, transaction->pktSrcInstName);\r
\r
/* Create a RM packet using the service information */\r
- switch (transaction->type)\r
- {\r
- case Rm_service_RESOURCE_ALLOCATE:\r
- case Rm_service_RESOURCE_BLOCK_ALLOCATE:\r
- case Rm_service_RESOURCE_ALLOCATE_BY_NAME:\r
+ switch (transaction->type) {\r
+ case Rm_service_RESOURCE_ALLOCATE_INIT:\r
+ case Rm_service_RESOURCE_ALLOCATE_USE:\r
case Rm_service_RESOURCE_FREE:\r
- case Rm_service_RESOURCE_BLOCK_FREE:\r
- case Rm_service_RESOURCE_FREE_BY_NAME:\r
+ case Rm_service_RESOURCE_GET_BY_NAME:\r
rmPkt = Rm_transportCreateResourceResponsePkt(rmInst, dstTransportNode, \r
- transaction, receipt);\r
+ transaction);\r
break;\r
case Rm_service_RESOURCE_MAP_TO_NAME:\r
case Rm_service_RESOURCE_UNMAP_NAME:\r
rmPkt = Rm_transportCreateNsResponsePkt(rmInst, dstTransportNode,\r
- transaction, receipt);\r
+ transaction);\r
break;\r
default:\r
/* Invalid service type. Flag the error and return */\r
- receipt->serviceResult = RM_SERVICE_ERROR_INVALID_SERVICE_TYPE;\r
+ transaction->state = RM_SERVICE_ERROR_INVALID_SERVICE_TYPE;\r
break;\r
}\r
\r
- if (receipt->serviceResult <= RM_SERVICE_ERROR_BASE)\r
- {\r
+ if (transaction->state <= RM_SERVICE_ERROR_BASE) {\r
/* Delete the transaction and return immediately because an error occurred \r
* allocating the packet */\r
- Rm_transactionQueueDelete(rmInst, transaction->id);\r
+ Rm_transactionQueueDelete(rmInst, transaction->localId);\r
return;\r
}\r
\r
/* Send the RM packet to the application transport */\r
- if (rmInst->transport.rmSend((Rm_TransportHandle) dstTransportNode, rmPkt))\r
- {\r
- /* Non-NULL value returned by transport send. An error occurred\r
+ if (rmInst->transport.rmSend((Rm_TransportHandle) dstTransportNode, rmPkt) < RM_TRANSPORT_SUCCESSFUL) {\r
+ /* Negative value returned by transport send. An error occurred\r
* in the transport while attempting to send the packet.*/\r
- receipt->serviceResult = RM_SERVICE_ERROR_TRANPSPORT_SEND_ERROR;\r
+ transaction->state = RM_SERVICE_ERROR_TRANPSPORT_SEND_ERROR;\r
/* Clean up the packet */\r
- if (rmInst->transport.rmFreePkt((Rm_TransportHandle) dstTransportNode, rmPkt))\r
- {\r
+ if (rmInst->transport.rmFreePkt((Rm_TransportHandle) dstTransportNode, rmPkt)) {\r
/* Non-NULL value returned by transport packet free. Flag the\r
* error */\r
- receipt->serviceResult = RM_SERVICE_ERROR_TRANSPORT_FREE_PKT_ERROR;\r
+ transaction->state = RM_SERVICE_ERROR_TRANSPORT_FREE_PKT_ERROR;\r
}\r
return;\r
}\r
\r
- /* Fill out the receipt information and delete the transaction */\r
- receipt->serviceResult = transaction->details;\r
- Rm_transactionQueueDelete(rmInst, transaction->id);\r
+ /* NEED TO DO SOMETHING IF GET AN ERROR IN THE transaction->state FIELD. CREATE\r
+ * NEW TRANSACTION WITH DATA FROM ORIGINAL? THEN TRY TO SEND FAILED REQUEST BACK\r
+ * TO REQUESTER??? KEEP RETRYING SEND OF RESPONSE??? */\r
+\r
+ /* Delete the transaction */\r
+ Rm_transactionQueueDelete(rmInst, transaction->localId);\r
}\r
\r
/* Function used to forward RM transactions to higher level agents */\r
-void Rm_transactionForwarder (Rm_Inst *rmInst, Rm_Transaction *transaction,\r
- Rm_TransactionReceipt *receipt)\r
+void Rm_transactionForwarder (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
{\r
Rm_TransportNode *dstTransportNode = NULL;\r
Rm_Packet *rmPkt = NULL;\r
\r
/* Make sure the RM instance has a transport registered with a higher level agent */\r
- if (rmInst->registeredWithDelegateOrServer == false)\r
- {\r
- receipt->serviceResult = RM_SERVICE_ERROR_NOT_REGISTERED_WITH_DEL_OR_SERVER;\r
+ if (rmInst->registeredWithDelegateOrServer == false) {\r
+ transaction->state = RM_SERVICE_ERROR_NOT_REGISTERED_WITH_DEL_OR_SERVER;\r
return;\r
}\r
\r
- /* Find the transport for the higher level agent. Check for a remote Client Delegate first.\r
- * If a connection does not exist check for a connection to a Server */\r
- dstTransportNode = Rm_transportNodeFindRemoteInstType(rmInst, Rm_instType_CLIENT_DELEGATE);\r
- if (dstTransportNode == NULL)\r
- {\r
+ /* Find the transport for the higher level agent. Check for a connection to a Client Delegate\r
+ * or a Server. Clients will be connected to either a Client Delegate or a Server. Client\r
+ * Delegates will be connected to a Server. */\r
+ if (rmInst->instType == Rm_instType_CLIENT) {\r
+ dstTransportNode = Rm_transportNodeFindRemoteInstType(rmInst, Rm_instType_CLIENT_DELEGATE);\r
+\r
+ if (!dstTransportNode) {\r
+ /* No Client Delegate connection found. Check for a Server connection */\r
+ dstTransportNode = Rm_transportNodeFindRemoteInstType(rmInst, Rm_instType_SERVER);\r
+ }\r
+ } \r
+ else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {\r
dstTransportNode = Rm_transportNodeFindRemoteInstType(rmInst, Rm_instType_SERVER);\r
}\r
\r
/* Create a RM packet using the service information */\r
- switch (transaction->type)\r
- {\r
- case Rm_service_RESOURCE_ALLOCATE:\r
- case Rm_service_RESOURCE_BLOCK_ALLOCATE:\r
- case Rm_service_RESOURCE_ALLOCATE_BY_NAME:\r
+ switch (transaction->type) {\r
+ case Rm_service_RESOURCE_ALLOCATE_INIT:\r
+ case Rm_service_RESOURCE_ALLOCATE_USE:\r
case Rm_service_RESOURCE_FREE:\r
- case Rm_service_RESOURCE_BLOCK_FREE:\r
- case Rm_service_RESOURCE_FREE_BY_NAME:\r
+ case Rm_service_RESOURCE_GET_BY_NAME:\r
rmPkt = Rm_transportCreateResourceReqPkt(rmInst, dstTransportNode, \r
- transaction, receipt);\r
+ transaction);\r
break;\r
case Rm_service_RESOURCE_MAP_TO_NAME:\r
case Rm_service_RESOURCE_UNMAP_NAME:\r
rmPkt = Rm_transportCreateNsRequestPkt(rmInst, dstTransportNode,\r
- transaction, receipt);\r
+ transaction);\r
break;\r
default:\r
/* Invalid service type. Flag the error and return */\r
- receipt->serviceResult = RM_SERVICE_ERROR_INVALID_SERVICE_TYPE;\r
+ transaction->state = RM_SERVICE_ERROR_INVALID_SERVICE_TYPE;\r
break;\r
}\r
\r
- if (receipt->serviceResult <= RM_SERVICE_ERROR_BASE)\r
- {\r
+ if (transaction->state <= RM_SERVICE_ERROR_BASE) {\r
/* Return immediately because an error occurred allocating the packet */\r
return;\r
}\r
\r
- /* Switch the queued transaction to the awaiting response state */\r
- transaction->state = Rm_transactionState_AWAITING_RESPONSE;\r
-\r
/* Send the RM packet to the application transport */\r
- if (rmInst->transport.rmSend((Rm_TransportHandle) dstTransportNode, rmPkt))\r
- {\r
- /* Non-NULL value returned by transport send. An error occurred\r
+ if (rmInst->transport.rmSend((Rm_TransportHandle) dstTransportNode, rmPkt) < RM_TRANSPORT_SUCCESSFUL) {\r
+ /* Negative value returned by transport send. An error occurred\r
* in the transport while attempting to send the packet.*/\r
- receipt->serviceResult = RM_SERVICE_ERROR_TRANPSPORT_SEND_ERROR;\r
+ transaction->state = RM_SERVICE_ERROR_TRANPSPORT_SEND_ERROR;\r
/* Clean up the packet */\r
- if (rmInst->transport.rmFreePkt((Rm_TransportHandle) dstTransportNode, rmPkt))\r
- {\r
+ if (rmInst->transport.rmFreePkt((Rm_TransportHandle) dstTransportNode, rmPkt)) {\r
/* Non-NULL value returned by transport packet free. Flag the\r
* error */\r
- receipt->serviceResult = RM_SERVICE_ERROR_TRANSPORT_FREE_PKT_ERROR;\r
+ transaction->state = RM_SERVICE_ERROR_TRANSPORT_FREE_PKT_ERROR;\r
}\r
return;\r
}\r
\r
- /* Inform requesting component that the service is being forwarded to a higher lever\r
- * RM agent for processing. The result of the service will be provided to the \r
- * component via the specified callback function */\r
- receipt->serviceResult = RM_SERVICE_PROCESSING;\r
- receipt->serviceId = transaction->id;\r
+ /* Transaction is not deleted because it is awaiting a response from the higher level\r
+ * RM instance */\r
+}\r
+\r
+void Rm_transactionProcessor (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
+{\r
+ void *validInstNode;\r
+ Rm_NameServerObjCfg nameServerObjCfg; \r
+ uint32_t allocType = 0;\r
+ \r
+ /* Handle auto-forwarded transactions. These transactions include:\r
+ * - All request transactions received on Clients are forwarded to the Client Delegate\r
+ * - NameServer requests received on the Client Delegate are forwarded to the Server */\r
+ if ((rmInst->instType == Rm_instType_CLIENT) ||\r
+ ((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&\r
+ ((transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) ||\r
+ (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) ||\r
+ (transaction->type == Rm_service_RESOURCE_UNMAP_NAME)))) {\r
+ \r
+ if (transaction->state != RM_SERVICE_PROCESSING) {\r
+ if (strcmp(transaction->serviceSrcInstName, rmInst->instName)) {\r
+ /* Transaction did not originate on this instance */\r
+ Rm_transactionResponder(rmInst, transaction);\r
+ }\r
+ else {\r
+ /* Transaction originated on this instance */\r
+ Rm_serviceResponder(rmInst, transaction);\r
+ }\r
+ }\r
+ else {\r
+ /* Forward new transaction */\r
+ Rm_transactionForwarder(rmInst, transaction);\r
+ }\r
+ }\r
+ else {\r
+ /* Validate service's originating instance name */\r
+ if (rmInst->instType == Rm_instType_SERVER) {\r
+ validInstNode = Rm_policyGetValidInstNode(rmInst->validInstances, transaction->serviceSrcInstName);\r
+ if (validInstNode == NULL) {\r
+ transaction->state = RM_SERVICE_DENIED_ORIGINATING_INSTANCE_NAME_NOT_VALID;\r
+\r
+ /* Send result via responder if transaction did not originate from this instance */\r
+ if (strcmp(transaction->serviceSrcInstName, rmInst->instName)) {\r
+ Rm_transactionResponder(rmInst, transaction);\r
+ }\r
+ }\r
+ }\r
+\r
+ switch (transaction->type) {\r
+ case Rm_service_RESOURCE_ALLOCATE_INIT:\r
+ case Rm_service_RESOURCE_ALLOCATE_USE:\r
+ case Rm_service_RESOURCE_FREE: \r
+ if (transaction->state != RM_SERVICE_PROCESSING) {\r
+ /* Transaction complete */\r
+ if (strcmp(transaction->serviceSrcInstName, rmInst->instName)) {\r
+ /* Transaction result not destined for this instance */\r
+ Rm_transactionResponder(rmInst, transaction);\r
+ }\r
+ else {\r
+ /* Transaction result destined for this instance */\r
+ Rm_serviceResponder(rmInst, transaction); \r
+ }\r
+ }\r
+ else {\r
+ /* Complete allocation/free request */\r
+ if (transaction->type == Rm_service_RESOURCE_FREE) {\r
+ Rm_freeHandler(rmInst, transaction, validInstNode);\r
+ }\r
+ else {\r
+ switch (transaction->type) {\r
+ case Rm_service_RESOURCE_ALLOCATE_INIT:\r
+ RM_policy_SET_PERM(allocType, RM_POLICY_PERM_INIT_SHIFT, 1);\r
+ break;\r
+ case Rm_service_RESOURCE_ALLOCATE_USE:\r
+ RM_policy_SET_PERM(allocType, RM_POLICY_PERM_USE_SHIFT, 1); \r
+ break;\r
+ }\r
+ Rm_allocationHandler(rmInst, transaction, validInstNode, allocType);\r
+ }\r
+ }\r
+ break;\r
+ case Rm_service_RESOURCE_MAP_TO_NAME:\r
+ case Rm_service_RESOURCE_GET_BY_NAME:\r
+ case Rm_service_RESOURCE_UNMAP_NAME: \r
+ /* NameServer resides on server */\r
+ memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));\r
+ nameServerObjCfg.nameServerTree = rmInst->nameServer;\r
+ nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;\r
+ if (rmInst->instType == Rm_instType_SERVER) {\r
+ if (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) {\r
+ nameServerObjCfg.nodeCfg.resourceName = transaction->resourceInfo.name;\r
+ nameServerObjCfg.nodeCfg.resourceBase= transaction->resourceInfo.base;\r
+ nameServerObjCfg.nodeCfg.resourceLength = transaction->resourceInfo.length;\r
+ transaction->state = Rm_nameServerAddObject(&nameServerObjCfg);\r
+ }\r
+ else if (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) {\r
+ if ((transaction->state = Rm_nameServerFindObject(&nameServerObjCfg)) ==\r
+ RM_SERVICE_PROCESSING) {\r
+ strcpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName);\r
+ transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;\r
+ transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;\r
+ transaction->state = RM_SERVICE_APPROVED_AND_COMPLETED;\r
+ } \r
+ }\r
+ else if (transaction->type == Rm_service_RESOURCE_UNMAP_NAME) {\r
+ transaction->state = Rm_nameServerDeleteObject(&nameServerObjCfg);\r
+ }\r
+\r
+ /* Send result via responder if transaction did not originate from this instance */\r
+ if (strcmp(transaction->serviceSrcInstName, rmInst->instName)) {\r
+ Rm_transactionResponder(rmInst, transaction);\r
+ }\r
+ }\r
+ else {\r
+ transaction->state = RM_SERVICE_ERROR_NAMESERVER_OBJECT_MOD_ON_INVALID_INSTANCE;\r
+ }\r
+ break;\r
+ }\r
+ }\r
+}\r
+\r
+int32_t Rm_reserveLinuxResource(Rm_Inst *rmInst, Rm_LinuxAlias *linuxAlias, \r
+ Rm_LinuxValueRange *linuxValues, Rm_AllocatorOpInfo *opInfo)\r
+{\r
+ int32_t retVal = RM_DTB_UTIL_RESULT_OKAY;\r
+ bool baseFound = FALSE;\r
+ bool lengthFound = FALSE;\r
+ uint32_t valueIndex = 0;\r
+\r
+ while ((linuxValues != NULL) && (!baseFound || !lengthFound)) {\r
+ if (linuxAlias->baseOffset == valueIndex) {\r
+ opInfo->resourceInfo->base = linuxValues->value;\r
+ baseFound = TRUE;\r
+\r
+ if (linuxAlias->lengthOffset == RM_DTB_LINUX_ALIAS_OFFSET_NOT_SET) {\r
+ opInfo->resourceInfo->length = 1;\r
+ lengthFound = TRUE;\r
+ }\r
+ }\r
+ else if (linuxAlias->lengthOffset == valueIndex) {\r
+ opInfo->resourceInfo->length = linuxValues->value;\r
+ lengthFound = TRUE;\r
+ }\r
+\r
+ linuxValues = (Rm_LinuxValueRange *)linuxValues->nextValue;\r
+ valueIndex++;\r
+ }\r
+\r
+ if (!baseFound || !lengthFound) {\r
+ retVal = -33; /* TODO: ERROR BASE OR LENGTH OFFSET IN LINUX DTB WAS INCORRECT */\r
+ }\r
+ else {\r
+ /* Allocate resource to Linux */\r
+ retVal = Rm_allocatorOperation(rmInst, opInfo);\r
+ }\r
+ return (retVal);\r
}\r
\r
-void Rm_transactionProcessor (Rm_Inst *rmInst, Rm_Transaction *transaction, \r
- Rm_TransactionReceipt *receipt)\r
+int32_t Rm_findAndReserveLinuxResource(Rm_Inst *rmInst, const char *resourceName, void *linuxDtb, \r
+ Rm_LinuxAlias *linuxAlias)\r
{\r
- Rm_Transaction *queuedTransaction = NULL;\r
+ Rm_AllocatorOpInfo opInfo;\r
+ Rm_ResourceInfo resourceInfo;\r
+ uint32_t pathOffset;\r
+ uint32_t pathSize;\r
+ char *spacePtr;\r
+ int32_t propOffset;\r
+ int32_t nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;\r
+ int32_t prevDepth = RM_DTB_UTIL_STARTING_DEPTH;\r
+ int32_t depth;\r
+ int32_t propertyLen;\r
+ const char *propertyName;\r
+ const void *propertyData; \r
+ Rm_LinuxValueRange *linuxValueRange;\r
+ int32_t retVal = RM_DTB_UTIL_RESULT_OKAY; \r
+\r
+ memset((void *) &opInfo, 0, sizeof(Rm_AllocatorOpInfo));\r
+ memset((void *) &resourceInfo, 0, sizeof(Rm_ResourceInfo));\r
+\r
+ strcpy(resourceInfo.name, resourceName);\r
+ opInfo.serviceSrcInstNode = Rm_policyGetLinuxInstNode(rmInst->validInstances);\r
+ opInfo.operation = Rm_allocatorOp_ALLOCATE;\r
+ opInfo.resourceInfo = &resourceInfo; \r
+\r
+ while(linuxAlias != NULL) {\r
+ /* Reset parsing variables */\r
+ pathOffset = 0;\r
+ pathSize = strlen(linuxAlias->path) + 1;\r
+ nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;\r
+ prevDepth = RM_DTB_UTIL_STARTING_DEPTH; \r
+ resourceInfo.base = 0;\r
+ resourceInfo.length = 0;\r
+\r
+ spacePtr = strpbrk(linuxAlias->path, " ");\r
+ if (spacePtr) {\r
+ *spacePtr = '\0';\r
+ } \r
+ \r
+ while(pathOffset < pathSize) {\r
+ /* Move through DTB nodes until next alias path node found */\r
+ if (strcmp(linuxAlias->path + pathOffset, fdt_get_name(linuxDtb, nodeOffset, NULL))) {\r
+ nodeOffset = fdt_next_node(linuxDtb, nodeOffset, &depth);\r
+\r
+ if ((depth < prevDepth) || (nodeOffset == -FDT_ERR_NOTFOUND)) {\r
+ /* Returning from subnode that matched part of alias path without finding\r
+ * resource values */\r
+ retVal = (-31); /* TODO: COULD NOT FIND RESOURCE AT ALIAS PATH */\r
+ break;\r
+ }\r
+ }\r
+ else {\r
+ /* Found next alias path node. Move to next node name in path string. */\r
+ pathOffset += (strlen(linuxAlias->path + pathOffset) + 1);\r
+ spacePtr = strpbrk(linuxAlias->path + pathOffset, " ");\r
+ if (spacePtr) {\r
+ *spacePtr = '\0';\r
+ } \r
+ \r
+ prevDepth = fdt_node_depth(linuxDtb, nodeOffset);\r
+ propOffset = fdt_first_property_offset(linuxDtb, nodeOffset);\r
+ while ((propOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) &&\r
+ (pathOffset < pathSize)) {\r
+ propertyData = fdt_getprop_by_offset(linuxDtb, propOffset, \r
+ &propertyName, &propertyLen);\r
+\r
+ if (strcmp(linuxAlias->path + pathOffset, propertyName) == 0) {\r
+ /* Found resource at end of alias path */\r
+ pathOffset += (strlen(linuxAlias->path + pathOffset) + 1);\r
+ linuxValueRange = Rm_linuxExtractValues(propertyData, propertyLen);\r
+ retVal = Rm_reserveLinuxResource(rmInst, linuxAlias, \r
+ linuxValueRange, &opInfo);\r
+ Rm_linuxFreeValues(linuxValueRange);\r
+ }\r
+ propOffset = fdt_next_property_offset(linuxDtb, propOffset);\r
+ } \r
+\r
+ if (propOffset < -FDT_ERR_NOTFOUND) {\r
+ retVal = propOffset;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (retVal < RM_DTB_UTIL_RESULT_OKAY) {\r
+ break;\r
+ }\r
+ linuxAlias = (Rm_LinuxAlias *) linuxAlias->nextLinuxAlias;\r
+ }\r
+ return (retVal);\r
+}\r
+\r
+int32_t Rm_createAndInitAllocator(Rm_Inst *rmInst, const char *resourceName, \r
+ Rm_ResourceProperties *resourceProperties, void *linuxDtb)\r
+{\r
+ Rm_ResourceRange *range = NULL;\r
+ Rm_ResourceRange *rangeBasePtr = NULL;\r
+ Rm_NsAssignment *nsAssignments = NULL;\r
+ Rm_NsAssignment *nsAssignmentBasePtr = NULL;\r
+ Rm_LinuxAlias *linuxAlias = NULL;\r
+ Rm_NameServerObjCfg nameServerObjCfg; \r
+ int32_t retVal = RM_DTB_UTIL_RESULT_OKAY;\r
+\r
+ if (resourceProperties->rangeData && (resourceProperties->rangeLen > 0))\r
+ {\r
+ /* Extract the resource properties from the DTB */\r
+ range = rangeBasePtr = Rm_resourceExtractRange(resourceProperties->rangeData, \r
+ resourceProperties->rangeLen);\r
+\r
+ /* Create a tree allocator using the resource properties */\r
+ retVal = Rm_createTreeAllocator(rmInst, resourceName, range); \r
+\r
+ if (retVal >= RM_DTB_UTIL_RESULT_OKAY)\r
+ {\r
+ if (resourceProperties->linuxAliasData && resourceProperties->linuxAliasLen)\r
+ {\r
+ /* Reserve the resources taken by the Linux kernel specified in the Linux DTB */\r
+ linuxAlias = Rm_resourceExtractLinuxAlias(resourceProperties->linuxAliasData,\r
+ resourceProperties->linuxAliasLen);\r
+\r
+ retVal = Rm_findAndReserveLinuxResource(rmInst, resourceName, linuxDtb, linuxAlias); \r
+ }\r
+ }\r
+ }\r
\r
- if (rmInst->instType == Rm_instType_CLIENT)\r
+ if (retVal >= RM_DTB_UTIL_RESULT_OKAY)\r
+ {\r
+ /* Create entries in the NameServer if any NameServer assignments were specified */\r
+ if (resourceProperties->nsAssignData && resourceProperties->nsAssignLen)\r
+ {\r
+ nsAssignments = Rm_resourceExtractNsAssignment(resourceProperties->nsAssignData, \r
+ resourceProperties->nsAssignLen);\r
+\r
+ /* Cycle through the list of assignments and add them to the NameServer */\r
+ nsAssignmentBasePtr = nsAssignments;\r
+ while (nsAssignments)\r
+ {\r
+ memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));\r
+ nameServerObjCfg.nameServerTree = rmInst->nameServer;\r
+ nameServerObjCfg.nodeCfg.objName = nsAssignments->nsName;\r
+ nameServerObjCfg.nodeCfg.resourceName = (char *)resourceName;\r
+ nameServerObjCfg.nodeCfg.resourceBase= nsAssignments->resourceBase;\r
+ nameServerObjCfg.nodeCfg.resourceLength = nsAssignments->resourceLength; \r
+ \r
+ /* TODO: RETURN IF ANY OF THE ADDS FAIL??? */\r
+ Rm_nameServerAddObject(&nameServerObjCfg);\r
+ nsAssignments = nsAssignments->nextNsAssignment;\r
+ }\r
+ /* Free the memory allocated for the NameServer assignments */\r
+ Rm_resourceFreeNsAssignmentList(nsAssignmentBasePtr);\r
+ }\r
+ }\r
+\r
+ /* Free the memory allocated for the resource properties */\r
+ Rm_resourceFreeRange(rangeBasePtr);\r
+ Rm_resourceFreeLinuxAlias(linuxAlias);\r
+\r
+ return(retVal);\r
+}\r
+\r
+int32_t Rm_parseResourceProperty(void *globalResourceDtb, int32_t offset, Rm_ResourceProperties *propertyInfo)\r
+{\r
+ int32_t propertyLen;\r
+ const char *propertyName;\r
+ const void *propertyData;\r
+ Rm_ResourcePropType propertyType;\r
+ int32_t retVal = RM_DTB_UTIL_RESULT_OKAY;\r
+\r
+ /* Get the property data and store it in the corresponding propertyInfo field */\r
+ propertyData = fdt_getprop_by_offset(globalResourceDtb, offset, &propertyName, &propertyLen);\r
+ if (propertyData)\r
{\r
- /* Check if the new transaction's ID matches any transactions waiting for\r
- * responses. A transaction received as a response will have an ID that \r
- * matches the transaction that originated the request packet */\r
- if (queuedTransaction = Rm_transactionQueueFind(rmInst, transaction->id))\r
+ propertyType = Rm_resourceGetPropertyType(propertyName);\r
+ if (propertyType == Rm_resourcePropType_RESOURCE_RANGE)\r
{\r
- if (queuedTransaction->state == Rm_transactionState_AWAITING_RESPONSE)\r
+ if (propertyInfo->rangeData || propertyInfo->rangeLen)\r
{\r
- /* Found a transaction awaiting a response. Pass both transactions\r
- * to the service responder for response processing */\r
- Rm_serviceResponder(rmInst, transaction, queuedTransaction, receipt);\r
+ /* The range fields have already been populated. Return an error.\r
+ * The resource list has specified a property field more than once\r
+ * for a resource node */\r
+ retVal = -18; /* TEMP ERROR: Can't conflict with LIBFDT errors */\r
}\r
else\r
{\r
- /* Request transaction was not in the awaiting response state. Flag the\r
- * error in the receipt and return */\r
- receipt->serviceResult = RM_SERVICE_ERROR_INVALID_REQUEST_TRANSACTION_STATE_UPON_RESPONSE;\r
+ propertyInfo->rangeData = propertyData;\r
+ propertyInfo->rangeLen = propertyLen;\r
}\r
}\r
- else\r
+ else if (propertyType == Rm_resourcePropType_NSASSIGNMENT)\r
{\r
- /* This is a new transaction. Make sure the transaction is not a \r
- * response transaction sent to the wrong RM instance */\r
- if ((transaction->state == Rm_transactionState_RESOURCE_APPROVED) ||\r
- (transaction->state == Rm_transactionState_RESOURCE_DENIED))\r
+ if (propertyInfo->nsAssignData || propertyInfo->nsAssignLen)\r
{\r
- /* No matching request transaction. This transaction result was sent to the\r
- * wrong RM instance. Flag the error in the receipt and return */\r
- receipt->serviceResult = RM_SERVICE_ERROR_INVALID_TRANSACTION_RECEIVED_ON_CLIENT;\r
+ /* The nsAssign fields have already been populated. Return an error.\r
+ * The resource list has specified a property field more than once\r
+ * for a resource node */\r
+ retVal = -19; /* TEMP ERROR: Can't conflict with LIBFDT errors */\r
}\r
else\r
{\r
- /* All service requests on Clients are forwarded to the higher level RM agent\r
- * either a Client Delegate or Server, based on the RM system architecture */\r
- Rm_transactionForwarder(rmInst, transaction, receipt);\r
+ propertyInfo->nsAssignData = propertyData;\r
+ propertyInfo->nsAssignLen = propertyLen;\r
}\r
}\r
+ else if (propertyType == Rm_resourcePropType_RESOURCE_LINUX_ALIAS)\r
+ {\r
+ if (propertyInfo->linuxAliasData || propertyInfo->linuxAliasLen)\r
+ {\r
+ /* The linuxAlias fields have already been populated. Return an error.\r
+ * The resource list has specified a property field more than once\r
+ * for a resource node */\r
+ retVal = -28; /* TEMP ERROR: Can't conflict with LIBFDT errors */\r
+ }\r
+ else\r
+ {\r
+ propertyInfo->linuxAliasData = propertyData;\r
+ propertyInfo->linuxAliasLen = propertyLen;\r
+ }\r
+ } \r
+ else\r
+ {\r
+ retVal = -20; /* TEMP ERROR: Can't conflict with LIBFDT errors */\r
+ }\r
}\r
else\r
{\r
- /* Execute a command processor based on the command type */\r
- switch (transaction->transCommand)\r
+ retVal = -16; /* TEMP ERROR: Can't conflict with LIBFDT errors */\r
+ }\r
+\r
+ /* Don't get anymore properties if error occurred */\r
+ if (retVal == RM_DTB_UTIL_RESULT_OKAY)\r
+ {\r
+ offset = fdt_next_property_offset(globalResourceDtb, offset);\r
+ if (offset >= 0)\r
+ {\r
+ retVal = Rm_parseResourceProperty(globalResourceDtb, offset, propertyInfo);\r
+ }\r
+ else if (offset != -FDT_ERR_NOTFOUND)\r
{\r
- case Rm_command_ALLOCATE:\r
- case Rm_command_BLOCK_ALLOCATE:\r
- case Rm_command_ALLOCATE_NAMED:\r
- Rm_allocate(rmInst, transaction, receipt);\r
- break;\r
- case Rm_command_FREE:\r
- case Rm_command_BLOCK_FREE:\r
- case Rm_command_FREE_NAMED:\r
- Rm_free(rmInst, transaction, receipt);\r
- break;\r
- case Rm_command_MAP_NAME:\r
- Rm_nsAddObject(rmInst, transaction, receipt);\r
- break;\r
- case Rm_command_UNMAP_NAME:\r
- Rm_nsDeleteObject(rmInst, transaction, receipt);\r
- break;\r
- case Rm_command_RESOURCE_STATUS:\r
- Rm_getResourceStatus(rmInst, transaction, receipt);\r
- break;\r
- case Rm_command_RESOURCE_RESPONSE:\r
- \r
- break;\r
- case Rm_command_POLICY_REQUEST:\r
- break;\r
- case Rm_command_POLICY_RESPONSE:\r
- break;\r
+ /* Error was returned by LIBFDT when parsing the properties */\r
+ retVal = offset;\r
}\r
+ }\r
+ \r
+ return (retVal);\r
+}\r
\r
+int32_t Rm_parseResourceNode(Rm_Inst *rmInst, void *globalResourceDtb, int32_t nodeOffset, int32_t depth,\r
+ void *linuxDtb)\r
+{\r
+ const char *resourceName = fdt_get_name(globalResourceDtb, nodeOffset, NULL);\r
+ Rm_ResourceProperties resourceProperties;\r
+ int32_t error = RM_DTB_UTIL_RESULT_OKAY;\r
+ int32_t offset;\r
+\r
+ /* Initialize the resource properties structure */\r
+ memset((void *)&resourceProperties, 0, sizeof(Rm_ResourceProperties));\r
+\r
+ /* Ignore properties of the base node */\r
+ if (strcmp(resourceName, rmDtbStartingNode))\r
+ {\r
+ /* Get the properties for the resource node if any exist */\r
+ offset = fdt_first_property_offset(globalResourceDtb, nodeOffset);\r
+ if (offset >= RM_DTB_UTIL_STARTING_NODE_OFFSET)\r
+ {\r
+ /* Since at least one property exists attempt to parse the property nodes and \r
+ * use them to create and initialize a resource allocator */\r
+ error = Rm_parseResourceProperty(globalResourceDtb, offset, &resourceProperties);\r
+ if (error < -FDT_ERR_NOTFOUND)\r
+ {\r
+ return (error);\r
+ }\r
+ \r
+ /* Initialize an allocator with the resource properties if no error was returned */\r
+ Rm_createAndInitAllocator(rmInst, resourceName, &resourceProperties, linuxDtb);\r
+ }\r
+ else if (offset != -FDT_ERR_NOTFOUND)\r
+ {\r
+ /* Error was returned by LIBFDT when parsing the properties */\r
+ return (offset);\r
+ }\r
+ }\r
+ \r
+ /* Get the next resource node */\r
+ offset = fdt_next_node(globalResourceDtb, nodeOffset, &depth);\r
+ /* Check the offset and depth of the next node to make sure the current node\r
+ * wasn't the last node in the Resource List. A depth less than the depth set\r
+ * at the start of the recursion will signal the end of the resource list */\r
+ if ((offset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) && (depth >= RM_DTB_UTIL_STARTING_DEPTH))\r
+ {\r
+ error = Rm_parseResourceNode(rmInst, globalResourceDtb, offset, depth, linuxDtb);\r
+ if (error < -FDT_ERR_NOTFOUND)\r
+ {\r
+ return (error);\r
+ }\r
+ }\r
+ else if (offset != -FDT_ERR_NOTFOUND)\r
+ {\r
+ /* Error was returned by LIBFDT when parsing the nodes */\r
+ return (offset);\r
}\r
\r
+ return (RM_DTB_UTIL_RESULT_OKAY);\r
}\r
\r
+int32_t Rm_initializeAllocators(Rm_Inst *rmInst, void *globalResourceDtb, void *linuxDtb)\r
+{\r
+ int32_t nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;\r
+ int32_t startDepth = RM_DTB_UTIL_STARTING_DEPTH;\r
+ int32_t result = RM_DTB_UTIL_RESULT_OKAY;\r
+\r
+ /* Recursively parse the Global Resource List, creating an allocator for\r
+ * each resource as specified in the node */\r
+ result = Rm_parseResourceNode(rmInst, globalResourceDtb, nodeOffset, startDepth, linuxDtb);\r
+\r
+ return(result);\r
+}\r
+ \r
/**********************************************************************\r
********************** Application visible APIs **********************\r
**********************************************************************/\r
\r
-Rm_Handle Rm_init(Rm_InitCfg *initCfg)\r
+/* Server Only */\r
+void Rm_printResourceStatus(Rm_Handle *rmHandle)\r
{\r
- Rm_Inst *rmInst;\r
+ Rm_Inst *rmInst = (Rm_Inst *) rmHandle;\r
+ Rm_Allocator *allocator = rmInst->allocators;\r
+ Rm_AllocatedTo *allocatedTo;\r
+ Rm_ResourceTree *treeRoot;\r
+ Rm_ResourceNode *treeNode;\r
\r
- /* Instance creation checks. Add one to strlen calculation for null character */\r
- if ((strlen(initCfg->instName) + 1) > RM_INSTANCE_NAME_MAX_CHARS)\r
- {\r
- /* Failure: Instance name is too big */\r
+ while (allocator != NULL) {\r
+ Rm_osalLog("Resource: %s\n", allocator->resourceName);\r
+\r
+ treeRoot = allocator->allocatorRootEntry;\r
+\r
+ RB_FOREACH(treeNode, _Rm_ResourceTree, treeRoot) { \r
+ Rm_osalLog(" %10d - %10d ", treeNode->base, \r
+ treeNode->base + treeNode->length -1);\r
+ \r
+ if (treeNode->allocationCount == 0) {\r
+ Rm_osalLog("NOT ALLOCATED\n");\r
+ }\r
+ else {\r
+ allocatedTo = treeNode->allocatedTo;\r
+ Rm_osalLog("allocated to ");\r
+ while (allocatedTo) {\r
+ Rm_osalLog(" %s", allocatedTo->instNameNode->name);\r
+ allocatedTo = allocatedTo->nextAllocatedTo;\r
+ }\r
+ Rm_osalLog("\n");\r
+ }\r
+ } \r
+ allocator = allocator->nextAllocator;\r
+ }\r
+\r
+ Rm_nameServerPrintObjects(rmInst->nameServer);\r
+}\r
+\r
+Rm_PreMainHandle Rm_preMainInit(Rm_PreMainInitCfg *preMainInitCfg, int32_t *result)\r
+{\r
+ Rm_PreMainInst *preMainInst;\r
+\r
+ if ((strlen(preMainInitCfg->instName) + 1) > RM_INSTANCE_NAME_MAX_CHARS) {\r
+ *result = RM_INIT_ERROR_INSTANCE_NAME_TOO_BIG;\r
return (NULL);\r
}\r
+\r
+ preMainInst = (Rm_PreMainInst *) Rm_osalMalloc (sizeof(Rm_PreMainInst));\r
+ fdt_open_into(preMainInitCfg->startupPolicyDtb, preMainInitCfg->startupPolicyDtb,\r
+ fdt_totalsize(preMainInitCfg->startupPolicyDtb));\r
+ preMainInst->startupDtb = preMainInitCfg->startupPolicyDtb;\r
+\r
+ preMainInst->validInstTree = Rm_policyCreateValidInstTree(preMainInst->startupDtb, result);\r
+ if (*result == RM_INIT_OK) {\r
+ /* Validate policy assignment strings */\r
+ *result = Rm_policyValidatePolicy(preMainInitCfg->startupPolicyDtb, preMainInst->validInstTree);\r
+ }\r
+\r
+ if (*result != RM_INIT_OK) {\r
+ if (preMainInst->validInstTree) {\r
+ Rm_policyFreeValidInstTree(preMainInst->validInstTree);\r
+ }\r
+ Rm_osalFree((void *)preMainInst, sizeof(Rm_PreMainInst));\r
+ preMainInst = NULL;\r
+ }\r
+ else {\r
+ strcpy(preMainInst->instName, preMainInitCfg->instName);\r
+ preMainInst->requestCount = 0;\r
+ preMainInst->preMainReqList = NULL;\r
+ }\r
+\r
+ return((Rm_PreMainHandle)preMainInst);\r
+}\r
+\r
+int32_t Rm_preMainHandleValidateAndDelete(Rm_Handle rmHandle, Rm_PreMainHandle rmPreMainHandle)\r
+{\r
+ Rm_Inst *rmInst = (Rm_Inst *)rmHandle;\r
+ Rm_PreMainInst *preMainInst = (Rm_PreMainInst *)rmPreMainHandle;\r
+ Rm_ServicePreMainReq *serviceReq = preMainInst->preMainReqList;\r
+ Rm_ServicePreMainReq *nextServiceReq;\r
+ int32_t retVal = RM_INIT_OK;\r
+\r
+ if (strcmp(rmInst->instName, preMainInst->instName) == 0) {\r
+ /* TODO: Validate the requests against the global policyDtb */\r
+\r
+ /* Free all memory associated with the pre-main instance */\r
+ Rm_policyFreeValidInstTree(preMainInst->validInstTree);\r
+ while(serviceReq) {\r
+ nextServiceReq = serviceReq->nextPreMainReq;\r
+ Rm_osalFree((void *)serviceReq->preMainReq, sizeof(Rm_ServiceReqInfo));\r
+ Rm_osalFree((void *)serviceReq, sizeof(Rm_ServicePreMainReq));\r
+ serviceReq = nextServiceReq;\r
+ }\r
+ Rm_osalFree((void *)preMainInst, sizeof(Rm_PreMainInst));\r
+ }\r
+ else {\r
+ retVal = RM_INIT_ERROR_PREMAIN_INST_AND_POSTMAIN_INST_NAMES_DONT_MATCH;\r
+ }\r
+ return(retVal);\r
+}\r
+\r
+Rm_Handle Rm_init(Rm_InitCfg *initCfg, int32_t *result)\r
+{\r
+ Rm_Inst *rmInst;\r
+ void *globalResourceDtb = NULL;\r
+ void *linuxResourceDtb = NULL;\r
+ void *policyDtb = NULL;\r
+\r
+ *result = RM_INIT_OK;\r
\r
- /* Get memory for RM instance from local memory */\r
- rmInst = Rm_osalMalloc (sizeof(Rm_Inst), false);\r
- /* Populate instance based on input parameters */\r
- strcpy (&rmInst->name[0], initCfg->instName);\r
- rmInst->instType = initCfg->instType;\r
- rmInst->instState = RM_state_IDLE;\r
- rmInst->registeredWithDelegateOrServer = false;\r
- rmInst->serviceCallback = NULL;\r
-\r
- /* The transport APIs must be provided */\r
- if ((initCfg->rmAllocPktFuncPtr == NULL) ||\r
- (initCfg->rmFreePktFuncPtr == NULL) ||\r
- (initCfg->rmSendFuncPtr == NULL) ||\r
- (initCfg->rmReceiveFuncPtr == NULL) ||\r
- (initCfg->rmNumPktsReceivedFuncPtr == NULL))\r
- {\r
+ if ((strlen(initCfg->instName) + 1) > RM_INSTANCE_NAME_MAX_CHARS) {\r
+ *result = RM_INIT_ERROR_INSTANCE_NAME_TOO_BIG;\r
return (NULL);\r
}\r
- \r
- /* Populate the instance transport callouts */\r
- rmInst->transport.rmAllocPkt = initCfg->rmAllocPktFuncPtr;\r
- rmInst->transport.rmFreePkt = initCfg->rmFreePktFuncPtr;\r
- rmInst->transport.rmSend = initCfg->rmSendFuncPtr;\r
- rmInst->transport.rmReceive = initCfg->rmReceiveFuncPtr;\r
- rmInst->transport.rmNumPktsReceived = initCfg->rmNumPktsReceivedFuncPtr;\r
-\r
- /* Initialize the transport routing map linked list pointer to NULL. The linked list\r
- * nodes will be created when the application registers transports */\r
- rmInst->routeMap = NULL;\r
\r
- /* Initialize the transaction queue linked list pointer to NULL. The linked list\r
- * nodes will be created when the transactions are forwarded to higher level RM\r
- * agents. */\r
+ /* Create and initialize instance */\r
+ rmInst = Rm_osalMalloc (sizeof(Rm_Inst));\r
+ memset ((void *) rmInst, 0, sizeof(Rm_Inst));\r
+ strcpy (rmInst->instName, initCfg->instName);\r
+ rmInst->instType = initCfg->instType;\r
+ rmInst->registeredWithDelegateOrServer = false;\r
+ rmInst->routeMap = NULL;\r
+ rmInst->allocators = NULL;\r
+ rmInst->nameServer = NULL;\r
+ rmInst->policy = NULL;\r
+ rmInst->validInstances = NULL;\r
+ rmInst->transactionSeqNum = Rm_transactionInitSequenceNum();\r
rmInst->transactionQueue= NULL;\r
\r
- /* RM Server specific actions */\r
- if (rmInst->instType == Rm_instType_SERVER)\r
- {\r
- /* parse DTB, etc */\r
+ if ((rmInst->instType != Rm_instType_CLIENT) && initCfg->policy) {\r
+ policyDtb = initCfg->policy;\r
+ fdt_open_into(policyDtb, policyDtb, fdt_totalsize(policyDtb)); \r
+\r
+ /* Create valid instance list from policy. Must be done prior to parsing\r
+ * GRL so that Linux resources can be reserved correctly */\r
+ rmInst->validInstances = Rm_policyCreateValidInstTree(policyDtb, result);\r
+ /* Validate policy assignment strings */\r
+ *result = Rm_policyValidatePolicy(rmInst, policyDtb);\r
+ rmInst->policy = policyDtb;\r
}\r
\r
- /* Instance startup policies are only used for Servers and Client Delegates */\r
- if (rmInst->instType != Rm_instType_CLIENT)\r
- {\r
- rmInst->instPolicy = initCfg->startupPolicy;\r
+ /* RM Server specific actions */\r
+ if (rmInst->instType == Rm_instType_SERVER) {\r
+ Rm_nameServerInit();\r
+\r
+ if (initCfg->globalResourceList) {\r
+ globalResourceDtb = initCfg->globalResourceList;\r
+ fdt_open_into(globalResourceDtb, globalResourceDtb, fdt_totalsize(globalResourceDtb));\r
\r
- /* Store policy via policy APIs ... */\r
+ if (initCfg->linuxDtb) {\r
+ linuxResourceDtb = initCfg->linuxDtb;\r
+ fdt_open_into(linuxResourceDtb, linuxResourceDtb, fdt_totalsize(linuxResourceDtb)); \r
+ }\r
+ Rm_initializeAllocators(rmInst, globalResourceDtb, linuxResourceDtb);\r
+ }\r
}\r
\r
- /* Return the RM Handle */\r
+ if ((rmInst->instType != Rm_instType_CLIENT) && initCfg->policy) {\r
+ *result = Rm_policyValidatePolicyResourceNames(rmInst, policyDtb);\r
+ } \r
+\r
return ((Rm_Handle) rmInst);\r
}\r
\r