241df5dce2d5d8f92fa366dc46e9b7b126e2918d
[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: Checks a resource node's ownership
107  ***********************************************************************
108  * DESCRIPTION: Returns the owner reference count if the provided
109  *              instance node is in the list of resource node owners.  Otherwise,
110  *              returns 0.
111  */
112 static int allocatorResNodeIsOwnedBy(Rm_Handle rmHandle, Rm_ResourceNode *node, void *serviceInstNode)
114     Rm_Inst  *rmInst = (Rm_Inst *)rmHandle;
115     Rm_Owner *owner = node->ownerList;
117     while (owner) {
118         RM_SS_OBJ_INV(owner, Rm_Owner);
119         if (owner->instNameNode == serviceInstNode) {
120             return(owner->refCnt);           
121         }
122         owner = owner->nextOwner;
123     }
124     return(0);
127 /* FUNCTION PURPOSE: Increments an owner's refCnt
128  ***********************************************************************
129  * DESCRIPTION: Increments a resource owner's reference count
130  */
131 static void allocatorResNodeOwnerRefCntInc(Rm_Handle rmHandle, Rm_ResourceNode *node, void *serviceInstNode)
133     Rm_Inst  *rmInst = (Rm_Inst *)rmHandle;
134     Rm_Owner *owner = node->ownerList;
136     while (owner) {
137         RM_SS_OBJ_INV(owner, Rm_Owner);
138         if (owner->instNameNode == serviceInstNode) {
139             owner->refCnt++;
140             RM_SS_OBJ_WB(owner, Rm_Owner);
141             break;
142         }
143         owner = owner->nextOwner;
144     }
147 /* FUNCTION PURPOSE: Decrements an owner's refCnt
148  ***********************************************************************
149  * DESCRIPTION: Decrements a resource owner's reference count
150  */
151 static void allocatorResNodeOwnerRefCntDec(Rm_Handle rmHandle, Rm_ResourceNode *node, void *serviceInstNode)
153     Rm_Inst  *rmInst = (Rm_Inst *)rmHandle;
154     Rm_Owner *owner = node->ownerList;
156     while (owner) {
157         RM_SS_OBJ_INV(owner, Rm_Owner);
158         if (owner->instNameNode == serviceInstNode) {
159             owner->refCnt--;
160             RM_SS_OBJ_WB(owner, Rm_Owner);
161             break;
162         }
163         owner = owner->nextOwner;
164     }
167 /* FUNCTION PURPOSE: Adds an owner to an allocator resource
168  ***********************************************************************
169  * DESCRIPTION: Adds a RM instance node to a resource node's
170  *              list of owners.  If the owner is already present that
171  *              owner's reference count is incremented
172  */
173 static void allocatorResNodeOwnerAdd(Rm_Handle rmHandle, Rm_ResourceNode *node, void *serviceInstNode)
175     Rm_Inst  *rmInst = (Rm_Inst *)rmHandle;    
176     Rm_Owner *ownerList = node->ownerList;
177     Rm_Owner *newOwner = NULL;
179     if (allocatorResNodeIsOwnedBy(rmHandle, node, serviceInstNode)) {
180         allocatorResNodeOwnerRefCntInc(rmHandle, node, serviceInstNode);
181     }
182     else {
183         newOwner = Rm_osalMalloc(sizeof(*newOwner));
185         if (newOwner) {
186             newOwner->instNameNode = serviceInstNode;
187             newOwner->refCnt = 0;
188             newOwner->nextOwner = NULL;  
190             /* Add owner entry to end of list */
191             if (ownerList) {
192                 RM_SS_OBJ_INV(ownerList, Rm_Owner);
193                 while (ownerList->nextOwner) {
194                     ownerList = ownerList->nextOwner;
195                     RM_SS_OBJ_INV(ownerList, Rm_Owner);
196                 }
197                 ownerList->nextOwner = newOwner;
198                 RM_SS_OBJ_WB(ownerList, Rm_Owner);
199             }
200             else {
201                 node->ownerList = newOwner;
202             }
204             node->allocationCount++;
205             newOwner->refCnt++;
206             newOwner->instNameNode->allocRefCount++;
207             RM_SS_OBJ_WB(newOwner, Rm_Owner);
208             RM_SS_OBJ_WB(newOwner->instNameNode, Rm_PolicyValidInstNode);
209         }
210     }
213 /* FUNCTION PURPOSE: Compares two resource node's boundaries
214  ***********************************************************************
215  * DESCRIPTION: Returns TRUE if the resource nodes are neighbors from
216  *              a base+length perspective.  Otherwise, returns FALSE.
217  */
218 static int allocatorResNodeBoundaryCompare(Rm_ResourceNode *node1, Rm_ResourceNode *node2)
220     uint32_t node1End = node1->base + node1->length - 1;
221     uint32_t node2End = node2->base + node2->length - 1;
223     if (node1 && node2) {
224         if (node1->base < node2->base) {
225             if (node1End == (node2->base - 1)) {
226                 return(RM_TRUE);
227             }
228         }
229         else if (node2->base < node1->base) {
230             if (node2End == (node1->base - 1)) {
231                 return(RM_TRUE);
232             }     
233         }
234     }
235     return(RM_FALSE);
238 /* FUNCTION PURPOSE: Compares two resource node's owners
239  ***********************************************************************
240  * DESCRIPTION: Returns TRUE if the owners of two resource nodes 
241  *              are equivalent.  Otherwise, returns FALSE.
242  */
243 static int allocatorResNodeOwnerCompare(Rm_Handle rmHandle, Rm_ResourceNode *node1, Rm_ResourceNode *node2)
245     Rm_Inst  *rmInst = (Rm_Inst *)rmHandle;    
246     Rm_Owner *node1Owners = node1->ownerList;
247     Rm_Owner *node2Owners = node2->ownerList;
248     int       matchedInst;
250     if (rmInst->instType == Rm_instType_SHARED_SERVER) {
251         while(node2Owners) {
252             Rm_osalBeginMemAccess((void *)node2Owners, sizeof(*node2Owners));
253             node2Owners = node2Owners->nextOwner;
254         }
255         node2Owners = node2->ownerList;
256     }
258     if (node1->allocationCount == node2->allocationCount) {
259         while (node1Owners) {
260             RM_SS_OBJ_INV(node1Owners, Rm_Owner);
261             matchedInst = RM_FALSE;
262             while (node2Owners) {
263                 if ((node1Owners->instNameNode == node2Owners->instNameNode) &&
264                     (node1Owners->refCnt == node2Owners->refCnt)) {
265                     matchedInst = RM_TRUE;
266                     break;
267                 }
268                 node2Owners = node2Owners->nextOwner;
269             }
271             if (matchedInst) {
272                 node2Owners = node2->ownerList;
273                 node1Owners = node1Owners->nextOwner;
274             }
275             else {
276                 return(RM_FALSE);
277             }                
278         }
279     }
280     else {
281         return(RM_FALSE);
282     }  
283     
284     return(RM_TRUE);
287 /* FUNCTION PURPOSE: Deletes an owner from an allocator resource
288  ***********************************************************************
289  * DESCRIPTION: Removes a RM owner entry from a resource node's
290  *              list of owners.  If the refCnt for the specified
291  *              owner is greater than 1 only the refCnt is
292  *              decremented
293  */
294 static void allocatorResNodeOwnerDelete(Rm_Handle rmHandle, Rm_ResourceNode *node, void *serviceInstNode)
296     Rm_Inst  *rmInst = (Rm_Inst *)rmHandle;    
297     Rm_Owner *owner = node->ownerList;
298     Rm_Owner *prevOwner = NULL;
300     if (allocatorResNodeIsOwnedBy(rmHandle, node, serviceInstNode) > 1) {
301         allocatorResNodeOwnerRefCntDec(rmHandle, node, serviceInstNode);
302     }
303     else {
304         while (owner) {
305             RM_SS_OBJ_INV(owner, Rm_Owner);
306             if (owner->instNameNode == serviceInstNode) {
307                 break;             
308             }
309             prevOwner = owner;
310             owner = owner->nextOwner;
311         }
313         if (owner) {
314             if (prevOwner == NULL) {
315                 node->ownerList = owner->nextOwner;
316             }
317             else {
318                 prevOwner->nextOwner = owner->nextOwner;
319                 RM_SS_OBJ_WB(prevOwner, Rm_Owner);
320             }
321             
322             node->allocationCount--;
323             owner->instNameNode->allocRefCount--;
324             RM_SS_OBJ_WB(owner->instNameNode, Rm_PolicyValidInstNode);
325             Rm_osalFree((void *)owner, sizeof(*owner));
326         }
327     }
330 /* FUNCTION PURPOSE: Copies the owners of a resource node
331  ***********************************************************************
332  * DESCRIPTION: Creates a list of resource owners for the destination
333  *              resource node that is equivalent to the source resource
334  *              node's owners
335  *
336  *              dstNode must be a newly created node without any owners.
337  */
338 static void allocatorResNodeOwnerCopy(Rm_Handle rmHandle, Rm_ResourceNode *dstNode, Rm_ResourceNode *srcNode)
340     Rm_Inst  *rmInst = (Rm_Inst *)rmHandle;
341     Rm_Owner *srcOwnerList = srcNode->ownerList;
342     Rm_Owner *dstNewOwner;
343     Rm_Owner *dstPrevOwner;
345     if (dstNode->ownerList != NULL) {
346         return;
347     }
348     dstNode->allocationCount = srcNode->allocationCount;
350     while (srcOwnerList) {
351         RM_SS_OBJ_INV(srcOwnerList, Rm_Owner);
352         dstNewOwner = Rm_osalMalloc(sizeof(*dstNewOwner));
353         dstNewOwner->instNameNode = srcOwnerList->instNameNode;
354         dstNewOwner->refCnt = srcOwnerList->refCnt;
355         dstNewOwner->nextOwner = NULL;
356         RM_SS_OBJ_WB(dstNewOwner, Rm_Owner);
358         if (dstNode->ownerList == NULL) {
359             dstNode->ownerList = dstNewOwner;
360         }
361         else {
362             dstPrevOwner->nextOwner = dstNewOwner;
363             RM_SS_OBJ_WB(dstPrevOwner, Rm_Owner);
364         }
365         dstPrevOwner = dstNewOwner;
366         srcOwnerList = srcOwnerList->nextOwner;
367     }
370 /* FUNCTION PURPOSE: Clears a resource node's owners
371  ***********************************************************************
372  * DESCRIPTION: Deletes all owners from the owners list of a 
373  *              resource node.
374  */
375 static void allocatorResNodeOwnerClear(Rm_Handle rmHandle, Rm_ResourceNode *node)
377     Rm_Inst  *rmInst = (Rm_Inst *)rmHandle;    
378     Rm_Owner *owner = node->ownerList;
379     Rm_Owner *nextOwner;
381     while (owner) {
382         RM_SS_OBJ_INV(owner, Rm_Owner);
383         nextOwner = owner->nextOwner;
384         node->allocationCount--;
385         owner->instNameNode->allocRefCount--;
386         RM_SS_OBJ_WB(owner->instNameNode, Rm_PolicyValidInstNode);
387         Rm_osalFree((void *)owner, sizeof(*owner));
388         owner = nextOwner;
389     }
392 /* FUNCTION PURPOSE: Get the status for an allocator resource
393  ***********************************************************************
394  * DESCRIPTION: Called when a resource status request is made.  The
395  *              resource's allocator is searched for the resource base
396  *              and length specified in the transaction.  The 
397  *              resource's owner reference count is returned if the 
398  *              resource range is found.
399  */
400 static int32_t allocatorStatus(Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)
402     Rm_ResourceNode  findNode;
403     Rm_ResourceNode *matchingNode = NULL; 
404     uint32_t         matchingEnd;
405     uint32_t         findEnd;    
406     int32_t          retVal;
408     memset((void *)&findNode, 0, sizeof(findNode));
409     findNode.base = opInfo->resourceInfo->base;
410     findNode.length = opInfo->resourceInfo->length;
411     matchingNode = RB_FIND(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, &findNode);
413     if (matchingNode) {
414         matchingEnd = matchingNode->base + matchingNode->length - 1;
415         findEnd = findNode.base + findNode.length - 1;
416         if ((findNode.base >= matchingNode->base) && (findEnd <= matchingEnd)) {        
417             opInfo->resourceInfo->ownerCount = matchingNode->allocationCount;
418             retVal = RM_SERVICE_APPROVED;
419         }
420         else {
421             retVal = RM_SERVICE_DENIED_PARTIAL_STATUS;
422         }
423     }
424     else {
425         retVal = RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST;
426     }
428     return(retVal);  
431 /* FUNCTION PURPOSE: Preallocates an allocator resource
432  ***********************************************************************
433  * DESCRIPTION: Called when an allocate request is made but the base 
434  *              is unspecified.  The preallocation algorithm looks at 
435  *              available resources as well as policy permissions to 
436  *              determine a resource range that satisfies the request.
437  *              If a valid range is found it will be returned for the 
438  *              treeAllocate algorithm to handle.
439  */
440 static int32_t allocatorPreAllocate(Rm_Handle rmHandle, Rm_Allocator *allocator, int32_t resourcePolicy, 
441                                     Rm_AllocatorOpInfo *opInfo)
442 {   
443     Rm_Inst           *rmInst = (Rm_Inst *)rmHandle;
444     Rm_ResourceNode    findNode;
445     Rm_ResourceNode   *matchingNode = NULL;
446     Rm_ResourceNode   *nextNode;
447     uint32_t           matchingEnd;
448     uint32_t           findEnd;
449     uint32_t           rangeIndex;
450     int                resourceFound = RM_FALSE;
451     Rm_PolicyCheckType policyCheckType;
452     Rm_PolicyCheckCfg  policyCheckCfg;
453     int                nodePassesPolicy;
454     int32_t            retVal = RM_OK;
456     if (opInfo->operation == Rm_allocatorOp_PRE_ALLOCATE_INIT) {
457         policyCheckType = Rm_policyCheck_INIT;
458     }
459     else if (opInfo->operation == Rm_allocatorOp_PRE_ALLOCATE_USE) {
460         policyCheckType = Rm_policyCheck_USE;
461     }
462     else {
463         retVal = RM_ERROR_INVALID_SERVICE_TYPE;
464         return (retVal);
465     }
467     if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
468         /* Set base to first node's base since CD will not have all resources like Server */
469         matchingNode = RB_MIN(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry);
470         opInfo->resourceInfo->base = matchingNode->base;
471     }
472     else {
473         opInfo->resourceInfo->base = rmPolicyGetResourceBase(opInfo->policy, opInfo->serviceSrcInstNode, 
474                                                              resourcePolicy, policyCheckType, 
475                                                              &retVal);
476     }
477     
478     if (retVal != RM_OK) {
479         return (retVal);
480     }
482     if (opInfo->resourceInfo->alignment == RM_RESOURCE_ALIGNMENT_UNSPECIFIED) {  
483         /* Get alignment from policy */
484         opInfo->resourceInfo->alignment = rmPolicyGetResourceAlignment(opInfo->policy, resourcePolicy);
485     }
486     
487     if (opInfo->resourceInfo->alignment == 0) {
488         opInfo->resourceInfo->alignment = 1;
489     }    
491     memset((void *)&findNode, 0, sizeof(findNode));
492     findNode.base = opInfo->resourceInfo->base;
493     findNode.length = opInfo->resourceInfo->length;
495     /* Configure policy checking structure */
496     memset((void *)&policyCheckCfg, 0, sizeof(policyCheckCfg));
497     policyCheckCfg.policyDtb = opInfo->policy;
498     policyCheckCfg.resourceOffset = resourcePolicy;
499     
500     do {
501         matchingNode = RB_FIND(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, &findNode);
502         
503         if (matchingNode) {
504             matchingEnd = matchingNode->base + matchingNode->length - 1;
505             findEnd = findNode.base + findNode.length - 1;
506             if ((matchingNode->allocationCount == 0) &&
507                 (findNode.base >= matchingNode->base) && (findEnd <= matchingEnd)) {
508                 /* Attempt to preallocate from node only if not owned by anyone and sits
509                  * within a matching node. */
510                 nodePassesPolicy = RM_FALSE;
511                 policyCheckCfg.type = policyCheckType;
512                 policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;
513                 policyCheckCfg.resourceBase = findNode.base;
514                 policyCheckCfg.resourceLength = findNode.length;
515                 nodePassesPolicy = rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);    
516                 
517                 if (nodePassesPolicy && (matchingNode->allocationCount > 0)) {
518                     policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;
519                     
520                     if (allocatorResNodeIsOwnedBy(rmHandle, matchingNode, rmPolicyGetLinuxInstNode(rmHandle))) {
521                         /* Check if instance requesting resource has privileges to share
522                          * a resource already reserved by Linux */
523                         policyCheckCfg.type = Rm_policyCheck_SHARED_LINUX;
524                         nodePassesPolicy = rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);
525                     }
527                     if (nodePassesPolicy) {
528                         /* Check exclusive privileges of instance requesting resource.  Requesting
529                          * instance with exclusive privileges can't reserve resource if already owned*/
530                         policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;
531                         nodePassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);
532                     }
533                 }
534                 
535                 if (nodePassesPolicy && (matchingNode->allocationCount == 1)) {
536                     /* Check exclusive privileges of instance that currently owns resource */
537                     policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;
538                     policyCheckCfg.validInstNode = matchingNode->ownerList->instNameNode;
539                     nodePassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);
540                 }
542                 if (retVal != RM_OK) {
543                     break;
544                 }
546                 if (nodePassesPolicy) {
547                     /* Initialize indexer to be first resource value that alignment satisfies */
548                     rangeIndex = findNode.base;
549                     if (rangeIndex % opInfo->resourceInfo->alignment) {
550                         rangeIndex += (opInfo->resourceInfo->alignment -
551                                       (rangeIndex % opInfo->resourceInfo->alignment));
552                     }
553                     
554                     if ((rangeIndex + opInfo->resourceInfo->length - 1) <= matchingEnd) {
555                         /* Block of unallocated resources within matchingNode that satisfies
556                          * allocate requirements */
557                         opInfo->resourceInfo->base = rangeIndex;
558                         resourceFound = RM_TRUE;
559                         retVal = RM_SERVICE_PROCESSING;
560                     }     
561                 }
562             }
563             
564             if (!resourceFound) {
565                 /* Check next resource node for available resources */
566                 if (findNode.base < matchingNode->base) {
567                     findNode.base = matchingNode->base;
568                 }
569                 else {
570                     if (nextNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode)) {
571                         findNode.base = nextNode->base;
572                     }
573                     else {
574                         retVal = RM_SERVICE_DENIED_RES_ALLOC_REQS_NOT_MET;
575                     }
576                 }
577             }
578         }
579         else {
580             retVal = RM_SERVICE_DENIED_RES_ALLOC_REQS_NOT_MET;
581         }
582     } while ((!resourceFound) && 
583              (retVal != RM_SERVICE_DENIED_RES_ALLOC_REQS_NOT_MET));
585     return(retVal); 
588 /* FUNCTION PURPOSE: Allocates an allocator resource
589  ***********************************************************************
590  * DESCRIPTION: Will attempt to allocate the resource with specified
591  *              base and length from the resource's allocator.  The
592  *              allocation algorithm will verify the allocation against
593  *              the policy permissions for the instance requesting the
594  *              allocation.  If the policy allows the allocation the 
595  *              algorithm will allocate the resource then combine any
596  *              resource nodes that may have become equivalent (in terms
597  *              of ownership) after the allocation.
598  */
599 static int32_t allocatorAllocate(Rm_Handle rmHandle, Rm_Allocator *allocator, int32_t resourcePolicy, 
600                                  Rm_AllocatorOpInfo *opInfo)
602     Rm_ResourceNode     findNode;
603     Rm_ResourceNode    *matchingNode = NULL;
604     Rm_ResourceNode    *leftNode = NULL;
605     Rm_ResourceNode    *rightNode = NULL;
606     Rm_PolicyCheckType  policyCheckType;    
607     Rm_PolicyCheckCfg   policyCheckCfg;
608     int                 allocPassesPolicy;
609     int                 combineLeft = RM_FALSE;
610     int                 combineRight = RM_FALSE;    
611     uint32_t            findEnd;
612     uint32_t            matchingEnd;  
613     int32_t             retVal;
615     if (opInfo->operation == Rm_allocatorOp_ALLOCATE_INIT) {
616         policyCheckType = Rm_policyCheck_INIT;
617     }
618     else if (opInfo->operation == Rm_allocatorOp_ALLOCATE_USE) {
619         policyCheckType = Rm_policyCheck_USE;
620     }
621     else {
622         retVal = RM_ERROR_INVALID_SERVICE_TYPE;
623         return (retVal);
624     }   
626     memset((void *)&findNode, 0, sizeof(findNode));
627     findNode.base = opInfo->resourceInfo->base;
628     findNode.length = opInfo->resourceInfo->length;
629     matchingNode = RB_FIND(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, &findNode);
631     /* Prepare privilege checks */
632     memset((void *)&policyCheckCfg, 0, sizeof(policyCheckCfg)); 
634     if (matchingNode) {
635         findEnd = findNode.base + findNode.length - 1;
636         matchingEnd = matchingNode->base + matchingNode->length - 1;
637         
638         if ((findNode.base >= matchingNode->base) && (findEnd <= matchingEnd)) {
639             if (opInfo->serviceSrcInstNode == rmPolicyGetLinuxInstNode(rmHandle)) {
640                 /* Bypass policy checks since Linux Kernel has full privileges */
641                 allocPassesPolicy = RM_TRUE;
642             }
643             else {
644                 policyCheckCfg.policyDtb = opInfo->policy;
645                 policyCheckCfg.resourceOffset = resourcePolicy;    
646                 policyCheckCfg.type = policyCheckType;
647                 policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;
648                 policyCheckCfg.resourceBase = findNode.base;
649                 policyCheckCfg.resourceLength = findNode.length;
650                 allocPassesPolicy = rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);
651                 if (!allocPassesPolicy) {
652                     if (policyCheckType == Rm_policyCheck_INIT) {
653                         retVal = RM_SERVICE_DENIED_INIT_PERM_NOT_GIVEN;
654                     }
655                     else {
656                         retVal = RM_SERVICE_DENIED_USE_PERM_NOT_GIVEN;
657                     }
658                 }
660                 if (!allocatorResNodeIsOwnedBy(rmHandle, matchingNode, opInfo->serviceSrcInstNode)) {
661                     if (allocPassesPolicy && (matchingNode->allocationCount > 0)) {
662                         if (allocatorResNodeIsOwnedBy(rmHandle, matchingNode, rmPolicyGetLinuxInstNode(rmHandle))) {
663                             /* Check if instance requesting resource has privileges to share
664                              * a resource already reserved by Linux */
665                             policyCheckCfg.type = Rm_policyCheck_SHARED_LINUX;
666                             policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;
667                             allocPassesPolicy = rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);
668                             if (!allocPassesPolicy) {
669                                 retVal = RM_SERVICE_DENIED_RES_NOT_SHARED_LINUX;
670                             }
671                         }
672                         if (allocPassesPolicy) {
673                             /* Check exclusive privileges of instance requesting resource.  Requesting
674                              * instance with exclusive privileges can't reserve resource if already owned*/
675                             policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;
676                             policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;
677                             allocPassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);
678                             if (!allocPassesPolicy) {
679                                 retVal = RM_SERVICE_DENIED_EXCLUSIVE_RES_ALLOCD;
680                             }
681                         }
682                     }
683                     if (allocPassesPolicy && (matchingNode->allocationCount == 1)) {
684                         /* Check exclusive privileges of instance that currently owns resource */
685                         policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;
686                         policyCheckCfg.validInstNode = matchingNode->ownerList->instNameNode;
687                         allocPassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);
688                         if (!allocPassesPolicy) {
689                             retVal = RM_SERVICE_DENIED_ALLOCD_TO_EXCLUSIVE_INST;
690                         }                
691                     }  
692                 }
693             }
694             
695             if (allocPassesPolicy) {
696                 /* Handle any possible node combinations if requesting instance is
697                  * not already in resource's owner list.  Automatic approval if requesting
698                  * instance is already in owner list. */
699                 if ((findNode.base == matchingNode->base) && (findEnd == matchingEnd)) {
700                     /* findNode range matches matchingNode range
701                      *
702                      *   |<--left node-->||<--matched  node-->||<--right node-->| => existing node
703                      *                    |<--alloc request-->|  => requested resources
704                      */                     
705                     leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
706                     rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
707                     RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
708                     allocatorResNodeOwnerAdd(rmHandle, matchingNode, opInfo->serviceSrcInstNode);
710                     if (leftNode && allocatorResNodeOwnerCompare(rmHandle, leftNode, matchingNode) &&
711                         allocatorResNodeBoundaryCompare(leftNode, matchingNode)) {
712                         RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
713                         combineLeft = RM_TRUE;
714                     }
715                     if (rightNode && allocatorResNodeOwnerCompare(rmHandle, rightNode, matchingNode) &&
716                         allocatorResNodeBoundaryCompare(rightNode, matchingNode)) {
717                         RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
718                         combineRight = RM_TRUE;
719                     }
721                     if (combineLeft && combineRight) {
722                         /* Combine all three nodes into matchingNode */
723                         matchingNode->base = leftNode->base;
724                         matchingNode->length = leftNode->length + matchingNode->length + rightNode->length;
726                         allocatorResNodeOwnerClear(rmHandle, leftNode);
727                         rmResourceNodeFree(leftNode);
728                         allocatorResNodeOwnerClear(rmHandle, rightNode);
729                         rmResourceNodeFree(rightNode);                        
730                     }
731                     else if (combineLeft) {
732                         /* Combine left and matching nodes.  Reinsert right. */
733                         matchingNode->base = leftNode->base;
734                         matchingNode->length += leftNode->length;
736                         allocatorResNodeOwnerClear(rmHandle, leftNode);
737                         rmResourceNodeFree(leftNode);
738                         if (rightNode) {
739                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);  
740                         }
741                     }
742                     else if (combineRight) {
743                         /* Combine right and matching nodes.  Reinsert left. */
744                         matchingNode->length += rightNode->length;
746                         allocatorResNodeOwnerClear(rmHandle, rightNode);
747                         rmResourceNodeFree(rightNode);
748                         if (leftNode) {
749                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
750                         }
751                     }
752                     else {
753                         /* No combine. */
754                         if (leftNode) {
755                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
756                         }
757                         if (rightNode) {
758                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
759                         }
760                     }
762                     /* Always reinsert matchingNode */                
763                     RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
764                     
765                     /* Matching node contains new reference count after alloc.  Return new owner count. */
766                     opInfo->resourceInfo->ownerCount = matchingNode->allocationCount;
767                 }   
768                 else if ((findNode.base > matchingNode->base) && (findEnd < matchingEnd)) {
769                     /* findNode range is subset of matchingNode range and neither boundary is
770                      * equivalent.
771                      *
772                      * |<----------matched node---------->|
773                      *        |<---alloc request--->|
774                      */ 
775                     RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
776                     leftNode = rmResourceNodeNew(matchingNode->base, findNode.base - matchingNode->base);
777                     allocatorResNodeOwnerCopy(rmHandle, leftNode, matchingNode);
778                     rightNode = rmResourceNodeNew(findNode.base + findNode.length, matchingEnd - findEnd);
779                     allocatorResNodeOwnerCopy(rmHandle, rightNode, matchingNode);
781                     matchingNode->base = findNode.base;                                    
782                     matchingNode->length = findNode.length;
783                     allocatorResNodeOwnerAdd(rmHandle, matchingNode, opInfo->serviceSrcInstNode);
785                     /* Insert all the nodes */
786                     RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
787                     RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
788                     RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
789                     
790                     /* Matching node contains new reference count after alloc.  Return new owner count. */
791                     opInfo->resourceInfo->ownerCount = matchingNode->allocationCount;
792                 }  
793                 else {    
794                     if (findNode.base == matchingNode->base) {
795                         /* findNode base and matchingNode base are equivalent.  May be combine
796                          * possibilities to the left
797                          *
798                          * |<---left node (alloc'd)--->||<----------matched node---------->|
799                          *                              |<---findNode (alloc req)--->|
800                          */                         
801                         leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
802                         RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
803                         /* Add allocating instance to owner list for compare with leftNode */
804                         allocatorResNodeOwnerAdd(rmHandle, matchingNode, opInfo->serviceSrcInstNode);
805                         
806                         if (leftNode && allocatorResNodeOwnerCompare(rmHandle, leftNode, matchingNode) &&
807                             allocatorResNodeBoundaryCompare(leftNode, matchingNode)) {
808                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
809                             /* Combine leftNode and findNode */
810                             leftNode->length += findNode.length;
811                         }
812                         else {
813                             leftNode = rmResourceNodeNew(findNode.base, findNode.length);
814                             allocatorResNodeOwnerCopy(rmHandle, leftNode, matchingNode);
815                         }
817                         /* Account for leftNode in matchingNode */
818                         matchingNode->base = findNode.base + findNode.length;
819                         matchingNode->length = matchingEnd - findEnd;  
821                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
822                         /* Left node contains new reference count after alloc.  Return new owner count. */
823                         opInfo->resourceInfo->ownerCount = leftNode->allocationCount;
824                     }
825                     else if (findEnd == matchingEnd) {
826                         /* findNode end and matchingNode end are equivalent.  May be combine
827                          * possibilities to the right
828                          *
829                          * |<----------matched node---------->||<---right node (alloc'd)--->|
830                          *       |<---findNode (alloc req)--->| 
831                          */                        
832                         rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
833                         RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
834                         /* Add allocating instance to owner list for compare with rightNode */
835                         allocatorResNodeOwnerAdd(rmHandle, matchingNode, opInfo->serviceSrcInstNode);
836                         
837                         if (rightNode && allocatorResNodeOwnerCompare(rmHandle, rightNode, matchingNode) &&
838                             allocatorResNodeBoundaryCompare(rightNode, matchingNode)) {
839                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
840                             /* Combine rightNode and findNode */
841                             rightNode->base = findNode.base;
842                             rightNode->length += findNode.length;
843                         }
844                         else {
845                             rightNode = rmResourceNodeNew(findNode.base, findNode.length);
846                             allocatorResNodeOwnerCopy(rmHandle, rightNode, matchingNode);
847                         }
849                         /* Account for rightNode in matchingNode */
850                         matchingNode->length -= findNode.length;  
852                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
853                         /* Right node contains new reference count after alloc.  Return new owner count. */
854                         opInfo->resourceInfo->ownerCount = rightNode->allocationCount;
855                     }
856                     /* Remove allocating instance from leftover matchingNode */
857                     allocatorResNodeOwnerDelete(rmHandle, matchingNode, opInfo->serviceSrcInstNode);
858                     RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
859                 }
860                 retVal = RM_SERVICE_APPROVED;
861             }
862         }
863         else {
864             retVal = RM_SERVICE_DENIED_PARTIAL_ALLOCATION;
865         }
866     }
867     else {
868         retVal = RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST;
869     }
871     return(retVal);        
874 /* FUNCTION PURPOSE: Frees an allocator resource
875  ***********************************************************************
876  * DESCRIPTION: Will attempt to free the resource with specified
877  *              base and length from the resource's allocator.  The
878  *              free algorithm will verify the free request parameters
879  *              match an allocated range for the resource and that the
880  *              range is owned by the instance requesting the free. If
881  *              the free is validated the algorithm will free the 
882  *              resource then combine any resource nodes that may have
883  *              become equivalent (in terms of ownership) after the
884  *              allocation.
885  */
886 static int32_t allocatorFree(Rm_Handle rmHandle, Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)
888     Rm_ResourceNode  findNode;
889     Rm_ResourceNode *matchingNode = NULL;
890     Rm_ResourceNode *leftNode = NULL;
891     Rm_ResourceNode *rightNode = NULL;
892     int              combineLeft = RM_FALSE;
893     int              combineRight = RM_FALSE;
894     uint32_t         findEnd;
895     uint32_t         matchingEnd;
896     int32_t          retVal;
898     memset((void *)&findNode, 0, sizeof(findNode));
899     findNode.base = opInfo->resourceInfo->base;
900     findNode.length = opInfo->resourceInfo->length;
901     matchingNode = RB_FIND(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, &findNode);
903     if (matchingNode) {
904         findEnd = findNode.base + findNode.length - 1;
905         matchingEnd = matchingNode->base + matchingNode->length - 1;
906         
907         if ((findNode.base >= matchingNode->base) && (findEnd <= matchingEnd)) {  
908             if (matchingNode->allocationCount) {
909                 if (allocatorResNodeIsOwnedBy(rmHandle, matchingNode, opInfo->serviceSrcInstNode)) {
910                     if ((findNode.base == matchingNode->base) && (findEnd == matchingEnd))
911                     {
912                         /* Case 1: Free range equals allocated matched node exactly. Attempt to combine 
913                          *         freed node with nodes to left and right.
914                          *
915                          * |<--left node-->||<---matched node--->||<--right node-->|
916                          *                  |<---free request--->|
917                          */ 
918                         leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
919                         rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
920                         RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
921                         allocatorResNodeOwnerDelete(rmHandle, matchingNode, opInfo->serviceSrcInstNode);
923                         if (leftNode && allocatorResNodeOwnerCompare(rmHandle, leftNode, matchingNode) &&
924                             allocatorResNodeBoundaryCompare(leftNode, matchingNode)) {
925                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
926                             combineLeft = RM_TRUE;
927                         }
928                         if (rightNode && allocatorResNodeOwnerCompare(rmHandle, rightNode, matchingNode) &&
929                             allocatorResNodeBoundaryCompare(rightNode, matchingNode)) {
930                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
931                             combineRight = RM_TRUE;
932                         }
934                         if (combineLeft && combineRight) {
935                             /* Combine all three nodes into matchingNode */
936                             matchingNode->base = leftNode->base;
937                             matchingNode->length = leftNode->length + matchingNode->length + rightNode->length;
939                             allocatorResNodeOwnerClear(rmHandle, leftNode);
940                             rmResourceNodeFree(leftNode);
941                             allocatorResNodeOwnerClear(rmHandle, rightNode);
942                             rmResourceNodeFree(rightNode);                        
943                         }
944                         else if (combineLeft) {
945                             /* Combine left and matching nodes.  Reinsert right. */
946                             matchingNode->base = leftNode->base;
947                             matchingNode->length += leftNode->length;
949                             allocatorResNodeOwnerClear(rmHandle, leftNode);
950                             rmResourceNodeFree(leftNode);
951                             if (rightNode) {
952                                 RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode); 
953                             }
954                         }
955                         else if (combineRight) {
956                             /* Combine right and matching nodes.  Reinsert left. */
957                             matchingNode->length += rightNode->length;
959                             allocatorResNodeOwnerClear(rmHandle, rightNode);
960                             rmResourceNodeFree(rightNode);
961                             if (leftNode) {
962                                 RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
963                             }
964                         }
965                         else {
966                             /* No combine. */
967                             if (leftNode) {
968                                 RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
969                             }
970                             if (rightNode) {
971                                 RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
972                             }
973                         }
975                         /* Always reinsert matchingNode */
976                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
977                         
978                         /* Matching node is what remains after free.  Return remaining owner count. */
979                         opInfo->resourceInfo->ownerCount = matchingNode->allocationCount;
980                     }
981                     else if ((findNode.base > matchingNode->base) && (findEnd < matchingEnd)) {
982                         /* Case 2: Free range is less than range in matched node. Split
983                          *         matched node into three nodes.
984                          *
985                          * |<----------matched node---------->|
986                          *        |<---free request--->|
987                          *
988                          * Remove instance from owner list then add it back in for side nodes for
989                          * proper accounting of allocations in validInstance list
990                          */ 
991                         RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
992                         allocatorResNodeOwnerDelete(rmHandle, matchingNode, opInfo->serviceSrcInstNode);
993                         
994                         leftNode = rmResourceNodeNew(matchingNode->base, findNode.base - matchingNode->base);
995                         allocatorResNodeOwnerCopy(rmHandle, leftNode, matchingNode);
996                         allocatorResNodeOwnerAdd(rmHandle, leftNode, opInfo->serviceSrcInstNode);
997                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
998                         
999                         rightNode = rmResourceNodeNew(findNode.base + findNode.length, matchingEnd - findEnd);
1000                         allocatorResNodeOwnerCopy(rmHandle, rightNode, matchingNode);
1001                         allocatorResNodeOwnerAdd(rmHandle, rightNode, opInfo->serviceSrcInstNode);
1002                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
1004                         matchingNode->base = findNode.base;                                    
1005                         matchingNode->length = findNode.length;
1006                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
1007                         
1008                         /* Matching node is what remains after free.  Return remaining owner count. */
1009                         opInfo->resourceInfo->ownerCount = matchingNode->allocationCount;
1010                     }
1011                     else {                        
1012                         if (findNode.base == matchingNode->base) {
1013                             /* Case 3: Free range is on left boundary of matched node. Try to 
1014                              *         combine free range with left node.
1015                              *
1016                              * |<---left node (free)--->||<----------matched node---------->|
1017                              *                           |<---findNode (free req)--->|
1018                              */ 
1020                             leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
1021                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
1022                             /* Remove freeing instance from owner list for compare with leftNode */
1023                             allocatorResNodeOwnerDelete(rmHandle, matchingNode, opInfo->serviceSrcInstNode);
1024                             
1025                             if (leftNode && allocatorResNodeOwnerCompare(rmHandle, leftNode, matchingNode) &&
1026                                 allocatorResNodeBoundaryCompare(leftNode, matchingNode)) {
1027                                 RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
1028                                 /* Combine leftNode and findNode */
1029                                 leftNode->length += findNode.length;
1030                             }
1031                             else {
1032                                 leftNode = rmResourceNodeNew(findNode.base, findNode.length);
1033                                 allocatorResNodeOwnerCopy(rmHandle, leftNode, matchingNode);
1034                             }
1036                             /* Remove leftNode range from matchingNode */
1037                             matchingNode->base = findNode.base + findNode.length;
1038                             matchingNode->length = matchingEnd - findEnd;  
1039                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
1040                             
1041                             /* Left node is what remains after free.  Return remaining owner count. */
1042                             opInfo->resourceInfo->ownerCount = leftNode->allocationCount;
1043                         }
1044                         else if (findEnd == matchingEnd) {
1045                             /* Case 4: Free range is on right boundary of matched node. Try to 
1046                              *         combine free range with right node.
1047                              *
1048                              * |<----------matched node---------->||<---right node (free)--->|
1049                              *        |<---findNode (free req)--->|
1050                              */ 
1051                             
1052                             rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
1053                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode); 
1054                             /* Remove freeing instance from owner list for compare with rightNode */
1055                             allocatorResNodeOwnerDelete(rmHandle, matchingNode, opInfo->serviceSrcInstNode);
1056                             
1057                             if (rightNode && allocatorResNodeOwnerCompare(rmHandle, rightNode, matchingNode) &&
1058                                 allocatorResNodeBoundaryCompare(rightNode, matchingNode)) {
1059                                 RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
1060                                 /* Combine rightNode and findNode */
1061                                 rightNode->base = findNode.base;
1062                                 rightNode->length += findNode.length;
1063                             }
1064                             else {
1065                                 rightNode = rmResourceNodeNew(findNode.base, findNode.length);
1066                                 allocatorResNodeOwnerCopy(rmHandle, rightNode, matchingNode);
1067                             }
1069                             /* Remove rightNode range from matchingNode */
1070                             matchingNode->length -= findNode.length;  
1071                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
1072                             
1073                             /* Right node is what remains after free.  Return remaining owner count. */
1074                             opInfo->resourceInfo->ownerCount = rightNode->allocationCount;
1075                         }
1077                         /* Add freeing instance back into matchingNode allocations */
1078                         allocatorResNodeOwnerAdd(rmHandle, matchingNode, opInfo->serviceSrcInstNode);
1079                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
1080                     }
1081                     retVal = RM_SERVICE_APPROVED;
1082                 }
1083                 else {
1084                     /* Return owner count.  In case it's a reference count check in application */
1085                     opInfo->resourceInfo->ownerCount = matchingNode->allocationCount;
1086                     retVal = RM_SERVICE_DENIED_RES_NOT_ALLOCD_TO_INST;
1087                 }
1088             }
1089             else {
1090                 /* Return owner count.  In case it's a reference count check in application */
1091                 opInfo->resourceInfo->ownerCount = matchingNode->allocationCount;
1092                 retVal = RM_SERVICE_DENIED_RES_ALREADY_FREE;
1093             }
1094         }
1095         else {
1096             retVal = RM_SERVICE_DENIED_PARTIAL_FREE;
1097         }
1098     }
1099     else {
1100         retVal = RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST;
1101     }
1102     return(retVal);  
1105 /* FUNCTION PURPOSE: Reserves a Linux resource
1106  ***********************************************************************
1107  * DESCRIPTION: Reserves resources for Linux using the base and length
1108  *              values retrieved from the Linux DTB via the
1109  *              "linux-dtb-alias" properties within the GRL.
1110  */
1111 static int32_t allocatorReserveLinuxResource(Rm_Handle rmHandle, Rm_LinuxAlias *linuxAlias, 
1112                                              Rm_LinuxValueRange *linuxValues, Rm_AllocatorOpInfo *opInfo)
1114     int32_t   retVal = RM_OK;
1115     int       baseFound = RM_FALSE;
1116     int       lengthFound = RM_FALSE;
1117     uint32_t  valueIndex = 0;
1119     while ((linuxValues) && (!baseFound || !lengthFound)) {
1120         if (linuxAlias->baseOffset == valueIndex) {
1121             opInfo->resourceInfo->base = linuxValues->value;
1122             baseFound = RM_TRUE;
1124             if (linuxAlias->lengthOffset == RM_DTB_UTIL_LINUX_ALIAS_OFFSET_NOT_SET) {
1125                 opInfo->resourceInfo->length = 1;
1126                 lengthFound = RM_TRUE;
1127             }
1128         }
1129         else if (linuxAlias->lengthOffset == valueIndex) {
1130             opInfo->resourceInfo->length = linuxValues->value;
1131             lengthFound = RM_TRUE;
1132         }
1134         linuxValues = (Rm_LinuxValueRange *)linuxValues->nextValue;
1135         valueIndex++;
1136     }
1138     if (!baseFound || !lengthFound) {
1139         retVal = RM_ERROR_DATA_NOT_FOUND_AT_LINUX_ALIAS;
1140     }
1141     else {
1142         /* Allocate resource to Linux */
1143         retVal = rmAllocatorOperation(rmHandle, opInfo);
1144         if (retVal == RM_SERVICE_APPROVED) {
1145             retVal = RM_OK;
1146         }
1147     }
1148     return (retVal);
1151 /* FUNCTION PURPOSE: Finds and reserves Linux resources
1152  ***********************************************************************
1153  * DESCRIPTION: Parses the Linux DTB for resources consumed by the
1154  *              Linux kernel.  If the resource is found via the
1155  *              "linux-dtb-alias" property defined in the GRL it is 
1156  *              reserved.
1157  */
1158 static int32_t allocatorFindLinuxResource(Rm_Handle rmHandle, const char *resourceName, void *linuxDtb, 
1159                                           Rm_LinuxAlias *linuxAlias)
1161     Rm_Inst            *rmInst = (Rm_Inst *)rmHandle;
1162     Rm_AllocatorOpInfo  opInfo;
1163     Rm_ResourceInfo     resourceInfo;
1164     uint32_t            pathOffset;
1165     uint32_t            pathSize;
1166     char               *spacePtr;
1167     int32_t             propOffset;
1168     int32_t             nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;
1169     int32_t             prevDepth = RM_DTB_UTIL_STARTING_DEPTH;
1170     int32_t             depth = RM_DTB_UTIL_STARTING_DEPTH;
1171     int32_t             propertyLen;
1172     const char         *propertyName;
1173     const void         *propertyData; 
1174     Rm_LinuxValueRange *linuxValueRange;
1175     int32_t             retVal = RM_OK; 
1177     memset((void *)&opInfo, 0, sizeof(opInfo));
1178     memset((void *)&resourceInfo, 0, sizeof(resourceInfo));
1180     strncpy(resourceInfo.name, resourceName, RM_NAME_MAX_CHARS);
1181     opInfo.policy = rmInst->u.server.globalPolicy;
1182     opInfo.serviceSrcInstNode = rmPolicyGetLinuxInstNode(rmHandle);
1183     opInfo.operation = Rm_allocatorOp_ALLOCATE_INIT;
1184     opInfo.resourceInfo = &resourceInfo;    
1186     while(linuxAlias) {
1187         /* Reset parsing variables */
1188         pathOffset = 0;
1189         pathSize = strlen(linuxAlias->path) + 1;
1190         nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;
1191         prevDepth = RM_DTB_UTIL_STARTING_DEPTH;   
1192         resourceInfo.base = 0;
1193         resourceInfo.length = 0;
1195         spacePtr = strpbrk(linuxAlias->path, " ");
1196         if (spacePtr) {
1197             *spacePtr = '\0';
1198         }       
1199         
1200         while(pathOffset < pathSize) {
1201             /* Move through DTB nodes until next alias path node found */
1202             if (strcmp(linuxAlias->path + pathOffset, fdt_get_name(linuxDtb, nodeOffset, NULL))) {
1203                 nodeOffset = fdt_next_node(linuxDtb, nodeOffset, &depth);
1205                 if ((depth < prevDepth) || (nodeOffset == -FDT_ERR_NOTFOUND)) {
1206                     /* Returning from subnode that matched part of alias path without finding
1207                      * resource values */
1208                     retVal = RM_ERROR_DATA_NOT_FOUND_AT_LINUX_ALIAS;
1209                     break;
1210                 }
1211             }
1212             else {
1213                 /* Found next alias path node.  Move to next node name in path string. */
1214                 pathOffset += (strlen(linuxAlias->path + pathOffset) + 1);
1215                 spacePtr = strpbrk(linuxAlias->path + pathOffset, " ");
1216                 if (spacePtr) {
1217                     *spacePtr = '\0';
1218                 }       
1219                 
1220                 prevDepth = fdt_node_depth(linuxDtb, nodeOffset);
1221                 propOffset = fdt_first_property_offset(linuxDtb, nodeOffset);
1222                 while ((propOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) &&
1223                        (pathOffset < pathSize)) {
1224                     propertyData = fdt_getprop_by_offset(linuxDtb, propOffset, 
1225                                                          &propertyName, &propertyLen);
1227                     if (strcmp(linuxAlias->path + pathOffset, propertyName) == 0) {
1228                         /* Found resource at end of alias path */
1229                         pathOffset += (strlen(linuxAlias->path + pathOffset) + 1);
1230                         linuxValueRange = rmDtbUtilLinuxExtractValues(propertyData, propertyLen);
1231                         retVal = allocatorReserveLinuxResource(rmHandle, linuxAlias, 
1232                                                                linuxValueRange, &opInfo);
1233                         rmDtbUtilLinuxFreeValues(linuxValueRange);
1234                     }
1235                     propOffset = fdt_next_property_offset(linuxDtb, propOffset);
1236                 } 
1238                 if (propOffset < -FDT_ERR_NOTFOUND) {
1239                     retVal = propOffset;
1240                     break;
1241                 }
1242             }
1243         }
1245         if (retVal < RM_OK) {
1246             break;
1247         }
1248         linuxAlias = linuxAlias->nextLinuxAlias;
1249     }
1250     return (retVal);
1253 /* FUNCTION PURPOSE: Creates and initializes a resource allocator
1254  ***********************************************************************
1255  * DESCRIPTION: Creates a resource allocator for the provided
1256  *              resource name and resource properties retrieved
1257  *              from the GRL.  Resources will be reserved for 
1258  *              the Linux kernel if the Linux DTB is provided
1259  *              and there are "linux-dtb-alias" properties
1260  *              specified in the GRL.
1261  */
1262 static int32_t allocatorExtractGrlResProps(Rm_Handle rmHandle, const char *resourceName, 
1263                                            Rm_ResourceProperties *resourceProperties, void *linuxDtb)
1265     Rm_Inst             *rmInst = (Rm_Inst *)rmHandle;
1266     Rm_ResourceRange    *range = NULL;
1267     Rm_ResourceRange    *rangeBasePtr = NULL;
1268     Rm_NsAssignment     *nsAssignments = NULL;
1269     Rm_NsAssignment     *nsAssignmentBasePtr = NULL;
1270     Rm_LinuxAlias       *linuxAlias = NULL;
1271     Rm_NameServerObjCfg  nameServerObjCfg;      
1272     int32_t              retVal = RM_OK;
1274     if (resourceProperties->rangeData && (resourceProperties->rangeLen > 0)) {
1275         range = rangeBasePtr = rmDtbUtilResExtractRange(resourceProperties->rangeData, 
1276                                                         resourceProperties->rangeLen);
1277         
1278         if ((retVal = rmAllocatorCreate(rmHandle, resourceName, range)) >= RM_OK) {
1279             if (resourceProperties->linuxAliasData && resourceProperties->linuxAliasLen) {
1280                 if (linuxDtb) {
1281                     linuxAlias = rmDtbUtilResExtractLinuxAlias(resourceProperties->linuxAliasData,
1282                                                                resourceProperties->linuxAliasLen, &retVal);
1283                     if (linuxAlias) {
1284                         retVal = allocatorFindLinuxResource(rmHandle, resourceName, linuxDtb, linuxAlias);            
1285                     }
1286                 }
1287             }
1288         }
1289     }
1290     
1291     if (retVal >= RM_OK) {
1292         if (resourceProperties->nsAssignData && resourceProperties->nsAssignLen) {
1293             nsAssignments = rmDtbUtilResExtractNsAssignment(resourceProperties->nsAssignData, 
1294                                                             resourceProperties->nsAssignLen, &retVal);
1295             if (nsAssignments) {
1296                 nsAssignmentBasePtr = nsAssignments;
1297                 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1298                     rmNameServerTreeInv(rmInst->u.server.nameServer);
1299                 }                  
1300                 while (nsAssignments) {
1301                     memset((void *)&nameServerObjCfg, 0, sizeof(nameServerObjCfg));
1302                     nameServerObjCfg.nameServerTree = rmInst->u.server.nameServer;
1303                     nameServerObjCfg.nodeCfg.objName = nsAssignments->nsName;
1304                     nameServerObjCfg.nodeCfg.resourceName = (char *)resourceName;
1305                     nameServerObjCfg.nodeCfg.resourceBase= nsAssignments->resourceBase;
1306                     nameServerObjCfg.nodeCfg.resourceLength = nsAssignments->resourceLength;                
1307                     rmNameServerAddObject(&nameServerObjCfg);
1308                     nsAssignments = nsAssignments->nextNsAssignment;
1309                 }
1310                 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1311                     rmNameServerTreeWb(rmInst->u.server.nameServer);
1312                 }                
1313                 rmDtbUtilResFreeNsAssignmentList(nsAssignmentBasePtr);
1314             }
1315         }
1316     }
1317     else {
1318         rmAllocatorDelete(rmHandle, resourceName);
1319     }
1321     rmDtbUtilResFreeRange(rangeBasePtr);
1322     if (linuxAlias) {
1323         rmDtbUtilResFreeLinuxAlias(linuxAlias);
1324     }
1325     return(retVal);
1328 /**********************************************************************
1329  ********************** Internal Functions ****************************
1330  **********************************************************************/
1332 /* FUNCTION PURPOSE: Creates a new resource tree
1333  ***********************************************************************
1334  * DESCRIPTION: Creates and populates a new resource tree allocator
1335  *              using the provided resource name and value range.  The
1336  *              name and value originate from the GRL.
1337  */
1338 int32_t rmAllocatorCreate(Rm_Handle rmHandle, const char *resourceName, Rm_ResourceRange *range)
1340     Rm_Inst         *rmInst = (Rm_Inst *)rmHandle;
1341     Rm_Allocator    *allocator = NULL;
1342     Rm_ResourceTree *treeRoot = NULL;
1343     Rm_ResourceNode *treeNode = NULL;
1345     allocator = allocatorAdd(rmHandle, resourceName);
1346     treeRoot = Rm_osalMalloc(sizeof(*treeRoot));
1347     RB_INIT(treeRoot);
1349     while (range != NULL) {
1350         treeNode = rmResourceNodeNew(range->base, range->length);
1351         RB_INSERT(_Rm_AllocatorResourceTree, treeRoot, treeNode);
1352         range = range->nextRange;
1353     }
1354     if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1355         rmResourceTreeWb(treeRoot);
1356     }
1357     
1358     allocator->allocatorRootEntry = treeRoot;
1359     RM_SS_OBJ_WB(allocator, Rm_Allocator);
1360     return(RM_OK);
1363 /* FUNCTION PURPOSE: Returns a pointer to the allocator list
1364  ***********************************************************************
1365  * DESCRIPTION: Returns a pointer to the instance's allocator list
1366  *              based on the instance type
1367  */
1368 Rm_Allocator *rmAllocatorGetAllocatorList(Rm_Handle rmHandle)
1370     Rm_Inst      *rmInst = (Rm_Inst *)rmHandle;
1371     Rm_Allocator *list = NULL;
1373     if ((rmInst->instType == Rm_instType_SERVER) ||
1374         (rmInst->instType == Rm_instType_SHARED_SERVER)) {
1375         list = rmInst->u.server.allocators;
1376     }
1377     else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1378         list = rmInst->u.cd.allocators;
1379     }
1380     return(list);
1383 /* FUNCTION PURPOSE: Finds an allocator
1384  ***********************************************************************
1385  * DESCRIPTION: Returns a pointer to an allocator that matches the 
1386  *              provided resource name.
1387  */
1388 Rm_Allocator *rmAllocatorFind(Rm_Handle rmHandle, const char *resourceName)
1390     Rm_Inst      *rmInst = (Rm_Inst *)rmHandle;
1391     Rm_Allocator *allocatorList = rmAllocatorGetAllocatorList(rmHandle);
1392     
1393     while (allocatorList) {
1394         RM_SS_OBJ_INV(allocatorList, Rm_Allocator);
1395         if (strncmp(allocatorList->resourceName, resourceName, RM_NAME_MAX_CHARS) == 0) {
1396             break;             
1397         }
1398         allocatorList = allocatorList->nextAllocator;
1399     }
1401     return (allocatorList);
1404 /* FUNCTION PURPOSE: Checks if a resource node is localized
1405  ***********************************************************************
1406  * DESCRIPTION: Checks if a resource node is localized.  A localized
1407  *              node is one that is free and has no neighboring nodes
1408  *              or neighboring nodes that do not have resource values
1409  *              contiguous with the node being checked.  The function
1410  *              will return RM_TRUE is the node is localized.  
1411  *              Otherwise, the function returns RM_FALSE
1412  */
1413 int rmAllocatorGetNodeLocalization(Rm_Handle rmHandle, char *resourceName, 
1414                                    int32_t *resBase, uint32_t *resLen)
1416     Rm_Inst         *rmInst = (Rm_Inst *)rmHandle;
1417     void *           policy = rmPolicyGetPolicy((Rm_Handle)rmInst);
1418     int32_t          resOffsetInPolicy = rmPolicyGetResourceOffset(policy, resourceName);
1419     uint32_t         allocSize = rmPolicyGetResourceCdAllocSize(policy, resOffsetInPolicy);    
1420     Rm_Allocator    *allocator = rmAllocatorFind(rmHandle, resourceName);
1421     Rm_ResourceNode  findNode;
1422     Rm_ResourceNode *matchingNode = NULL;
1423     Rm_ResourceNode *neighborNode = NULL;   
1424     int              nodeIsLocalized;
1426     memset((void *)&findNode, 0, sizeof(findNode));
1427     findNode.base = *resBase;
1428     findNode.length = *resLen;
1429     matchingNode = RB_FIND(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, &findNode);
1431     if (matchingNode) {
1432         /* Node can be freed back to Server from CD if:
1433          * - allocationCount == 0
1434          * - node's resource range is multiple of policy allocation size
1435          * - node's resource range boundaries are not contiguous with surrounding nodes */
1436         if (matchingNode->allocationCount) {
1437             nodeIsLocalized = RM_FALSE;
1438             goto exitLocalization;
1439         }
1440             
1441         if (matchingNode->length % allocSize) {
1442             nodeIsLocalized = RM_FALSE;
1443             goto exitLocalization;        
1444         }
1446         /* Check left neighbor */
1447         neighborNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
1448         if (neighborNode && allocatorResNodeBoundaryCompare(neighborNode, matchingNode)) {
1449             nodeIsLocalized = RM_FALSE;
1450             goto exitLocalization; 
1451         }
1453         /* Check right neighbor */
1454         neighborNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
1455         if (neighborNode && allocatorResNodeBoundaryCompare(neighborNode, matchingNode)) {
1456             nodeIsLocalized = RM_FALSE;
1457             goto exitLocalization; 
1458         }
1460         /* All localization checks passed.  Return the base and length of localized node. */
1461         nodeIsLocalized = RM_TRUE;
1462         *resBase = matchingNode->base;
1463         *resLen = matchingNode->length;
1464     }
1465     else {
1466         nodeIsLocalized = RM_FALSE;
1467     }
1469 exitLocalization:
1470     return (nodeIsLocalized);
1473 /* FUNCTION PURPOSE: Issues an allocator operation
1474  ***********************************************************************
1475  * DESCRIPTION: Issues an allocator preallocate, allocate, or free
1476  *              for an RM resource.
1477  */
1478 int32_t rmAllocatorOperation(Rm_Handle rmHandle, Rm_AllocatorOpInfo *opInfo)
1480     Rm_Inst      *rmInst = (Rm_Inst *)rmHandle;
1481     Rm_Allocator *allocator = NULL;
1482     int32_t       resourceOffsetInPolicy;
1483     int32_t       retVal;
1484     
1485     resourceOffsetInPolicy = rmPolicyGetResourceOffset(opInfo->policy, opInfo->resourceInfo->name);
1486     allocator = rmAllocatorFind(rmHandle, opInfo->resourceInfo->name);
1487     
1488     if ((resourceOffsetInPolicy > 0) && allocator) {
1489         if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1490             rmResourceTreeInv(allocator->allocatorRootEntry);
1491         }
1493         if (opInfo->operation == Rm_allocatorOp_GET_STATUS) {
1494             retVal = allocatorStatus(allocator, opInfo);
1495         }
1496         else if ((opInfo->operation == Rm_allocatorOp_PRE_ALLOCATE_INIT) ||
1497                  (opInfo->operation == Rm_allocatorOp_PRE_ALLOCATE_USE)) {
1498             retVal = allocatorPreAllocate(rmHandle, allocator, resourceOffsetInPolicy, opInfo);
1499         }               
1500         else if ((opInfo->operation == Rm_allocatorOp_ALLOCATE_INIT) ||
1501                  (opInfo->operation == Rm_allocatorOp_ALLOCATE_USE)) {
1502             retVal = allocatorAllocate(rmHandle, allocator, resourceOffsetInPolicy, opInfo);
1503         }
1504         else if (opInfo->operation == Rm_allocatorOp_FREE) {
1505             retVal = allocatorFree(rmHandle, allocator, opInfo);
1506         } 
1508         if ((rmInst->instType == Rm_instType_SHARED_SERVER) &&
1509             (opInfo->operation != Rm_allocatorOp_GET_STATUS) &&
1510             (retVal == RM_SERVICE_APPROVED)) {
1511             rmResourceTreeWb(allocator->allocatorRootEntry);
1512         }        
1513     }
1514     else {
1515         /* Resource could not be found in policy and/or allocator */
1516         retVal = RM_SERVICE_DENIED_RES_DOES_NOT_EXIST;
1517     }
1518     return(retVal);
1521 /* FUNCTION PURPOSE: Initializes server allocators
1522  ***********************************************************************
1523  * DESCRIPTION: Creates and initializes a server instance's
1524  *              resource allocators using the GRL and, if
1525  *              provided, Linux DTB.
1526  */
1527 int32_t rmAllocatorInitializeResources(Rm_Handle rmHandle, void *globalResourceDtb, void *linuxDtb)
1529     int32_t                nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;
1530     int32_t                nodeDepth = RM_DTB_UTIL_STARTING_DEPTH;
1531     Rm_ResourceProperties  resProperties;    
1532     int32_t                propOffset;
1533     int32_t                propertyLen;
1534     const char            *propertyName;
1535     const void            *propertyData;
1536     Rm_ResourcePropType    propertyType;  
1537     int32_t                retVal = RM_OK;
1539     /* Parse the Global Resource List, creating an allocator for each specified resource node */
1540     while ((nodeOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) && (nodeDepth >= RM_DTB_UTIL_STARTING_DEPTH)) {
1541         memset((void *)&resProperties, 0, sizeof(resProperties));
1542         /* Get properties of resource node */
1543         propOffset = fdt_first_property_offset(globalResourceDtb, nodeOffset);
1544         while (propOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) {
1545             propertyData = fdt_getprop_by_offset(globalResourceDtb, propOffset, &propertyName, &propertyLen);
1546             propertyType = rmDtbUtilResGetPropertyType(propertyName);
1547             if (propertyType == Rm_resourcePropType_RESOURCE_RANGE) {
1548                 resProperties.rangeData = propertyData;
1549                 resProperties.rangeLen = propertyLen;
1550             }
1551             else if (propertyType == Rm_resourcePropType_NSASSIGNMENT) {
1552                 resProperties.nsAssignData = propertyData;
1553                 resProperties.nsAssignLen = propertyLen;
1554             }
1555             else if (propertyType == Rm_resourcePropType_RESOURCE_LINUX_ALIAS) {
1556                 resProperties.linuxAliasData = propertyData;
1557                 resProperties.linuxAliasLen = propertyLen;
1558             }        
1559             else {
1560                 retVal = RM_ERROR_GRL_UNKNOWN_RESOURCE_PROPERTY;
1561                 goto exitAllocInit;
1562             }
1564             propOffset = fdt_next_property_offset(globalResourceDtb, propOffset);
1565             if (propOffset == -FDT_ERR_NOTFOUND) {
1566                 /* No more resource properties but at least one found.  Extract the property values */
1567                 retVal = allocatorExtractGrlResProps(rmHandle, fdt_get_name(globalResourceDtb, nodeOffset, NULL), 
1568                                                      &resProperties, linuxDtb);
1569                 if (retVal < RM_OK) {
1570                     goto exitAllocInit;
1571                 }
1572             }
1573             else if (propOffset < -FDT_ERR_NOTFOUND) {
1574                 /* Error returned by LIBFDT */
1575                 retVal = propOffset;
1576                 goto exitAllocInit;
1577             }
1578         }
1579         if (propOffset < -FDT_ERR_NOTFOUND) {
1580             /* Error returned by LIBFDT */
1581             retVal = propOffset;
1582             goto exitAllocInit;
1583         }
1585         nodeOffset = fdt_next_node(globalResourceDtb, nodeOffset, &nodeDepth);
1586         if (nodeOffset < -FDT_ERR_NOTFOUND) {
1587             /* Error returned by LIBFDT */
1588             retVal = nodeOffset;
1589             goto exitAllocInit;
1590         }
1591     }
1592 exitAllocInit:    
1593     return(retVal);
1596 /* FUNCTION PURPOSE: Deletes a resource allocator resource node
1597  ***********************************************************************
1598  * DESCRIPTION: Deletes a resource allocator's node based on the given
1599  *              resource name, base and length.
1600  */
1601 void rmAllocatorDeleteNode(Rm_Handle rmHandle, const char *resName, int32_t resBase, uint32_t resLen)
1603     Rm_Allocator    *allocator = rmAllocatorFind(rmHandle, resName);
1604     Rm_ResourceNode  findNode;
1605     Rm_ResourceNode *matchingNode;
1607     memset((void *)&findNode, 0, sizeof(findNode));
1608     findNode.base = resBase;
1609     findNode.length = resLen;
1610     matchingNode = RB_FIND(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, &findNode);
1611     
1612     if (matchingNode) {
1613         RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
1614         rmResourceNodeFree(matchingNode);
1615     }
1618 /* FUNCTION PURPOSE: Deletes a resource allocator
1619  ***********************************************************************
1620  * DESCRIPTION: Deletes a resource allocator based on the given
1621  *              resource name.  The resource allocator will be
1622  *              removed from the RM instance allocator list.
1623  */
1624 int32_t rmAllocatorDelete(Rm_Handle rmHandle, const char *resourceName)
1626     Rm_Inst         *rmInst = (Rm_Inst *)rmHandle;    
1627     Rm_Allocator    *allocator = rmAllocatorGetAllocatorList(rmHandle);
1628     Rm_Allocator    *prevAllocator = NULL;
1629     Rm_ResourceTree *treeRoot;
1630     Rm_ResourceNode *node = NULL;
1631     Rm_ResourceNode *nextNode = NULL;
1632     int32_t          retVal = RM_OK;
1634     while (allocator) {
1635         if (strncmp(allocator->resourceName, resourceName, RM_NAME_MAX_CHARS) == 0) {
1636             break;             
1637         }
1638         prevAllocator = allocator;
1639         allocator = allocator->nextAllocator;
1640     }
1642     if (allocator) {
1643         if (prevAllocator == NULL) {
1644             if ((rmInst->instType == Rm_instType_SERVER) ||
1645                 (rmInst->instType == Rm_instType_SHARED_SERVER)) {
1646                 rmInst->u.server.allocators = allocator->nextAllocator;
1647             }
1648             else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1649                 rmInst->u.cd.allocators = allocator->nextAllocator;
1650             }              
1651         }
1652         else {
1653             prevAllocator->nextAllocator = allocator->nextAllocator;
1654             RM_SS_OBJ_WB(prevAllocator, Rm_Allocator);
1655         }
1656             
1657         /* Destroy tree and return error */
1658         treeRoot = allocator->allocatorRootEntry;
1659         for (node = RB_MIN(_Rm_AllocatorResourceTree, treeRoot); node != NULL; node = nextNode) {
1660                 nextNode = RB_NEXT(_Rm_AllocatorResourceTree, treeRoot, node);
1661                 RB_REMOVE(_Rm_AllocatorResourceTree, treeRoot, nextNode);
1662             rmResourceNodeFree(node);
1663         }
1664         Rm_osalFree((void *)treeRoot, sizeof(*treeRoot));        
1665         Rm_osalFree((void *)allocator, sizeof(*allocator));
1666     }
1667     else {
1668         retVal = RM_ERROR_RES_ALLOCATOR_DOES_NOT_EXIST;
1669     }
1670     return (retVal);
1673 /* FUNCTION PURPOSE: Deletes server allocators
1674  ***********************************************************************
1675  * DESCRIPTION: Removes all resource nodes for each
1676  *              resource allocator and then deletes the allocator
1677  *              itself.  Used to free all memory consumed
1678  *              by the allocators.
1679  */
1680 void rmAllocatorDeleteResources(Rm_Handle rmHandle)
1682     Rm_Inst         *rmInst = (Rm_Inst *)rmHandle;
1683     Rm_Allocator    *allocatorList = rmAllocatorGetAllocatorList(rmHandle);
1684     Rm_Allocator    *nextAllocator;
1685     Rm_ResourceTree *resTree;
1686     Rm_ResourceNode *resNode;
1687     Rm_ResourceNode *nextResNode;
1689     while (allocatorList) {
1690         RM_SS_OBJ_INV(allocatorList, Rm_Allocator);
1691         nextAllocator = allocatorList->nextAllocator;
1692         resTree = allocatorList->allocatorRootEntry;
1694         if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1695             rmResourceTreeInv(resTree);
1696         }
1697         /* Delete each resource node in the allocator */
1698         for (resNode = RB_MIN(_Rm_AllocatorResourceTree, resTree); resNode != NULL; resNode = nextResNode) {
1699             nextResNode = RB_NEXT(_Rm_AllocatorResourceTree, resTree, resNode);
1700             RB_REMOVE(_Rm_AllocatorResourceTree, resTree, resNode);
1701             if (resNode->allocationCount) {
1702                 /* Delete all the owners in the resource's owner list */
1703                 allocatorResNodeOwnerClear(rmHandle, resNode);
1704             }
1705             rmResourceNodeFree(resNode);
1706         }        
1708         Rm_osalFree((void *)resTree, sizeof(*resTree));
1709         Rm_osalFree((void *)allocatorList, sizeof(*allocatorList));
1710         allocatorList = nextAllocator;
1711     }