Added ability for instance to allocate same resource twice (init then use)
authorJustin Sobota <jsobota@ti.com>
Tue, 12 Feb 2013 19:37:49 +0000 (14:37 -0500)
committerJustin Sobota <jsobota@ti.com>
Tue, 12 Feb 2013 19:37:49 +0000 (14:37 -0500)
rm.h
src/rm.c
test/rm_test.c

diff --git a/rm.h b/rm.h
index e41967289eb2bda043899d510cfcdbcc417ec365..03cdd3f6b0d90407b92e6c421ad45f25c5716947 100644 (file)
--- a/rm.h
+++ b/rm.h
@@ -298,7 +298,7 @@ extern "C" {
 #define RM_ERROR_ALREADY_REGD_SERVER_OR_CD         RM_ERROR_BASE-37
 /** Transport registration callout function pointers specified as valid but were NULL */
 #define RM_ERROR_NULL_CALLOUTS_WHEN_VALID          RM_ERROR_BASE-38
-/** Service both a NameServer name and a base, length, or alignment */
+/** Service has both a NameServer name and a base, length, or alignment specified */
 #define RM_ERROR_NS_NAME_AND_RES_VAL_CONFLICT      RM_ERROR_BASE-39
 /** Instance type not recognized */
 #define RM_ERROR_INVALID_INST_TYPE                 RM_ERROR_BASE-40
index 8972186ad07b810f9139751f77649662233c14f7..96dbf83ab7345f0fa936397e95fc49cc298d7865 100644 (file)
--- a/src/rm.c
+++ b/src/rm.c
@@ -568,167 +568,176 @@ static int32_t treeAllocate(Rm_Inst *rmInst, Rm_Allocator *allocator, int32_t re
                         retVal = RM_SERVICE_DENIED_USE_PERM_NOT_GIVEN;\r
                     }\r
                 }\r
-                \r
-                if (allocPassesPolicy && (matchingNode->allocationCount > 0)) {\r
-                    /* Check exclusive privileges of instance requesting resource.  Requesting\r
-                     * instance with exclusive privileges can't reserve resource if already owned*/\r
-                    policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;\r
-                    policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;\r
-                    allocPassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);\r
-                    if (!allocPassesPolicy) {\r
-                        retVal = RM_SERVICE_DENIED_EXCLUSIVE_RES_ALLOCD;\r
+\r
+                if (!isOwnedBy(matchingNode, opInfo->serviceSrcInstNode)) {\r
+                    /* Perform exclusive checks if requesting instance does not already an\r
+                     * owner of the resource */\r
+                    if (allocPassesPolicy && (matchingNode->allocationCount > 0)) {\r
+                        /* Check exclusive privileges of instance requesting resource.  Requesting\r
+                         * instance with exclusive privileges can't reserve resource if already owned*/\r
+                        policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;\r
+                        policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;\r
+                        allocPassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);\r
+                        if (!allocPassesPolicy) {\r
+                            retVal = RM_SERVICE_DENIED_EXCLUSIVE_RES_ALLOCD;\r
+                        }\r
                     }\r
+                    if (allocPassesPolicy && (matchingNode->allocationCount == 1)) {\r
+                        /* Check exclusive privileges of instance that currently owns resource */\r
+                        policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;\r
+                        policyCheckCfg.validInstNode = matchingNode->ownerList->instNameNode;\r
+                        allocPassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);\r
+                        if (!allocPassesPolicy) {\r
+                            retVal = RM_SERVICE_DENIED_ALLOCD_TO_EXCLUSIVE_INST;\r
+                        }                \r
+                    }  \r
                 }\r
-                if (allocPassesPolicy && (matchingNode->allocationCount == 1)) {\r
-                    /* Check exclusive privileges of instance that currently owns resource */\r
-                    policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;\r
-                    policyCheckCfg.validInstNode = matchingNode->ownerList->instNameNode;\r
-                    allocPassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);\r
-                    if (!allocPassesPolicy) {\r
-                        retVal = RM_SERVICE_DENIED_ALLOCD_TO_EXCLUSIVE_INST;\r
-                    }                \r
-                }  \r
             }\r
             \r
-            if (allocPassesPolicy) {   \r
-                if ((findNode.base == matchingNode->base) && (findEnd == matchingEnd)) {\r
-                    /* findNode range matches matchingNode range\r
-                     *\r
-                     *   |<--left node-->||<--matched  node-->||<--right node-->| => existing node\r
-                     *                    |<--alloc request-->|  => requested resources\r
-                     */                     \r
-                    leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
-                    rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
-                    RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
-                    addOwner(matchingNode, opInfo->serviceSrcInstNode);\r
-\r
-                    if (leftNode && compareResourceNodeOwners(leftNode, matchingNode)) {\r
-                        RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
-                        combineLeft = true;\r
-                    }\r
-                    if (rightNode && compareResourceNodeOwners(rightNode, matchingNode)) {\r
-                        RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
-                        combineRight = true;\r
-                    }\r
-\r
-                    if (combineLeft && combineRight) {\r
-                        /* Combine all three nodes into matchingNode */\r
-                        matchingNode->base = leftNode->base;\r
-                        matchingNode->length = leftNode->length + matchingNode->length + rightNode->length;\r
-\r
-                        clearOwners(leftNode);\r
-                        rmResourceNodeFree(leftNode);\r
-                        clearOwners(rightNode);\r
-                        rmResourceNodeFree(rightNode);                        \r
-                    }\r
-                    else if (combineLeft) {\r
-                        /* Combine left and matching nodes.  Reinsert right. */\r
-                        matchingNode->base = leftNode->base;\r
-                        matchingNode->length += leftNode->length;\r
-\r
-                        clearOwners(leftNode);\r
-                        rmResourceNodeFree(leftNode);\r
-                        RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);                        \r
-                    }\r
-                    else if (combineRight) {\r
-                        /* Combine right and matching nodes.  Reinsert left. */\r
-                        matchingNode->length += rightNode->length;\r
-\r
-                        clearOwners(rightNode);\r
-                        rmResourceNodeFree(rightNode);\r
-                        RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
-                    }\r
-                    else {\r
-                        /* No combine. */\r
-                        RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
-                        RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
-                    }\r
-\r
-                    /* Always reinsert matchingNode */                \r
-                    RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);   \r
-                }   \r
-                else if ((findNode.base > matchingNode->base) && (findEnd < matchingEnd)) {\r
-                    /* findNode range is subset of matchingNode range and neither boundary is\r
-                     * equivalent.\r
-                     *\r
-                     * |<----------matched node---------->|\r
-                     *        |<---alloc request--->|\r
-                     */ \r
-                    RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
-                    leftNode = rmResourceNodeNew(matchingNode->base, findNode.base - matchingNode->base);\r
-                    copyOwners(leftNode, matchingNode);\r
-                    rightNode = rmResourceNodeNew(findNode.base + findNode.length, matchingEnd - findEnd);\r
-                    copyOwners(rightNode, matchingNode);\r
-\r
-                    matchingNode->base = findNode.base;                                    \r
-                    matchingNode->length = findNode.length;\r
-                    addOwner(matchingNode, opInfo->serviceSrcInstNode);\r
-\r
-                    /* Insert all the nodes */\r
-                    RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
-                    RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
-                    RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
-                }  \r
-                else {    \r
-                    if (findNode.base == matchingNode->base) {\r
-                        /* findNode base and matchingNode base are equivalent.  May be combine\r
-                         * possibilities to the left\r
+            if (allocPassesPolicy) {\r
+                if (!isOwnedBy(matchingNode, opInfo->serviceSrcInstNode)) {\r
+                    /* Handle any possible node combinations if requesting instance is\r
+                     * not already in resource's owner list.  Automatic approval if requesting\r
+                     * instance is already in owner list. */\r
+                    if ((findNode.base == matchingNode->base) && (findEnd == matchingEnd)) {\r
+                        /* findNode range matches matchingNode range\r
                          *\r
-                         * |<---left node (alloc'd)--->||<----------matched node---------->|\r
-                         *                              |<---findNode (alloc req)--->|\r
-                         */                         \r
+                         *   |<--left node-->||<--matched  node-->||<--right node-->| => existing node\r
+                         *                    |<--alloc request-->|  => requested resources\r
+                         */                     \r
                         leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+                        rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
                         RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
-                        /* Add allocating instance to owner list for compare with leftNode */\r
                         addOwner(matchingNode, opInfo->serviceSrcInstNode);\r
-                        \r
+\r
                         if (leftNode && compareResourceNodeOwners(leftNode, matchingNode)) {\r
                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
-                            /* Combine leftNode and findNode */\r
-                            leftNode->length += findNode.length;\r
+                            combineLeft = true;\r
                         }\r
-                        else {\r
-                            leftNode = rmResourceNodeNew(findNode.base, findNode.length);\r
-                            copyOwners(leftNode, matchingNode);\r
+                        if (rightNode && compareResourceNodeOwners(rightNode, matchingNode)) {\r
+                            RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
+                            combineRight = true;\r
                         }\r
 \r
-                        /* Account for leftNode in matchingNode */\r
-                        matchingNode->base = findNode.base + findNode.length;\r
-                        matchingNode->length = matchingEnd - findEnd;  \r
+                        if (combineLeft && combineRight) {\r
+                            /* Combine all three nodes into matchingNode */\r
+                            matchingNode->base = leftNode->base;\r
+                            matchingNode->length = leftNode->length + matchingNode->length + rightNode->length;\r
 \r
-                        RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
-                    }\r
-                    else if (findEnd == matchingEnd) {\r
-                        /* findNode end and matchingNode end are equivalent.  May be combine\r
-                         * possibilities to the right\r
-                         *\r
-                         * |<----------matched node---------->||<---right node (alloc'd)--->|\r
-                         *       |<---findNode (alloc req)--->| \r
-                         */                        \r
-                        rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
-                        RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
-                        /* Add allocating instance to owner list for compare with rightNode */\r
-                        addOwner(matchingNode, opInfo->serviceSrcInstNode);\r
-                        \r
-                        if (rightNode && compareResourceNodeOwners(rightNode, matchingNode)) {\r
-                            RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
-                            /* Combine rightNode and findNode */\r
-                            rightNode->base = findNode.base;\r
-                            rightNode->length += findNode.length;\r
+                            clearOwners(leftNode);\r
+                            rmResourceNodeFree(leftNode);\r
+                            clearOwners(rightNode);\r
+                            rmResourceNodeFree(rightNode);                        \r
+                        }\r
+                        else if (combineLeft) {\r
+                            /* Combine left and matching nodes.  Reinsert right. */\r
+                            matchingNode->base = leftNode->base;\r
+                            matchingNode->length += leftNode->length;\r
+\r
+                            clearOwners(leftNode);\r
+                            rmResourceNodeFree(leftNode);\r
+                            RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);                        \r
+                        }\r
+                        else if (combineRight) {\r
+                            /* Combine right and matching nodes.  Reinsert left. */\r
+                            matchingNode->length += rightNode->length;\r
+\r
+                            clearOwners(rightNode);\r
+                            rmResourceNodeFree(rightNode);\r
+                            RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
                         }\r
                         else {\r
-                            rightNode = rmResourceNodeNew(findNode.base, findNode.length);\r
-                            copyOwners(rightNode, matchingNode);\r
+                            /* No combine. */\r
+                            RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
+                            RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
                         }\r
 \r
-                        /* Account for rightNode in matchingNode */\r
-                        matchingNode->length -= findNode.length;  \r
+                        /* Always reinsert matchingNode */                \r
+                        RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);   \r
+                    }   \r
+                    else if ((findNode.base > matchingNode->base) && (findEnd < matchingEnd)) {\r
+                        /* findNode range is subset of matchingNode range and neither boundary is\r
+                         * equivalent.\r
+                         *\r
+                         * |<----------matched node---------->|\r
+                         *        |<---alloc request--->|\r
+                         */ \r
+                        RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+                        leftNode = rmResourceNodeNew(matchingNode->base, findNode.base - matchingNode->base);\r
+                        copyOwners(leftNode, matchingNode);\r
+                        rightNode = rmResourceNodeNew(findNode.base + findNode.length, matchingEnd - findEnd);\r
+                        copyOwners(rightNode, matchingNode);\r
+\r
+                        matchingNode->base = findNode.base;                                    \r
+                        matchingNode->length = findNode.length;\r
+                        addOwner(matchingNode, opInfo->serviceSrcInstNode);\r
 \r
+                        /* Insert all the nodes */\r
+                        RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+                        RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
+                    }  \r
+                    else {    \r
+                        if (findNode.base == matchingNode->base) {\r
+                            /* findNode base and matchingNode base are equivalent.  May be combine\r
+                             * possibilities to the left\r
+                             *\r
+                             * |<---left node (alloc'd)--->||<----------matched node---------->|\r
+                             *                              |<---findNode (alloc req)--->|\r
+                             */                         \r
+                            leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+                            RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+                            /* Add allocating instance to owner list for compare with leftNode */\r
+                            addOwner(matchingNode, opInfo->serviceSrcInstNode);\r
+                            \r
+                            if (leftNode && compareResourceNodeOwners(leftNode, matchingNode)) {\r
+                                RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
+                                /* Combine leftNode and findNode */\r
+                                leftNode->length += findNode.length;\r
+                            }\r
+                            else {\r
+                                leftNode = rmResourceNodeNew(findNode.base, findNode.length);\r
+                                copyOwners(leftNode, matchingNode);\r
+                            }\r
+\r
+                            /* Account for leftNode in matchingNode */\r
+                            matchingNode->base = findNode.base + findNode.length;\r
+                            matchingNode->length = matchingEnd - findEnd;  \r
+\r
+                            RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
+                        }\r
+                        else if (findEnd == matchingEnd) {\r
+                            /* findNode end and matchingNode end are equivalent.  May be combine\r
+                             * possibilities to the right\r
+                             *\r
+                             * |<----------matched node---------->||<---right node (alloc'd)--->|\r
+                             *       |<---findNode (alloc req)--->| \r
+                             */                        \r
+                            rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+                            RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+                            /* Add allocating instance to owner list for compare with rightNode */\r
+                            addOwner(matchingNode, opInfo->serviceSrcInstNode);\r
+                            \r
+                            if (rightNode && compareResourceNodeOwners(rightNode, matchingNode)) {\r
+                                RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
+                                /* Combine rightNode and findNode */\r
+                                rightNode->base = findNode.base;\r
+                                rightNode->length += findNode.length;\r
+                            }\r
+                            else {\r
+                                rightNode = rmResourceNodeNew(findNode.base, findNode.length);\r
+                                copyOwners(rightNode, matchingNode);\r
+                            }\r
+\r
+                            /* Account for rightNode in matchingNode */\r
+                            matchingNode->length -= findNode.length;  \r
+\r
+                            RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
+                        }\r
+                        /* Remove allocating instance from leftover matchingNode */\r
+                        deleteOwner(matchingNode, opInfo->serviceSrcInstNode);\r
+                        RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
                     }\r
-                    /* Remove allocating instance from leftover matchingNode */\r
-                    deleteOwner(matchingNode, opInfo->serviceSrcInstNode);\r
-                    RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
                 }\r
                 retVal = RM_SERVICE_APPROVED;\r
             }\r
index e0b4a641751846311795404d38945f1c6b6f4b3a..b852246d4c7fee4fd9087b07076a9a40fb1e879f 100644 (file)
@@ -798,8 +798,58 @@ void testRmTsk(UArg arg0, UArg arg1)
         /* Wait for Client and Client Delegate to do their UNSPECIFIED allocates */
         waitOnSyncObj();
 
-        Rm_printResourceStatus(rmServerHandle);      
+        Rm_printResourceStatus(rmServerHandle);
+
+        /* Test allocation of a resource twice from the same instance with init and use privileges.  Both
+         * should be approved but the instance should only be mentioned once in the resource's owner list */
+        memset((void *) &requestInfo, 0, sizeof(Rm_ServiceReqInfo));        
+        requestInfo.type = Rm_service_RESOURCE_ALLOCATE_INIT;
+        requestInfo.resourceName = resourceNameGpQ;
+        requestInfo.resourceBase = 6543;
+        requestInfo.resourceLength = 10;
+        requestInfo.callback.serviceCallback = testServiceCallback;
         
+        System_printf("Core %d: %s Allocating resource for init...\n", MultiProc_self(), rmServerName);
+        rmServerServiceHandle->Rm_serviceHandler(rmServerServiceHandle->rmHandle, &requestInfo, &responseInfo);
+        if ((responseInfo.serviceState == RM_SERVICE_APPROVED) ||
+            (responseInfo.serviceState == RM_SERVICE_PROCESSING)) {        
+            if (blockForResponse(&responseInfo)) {
+                System_printf("Core %d: %s allocate resource: %s base: %d length: %d\n", MultiProc_self(),
+                                                                                          rmServerName,
+                                                                                          requestInfo.resourceName, 
+                                                                                          requestInfo.resourceBase,
+                                                                                          requestInfo.resourceLength);            
+            }   
+        }
+        else {
+            System_printf("Core %d: Static allocation failed with error: %d\n", MultiProc_self(), 
+                                                                                responseInfo.serviceState);
+        }     
+        memset((void *) &requestInfo, 0, sizeof(Rm_ServiceReqInfo));        
+        requestInfo.type = Rm_service_RESOURCE_ALLOCATE_USE;
+        requestInfo.resourceName = resourceNameGpQ;
+        requestInfo.resourceBase = 6543;
+        requestInfo.resourceLength = 10;
+        requestInfo.callback.serviceCallback = testServiceCallback;
+        
+        System_printf("Core %d: %s Allocating same resource for use...\n", MultiProc_self(), rmServerName);
+        rmServerServiceHandle->Rm_serviceHandler(rmServerServiceHandle->rmHandle, &requestInfo, &responseInfo);
+        if ((responseInfo.serviceState == RM_SERVICE_APPROVED) ||
+            (responseInfo.serviceState == RM_SERVICE_PROCESSING)) {        
+            if (blockForResponse(&responseInfo)) {
+                System_printf("Core %d: %s allocate resource: %s base: %d length: %d\n", MultiProc_self(),
+                                                                                          rmServerName,
+                                                                                          requestInfo.resourceName, 
+                                                                                          requestInfo.resourceBase,
+                                                                                          requestInfo.resourceLength);            
+            }   
+        }
+        else {
+            System_printf("Core %d: Static allocation failed with error: %d\n", MultiProc_self(), 
+                                                                                responseInfo.serviceState);
+        }         
+
+        Rm_printResourceStatus(rmServerHandle);        
     }
     else if (MultiProc_self() == 1) {    
         /* Issue the service request for the resources tied to the name via the service port */