diff --git a/src/rm.c b/src/rm.c
index 16b3dd72ebab462338aba2d5934295e6f44de774..273c1759364e535d3fc4f21255661f245c03af74 100644 (file)
--- a/src/rm.c
+++ b/src/rm.c
#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
************************** Globals ***********************************\r
**********************************************************************/\r
-char rmIntegerAllocator[] = "integer";\r
-char rmTreeAllocator[] = "tree";\r
-\r
extern char rmDtbStartingNode[];\r
\r
/** @brief Global Variable which describes the RM Version Information */\r
************** Red-Black BBST Tree Allocator Functions ***************\r
**********************************************************************/\r
\r
-/* TODO: This needed? */\r
-/* Prototype for function that allocates new tree nodes */\r
-Rm_ResourceTreeNode *Rm_newResourceTreeNode(uint32_t resourceBase, uint32_t resourceLength)\r
+\r
+Rm_ResourceNode *Rm_newResourceNode(uint32_t resourceBase, uint32_t resourceLength)\r
{\r
- Rm_ResourceTreeNode *newNode = NULL;\r
+ Rm_ResourceNode *newNode = NULL;\r
\r
- newNode = Rm_osalMalloc(sizeof(Rm_ResourceTreeNode));\r
+ newNode = Rm_osalMalloc(sizeof(Rm_ResourceNode));\r
+ memset((void *)newNode, 0, sizeof(Rm_ResourceNode));\r
\r
- /* Populate the RM relevant fields */\r
newNode->base = resourceBase;\r
newNode->length = resourceLength;\r
+ newNode->allocationCount = 0;\r
+ newNode->allocatedTo = NULL;\r
\r
return(newNode);\r
}\r
\r
-/* TODO: This needed? */\r
-/* Prototype for function that frees new tree nodes */\r
-void Rm_freeResourceTreeNode(Rm_ResourceTreeNode *treeNode)\r
+void Rm_freeResourceNode(Rm_ResourceNode *node)\r
{\r
- /* Free the memory associated with the tree node. */\r
- Rm_osalFree((void *)treeNode, sizeof(Rm_ResourceTreeNode));\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_ResourceTreeNodeCompare(Rm_ResourceTreeNode *element1, Rm_ResourceTreeNode *element2)\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
- {\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
- {\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
- {\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
@@ -131,7 +126,7 @@ int Rm_ResourceTreeNodeCompare(Rm_ResourceTreeNode *element1, Rm_ResourceTreeNod
}\r
\r
/* Generate the red-black tree manipulation functions */\r
-RB_GENERATE(_Rm_ResourceTree, _Rm_ResourceTreeNode, linkage, Rm_ResourceTreeNodeCompare);\r
+RB_GENERATE(_Rm_ResourceTree, _Rm_ResourceNode, linkage, Rm_ResourceNodeCompare);\r
\r
/**********************************************************************\r
********************** Internal Functions ****************************\r
@@ -140,8 +135,8 @@ RB_GENERATE(_Rm_ResourceTree, _Rm_ResourceTreeNode, linkage, Rm_ResourceTreeNode
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_osalMtCsEnter();\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
+ if (newTransaction != NULL) {\r
/* Clear the transaction */\r
memset((void *)newTransaction, 0, sizeof(Rm_Transaction));\r
\r
newTransaction->nextTransaction = NULL; \r
\r
/* Check if there are any transactions in the transaction queue */\r
- if (transactionQueue)\r
- {\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
- {\r
+ while (transactionQueue->nextTransaction != NULL) {\r
/* Traverse the list until arriving at the last transaction */\r
transactionQueue = transactionQueue->nextTransaction;\r
}\r
/* Add the new transaction to the end of the queue */\r
transactionQueue->nextTransaction = newTransaction;\r
}\r
- else\r
- {\r
+ else {\r
/* The transaction queue does not currently exist. The new transaction is the \r
* first transaction */\r
rmInst->transactionQueue = newTransaction;\r
@@ -193,42 +184,30 @@ Rm_Transaction *Rm_transactionQueueFind(Rm_Inst *rmInst, uint32_t transactionId)
{\r
Rm_Transaction *transaction = (Rm_Transaction *)rmInst->transactionQueue;\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->localId == 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
- int32_t retVal = RM_SERVICE_STATE_OKAY;\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
+ /* Lock access to the instance */\r
key = Rm_osalMtCsEnter();\r
\r
- /* Find the transaction ID within the specified RM instance's transaction queue. */\r
- while (transaction != NULL)\r
- {\r
- if (transaction->localId == 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
transaction = transaction->nextTransaction;\r
}\r
\r
- /* Traversed entire queue but did not find transaction */\r
- if (transaction == NULL)\r
- {\r
- retVal = 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
-\r
- /* Free the memory associated with the transaction. */\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
uint32_t Rm_transactionInitSequenceNum(void)\r
{\r
- /* Sequence number can never have a value of zero so that there are no conflicts\r
- * with transactions that have a remoteOriginatingId of zero */\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
{\r
uint32_t sequenceNum = 0;\r
\r
- /* Get the next sequence number and then increment. If there's an overflow\r
- * assign the initial value instead of incrementing. */\r
- if (rmInst->transactionSeqNum + 1 < rmInst->transactionSeqNum)\r
- {\r
+ if (rmInst->transactionSeqNum + 1 < rmInst->transactionSeqNum) {\r
/* Overflow */\r
sequenceNum = rmInst->transactionSeqNum;\r
rmInst->transactionSeqNum = Rm_transactionInitSequenceNum();\r
}\r
- else\r
- {\r
+ else {\r
sequenceNum = rmInst->transactionSeqNum++;\r
} \r
-\r
return (sequenceNum);\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
-{\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
-\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
- case Rm_service_RESOURCE_FREE:\r
- case Rm_service_RESOURCE_BLOCK_FREE:\r
- case Rm_service_RESOURCE_FREE_BY_NAME:\r
- rmPkt = Rm_transportCreateResourceResponsePkt(rmInst, dstTransportNode, \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);\r
- break;\r
- default:\r
- /* Invalid service type. Flag the error and return */\r
- transaction->state = RM_SERVICE_ERROR_INVALID_SERVICE_TYPE;\r
- break;\r
- }\r
-\r
- if (transaction->state <= RM_SERVICE_ERROR_BASE)\r
- {\r
- /* Delete the transaction and return immediately because an error occurred \r
- * allocating the packet */\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) < RM_TRANSPORT_SUCCESSFUL)\r
- {\r
- /* Negative value returned by transport send. An error occurred\r
- * in the transport while attempting to send the packet.*/\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
- /* Non-NULL value returned by transport packet free. Flag the\r
- * error */\r
- transaction->state = RM_SERVICE_ERROR_TRANSPORT_FREE_PKT_ERROR;\r
- }\r
- return;\r
- }\r
-\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
-Rm_Allocator *Rm_allocatorAdd(Rm_Inst *rmInst, const char *resourceName, Rm_AllocatorType type)\r
+Rm_Allocator *Rm_allocatorAdd(Rm_Inst *rmInst, const char *resourceName)\r
{\r
- Rm_Allocator *allocators = (Rm_Allocator *)rmInst->allocators;\r
+ Rm_Allocator *allocators = (Rm_Allocator *)rmInst->allocators;\r
Rm_Allocator *newAllocator = NULL;\r
- void *key;\r
+ void *key;\r
\r
- /* Lock access to the RM instance's allocator list */\r
+ /* Lock access to the instance */\r
key = Rm_osalMtCsEnter();\r
\r
- /* Get memory for a new allocator from local memory */\r
newAllocator = Rm_osalMalloc(sizeof(Rm_Allocator));\r
\r
- /* Return if the memory allocated for the allocator is NULL */\r
- if (newAllocator != NULL)\r
- {\r
- /* Clear the allocator */\r
+ if (newAllocator) {\r
memset((void *)newAllocator, 0, sizeof(Rm_Allocator));\r
-\r
- /* Populate the allocator */\r
- newAllocator->type = type;\r
strcpy(newAllocator->resourceName, resourceName);\r
- /* allocator's root entry will be created by the invoking function */\r
newAllocator->allocatorRootEntry = NULL;\r
- /* New allocator's nextAllocator pointer will always be NULL */\r
newAllocator->nextAllocator = NULL; \r
\r
- /* Check if there are any allocators in the allocator list */\r
- if (allocators)\r
- {\r
- /* At least one allocator in the allocator list. Add the new allocator to the \r
- * end of the allocator list */\r
- while (allocators->nextAllocator != NULL)\r
- {\r
- /* Traverse the list until arriving at the last allocator */\r
+ /* Add allocator to end of list */\r
+ if (allocators) {\r
+ while (allocators->nextAllocator != NULL) {\r
allocators = allocators->nextAllocator;\r
}\r
-\r
- /* Add the new allocator to the end of the list */\r
allocators->nextAllocator = newAllocator;\r
}\r
- else\r
- {\r
- /* The allocator list does not currently exist. The new allocator is the \r
- * first allocator */\r
+ else {\r
rmInst->allocators = newAllocator;\r
}\r
}\r
@@ -410,1005 +290,1521 @@ Rm_Allocator *Rm_allocatorAdd(Rm_Inst *rmInst, const char *resourceName, Rm_Allo
return (newAllocator);\r
}\r
\r
-Rm_Allocator *Rm_allocatorFind(Rm_Inst *rmInst, char *resourceName)\r
+Rm_Allocator *Rm_allocatorFind(Rm_Allocator *allocatorList, char *resourceName)\r
{\r
- Rm_Allocator *allocator = (Rm_Allocator *)rmInst->allocators;\r
-\r
- /* Make sure there is at least one allocator in the allocator list */\r
- if (allocator != NULL)\r
- {\r
- /* Find the resource name within the allocator list. If the end of the\r
- * allocator list is reached without finding the resource name the \r
- * allocator pointer will be NULL */\r
- while (allocator != NULL)\r
- {\r
- if (strcmp(allocator->resourceName, resourceName) == 0)\r
- {\r
- /* Match: break out of loop and return the allocator */\r
- break; \r
- }\r
- allocator = allocator->nextAllocator;\r
+ while (allocatorList) {\r
+ if (strcmp(allocatorList->resourceName, resourceName) == 0) {\r
+ break; \r
}\r
+ allocatorList = allocatorList->nextAllocator;\r
}\r
\r
- return (allocator);\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
+ int32_t retVal = RM_SERVICE_STATE_OKAY;\r
+ void *key;\r
\r
- /* Lock access to the RM instance's allocator list */\r
+ /* Lock access to instance */\r
key = Rm_osalMtCsEnter();\r
\r
- /* Find the resource within the specified RM instance's allocator list. */\r
- while (allocator != NULL)\r
- {\r
- if (strcmp(allocator->resourceName, resourceName) == 0)\r
- {\r
- /* Match: break out of loop and delete the transaction */\r
+ while (allocator) {\r
+ if (strcmp(allocator->resourceName, resourceName) == 0) {\r
break; \r
}\r
-\r
prevAllocator = allocator;\r
allocator = allocator->nextAllocator;\r
}\r
\r
- /* Traversed entire list but did not find allocator. */\r
- if (allocator == NULL)\r
- {\r
- retVal = -22; /* TEMP ERROR: Can't conflict with LIBFDT errors */\r
- }\r
- else\r
- {\r
- /* Delete the allocator */\r
- if ((prevAllocator == NULL) && allocator->nextAllocator)\r
- {\r
- /* Allocator to be deleted exists at start of allocator list. Map second\r
- * allocator to be start of allocator list as long as there are more than\r
- * one allocators. */\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
- {\r
- /* Allocator to be deleted is in the middle or at end of the list. Adjust \r
- * adjacent allocator pointers. This covers the case where the allocator to be \r
- * removed is at the end of the list. */\r
+ else {\r
+ /* Allocator in middle or end of list. */\r
prevAllocator->nextAllocator = allocator->nextAllocator;\r
}\r
-\r
- /* Free the memory associated with the allocator. */\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
-int32_t Rm_createIntegerAllocator(Rm_Inst *rmInst, const char *resourceName, Rm_ResourceRange *range)\r
+void Rm_addAllocatedTo(Rm_ResourceNode *node, void *serviceInstNode)\r
{\r
- Rm_Allocator *allocator = NULL;\r
- Rm_ResourceRange *rangeBasePtr = range;\r
- Rm_IntegerAllocatorRootEntry *intRootEntry = NULL;\r
- uint16_t i, entryIndex;\r
+ Rm_AllocatedTo *allocatedToList = node->allocatedTo;\r
+ Rm_AllocatedTo *newAllocatedTo = NULL;\r
\r
- /* Create the new base integer allocator */\r
- allocator = Rm_allocatorAdd(rmInst, resourceName, Rm_allocatorType_INTEGER);\r
+ newAllocatedTo = Rm_osalMalloc(sizeof(Rm_AllocatedTo));\r
\r
- /* Construct the integer allocator root entry */\r
- intRootEntry = Rm_osalMalloc(sizeof(Rm_IntegerAllocatorRootEntry));\r
- intRootEntry->numResourceElements = 0;\r
+ if (newAllocatedTo) {\r
+ newAllocatedTo->instNameNode = serviceInstNode;\r
+ newAllocatedTo->nextAllocatedTo = NULL; \r
\r
- /* Get the number of entries to allocate based on the lengths in the ranges */\r
- while (range != NULL)\r
- {\r
- intRootEntry->numResourceElements += range->length;\r
- range = range->nextRange;\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
- /* Initialize the entries using the range information */\r
- if (intRootEntry->numResourceElements)\r
- {\r
- intRootEntry->resourceArrayBase = Rm_osalMalloc(sizeof(Rm_IntegerEntry) * intRootEntry->numResourceElements);\r
- memset((void *)intRootEntry->resourceArrayBase, 0, sizeof(Rm_IntegerEntry) * intRootEntry->numResourceElements);\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
- /* Reset the range pointer */\r
- range = rangeBasePtr;\r
- entryIndex = 0;\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
- while (range != NULL)\r
- {\r
- /* Initialize each entry */\r
- for (i = range->base; i < (range->base + range->length); i++, entryIndex++)\r
- {\r
- intRootEntry->resourceArrayBase[entryIndex].value = i;\r
- /* Initialize the allocatedTo field to the NOT_ALLOCATED string */\r
- strcpy(intRootEntry->resourceArrayBase[entryIndex].allocatedTo, RM_NOT_ALLOCATED_STRING);\r
+ if (matchedInst) {\r
+ nodeTwoAllocs = nodeTwo->allocatedTo;\r
+ nodeOneAllocs = nodeOneAllocs->nextAllocatedTo;\r
}\r
- \r
- range = range->nextRange;\r
+ else {\r
+ return(FALSE);\r
+ } \r
}\r
- \r
- allocator->allocatorRootEntry = intRootEntry;\r
}\r
- else\r
- {\r
- /* No resource entries were created. Free the memory associated with the\r
- * allocator and the root entry */\r
- Rm_osalFree((void *)intRootEntry, sizeof(Rm_IntegerAllocatorRootEntry));\r
- Rm_allocatorDelete(rmInst, allocator->resourceName);\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
- return(0); /* TODO: FIX THIS RETURN */\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_Allocator *allocator = NULL;\r
Rm_ResourceTree *treeRootEntry = NULL;\r
- Rm_ResourceTreeNode *treeNode = NULL;\r
- Rm_ResourceTreeNode *collidingNode = NULL;\r
-\r
- /* Create the new base integer allocator */\r
- allocator = Rm_allocatorAdd(rmInst, resourceName, Rm_allocatorType_TREE);\r
+ Rm_ResourceNode *treeNode = NULL;\r
+ Rm_ResourceNode *collidingNode = NULL;\r
\r
- /* Create the tree root entry and initialize it */\r
+ allocator = Rm_allocatorAdd(rmInst, resourceName);\r
treeRootEntry = Rm_osalMalloc(sizeof(Rm_ResourceTree));\r
RB_INIT(treeRootEntry);\r
\r
- /* Create a node in the tree for resource range and insert them into the tree. */\r
- while (range != NULL)\r
- {\r
- treeNode = Rm_osalMalloc(sizeof(Rm_ResourceTreeNode));\r
- treeNode->base = range->base;\r
- treeNode->length = range->length;\r
- /* Initialize the allocatedTo field to the NOT_ALLOCATED string */\r
- strcpy(treeNode->allocatedTo, RM_NOT_ALLOCATED_STRING);\r
-\r
- /* Insert the node into the tree */\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
- {\r
- Rm_ResourceTreeNode *nextNode = NULL;\r
+ if (collidingNode) {\r
+ Rm_ResourceNode *nextNode = NULL;\r
\r
- /* Node that was inserted colliding with an existing node. Clean up the tree\r
- * that's been allocated thus far and return an error since there should be no\r
- * collisions */\r
- for (treeNode = RB_MIN(_Rm_ResourceTree, treeRootEntry); treeNode != NULL; treeNode = nextNode)\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_osalFree((void *)treeNode, sizeof(Rm_ResourceTreeNode));\r
+ Rm_freeResourceNode(treeNode);\r
}\r
- /* Delete the tree root entry and the allocator */\r
Rm_osalFree((void *)treeRootEntry, sizeof(Rm_ResourceTree));\r
Rm_allocatorDelete(rmInst, allocator->resourceName);\r
return (-24); /* TODO FIX RETURN */\r
}\r
-\r
range = range->nextRange;\r
}\r
-\r
- /* Assign the tree's root to the allocator */\r
+ \r
allocator->allocatorRootEntry = treeRootEntry;\r
-\r
- /* Print the base values as a test */\r
- RB_FOREACH(treeNode, _Rm_ResourceTree, (Rm_ResourceTree *) allocator->allocatorRootEntry)\r
- {\r
- Rm_osalLog("Tree node base: %d length: %d and allocated to: %s\n", treeNode->base, treeNode->length, treeNode->allocatedTo);\r
- }\r
-\r
return(0); /* TODO: FIX THIS RETURN */\r
}\r
\r
-int32_t Rm_createAndInitAllocator(Rm_Inst *rmInst, const char *resourceName, \r
- Rm_ResourceProperties *resourceProperties)\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
- char *allocatorType = NULL;\r
- Rm_ResourceRange *range = NULL;\r
- Rm_ResourceRange *rangeBasePtr = NULL;\r
- Rm_NsAssignment *nsAssignments = NULL;\r
- Rm_NsAssignment *nsAssignmentBasePtr = NULL;\r
- int32_t retVal = RM_DTB_UTIL_RESULT_OKAY;\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
- /* TODO: NEED CHECKS FOR VALIDITY OF ALL THE resourceProperties FIELDS */\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
- /* Extract the resource properties from the DTB */\r
- allocatorType = Rm_resourceExtractResourceAllocator(resourceProperties->allocatorData, \r
- resourceProperties->allocatorLen);\r
- range = rangeBasePtr = Rm_resourceExtractResourceRange(resourceProperties->rangeData, \r
- resourceProperties->rangeLen);\r
+ memset((void *)&findNode, 0, sizeof(Rm_ResourceNode));\r
+ findNode.base = opInfo->resourceInfo->base;\r
+ findNode.length = opInfo->resourceInfo->length;\r
\r
- /* Create an allocator based on the allocator type specified */\r
- if (strcmp(allocatorType, &rmIntegerAllocator[0]) == 0)\r
- {\r
- /* Create an integer allocator using the resource properties */\r
- retVal = Rm_createIntegerAllocator(rmInst, resourceName, range); \r
- }\r
- else if (strcmp(allocatorType, &rmTreeAllocator[0]) == 0)\r
- {\r
- /* Create a tree allocator using the resource properties */\r
- retVal = Rm_createTreeAllocator(rmInst, resourceName, range); \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\r
- {\r
- /* Allocator type not recognized. Free the resource properties and return */\r
- retVal = -21; /* TEMP ERROR: Can't conflict with LIBFDT errors */\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
- 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
+ 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
- /* Cycle through the list of assignments and add them to the NameServer */\r
- nsAssignmentBasePtr = nsAssignments;\r
- while (nsAssignments)\r
- {\r
- /* TODO: RETURN IF ANY OF THE ADDS FAIL??? */\r
- Rm_nsAddObject(rmInst, nsAssignments->nsName, nsAssignments->resourceValue);\r
- nsAssignments = nsAssignments->nextNsAssignment;\r
+ if (retVal != RM_SERVICE_PROCESSING) {\r
+ break;\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_resourceFreeResourceAllocator(allocatorType);\r
- Rm_resourceFreeResourceRange(rangeBasePtr);\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
+ return(retVal); \r
}\r
\r
-int32_t Rm_parseResourceProperty(void *globalResourceDtb, int32_t offset, Rm_ResourceProperties *propertyInfo)\r
+int32_t Rm_treeAllocate(Rm_Inst *rmInst, Rm_Allocator *allocator, int32_t resourcePolicy,\r
+ Rm_AllocatorOpInfo *opInfo)\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
+ 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
- /* 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
- propertyType = Rm_resourceGetPropertyType(propertyName);\r
- if (propertyType == Rm_resourcePropType_RESOURCE_ALLOCATOR)\r
- {\r
- if (propertyInfo->allocatorData || propertyInfo->allocatorLen)\r
- {\r
- /* The allocator 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 = -17; /* TEMP ERROR: Can't conflict with LIBFDT errors */\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
- {\r
- propertyInfo->allocatorData = propertyData;\r
- propertyInfo->allocatorLen = propertyLen;\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
- else if (propertyType == Rm_resourcePropType_RESOURCE_RANGE)\r
- {\r
- if (propertyInfo->rangeData || propertyInfo->rangeLen)\r
- {\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
- propertyInfo->rangeData = propertyData;\r
- propertyInfo->rangeLen = propertyLen;\r
- }\r
- }\r
- else if (propertyType == Rm_resourcePropType_NSASSIGNMENT)\r
- {\r
- if (propertyInfo->nsAssignData || propertyInfo->nsAssignLen)\r
- {\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
- propertyInfo->nsAssignData = propertyData;\r
- propertyInfo->nsAssignLen = propertyLen;\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
- {\r
- retVal = -20; /* TEMP ERROR: Can't conflict with LIBFDT errors */\r
+ else {\r
+ retVal = RM_SERVICE_DENIED_RESOURCE_ALREADY_ALLOCATED;\r
}\r
}\r
- else\r
- {\r
- retVal = -16; /* TEMP ERROR: Can't conflict with LIBFDT errors */\r
+ else {\r
+ retVal = RM_SERVICE_DENIED_RESOURCE_VALUE_RANGE_DOES_NOT_EXIST;\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
- /* Error was returned by LIBFDT when parsing the properties */\r
- retVal = offset;\r
- }\r
- }\r
- \r
- return (retVal);\r
+ return(retVal); \r
}\r
\r
-int32_t Rm_parseResourceNode(Rm_Inst *rmInst, void *globalResourceDtb, int32_t nodeOffset, int32_t depth)\r
+int32_t Rm_treeFree(Rm_Inst *rmInst, Rm_Allocator *allocator, int32_t resourcePolicy, Rm_AllocatorOpInfo *opInfo)\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
+ 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
- /* Initialize the resource properties structure */\r
- memset((void *)&resourceProperties, 0, sizeof(Rm_ResourceProperties));\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
- /* 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
+ 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
- /* Initialize an allocator with the resource properties if no error was returned */\r
- Rm_createAndInitAllocator(rmInst, resourceName, &resourceProperties);\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);\r
- if (error < -FDT_ERR_NOTFOUND)\r
- {\r
- return (error);\r
+ else {\r
+ retVal = RM_SERVICE_DENIED_INVALID_RESOURCE_RANGE;\r
}\r
}\r
- else if (offset != -FDT_ERR_NOTFOUND)\r
- {\r
- /* Error was returned by LIBFDT when parsing the nodes */\r
- return (offset);\r
+ else {\r
+ retVal = RM_SERVICE_DENIED_RESOURCE_VALUE_RANGE_DOES_NOT_EXIST;\r
}\r
-\r
- return (RM_DTB_UTIL_RESULT_OKAY);\r
+ return(retVal); \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_integerPreAllocate(Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)\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
-int32_t Rm_integerAllocate(Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)\r
+void Rm_allocationHandler (Rm_Inst *rmInst, Rm_Transaction *transaction, void *validInstNode,\r
+ uint32_t allocType)\r
{\r
- Rm_IntegerAllocatorRootEntry *root = allocator->allocatorRootEntry;\r
- uint16_t resourceIndex, i, j;\r
- bool resourcesValidated = TRUE;\r
- int32_t retVal;\r
+ Rm_AllocatorOpInfo opInfo;\r
+ Rm_NameServerObjCfg nameServerObjCfg;\r
+ int32_t retVal = transaction->state;\r
\r
- /* Find the specified resource base within the allocator */\r
- for (resourceIndex = 0; resourceIndex < root->numResourceElements; resourceIndex++)\r
- {\r
- if (root->resourceArrayBase[resourceIndex].value == opInfo->resourceInfo->base)\r
- {\r
- /* Found the resource base in the allocator. Break from the loop */\r
- break;\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
-\r
- /* Only execute the allocate operation if the resource base was found in the allocator\r
- * and the base+range does not exceed the number of entries in the allocator */\r
- if (resourceIndex + opInfo->resourceInfo->range <= root->numResourceElements)\r
- {\r
- /* Verify all resource values from base to base+range exist in the allocator and\r
- * are not allocated to another instance. */\r
- for (i = resourceIndex, j = opInfo->resourceInfo->base; \r
- i < (resourceIndex + opInfo->resourceInfo->range);\r
- i++, j++)\r
- {\r
- if (root->resourceArrayBase[i].value != j)\r
- {\r
- /* A value in the range did not match. */\r
- retVal = RM_SERVICE_DENIED_RESOURCE_VALUE_IN_RANGE_DOES_NOT_EXIST;\r
- resourcesValidated = FALSE;\r
- break;\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 if (strcmp(root->resourceArrayBase[i].allocatedTo, RM_NOT_ALLOCATED_STRING) != 0)\r
- {\r
- /* A value in the range is already allocated. */\r
- retVal = RM_SERVICE_DENIED_RESOURCE_ALREADY_ALLOCATED;\r
- resourcesValidated = FALSE;\r
- break; \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
- if (resourcesValidated)\r
- {\r
- /* Allocate all resources from base to base+range */\r
- for (i = resourceIndex; i < (resourceIndex + opInfo->resourceInfo->range); i++)\r
- {\r
- strcpy(root->resourceArrayBase[i].allocatedTo, opInfo->srcInstName);\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
- retVal = RM_SERVICE_APPROVED_AND_COMPLETED;\r
+ \r
+ if (retVal == RM_SERVICE_PROCESSING) {\r
+ opInfo.operation = Rm_allocatorOp_ALLOCATE;\r
+ retVal = Rm_allocatorOperation(rmInst, &opInfo);\r
+ } \r
}\r
- }\r
- else\r
- {\r
- retVal = RM_SERVICE_DENIED_RESOURCE_VALUE_IN_RANGE_DOES_NOT_EXIST;\r
- }\r
+ \r
+ transaction->state = retVal;\r
\r
- return(retVal); \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
-int32_t Rm_integerFree(Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)\r
+void Rm_freeHandler (Rm_Inst *rmInst, Rm_Transaction *transaction, void *validInstNode)\r
{\r
- Rm_IntegerAllocatorRootEntry *root = allocator->allocatorRootEntry;\r
- uint16_t resourceIndex, i, j;\r
- bool resourcesValidated = TRUE;\r
- int32_t retVal;\r
+ Rm_AllocatorOpInfo opInfo; \r
+ Rm_NameServerObjCfg nameServerObjCfg; \r
+ int32_t retVal = transaction->state;\r
\r
- /* Find the specified resource base within the allocator */\r
- for (resourceIndex = 0; resourceIndex < root->numResourceElements; resourceIndex++)\r
- {\r
- if (root->resourceArrayBase[resourceIndex].value == opInfo->resourceInfo->base)\r
- {\r
- /* Found the resource base in the allocator. Break from the loop */\r
- break;\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
-\r
- /* Only execute the free operation if the resource base was found in the allocator\r
- * and the base+range does not exceed the number of entries in the allocator */\r
- if (resourceIndex + opInfo->resourceInfo->range <= root->numResourceElements)\r
- {\r
- /* Verify all resource values from base to base+range exist in the allocator,\r
- * were not already free and were allocated to the instance that is the source\r
- * of the free request. */\r
- for (i = resourceIndex, j = opInfo->resourceInfo->base; \r
- i < (resourceIndex + opInfo->resourceInfo->range);\r
- i++, j++)\r
- {\r
- if (root->resourceArrayBase[i].value != j)\r
- {\r
- /* A value in the range did not match. */\r
- retVal = RM_SERVICE_DENIED_RESOURCE_VALUE_IN_RANGE_DOES_NOT_EXIST;\r
- resourcesValidated = FALSE;\r
- break;\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 if (strcmp(root->resourceArrayBase[i].allocatedTo, RM_NOT_ALLOCATED_STRING) == 0)\r
- {\r
- /* A value in the range is already free. */\r
- retVal = RM_SERVICE_DENIED_RESOURCE_ALREADY_FREE;\r
- resourcesValidated = FALSE;\r
- break; \r
- } \r
- else if (strcmp(root->resourceArrayBase[i].allocatedTo, opInfo->srcInstName) != 0)\r
- {\r
- /* A value in the range was not allocated to the source of\r
- * the free request */\r
- retVal = RM_SERVICE_DENIED_RESOURCE_NOT_ALLOCATED_TO_INSTANCE_REQUESTING_THE_SERVICE;\r
- resourcesValidated = FALSE;\r
- break;\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
- if (resourcesValidated)\r
- {\r
- /* Free all resources from base to base+range */\r
- for (i = resourceIndex; i < (resourceIndex + opInfo->resourceInfo->range); i++)\r
- {\r
- strcpy(root->resourceArrayBase[i].allocatedTo, RM_NOT_ALLOCATED_STRING);\r
- }\r
- retVal = RM_SERVICE_APPROVED_AND_COMPLETED;\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
- }\r
- else\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
- retVal = RM_SERVICE_DENIED_RESOURCE_VALUE_IN_RANGE_DOES_NOT_EXIST;\r
+ strcpy(serviceResponse.resourceName, transaction->resourceInfo.name);\r
+ serviceResponse.resourceBase = transaction->resourceInfo.base;\r
+ serviceResponse.resourceLength = transaction->resourceInfo.length;\r
}\r
\r
- return(retVal);\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
-/* 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 */\r
-int32_t Rm_treePreAllocate(Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)\r
+/* Function used to send RM response transactions to lower level agents */\r
+void Rm_transactionResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
{\r
+ Rm_TransportNode *dstTransportNode = NULL;\r
+ Rm_Packet *rmPkt = NULL;\r
\r
-}\r
+ /* Find the transport for the RM instance that sent the request. */\r
+ dstTransportNode = Rm_transportNodeFindRemoteName(rmInst, transaction->pktSrcInstName);\r
\r
-int32_t Rm_treeAllocate(Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)\r
-{\r
- \r
-}\r
+ /* Create a RM packet using the service information */\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_GET_BY_NAME:\r
+ rmPkt = Rm_transportCreateResourceResponsePkt(rmInst, dstTransportNode, \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);\r
+ break;\r
+ default:\r
+ /* Invalid service type. Flag the error and return */\r
+ transaction->state = RM_SERVICE_ERROR_INVALID_SERVICE_TYPE;\r
+ break;\r
+ }\r
\r
-int32_t Rm_treeFree(Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)\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->localId);\r
+ return;\r
+ }\r
\r
+ /* Send the RM packet to the application transport */\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
+ transaction->state = RM_SERVICE_ERROR_TRANPSPORT_SEND_ERROR;\r
+ /* Clean up the packet */\r
+ if (rmInst->transport.rmFreePkt((Rm_TransportHandle) dstTransportNode, rmPkt)) {\r
+ /* Non-NULL value returned by transport packet free. Flag the\r
+ * error */\r
+ transaction->state = RM_SERVICE_ERROR_TRANSPORT_FREE_PKT_ERROR;\r
+ }\r
+ return;\r
+ }\r
+\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
-int32_t Rm_allocatorOperation(Rm_Inst *rmInst, Rm_AllocatorOpInfo *opInfo)\r
+/* Function used to forward RM transactions to higher level agents */\r
+void Rm_transactionForwarder (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
{\r
- Rm_Allocator *allocator = NULL;\r
- int32_t retVal;\r
- void *key;\r
+ Rm_TransportNode *dstTransportNode = NULL;\r
+ Rm_Packet *rmPkt = NULL;\r
\r
- /* Lock access to the RM instance's transaction queue */\r
- key = Rm_osalMtCsEnter();\r
+ /* Make sure the RM instance has a transport registered with a higher level agent */\r
+ if (rmInst->registeredWithDelegateOrServer == false) {\r
+ transaction->state = RM_SERVICE_ERROR_NOT_REGISTERED_WITH_DEL_OR_SERVER;\r
+ return;\r
+ }\r
\r
- /* Get the specified resource's allocator */\r
- allocator = Rm_allocatorFind(rmInst, opInfo->resourceInfo->name);\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 (allocator)\r
- {\r
- /* Call the allocator's type-based allocation function */\r
- if(allocator->type == Rm_allocatorType_INTEGER)\r
- {\r
- if (opInfo->operation == Rm_allocatorOp_PRE_ALLOCATE)\r
- {\r
- retVal = Rm_integerPreAllocateUnspecified(allocator, opInfo);\r
- } \r
- else if (opInfo->operation == Rm_allocatorOp_ALLOCATE)\r
- {\r
- retVal = Rm_integerAllocate(allocator, opInfo);\r
- }\r
- else if (opInfo->operation == Rm_allocatorOp_FREE)\r
- {\r
- retVal = Rm_integerFree(allocator, opInfo);\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
- else if (allocator->type == Rm_allocatorType_TREE)\r
- {\r
- if (opInfo->operation == Rm_allocatorOp_PRE_ALLOCATE)\r
- {\r
- retVal = Rm_treePreAllocateUnspecified(allocator, opInfo);\r
- } \r
- else if (opInfo->operation == Rm_allocatorOp_ALLOCATE)\r
- {\r
- retVal = Rm_treeAllocate(allocator, opInfo);\r
- }\r
- else if (opInfo->operation == Rm_allocatorOp_FREE)\r
- {\r
- retVal = Rm_treeFree(allocator, opInfo);\r
- } \r
- } \r
+ } \r
+ else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {\r
+ dstTransportNode = Rm_transportNodeFindRemoteInstType(rmInst, Rm_instType_SERVER);\r
}\r
- else\r
- {\r
- /* Allocator could not be found for resource */\r
- retVal = RM_SERVICE_DENIED_RESOURCE_DOES_NOT_EXIST;\r
+\r
+ /* Create a RM packet using the service information */\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_GET_BY_NAME:\r
+ rmPkt = Rm_transportCreateResourceReqPkt(rmInst, dstTransportNode, \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);\r
+ break;\r
+ default:\r
+ /* Invalid service type. Flag the error and return */\r
+ transaction->state = RM_SERVICE_ERROR_INVALID_SERVICE_TYPE;\r
+ break;\r
}\r
\r
- Rm_osalMtCsExit(key);\r
- return(retVal);\r
+ if (transaction->state <= RM_SERVICE_ERROR_BASE) {\r
+ /* Return immediately because an error occurred allocating the packet */\r
+ return;\r
+ }\r
+\r
+ /* Send the RM packet to the application transport */\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
+ transaction->state = RM_SERVICE_ERROR_TRANPSPORT_SEND_ERROR;\r
+ /* Clean up the packet */\r
+ if (rmInst->transport.rmFreePkt((Rm_TransportHandle) dstTransportNode, rmPkt)) {\r
+ /* Non-NULL value returned by transport packet free. Flag the\r
+ * error */\r
+ transaction->state = RM_SERVICE_ERROR_TRANSPORT_FREE_PKT_ERROR;\r
+ }\r
+ return;\r
+ }\r
+\r
+ /* Transaction is not deleted because it is awaiting a response from the higher level\r
+ * RM instance */\r
}\r
\r
-void Rm_allocationHandler (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
+void Rm_transactionProcessor (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
{\r
- if (rmInst->instType == Rm_instType_CLIENT_DELEGATE)\r
- {\r
-#if 0 \r
- if (resourceBase is unspecified)\r
- {\r
- while (policy does not approve)\r
- {\r
- Rm_policy check get allowed base as starting point for prealloc\r
- preallocate resource based on the range and alignment\r
- Rm_policy...check\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
- else\r
- {\r
- /* Check local policy to see if the request can be satisfied with the\r
- * resources stored locally */\r
- Rm_policy...API()\r
\r
- if (policy check approves the resource)\r
- {\r
- /* call the allocator to allocate the resource */\r
- if (allocator returns resource)\r
- {\r
- /* Populate the transaction with the allocated resources and the result */\r
- transaction->state = approve reason;\r
- return ...\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
- {\r
- /* allocator ran out of resources, need to contact Server for more\r
- * resources */\r
- Rm_resourcePoolModRequest(...);\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
- else if (policy check denies resource)\r
- {\r
- /* Policy check denied resource. */\r
- transaction->state= deny reason;\r
- return ...\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
+int32_t Rm_findAndReserveLinuxResource(Rm_Inst *rmInst, const char *resourceName, void *linuxDtb, \r
+ Rm_LinuxAlias *linuxAlias)\r
+{\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 if (policy check says forward to Server for validation)\r
- {\r
- /* Forward the transaction to the Server */\r
- Rm_transactionForwarder(rmInst, transaction);\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
-#endif \r
+\r
+ if (retVal < RM_DTB_UTIL_RESULT_OKAY) {\r
+ break;\r
+ }\r
+ linuxAlias = (Rm_LinuxAlias *) linuxAlias->nextLinuxAlias;\r
}\r
- else if (rmInst->instType == Rm_instType_SERVER)\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
-#if 0 \r
- if (resourceBase is unspecified)\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
- while (policy does not approve)\r
- {\r
- Rm_policy check get allowed base as starting point for prealloc\r
- preallocate resource based on the range and alignment\r
- Rm_policy...check\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
- else\r
+ }\r
+ \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
- /* Check global policy to see if resource can be allocated. return result\r
- * no matter what */\r
- Rm_policy...API()\r
+ nsAssignments = Rm_resourceExtractNsAssignment(resourceProperties->nsAssignData, \r
+ resourceProperties->nsAssignLen);\r
\r
- if (policy approves)\r
+ /* Cycle through the list of assignments and add them to the NameServer */\r
+ nsAssignmentBasePtr = nsAssignments;\r
+ while (nsAssignments)\r
{\r
- /* call allocator to allocate resource */\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
- transaction->state = approve or deny reason;\r
- transaction->resourceInfo.base = ...;\r
- transaction->resourceInfo.range = ...;\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
- /* If source instance name does not match the current instance\r
- * name the allocation request came from a Client. The result\r
- * must be sent back to the Client */\r
- if (strcmp(transaction->sourceInstName, rmInst->name))\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
+ propertyType = Rm_resourceGetPropertyType(propertyName);\r
+ if (propertyType == Rm_resourcePropType_RESOURCE_RANGE)\r
+ {\r
+ if (propertyInfo->rangeData || propertyInfo->rangeLen)\r
{\r
- /* Names don't match. Send the transaction back to the Client */\r
- Rm_transactionResponder(rmInst, transaction);\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
- /* Resource allocation request originated locally on the active\r
- * instance. Send the response via the service responder. */ \r
- Rm_serviceResponder(rmInst, transaction); \r
+ propertyInfo->rangeData = propertyData;\r
+ propertyInfo->rangeLen = propertyLen;\r
}\r
}\r
-#endif \r
- } \r
-}\r
-\r
-void Rm_freeHandler (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
-{\r
- if (rmInst->instType == Rm_instType_CLIENT_DELEGATE)\r
- {\r
-#if 0 \r
- /* Check local policy to see if the request can be satisfied with the\r
- * resources stored locally */\r
- Rm_policy...API()\r
-\r
- if (policy check approves the free)\r
+ else if (propertyType == Rm_resourcePropType_NSASSIGNMENT)\r
{\r
- /* call the allocator to free the resource */\r
- /* Run a resource pool check to see if the free combined a resource block\r
- * that can be returned to the server */\r
- if (resource block has been combined)\r
+ if (propertyInfo->nsAssignData || propertyInfo->nsAssignLen)\r
{\r
- /* allocator ran out of resources, need to contact Server for more\r
- * resources */\r
- Rm_resourcePoolModRequest(free pool block to server...);\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
- /* Populate the receipt with the freed resources and the result */\r
- transaction->state = approve reason;\r
- return ...\r
+ propertyInfo->nsAssignData = propertyData;\r
+ propertyInfo->nsAssignLen = propertyLen;\r
}\r
}\r
- else if (policy check denies resource free)\r
+ else if (propertyType == Rm_resourcePropType_RESOURCE_LINUX_ALIAS)\r
{\r
- /* Policy check denied resource. */\r
- transaction->state = deny reason;\r
- return ...\r
- }\r
- else if (policy check says forward to Server for validation)\r
- {\r
- /* Forward the transaction to the Server */\r
- Rm_transactionForwarder(rmInst, transaction);\r
- }\r
-#endif \r
- }\r
- else if (rmInst->instType == Rm_instType_SERVER)\r
- {\r
-#if 0 \r
- /* Check global policy to see if resource can be freed. return result\r
- * no matter what */\r
- Rm_policy...API()\r
- if (policy approves)\r
- {\r
- /* call allocator to free resources */\r
- }\r
- \r
- transaction->state = approve or deny reason;\r
- transaction->resourceInfo.base = ...;\r
- transaction->resourceInfo.range = ...;\r
-\r
- /* If source instance name does not match the current instance\r
- * name the allocation request came from a client. The result\r
- * must be sent back to the Client */\r
- if (strcmp(transaction->sourceInstName, rmInst->name))\r
- {\r
- /* Names don't match. Send the transaction back to the Client Delegate or Client */\r
- Rm_transactionResponder(rmInst, transaction);\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
- /* Resource allocation request originated locally on the active\r
- * instance. Send the response via the service responder. */\r
- Rm_serviceResponder(rmInst, transaction); \r
+ retVal = -20; /* TEMP ERROR: Can't conflict with LIBFDT errors */\r
}\r
-#endif \r
- } \r
-}\r
-\r
-/* Function used to forward RM transactions to higher level agents */\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
- 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 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
- {\r
- dstTransportNode = Rm_transportNodeFindRemoteInstType(rmInst, Rm_instType_CLIENT_DELEGATE);\r
- } \r
- else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE)\r
- {\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
- case Rm_service_RESOURCE_FREE:\r
- case Rm_service_RESOURCE_BLOCK_FREE:\r
- case Rm_service_RESOURCE_FREE_BY_NAME:\r
- rmPkt = Rm_transportCreateResourceReqPkt(rmInst, dstTransportNode, \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);\r
- break;\r
- default:\r
- /* Invalid service type. Flag the error and return */\r
- transaction->state = RM_SERVICE_ERROR_INVALID_SERVICE_TYPE;\r
- break;\r
}\r
-\r
- if (transaction->state <= RM_SERVICE_ERROR_BASE)\r
+ else\r
{\r
- /* Return immediately because an error occurred allocating the packet */\r
- return;\r
+ retVal = -16; /* TEMP ERROR: Can't conflict with LIBFDT errors */\r
}\r
\r
- /* Send the RM packet to the application transport */\r
- if (rmInst->transport.rmSend((Rm_TransportHandle) dstTransportNode, rmPkt) < RM_TRANSPORT_SUCCESSFUL)\r
+ /* Don't get anymore properties if error occurred */\r
+ if (retVal == RM_DTB_UTIL_RESULT_OKAY)\r
{\r
- /* Negative value returned by transport send. An error occurred\r
- * in the transport while attempting to send the packet.*/\r
- transaction->state = RM_SERVICE_ERROR_TRANPSPORT_SEND_ERROR;\r
- /* Clean up the packet */\r
- if (rmInst->transport.rmFreePkt((Rm_TransportHandle) dstTransportNode, rmPkt))\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
- /* Non-NULL value returned by transport packet free. Flag the\r
- * error */\r
- transaction->state = RM_SERVICE_ERROR_TRANSPORT_FREE_PKT_ERROR;\r
+ /* Error was returned by LIBFDT when parsing the properties */\r
+ retVal = offset;\r
}\r
- return;\r
}\r
-\r
- /* Transaction is not deleted because it is awaiting a response from the higher level\r
- * RM instance */\r
+ \r
+ return (retVal);\r
}\r
\r
-void Rm_transactionProcessor (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
+int32_t Rm_parseResourceNode(Rm_Inst *rmInst, void *globalResourceDtb, int32_t nodeOffset, int32_t depth,\r
+ void *linuxDtb)\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_UNMAP_NAME)))\r
- {\r
- /* Check if the transaction is a transaction that received a response to its\r
- * request. */\r
- if (transaction->state != RM_SERVICE_PROCESSING)\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
- /* A transaction has received a response. Send the response to either the \r
- * transaction or service responder based on the source instance */\r
- if (strcmp(transaction->sourceInstName, rmInst->name))\r
- {\r
- /* Transaction originated from another instance. Use the \r
- * transaction responder to send the result to the source instance. This\r
- * is not possible on RM Clients since they can't forward RM services */\r
- Rm_transactionResponder(rmInst, transaction);\r
- }\r
- else\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
- /* Transaction originated on this instance. Send to the\r
- * service responder */\r
- Rm_serviceResponder(rmInst, transaction);\r
+ return (error);\r
}\r
- }\r
- else\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
- /* This is a new transaction that must be forwarded to a higher level RM instance. */\r
- Rm_transactionForwarder(rmInst, transaction);\r
+ /* Error was returned by LIBFDT when parsing the properties */\r
+ return (offset);\r
}\r
}\r
- else\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
- /* Client Delegate and Server transaction processors. */\r
- switch (transaction->type)\r
+ error = Rm_parseResourceNode(rmInst, globalResourceDtb, offset, depth, linuxDtb);\r
+ if (error < -FDT_ERR_NOTFOUND)\r
{\r
- case Rm_service_RESOURCE_ALLOCATE:\r
- case Rm_service_RESOURCE_BLOCK_ALLOCATE:\r
- case Rm_service_RESOURCE_ALLOCATE_BY_NAME:\r
- case Rm_service_RESOURCE_FREE:\r
- case Rm_service_RESOURCE_BLOCK_FREE:\r
- case Rm_service_RESOURCE_FREE_BY_NAME: \r
- /* Check if the transaction is fulfilled request */\r
- if (transaction->state != RM_SERVICE_PROCESSING)\r
- {\r
- /* If source instance name does not match the current instance\r
- * name the allocation request came from a client. The result\r
- * must be sent back to the Client */\r
- if (strcmp(transaction->sourceInstName, rmInst->name))\r
- {\r
- Rm_transactionResponder(rmInst, transaction);\r
- }\r
- else\r
- {\r
- /* Resource allocation request originated locally. Send the response\r
- * via the service responder. */\r
- Rm_serviceResponder(rmInst, transaction); \r
- }\r
- }\r
- else\r
- {\r
- /* This is a new transaction request originating from an RM instance with fewer\r
- * allocate/free privileges. Run the allocation or free handler to see if the resource\r
- * request can be handled locally or if it needs to be forwarded to a higher level\r
- * agent */\r
- if ((transaction->type == Rm_service_RESOURCE_ALLOCATE) ||\r
- (transaction->type == Rm_service_RESOURCE_BLOCK_ALLOCATE) ||\r
- (transaction->type == Rm_service_RESOURCE_ALLOCATE_BY_NAME))\r
- {\r
- Rm_allocationHandler(rmInst, transaction);\r
- }\r
- else\r
- {\r
- Rm_freeHandler(rmInst, transaction);\r
- }\r
- }\r
- break;\r
- case Rm_service_RESOURCE_MAP_TO_NAME:\r
- case Rm_service_RESOURCE_UNMAP_NAME: \r
- /* Server is the only RM instance capable of adding NameServer objects */\r
- if (rmInst->instType == Rm_instType_SERVER)\r
- {\r
- if (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME)\r
- {\r
- /* Create a new NameServer object with the request transaction information.\r
- * Transaction will contain the state result of the NameServer addition. */\r
- if (Rm_nsAddObject(rmInst, transaction->resourceInfo.nsName,\r
- transaction->resourceInfo.base) == RM_NS_ACTION_APPROVED)\r
- {\r
- transaction->state = RM_SERVICE_APPROVED_AND_COMPLETED;\r
- }\r
- else\r
- {\r
- /* TEMP: UPDATE THIS STATE VALUE */\r
- transaction->state = RM_SERVICE_DENIED_BEGIN;\r
- }\r
- }\r
- else\r
- {\r
- /* Delete an existing NameServer object with the request transaction information\r
- * Transaction will contain the state result of the NameServer addition. */\r
- if (Rm_nsDeleteObject(rmInst, transaction->resourceInfo.nsName) == \r
- RM_NS_ACTION_APPROVED)\r
- {\r
- transaction->state = RM_SERVICE_APPROVED_AND_COMPLETED;\r
- }\r
- else\r
- {\r
- /* TEMP: UPDATE THIS STATE VALUE */\r
- transaction->state = RM_SERVICE_DENIED_BEGIN;\r
- }\r
- }\r
-\r
- /* If source instance name does not match the local instance\r
- * name the NameServer request came from a Client or Client Delegate. The \r
- * result must be sent back to the Client or Client Delegate. Just return if it does\r
- * match since the NameServer transaction result can be returned immediately by the\r
- * Rm_serviceHandler. */\r
- if (strcmp(transaction->sourceInstName, rmInst->name))\r
- {\r
- Rm_transactionResponder(rmInst, transaction);\r
- }\r
- }\r
- else\r
- {\r
- transaction->state = RM_SERVICE_ERROR_NAMESERVER_OBJECT_MOD_ON_INVALID_INSTANCE;\r
- }\r
- break;\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)\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
\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);\r
+ result = Rm_parseResourceNode(rmInst, globalResourceDtb, nodeOffset, startDepth, linuxDtb);\r
\r
return(result);\r
}\r
- \r
-int32_t Rm_reserveLinuxResources(Rm_Inst *rmInst, void *linuxResourceDtb)\r
+ \r
+/**********************************************************************\r
+ ********************** Application visible APIs **********************\r
+ **********************************************************************/\r
+\r
+/* Server Only */\r
+void Rm_printResourceStatus(Rm_Handle *rmHandle)\r
{\r
- return(0);\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
+ 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
-/**********************************************************************\r
- ********************** Application visible APIs **********************\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)\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 *globalResourceDtb = NULL;\r
+ void *linuxResourceDtb = NULL;\r
+ void *policyDtb = NULL;\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
+ *result = RM_INIT_OK;\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
- /* Get memory for RM instance from local memory */\r
+\r
+ /* Create and initialize instance */\r
rmInst = Rm_osalMalloc (sizeof(Rm_Inst));\r
- /* Populate instance based on input parameters */\r
- strcpy (&rmInst->name[0], initCfg->instName);\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->policyDtb = NULL;\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 allocators linked list pointer to NULL. The linked list nodes will\r
- * be created on the Server instance when the application reads in the resource list.\r
- * Nodes will also be created on Client Delegates when blocks of resources are requested\r
- * for allocation to clients. */\r
rmInst->allocators = NULL;\r
-\r
- /* Initialize the transaction queue elements. */\r
+ rmInst->nameServer = NULL;\r
+ rmInst->policy = NULL;\r
+ rmInst->validInstances = NULL;\r
rmInst->transactionSeqNum = Rm_transactionInitSequenceNum();\r
rmInst->transactionQueue= NULL;\r
\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
/* RM Server specific actions */\r
- if (rmInst->instType == Rm_instType_SERVER)\r
- {\r
- /* Open the ResourceList file and provide it to the resource initializer. */\r
- if (initCfg->globalResourceList)\r
- {\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
- Rm_initializeAllocators(rmInst, globalResourceDtb);\r
- }\r
+ fdt_open_into(globalResourceDtb, globalResourceDtb, fdt_totalsize(globalResourceDtb));\r
\r
- /* Parse the Linux DTB for the resources reserved by the Linux kernel. These resources\r
- * will be marked as used in the resource allocators. */\r
- if (initCfg->linuxDtb)\r
- {\r
- linuxResourceDtb = initCfg->linuxDtb;\r
- fdt_open_into(linuxResourceDtb, linuxResourceDtb, fdt_totalsize(linuxResourceDtb)); \r
- Rm_reserveLinuxResources(rmInst, linuxResourceDtb);\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
- /* Instance startup policies are only used for Servers and Client Delegates */\r
- if (rmInst->instType != Rm_instType_CLIENT)\r
- {\r
- /* Open the instance's policy and store it */\r
- if (initCfg->startupPolicy)\r
- {\r
- rmInst->policyDtb = initCfg->startupPolicy;\r
- fdt_open_into(rmInst->policyDtb, rmInst->policyDtb, fdt_totalsize(rmInst->policyDtb)); \r
- }\r
-\r
- /* Store policy via policy APIs ... */\r
- }\r
+ if ((rmInst->instType != Rm_instType_CLIENT) && initCfg->policy) {\r
+ *result = Rm_policyValidatePolicyResourceNames(rmInst, policyDtb);\r
+ } \r
\r
- /* Return the RM Handle */\r
return ((Rm_Handle) rmInst);\r
}\r
\r