Free and unspecified allocation bug fixes
authorJustin Sobota <jsobota@ti.com>
Wed, 19 Dec 2012 22:28:23 +0000 (17:28 -0500)
committerJustin Sobota <jsobota@ti.com>
Wed, 19 Dec 2012 22:28:23 +0000 (17:28 -0500)
device/tci6614-global-resources.dtb
include/rm_loc.h
rm_services.h
rm_types.h
src/rm.c
test/rm_test.c

index dc537ccd8b76700b65364add6c81447867920b4d..5746f10204ab4073034e8d758cbbf29dbd3b8c07 100644 (file)
Binary files a/device/tci6614-global-resources.dtb and b/device/tci6614-global-resources.dtb differ
index ec1677da69c3d14933a6ce0db10d7c04c966838b..115ac4f98bef70e0126a04d289667521715c8c57 100644 (file)
@@ -146,12 +146,6 @@ typedef enum {
 typedef struct {
     char *serviceSrcInstName;
     Rm_AllocatorOp operation;
-    /* When pre-allocating, the policy's ranges and alignment for the resource
-     * for the RM instance will be copied to the following three variables.  These
-     * variables will be used as the basis for pre-allocating a resource. */
-    uint32_t policyBase;
-    uint32_t policyLength;
-    uint32_t policyAlignment;
     /* Will contain the actual allocation/free values */
     Rm_ResourceInfo *resourceInfo;
 } Rm_AllocatorOpInfo;
index 88680b705aa7fa320cec7521d70e0fb6a0c3a8d6..224bd33bb74a180e1c33b819fb082111152b8382 100644 (file)
@@ -82,8 +82,13 @@ extern "C" {
 /** A resource value within the specifed base+range is already allocated to another
  *  RM instance. */
 #define RM_SERVICE_DENIED_RESOURCE_ALREADY_ALLOCATED (RM_SERVICE_DENIED_BEGIN+4)
+/** The resource range specified for freeing included free and allocated resoruces. */
+#define RM_SERVICE_DENIED_INVALID_RESOURCE_RANGE (RM_SERVICE_DENIED_BEGIN+5)
+/** No free resource ranges could be found that satisfy the resource base, length, and
+ *  alignment requirements */
+#define RM_SERVICE_DENIED_RESOURCE_ALLOCATION_REQUIREMENTS_COULD_NOT_BE_SATISFIED (RM_SERVICE_DENIED_BEGIN+6)
 /** End of resource denied reasons */
-#define RM_SERVICE_DENIED_END (RM_SERVICE_DENIED_BEGIN+4)
+#define RM_SERVICE_DENIED_END (RM_SERVICE_DENIED_BEGIN+5)
 
 /** RM Service Request Error Code Base */
 #define RM_SERVICE_ERROR_BASE (-64)
index 4829424e856864e671e2b7d7397e6d1c5f33d5c6..4b958cd8bbc87bc8095bf1c925ddf1f549a0b617 100644 (file)
@@ -44,6 +44,7 @@
 
 /* c99 include */
 #include <stdint.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <stdbool.h>
index 57e42c0a379831fb8739e85aad45a8af4aeddd23..27a6f728e9a78eb4ba77edbc7c959b3c124b481c 100644 (file)
--- a/src/rm.c
+++ b/src/rm.c
@@ -482,92 +482,67 @@ int32_t Rm_treePreAllocate(Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)
 {\r
     Rm_ResourceTreeNode findNode;\r
     Rm_ResourceTreeNode *matchingNode = NULL;\r
-    uint32_t policyRangeEnd = opInfo->policyBase + opInfo->policyLength - 1;\r
-    uint32_t index;\r
+    uint32_t matchingEnd;\r
+    uint32_t rangeIndex;\r
     bool resourceFound = FALSE;\r
     int32_t retVal = RM_SERVICE_PROCESSING;\r
 \r
-    /* Find the tree node that contains the first value in the specified policy range. */\r
-    if (opInfo->policyBase)\r
+    /* Initialize the findNode parameters to the starting preallocation parameters */\r
+    if (opInfo->resourceInfo->base)\r
     {\r
-        findNode.base = opInfo->policyBase;\r
+        findNode.base = opInfo->resourceInfo->base;\r
     }\r
     else\r
     {\r
+        /* Otherwise use the first resource value in the tree */\r
         matchingNode = RB_MIN(_Rm_ResourceTree, allocator->allocatorRootEntry);\r
         findNode.base = matchingNode->base;\r
     }\r
-    \r
-    findNode.length = 1;\r
-    matchingNode = RB_FIND(_Rm_ResourceTree, allocator->allocatorRootEntry, &findNode);\r
+    findNode.length = opInfo->resourceInfo->length;\r
 \r
-    if (matchingNode != NULL)\r
+    do\r
     {\r
-        /* Begin searching for an available range of resources starting from the\r
-         * matching node */\r
-        for (index = matchingNode->base; index <= policyRangeEnd;)\r
+        matchingNode = RB_FIND(_Rm_ResourceTree, allocator->allocatorRootEntry, &findNode);\r
+        \r
+        if (matchingNode != NULL)\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
-\r
-                /* Move index to the first resource satisfying the alignment property */\r
-                if ((index % opInfo->policyAlignment) != 0)\r
+                matchingEnd = matchingNode->base + matchingNode->length - 1;\r
+                /* Initialize the indexer to be the first resource base value that \r
+                 * satisfies the alignment property */\r
+                rangeIndex = findNode.base;\r
+                if (rangeIndex % opInfo->resourceInfo->alignment)\r
                 {\r
-                    index += (opInfo->policyAlignment - (index % opInfo->policyAlignment));\r
+                    rangeIndex += (opInfo->resourceInfo->alignment -\r
+                              (rangeIndex % opInfo->resourceInfo->alignment));\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
+                /*Is there a block of unallocated resources within the matchingNode\r
+                 * that satisfies the allocate properties? */\r
+                if ((rangeIndex + opInfo->resourceInfo->length - 1) <= matchingEnd)\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
-                    /* Move index to the next resource value that satisfies the alignment property */\r
-                    index += (opInfo->policyAlignment - (index % opInfo->policyAlignment));\r
+                    opInfo->resourceInfo->base = rangeIndex;\r
+                    resourceFound = TRUE;\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
-                }\r
-                else\r
-                {\r
-                    index = matchingNode->base;\r
-                }\r
-            }\r
-            else\r
-            {\r
-                /* Found a resource range that satisfies the request properties.  Break out of the\r
-                 * search loop */\r
-                break;\r
+                /* If the matchingNode does not satisfy allocate requirements update the resource base \r
+                 * to the first resource value after the end of the current matchingNode */\r
+                findNode.base = matchingNode->base + matchingNode->length;\r
             }\r
         }\r
-\r
-        if (!resourceFound)\r
+        else\r
         {\r
-            retVal = RM_SERVICE_DENIED_RESOURCE_ALREADY_ALLOCATED;\r
+            /* If not matchingNode has been found the end of the tree has been reached and there\r
+             * is not resource range available that meets the needs of the request */\r
+            retVal = RM_SERVICE_DENIED_RESOURCE_ALLOCATION_REQUIREMENTS_COULD_NOT_BE_SATISFIED;\r
         }\r
-    }\r
-    else\r
-    {\r
-        retVal = RM_SERVICE_DENIED_RESOURCE_VALUE_RANGE_DOES_NOT_EXIST;\r
-    }\r
+    } while ((!resourceFound) && \r
+             (retVal != RM_SERVICE_DENIED_RESOURCE_ALLOCATION_REQUIREMENTS_COULD_NOT_BE_SATISFIED));\r
 \r
     return(retVal); \r
 }\r
@@ -669,14 +644,14 @@ int32_t Rm_treeAllocate(Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)
                  *                base1                   base1+length1-1                 \r
                  */    \r
                 else\r
-                {     \r
-                    /* Remove the matchingNode from the tree since it will be edited */\r
-                    RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
-                    \r
+                {    \r
                     if (findNode.base == matchingNode->base)\r
                     {\r
                         /* There may be a combine possibility to the left. Extract leftNode to check */\r
                         leftNode = RB_PREV(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+\r
+                        /* Remove the matchingNode from the tree since it will be edited */\r
+                        RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);                        \r
                         \r
                         /* Can the node to the left of the matchingNode be combined with the \r
                          * findNode's range? */\r
@@ -707,6 +682,9 @@ int32_t Rm_treeAllocate(Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)
                     {\r
                         /* There may be a combine possibility to the right. Extract rightNode to check */\r
                         rightNode = RB_NEXT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+\r
+                        /* Remove the matchingNode from the tree since it will be edited */\r
+                        RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
                         \r
                         /* Can the node to the right of the matchingNode be combined with the \r
                          * findNode's range? */\r
@@ -791,211 +769,222 @@ int32_t Rm_treeFree(Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)
          * 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->serviceSrcInstName) == 0)\r
+        {  \r
+            if (strcmp(matchingNode->allocatedTo, RM_NOT_ALLOCATED_STRING))\r
             {\r
-                /* Resources can be freed */\r
-\r
-                if ((findNode.base == matchingNode->base) && (findEnd == matchingEnd))\r
+                if (strcmp(matchingNode->allocatedTo, opInfo->serviceSrcInstName) == 0)\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
-                    leftNode = RB_PREV(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
-                    rightNode = RB_NEXT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\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
-\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
-                        RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\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
-                        RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
-                        combineRight = TRUE;\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
+                    /* Resources can be freed */\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
-                    {\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
+                    if ((findNode.base == matchingNode->base) && (findEnd == matchingEnd))\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
-                    /* 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 if ((findNode.base > matchingNode->base) && (findEnd < matchingEnd))\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
-                    /* Remove matching node for editing. */\r
-                    RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\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
-                    /* 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
-                    /* Insert the left and right nodes into the tree. */\r
-                    RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
-                    RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
-\r
-                    /* Base and length of matching node become 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
-                else\r
-                {\r
-                    /* Remove the matchingNode from the tree since it will be edited */\r
-                    RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
-                    \r
-                    if (findNode.base == matchingNode->base)\r
-                    {\r
-                        /* Case 3: Free range is on left boundary of matched node. Try to \r
-                         *         combine the free range with the left node if free.\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 (free)--->||<----------matched node---------->|\r
-                         *                           |<---findNode (free req)--->|\r
+                         * |<--left node-->||<---matched node--->||<--right node-->|\r
+                         *                  |<---free request--->|\r
                          */ \r
-                   \r
-                        /* There may be a combine possibility to the left. Extract leftNode to check */\r
+\r
                         leftNode = RB_PREV(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
-                        \r
-                        /* Can the node to the left of the matchingNode be combined with the \r
-                         * findNode's range? */\r
+                        rightNode = RB_NEXT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\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
+\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
-                            /* Remove the leftNode from the tree for editing */\r
+                            /* Combine the left node and the matching node */\r
                             RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\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
+                            RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
+                            combineRight = TRUE;\r
+                        }\r
 \r
-                            /* Combine the leftNode and the findNode */\r
-                            leftNode->length += findNode.length;\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
+                            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
+                        {\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
-                            /* Allocate a new leftNode that will take the place of the findNode\r
-                             * range in tree. */\r
-                            leftNode = Rm_newResourceTreeNode(findNode.base, findNode.length,\r
-                                                              RM_NOT_ALLOCATED_STRING);\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
-                        /* Account for the leftNode in the matchingNode */\r
-                        matchingNode->base = findNode.base + findNode.length;\r
-                        matchingNode->length = matchingEnd - findEnd;  \r
-\r
-                        /* Insert the left node */\r
-                        RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\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 if (findEnd == matchingEnd)\r
+                    else if ((findNode.base > matchingNode->base) && (findEnd < matchingEnd))\r
                     {\r
-                        /* Case 4: Free range is on right boundary of matched node. Try to \r
-                         *         combine the free range with the right node if free.\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---------->||<---right node (free)--->|\r
-                         *        |<---findNode (free req)--->|\r
+                         * |<----------matched node---------->|\r
+                         *        |<---free request--->|\r
                          */ \r
-                        \r
-                        /* There may be a combine possibility to the right. Extract rightNode to check */\r
-                        rightNode = RB_NEXT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
-                        \r
-                        /* Can the node to the right of the matchingNode be combined with the \r
-                         * findNode's range? */\r
-                        if (rightNode && (strcmp(rightNode->allocatedTo, RM_NOT_ALLOCATED_STRING) == 0))\r
-                        {\r
-                            /* Remove the rightNode from the tree for editing */\r
-                            RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
 \r
-                            /* Combine the rightNode and the findNode */\r
-                            rightNode->base = findNode.base;\r
-                            rightNode->length += findNode.length;\r
+                        /* Remove matching node for editing. */\r
+                        RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\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
+                        /* 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
+                        /* Insert the left and right nodes into the tree. */\r
+                        RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
+                        RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
+\r
+                        /* Base and length of matching node become 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
+                    else\r
+                    {                        \r
+                        if (findNode.base == matchingNode->base)\r
+                        {\r
+                            /* Case 3: Free range is on left boundary of matched node. Try to \r
+                             *         combine the free range with the left node if free.\r
+                             *\r
+                             * |<---left node (free)--->||<----------matched node---------->|\r
+                             *                           |<---findNode (free req)--->|\r
+                             */ \r
+                       \r
+                            /* There may be a combine possibility to the left. Extract leftNode to check */\r
+                            leftNode = RB_PREV(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+                            \r
+                            /* Remove the matchingNode from the tree since it will be edited */\r
+                            RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+                            \r
+                            /* Can the node to the left of the matchingNode be combined with the \r
+                             * findNode's range? */\r
+                            if (leftNode && (strcmp(leftNode->allocatedTo, RM_NOT_ALLOCATED_STRING) == 0))\r
+                            {\r
+                                /* Remove the leftNode from the tree for editing */\r
+                                RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
+\r
+                                /* Combine the leftNode and the findNode */\r
+                                leftNode->length += findNode.length;\r
+                            }\r
+                            else\r
+                            {\r
+                                /* Allocate a new leftNode that will take the place of the findNode\r
+                                 * range in tree. */\r
+                                leftNode = Rm_newResourceTreeNode(findNode.base, findNode.length,\r
+                                                                  RM_NOT_ALLOCATED_STRING);\r
+                            }\r
+\r
+                            /* Account for the leftNode in the matchingNode */\r
+                            matchingNode->base = findNode.base + findNode.length;\r
+                            matchingNode->length = matchingEnd - findEnd;  \r
+\r
+                            /* Insert the left node */\r
+                            RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
                         }\r
-                        else\r
+                        else if (findEnd == matchingEnd)\r
                         {\r
-                            /* Allocate a new rightNode that will take the place of the findNode\r
-                             * range in tree. */\r
-                            rightNode = Rm_newResourceTreeNode(findNode.base, findNode.length,\r
-                                                               RM_NOT_ALLOCATED_STRING);\r
+                            /* Case 4: Free range is on right boundary of matched node. Try to \r
+                             *         combine the free range with the right node if free.\r
+                             *\r
+                             * |<----------matched node---------->||<---right node (free)--->|\r
+                             *        |<---findNode (free req)--->|\r
+                             */ \r
+                            \r
+                            /* There may be a combine possibility to the right. Extract rightNode to check */\r
+                            rightNode = RB_NEXT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+\r
+                            /* Remove the matchingNode from the tree since it will be edited */\r
+                            RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);   \r
+                            \r
+                            /* Can the node to the right of the matchingNode be combined with the \r
+                             * findNode's range? */\r
+                            if (rightNode && (strcmp(rightNode->allocatedTo, RM_NOT_ALLOCATED_STRING) == 0))\r
+                            {\r
+                                /* Remove the rightNode from the tree for editing */\r
+                                RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
+\r
+                                /* Combine the rightNode and the findNode */\r
+                                rightNode->base = findNode.base;\r
+                                rightNode->length += findNode.length;\r
+                            }\r
+                            else\r
+                            {\r
+                                /* Allocate a new rightNode that will take the place of the findNode\r
+                                 * range in tree. */\r
+                                rightNode = Rm_newResourceTreeNode(findNode.base, findNode.length,\r
+                                                                   RM_NOT_ALLOCATED_STRING);\r
+                            }\r
+\r
+                            /* Account for the rightNode in the matchingNode */\r
+                            matchingNode->length -= findNode.length;  \r
+\r
+                            /* Insert the right node */\r
+                            RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
                         }\r
 \r
-                        /* Account for the rightNode in the matchingNode */\r
-                        matchingNode->length -= findNode.length;  \r
-\r
-                        /* Insert the right node */\r
-                        RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
+                        /* Reinsert the edited matching node */\r
+                        RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
                     }\r
 \r
-                    /* Reinsert the edited matching node */\r
-                    RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\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
-                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
+                /* Resources are already free */\r
+                retVal = RM_SERVICE_DENIED_RESOURCE_ALREADY_FREE;\r
             }\r
         }\r
         else\r
@@ -1003,7 +992,7 @@ int32_t Rm_treeFree(Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)
             /* 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
+            retVal = RM_SERVICE_DENIED_INVALID_RESOURCE_RANGE;\r
         }\r
     }\r
     else\r
@@ -1138,26 +1127,25 @@ void Rm_allocationHandler (Rm_Inst *rmInst, Rm_Transaction *transaction)
         }\r
         else if (transaction->resourceInfo.base == RM_RESOURCE_BASE_UNSPECIFIED)\r
         {\r
-            /* Execute the allocator pre-allocate operation to get the next available resources.\r
-             * NORMALLY CHECKED AGAINST THE POLICY */\r
-            opInfo.operation = Rm_allocatorOp_PRE_ALLOCATE;\r
-                \r
-            if (transaction->resourceInfo.alignment == RM_RESOURCE_ALIGNMENT_UNSPECIFIED)\r
+            if ((transaction->resourceInfo.alignment == RM_RESOURCE_ALIGNMENT_UNSPECIFIED) ||\r
+                (transaction->resourceInfo.alignment == 0))\r
             {   \r
                 /* TEMP: Default resource alignment of 1 if the resource alignment is not\r
                  *       specified */\r
-                opInfo.policyAlignment = 1;\r
-            }\r
-            else\r
-            {\r
-                opInfo.policyAlignment = transaction->resourceInfo.alignment;\r
+                opInfo.resourceInfo->alignment = 1;\r
             }\r
 \r
-            /* opInfo.policyBase = comes from policy once implemented */\r
-            opInfo.policyLength = transaction->resourceInfo.length;\r
+            /* TODO: set the resourceInfo->base value to be the base of the resource range\r
+             *       allowed for the RM instance */\r
+            // opInfo.resourceInfo->base = policy_get_instance_base(...);\r
+            opInfo.resourceInfo->base = 0;\r
+\r
+            /* Execute the allocator pre-allocate operation to get the next available resources.\r
+             * NORMALLY CHECKED AGAINST THE POLICY */\r
+            opInfo.operation = Rm_allocatorOp_PRE_ALLOCATE;\r
 \r
             /* If the pre-allocate operation succeeds the resourceInfo field pointed to\r
-             * by opInfo will contain the next available resources taht satisfy the\r
+             * by opInfo will contain the next available resources that satisfy the\r
              * resource properties */\r
             retVal = Rm_allocatorOperation(rmInst, &opInfo);\r
         }\r
index 1a9623b44d7ee66a1f5ee9ef69b243aa5daef59c..38f10886053a29f05a66a8e83bc7c7653b9e88b0 100644 (file)
@@ -666,7 +666,49 @@ void testRmTsk(UArg arg0, UArg arg1)
                                                                                       requestInfo.resourceLength);            
         }            
         
-        Rm_printResourceStatus(rmServerHandle);           
+        Rm_printResourceStatus(rmServerHandle);     
+
+        memset((void *) &requestInfo, 0, sizeof(Rm_ServiceReqInfo));        
+        requestInfo.type = Rm_service_RESOURCE_FREE;
+        requestInfo.resourceName = aifName;
+        requestInfo.resourceBase = 29;
+        requestInfo.resourceLength = 2;
+        requestInfo.callback.serviceCallback = testServiceCallback;
+        
+        System_printf("Core %d: %s freeing resource...\n", MultiProc_self(), rmServerName);
+        rmServerServicePort->rmService(rmServerServicePort->rmHandle, &requestInfo, &responseInfo);
+        if (blockForResponse(&responseInfo))
+        {
+            System_printf("Core %d: %s freed resource: %s base: %d length: %d\n", MultiProc_self(),
+                                                                                      rmServerName,
+                                                                                      requestInfo.resourceName, 
+                                                                                      requestInfo.resourceBase,
+                                                                                      requestInfo.resourceLength);            
+        }    
+        memset((void *) &requestInfo, 0, sizeof(Rm_ServiceReqInfo));        
+        requestInfo.type = Rm_service_RESOURCE_FREE;
+        requestInfo.resourceName = aifName;
+        requestInfo.resourceBase = 46;
+        requestInfo.resourceLength = 4;
+        requestInfo.callback.serviceCallback = testServiceCallback;
+        
+        System_printf("Core %d: %s freeing resource...\n", MultiProc_self(), rmServerName);
+        rmServerServicePort->rmService(rmServerServicePort->rmHandle, &requestInfo, &responseInfo);
+        if (blockForResponse(&responseInfo))
+        {
+            System_printf("Core %d: %s freed resource: %s base: %d length: %d\n", MultiProc_self(),
+                                                                                      rmServerName,
+                                                                                      requestInfo.resourceName, 
+                                                                                      requestInfo.resourceBase,
+                                                                                      requestInfo.resourceLength);            
+        }           
+        
+        Rm_printResourceStatus(rmServerHandle); 
+
+        /* Wait for Client and Client Delegate to do their UNSPECIFIED allocates */
+        waitOnSyncObj();
+
+        Rm_printResourceStatus(rmServerHandle);      
         
     }
     else if (MultiProc_self() == 1)
@@ -674,7 +716,8 @@ void testRmTsk(UArg arg0, UArg arg1)
         char resourceName[RM_RESOURCE_NAME_MAX_CHARS] = "gp-queue";
         char resourceNsName[RM_RESOURCE_NAME_MAX_CHARS] = "My_Favorite_Queue";
 
-        char aifName[RM_RESOURCE_NAME_MAX_CHARS] = "aif-rx-ch";        
+        char aifName[RM_RESOURCE_NAME_MAX_CHARS] = "aif-rx-ch";    
+        char accumChName[RM_RESOURCE_NAME_MAX_CHARS] = "accumulator-ch";
 
         /* Issue the service request for the resources tied to the name via the service port */                
         requestInfo.type = Rm_service_RESOURCE_GET_BY_NAME;
@@ -774,6 +817,7 @@ void testRmTsk(UArg arg0, UArg arg1)
                                                                                       requestInfo.resourceBase,
                                                                                       requestInfo.resourceLength);            
         }     
+        
         memset((void *) &requestInfo, 0, sizeof(Rm_ServiceReqInfo));        
         requestInfo.type = Rm_service_RESOURCE_ALLOCATE;
         requestInfo.resourceName = aifName;
@@ -793,7 +837,70 @@ void testRmTsk(UArg arg0, UArg arg1)
         }  
 
         /* Release the syncObj so Server can print results of resource allocations */
-        releaseSyncObj();          
+        releaseSyncObj();    
+
+        /* Take the syncObj to allocate resources using the UNSPECIFIED parameters. */
+        takeSyncObj();
+
+        memset((void *) &requestInfo, 0, sizeof(Rm_ServiceReqInfo));        
+        requestInfo.type = Rm_service_RESOURCE_ALLOCATE;
+        requestInfo.resourceName = accumChName;
+        requestInfo.resourceBase = RM_RESOURCE_BASE_UNSPECIFIED;
+        requestInfo.resourceLength = 5;
+        requestInfo.resourceAlignment = 4;
+        requestInfo.callback.serviceCallback = testServiceCallback;
+        
+        System_printf("Core %d: %s Allocating resource...\n", MultiProc_self(), rmClientDelegateName);
+        rmClientDelegateServicePort->rmService(rmClientDelegateServicePort->rmHandle, &requestInfo, &responseInfo);
+        if (blockForResponse(&responseInfo))
+        {
+            System_printf("Core %d: %s allocated resource: %s base: %d length: %d\n", MultiProc_self(),
+                                                                                      rmClientDelegateName,
+                                                                                      responseInfo.resourceName, 
+                                                                                      responseInfo.resourceBase,
+                                                                                      responseInfo.resourceLength);            
+        }    
+
+        memset((void *) &requestInfo, 0, sizeof(Rm_ServiceReqInfo));        
+        requestInfo.type = Rm_service_RESOURCE_ALLOCATE;
+        requestInfo.resourceName = accumChName;
+        requestInfo.resourceBase = RM_RESOURCE_BASE_UNSPECIFIED;
+        requestInfo.resourceLength = 2;
+        requestInfo.resourceAlignment = RM_RESOURCE_ALIGNMENT_UNSPECIFIED;
+        requestInfo.callback.serviceCallback = testServiceCallback;
+        
+        System_printf("Core %d: %s Allocating resource...\n", MultiProc_self(), rmClientName);
+        rmClientServicePort->rmService(rmClientServicePort->rmHandle, &requestInfo, &responseInfo);
+        if (blockForResponse(&responseInfo))
+        {
+            System_printf("Core %d: %s allocated resource: %s base: %d length: %d\n", MultiProc_self(),
+                                                                                      rmClientName,
+                                                                                      responseInfo.resourceName, 
+                                                                                      responseInfo.resourceBase,
+                                                                                      responseInfo.resourceLength);            
+        }    
+
+        memset((void *) &requestInfo, 0, sizeof(Rm_ServiceReqInfo));        
+        requestInfo.type = Rm_service_RESOURCE_ALLOCATE;
+        requestInfo.resourceName = accumChName;
+        requestInfo.resourceBase = RM_RESOURCE_BASE_UNSPECIFIED;
+        requestInfo.resourceLength = 2;
+        requestInfo.resourceAlignment = 20;
+        requestInfo.callback.serviceCallback = testServiceCallback;
+        
+        System_printf("Core %d: %s Allocating resource...\n", MultiProc_self(), rmClientName);
+        rmClientServicePort->rmService(rmClientServicePort->rmHandle, &requestInfo, &responseInfo);
+        if (blockForResponse(&responseInfo))
+        {
+            System_printf("Core %d: %s allocated resource: %s base: %d length: %d\n", MultiProc_self(),
+                                                                                      rmClientName,
+                                                                                      responseInfo.resourceName, 
+                                                                                      responseInfo.resourceBase,
+                                                                                      responseInfo.resourceLength);            
+        }           
+
+        /* Release the syncObj so Server can print results of resource allocations */
+        releaseSyncObj();           
     }
 
     System_printf("Core %d: Testing is complete\n", MultiProc_self());