summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (from parent 1: 20ad26c)
raw | patch | inline | side by side (from parent 1: 20ad26c)
author | Justin Sobota <jsobota@ti.com> | |
Fri, 14 Dec 2012 00:02:52 +0000 (19:02 -0500) | ||
committer | Justin Sobota <jsobota@ti.com> | |
Fri, 14 Dec 2012 00:02:52 +0000 (19:02 -0500) |
include/rm_dtb_utilloc.h | patch | blob | history | |
include/rm_loc.h | patch | blob | history | |
src/rm.c | patch | blob | history | |
src/rm_dtb_util.c | patch | blob | history | |
test/rm_test.c | patch | blob | history |
index 3b49c0de4abaabaf9116828d09605dfeb37ea127..7405b782458914d56b3f2cfeeede2495ff097b91 100644 (file)
--- a/include/rm_dtb_utilloc.h
+++ b/include/rm_dtb_utilloc.h
} Rm_ResourcePropType;
typedef struct {
- char *pathList;
+ const char *pathList;
uint32_t pathListLenBytes;
- uint32_t base;
- uint32_t length;
+ uint32_t baseOffset;
+ uint32_t lengthOffset;
void *nextLinuxAlias;
} Rm_LinuxAlias;
@@ -155,6 +155,18 @@ void Rm_policyFreeAllocationSizesPropList(Rm_AllocationSize *allocationSizeList)
Rm_AssignedNsNames *Rm_policyExtractAssignedNsNames(const void *dtbDataPtr, int32_t dtbDataLen);
void Rm_policyFreeAssignmentNsNamesList(Rm_AssignedNsNames *assignedNsNamesList);
+/**********************************************************************
+ ****************Linux DTB Parsing Defines and Functions***************
+ **********************************************************************/
+
+typedef struct {
+ uint32_t value;
+ void *nextValue;
+} Rm_LinuxValueRange;
+
+Rm_LinuxValueRange *Rm_linuxExtractValues(const void *dtbDataPtr, int32_t dtbDataLen);
+void Rm_linuxFreeValues(Rm_LinuxValueRange *valueList);
+
#ifdef __cplusplus
}
#endif
diff --git a/include/rm_loc.h b/include/rm_loc.h
index 4b5f4ebc13a634ad219a839ecf91081a2e266a59..322c7e244c4208369c61ba48421e55f9002b214b 100644 (file)
--- a/include/rm_loc.h
+++ b/include/rm_loc.h
* resource is allocated the allocatedTo field will be populated with the RM instance
* name it was allocated to. */
#define RM_NOT_ALLOCATED_STRING "\0"
+/** String stored for resource elements that are reserved by the Linux kernel. These
+ * resources will be in use for the lifetime of the system */
+#define RM_ALLOCATED_TO_LINUX "Linux-Kernel"
/** Maximum size of a transmittable RM policy in bytes */
#define RM_MAX_POLICY_SIZE_BYTES (64) // Placeholder: This will change
diff --git a/src/rm.c b/src/rm.c
index 5096e1d485eccb63f4819f9c3b3f2a23b3cdc93c..32be8a8f04fc7508708753bcd4c0267f919304d7 100644 (file)
--- a/src/rm.c
+++ b/src/rm.c
@@ -545,6 +545,228 @@ int32_t Rm_createIntegerAllocator(Rm_Inst *rmInst, const char *resourceName, Rm_
return(0); /* TODO: FIX THIS RETURN */\r
}\r
\r
+/* Called when an allocate request is made but the base is unspecified. RM must preallocate\r
+ * resources which then must be checked against the RM policy for the instance. If the\r
+ * policy does not agree another resource(s) must be preallocated and tested against the \r
+ * policy. Policy will provide initialize the preallocate with the base that it allows\r
+ * for the rm instance for the specified resource. */\r
+int32_t Rm_integerPreAllocate(Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)\r
+{\r
+ Rm_IntegerAllocatorRootEntry *root = allocator->allocatorRootEntry;\r
+ Rm_IntegerEntry *resourceArray = root->resourceArrayBase;\r
+ uint16_t index, i;\r
+ bool resourcesValidated;\r
+ int32_t retVal = RM_SERVICE_PROCESSING;\r
+\r
+ /* Find the specified resource base within the allocator */\r
+ for (index = 0; index < root->numResourceElements; index++)\r
+ {\r
+ if (resourceArray[index].value == opInfo->resourceInfo->base)\r
+ {\r
+ /* Found the resource base in the allocator. Break from the loop */\r
+ break;\r
+ }\r
+ } \r
+\r
+ /* Only execute the allocate operation if the resource base was found in the allocator\r
+ * and the base+length does not exceed the number of entries in the allocator */\r
+ if ((index + opInfo->resourceInfo->length) <= root->numResourceElements)\r
+ {\r
+ /* Search for a contiguous block of unallocated resources of length "length"\r
+ * and with the alignment specified */\r
+ while ((index + opInfo->resourceInfo->length) <= root->numResourceElements)\r
+ {\r
+ resourcesValidated = FALSE; \r
+ \r
+ /* Does the resource base value satisfy the alignment? */\r
+ if ((resourceArray[index].value % opInfo->resourceInfo->alignment) == 0)\r
+ {\r
+ /* Check to see all the resource values in the requested range are free */\r
+ resourcesValidated = TRUE;\r
+ for (i = index; i < opInfo->resourceInfo->length; i++)\r
+ {\r
+ if (strcmp(resourceArray[i].allocatedTo, RM_NOT_ALLOCATED_STRING) != 0)\r
+ {\r
+ /* A resource within the range was already allocated. Update the\r
+ * index to the resource after the allocated resource and continue \r
+ * looking. */\r
+ index = i + 1;\r
+ resourcesValidated = FALSE;\r
+ /* Break out of the for loop */\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (resourcesValidated)\r
+ {\r
+ /* Found a set of resources that satisfies the request requirements. Return\r
+ * the results to be tested against the policy. If the policy approves the\r
+ * resources will be allocated via the Rm_integerAllocate API. */\r
+ opInfo->resourceInfo->base = resourceArray[index].value;\r
+ /* Break out of the while loop */\r
+ break;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ /* Jump to the next resource value that satisfies the alignment */\r
+ for (; index < root->numResourceElements; index++)\r
+ {\r
+ if ((resourceArray[index].value % opInfo->resourceInfo->alignment) == 0)\r
+ {\r
+ /* Found the next resource value that satisfies the alignment */\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ if (!resourcesValidated)\r
+ {\r
+ retVal = RM_SERVICE_DENIED_RESOURCE_VALUE_RANGE_DOES_NOT_EXIST;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ retVal = RM_SERVICE_DENIED_RESOURCE_VALUE_RANGE_DOES_NOT_EXIST;\r
+ }\r
+\r
+ return(retVal); \r
+}\r
+\r
+/* Assumes resource range for allocation has already been approved by the policy */\r
+int32_t Rm_integerAllocate(Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)\r
+{\r
+ Rm_IntegerAllocatorRootEntry *root = allocator->allocatorRootEntry;\r
+ uint16_t resourceIndex, i, j;\r
+ bool resourcesValidated = TRUE;\r
+ int32_t retVal;\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
+ }\r
+\r
+ /* Only execute the allocate operation if the resource base was found in the allocator\r
+ * and the base+length does not exceed the number of entries in the allocator */\r
+ if ((resourceIndex + opInfo->resourceInfo->length) <= root->numResourceElements)\r
+ {\r
+ /* Verify all resource values from base to base+length 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->length);\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_RANGE_DOES_NOT_EXIST;\r
+ resourcesValidated = FALSE;\r
+ break;\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
+ }\r
+ }\r
+\r
+ if (resourcesValidated)\r
+ {\r
+ /* Allocate all resources from base to base+length */\r
+ for (i = resourceIndex; i < (resourceIndex + opInfo->resourceInfo->length); i++)\r
+ {\r
+ strcpy(root->resourceArrayBase[i].allocatedTo, opInfo->srcInstName);\r
+ }\r
+ retVal = RM_SERVICE_APPROVED_AND_COMPLETED;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ retVal = RM_SERVICE_DENIED_RESOURCE_VALUE_RANGE_DOES_NOT_EXIST;\r
+ }\r
+\r
+ return(retVal); \r
+}\r
+\r
+/* Assumes resource range for free has already been approved by the policy */\r
+int32_t Rm_integerFree(Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)\r
+{\r
+ Rm_IntegerAllocatorRootEntry *root = allocator->allocatorRootEntry;\r
+ uint16_t resourceIndex, i, j;\r
+ bool resourcesValidated = TRUE;\r
+ int32_t retVal;\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
+ }\r
+\r
+ /* Only execute the free operation if the resource base was found in the allocator\r
+ * and the base+length does not exceed the number of entries in the allocator */\r
+ if ((resourceIndex + opInfo->resourceInfo->length) <= root->numResourceElements)\r
+ {\r
+ /* Verify all resource values from base to base+length 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->length);\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_RANGE_DOES_NOT_EXIST;\r
+ resourcesValidated = FALSE;\r
+ break;\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
+ }\r
+ }\r
+\r
+ if (resourcesValidated)\r
+ {\r
+ /* Free all resources from base to base+length */\r
+ for (i = resourceIndex; i < (resourceIndex + opInfo->resourceInfo->length); i++)\r
+ {\r
+ strcpy(root->resourceArrayBase[i].allocatedTo, RM_NOT_ALLOCATED_STRING);\r
+ }\r
+ retVal = RM_SERVICE_APPROVED_AND_COMPLETED;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ retVal = RM_SERVICE_DENIED_RESOURCE_VALUE_RANGE_DOES_NOT_EXIST;\r
+ }\r
+\r
+ return(retVal);\r
+}\r
+\r
int32_t Rm_createTreeAllocator(Rm_Inst *rmInst, const char *resourceName, Rm_ResourceRange *range)\r
{\r
Rm_Allocator *allocator = NULL;\r
@@ -595,1332 +817,1289 @@ int32_t Rm_createTreeAllocator(Rm_Inst *rmInst, const char *resourceName, Rm_Res
return(0); /* TODO: FIX THIS RETURN */\r
}\r
\r
-int32_t Rm_createAndInitAllocator(Rm_Inst *rmInst, const char *resourceName, \r
- Rm_ResourceProperties *resourceProperties, void *linuxDtb)\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_Allocator *allocator, 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
- Rm_LinuxAlias *linuxAlias = NULL;\r
- Rm_LinuxAlias *linuxAliasBasePtr = NULL;\r
- int32_t retVal = RM_DTB_UTIL_RESULT_OKAY;\r
-\r
- /* TODO: NEED CHECKS FOR VALIDITY OF ALL THE resourceProperties FIELDS */\r
+ Rm_ResourceTreeNode findNode;\r
+ Rm_ResourceTreeNode *matchingNode = NULL;\r
+ uint32_t policyRangeEnd = opInfo->policyBase + opInfo->policyLength - 1;\r
+ uint32_t index;\r
+ bool resourceFound = FALSE;\r
+ int32_t retVal = RM_SERVICE_PROCESSING;\r
\r
- /* Extract the resource properties from the DTB */\r
- allocatorType = Rm_resourceExtractAllocator(resourceProperties->allocatorData, \r
- resourceProperties->allocatorLen);\r
- range = rangeBasePtr = Rm_resourceExtractRange(resourceProperties->rangeData, \r
- resourceProperties->rangeLen);\r
+ /* Find the tree node that contains the first value in the specified policy range. */\r
+ findNode.base = opInfo->policyBase;\r
+ findNode.length = 1;\r
+ matchingNode = RB_FIND(_Rm_ResourceTree, allocator->allocatorRootEntry, &findNode);\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
- }\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
- }\r
-\r
- /* Reserve the resources taken by the Linux kernel specified in the Linux DTB */\r
- linuxAlias = linuxAliasBasePtr = Rm_resourceExtractLinuxAlias(resourceProperties->linuxAliasData,\r
- resourceProperties->linuxAliasLen);\r
- \r
- if (retVal >= RM_DTB_UTIL_RESULT_OKAY)\r
+ if (matchingNode != NULL)\r
{\r
- /* Create entries in the NameServer if any NameServer assignments were specified */\r
- if (resourceProperties->nsAssignData && resourceProperties->nsAssignLen)\r
+ /* Begin searching for an available range of resources starting from the\r
+ * matching node */\r
+ for (index = matchingNode->base; index <= policyRangeEnd;)\r
{\r
- nsAssignments = Rm_resourceExtractNsAssignment(resourceProperties->nsAssignData, \r
- resourceProperties->nsAssignLen);\r
-\r
- /* Cycle through the list of assignments and add them to the NameServer */\r
- nsAssignmentBasePtr = nsAssignments;\r
- while (nsAssignments)\r
+ /* Is the matchingNode free? */\r
+ if (strcmp(matchingNode->allocatedTo, RM_NOT_ALLOCATED_STRING) == 0)\r
{\r
- /* TODO: RETURN IF ANY OF THE ADDS FAIL??? */\r
- Rm_nsAddObject(rmInst, nsAssignments->nsName, nsAssignments->resourceValue);\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_resourceFreeAllocator(allocatorType);\r
- Rm_resourceFreeRange(rangeBasePtr);\r
- Rm_resourceFreeLinuxAlias(linuxAliasBasePtr);\r
-\r
- return(retVal);\r
-}\r
+ uint32_t matchEnd = matchingNode->base + matchingNode->length - 1;\r
\r
-int32_t Rm_parseResourceProperty(void *globalResourceDtb, int32_t offset, Rm_ResourceProperties *propertyInfo)\r
-{\r
- int32_t propertyLen;\r
- const char *propertyName;\r
- const void *propertyData;\r
- Rm_ResourcePropType propertyType;\r
- int32_t retVal = RM_DTB_UTIL_RESULT_OKAY;\r
+ /* Move index to the first resource satisfying the alignment property */\r
+ if ((index % opInfo->policyAlignment) != 0)\r
+ {\r
+ index += (opInfo->policyAlignment - (index % opInfo->policyAlignment));\r
+ }\r
+ \r
+ /* Move through the node's resource range looking for a contiguous set of resources\r
+ * that satisfy the request. */\r
+ while ((index <= matchEnd) && (index <= policyRangeEnd))\r
+ {\r
+ if (((index + opInfo->resourceInfo->length - 1) <= matchEnd) &&\r
+ ((index + opInfo->resourceInfo->length - 1) <= policyRangeEnd))\r
+ {\r
+ /* Found a resource range in the node that satisfies the requirements */\r
+ opInfo->resourceInfo->base = index;\r
+ resourceFound = TRUE;\r
+ break;\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
- }\r
- else\r
- {\r
- propertyInfo->allocatorData = propertyData;\r
- propertyInfo->allocatorLen = propertyLen;\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
+ /* Move index to the next resource value that satisfies the alignment property */\r
+ index += (opInfo->policyAlignment - (index % opInfo->policyAlignment));\r
+ }\r
}\r
- }\r
- else if (propertyType == Rm_resourcePropType_NSASSIGNMENT)\r
- {\r
- if (propertyInfo->nsAssignData || propertyInfo->nsAssignLen)\r
+ \r
+ if (!resourceFound)\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
+ /* Move to the next tree node */\r
+ matchingNode = RB_NEXT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+ if (matchingNode == NULL)\r
+ {\r
+ /* Reached end of tree. Resource range does not exist. Leave the search\r
+ * loop */\r
+ break;\r
+ }\r
+ else\r
+ {\r
+ index = matchingNode->base;\r
+ }\r
}\r
else\r
{\r
- propertyInfo->nsAssignData = propertyData;\r
- propertyInfo->nsAssignLen = propertyLen;\r
+ /* Found a resource range that satisfies the request properties. Break out of the\r
+ * search loop */\r
+ break;\r
}\r
}\r
- else if (propertyType == Rm_resourcePropType_RESOURCE_LINUX_ALIAS)\r
- {\r
- if (propertyInfo->linuxAliasData || propertyInfo->linuxAliasLen)\r
- {\r
- /* The linuxAlias fields have already been populated. Return an error.\r
- * The resource list has specified a property field more than once\r
- * for a resource node */\r
- retVal = -28; /* TEMP ERROR: Can't conflict with LIBFDT errors */\r
- }\r
- else\r
- {\r
- propertyInfo->linuxAliasData = propertyData;\r
- propertyInfo->linuxAliasLen = propertyLen;\r
- }\r
- } \r
- else\r
+\r
+ if (!resourceFound)\r
{\r
- retVal = -20; /* TEMP ERROR: Can't conflict with LIBFDT errors */\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
+ 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
- void *linuxDtb)\r
+/* Assume the policy has already approved of the allocation */\r
+int32_t Rm_treeAllocate(Rm_Allocator *allocator, 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_ResourceTreeNode findNode;\r
+ Rm_ResourceTreeNode *matchingNode = NULL;\r
+ Rm_ResourceTreeNode *leftNode = NULL;\r
+ Rm_ResourceTreeNode *rightNode = NULL;\r
+ uint32_t findEnd, matchingEnd;\r
+ int32_t retVal;\r
\r
- /* Initialize the resource properties structure */\r
- memset((void *)&resourceProperties, 0, sizeof(Rm_ResourceProperties));\r
+ /* Find the tree node that contains the specified resource range */\r
+ findNode.base = opInfo->resourceInfo->base;\r
+ findNode.length = opInfo->resourceInfo->length;\r
+ matchingNode = RB_FIND(_Rm_ResourceTree, allocator->allocatorRootEntry, &findNode);\r
\r
- /* Ignore properties of the base node */\r
- if (strcmp(resourceName, rmDtbStartingNode))\r
- {\r
- /* Get the properties for the resource node if any exist */\r
- offset = fdt_first_property_offset(globalResourceDtb, nodeOffset);\r
- if (offset >= RM_DTB_UTIL_STARTING_NODE_OFFSET)\r
- {\r
- /* Since at least one property exists attempt to parse the property nodes and \r
- * use them to create and initialize a resource allocator */\r
- error = Rm_parseResourceProperty(globalResourceDtb, offset, &resourceProperties);\r
- if (error < -FDT_ERR_NOTFOUND)\r
- {\r
- return (error);\r
- }\r
- \r
- /* Initialize an allocator with the resource properties if no error was returned */\r
- Rm_createAndInitAllocator(rmInst, resourceName, &resourceProperties, linuxDtb);\r
- }\r
- else if (offset != -FDT_ERR_NOTFOUND)\r
- {\r
- /* Error was returned by LIBFDT when parsing the properties */\r
- return (offset);\r
- }\r
- }\r
- \r
- /* Get the next resource node */\r
- offset = fdt_next_node(globalResourceDtb, nodeOffset, &depth);\r
- /* Check the offset and depth of the next node to make sure the current node\r
- * wasn't the last node in the Resource List. A depth less than the depth set\r
- * at the start of the recursion will signal the end of the resource list */\r
- if ((offset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) && (depth >= RM_DTB_UTIL_STARTING_DEPTH))\r
+ if (matchingNode != NULL)\r
{\r
- error = Rm_parseResourceNode(rmInst, globalResourceDtb, offset, depth, linuxDtb);\r
- if (error < -FDT_ERR_NOTFOUND)\r
+ findEnd = findNode.base + findNode.length - 1;\r
+ matchingEnd = matchingNode->base + matchingNode->length - 1;\r
+ \r
+ /* Does the request range fit within the matching nodes entire range? */\r
+ if ((findNode.base >= matchingNode->base) && (findEnd <= matchingEnd))\r
{\r
- return (error);\r
- }\r
- }\r
- else if (offset != -FDT_ERR_NOTFOUND)\r
- {\r
- /* Error was returned by LIBFDT when parsing the nodes */\r
- return (offset);\r
- }\r
-\r
- return (RM_DTB_UTIL_RESULT_OKAY);\r
-}\r
-\r
-/* 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
-{\r
- Rm_IntegerAllocatorRootEntry *root = allocator->allocatorRootEntry;\r
- Rm_IntegerEntry *resourceArray = root->resourceArrayBase;\r
- uint16_t index, i;\r
- bool resourcesValidated;\r
- int32_t retVal = RM_SERVICE_PROCESSING;\r
+ /* Handle requested resource range that is isolated to a single node\r
+ *\r
+ *\r
+ * base0 base0+length0-1\r
+ * |<---------------length0------------------->| => existing node\r
+ * |<---------length1---------->| => requested resources\r
+ * base1 base1+length1-1\r
+ */ \r
+ if (strcmp(matchingNode->allocatedTo, RM_NOT_ALLOCATED_STRING) == 0)\r
+ {\r
+ /* Resources are available - split up the node into potentially\r
+ * three new nodes:\r
+ * left node - free resources to left of newly allocated resources\r
+ * middle node - newly allocated resources that satisfy the request\r
+ * right node - free resources to the right of newly allocated resources\r
+ *\r
+ * There also may be combine possibilities to the left and right of the\r
+ * matching node. Need to extract those as well to check */\r
+ leftNode = RB_PREV(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+ rightNode = RB_NEXT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
\r
- /* Find the specified resource base within the allocator */\r
- for (index = 0; index < root->numResourceElements; index++)\r
- {\r
- if (resourceArray[index].value == opInfo->resourceInfo->base)\r
- {\r
- /* Found the resource base in the allocator. Break from the loop */\r
- break;\r
- }\r
- } \r
+ /* Remove the matching node from the tree and the nodes to the left and\r
+ * right of the matching node. Removing from tree will not\r
+ * wipe any of the base+length data in the node. Can reuse since they won't\r
+ * be freed */\r
+ RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+ if (leftNode)\r
+ {\r
+ RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
+ }\r
+ if (rightNode)\r
+ {\r
+ RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
+ }\r
\r
- /* Only execute the allocate operation if the resource base was found in the allocator\r
- * and the base+length does not exceed the number of entries in the allocator */\r
- if ((index + opInfo->resourceInfo->length) <= root->numResourceElements)\r
- {\r
- /* Search for a contiguous block of unallocated resources of length "length"\r
- * and with the alignment specified */\r
- while ((index + opInfo->resourceInfo->length) <= root->numResourceElements)\r
- {\r
- resourcesValidated = FALSE; \r
- \r
- /* Does the resource base value satisfy the alignment? */\r
- if ((resourceArray[index].value % opInfo->resourceInfo->alignment) == 0)\r
- {\r
- /* Check to see all the resource values in the requested range are free */\r
- resourcesValidated = TRUE;\r
- for (i = index; i < opInfo->resourceInfo->length; i++)\r
+ /* Create the left node if needed. If the bases are equal the matchingNode can\r
+ * be reused as the left bound of the range. */\r
+ if (findNode.base > matchingNode->base)\r
{\r
- if (strcmp(resourceArray[i].allocatedTo, RM_NOT_ALLOCATED_STRING) != 0)\r
+ /* Can the left node be combined with the node to the left of the matching\r
+ * node */\r
+ if (leftNode && (strcmp(leftNode->allocatedTo, opInfo->srcInstName) == 0))\r
{\r
- /* A resource within the range was already allocated. Update the\r
- * index to the resource after the allocated resource and continue \r
- * looking. */\r
- index = i + 1;\r
- resourcesValidated = FALSE;\r
- /* Break out of the for loop */\r
- break;\r
+ /* Combine the left node and what's leftover on the left side of the \r
+ * matchingNode range after the allocation */\r
+ leftNode->length += (findNode.base - matchingNode->base);\r
+ }\r
+ else\r
+ {\r
+ /* Reinsert left node and create a new node to left of range to be allocated */\r
+ if (leftNode)\r
+ {\r
+ RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
+ }\r
+ \r
+ /* New left node attributes:\r
+ * base: base of the matching node\r
+ * length: base of requested resources - base of matching node */\r
+ leftNode = Rm_newResourceTreeNode(matchingNode->base, findNode.base - matchingNode->base,\r
+ RM_NOT_ALLOCATED_STRING);\r
}\r
- }\r
\r
- if (resourcesValidated)\r
- {\r
- /* Found a set of resources that satisfies the request requirements. Return\r
- * the results to be tested against the policy. If the policy approves the\r
- * resources will be allocated via the Rm_integerAllocate API. */\r
- opInfo->resourceInfo->base = resourceArray[index].value;\r
- /* Break out of the while loop */\r
- break;\r
}\r
- }\r
- else\r
- {\r
- /* Jump to the next resource value that satisfies the alignment */\r
- for (; index < root->numResourceElements; index++)\r
+\r
+ /* Create the right node if needed. If the end ranges are equal the matchingNode\r
+ * can be reused as the right bound of the range */\r
+ if (findEnd < matchingEnd)\r
{\r
- if ((resourceArray[index].value % opInfo->resourceInfo->alignment) == 0)\r
+ /* Can the right node be combined with the node to the right of the matching\r
+ * node */\r
+ if (rightNode && (strcmp(rightNode->allocatedTo, opInfo->srcInstName) == 0))\r
{\r
- /* Found the next resource value that satisfies the alignment */\r
- break;\r
+ /* Combine the right node and what's leftover on the right side of the \r
+ * matchingNode range after the allocation */\r
+ rightNode->base = findNode.base + findNode.length;\r
+ rightNode->length += (matchingEnd - findEnd);\r
+ }\r
+ else\r
+ {\r
+ /* Reinsert right node and create a new node to right of range to be allocated */\r
+ if (rightNode)\r
+ {\r
+ RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
+ }\r
+ \r
+ /* New right node attributes:\r
+ * base: base of the requested resources + length of requested resources\r
+ * length: right bound of matching node - right bound of request resources */\r
+ rightNode = Rm_newResourceTreeNode(findNode.base + findNode.length,\r
+ matchingEnd - findEnd, RM_NOT_ALLOCATED_STRING);\r
}\r
}\r
- }\r
- }\r
-\r
- if (!resourcesValidated)\r
- {\r
- retVal = RM_SERVICE_DENIED_RESOURCE_VALUE_RANGE_DOES_NOT_EXIST;\r
- }\r
- }\r
- else\r
- {\r
- retVal = RM_SERVICE_DENIED_RESOURCE_VALUE_RANGE_DOES_NOT_EXIST;\r
- }\r
\r
- return(retVal); \r
-}\r
-\r
-/* Assumes resource range for allocation has already been approved by the policy */\r
-int32_t Rm_integerAllocate(Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)\r
-{\r
- Rm_IntegerAllocatorRootEntry *root = allocator->allocatorRootEntry;\r
- uint16_t resourceIndex, i, j;\r
- bool resourcesValidated = TRUE;\r
- int32_t retVal;\r
+ /* Reinsert the left node into the tree if it was modified or created. */\r
+ if (leftNode)\r
+ {\r
+ RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
+ }\r
+ /* Reinsert the right node into the tree if it was modified or created. */\r
+ if (rightNode)\r
+ {\r
+ RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
+ }\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
- }\r
+ /* Base and length of matching node becomes the base and length of the requested resources */\r
+ matchingNode->base = findNode.base; \r
+ matchingNode->length = findNode.length;\r
+ /* Reserve the resources and insert them into the tree */\r
+ strcpy(matchingNode->allocatedTo, opInfo->srcInstName);\r
+ RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
\r
- /* Only execute the allocate operation if the resource base was found in the allocator\r
- * and the base+length does not exceed the number of entries in the allocator */\r
- if ((resourceIndex + opInfo->resourceInfo->length) <= root->numResourceElements)\r
- {\r
- /* Verify all resource values from base to base+length 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->length);\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_RANGE_DOES_NOT_EXIST;\r
- resourcesValidated = FALSE;\r
- break;\r
+ retVal = RM_SERVICE_APPROVED_AND_COMPLETED;\r
}\r
- else if (strcmp(root->resourceArrayBase[i].allocatedTo, RM_NOT_ALLOCATED_STRING) != 0)\r
+ else\r
{\r
- /* A value in the range is already allocated. */\r
+ /* A resource superset containing the requested range has\r
+ * already been allocated. */\r
retVal = RM_SERVICE_DENIED_RESOURCE_ALREADY_ALLOCATED;\r
- resourcesValidated = FALSE;\r
- break; \r
}\r
}\r
-\r
- if (resourcesValidated)\r
+ else\r
{\r
- /* Allocate all resources from base to base+length */\r
- for (i = resourceIndex; i < (resourceIndex + opInfo->resourceInfo->length); i++)\r
- {\r
- strcpy(root->resourceArrayBase[i].allocatedTo, opInfo->srcInstName);\r
- }\r
- retVal = RM_SERVICE_APPROVED_AND_COMPLETED;\r
+ /* Request ranges that span multiple nodes signify resources are\r
+ * not available because nodes are combined into larger contiguous ranges\r
+ * on resource free operations. */\r
+ retVal = RM_SERVICE_DENIED_RESOURCE_ALREADY_ALLOCATED;\r
}\r
}\r
else\r
{\r
+ /* The requested resources could not be found in the allocator */\r
retVal = RM_SERVICE_DENIED_RESOURCE_VALUE_RANGE_DOES_NOT_EXIST;\r
}\r
\r
- return(retVal); \r
+ return(retVal); \r
}\r
\r
-/* Assumes resource range for free has already been approved by the policy */\r
-int32_t Rm_integerFree(Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)\r
+/* Assume policy has already approved of the free */\r
+int32_t Rm_treeFree(Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)\r
{\r
- Rm_IntegerAllocatorRootEntry *root = allocator->allocatorRootEntry;\r
- uint16_t resourceIndex, i, j;\r
- bool resourcesValidated = TRUE;\r
+ Rm_ResourceTreeNode findNode;\r
+ Rm_ResourceTreeNode *matchingNode = NULL;\r
+ Rm_ResourceTreeNode *leftNode = NULL;\r
+ Rm_ResourceTreeNode *rightNode = NULL;\r
+ bool combineLeft = FALSE;\r
+ bool combineRight = FALSE;\r
+ uint32_t findEnd, matchingEnd;\r
int32_t retVal;\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
- }\r
+ /* Find the tree node that contains the specified resource range */\r
+ findNode.base = opInfo->resourceInfo->base;\r
+ findNode.length = opInfo->resourceInfo->length;\r
+ matchingNode = RB_FIND(_Rm_ResourceTree, allocator->allocatorRootEntry, &findNode);\r
\r
- /* Only execute the free operation if the resource base was found in the allocator\r
- * and the base+length does not exceed the number of entries in the allocator */\r
- if ((resourceIndex + opInfo->resourceInfo->length) <= root->numResourceElements)\r
+ if (matchingNode != NULL)\r
{\r
- /* Verify all resource values from base to base+length 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->length);\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_RANGE_DOES_NOT_EXIST;\r
- resourcesValidated = FALSE;\r
- break;\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
+ findEnd = findNode.base + findNode.length - 1;\r
+ matchingEnd = matchingNode->base + matchingNode->length - 1;\r
+ \r
+ /* Does the free range fit within the matching nodes entire range? It should\r
+ * either be the entire range or a subset set of the found range. (the latter\r
+ * satisfies the case where an entity allocated a contiguous block of resources\r
+ * then attempts to free a contiguous subset of the allocated block. */\r
+ if ((findNode.base >= matchingNode->base) && (findEnd <= matchingEnd))\r
+ { \r
+ if (strcmp(matchingNode->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
- }\r
- }\r
+ /* Resources can be freed */\r
\r
- if (resourcesValidated)\r
- {\r
- /* Free all resources from base to base+length */\r
- for (i = resourceIndex; i < (resourceIndex + opInfo->resourceInfo->length); i++)\r
- {\r
- strcpy(root->resourceArrayBase[i].allocatedTo, RM_NOT_ALLOCATED_STRING);\r
- }\r
- retVal = RM_SERVICE_APPROVED_AND_COMPLETED;\r
- }\r
- }\r
- else\r
- {\r
- retVal = RM_SERVICE_DENIED_RESOURCE_VALUE_RANGE_DOES_NOT_EXIST;\r
- }\r
+ if ((findNode.base == matchingNode->base) && (findEnd == matchingEnd))\r
+ {\r
+ /* Case 1: free range equals allocated matched node exactly. Attempt to combine \r
+ * the range to be freed with the resource nodes to the left and\r
+ * right of the free range.\r
+ *\r
+ * |<--left node-->||<---matched node--->||<--right node-->|\r
+ * |<---free request--->|\r
+ */ \r
\r
- return(retVal);\r
-}\r
+ leftNode = RB_PREV(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+ rightNode = RB_NEXT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
\r
-/* Called when an allocate request is made but the base is unspecified. RM must preallocate\r
- * resources which then must be checked against the RM policy for the instance. If the\r
- * policy does not agree another resource(s) must be preallocated and tested against the \r
- * policy. Policy will provide initialize the preallocate with the base that it allows\r
- * for the rm instance for the specified resource. */\r
-int32_t Rm_treePreAllocate(Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)\r
-{\r
- Rm_ResourceTreeNode findNode;\r
- Rm_ResourceTreeNode *matchingNode = NULL;\r
- uint32_t policyRangeEnd = opInfo->policyBase + opInfo->policyLength - 1;\r
- uint32_t index;\r
- bool resourceFound = FALSE;\r
- int32_t retVal = RM_SERVICE_PROCESSING;\r
+ /* Remove the matching node from the tree and the nodes to the left and\r
+ * right of the matching node. Removing from tree will not\r
+ * wipe any of the base+length data in the node. Can reuse since they won't\r
+ * be freed */\r
+ RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+ if (leftNode)\r
+ {\r
+ RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
+ }\r
+ if (rightNode)\r
+ {\r
+ RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
+ }\r
\r
- /* Find the tree node that contains the first value in the specified policy range. */\r
- findNode.base = opInfo->policyBase;\r
- findNode.length = 1;\r
- matchingNode = RB_FIND(_Rm_ResourceTree, allocator->allocatorRootEntry, &findNode);\r
+ /* See if the left or right or both nodes can be combined with the matching\r
+ * node that will be freed. */\r
+ if (leftNode && (strcmp(leftNode->allocatedTo, RM_NOT_ALLOCATED_STRING) == 0))\r
+ {\r
+ /* Combine the left node and the matching node */\r
+ combineLeft = TRUE;\r
+ }\r
+ if (rightNode && (strcmp(rightNode->allocatedTo, RM_NOT_ALLOCATED_STRING) == 0))\r
+ {\r
+ /* Combine the right node and the matching node */\r
+ combineRight = TRUE;\r
+ }\r
\r
- if (matchingNode != NULL)\r
- {\r
- /* Begin searching for an available range of resources starting from the\r
- * matching node */\r
- for (index = matchingNode->base; index <= policyRangeEnd;)\r
- {\r
- /* Is the matchingNode free? */\r
- if (strcmp(matchingNode->allocatedTo, RM_NOT_ALLOCATED_STRING) == 0)\r
- {\r
- uint32_t matchEnd = matchingNode->base + matchingNode->length - 1;\r
+ /* Perform any combines, insert the leftover nodes, and free any memory associated\r
+ * with any nodes that weren't reinserted into the tree */\r
+ if (combineLeft && combineRight)\r
+ {\r
+ /* Combine all three nodes into the matchingNode. Insert the freed cumulative\r
+ * matching node and delete the memory for the old left and right nodes */\r
+ matchingNode->base = leftNode->base;\r
+ matchingNode->length = leftNode->length + matchingNode->length + rightNode->length;\r
\r
- /* Move index to the first resource satisfying the alignment property */\r
- if ((index % opInfo->policyAlignment) != 0)\r
- {\r
- index += (opInfo->policyAlignment - (index % opInfo->policyAlignment));\r
- }\r
- \r
- /* Move through the node's resource range looking for a contiguous set of resources\r
- * that satisfy the request. */\r
- while ((index <= matchEnd) && (index <= policyRangeEnd))\r
- {\r
- if (((index + opInfo->resourceInfo->length - 1) <= matchEnd) &&\r
- ((index + opInfo->resourceInfo->length - 1) <= policyRangeEnd))\r
+ Rm_freeResourceTreeNode(leftNode);\r
+ Rm_freeResourceTreeNode(rightNode); \r
+ }\r
+ else if (combineLeft)\r
{\r
- /* Found a resource range in the node that satisfies the requirements */\r
- opInfo->resourceInfo->base = index;\r
- resourceFound = TRUE;\r
- break;\r
+ /* Combine the left and matching nodes. Reinsert the right. */\r
+ matchingNode->base = leftNode->base;\r
+ matchingNode->length += leftNode->length;\r
+ \r
+ Rm_freeResourceTreeNode(leftNode);\r
+ RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode); \r
+ }\r
+ else if (combineRight)\r
+ {\r
+ /* Combine the right and matching nodes. Reinsert the left. */\r
+ matchingNode->length += rightNode->length;\r
+ \r
+ Rm_freeResourceTreeNode(rightNode);\r
+ RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
+ }\r
+ else\r
+ {\r
+ /* Combine cannot be performed. Reinsert the left and right nodes then\r
+ * free the matching node and reinsert it */\r
+ RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
+ RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
}\r
\r
- /* Move index to the next resource value that satisfies the alignment property */\r
- index += (opInfo->policyAlignment - (index % opInfo->policyAlignment));\r
- }\r
- }\r
- \r
- if (!resourceFound)\r
- {\r
- /* Move to the next tree node */\r
- matchingNode = RB_NEXT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
- if (matchingNode == NULL)\r
- {\r
- /* Reached end of tree. Resource range does not exist. Leave the search\r
- * loop */\r
- break;\r
+ /* No matter the combine route taken the matching node will always be declared\r
+ * free and reinserted */\r
+ strcpy(matchingNode->allocatedTo, RM_NOT_ALLOCATED_STRING);\r
+ RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode); \r
}\r
else\r
{\r
- index = matchingNode->base;\r
+ /* Case 2: free range is less than range in matched node. Need to split\r
+ * the matched node into three nodes.\r
+ *\r
+ * |<----------matched node---------->|\r
+ * |<---free request--->|\r
+ */ \r
+\r
+ /* Create the left node if needed. If the bases are equal the matchingNode can\r
+ * be reused as the left bound of the range. */\r
+ if (findNode.base > matchingNode->base)\r
+ {\r
+ /* New left node attributes:\r
+ * base: base of the matching node\r
+ * length: base of requested resources - base of matching node */\r
+ leftNode = Rm_newResourceTreeNode(matchingNode->base, findNode.base - matchingNode->base,\r
+ matchingNode->allocatedTo); \r
+ }\r
+\r
+ /* Create the right node if needed. If the end ranges are equal the matchingNode\r
+ * can be reused as the right bound of the range */\r
+ if (findEnd < matchingEnd)\r
+ { \r
+ /* New right node attributes:\r
+ * base: base of the requested resources + length of requested resources\r
+ * length: right bound of matching node - right bound of request resources */\r
+ rightNode = Rm_newResourceTreeNode(findNode.base + findNode.length,\r
+ matchingEnd - findEnd, matchingNode->allocatedTo);\r
+ }\r
+\r
+ /* Insert the left node into the tree if it was created. */\r
+ if (leftNode)\r
+ {\r
+ RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
+ }\r
+ /* Insert the right node into the tree if it was created. */\r
+ if (rightNode)\r
+ {\r
+ RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
+ }\r
+\r
+ /* Base and length of matching node becomes the base and length of the freed resources */\r
+ matchingNode->base = findNode.base; \r
+ matchingNode->length = findNode.length;\r
+ /* Free the resources and insert them into the tree */\r
+ strcpy(matchingNode->allocatedTo, RM_NOT_ALLOCATED_STRING);\r
+ RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
}\r
+\r
+ retVal = RM_SERVICE_APPROVED_AND_COMPLETED;\r
}\r
else\r
{\r
- /* Found a resource range that satisfies the request properties. Break out of the\r
- * search loop */\r
- break;\r
+ /* The matching allocated range to be freed was allocated to a different instance. */\r
+ retVal = RM_SERVICE_DENIED_RESOURCE_NOT_ALLOCATED_TO_INSTANCE_REQUESTING_THE_SERVICE;\r
}\r
- }\r
\r
- if (!resourceFound)\r
+ }\r
+ else\r
{\r
- retVal = RM_SERVICE_DENIED_RESOURCE_ALREADY_ALLOCATED;\r
+ /* Free resource range crosses over node boundaries. This signifies a\r
+ * free of both allocated and unallocated resources since nodes are combined\r
+ * on allocate and free operations if possible. */\r
+ retVal = RM_SERVICE_DENIED_RESOURCE_ALREADY_FREE;\r
}\r
}\r
else\r
{\r
+ /* The free resources could not be found in the allocator */\r
retVal = RM_SERVICE_DENIED_RESOURCE_VALUE_RANGE_DOES_NOT_EXIST;\r
}\r
\r
- return(retVal); \r
+ return(retVal); \r
}\r
\r
-/* Assume the policy has already approved of the allocation */\r
-int32_t Rm_treeAllocate(Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)\r
+int32_t Rm_allocatorOperation(Rm_Inst *rmInst, Rm_AllocatorOpInfo *opInfo)\r
{\r
- Rm_ResourceTreeNode findNode;\r
- Rm_ResourceTreeNode *matchingNode = NULL;\r
- Rm_ResourceTreeNode *leftNode = NULL;\r
- Rm_ResourceTreeNode *rightNode = NULL;\r
- uint32_t findEnd, matchingEnd;\r
+ Rm_Allocator *allocator = NULL;\r
int32_t retVal;\r
+ void *key;\r
\r
- /* Find the tree node that contains the specified resource range */\r
- findNode.base = opInfo->resourceInfo->base;\r
- findNode.length = opInfo->resourceInfo->length;\r
- matchingNode = RB_FIND(_Rm_ResourceTree, allocator->allocatorRootEntry, &findNode);\r
+ /* Lock access to the RM instance's transaction queue */\r
+ key = Rm_osalMtCsEnter();\r
\r
- if (matchingNode != NULL)\r
+ /* Get the specified resource's allocator */\r
+ allocator = Rm_allocatorFind(rmInst, opInfo->resourceInfo->name);\r
+\r
+ if (allocator)\r
{\r
- findEnd = findNode.base + findNode.length - 1;\r
- matchingEnd = matchingNode->base + matchingNode->length - 1;\r
- \r
- /* Does the request range fit within the matching nodes entire range? */\r
- if ((findNode.base >= matchingNode->base) && (findEnd <= matchingEnd))\r
+ /* Call the allocator's type-based allocation function */\r
+ if(allocator->type == Rm_allocatorType_INTEGER)\r
{\r
- /* Handle requested resource range that is isolated to a single node\r
- *\r
- *\r
- * base0 base0+length0-1\r
- * |<---------------length0------------------->| => existing node\r
- * |<---------length1---------->| => requested resources\r
- * base1 base1+length1-1\r
- */ \r
- if (strcmp(matchingNode->allocatedTo, RM_NOT_ALLOCATED_STRING) == 0)\r
+ if (opInfo->operation == Rm_allocatorOp_PRE_ALLOCATE)\r
{\r
- /* Resources are available - split up the node into potentially\r
- * three new nodes:\r
- * left node - free resources to left of newly allocated resources\r
- * middle node - newly allocated resources that satisfy the request\r
- * right node - free resources to the right of newly allocated resources\r
- *\r
- * There also may be combine possibilities to the left and right of the\r
- * matching node. Need to extract those as well to check */\r
- leftNode = RB_PREV(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
- rightNode = RB_NEXT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+ retVal = Rm_integerPreAllocate(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
+ }\r
+ else if (allocator->type == Rm_allocatorType_TREE)\r
+ {\r
+ if (opInfo->operation == Rm_allocatorOp_PRE_ALLOCATE)\r
+ {\r
+ retVal = Rm_treePreAllocate(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\r
+ {\r
+ /* Allocator could not be found for resource */\r
+ retVal = RM_SERVICE_DENIED_RESOURCE_DOES_NOT_EXIST;\r
+ }\r
\r
- /* Remove the matching node from the tree and the nodes to the left and\r
- * right of the matching node. Removing from tree will not\r
- * wipe any of the base+length data in the node. Can reuse since they won't\r
- * be freed */\r
- RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
- if (leftNode)\r
+ Rm_osalMtCsExit(key);\r
+ return(retVal);\r
+}\r
+\r
+void Rm_allocationHandler (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
+ }\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
- RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
+ /* Populate the transaction with the allocated resources and the result */\r
+ transaction->state = approve reason;\r
+ return ...\r
}\r
- if (rightNode)\r
+ else\r
{\r
- RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
+ /* allocator ran out of resources, need to contact Server for more\r
+ * resources */\r
+ Rm_resourcePoolModRequest(...);\r
}\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 (policy check says forward to Server for validation)\r
+ {\r
+ /* Forward the transaction to the Server */\r
+ Rm_transactionForwarder(rmInst, transaction);\r
+ }\r
+ }\r
+#endif \r
+ }\r
+ else if (rmInst->instType == Rm_instType_SERVER)\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
+ }\r
+ else\r
+ {\r
+ /* Check global policy to see if resource can be allocated. return result\r
+ * no matter what */\r
+ Rm_policy...API()\r
\r
- /* Create the left node if needed. If the bases are equal the matchingNode can\r
- * be reused as the left bound of the range. */\r
- if (findNode.base > matchingNode->base)\r
- {\r
- /* Can the left node be combined with the node to the left of the matching\r
- * node */\r
- if (leftNode && (strcmp(leftNode->allocatedTo, opInfo->srcInstName) == 0))\r
- {\r
- /* Combine the left node and what's leftover on the left side of the \r
- * matchingNode range after the allocation */\r
- leftNode->length += (findNode.base - matchingNode->base);\r
- }\r
- else\r
- {\r
- /* Reinsert left node and create a new node to left of range to be allocated */\r
- if (leftNode)\r
- {\r
- RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
- }\r
- \r
- /* New left node attributes:\r
- * base: base of the matching node\r
- * length: base of requested resources - base of matching node */\r
- leftNode = Rm_newResourceTreeNode(matchingNode->base, findNode.base - matchingNode->base,\r
- RM_NOT_ALLOCATED_STRING);\r
- }\r
-\r
- }\r
+ if (policy approves)\r
+ {\r
+ /* call allocator to allocate resource */\r
+ }\r
\r
- /* Create the right node if needed. If the end ranges are equal the matchingNode\r
- * can be reused as the right bound of the range */\r
- if (findEnd < matchingEnd)\r
- {\r
- /* Can the right node be combined with the node to the right of the matching\r
- * node */\r
- if (rightNode && (strcmp(rightNode->allocatedTo, opInfo->srcInstName) == 0))\r
- {\r
- /* Combine the right node and what's leftover on the right side of the \r
- * matchingNode range after the allocation */\r
- rightNode->base = findNode.base + findNode.length;\r
- rightNode->length += (matchingEnd - findEnd);\r
- }\r
- else\r
- {\r
- /* Reinsert right node and create a new node to right of range to be allocated */\r
- if (rightNode)\r
- {\r
- RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
- }\r
- \r
- /* New right node attributes:\r
- * base: base of the requested resources + length of requested resources\r
- * length: right bound of matching node - right bound of request resources */\r
- rightNode = Rm_newResourceTreeNode(findNode.base + findNode.length,\r
- matchingEnd - findEnd, RM_NOT_ALLOCATED_STRING);\r
- }\r
- }\r
+ transaction->state = approve or deny reason;\r
+ transaction->resourceInfo.base = ...;\r
+ transaction->resourceInfo.length = ...;\r
\r
- /* Reinsert the left node into the tree if it was modified or created. */\r
- if (leftNode)\r
- {\r
- RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
- }\r
- /* Reinsert the right node into the tree if it was modified or created. */\r
- if (rightNode)\r
- {\r
- RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\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 */\r
+ Rm_transactionResponder(rmInst, transaction);\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
+ }\r
+ }\r
+#endif \r
+ } \r
+}\r
\r
- /* Base and length of matching node becomes the base and length of the requested resources */\r
- matchingNode->base = findNode.base; \r
- matchingNode->length = findNode.length;\r
- /* Reserve the resources and insert them into the tree */\r
- strcpy(matchingNode->allocatedTo, opInfo->srcInstName);\r
- RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\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
- retVal = RM_SERVICE_APPROVED_AND_COMPLETED;\r
+ if (policy check approves the free)\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
+ {\r
+ /* allocator ran out of resources, need to contact Server for more\r
+ * resources */\r
+ Rm_resourcePoolModRequest(free pool block to server...);\r
}\r
else\r
{\r
- /* A resource superset containing the requested range has\r
- * already been allocated. */\r
- retVal = RM_SERVICE_DENIED_RESOURCE_ALREADY_ALLOCATED;\r
+ /* Populate the receipt with the freed resources and the result */\r
+ transaction->state = approve reason;\r
+ return ...\r
}\r
}\r
- else\r
+ else if (policy check denies resource free)\r
{\r
- /* Request ranges that span multiple nodes signify resources are\r
- * not available because nodes are combined into larger contiguous ranges\r
- * on resource free operations. */\r
- retVal = RM_SERVICE_DENIED_RESOURCE_ALREADY_ALLOCATED;\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\r
+ else if (rmInst->instType == Rm_instType_SERVER)\r
{\r
- /* The requested resources could not be found in the allocator */\r
- retVal = RM_SERVICE_DENIED_RESOURCE_VALUE_RANGE_DOES_NOT_EXIST;\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.length = ...;\r
\r
- return(retVal); \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
+ 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
+ }\r
+#endif \r
+ } \r
}\r
\r
-/* Assume policy has already approved of the free */\r
-int32_t Rm_treeFree(Rm_Allocator *allocator, 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_ResourceTreeNode findNode;\r
- Rm_ResourceTreeNode *matchingNode = NULL;\r
- Rm_ResourceTreeNode *leftNode = NULL;\r
- Rm_ResourceTreeNode *rightNode = NULL;\r
- bool combineLeft = FALSE;\r
- bool combineRight = FALSE;\r
- uint32_t findEnd, matchingEnd;\r
- int32_t retVal;\r
+ Rm_TransportNode *dstTransportNode = NULL;\r
+ Rm_Packet *rmPkt = NULL;\r
\r
- /* Find the tree node that contains the specified resource range */\r
- findNode.base = opInfo->resourceInfo->base;\r
- findNode.length = opInfo->resourceInfo->length;\r
- matchingNode = RB_FIND(_Rm_ResourceTree, allocator->allocatorRootEntry, &findNode);\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
- if (matchingNode != NULL)\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
- findEnd = findNode.base + findNode.length - 1;\r
- matchingEnd = matchingNode->base + matchingNode->length - 1;\r
- \r
- /* Does the free range fit within the matching nodes entire range? It should\r
- * either be the entire range or a subset set of the found range. (the latter\r
- * satisfies the case where an entity allocated a contiguous block of resources\r
- * then attempts to free a contiguous subset of the allocated block. */\r
- if ((findNode.base >= matchingNode->base) && (findEnd <= matchingEnd))\r
- { \r
- if (strcmp(matchingNode->allocatedTo, opInfo->srcInstName) == 0)\r
- {\r
- /* Resources can be freed */\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
- if ((findNode.base == matchingNode->base) && (findEnd == matchingEnd))\r
- {\r
- /* Case 1: free range equals allocated matched node exactly. Attempt to combine \r
- * the range to be freed with the resource nodes to the left and\r
- * right of the free range.\r
- *\r
- * |<--left node-->||<---matched node--->||<--right node-->|\r
- * |<---free request--->|\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
- leftNode = RB_PREV(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
- rightNode = RB_NEXT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+ if (transaction->state <= RM_SERVICE_ERROR_BASE)\r
+ {\r
+ /* Return immediately because an error occurred allocating the packet */\r
+ return;\r
+ }\r
\r
- /* Remove the matching node from the tree and the nodes to the left and\r
- * right of the matching node. Removing from tree will not\r
- * wipe any of the base+length data in the node. Can reuse since they won't\r
- * be freed */\r
- RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
- if (leftNode)\r
- {\r
- RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
- }\r
- if (rightNode)\r
- {\r
- RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\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
- /* See if the left or right or both nodes can be combined with the matching\r
- * node that will be freed. */\r
- if (leftNode && (strcmp(leftNode->allocatedTo, RM_NOT_ALLOCATED_STRING) == 0))\r
- {\r
- /* Combine the left node and the matching node */\r
- combineLeft = TRUE;\r
- }\r
- if (rightNode && (strcmp(rightNode->allocatedTo, RM_NOT_ALLOCATED_STRING) == 0))\r
- {\r
- /* Combine the right node and the matching node */\r
- combineRight = TRUE;\r
- }\r
+ /* Transaction is not deleted because it is awaiting a response from the higher level\r
+ * RM instance */\r
+}\r
\r
- /* Perform any combines, insert the leftover nodes, and free any memory associated\r
- * with any nodes that weren't reinserted into the tree */\r
- if (combineLeft && combineRight)\r
- {\r
- /* Combine all three nodes into the matchingNode. Insert the freed cumulative\r
- * matching node and delete the memory for the old left and right nodes */\r
- matchingNode->base = leftNode->base;\r
- matchingNode->length = leftNode->length + matchingNode->length + rightNode->length;\r
+void Rm_transactionProcessor (Rm_Inst *rmInst, Rm_Transaction *transaction)\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
\r
- Rm_freeResourceTreeNode(leftNode);\r
- Rm_freeResourceTreeNode(rightNode); \r
- }\r
- else if (combineLeft)\r
- {\r
- /* Combine the left and matching nodes. Reinsert the right. */\r
- matchingNode->base = leftNode->base;\r
- matchingNode->length += leftNode->length;\r
- \r
- Rm_freeResourceTreeNode(leftNode);\r
- RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode); \r
- }\r
- else if (combineRight)\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
+ {\r
+ /* Transaction originated on this instance. Send to the\r
+ * service responder */\r
+ Rm_serviceResponder(rmInst, transaction);\r
+ }\r
+ }\r
+ else\r
+ {\r
+ /* This is a new transaction that must be forwarded to a higher level RM instance. */\r
+ Rm_transactionForwarder(rmInst, transaction);\r
+ }\r
+ }\r
+ else\r
+ {\r
+ /* Client Delegate and Server transaction processors. */\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
+ /* 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
- /* Combine the right and matching nodes. Reinsert the left. */\r
- matchingNode->length += rightNode->length;\r
- \r
- Rm_freeResourceTreeNode(rightNode);\r
- RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
+ Rm_transactionResponder(rmInst, transaction);\r
}\r
else\r
{\r
- /* Combine cannot be performed. Reinsert the left and right nodes then\r
- * free the matching node and reinsert it */\r
- RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
- RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
+ /* Resource allocation request originated locally. Send the response\r
+ * via the service responder. */\r
+ Rm_serviceResponder(rmInst, transaction); \r
}\r
-\r
- /* No matter the combine route taken the matching node will always be declared\r
- * free and reinserted */\r
- strcpy(matchingNode->allocatedTo, RM_NOT_ALLOCATED_STRING);\r
- RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode); \r
}\r
else\r
{\r
- /* Case 2: free range is less than range in matched node. Need to split\r
- * the matched node into three nodes.\r
- *\r
- * |<----------matched node---------->|\r
- * |<---free request--->|\r
- */ \r
-\r
- /* Create the left node if needed. If the bases are equal the matchingNode can\r
- * be reused as the left bound of the range. */\r
- if (findNode.base > matchingNode->base)\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
- /* New left node attributes:\r
- * base: base of the matching node\r
- * length: base of requested resources - base of matching node */\r
- leftNode = Rm_newResourceTreeNode(matchingNode->base, findNode.base - matchingNode->base,\r
- matchingNode->allocatedTo); \r
+ Rm_allocationHandler(rmInst, transaction);\r
}\r
-\r
- /* Create the right node if needed. If the end ranges are equal the matchingNode\r
- * can be reused as the right bound of the range */\r
- if (findEnd < matchingEnd)\r
- { \r
- /* New right node attributes:\r
- * base: base of the requested resources + length of requested resources\r
- * length: right bound of matching node - right bound of request resources */\r
- rightNode = Rm_newResourceTreeNode(findNode.base + findNode.length,\r
- matchingEnd - findEnd, matchingNode->allocatedTo);\r
+ else\r
+ {\r
+ Rm_freeHandler(rmInst, transaction);\r
}\r
-\r
- /* Insert the left node into the tree if it was created. */\r
- if (leftNode)\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
- RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\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
- /* Insert the right node into the tree if it was created. */\r
- if (rightNode)\r
+ else\r
{\r
- RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\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
- /* Base and length of matching node becomes the base and length of the freed resources */\r
- matchingNode->base = findNode.base; \r
- matchingNode->length = findNode.length;\r
- /* Free the resources and insert them into the tree */\r
- strcpy(matchingNode->allocatedTo, RM_NOT_ALLOCATED_STRING);\r
- RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\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
-\r
- retVal = RM_SERVICE_APPROVED_AND_COMPLETED;\r
- }\r
- else\r
- {\r
- /* The matching allocated range to be freed was allocated to a different instance. */\r
- retVal = RM_SERVICE_DENIED_RESOURCE_NOT_ALLOCATED_TO_INSTANCE_REQUESTING_THE_SERVICE;\r
- }\r
-\r
- }\r
- else\r
- {\r
- /* Free resource range crosses over node boundaries. This signifies a\r
- * free of both allocated and unallocated resources since nodes are combined\r
- * on allocate and free operations if possible. */\r
- retVal = RM_SERVICE_DENIED_RESOURCE_ALREADY_FREE;\r
+ else\r
+ {\r
+ transaction->state = RM_SERVICE_ERROR_NAMESERVER_OBJECT_MOD_ON_INVALID_INSTANCE;\r
+ }\r
+ break;\r
}\r
}\r
- else\r
- {\r
- /* The free resources could not be found in the allocator */\r
- retVal = RM_SERVICE_DENIED_RESOURCE_VALUE_RANGE_DOES_NOT_EXIST;\r
- }\r
-\r
- return(retVal); \r
}\r
\r
-int32_t Rm_allocatorOperation(Rm_Inst *rmInst, Rm_AllocatorOpInfo *opInfo)\r
+int32_t Rm_reserveLinuxResource(Rm_Inst *rmInst, Rm_LinuxAlias *linuxAlias, \r
+ Rm_LinuxValueRange *linuxValues, Rm_AllocatorOpInfo *opInfo)\r
{\r
- Rm_Allocator *allocator = NULL;\r
- int32_t retVal;\r
- void *key;\r
-\r
- /* Lock access to the RM instance's transaction queue */\r
- key = Rm_osalMtCsEnter();\r
-\r
- /* Get the specified resource's allocator */\r
- allocator = Rm_allocatorFind(rmInst, opInfo->resourceInfo->name);\r
+ int32_t retVal = RM_DTB_UTIL_RESULT_OKAY;\r
+ bool baseFound = FALSE;\r
+ bool lengthFound = FALSE;\r
+ uint32_t valueIndex = 0;\r
\r
- if (allocator)\r
+ while ((linuxValues != NULL) && (!baseFound || !lengthFound))\r
{\r
- /* Call the allocator's type-based allocation function */\r
- if(allocator->type == Rm_allocatorType_INTEGER)\r
+ if (linuxAlias->baseOffset == valueIndex)\r
{\r
- if (opInfo->operation == Rm_allocatorOp_PRE_ALLOCATE)\r
- {\r
- retVal = Rm_integerPreAllocate(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
+ /* Found the resource base. Store it in the operation info structure */\r
+ opInfo->resourceInfo->base = linuxValues->value;\r
+ baseFound = TRUE;\r
+\r
+ /* length will always be 1 if there is no length specified in the Linux DTB */\r
+ if (linuxAlias->lengthOffset == RM_DTB_LINUX_ALIAS_OFFSET_NOT_SET)\r
{\r
- retVal = Rm_integerFree(allocator, opInfo);\r
+ opInfo->resourceInfo->length = 1;\r
+ lengthFound = TRUE;\r
}\r
}\r
- else if (allocator->type == Rm_allocatorType_TREE)\r
+ else if (linuxAlias->lengthOffset == valueIndex)\r
{\r
- if (opInfo->operation == Rm_allocatorOp_PRE_ALLOCATE)\r
- {\r
- retVal = Rm_treePreAllocate(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
+ /* Found the resource length. Store it in the operation info structure */\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
+ {\r
+ retVal = -33; /* TODO: ERROR BASE OR LENGTH OFFSET IN LINUX DTB WAS INCORRECT */\r
}\r
else\r
{\r
- /* Allocator could not be found for resource */\r
- retVal = RM_SERVICE_DENIED_RESOURCE_DOES_NOT_EXIST;\r
+ /* Allocate the resource to Linux */\r
+ retVal = Rm_allocatorOperation(rmInst, opInfo);\r
}\r
\r
- Rm_osalMtCsExit(key);\r
- return(retVal);\r
+ return (retVal);\r
}\r
\r
-void Rm_allocationHandler (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
- }\r
- else\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
+ 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
+ bool foundResource;\r
+ int32_t retVal = RM_DTB_UTIL_RESULT_OKAY; \r
+\r
+ /* Initialize the allocator opInfo and resourceInfo structures that will be used to \r
+ * reserve the resources taken by the Linux kernel */\r
+ memset((void *) &opInfo, 0, sizeof(Rm_AllocatorOpInfo));\r
+ memset((void *) &resourceInfo, 0, sizeof(Rm_ResourceInfo));\r
+\r
+ strcpy(resourceInfo.name, resourceName);\r
+\r
+ opInfo.srcInstName = RM_ALLOCATED_TO_LINUX;\r
+ opInfo.operation = Rm_allocatorOp_ALLOCATE;\r
+ opInfo.resourceInfo = &resourceInfo; \r
+\r
+ /* Find each resource specified in the Linux resource alias list and reserve that \r
+ * resource as used */\r
+ while(linuxAlias != NULL)\r
+ {\r
+ /* Reset the parsing variables */\r
+ foundResource = FALSE;\r
+ pathOffset = 0;\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
+ while(1)\r
{\r
- /* Check local policy to see if the request can be satisfied with the\r
- * resources stored locally */\r
- Rm_policy...API()\r
+ /* Move through the DTB nodes until the next alias path node is found */\r
+ if (strcmp(linuxAlias->pathList + pathOffset, fdt_get_name(linuxDtb, nodeOffset, NULL)))\r
+ {\r
+ nodeOffset = fdt_next_node(linuxDtb, nodeOffset, &depth);\r
\r
- if (policy check approves the resource)\r
+ if (depth < prevDepth)\r
+ {\r
+ /* Returning from subnode that matched part of alias path without finding\r
+ * the resource values */\r
+ retVal = (-31); /* TODO: COULD NOT HAVE RESOURCE AT ALIAS PATH */\r
+ break;\r
+ }\r
+ }\r
+ else\r
{\r
- /* call the allocator to allocate the resource */\r
- if (allocator returns resource)\r
+ /* Found the next alias path node */\r
+ pathOffset += (strlen(linuxAlias->pathList + pathOffset) + 1);\r
+ prevDepth = fdt_node_depth(linuxDtb, nodeOffset);\r
+\r
+ /* Check the properties of the node to see if they match the next alias\r
+ * path string */\r
+ propOffset = fdt_first_property_offset(linuxDtb, nodeOffset);\r
+ if (propOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET)\r
+ { \r
+ /* Search the properties for the next alias path string */\r
+ while (propOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET)\r
+ {\r
+ propertyData = fdt_getprop_by_offset(linuxDtb, propOffset, \r
+ &propertyName, &propertyLen);\r
+\r
+ if (strcmp(linuxAlias->pathList + pathOffset, propertyName) == 0)\r
+ {\r
+ /* Found the alias property. Extract the values that will\r
+ * contain the resource information that must be reserved. */\r
+ linuxValueRange = Rm_linuxExtractValues(propertyData, propertyLen);\r
+ /* Use the values to reserve resources for the Linux kernel */\r
+ retVal = Rm_reserveLinuxResource(rmInst, linuxAlias, \r
+ linuxValueRange, &opInfo);\r
+ \r
+ /* Free the memory used to store the values */\r
+ Rm_linuxFreeValues(linuxValueRange);\r
+\r
+ foundResource = TRUE;\r
+ break;\r
+ }\r
+ \r
+ propOffset = fdt_next_property_offset(linuxDtb, propOffset);\r
+ if (propOffset < -FDT_ERR_NOTFOUND)\r
+ {\r
+ /* Error was returned by LIBFDT when parsing the properties */\r
+ retVal = propOffset;\r
+ break;\r
+ } \r
+ } \r
+ }\r
+\r
+ if (propOffset < -FDT_ERR_NOTFOUND)\r
{\r
- /* Populate the transaction with the allocated resources and the result */\r
- transaction->state = approve reason;\r
- return ...\r
+ /* Error was returned by LIBFDT when parsing the properties */\r
+ retVal = propOffset;\r
+ break;\r
}\r
- else\r
+\r
+ if (foundResource)\r
{\r
- /* allocator ran out of resources, need to contact Server for more\r
- * resources */\r
- Rm_resourcePoolModRequest(...);\r
+ /* Found the resource and reserved it or there was an error\r
+ * trying to reserve it. Break out of the while(1) loop */\r
+ break;\r
}\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 (policy check says forward to Server for validation)\r
- {\r
- /* Forward the transaction to the Server */\r
- Rm_transactionForwarder(rmInst, transaction);\r
- }\r
}\r
-#endif \r
+\r
+ if (retVal < RM_DTB_UTIL_RESULT_OKAY)\r
+ {\r
+ /* Error occurred during parsing of Linux DTB. Return the error */\r
+ break;\r
+ }\r
+ linuxAlias = (Rm_LinuxAlias *) linuxAlias->nextLinuxAlias;\r
}\r
- else if (rmInst->instType == Rm_instType_SERVER)\r
+\r
+ return (retVal);\r
+}\r
+\r
+int32_t Rm_createAndInitAllocator(Rm_Inst *rmInst, const char *resourceName, \r
+ Rm_ResourceProperties *resourceProperties, void *linuxDtb)\r
+{\r
+ char *allocatorType = NULL;\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
+ int32_t retVal = RM_DTB_UTIL_RESULT_OKAY;\r
+\r
+ /* TODO: NEED CHECKS FOR VALIDITY OF ALL THE resourceProperties FIELDS */\r
+\r
+ /* Extract the resource properties from the DTB */\r
+ allocatorType = Rm_resourceExtractAllocator(resourceProperties->allocatorData, \r
+ resourceProperties->allocatorLen);\r
+ range = rangeBasePtr = Rm_resourceExtractRange(resourceProperties->rangeData, \r
+ resourceProperties->rangeLen);\r
+\r
+ /* Create an allocator based on the allocator type specified */\r
+ if (strcmp(allocatorType, &rmIntegerAllocator[0]) == 0)\r
{\r
-#if 0 \r
- if (resourceBase is unspecified)\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
+ }\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
+ }\r
+\r
+ if (retVal >= RM_DTB_UTIL_RESULT_OKAY)\r
+ {\r
+ if (resourceProperties->linuxAliasData && resourceProperties->linuxAliasLen)\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
+ /* 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
- 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
+ /* TODO: RETURN IF ANY OF THE ADDS FAIL??? */\r
+ Rm_nsAddObject(rmInst, nsAssignments->nsName, nsAssignments->resourceValue);\r
+ nsAssignments = nsAssignments->nextNsAssignment;\r
}\r
+ /* Free the memory allocated for the NameServer assignments */\r
+ Rm_resourceFreeNsAssignmentList(nsAssignmentBasePtr);\r
+ }\r
+ }\r
\r
- transaction->state = approve or deny reason;\r
- transaction->resourceInfo.base = ...;\r
- transaction->resourceInfo.length = ...;\r
+ /* Free the memory allocated for the resource properties */\r
+ Rm_resourceFreeAllocator(allocatorType);\r
+ Rm_resourceFreeRange(rangeBasePtr);\r
+ Rm_resourceFreeLinuxAlias(linuxAlias);\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 */\r
- Rm_transactionResponder(rmInst, transaction);\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
- }\r
- }\r
-#endif \r
- } \r
+ return(retVal);\r
}\r
\r
-void Rm_freeHandler (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
+int32_t Rm_parseResourceProperty(void *globalResourceDtb, int32_t offset, Rm_ResourceProperties *propertyInfo)\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
+ 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 (policy check approves the free)\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
- /* 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->allocatorData || propertyInfo->allocatorLen)\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 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
}\r
else\r
{\r
- /* Populate the receipt with the freed resources and the result */\r
- transaction->state = approve reason;\r
- return ...\r
+ propertyInfo->allocatorData = propertyData;\r
+ propertyInfo->allocatorLen = propertyLen;\r
}\r
}\r
- else if (policy check denies resource free)\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
+ else if (propertyType == Rm_resourcePropType_RESOURCE_RANGE)\r
{\r
- /* Forward the transaction to the Server */\r
- Rm_transactionForwarder(rmInst, transaction);\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
-#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
+ else if (propertyType == Rm_resourcePropType_NSASSIGNMENT)\r
{\r
- /* call allocator to free resources */\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
}\r
- \r
- transaction->state = approve or deny reason;\r
- transaction->resourceInfo.base = ...;\r
- transaction->resourceInfo.length = ...;\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
+ else if (propertyType == Rm_resourcePropType_RESOURCE_LINUX_ALIAS)\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, void *linuxDtb)\r
diff --git a/src/rm_dtb_util.c b/src/rm_dtb_util.c
index 3334df2733b96f28baa1050cc0fa27571e185fe1..1c381dc42d7e4187f391130f9fdeab6f6291e85d 100644 (file)
--- a/src/rm_dtb_util.c
+++ b/src/rm_dtb_util.c
@@ -204,7 +204,7 @@ Rm_ResourceRange *Rm_resourceExtractRange(const void *dtbDataPtr, int32_t dtbDat
return(Rm_commonExtractRange(dtbDataPtr, dtbDataLen));
}
-void Rm_resourceFreeResourceRange(Rm_ResourceRange *rangeList)
+void Rm_resourceFreeRange(Rm_ResourceRange *rangeList)
{
Rm_commonFreeRangeList(rangeList);
}
return(Rm_commonExtractName(dtbDataPtr, dtbDataLen));
}
-void Rm_resourceFreeResourceAllocator(char *resourceAllocatorType)
+void Rm_resourceFreeAllocator(char *resourceAllocatorType)
{
Rm_commonFreeName(resourceAllocatorType);
}
@@ -225,13 +225,13 @@ Rm_LinuxAlias *Rm_resourceExtractLinuxAlias(const void *dtbDataPtr, int32_t dtbD
uint8_t *aliasData = (uint8_t *)dtbDataPtr;
uint8_t *pathStart = NULL;
uint32_t pathLenBytes;
- uint32_t nameLenBytes;
+ uint32_t stringLenBytes;
uint32_t extractedValue;
uint8_t *extractedValueBytePtr;
Rm_LinuxAlias *startAlias = NULL;
Rm_LinuxAlias *newAlias = NULL;
Rm_LinuxAlias *prevAlias = NULL;
- int8_t i = 0;
+ uint32_t i = 0;
uint16_t j;
/* Linux aliases are stored in the DTB as a list of null-terminated character
@@ -254,18 +254,18 @@ Rm_LinuxAlias *Rm_resourceExtractLinuxAlias(const void *dtbDataPtr, int32_t dtbD
* path string (adding one for each null character). */
pathStart = aliasData + i;
pathLenBytes = 0;
- while (strcmp((char *)aliasData[i], rmResourceLinuxAliasCompletionString) != 0)
+ while (strcmp((char *)(aliasData + i), rmResourceLinuxAliasCompletionString) != 0)
{
- nameLenBytes = strlen((char *) aliasData[i]) + 1;
- pathLenBytes += nameLenBytes;
- i += nameLenBytes;
+ stringLenBytes = strlen((char *) (aliasData + i)) + 1;
+ pathLenBytes += stringLenBytes;
+ i += stringLenBytes;
}
newAlias->pathList = (char *) Rm_osalMalloc(pathLenBytes);
newAlias->pathListLenBytes = pathLenBytes;
memcpy((void *) newAlias->pathList, (void *)pathStart, pathLenBytes);
/* Skip past the first "end" string */
- i += (strlen((char *) aliasData[i]) + 1);
+ i += (strlen((char *) (aliasData + i)) + 1);
/* Extract the first 32-bit offset */
extractedValueBytePtr = (uint8_t *)&extractedValue;
@@ -274,10 +274,10 @@ Rm_LinuxAlias *Rm_resourceExtractLinuxAlias(const void *dtbDataPtr, int32_t dtbD
extractedValueBytePtr[j] = aliasData[i];
}
/* flip the endianness */
- newAlias->base = fdt32_to_cpu(extractedValue);
+ newAlias->baseOffset = fdt32_to_cpu(extractedValue);
/* Check for the "end" string. Extract the second offset if it isn't there */
- if (strcmp((char *) aliasData[i], rmResourceLinuxAliasCompletionString) != 0)
+ if (strcmp((char *) (aliasData + i), rmResourceLinuxAliasCompletionString) != 0)
{
/* Extract the second 32-bit offset */
extractedValueBytePtr = (uint8_t *)&extractedValue;
@@ -286,15 +286,15 @@ Rm_LinuxAlias *Rm_resourceExtractLinuxAlias(const void *dtbDataPtr, int32_t dtbD
extractedValueBytePtr[j] = aliasData[i];
}
/* flip the endianness */
- newAlias->base = fdt32_to_cpu(extractedValue);
+ newAlias->lengthOffset = fdt32_to_cpu(extractedValue);
}
else
{
- newAlias->length = RM_DTB_LINUX_ALIAS_OFFSET_NOT_SET;
+ newAlias->lengthOffset = RM_DTB_LINUX_ALIAS_OFFSET_NOT_SET;
}
/* Skip past the second "end" string */
- i += (strlen((char *) aliasData[i]) + 1);
+ i += (strlen((char *) (aliasData + i)) + 1);
newAlias->nextLinuxAlias = NULL;
@@ -588,6 +588,61 @@ void Rm_policyFreeAssignmentNsNamesList (Rm_AssignedNsNames *assignedNsNamesList
}
}
+/**********************************************************************
+ ****************Linux DTB Parsing Defines and Functions***************
+ **********************************************************************/
+
+Rm_LinuxValueRange *Rm_linuxExtractValues(const void *dtbDataPtr, int32_t dtbDataLen)
+{
+ uint32_t *dtbValueData = (uint32_t *)dtbDataPtr;
+ Rm_LinuxValueRange *startValue = NULL;
+ Rm_LinuxValueRange *newValue = NULL;
+ Rm_LinuxValueRange *prevValue = NULL;
+ uint32_t i;
+
+ /* Values are stored in the Linux DTB as a list of 32-bit words. The number of 32-bit
+ * words in the value field can differ. depending on the number of values specified. */
+
+ /* Extract the value data from the Linux DTB */
+ for (i = 0; i < (dtbDataLen / sizeof(uint32_t)); i++)
+ {
+ /* Creat a new value entry */
+ newValue = (Rm_LinuxValueRange *) Rm_osalMalloc(sizeof(Rm_LinuxValueRange));
+ /* Populate the new value entry. The endianness of the value extracted must
+ * be flipped */
+ newValue->value = fdt32_to_cpu(dtbValueData[i]);
+ newValue->nextValue = NULL;
+
+ /* Value linked list pointer accounting */
+ if (prevValue == NULL)
+ {
+ /* Save the first entry so it can be returned */
+ startValue = newValue;
+ }
+ else
+ {
+ prevValue->nextValue = (void *) newValue;
+ }
+
+ prevValue = newValue;
+ }
+
+ /* Return a pointer to the start of the value list */
+ return (startValue);
+}
+
+void Rm_linuxFreeValues(Rm_LinuxValueRange *valueList)
+{
+ Rm_LinuxValueRange *nextValue;
+
+ while (valueList != NULL)
+ {
+ nextValue = valueList->nextValue;
+ Rm_osalFree((void *)valueList, sizeof(Rm_LinuxValueRange));
+ valueList = nextValue;
+ }
+}
+
/**
@}
*/
diff --git a/test/rm_test.c b/test/rm_test.c
index 855986c2d67b475debf77db11dd009c3c1ea9d7a..9cc693696f0811d6daa0dbe134ae8555d3c88595 100644 (file)
--- a/test/rm_test.c
+++ b/test/rm_test.c
requestInfo.type = Rm_service_RESOURCE_MAP_TO_NAME;
requestInfo.resourceName = &resourceName[0];
requestInfo.resourceBase = 1;
- requestInfo.resourceRange = 2;
+ requestInfo.resourceLength = 2;
requestInfo.resourceNsName = &resourceNsName[0];
requestInfo.callback.serviceCallback = testServiceCallback;
requestInfo.type = Rm_service_RESOURCE_MAP_TO_NAME;
requestInfo.resourceName = &resourceName[0];
requestInfo.resourceBase = 2;
- requestInfo.resourceRange = 3;
+ requestInfo.resourceLength = 3;
requestInfo.resourceNsName = &resourceNsName[0];
requestInfo.callback.serviceCallback = testServiceCallback;