Preallocation routine will now correctly get next tree node during resource search
[keystone-rtos/rm-lld.git] / src / rm_allocator.c
1 /**
2  *   @file  rm_allocator.c
3  *
4  *   @brief   
5  *      This is the Resource Manager allocator source.
6  *
7  *  \par
8  *  ============================================================================
9  *  @n   (C) Copyright 2012-2013, Texas Instruments, Inc.
10  * 
11  *  Redistribution and use in source and binary forms, with or without 
12  *  modification, are permitted provided that the following conditions 
13  *  are met:
14  *
15  *    Redistributions of source code must retain the above copyright 
16  *    notice, this list of conditions and the following disclaimer.
17  *
18  *    Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the 
20  *    documentation and/or other materials provided with the   
21  *    distribution.
22  *
23  *    Neither the name of Texas Instruments Incorporated nor the names of
24  *    its contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
28  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
29  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
31  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
32  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
33  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
36  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
37  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38  *
39  *  \par
40 */
42 /* RM external includes */
43 #include <ti/drv/rm/rm.h>
45 /* RM internal includes */
46 #include <ti/drv/rm/include/rm_loc.h>
47 #include <ti/drv/rm/include/rm_allocatorloc.h>
48 #include <ti/drv/rm/include/rm_dtb_utilloc.h>
49 #include <ti/drv/rm/include/rm_policyloc.h>
50 #include <ti/drv/rm/include/rm_treeloc.h>
52 /* RM LIBFDT includes */
53 #include <ti/drv/rm/util/libfdt/libfdt.h>
55 /* Tree algorithm includes */
56 #include <ti/drv/rm/util/tree.h>
58 /* RM OSAL layer */
59 #include <rm_osal.h>
61 /**********************************************************************
62  ************************ Local Functions *****************************
63  **********************************************************************/
65 /* FUNCTION PURPOSE: Creates a resource allocator
66  ***********************************************************************
67  * DESCRIPTION: Returns a newly Created and initialized resource
68  *              The allocator is also stored in the RM instance
69  *              allocator list.            
70  */
71 static Rm_Allocator *allocatorAdd(Rm_Handle rmHandle, const char *resourceName)
72 {
73     Rm_Inst      *rmInst = (Rm_Inst *)rmHandle;
74     Rm_Allocator *allocators   = rmAllocatorGetAllocatorList(rmHandle);
75     Rm_Allocator *newAllocator = NULL;
77     newAllocator = Rm_osalMalloc(sizeof(*allocators));
79     if (newAllocator) {
80         memset((void *)newAllocator, 0, sizeof(*newAllocator));
81         strncpy(newAllocator->resourceName, resourceName, RM_NAME_MAX_CHARS);
82         newAllocator->allocatorRootEntry = NULL;
83         newAllocator->nextAllocator = NULL;  
85         /* Add allocator to end of list */
86         if (allocators) {
87             while (allocators->nextAllocator) {
88                 allocators = allocators->nextAllocator;
89             }
90             allocators->nextAllocator = newAllocator;
91             RM_SS_OBJ_WB(allocators, Rm_Allocator);
92         }
93         else {
94             if ((rmInst->instType == Rm_instType_SERVER) ||
95                 (rmInst->instType == Rm_instType_SHARED_SERVER)) {
96                 rmInst->u.server.allocators = newAllocator;
97             }
98             else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
99                 rmInst->u.cd.allocators = newAllocator;
100             }            
101         }
102     }
103     return (newAllocator);
106 /* FUNCTION PURPOSE: Adds an owner to an allocator resource
107  ***********************************************************************
108  * DESCRIPTION: Adds a RM instance node to a resource node's
109  *              list of owners.
110  */
111 static void allocatorResNodeOwnerAdd(Rm_Handle rmHandle, Rm_ResourceNode *node, void *serviceInstNode)
113     Rm_Inst  *rmInst = (Rm_Inst *)rmHandle;    
114     Rm_Owner *ownerList = node->ownerList;
115     Rm_Owner *newOwner = NULL;
117     newOwner = Rm_osalMalloc(sizeof(*newOwner));
119     if (newOwner) {
120         newOwner->instNameNode = serviceInstNode;
121         newOwner->nextOwner = NULL;  
123         /* Add owner entry to end of list */
124         if (ownerList) {
125             RM_SS_OBJ_INV(ownerList, Rm_Owner);
126             while (ownerList->nextOwner) {
127                 ownerList = ownerList->nextOwner;
128                 RM_SS_OBJ_INV(ownerList, Rm_Owner);
129             }
130             ownerList->nextOwner = newOwner;
131             RM_SS_OBJ_WB(ownerList, Rm_Owner);
132         }
133         else {
134             node->ownerList = newOwner;
135         }
137         node->allocationCount++;
138         newOwner->instNameNode->allocRefCount++;
139         RM_SS_OBJ_WB(newOwner, Rm_Owner);
140         RM_SS_OBJ_WB(newOwner->instNameNode, Rm_PolicyValidInstNode);
141     }
144 /* FUNCTION PURPOSE: Compares two resource node's boundaries
145  ***********************************************************************
146  * DESCRIPTION: Returns TRUE if the resource nodes are neighbors from
147  *              a base+length perspective.  Otherwise, returns FALSE.
148  */
149 static int allocatorResNodeBoundaryCompare(Rm_ResourceNode *node1, Rm_ResourceNode *node2)
151     uint32_t node1End = node1->base + node1->length - 1;
152     uint32_t node2End = node2->base + node2->length - 1;
154     if (node1 && node2) {
155         if (node1->base < node2->base) {
156             if (node1End == (node2->base - 1)) {
157                 return(RM_TRUE);
158             }
159         }
160         else if (node2->base < node1->base) {
161             if (node2End == (node1->base - 1)) {
162                 return(RM_TRUE);
163             }     
164         }
165     }
166     return(RM_FALSE);
169 /* FUNCTION PURPOSE: Compares two resource node's owners
170  ***********************************************************************
171  * DESCRIPTION: Returns TRUE if the owners of two resource nodes 
172  *              are equivalent.  Otherwise, returns FALSE.
173  */
174 static int allocatorResNodeOwnerCompare(Rm_Handle rmHandle, Rm_ResourceNode *node1, Rm_ResourceNode *node2)
176     Rm_Inst  *rmInst = (Rm_Inst *)rmHandle;    
177     Rm_Owner *node1Owners = node1->ownerList;
178     Rm_Owner *node2Owners = node2->ownerList;
179     int       matchedInst;
181     if (rmInst->instType == Rm_instType_SHARED_SERVER) {
182         while(node2Owners) {
183             Rm_osalBeginMemAccess((void *)node2Owners, sizeof(*node2Owners));
184             node2Owners = node2Owners->nextOwner;
185         }
186         node2Owners = node2->ownerList;
187     }
189     if (node1->allocationCount == node2->allocationCount) {
190         while (node1Owners) {
191             RM_SS_OBJ_INV(node1Owners, Rm_Owner);
192             matchedInst = RM_FALSE;
193             while (node2Owners) {
194                 if (node1Owners->instNameNode == node2Owners->instNameNode) {
195                     matchedInst = RM_TRUE;
196                     break;
197                 }
198                 node2Owners = node2Owners->nextOwner;
199             }
201             if (matchedInst) {
202                 node2Owners = node2->ownerList;
203                 node1Owners = node1Owners->nextOwner;
204             }
205             else {
206                 return(RM_FALSE);
207             }                
208         }
209     }
210     else {
211         return(RM_FALSE);
212     }  
213     
214     return(RM_TRUE);
217 /* FUNCTION PURPOSE: Deletes an owner from an allocator resource
218  ***********************************************************************
219  * DESCRIPTION: Removes a RM instance node from a resource node's
220  *              list of owners.
221  */
222 static void allocatorResNodeOwnerDelete(Rm_Handle rmHandle, Rm_ResourceNode *node, void *serviceInstNode)
224     Rm_Inst  *rmInst = (Rm_Inst *)rmHandle;    
225     Rm_Owner *owner = node->ownerList;
226     Rm_Owner *prevOwner = NULL;
228     while (owner) {
229         RM_SS_OBJ_INV(owner, Rm_Owner);
230         if (owner->instNameNode == serviceInstNode) {
231             break;             
232         }
233         prevOwner = owner;
234         owner = owner->nextOwner;
235     }
237     if (owner) {
238         if (prevOwner == NULL) {
239             node->ownerList = owner->nextOwner;
240         }
241         else {
242             prevOwner->nextOwner = owner->nextOwner;
243             RM_SS_OBJ_WB(prevOwner, Rm_Owner);
244         }
245         
246         node->allocationCount--;
247         owner->instNameNode->allocRefCount--;
248         RM_SS_OBJ_WB(owner->instNameNode, Rm_PolicyValidInstNode);
249         Rm_osalFree((void *)owner, sizeof(*owner));
250     }
253 /* FUNCTION PURPOSE: Copies the owners of a resource node
254  ***********************************************************************
255  * DESCRIPTION: Creates a list of resource owners for the destination
256  *              resource node that is equivalent to the source resource
257  *              node's owners
258  *
259  *              dstNode must be a newly created node without any owners.
260  */
261 static void allocatorResNodeOwnerCopy(Rm_Handle rmHandle, Rm_ResourceNode *dstNode, Rm_ResourceNode *srcNode)
263     Rm_Inst  *rmInst = (Rm_Inst *)rmHandle;
264     Rm_Owner *srcOwnerList = srcNode->ownerList;
265     Rm_Owner *dstNewOwner;
266     Rm_Owner *dstPrevOwner;
268     if (dstNode->ownerList != NULL) {
269         return;
270     }
271     dstNode->allocationCount = srcNode->allocationCount;
273     while (srcOwnerList) {
274         RM_SS_OBJ_INV(srcOwnerList, Rm_Owner);
275         dstNewOwner = Rm_osalMalloc(sizeof(*dstNewOwner));
276         dstNewOwner->instNameNode = srcOwnerList->instNameNode;
277         dstNewOwner->nextOwner = NULL;
278         RM_SS_OBJ_WB(dstNewOwner, Rm_Owner);
280         if (dstNode->ownerList == NULL) {
281             dstNode->ownerList = dstNewOwner;
282         }
283         else {
284             dstPrevOwner->nextOwner = dstNewOwner;
285             RM_SS_OBJ_WB(dstPrevOwner, Rm_Owner);
286         }
287         dstPrevOwner = dstNewOwner;
288         srcOwnerList = srcOwnerList->nextOwner;
289     }
292 /* FUNCTION PURPOSE: Clears a resource node's owners
293  ***********************************************************************
294  * DESCRIPTION: Deletes all owners from the owners list of a 
295  *              resource node.
296  */
297 static void allocatorResNodeOwnerClear(Rm_Handle rmHandle, Rm_ResourceNode *node)
299     Rm_Inst  *rmInst = (Rm_Inst *)rmHandle;    
300     Rm_Owner *owner = node->ownerList;
301     Rm_Owner *nextOwner;
303     while (owner) {
304         RM_SS_OBJ_INV(owner, Rm_Owner);
305         nextOwner = owner->nextOwner;
306         node->allocationCount--;
307         owner->instNameNode->allocRefCount--;
308         RM_SS_OBJ_WB(owner->instNameNode, Rm_PolicyValidInstNode);
309         Rm_osalFree((void *)owner, sizeof(*owner));
310         owner = nextOwner;
311     }
314 /* FUNCTION PURPOSE: Checks a resource node's ownership
315  ***********************************************************************
316  * DESCRIPTION: Returns TRUE if the provided instance node is
317  *              in the list of resource node owners.  Otherwise,
318  *              returns FALSE.
319  */
320 static int allocatorResNodeIsOwnedBy(Rm_Handle rmHandle, Rm_ResourceNode *node, void *serviceInstNode)
322     Rm_Inst  *rmInst = (Rm_Inst *)rmHandle;
323     Rm_Owner *owner = node->ownerList;
325     while (owner) {
326         RM_SS_OBJ_INV(owner, Rm_Owner);
327         if (owner->instNameNode == serviceInstNode) {
328             return(RM_TRUE);           
329         }
330         owner = owner->nextOwner;
331     }
332     return(RM_FALSE);
335 /* FUNCTION PURPOSE: Get the status for an allocator resource
336  ***********************************************************************
337  * DESCRIPTION: Called when a resource status request is made.  The
338  *              resource's allocator is searched for the resource base
339  *              and length specified in the transaction.  The 
340  *              resource's owner reference count is returned if the 
341  *              resource range is found.
342  */
343 static int32_t allocatorStatus(Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)
345     Rm_ResourceNode  findNode;
346     Rm_ResourceNode *matchingNode = NULL; 
347     uint32_t         matchingEnd;
348     uint32_t         findEnd;    
349     int32_t          retVal;
351     memset((void *)&findNode, 0, sizeof(findNode));
352     findNode.base = opInfo->resourceInfo->base;
353     findNode.length = opInfo->resourceInfo->length;
354     matchingNode = RB_FIND(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, &findNode);
356     if (matchingNode) {
357         matchingEnd = matchingNode->base + matchingNode->length - 1;
358         findEnd = findNode.base + findNode.length - 1;
359         if ((findNode.base >= matchingNode->base) && (findEnd <= matchingEnd)) {        
360             opInfo->resourceInfo->ownerCount = matchingNode->allocationCount;
361             retVal = RM_SERVICE_APPROVED;
362         }
363         else {
364             retVal = RM_SERVICE_DENIED_PARTIAL_STATUS;
365         }
366     }
367     else {
368         retVal = RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST;
369     }
371     return(retVal);  
374 /* FUNCTION PURPOSE: Preallocates an allocator resource
375  ***********************************************************************
376  * DESCRIPTION: Called when an allocate request is made but the base 
377  *              is unspecified.  The preallocation algorithm looks at 
378  *              available resources as well as policy permissions to 
379  *              determine a resource range that satisfies the request.
380  *              If a valid range is found it will be returned for the 
381  *              treeAllocate algorithm to handle.
382  */
383 static int32_t allocatorPreAllocate(Rm_Handle rmHandle, Rm_Allocator *allocator, int32_t resourcePolicy, 
384                                     Rm_AllocatorOpInfo *opInfo)
385 {   
386     Rm_Inst           *rmInst = (Rm_Inst *)rmHandle;
387     Rm_ResourceNode    findNode;
388     Rm_ResourceNode   *matchingNode = NULL;
389     Rm_ResourceNode   *nextNode;
390     uint32_t           matchingEnd;
391     uint32_t           findEnd;
392     uint32_t           rangeIndex;
393     int                resourceFound = RM_FALSE;
394     Rm_PolicyCheckType policyCheckType;
395     Rm_PolicyCheckCfg  policyCheckCfg;
396     int                nodePassesPolicy;
397     int32_t            retVal = RM_OK;
399     if (opInfo->operation == Rm_allocatorOp_PRE_ALLOCATE_INIT) {
400         policyCheckType = Rm_policyCheck_INIT;
401     }
402     else if (opInfo->operation == Rm_allocatorOp_PRE_ALLOCATE_USE) {
403         policyCheckType = Rm_policyCheck_USE;
404     }
405     else {
406         retVal = RM_ERROR_INVALID_SERVICE_TYPE;
407         return (retVal);
408     }
410     if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
411         /* Set base to first node's base since CD will not have all resources like Server */
412         matchingNode = RB_MIN(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry);
413         opInfo->resourceInfo->base = matchingNode->base;
414     }
415     else {
416         opInfo->resourceInfo->base = rmPolicyGetResourceBase(opInfo->policy, opInfo->serviceSrcInstNode, 
417                                                              resourcePolicy, policyCheckType, 
418                                                              &retVal);
419     }
420     
421     if (retVal != RM_OK) {
422         return (retVal);
423     }
425     if (opInfo->resourceInfo->alignment == RM_RESOURCE_ALIGNMENT_UNSPECIFIED) {  
426         /* Get alignment from policy */
427         opInfo->resourceInfo->alignment = rmPolicyGetResourceAlignment(opInfo->policy, resourcePolicy);
428     }
429     
430     if (opInfo->resourceInfo->alignment == 0) {
431         opInfo->resourceInfo->alignment = 1;
432     }    
434     memset((void *)&findNode, 0, sizeof(findNode));
435     findNode.base = opInfo->resourceInfo->base;
436     findNode.length = opInfo->resourceInfo->length;
438     /* Configure policy checking structure */
439     memset((void *)&policyCheckCfg, 0, sizeof(policyCheckCfg));
440     policyCheckCfg.policyDtb = opInfo->policy;
441     policyCheckCfg.resourceOffset = resourcePolicy;
442     
443     do {
444         matchingNode = RB_FIND(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, &findNode);
445         
446         if (matchingNode) {
447             matchingEnd = matchingNode->base + matchingNode->length - 1;
448             findEnd = findNode.base + findNode.length - 1;
449             if ((matchingNode->allocationCount == 0) &&
450                 (findNode.base >= matchingNode->base) && (findEnd <= matchingEnd)) {
451                 /* Attempt to preallocate from node only if not owned by anyone and sits
452                  * within a matching node. */
453                 nodePassesPolicy = RM_FALSE;
454                 policyCheckCfg.type = policyCheckType;
455                 policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;
456                 policyCheckCfg.resourceBase = findNode.base;
457                 policyCheckCfg.resourceLength = findNode.length;
458                 nodePassesPolicy = rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);    
459                 
460                 if (nodePassesPolicy && (matchingNode->allocationCount > 0)) {
461                     policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;
462                     
463                     if (allocatorResNodeIsOwnedBy(rmHandle, matchingNode, rmPolicyGetLinuxInstNode(rmHandle))) {
464                         /* Check if instance requesting resource has privileges to share
465                          * a resource already reserved by Linux */
466                         policyCheckCfg.type = Rm_policyCheck_SHARED_LINUX;
467                         nodePassesPolicy = rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);
468                     }
470                     if (nodePassesPolicy) {
471                         /* Check exclusive privileges of instance requesting resource.  Requesting
472                          * instance with exclusive privileges can't reserve resource if already owned*/
473                         policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;
474                         nodePassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);
475                     }
476                 }
477                 
478                 if (nodePassesPolicy && (matchingNode->allocationCount == 1)) {
479                     /* Check exclusive privileges of instance that currently owns resource */
480                     policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;
481                     policyCheckCfg.validInstNode = matchingNode->ownerList->instNameNode;
482                     nodePassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);
483                 }
485                 if (retVal != RM_OK) {
486                     break;
487                 }
489                 if (nodePassesPolicy) {
490                     /* Initialize indexer to be first resource value that alignment satisfies */
491                     rangeIndex = findNode.base;
492                     if (rangeIndex % opInfo->resourceInfo->alignment) {
493                         rangeIndex += (opInfo->resourceInfo->alignment -
494                                       (rangeIndex % opInfo->resourceInfo->alignment));
495                     }
496                     
497                     if ((rangeIndex + opInfo->resourceInfo->length - 1) <= matchingEnd) {
498                         /* Block of unallocated resources within matchingNode that satisfies
499                          * allocate requirements */
500                         opInfo->resourceInfo->base = rangeIndex;
501                         resourceFound = RM_TRUE;
502                         retVal = RM_SERVICE_PROCESSING;
503                     }     
504                 }
505             }
506             
507             if (!resourceFound) {
508                 /* Check next resource node for available resources */
509                 if (findNode.base < matchingNode->base) {
510                     findNode.base = matchingNode->base;
511                 }
512                 else {
513                     if (nextNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode)) {
514                         findNode.base = nextNode->base;
515                     }
516                     else {
517                         retVal = RM_SERVICE_DENIED_RES_ALLOC_REQS_NOT_MET;
518                     }
519                 }
520             }
521         }
522         else {
523             retVal = RM_SERVICE_DENIED_RES_ALLOC_REQS_NOT_MET;
524         }
525     } while ((!resourceFound) && 
526              (retVal != RM_SERVICE_DENIED_RES_ALLOC_REQS_NOT_MET));
528     return(retVal); 
531 /* FUNCTION PURPOSE: Allocates an allocator resource
532  ***********************************************************************
533  * DESCRIPTION: Will attempt to allocate the resource with specified
534  *              base and length from the resource's allocator.  The
535  *              allocation algorithm will verify the allocation against
536  *              the policy permissions for the instance requesting the
537  *              allocation.  If the policy allows the allocation the 
538  *              algorithm will allocate the resource then combine any
539  *              resource nodes that may have become equivalent (in terms
540  *              of ownership) after the allocation.
541  */
542 static int32_t allocatorAllocate(Rm_Handle rmHandle, Rm_Allocator *allocator, int32_t resourcePolicy, 
543                                  Rm_AllocatorOpInfo *opInfo)
545     Rm_ResourceNode     findNode;
546     Rm_ResourceNode    *matchingNode = NULL;
547     Rm_ResourceNode    *leftNode = NULL;
548     Rm_ResourceNode    *rightNode = NULL;
549     Rm_PolicyCheckType  policyCheckType;    
550     Rm_PolicyCheckCfg   policyCheckCfg;
551     int                 allocPassesPolicy;
552     int                 combineLeft = RM_FALSE;
553     int                 combineRight = RM_FALSE;    
554     uint32_t            findEnd;
555     uint32_t            matchingEnd;  
556     int32_t             retVal;
558     if (opInfo->operation == Rm_allocatorOp_ALLOCATE_INIT) {
559         policyCheckType = Rm_policyCheck_INIT;
560     }
561     else if (opInfo->operation == Rm_allocatorOp_ALLOCATE_USE) {
562         policyCheckType = Rm_policyCheck_USE;
563     }
564     else {
565         retVal = RM_ERROR_INVALID_SERVICE_TYPE;
566         return (retVal);
567     }   
569     memset((void *)&findNode, 0, sizeof(findNode));
570     findNode.base = opInfo->resourceInfo->base;
571     findNode.length = opInfo->resourceInfo->length;
572     matchingNode = RB_FIND(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, &findNode);
574     /* Prepare privilege checks */
575     memset((void *)&policyCheckCfg, 0, sizeof(policyCheckCfg)); 
577     if (matchingNode) {
578         findEnd = findNode.base + findNode.length - 1;
579         matchingEnd = matchingNode->base + matchingNode->length - 1;
580         
581         if ((findNode.base >= matchingNode->base) && (findEnd <= matchingEnd)) {
582             if (opInfo->serviceSrcInstNode == rmPolicyGetLinuxInstNode(rmHandle)) {
583                 /* Bypass policy checks since Linux Kernel has full privileges */
584                 allocPassesPolicy = RM_TRUE;
585             }
586             else {
587                 policyCheckCfg.policyDtb = opInfo->policy;
588                 policyCheckCfg.resourceOffset = resourcePolicy;    
589                 policyCheckCfg.type = policyCheckType;
590                 policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;
591                 policyCheckCfg.resourceBase = findNode.base;
592                 policyCheckCfg.resourceLength = findNode.length;
593                 allocPassesPolicy = rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);
594                 if (!allocPassesPolicy) {
595                     if (policyCheckType == Rm_policyCheck_INIT) {
596                         retVal = RM_SERVICE_DENIED_INIT_PERM_NOT_GIVEN;
597                     }
598                     else {
599                         retVal = RM_SERVICE_DENIED_USE_PERM_NOT_GIVEN;
600                     }
601                 }
603                 if (!allocatorResNodeIsOwnedBy(rmHandle, matchingNode, opInfo->serviceSrcInstNode)) {
604                     if (allocPassesPolicy && (matchingNode->allocationCount > 0)) {
605                         if (allocatorResNodeIsOwnedBy(rmHandle, matchingNode, rmPolicyGetLinuxInstNode(rmHandle))) {
606                             /* Check if instance requesting resource has privileges to share
607                              * a resource already reserved by Linux */
608                             policyCheckCfg.type = Rm_policyCheck_SHARED_LINUX;
609                             policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;
610                             allocPassesPolicy = rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);
611                             if (!allocPassesPolicy) {
612                                 retVal = RM_SERVICE_DENIED_RES_NOT_SHARED_LINUX;
613                             }
614                         }
615                         if (allocPassesPolicy) {
616                             /* Check exclusive privileges of instance requesting resource.  Requesting
617                              * instance with exclusive privileges can't reserve resource if already owned*/
618                             policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;
619                             policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;
620                             allocPassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);
621                             if (!allocPassesPolicy) {
622                                 retVal = RM_SERVICE_DENIED_EXCLUSIVE_RES_ALLOCD;
623                             }
624                         }
625                     }
626                     if (allocPassesPolicy && (matchingNode->allocationCount == 1)) {
627                         /* Check exclusive privileges of instance that currently owns resource */
628                         policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;
629                         policyCheckCfg.validInstNode = matchingNode->ownerList->instNameNode;
630                         allocPassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);
631                         if (!allocPassesPolicy) {
632                             retVal = RM_SERVICE_DENIED_ALLOCD_TO_EXCLUSIVE_INST;
633                         }                
634                     }  
635                 }
636             }
637             
638             if (allocPassesPolicy) {
639                 if (!allocatorResNodeIsOwnedBy(rmHandle, matchingNode, opInfo->serviceSrcInstNode)) {
640                     /* Handle any possible node combinations if requesting instance is
641                      * not already in resource's owner list.  Automatic approval if requesting
642                      * instance is already in owner list. */
643                     if ((findNode.base == matchingNode->base) && (findEnd == matchingEnd)) {
644                         /* findNode range matches matchingNode range
645                          *
646                          *   |<--left node-->||<--matched  node-->||<--right node-->| => existing node
647                          *                    |<--alloc request-->|  => requested resources
648                          */                     
649                         leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
650                         rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
651                         RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
652                         allocatorResNodeOwnerAdd(rmHandle, matchingNode, opInfo->serviceSrcInstNode);
654                         if (leftNode && allocatorResNodeOwnerCompare(rmHandle, leftNode, matchingNode) &&
655                             allocatorResNodeBoundaryCompare(leftNode, matchingNode)) {
656                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
657                             combineLeft = RM_TRUE;
658                         }
659                         if (rightNode && allocatorResNodeOwnerCompare(rmHandle, rightNode, matchingNode) &&
660                             allocatorResNodeBoundaryCompare(rightNode, matchingNode)) {
661                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
662                             combineRight = RM_TRUE;
663                         }
665                         if (combineLeft && combineRight) {
666                             /* Combine all three nodes into matchingNode */
667                             matchingNode->base = leftNode->base;
668                             matchingNode->length = leftNode->length + matchingNode->length + rightNode->length;
670                             allocatorResNodeOwnerClear(rmHandle, leftNode);
671                             rmResourceNodeFree(leftNode);
672                             allocatorResNodeOwnerClear(rmHandle, rightNode);
673                             rmResourceNodeFree(rightNode);                        
674                         }
675                         else if (combineLeft) {
676                             /* Combine left and matching nodes.  Reinsert right. */
677                             matchingNode->base = leftNode->base;
678                             matchingNode->length += leftNode->length;
680                             allocatorResNodeOwnerClear(rmHandle, leftNode);
681                             rmResourceNodeFree(leftNode);
682                             if (rightNode) {
683                                 RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);  
684                             }
685                         }
686                         else if (combineRight) {
687                             /* Combine right and matching nodes.  Reinsert left. */
688                             matchingNode->length += rightNode->length;
690                             allocatorResNodeOwnerClear(rmHandle, rightNode);
691                             rmResourceNodeFree(rightNode);
692                             if (leftNode) {
693                                 RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
694                             }
695                         }
696                         else {
697                             /* No combine. */
698                             if (leftNode) {
699                                 RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
700                             }
701                             if (rightNode) {
702                                 RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
703                             }
704                         }
706                         /* Always reinsert matchingNode */                
707                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
708                         
709                         /* Matching node contains new reference count after alloc.  Return new owner count. */
710                         opInfo->resourceInfo->ownerCount = matchingNode->allocationCount;
711                     }   
712                     else if ((findNode.base > matchingNode->base) && (findEnd < matchingEnd)) {
713                         /* findNode range is subset of matchingNode range and neither boundary is
714                          * equivalent.
715                          *
716                          * |<----------matched node---------->|
717                          *        |<---alloc request--->|
718                          */ 
719                         RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
720                         leftNode = rmResourceNodeNew(matchingNode->base, findNode.base - matchingNode->base);
721                         allocatorResNodeOwnerCopy(rmHandle, leftNode, matchingNode);
722                         rightNode = rmResourceNodeNew(findNode.base + findNode.length, matchingEnd - findEnd);
723                         allocatorResNodeOwnerCopy(rmHandle, rightNode, matchingNode);
725                         matchingNode->base = findNode.base;                                    
726                         matchingNode->length = findNode.length;
727                         allocatorResNodeOwnerAdd(rmHandle, matchingNode, opInfo->serviceSrcInstNode);
729                         /* Insert all the nodes */
730                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
731                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
732                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
733                         
734                         /* Matching node contains new reference count after alloc.  Return new owner count. */
735                         opInfo->resourceInfo->ownerCount = matchingNode->allocationCount;
736                     }  
737                     else {    
738                         if (findNode.base == matchingNode->base) {
739                             /* findNode base and matchingNode base are equivalent.  May be combine
740                              * possibilities to the left
741                              *
742                              * |<---left node (alloc'd)--->||<----------matched node---------->|
743                              *                              |<---findNode (alloc req)--->|
744                              */                         
745                             leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
746                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
747                             /* Add allocating instance to owner list for compare with leftNode */
748                             allocatorResNodeOwnerAdd(rmHandle, matchingNode, opInfo->serviceSrcInstNode);
749                             
750                             if (leftNode && allocatorResNodeOwnerCompare(rmHandle, leftNode, matchingNode) &&
751                                 allocatorResNodeBoundaryCompare(leftNode, matchingNode)) {
752                                 RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
753                                 /* Combine leftNode and findNode */
754                                 leftNode->length += findNode.length;
755                             }
756                             else {
757                                 leftNode = rmResourceNodeNew(findNode.base, findNode.length);
758                                 allocatorResNodeOwnerCopy(rmHandle, leftNode, matchingNode);
759                             }
761                             /* Account for leftNode in matchingNode */
762                             matchingNode->base = findNode.base + findNode.length;
763                             matchingNode->length = matchingEnd - findEnd;  
765                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
766                             /* Left node contains new reference count after alloc.  Return new owner count. */
767                             opInfo->resourceInfo->ownerCount = leftNode->allocationCount;
768                         }
769                         else if (findEnd == matchingEnd) {
770                             /* findNode end and matchingNode end are equivalent.  May be combine
771                              * possibilities to the right
772                              *
773                              * |<----------matched node---------->||<---right node (alloc'd)--->|
774                              *       |<---findNode (alloc req)--->| 
775                              */                        
776                             rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
777                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
778                             /* Add allocating instance to owner list for compare with rightNode */
779                             allocatorResNodeOwnerAdd(rmHandle, matchingNode, opInfo->serviceSrcInstNode);
780                             
781                             if (rightNode && allocatorResNodeOwnerCompare(rmHandle, rightNode, matchingNode) &&
782                                 allocatorResNodeBoundaryCompare(rightNode, matchingNode)) {
783                                 RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
784                                 /* Combine rightNode and findNode */
785                                 rightNode->base = findNode.base;
786                                 rightNode->length += findNode.length;
787                             }
788                             else {
789                                 rightNode = rmResourceNodeNew(findNode.base, findNode.length);
790                                 allocatorResNodeOwnerCopy(rmHandle, rightNode, matchingNode);
791                             }
793                             /* Account for rightNode in matchingNode */
794                             matchingNode->length -= findNode.length;  
796                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
797                             /* Right node contains new reference count after alloc.  Return new owner count. */
798                             opInfo->resourceInfo->ownerCount = rightNode->allocationCount;
799                         }
800                         /* Remove allocating instance from leftover matchingNode */
801                         allocatorResNodeOwnerDelete(rmHandle, matchingNode, opInfo->serviceSrcInstNode);
802                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
803                     }
804                 }
805                 retVal = RM_SERVICE_APPROVED;
806             }
807         }
808         else {
809             retVal = RM_SERVICE_DENIED_PARTIAL_ALLOCATION;
810         }
811     }
812     else {
813         retVal = RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST;
814     }
816     return(retVal);        
819 /* FUNCTION PURPOSE: Frees an allocator resource
820  ***********************************************************************
821  * DESCRIPTION: Will attempt to free the resource with specified
822  *              base and length from the resource's allocator.  The
823  *              free algorithm will verify the free request parameters
824  *              match an allocated range for the resource and that the
825  *              range is owned by the instance requesting the free. If
826  *              the free is validated the algorithm will free the 
827  *              resource then combine any resource nodes that may have
828  *              become equivalent (in terms of ownership) after the
829  *              allocation.
830  */
831 static int32_t allocatorFree(Rm_Handle rmHandle, Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)
833     Rm_ResourceNode  findNode;
834     Rm_ResourceNode *matchingNode = NULL;
835     Rm_ResourceNode *leftNode = NULL;
836     Rm_ResourceNode *rightNode = NULL;
837     int              combineLeft = RM_FALSE;
838     int              combineRight = RM_FALSE;
839     uint32_t         findEnd;
840     uint32_t         matchingEnd;
841     int32_t          retVal;
843     memset((void *)&findNode, 0, sizeof(findNode));
844     findNode.base = opInfo->resourceInfo->base;
845     findNode.length = opInfo->resourceInfo->length;
846     matchingNode = RB_FIND(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, &findNode);
848     if (matchingNode) {
849         findEnd = findNode.base + findNode.length - 1;
850         matchingEnd = matchingNode->base + matchingNode->length - 1;
851         
852         if ((findNode.base >= matchingNode->base) && (findEnd <= matchingEnd)) {  
853             if (matchingNode->allocationCount) {
854                 if (allocatorResNodeIsOwnedBy(rmHandle, matchingNode, opInfo->serviceSrcInstNode)) {
855                     if ((findNode.base == matchingNode->base) && (findEnd == matchingEnd))
856                     {
857                         /* Case 1: Free range equals allocated matched node exactly. Attempt to combine 
858                          *         freed node with nodes to left and right.
859                          *
860                          * |<--left node-->||<---matched node--->||<--right node-->|
861                          *                  |<---free request--->|
862                          */ 
863                         leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
864                         rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
865                         RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
866                         allocatorResNodeOwnerDelete(rmHandle, matchingNode, opInfo->serviceSrcInstNode);
868                         if (leftNode && allocatorResNodeOwnerCompare(rmHandle, leftNode, matchingNode) &&
869                             allocatorResNodeBoundaryCompare(leftNode, matchingNode)) {
870                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
871                             combineLeft = RM_TRUE;
872                         }
873                         if (rightNode && allocatorResNodeOwnerCompare(rmHandle, rightNode, matchingNode) &&
874                             allocatorResNodeBoundaryCompare(rightNode, matchingNode)) {
875                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
876                             combineRight = RM_TRUE;
877                         }
879                         if (combineLeft && combineRight) {
880                             /* Combine all three nodes into matchingNode */
881                             matchingNode->base = leftNode->base;
882                             matchingNode->length = leftNode->length + matchingNode->length + rightNode->length;
884                             allocatorResNodeOwnerClear(rmHandle, leftNode);
885                             rmResourceNodeFree(leftNode);
886                             allocatorResNodeOwnerClear(rmHandle, rightNode);
887                             rmResourceNodeFree(rightNode);                        
888                         }
889                         else if (combineLeft) {
890                             /* Combine left and matching nodes.  Reinsert right. */
891                             matchingNode->base = leftNode->base;
892                             matchingNode->length += leftNode->length;
894                             allocatorResNodeOwnerClear(rmHandle, leftNode);
895                             rmResourceNodeFree(leftNode);
896                             if (rightNode) {
897                                 RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode); 
898                             }
899                         }
900                         else if (combineRight) {
901                             /* Combine right and matching nodes.  Reinsert left. */
902                             matchingNode->length += rightNode->length;
904                             allocatorResNodeOwnerClear(rmHandle, rightNode);
905                             rmResourceNodeFree(rightNode);
906                             if (leftNode) {
907                                 RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
908                             }
909                         }
910                         else {
911                             /* No combine. */
912                             if (leftNode) {
913                                 RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
914                             }
915                             if (rightNode) {
916                                 RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
917                             }
918                         }
920                         /* Always reinsert matchingNode */
921                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
922                         
923                         /* Matching node is what remains after free.  Return remaining owner count. */
924                         opInfo->resourceInfo->ownerCount = matchingNode->allocationCount;
925                     }
926                     else if ((findNode.base > matchingNode->base) && (findEnd < matchingEnd)) {
927                         /* Case 2: Free range is less than range in matched node. Split
928                          *         matched node into three nodes.
929                          *
930                          * |<----------matched node---------->|
931                          *        |<---free request--->|
932                          *
933                          * Remove instance from AllocatedTo list then add it back in for side nodes for
934                          * proper accounting of allocations in validInstance list
935                          */ 
936                         RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
937                         allocatorResNodeOwnerDelete(rmHandle, matchingNode, opInfo->serviceSrcInstNode);
938                         
939                         leftNode = rmResourceNodeNew(matchingNode->base, findNode.base - matchingNode->base);
940                         allocatorResNodeOwnerCopy(rmHandle, leftNode, matchingNode);
941                         allocatorResNodeOwnerAdd(rmHandle, leftNode, opInfo->serviceSrcInstNode);
942                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
943                         
944                         rightNode = rmResourceNodeNew(findNode.base + findNode.length, matchingEnd - findEnd);
945                         allocatorResNodeOwnerCopy(rmHandle, rightNode, matchingNode);
946                         allocatorResNodeOwnerAdd(rmHandle, rightNode, opInfo->serviceSrcInstNode);
947                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
949                         matchingNode->base = findNode.base;                                    
950                         matchingNode->length = findNode.length;
951                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
952                         
953                         /* Matching node is what remains after free.  Return remaining owner count. */
954                         opInfo->resourceInfo->ownerCount = matchingNode->allocationCount;
955                     }
956                     else {                        
957                         if (findNode.base == matchingNode->base) {
958                             /* Case 3: Free range is on left boundary of matched node. Try to 
959                              *         combine free range with left node.
960                              *
961                              * |<---left node (free)--->||<----------matched node---------->|
962                              *                           |<---findNode (free req)--->|
963                              */ 
965                             leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
966                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
967                             /* Remove freeing instance from owner list for compare with leftNode */
968                             allocatorResNodeOwnerDelete(rmHandle, matchingNode, opInfo->serviceSrcInstNode);
969                             
970                             if (leftNode && allocatorResNodeOwnerCompare(rmHandle, leftNode, matchingNode) &&
971                                 allocatorResNodeBoundaryCompare(leftNode, matchingNode)) {
972                                 RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
973                                 /* Combine leftNode and findNode */
974                                 leftNode->length += findNode.length;
975                             }
976                             else {
977                                 leftNode = rmResourceNodeNew(findNode.base, findNode.length);
978                                 allocatorResNodeOwnerCopy(rmHandle, leftNode, matchingNode);
979                             }
981                             /* Remove leftNode range from matchingNode */
982                             matchingNode->base = findNode.base + findNode.length;
983                             matchingNode->length = matchingEnd - findEnd;  
984                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
985                             
986                             /* Left node is what remains after free.  Return remaining owner count. */
987                             opInfo->resourceInfo->ownerCount = leftNode->allocationCount;
988                         }
989                         else if (findEnd == matchingEnd) {
990                             /* Case 4: Free range is on right boundary of matched node. Try to 
991                              *         combine free range with right node.
992                              *
993                              * |<----------matched node---------->||<---right node (free)--->|
994                              *        |<---findNode (free req)--->|
995                              */ 
996                             
997                             rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
998                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode); 
999                             /* Remove freeing instance from owner list for compare with rightNode */
1000                             allocatorResNodeOwnerDelete(rmHandle, matchingNode, opInfo->serviceSrcInstNode);
1001                             
1002                             if (rightNode && allocatorResNodeOwnerCompare(rmHandle, rightNode, matchingNode) &&
1003                                 allocatorResNodeBoundaryCompare(rightNode, matchingNode)) {
1004                                 RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
1005                                 /* Combine rightNode and findNode */
1006                                 rightNode->base = findNode.base;
1007                                 rightNode->length += findNode.length;
1008                             }
1009                             else {
1010                                 rightNode = rmResourceNodeNew(findNode.base, findNode.length);
1011                                 allocatorResNodeOwnerCopy(rmHandle, rightNode, matchingNode);
1012                             }
1014                             /* Remove rightNode range from matchingNode */
1015                             matchingNode->length -= findNode.length;  
1016                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
1017                             
1018                             /* Right node is what remains after free.  Return remaining owner count. */
1019                             opInfo->resourceInfo->ownerCount = rightNode->allocationCount;
1020                         }
1022                         /* Add freeing instance back into matchingNode allocations */
1023                         allocatorResNodeOwnerAdd(rmHandle, matchingNode, opInfo->serviceSrcInstNode);
1024                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
1025                     }
1026                     retVal = RM_SERVICE_APPROVED;
1027                 }
1028                 else {
1029                     /* Return owner count.  In case it's a reference count check in application */
1030                     opInfo->resourceInfo->ownerCount = matchingNode->allocationCount;
1031                     retVal = RM_SERVICE_DENIED_RES_NOT_ALLOCD_TO_INST;
1032                 }
1033             }
1034             else {
1035                 /* Return owner count.  In case it's a reference count check in application */
1036                 opInfo->resourceInfo->ownerCount = matchingNode->allocationCount;
1037                 retVal = RM_SERVICE_DENIED_RES_ALREADY_FREE;
1038             }
1039         }
1040         else {
1041             retVal = RM_SERVICE_DENIED_PARTIAL_FREE;
1042         }
1043     }
1044     else {
1045         retVal = RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST;
1046     }
1047     return(retVal);  
1050 /* FUNCTION PURPOSE: Reserves a Linux resource
1051  ***********************************************************************
1052  * DESCRIPTION: Reserves resources for Linux using the base and length
1053  *              values retrieved from the Linux DTB via the
1054  *              "linux-dtb-alias" properties within the GRL.
1055  */
1056 static int32_t allocatorReserveLinuxResource(Rm_Handle rmHandle, Rm_LinuxAlias *linuxAlias, 
1057                                              Rm_LinuxValueRange *linuxValues, Rm_AllocatorOpInfo *opInfo)
1059     int32_t   retVal = RM_OK;
1060     int       baseFound = RM_FALSE;
1061     int       lengthFound = RM_FALSE;
1062     uint32_t  valueIndex = 0;
1064     while ((linuxValues) && (!baseFound || !lengthFound)) {
1065         if (linuxAlias->baseOffset == valueIndex) {
1066             opInfo->resourceInfo->base = linuxValues->value;
1067             baseFound = RM_TRUE;
1069             if (linuxAlias->lengthOffset == RM_DTB_UTIL_LINUX_ALIAS_OFFSET_NOT_SET) {
1070                 opInfo->resourceInfo->length = 1;
1071                 lengthFound = RM_TRUE;
1072             }
1073         }
1074         else if (linuxAlias->lengthOffset == valueIndex) {
1075             opInfo->resourceInfo->length = linuxValues->value;
1076             lengthFound = RM_TRUE;
1077         }
1079         linuxValues = (Rm_LinuxValueRange *)linuxValues->nextValue;
1080         valueIndex++;
1081     }
1083     if (!baseFound || !lengthFound) {
1084         retVal = RM_ERROR_DATA_NOT_FOUND_AT_LINUX_ALIAS;
1085     }
1086     else {
1087         /* Allocate resource to Linux */
1088         retVal = rmAllocatorOperation(rmHandle, opInfo);
1089         if (retVal == RM_SERVICE_APPROVED) {
1090             retVal = RM_OK;
1091         }
1092     }
1093     return (retVal);
1096 /* FUNCTION PURPOSE: Finds and reserves Linux resources
1097  ***********************************************************************
1098  * DESCRIPTION: Parses the Linux DTB for resources consumed by the
1099  *              Linux kernel.  If the resource is found via the
1100  *              "linux-dtb-alias" property defined in the GRL it is 
1101  *              reserved.
1102  */
1103 static int32_t allocatorFindLinuxResource(Rm_Handle rmHandle, const char *resourceName, void *linuxDtb, 
1104                                           Rm_LinuxAlias *linuxAlias)
1106     Rm_Inst            *rmInst = (Rm_Inst *)rmHandle;
1107     Rm_AllocatorOpInfo  opInfo;
1108     Rm_ResourceInfo     resourceInfo;
1109     uint32_t            pathOffset;
1110     uint32_t            pathSize;
1111     char               *spacePtr;
1112     int32_t             propOffset;
1113     int32_t             nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;
1114     int32_t             prevDepth = RM_DTB_UTIL_STARTING_DEPTH;
1115     int32_t             depth = RM_DTB_UTIL_STARTING_DEPTH;
1116     int32_t             propertyLen;
1117     const char         *propertyName;
1118     const void         *propertyData; 
1119     Rm_LinuxValueRange *linuxValueRange;
1120     int32_t             retVal = RM_OK; 
1122     memset((void *)&opInfo, 0, sizeof(opInfo));
1123     memset((void *)&resourceInfo, 0, sizeof(resourceInfo));
1125     strncpy(resourceInfo.name, resourceName, RM_NAME_MAX_CHARS);
1126     opInfo.policy = rmInst->u.server.globalPolicy;
1127     opInfo.serviceSrcInstNode = rmPolicyGetLinuxInstNode(rmHandle);
1128     opInfo.operation = Rm_allocatorOp_ALLOCATE_INIT;
1129     opInfo.resourceInfo = &resourceInfo;    
1131     while(linuxAlias) {
1132         /* Reset parsing variables */
1133         pathOffset = 0;
1134         pathSize = strlen(linuxAlias->path) + 1;
1135         nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;
1136         prevDepth = RM_DTB_UTIL_STARTING_DEPTH;   
1137         resourceInfo.base = 0;
1138         resourceInfo.length = 0;
1140         spacePtr = strpbrk(linuxAlias->path, " ");
1141         if (spacePtr) {
1142             *spacePtr = '\0';
1143         }       
1144         
1145         while(pathOffset < pathSize) {
1146             /* Move through DTB nodes until next alias path node found */
1147             if (strcmp(linuxAlias->path + pathOffset, fdt_get_name(linuxDtb, nodeOffset, NULL))) {
1148                 nodeOffset = fdt_next_node(linuxDtb, nodeOffset, &depth);
1150                 if ((depth < prevDepth) || (nodeOffset == -FDT_ERR_NOTFOUND)) {
1151                     /* Returning from subnode that matched part of alias path without finding
1152                      * resource values */
1153                     retVal = RM_ERROR_DATA_NOT_FOUND_AT_LINUX_ALIAS;
1154                     break;
1155                 }
1156             }
1157             else {
1158                 /* Found next alias path node.  Move to next node name in path string. */
1159                 pathOffset += (strlen(linuxAlias->path + pathOffset) + 1);
1160                 spacePtr = strpbrk(linuxAlias->path + pathOffset, " ");
1161                 if (spacePtr) {
1162                     *spacePtr = '\0';
1163                 }       
1164                 
1165                 prevDepth = fdt_node_depth(linuxDtb, nodeOffset);
1166                 propOffset = fdt_first_property_offset(linuxDtb, nodeOffset);
1167                 while ((propOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) &&
1168                        (pathOffset < pathSize)) {
1169                     propertyData = fdt_getprop_by_offset(linuxDtb, propOffset, 
1170                                                          &propertyName, &propertyLen);
1172                     if (strcmp(linuxAlias->path + pathOffset, propertyName) == 0) {
1173                         /* Found resource at end of alias path */
1174                         pathOffset += (strlen(linuxAlias->path + pathOffset) + 1);
1175                         linuxValueRange = rmDtbUtilLinuxExtractValues(propertyData, propertyLen);
1176                         retVal = allocatorReserveLinuxResource(rmHandle, linuxAlias, 
1177                                                                linuxValueRange, &opInfo);
1178                         rmDtbUtilLinuxFreeValues(linuxValueRange);
1179                     }
1180                     propOffset = fdt_next_property_offset(linuxDtb, propOffset);
1181                 } 
1183                 if (propOffset < -FDT_ERR_NOTFOUND) {
1184                     retVal = propOffset;
1185                     break;
1186                 }
1187             }
1188         }
1190         if (retVal < RM_OK) {
1191             break;
1192         }
1193         linuxAlias = linuxAlias->nextLinuxAlias;
1194     }
1195     return (retVal);
1198 /* FUNCTION PURPOSE: Creates and initializes a resource allocator
1199  ***********************************************************************
1200  * DESCRIPTION: Creates a resource allocator for the provided
1201  *              resource name and resource properties retrieved
1202  *              from the GRL.  Resources will be reserved for 
1203  *              the Linux kernel if the Linux DTB is provided
1204  *              and there are "linux-dtb-alias" properties
1205  *              specified in the GRL.
1206  */
1207 static int32_t allocatorExtractGrlResProps(Rm_Handle rmHandle, const char *resourceName, 
1208                                            Rm_ResourceProperties *resourceProperties, void *linuxDtb)
1210     Rm_Inst             *rmInst = (Rm_Inst *)rmHandle;
1211     Rm_ResourceRange    *range = NULL;
1212     Rm_ResourceRange    *rangeBasePtr = NULL;
1213     Rm_NsAssignment     *nsAssignments = NULL;
1214     Rm_NsAssignment     *nsAssignmentBasePtr = NULL;
1215     Rm_LinuxAlias       *linuxAlias = NULL;
1216     Rm_NameServerObjCfg  nameServerObjCfg;      
1217     int32_t              retVal = RM_OK;
1219     if (resourceProperties->rangeData && (resourceProperties->rangeLen > 0)) {
1220         range = rangeBasePtr = rmDtbUtilResExtractRange(resourceProperties->rangeData, 
1221                                                         resourceProperties->rangeLen);
1222         
1223         if ((retVal = rmAllocatorCreate(rmHandle, resourceName, range)) >= RM_OK) {
1224             if (resourceProperties->linuxAliasData && resourceProperties->linuxAliasLen) {
1225                 if (linuxDtb) {
1226                     linuxAlias = rmDtbUtilResExtractLinuxAlias(resourceProperties->linuxAliasData,
1227                                                                resourceProperties->linuxAliasLen, &retVal);
1228                     if (linuxAlias) {
1229                         retVal = allocatorFindLinuxResource(rmHandle, resourceName, linuxDtb, linuxAlias);            
1230                     }
1231                 }
1232             }
1233         }
1234     }
1235     
1236     if (retVal >= RM_OK) {
1237         if (resourceProperties->nsAssignData && resourceProperties->nsAssignLen) {
1238             nsAssignments = rmDtbUtilResExtractNsAssignment(resourceProperties->nsAssignData, 
1239                                                             resourceProperties->nsAssignLen, &retVal);
1240             if (nsAssignments) {
1241                 nsAssignmentBasePtr = nsAssignments;
1242                 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1243                     rmNameServerTreeInv(rmInst->u.server.nameServer);
1244                 }                  
1245                 while (nsAssignments) {
1246                     memset((void *)&nameServerObjCfg, 0, sizeof(nameServerObjCfg));
1247                     nameServerObjCfg.nameServerTree = rmInst->u.server.nameServer;
1248                     nameServerObjCfg.nodeCfg.objName = nsAssignments->nsName;
1249                     nameServerObjCfg.nodeCfg.resourceName = (char *)resourceName;
1250                     nameServerObjCfg.nodeCfg.resourceBase= nsAssignments->resourceBase;
1251                     nameServerObjCfg.nodeCfg.resourceLength = nsAssignments->resourceLength;                
1252                     rmNameServerAddObject(&nameServerObjCfg);
1253                     nsAssignments = nsAssignments->nextNsAssignment;
1254                 }
1255                 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1256                     rmNameServerTreeWb(rmInst->u.server.nameServer);
1257                 }                
1258                 rmDtbUtilResFreeNsAssignmentList(nsAssignmentBasePtr);
1259             }
1260         }
1261     }
1262     else {
1263         rmAllocatorDelete(rmHandle, resourceName);
1264     }
1266     rmDtbUtilResFreeRange(rangeBasePtr);
1267     if (linuxAlias) {
1268         rmDtbUtilResFreeLinuxAlias(linuxAlias);
1269     }
1270     return(retVal);
1273 /**********************************************************************
1274  ********************** Internal Functions ****************************
1275  **********************************************************************/
1277 /* FUNCTION PURPOSE: Creates a new resource tree
1278  ***********************************************************************
1279  * DESCRIPTION: Creates and populates a new resource tree allocator
1280  *              using the provided resource name and value range.  The
1281  *              name and value originate from the GRL.
1282  */
1283 int32_t rmAllocatorCreate(Rm_Handle rmHandle, const char *resourceName, Rm_ResourceRange *range)
1285     Rm_Inst         *rmInst = (Rm_Inst *)rmHandle;
1286     Rm_Allocator    *allocator = NULL;
1287     Rm_ResourceTree *treeRoot = NULL;
1288     Rm_ResourceNode *treeNode = NULL;
1290     allocator = allocatorAdd(rmHandle, resourceName);
1291     treeRoot = Rm_osalMalloc(sizeof(*treeRoot));
1292     RB_INIT(treeRoot);
1294     while (range != NULL) {
1295         treeNode = rmResourceNodeNew(range->base, range->length);
1296         RB_INSERT(_Rm_AllocatorResourceTree, treeRoot, treeNode);
1297         range = range->nextRange;
1298     }
1299     if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1300         rmResourceTreeWb(treeRoot);
1301     }
1302     
1303     allocator->allocatorRootEntry = treeRoot;
1304     RM_SS_OBJ_WB(allocator, Rm_Allocator);
1305     return(RM_OK);
1308 /* FUNCTION PURPOSE: Returns a pointer to the allocator list
1309  ***********************************************************************
1310  * DESCRIPTION: Returns a pointer to the instance's allocator list
1311  *              based on the instance type
1312  */
1313 Rm_Allocator *rmAllocatorGetAllocatorList(Rm_Handle rmHandle)
1315     Rm_Inst      *rmInst = (Rm_Inst *)rmHandle;
1316     Rm_Allocator *list = NULL;
1318     if ((rmInst->instType == Rm_instType_SERVER) ||
1319         (rmInst->instType == Rm_instType_SHARED_SERVER)) {
1320         list = rmInst->u.server.allocators;
1321     }
1322     else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1323         list = rmInst->u.cd.allocators;
1324     }
1325     return(list);
1328 /* FUNCTION PURPOSE: Finds an allocator
1329  ***********************************************************************
1330  * DESCRIPTION: Returns a pointer to an allocator that matches the 
1331  *              provided resource name.
1332  */
1333 Rm_Allocator *rmAllocatorFind(Rm_Handle rmHandle, const char *resourceName)
1335     Rm_Inst      *rmInst = (Rm_Inst *)rmHandle;
1336     Rm_Allocator *allocatorList = rmAllocatorGetAllocatorList(rmHandle);
1337     
1338     while (allocatorList) {
1339         RM_SS_OBJ_INV(allocatorList, Rm_Allocator);
1340         if (strncmp(allocatorList->resourceName, resourceName, RM_NAME_MAX_CHARS) == 0) {
1341             break;             
1342         }
1343         allocatorList = allocatorList->nextAllocator;
1344     }
1346     return (allocatorList);
1349 /* FUNCTION PURPOSE: Checks if a resource node is localized
1350  ***********************************************************************
1351  * DESCRIPTION: Checks if a resource node is localized.  A localized
1352  *              node is one that is free and has no neighboring nodes
1353  *              or neighboring nodes that do not have resource values
1354  *              contiguous with the node being checked.  The function
1355  *              will return RM_TRUE is the node is localized.  
1356  *              Otherwise, the function returns RM_FALSE
1357  */
1358 int rmAllocatorGetNodeLocalization(Rm_Handle rmHandle, char *resourceName, 
1359                                    int32_t *resBase, uint32_t *resLen)
1361     Rm_Inst         *rmInst = (Rm_Inst *)rmHandle;
1362     void *           policy = rmPolicyGetPolicy((Rm_Handle)rmInst);
1363     int32_t          resOffsetInPolicy = rmPolicyGetResourceOffset(policy, resourceName);
1364     uint32_t         allocSize = rmPolicyGetResourceCdAllocSize(policy, resOffsetInPolicy);    
1365     Rm_Allocator    *allocator = rmAllocatorFind(rmHandle, resourceName);
1366     Rm_ResourceNode  findNode;
1367     Rm_ResourceNode *matchingNode = NULL;
1368     Rm_ResourceNode *neighborNode = NULL;   
1369     int              nodeIsLocalized;
1371     memset((void *)&findNode, 0, sizeof(findNode));
1372     findNode.base = *resBase;
1373     findNode.length = *resLen;
1374     matchingNode = RB_FIND(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, &findNode);
1376     if (matchingNode) {
1377         /* Node can be freed back to Server from CD if:
1378          * - allocationCount == 0
1379          * - node's resource range is multiple of policy allocation size
1380          * - node's resource range boundaries are not contiguous with surrounding nodes */
1381         if (matchingNode->allocationCount) {
1382             nodeIsLocalized = RM_FALSE;
1383             goto exitLocalization;
1384         }
1385             
1386         if (matchingNode->length % allocSize) {
1387             nodeIsLocalized = RM_FALSE;
1388             goto exitLocalization;        
1389         }
1391         /* Check left neighbor */
1392         neighborNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
1393         if (neighborNode && allocatorResNodeBoundaryCompare(neighborNode, matchingNode)) {
1394             nodeIsLocalized = RM_FALSE;
1395             goto exitLocalization; 
1396         }
1398         /* Check right neighbor */
1399         neighborNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
1400         if (neighborNode && allocatorResNodeBoundaryCompare(neighborNode, matchingNode)) {
1401             nodeIsLocalized = RM_FALSE;
1402             goto exitLocalization; 
1403         }
1405         /* All localization checks passed.  Return the base and length of localized node. */
1406         nodeIsLocalized = RM_TRUE;
1407         *resBase = matchingNode->base;
1408         *resLen = matchingNode->length;
1409     }
1410     else {
1411         nodeIsLocalized = RM_FALSE;
1412     }
1414 exitLocalization:
1415     return (nodeIsLocalized);
1418 /* FUNCTION PURPOSE: Issues an allocator operation
1419  ***********************************************************************
1420  * DESCRIPTION: Issues an allocator preallocate, allocate, or free
1421  *              for an RM resource.
1422  */
1423 int32_t rmAllocatorOperation(Rm_Handle rmHandle, Rm_AllocatorOpInfo *opInfo)
1425     Rm_Inst      *rmInst = (Rm_Inst *)rmHandle;
1426     Rm_Allocator *allocator = NULL;
1427     int32_t       resourceOffsetInPolicy;
1428     int32_t       retVal;
1429     
1430     resourceOffsetInPolicy = rmPolicyGetResourceOffset(opInfo->policy, opInfo->resourceInfo->name);
1431     allocator = rmAllocatorFind(rmHandle, opInfo->resourceInfo->name);
1432     
1433     if ((resourceOffsetInPolicy > 0) && allocator) {
1434         if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1435             rmResourceTreeInv(allocator->allocatorRootEntry);
1436         }
1438         if (opInfo->operation == Rm_allocatorOp_GET_STATUS) {
1439             retVal = allocatorStatus(allocator, opInfo);
1440         }
1441         else if ((opInfo->operation == Rm_allocatorOp_PRE_ALLOCATE_INIT) ||
1442                  (opInfo->operation == Rm_allocatorOp_PRE_ALLOCATE_USE)) {
1443             retVal = allocatorPreAllocate(rmHandle, allocator, resourceOffsetInPolicy, opInfo);
1444         }               
1445         else if ((opInfo->operation == Rm_allocatorOp_ALLOCATE_INIT) ||
1446                  (opInfo->operation == Rm_allocatorOp_ALLOCATE_USE)) {
1447             retVal = allocatorAllocate(rmHandle, allocator, resourceOffsetInPolicy, opInfo);
1448         }
1449         else if (opInfo->operation == Rm_allocatorOp_FREE) {
1450             retVal = allocatorFree(rmHandle, allocator, opInfo);
1451         } 
1453         if ((rmInst->instType == Rm_instType_SHARED_SERVER) &&
1454             (opInfo->operation != Rm_allocatorOp_GET_STATUS) &&
1455             (retVal == RM_SERVICE_APPROVED)) {
1456             rmResourceTreeWb(allocator->allocatorRootEntry);
1457         }        
1458     }
1459     else {
1460         /* Resource could not be found in policy and/or allocator */
1461         retVal = RM_SERVICE_DENIED_RES_DOES_NOT_EXIST;
1462     }
1463     return(retVal);
1466 /* FUNCTION PURPOSE: Initializes server allocators
1467  ***********************************************************************
1468  * DESCRIPTION: Creates and initializes a server instance's
1469  *              resource allocators using the GRL and, if
1470  *              provided, Linux DTB.
1471  */
1472 int32_t rmAllocatorInitializeResources(Rm_Handle rmHandle, void *globalResourceDtb, void *linuxDtb)
1474     int32_t                nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;
1475     int32_t                nodeDepth = RM_DTB_UTIL_STARTING_DEPTH;
1476     Rm_ResourceProperties  resProperties;    
1477     int32_t                propOffset;
1478     int32_t                propertyLen;
1479     const char            *propertyName;
1480     const void            *propertyData;
1481     Rm_ResourcePropType    propertyType;  
1482     int32_t                retVal = RM_OK;
1484     /* Parse the Global Resource List, creating an allocator for each specified resource node */
1485     while ((nodeOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) && (nodeDepth >= RM_DTB_UTIL_STARTING_DEPTH)) {
1486         memset((void *)&resProperties, 0, sizeof(resProperties));
1487         /* Get properties of resource node */
1488         propOffset = fdt_first_property_offset(globalResourceDtb, nodeOffset);
1489         while (propOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) {
1490             propertyData = fdt_getprop_by_offset(globalResourceDtb, propOffset, &propertyName, &propertyLen);
1491             propertyType = rmDtbUtilResGetPropertyType(propertyName);
1492             if (propertyType == Rm_resourcePropType_RESOURCE_RANGE) {
1493                 resProperties.rangeData = propertyData;
1494                 resProperties.rangeLen = propertyLen;
1495             }
1496             else if (propertyType == Rm_resourcePropType_NSASSIGNMENT) {
1497                 resProperties.nsAssignData = propertyData;
1498                 resProperties.nsAssignLen = propertyLen;
1499             }
1500             else if (propertyType == Rm_resourcePropType_RESOURCE_LINUX_ALIAS) {
1501                 resProperties.linuxAliasData = propertyData;
1502                 resProperties.linuxAliasLen = propertyLen;
1503             }        
1504             else {
1505                 retVal = RM_ERROR_GRL_UNKNOWN_RESOURCE_PROPERTY;
1506                 goto exitAllocInit;
1507             }
1509             propOffset = fdt_next_property_offset(globalResourceDtb, propOffset);
1510             if (propOffset == -FDT_ERR_NOTFOUND) {
1511                 /* No more resource properties but at least one found.  Extract the property values */
1512                 retVal = allocatorExtractGrlResProps(rmHandle, fdt_get_name(globalResourceDtb, nodeOffset, NULL), 
1513                                                      &resProperties, linuxDtb);
1514                 if (retVal < RM_OK) {
1515                     goto exitAllocInit;
1516                 }
1517             }
1518             else if (propOffset < -FDT_ERR_NOTFOUND) {
1519                 /* Error returned by LIBFDT */
1520                 retVal = propOffset;
1521                 goto exitAllocInit;
1522             }
1523         }
1524         if (propOffset < -FDT_ERR_NOTFOUND) {
1525             /* Error returned by LIBFDT */
1526             retVal = propOffset;
1527             goto exitAllocInit;
1528         }
1530         nodeOffset = fdt_next_node(globalResourceDtb, nodeOffset, &nodeDepth);
1531         if (nodeOffset < -FDT_ERR_NOTFOUND) {
1532             /* Error returned by LIBFDT */
1533             retVal = nodeOffset;
1534             goto exitAllocInit;
1535         }
1536     }
1537 exitAllocInit:    
1538     return(retVal);
1541 /* FUNCTION PURPOSE: Deletes a resource allocator resource node
1542  ***********************************************************************
1543  * DESCRIPTION: Deletes a resource allocator's node based on the given
1544  *              resource name, base and length.
1545  */
1546 void rmAllocatorDeleteNode(Rm_Handle rmHandle, const char *resName, int32_t resBase, uint32_t resLen)
1548     Rm_Allocator    *allocator = rmAllocatorFind(rmHandle, resName);
1549     Rm_ResourceNode  findNode;
1550     Rm_ResourceNode *matchingNode;
1552     memset((void *)&findNode, 0, sizeof(findNode));
1553     findNode.base = resBase;
1554     findNode.length = resLen;
1555     matchingNode = RB_FIND(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, &findNode);
1556     
1557     if (matchingNode) {
1558         RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
1559         rmResourceNodeFree(matchingNode);
1560     }
1563 /* FUNCTION PURPOSE: Deletes a resource allocator
1564  ***********************************************************************
1565  * DESCRIPTION: Deletes a resource allocator based on the given
1566  *              resource name.  The resource allocator will be
1567  *              removed from the RM instance allocator list.
1568  */
1569 int32_t rmAllocatorDelete(Rm_Handle rmHandle, const char *resourceName)
1571     Rm_Inst         *rmInst = (Rm_Inst *)rmHandle;    
1572     Rm_Allocator    *allocator = rmAllocatorGetAllocatorList(rmHandle);
1573     Rm_Allocator    *prevAllocator = NULL;
1574     Rm_ResourceTree *treeRoot;
1575     Rm_ResourceNode *node = NULL;
1576     Rm_ResourceNode *nextNode = NULL;
1577     int32_t          retVal = RM_OK;
1579     while (allocator) {
1580         if (strncmp(allocator->resourceName, resourceName, RM_NAME_MAX_CHARS) == 0) {
1581             break;             
1582         }
1583         prevAllocator = allocator;
1584         allocator = allocator->nextAllocator;
1585     }
1587     if (allocator) {
1588         if (prevAllocator == NULL) {
1589             if ((rmInst->instType == Rm_instType_SERVER) ||
1590                 (rmInst->instType == Rm_instType_SHARED_SERVER)) {
1591                 rmInst->u.server.allocators = allocator->nextAllocator;
1592             }
1593             else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1594                 rmInst->u.cd.allocators = allocator->nextAllocator;
1595             }              
1596         }
1597         else {
1598             prevAllocator->nextAllocator = allocator->nextAllocator;
1599             RM_SS_OBJ_WB(prevAllocator, Rm_Allocator);
1600         }
1601             
1602         /* Destroy tree and return error */
1603         treeRoot = allocator->allocatorRootEntry;
1604         for (node = RB_MIN(_Rm_AllocatorResourceTree, treeRoot); node != NULL; node = nextNode) {
1605                 nextNode = RB_NEXT(_Rm_AllocatorResourceTree, treeRoot, node);
1606                 RB_REMOVE(_Rm_AllocatorResourceTree, treeRoot, nextNode);
1607             rmResourceNodeFree(node);
1608         }
1609         Rm_osalFree((void *)treeRoot, sizeof(*treeRoot));        
1610         Rm_osalFree((void *)allocator, sizeof(*allocator));
1611     }
1612     else {
1613         retVal = RM_ERROR_RES_ALLOCATOR_DOES_NOT_EXIST;
1614     }
1615     return (retVal);
1618 /* FUNCTION PURPOSE: Deletes server allocators
1619  ***********************************************************************
1620  * DESCRIPTION: Removes all resource nodes for each
1621  *              resource allocator and then deletes the allocator
1622  *              itself.  Used to free all memory consumed
1623  *              by the allocators.
1624  */
1625 void rmAllocatorDeleteResources(Rm_Handle rmHandle)
1627     Rm_Inst         *rmInst = (Rm_Inst *)rmHandle;
1628     Rm_Allocator    *allocatorList = rmAllocatorGetAllocatorList(rmHandle);
1629     Rm_Allocator    *nextAllocator;
1630     Rm_ResourceTree *resTree;
1631     Rm_ResourceNode *resNode;
1632     Rm_ResourceNode *nextResNode;
1634     while (allocatorList) {
1635         RM_SS_OBJ_INV(allocatorList, Rm_Allocator);
1636         nextAllocator = allocatorList->nextAllocator;
1637         resTree = allocatorList->allocatorRootEntry;
1639         if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1640             rmResourceTreeInv(resTree);
1641         }
1642         /* Delete each resource node in the allocator */
1643         for (resNode = RB_MIN(_Rm_AllocatorResourceTree, resTree); resNode != NULL; resNode = nextResNode) {
1644             nextResNode = RB_NEXT(_Rm_AllocatorResourceTree, resTree, resNode);
1645             RB_REMOVE(_Rm_AllocatorResourceTree, resTree, resNode);
1646             if (resNode->allocationCount) {
1647                 /* Delete all the owners in the resource's owner list */
1648                 allocatorResNodeOwnerClear(rmHandle, resNode);
1649             }
1650             rmResourceNodeFree(resNode);
1651         }        
1653         Rm_osalFree((void *)resTree, sizeof(*resTree));
1654         Rm_osalFree((void *)allocatorList, sizeof(*allocatorList));
1655         allocatorList = nextAllocator;
1656     }