Resolved SDOCM00101586. Added test cases to cover resolved issued
[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             nodePassesPolicy = RM_BOOL_UNDEF;
507             if ((matchingNode->allocationCount == 0) &&
508                 (findNode.base >= matchingNode->base) && (findEnd <= matchingEnd)) {
509                 /* Attempt to preallocate from node only if not owned by anyone and sits
510                  * within a matching node. */
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 (!nodePassesPolicy) {
571                         findNode.base += findNode.length;
572                     }
573                     else {
574                         /* Matching node allocated, move to next node */
575                         if (nextNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode)) {
576                             findNode.base = nextNode->base;
577                         }
578                         else {
579                             retVal = RM_SERVICE_DENIED_RES_ALLOC_REQS_NOT_MET;
580                         }
581                     }
582                 }
583             }
584         }
585         else {
586             retVal = RM_SERVICE_DENIED_RES_ALLOC_REQS_NOT_MET;
587         }
588     } while ((!resourceFound) && 
589              (retVal != RM_SERVICE_DENIED_RES_ALLOC_REQS_NOT_MET));
591     return(retVal); 
594 /* FUNCTION PURPOSE: Allocates an allocator resource
595  ***********************************************************************
596  * DESCRIPTION: Will attempt to allocate the resource with specified
597  *              base and length from the resource's allocator.  The
598  *              allocation algorithm will verify the allocation against
599  *              the policy permissions for the instance requesting the
600  *              allocation.  If the policy allows the allocation the 
601  *              algorithm will allocate the resource then combine any
602  *              resource nodes that may have become equivalent (in terms
603  *              of ownership) after the allocation.
604  */
605 static int32_t allocatorAllocate(Rm_Handle rmHandle, Rm_Allocator *allocator, int32_t resourcePolicy, 
606                                  Rm_AllocatorOpInfo *opInfo)
608     Rm_ResourceNode     findNode;
609     Rm_ResourceNode    *matchingNode = NULL;
610     Rm_ResourceNode    *leftNode = NULL;
611     Rm_ResourceNode    *rightNode = NULL;
612     Rm_PolicyCheckType  policyCheckType;    
613     Rm_PolicyCheckCfg   policyCheckCfg;
614     int                 allocPassesPolicy;
615     int                 combineLeft = RM_FALSE;
616     int                 combineRight = RM_FALSE;    
617     uint32_t            findEnd;
618     uint32_t            matchingEnd;  
619     int32_t             retVal;
621     if (opInfo->operation == Rm_allocatorOp_ALLOCATE_INIT) {
622         policyCheckType = Rm_policyCheck_INIT;
623     }
624     else if (opInfo->operation == Rm_allocatorOp_ALLOCATE_USE) {
625         policyCheckType = Rm_policyCheck_USE;
626     }
627     else {
628         retVal = RM_ERROR_INVALID_SERVICE_TYPE;
629         return (retVal);
630     }   
632     memset((void *)&findNode, 0, sizeof(findNode));
633     findNode.base = opInfo->resourceInfo->base;
634     findNode.length = opInfo->resourceInfo->length;
635     matchingNode = RB_FIND(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, &findNode);
637     /* Prepare privilege checks */
638     memset((void *)&policyCheckCfg, 0, sizeof(policyCheckCfg)); 
640     if (matchingNode) {
641         findEnd = findNode.base + findNode.length - 1;
642         matchingEnd = matchingNode->base + matchingNode->length - 1;
643         
644         if ((findNode.base >= matchingNode->base) && (findEnd <= matchingEnd)) {
645             if (opInfo->serviceSrcInstNode == rmPolicyGetLinuxInstNode(rmHandle)) {
646                 /* Bypass policy checks since Linux Kernel has full privileges */
647                 allocPassesPolicy = RM_TRUE;
648             }
649             else {
650                 policyCheckCfg.policyDtb = opInfo->policy;
651                 policyCheckCfg.resourceOffset = resourcePolicy;    
652                 policyCheckCfg.type = policyCheckType;
653                 policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;
654                 policyCheckCfg.resourceBase = findNode.base;
655                 policyCheckCfg.resourceLength = findNode.length;
656                 allocPassesPolicy = rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);
657                 if (!allocPassesPolicy) {
658                     if (policyCheckType == Rm_policyCheck_INIT) {
659                         retVal = RM_SERVICE_DENIED_INIT_PERM_NOT_GIVEN;
660                     }
661                     else {
662                         retVal = RM_SERVICE_DENIED_USE_PERM_NOT_GIVEN;
663                     }
664                 }
666                 if (!allocatorResNodeIsOwnedBy(rmHandle, matchingNode, opInfo->serviceSrcInstNode)) {
667                     if (allocPassesPolicy && (matchingNode->allocationCount > 0)) {
668                         if (allocatorResNodeIsOwnedBy(rmHandle, matchingNode, rmPolicyGetLinuxInstNode(rmHandle))) {
669                             /* Check if instance requesting resource has privileges to share
670                              * a resource already reserved by Linux */
671                             policyCheckCfg.type = Rm_policyCheck_SHARED_LINUX;
672                             policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;
673                             allocPassesPolicy = rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);
674                             if (!allocPassesPolicy) {
675                                 retVal = RM_SERVICE_DENIED_RES_NOT_SHARED_LINUX;
676                             }
677                         }
678                         if (allocPassesPolicy) {
679                             /* Check exclusive privileges of instance requesting resource.  Requesting
680                              * instance with exclusive privileges can't reserve resource if already owned*/
681                             policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;
682                             policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;
683                             allocPassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);
684                             if (!allocPassesPolicy) {
685                                 retVal = RM_SERVICE_DENIED_EXCLUSIVE_RES_ALLOCD;
686                             }
687                         }
688                     }
689                     if (allocPassesPolicy && (matchingNode->allocationCount == 1)) {
690                         /* Check exclusive privileges of instance that currently owns resource */
691                         policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;
692                         policyCheckCfg.validInstNode = matchingNode->ownerList->instNameNode;
693                         allocPassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);
694                         if (!allocPassesPolicy) {
695                             retVal = RM_SERVICE_DENIED_ALLOCD_TO_EXCLUSIVE_INST;
696                         }                
697                     }  
698                 }
699             }
700             
701             if (allocPassesPolicy) {
702                 /* Handle any possible node combinations if requesting instance is
703                  * not already in resource's owner list.  Automatic approval if requesting
704                  * instance is already in owner list. */
705                 if ((findNode.base == matchingNode->base) && (findEnd == matchingEnd)) {
706                     /* findNode range matches matchingNode range
707                      *
708                      *   |<--left node-->||<--matched  node-->||<--right node-->| => existing node
709                      *                    |<--alloc request-->|  => requested resources
710                      */                     
711                     leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
712                     rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
713                     RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
714                     allocatorResNodeOwnerAdd(rmHandle, matchingNode, opInfo->serviceSrcInstNode);
716                     if (leftNode && allocatorResNodeOwnerCompare(rmHandle, leftNode, matchingNode) &&
717                         allocatorResNodeBoundaryCompare(leftNode, matchingNode)) {
718                         RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
719                         combineLeft = RM_TRUE;
720                     }
721                     if (rightNode && allocatorResNodeOwnerCompare(rmHandle, rightNode, matchingNode) &&
722                         allocatorResNodeBoundaryCompare(rightNode, matchingNode)) {
723                         RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
724                         combineRight = RM_TRUE;
725                     }
727                     if (combineLeft && combineRight) {
728                         /* Combine all three nodes into matchingNode */
729                         matchingNode->base = leftNode->base;
730                         matchingNode->length = leftNode->length + matchingNode->length + rightNode->length;
732                         allocatorResNodeOwnerClear(rmHandle, leftNode);
733                         rmResourceNodeFree(leftNode);
734                         allocatorResNodeOwnerClear(rmHandle, rightNode);
735                         rmResourceNodeFree(rightNode);                        
736                     }
737                     else if (combineLeft) {
738                         /* Combine left and matching nodes.  Reinsert right. */
739                         matchingNode->base = leftNode->base;
740                         matchingNode->length += leftNode->length;
742                         allocatorResNodeOwnerClear(rmHandle, leftNode);
743                         rmResourceNodeFree(leftNode);
744                         if (rightNode) {
745                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);  
746                         }
747                     }
748                     else if (combineRight) {
749                         /* Combine right and matching nodes.  Reinsert left. */
750                         matchingNode->length += rightNode->length;
752                         allocatorResNodeOwnerClear(rmHandle, rightNode);
753                         rmResourceNodeFree(rightNode);
754                         if (leftNode) {
755                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
756                         }
757                     }
758                     else {
759                         /* No combine. */
760                         if (leftNode) {
761                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
762                         }
763                         if (rightNode) {
764                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
765                         }
766                     }
768                     /* Always reinsert matchingNode */                
769                     RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
770                     
771                     /* Matching node contains new reference count after alloc.  Return new owner count. */
772                     opInfo->resourceInfo->ownerCount = matchingNode->allocationCount;
773                 }   
774                 else if ((findNode.base > matchingNode->base) && (findEnd < matchingEnd)) {
775                     /* findNode range is subset of matchingNode range and neither boundary is
776                      * equivalent.
777                      *
778                      * |<----------matched node---------->|
779                      *        |<---alloc request--->|
780                      */ 
781                     RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
782                     leftNode = rmResourceNodeNew(matchingNode->base, findNode.base - matchingNode->base);
783                     allocatorResNodeOwnerCopy(rmHandle, leftNode, matchingNode);
784                     rightNode = rmResourceNodeNew(findNode.base + findNode.length, matchingEnd - findEnd);
785                     allocatorResNodeOwnerCopy(rmHandle, rightNode, matchingNode);
787                     matchingNode->base = findNode.base;                                    
788                     matchingNode->length = findNode.length;
789                     allocatorResNodeOwnerAdd(rmHandle, matchingNode, opInfo->serviceSrcInstNode);
791                     /* Insert all the nodes */
792                     RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
793                     RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
794                     RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
795                     
796                     /* Matching node contains new reference count after alloc.  Return new owner count. */
797                     opInfo->resourceInfo->ownerCount = matchingNode->allocationCount;
798                 }  
799                 else {    
800                     if (findNode.base == matchingNode->base) {
801                         /* findNode base and matchingNode base are equivalent.  May be combine
802                          * possibilities to the left
803                          *
804                          * |<---left node (alloc'd)--->||<----------matched node---------->|
805                          *                              |<---findNode (alloc req)--->|
806                          */                         
807                         leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
808                         RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
809                         /* Add allocating instance to owner list for compare with leftNode */
810                         allocatorResNodeOwnerAdd(rmHandle, matchingNode, opInfo->serviceSrcInstNode);
811                         
812                         if (leftNode && allocatorResNodeOwnerCompare(rmHandle, leftNode, matchingNode) &&
813                             allocatorResNodeBoundaryCompare(leftNode, matchingNode)) {
814                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
815                             /* Combine leftNode and findNode */
816                             leftNode->length += findNode.length;
817                         }
818                         else {
819                             leftNode = rmResourceNodeNew(findNode.base, findNode.length);
820                             allocatorResNodeOwnerCopy(rmHandle, leftNode, matchingNode);
821                         }
823                         /* Account for leftNode in matchingNode */
824                         matchingNode->base = findNode.base + findNode.length;
825                         matchingNode->length = matchingEnd - findEnd;  
827                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
828                         /* Left node contains new reference count after alloc.  Return new owner count. */
829                         opInfo->resourceInfo->ownerCount = leftNode->allocationCount;
830                     }
831                     else if (findEnd == matchingEnd) {
832                         /* findNode end and matchingNode end are equivalent.  May be combine
833                          * possibilities to the right
834                          *
835                          * |<----------matched node---------->||<---right node (alloc'd)--->|
836                          *       |<---findNode (alloc req)--->| 
837                          */                        
838                         rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
839                         RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
840                         /* Add allocating instance to owner list for compare with rightNode */
841                         allocatorResNodeOwnerAdd(rmHandle, matchingNode, opInfo->serviceSrcInstNode);
842                         
843                         if (rightNode && allocatorResNodeOwnerCompare(rmHandle, rightNode, matchingNode) &&
844                             allocatorResNodeBoundaryCompare(rightNode, matchingNode)) {
845                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
846                             /* Combine rightNode and findNode */
847                             rightNode->base = findNode.base;
848                             rightNode->length += findNode.length;
849                         }
850                         else {
851                             rightNode = rmResourceNodeNew(findNode.base, findNode.length);
852                             allocatorResNodeOwnerCopy(rmHandle, rightNode, matchingNode);
853                         }
855                         /* Account for rightNode in matchingNode */
856                         matchingNode->length -= findNode.length;  
858                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
859                         /* Right node contains new reference count after alloc.  Return new owner count. */
860                         opInfo->resourceInfo->ownerCount = rightNode->allocationCount;
861                     }
862                     /* Remove allocating instance from leftover matchingNode */
863                     allocatorResNodeOwnerDelete(rmHandle, matchingNode, opInfo->serviceSrcInstNode);
864                     RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
865                 }
866                 retVal = RM_SERVICE_APPROVED;
867             }
868         }
869         else {
870             retVal = RM_SERVICE_DENIED_PARTIAL_ALLOCATION;
871         }
872     }
873     else {
874         retVal = RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST;
875     }
877     return(retVal);        
880 /* FUNCTION PURPOSE: Frees an allocator resource
881  ***********************************************************************
882  * DESCRIPTION: Will attempt to free the resource with specified
883  *              base and length from the resource's allocator.  The
884  *              free algorithm will verify the free request parameters
885  *              match an allocated range for the resource and that the
886  *              range is owned by the instance requesting the free. If
887  *              the free is validated the algorithm will free the 
888  *              resource then combine any resource nodes that may have
889  *              become equivalent (in terms of ownership) after the
890  *              allocation.
891  */
892 static int32_t allocatorFree(Rm_Handle rmHandle, Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)
894     Rm_ResourceNode  findNode;
895     Rm_ResourceNode *matchingNode = NULL;
896     Rm_ResourceNode *leftNode = NULL;
897     Rm_ResourceNode *rightNode = NULL;
898     int              combineLeft = RM_FALSE;
899     int              combineRight = RM_FALSE;
900     uint32_t         findEnd;
901     uint32_t         matchingEnd;
902     int32_t          retVal;
904     memset((void *)&findNode, 0, sizeof(findNode));
905     findNode.base = opInfo->resourceInfo->base;
906     findNode.length = opInfo->resourceInfo->length;
907     matchingNode = RB_FIND(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, &findNode);
909     if (matchingNode) {
910         findEnd = findNode.base + findNode.length - 1;
911         matchingEnd = matchingNode->base + matchingNode->length - 1;
912         
913         if ((findNode.base >= matchingNode->base) && (findEnd <= matchingEnd)) {  
914             if (matchingNode->allocationCount) {
915                 if (allocatorResNodeIsOwnedBy(rmHandle, matchingNode, opInfo->serviceSrcInstNode)) {
916                     if ((findNode.base == matchingNode->base) && (findEnd == matchingEnd))
917                     {
918                         /* Case 1: Free range equals allocated matched node exactly. Attempt to combine 
919                          *         freed node with nodes to left and right.
920                          *
921                          * |<--left node-->||<---matched node--->||<--right node-->|
922                          *                  |<---free request--->|
923                          */ 
924                         leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
925                         rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
926                         RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
927                         allocatorResNodeOwnerDelete(rmHandle, matchingNode, opInfo->serviceSrcInstNode);
929                         if (leftNode && allocatorResNodeOwnerCompare(rmHandle, leftNode, matchingNode) &&
930                             allocatorResNodeBoundaryCompare(leftNode, matchingNode)) {
931                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
932                             combineLeft = RM_TRUE;
933                         }
934                         if (rightNode && allocatorResNodeOwnerCompare(rmHandle, rightNode, matchingNode) &&
935                             allocatorResNodeBoundaryCompare(rightNode, matchingNode)) {
936                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
937                             combineRight = RM_TRUE;
938                         }
940                         if (combineLeft && combineRight) {
941                             /* Combine all three nodes into matchingNode */
942                             matchingNode->base = leftNode->base;
943                             matchingNode->length = leftNode->length + matchingNode->length + rightNode->length;
945                             allocatorResNodeOwnerClear(rmHandle, leftNode);
946                             rmResourceNodeFree(leftNode);
947                             allocatorResNodeOwnerClear(rmHandle, rightNode);
948                             rmResourceNodeFree(rightNode);                        
949                         }
950                         else if (combineLeft) {
951                             /* Combine left and matching nodes.  Reinsert right. */
952                             matchingNode->base = leftNode->base;
953                             matchingNode->length += leftNode->length;
955                             allocatorResNodeOwnerClear(rmHandle, leftNode);
956                             rmResourceNodeFree(leftNode);
957                             if (rightNode) {
958                                 RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode); 
959                             }
960                         }
961                         else if (combineRight) {
962                             /* Combine right and matching nodes.  Reinsert left. */
963                             matchingNode->length += rightNode->length;
965                             allocatorResNodeOwnerClear(rmHandle, rightNode);
966                             rmResourceNodeFree(rightNode);
967                             if (leftNode) {
968                                 RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
969                             }
970                         }
971                         else {
972                             /* No combine. */
973                             if (leftNode) {
974                                 RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
975                             }
976                             if (rightNode) {
977                                 RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
978                             }
979                         }
981                         /* Always reinsert matchingNode */
982                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
983                         
984                         /* Matching node is what remains after free.  Return remaining owner count. */
985                         opInfo->resourceInfo->ownerCount = matchingNode->allocationCount;
986                     }
987                     else if ((findNode.base > matchingNode->base) && (findEnd < matchingEnd)) {
988                         /* Case 2: Free range is less than range in matched node. Split
989                          *         matched node into three nodes.
990                          *
991                          * |<----------matched node---------->|
992                          *        |<---free request--->|
993                          *
994                          * Remove instance from owner list then add it back in for side nodes for
995                          * proper accounting of allocations in validInstance list
996                          */ 
997                         RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
998                         allocatorResNodeOwnerDelete(rmHandle, matchingNode, opInfo->serviceSrcInstNode);
999                         
1000                         leftNode = rmResourceNodeNew(matchingNode->base, findNode.base - matchingNode->base);
1001                         allocatorResNodeOwnerCopy(rmHandle, leftNode, matchingNode);
1002                         allocatorResNodeOwnerAdd(rmHandle, leftNode, opInfo->serviceSrcInstNode);
1003                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
1004                         
1005                         rightNode = rmResourceNodeNew(findNode.base + findNode.length, matchingEnd - findEnd);
1006                         allocatorResNodeOwnerCopy(rmHandle, rightNode, matchingNode);
1007                         allocatorResNodeOwnerAdd(rmHandle, rightNode, opInfo->serviceSrcInstNode);
1008                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
1010                         matchingNode->base = findNode.base;                                    
1011                         matchingNode->length = findNode.length;
1012                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
1013                         
1014                         /* Matching node is what remains after free.  Return remaining owner count. */
1015                         opInfo->resourceInfo->ownerCount = matchingNode->allocationCount;
1016                     }
1017                     else {                        
1018                         if (findNode.base == matchingNode->base) {
1019                             /* Case 3: Free range is on left boundary of matched node. Try to 
1020                              *         combine free range with left node.
1021                              *
1022                              * |<---left node (free)--->||<----------matched node---------->|
1023                              *                           |<---findNode (free req)--->|
1024                              */ 
1026                             leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
1027                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
1028                             /* Remove freeing instance from owner list for compare with leftNode */
1029                             allocatorResNodeOwnerDelete(rmHandle, matchingNode, opInfo->serviceSrcInstNode);
1030                             
1031                             if (leftNode && allocatorResNodeOwnerCompare(rmHandle, leftNode, matchingNode) &&
1032                                 allocatorResNodeBoundaryCompare(leftNode, matchingNode)) {
1033                                 RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
1034                                 /* Combine leftNode and findNode */
1035                                 leftNode->length += findNode.length;
1036                             }
1037                             else {
1038                                 leftNode = rmResourceNodeNew(findNode.base, findNode.length);
1039                                 allocatorResNodeOwnerCopy(rmHandle, leftNode, matchingNode);
1040                             }
1042                             /* Remove leftNode range from matchingNode */
1043                             matchingNode->base = findNode.base + findNode.length;
1044                             matchingNode->length = matchingEnd - findEnd;  
1045                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
1046                             
1047                             /* Left node is what remains after free.  Return remaining owner count. */
1048                             opInfo->resourceInfo->ownerCount = leftNode->allocationCount;
1049                         }
1050                         else if (findEnd == matchingEnd) {
1051                             /* Case 4: Free range is on right boundary of matched node. Try to 
1052                              *         combine free range with right node.
1053                              *
1054                              * |<----------matched node---------->||<---right node (free)--->|
1055                              *        |<---findNode (free req)--->|
1056                              */ 
1057                             
1058                             rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
1059                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode); 
1060                             /* Remove freeing instance from owner list for compare with rightNode */
1061                             allocatorResNodeOwnerDelete(rmHandle, matchingNode, opInfo->serviceSrcInstNode);
1062                             
1063                             if (rightNode && allocatorResNodeOwnerCompare(rmHandle, rightNode, matchingNode) &&
1064                                 allocatorResNodeBoundaryCompare(rightNode, matchingNode)) {
1065                                 RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
1066                                 /* Combine rightNode and findNode */
1067                                 rightNode->base = findNode.base;
1068                                 rightNode->length += findNode.length;
1069                             }
1070                             else {
1071                                 rightNode = rmResourceNodeNew(findNode.base, findNode.length);
1072                                 allocatorResNodeOwnerCopy(rmHandle, rightNode, matchingNode);
1073                             }
1075                             /* Remove rightNode range from matchingNode */
1076                             matchingNode->length -= findNode.length;  
1077                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
1078                             
1079                             /* Right node is what remains after free.  Return remaining owner count. */
1080                             opInfo->resourceInfo->ownerCount = rightNode->allocationCount;
1081                         }
1083                         /* Add freeing instance back into matchingNode allocations */
1084                         allocatorResNodeOwnerAdd(rmHandle, matchingNode, opInfo->serviceSrcInstNode);
1085                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
1086                     }
1087                     retVal = RM_SERVICE_APPROVED;
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_NOT_ALLOCD_TO_INST;
1093                 }
1094             }
1095             else {
1096                 /* Return owner count.  In case it's a reference count check in application */
1097                 opInfo->resourceInfo->ownerCount = matchingNode->allocationCount;
1098                 retVal = RM_SERVICE_DENIED_RES_ALREADY_FREE;
1099             }
1100         }
1101         else {
1102             retVal = RM_SERVICE_DENIED_PARTIAL_FREE;
1103         }
1104     }
1105     else {
1106         retVal = RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST;
1107     }
1108     return(retVal);  
1111 /* FUNCTION PURPOSE: Reserves a Linux resource
1112  ***********************************************************************
1113  * DESCRIPTION: Reserves resources for Linux using the base and length
1114  *              values retrieved from the Linux DTB via the
1115  *              "linux-dtb-alias" properties within the GRL.
1116  */
1117 static int32_t allocatorReserveLinuxResource(Rm_Handle rmHandle, Rm_LinuxAlias *linuxAlias, 
1118                                              Rm_LinuxValueRange *linuxValues, Rm_AllocatorOpInfo *opInfo)
1120     int32_t   retVal = RM_OK;
1121     int       baseFound = RM_FALSE;
1122     int       lengthFound = RM_FALSE;
1123     uint32_t  valueIndex = 0;
1125     while ((linuxValues) && (!baseFound || !lengthFound)) {
1126         if (linuxAlias->baseOffset == valueIndex) {
1127             opInfo->resourceInfo->base = linuxValues->value;
1128             baseFound = RM_TRUE;
1130             if (linuxAlias->lengthOffset == RM_DTB_UTIL_LINUX_ALIAS_OFFSET_NOT_SET) {
1131                 opInfo->resourceInfo->length = 1;
1132                 lengthFound = RM_TRUE;
1133             }
1134         }
1135         else if (linuxAlias->lengthOffset == valueIndex) {
1136             opInfo->resourceInfo->length = linuxValues->value;
1137             lengthFound = RM_TRUE;
1138         }
1140         linuxValues = (Rm_LinuxValueRange *)linuxValues->nextValue;
1141         valueIndex++;
1142     }
1144     if (!baseFound || !lengthFound) {
1145         retVal = RM_ERROR_DATA_NOT_FOUND_AT_LINUX_ALIAS;
1146     }
1147     else {
1148         /* Allocate resource to Linux */
1149         retVal = rmAllocatorOperation(rmHandle, opInfo);
1150         if (retVal == RM_SERVICE_APPROVED) {
1151             retVal = RM_OK;
1152         }
1153     }
1154     return (retVal);
1157 /* FUNCTION PURPOSE: Finds and reserves Linux resources
1158  ***********************************************************************
1159  * DESCRIPTION: Parses the Linux DTB for resources consumed by the
1160  *              Linux kernel.  If the resource is found via the
1161  *              "linux-dtb-alias" property defined in the GRL it is 
1162  *              reserved.
1163  */
1164 static int32_t allocatorFindLinuxResource(Rm_Handle rmHandle, const char *resourceName, void *linuxDtb, 
1165                                           Rm_LinuxAlias *linuxAlias)
1167     Rm_Inst            *rmInst = (Rm_Inst *)rmHandle;
1168     Rm_AllocatorOpInfo  opInfo;
1169     Rm_ResourceInfo     resourceInfo;
1170     uint32_t            pathOffset;
1171     uint32_t            pathSize;
1172     char               *spacePtr;
1173     int32_t             propOffset;
1174     int32_t             nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;
1175     int32_t             prevDepth = RM_DTB_UTIL_STARTING_DEPTH;
1176     int32_t             depth = RM_DTB_UTIL_STARTING_DEPTH;
1177     int32_t             propertyLen;
1178     const char         *propertyName;
1179     const void         *propertyData; 
1180     Rm_LinuxValueRange *linuxValueRange;
1181     int32_t             retVal = RM_OK; 
1183     memset((void *)&opInfo, 0, sizeof(opInfo));
1184     memset((void *)&resourceInfo, 0, sizeof(resourceInfo));
1186     strncpy(resourceInfo.name, resourceName, RM_NAME_MAX_CHARS);
1187     opInfo.policy = rmInst->u.server.globalPolicy;
1188     opInfo.serviceSrcInstNode = rmPolicyGetLinuxInstNode(rmHandle);
1189     opInfo.operation = Rm_allocatorOp_ALLOCATE_INIT;
1190     opInfo.resourceInfo = &resourceInfo;    
1192     while(linuxAlias) {
1193         /* Reset parsing variables */
1194         pathOffset = 0;
1195         pathSize = strlen(linuxAlias->path) + 1;
1196         nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;
1197         prevDepth = RM_DTB_UTIL_STARTING_DEPTH;   
1198         resourceInfo.base = 0;
1199         resourceInfo.length = 0;
1201         spacePtr = strpbrk(linuxAlias->path, " ");
1202         if (spacePtr) {
1203             *spacePtr = '\0';
1204         }       
1205         
1206         while(pathOffset < pathSize) {
1207             /* Move through DTB nodes until next alias path node found */
1208             if (strcmp(linuxAlias->path + pathOffset, fdt_get_name(linuxDtb, nodeOffset, NULL))) {
1209                 nodeOffset = fdt_next_node(linuxDtb, nodeOffset, &depth);
1211                 if ((depth < prevDepth) || (nodeOffset == -FDT_ERR_NOTFOUND)) {
1212                     /* Returning from subnode that matched part of alias path without finding
1213                      * resource values */
1214                     retVal = RM_ERROR_DATA_NOT_FOUND_AT_LINUX_ALIAS;
1215                     break;
1216                 }
1217             }
1218             else {
1219                 /* Found next alias path node.  Move to next node name in path string. */
1220                 pathOffset += (strlen(linuxAlias->path + pathOffset) + 1);
1221                 spacePtr = strpbrk(linuxAlias->path + pathOffset, " ");
1222                 if (spacePtr) {
1223                     *spacePtr = '\0';
1224                 }       
1225                 
1226                 prevDepth = fdt_node_depth(linuxDtb, nodeOffset);
1227                 propOffset = fdt_first_property_offset(linuxDtb, nodeOffset);
1228                 while ((propOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) &&
1229                        (pathOffset < pathSize)) {
1230                     propertyData = fdt_getprop_by_offset(linuxDtb, propOffset, 
1231                                                          &propertyName, &propertyLen);
1233                     if (strcmp(linuxAlias->path + pathOffset, propertyName) == 0) {
1234                         /* Found resource at end of alias path */
1235                         pathOffset += (strlen(linuxAlias->path + pathOffset) + 1);
1236                         linuxValueRange = rmDtbUtilLinuxExtractValues(propertyData, propertyLen);
1237                         retVal = allocatorReserveLinuxResource(rmHandle, linuxAlias, 
1238                                                                linuxValueRange, &opInfo);
1239                         rmDtbUtilLinuxFreeValues(linuxValueRange);
1240                     }
1241                     propOffset = fdt_next_property_offset(linuxDtb, propOffset);
1242                 } 
1244                 if (propOffset < -FDT_ERR_NOTFOUND) {
1245                     retVal = propOffset;
1246                     break;
1247                 }
1248             }
1249         }
1251         if (retVal < RM_OK) {
1252             break;
1253         }
1254         linuxAlias = linuxAlias->nextLinuxAlias;
1255     }
1256     return (retVal);
1259 /* FUNCTION PURPOSE: Creates and initializes a resource allocator
1260  ***********************************************************************
1261  * DESCRIPTION: Creates a resource allocator for the provided
1262  *              resource name and resource properties retrieved
1263  *              from the GRL.  Resources will be reserved for 
1264  *              the Linux kernel if the Linux DTB is provided
1265  *              and there are "linux-dtb-alias" properties
1266  *              specified in the GRL.
1267  */
1268 static int32_t allocatorExtractGrlResProps(Rm_Handle rmHandle, const char *resourceName, 
1269                                            Rm_ResourceProperties *resourceProperties, void *linuxDtb)
1271     Rm_Inst             *rmInst = (Rm_Inst *)rmHandle;
1272     Rm_ResourceRange    *range = NULL;
1273     Rm_ResourceRange    *rangeBasePtr = NULL;
1274     Rm_NsAssignment     *nsAssignments = NULL;
1275     Rm_NsAssignment     *nsAssignmentBasePtr = NULL;
1276     Rm_LinuxAlias       *linuxAlias = NULL;
1277     Rm_NameServerObjCfg  nameServerObjCfg;      
1278     int32_t              retVal = RM_OK;
1280     if (resourceProperties->rangeData && (resourceProperties->rangeLen > 0)) {
1281         range = rangeBasePtr = rmDtbUtilResExtractRange(resourceProperties->rangeData, 
1282                                                         resourceProperties->rangeLen);
1283         
1284         if ((retVal = rmAllocatorCreate(rmHandle, resourceName, range)) >= RM_OK) {
1285             if (resourceProperties->linuxAliasData && resourceProperties->linuxAliasLen) {
1286                 if (linuxDtb) {
1287                     linuxAlias = rmDtbUtilResExtractLinuxAlias(resourceProperties->linuxAliasData,
1288                                                                resourceProperties->linuxAliasLen, &retVal);
1289                     if (linuxAlias) {
1290                         retVal = allocatorFindLinuxResource(rmHandle, resourceName, linuxDtb, linuxAlias);            
1291                     }
1292                 }
1293             }
1294         }
1295     }
1296     
1297     if (retVal >= RM_OK) {
1298         if (resourceProperties->nsAssignData && resourceProperties->nsAssignLen) {
1299             nsAssignments = rmDtbUtilResExtractNsAssignment(resourceProperties->nsAssignData, 
1300                                                             resourceProperties->nsAssignLen, &retVal);
1301             if (nsAssignments) {
1302                 nsAssignmentBasePtr = nsAssignments;
1303                 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1304                     rmNameServerTreeInv(rmInst->u.server.nameServer);
1305                 }                  
1306                 while (nsAssignments) {
1307                     memset((void *)&nameServerObjCfg, 0, sizeof(nameServerObjCfg));
1308                     nameServerObjCfg.nameServerTree = rmInst->u.server.nameServer;
1309                     nameServerObjCfg.nodeCfg.objName = nsAssignments->nsName;
1310                     nameServerObjCfg.nodeCfg.resourceName = (char *)resourceName;
1311                     nameServerObjCfg.nodeCfg.resourceBase= nsAssignments->resourceBase;
1312                     nameServerObjCfg.nodeCfg.resourceLength = nsAssignments->resourceLength;                
1313                     rmNameServerAddObject(&nameServerObjCfg);
1314                     nsAssignments = nsAssignments->nextNsAssignment;
1315                 }
1316                 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1317                     rmNameServerTreeWb(rmInst->u.server.nameServer);
1318                 }                
1319                 rmDtbUtilResFreeNsAssignmentList(nsAssignmentBasePtr);
1320             }
1321         }
1322     }
1323     else {
1324         rmAllocatorDelete(rmHandle, resourceName);
1325     }
1327     rmDtbUtilResFreeRange(rangeBasePtr);
1328     if (linuxAlias) {
1329         rmDtbUtilResFreeLinuxAlias(linuxAlias);
1330     }
1331     return(retVal);
1334 /**********************************************************************
1335  ********************** Internal Functions ****************************
1336  **********************************************************************/
1338 /* FUNCTION PURPOSE: Creates a new resource tree
1339  ***********************************************************************
1340  * DESCRIPTION: Creates and populates a new resource tree allocator
1341  *              using the provided resource name and value range.  The
1342  *              name and value originate from the GRL.
1343  */
1344 int32_t rmAllocatorCreate(Rm_Handle rmHandle, const char *resourceName, Rm_ResourceRange *range)
1346     Rm_Inst         *rmInst = (Rm_Inst *)rmHandle;
1347     Rm_Allocator    *allocator = NULL;
1348     Rm_ResourceTree *treeRoot = NULL;
1349     Rm_ResourceNode *treeNode = NULL;
1351     allocator = allocatorAdd(rmHandle, resourceName);
1352     treeRoot = Rm_osalMalloc(sizeof(*treeRoot));
1353     RB_INIT(treeRoot);
1355     while (range != NULL) {
1356         treeNode = rmResourceNodeNew(range->base, range->length);
1357         RB_INSERT(_Rm_AllocatorResourceTree, treeRoot, treeNode);
1358         range = range->nextRange;
1359     }
1360     if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1361         rmResourceTreeWb(treeRoot);
1362     }
1363     
1364     allocator->allocatorRootEntry = treeRoot;
1365     RM_SS_OBJ_WB(allocator, Rm_Allocator);
1366     return(RM_OK);
1369 /* FUNCTION PURPOSE: Returns a pointer to the allocator list
1370  ***********************************************************************
1371  * DESCRIPTION: Returns a pointer to the instance's allocator list
1372  *              based on the instance type
1373  */
1374 Rm_Allocator *rmAllocatorGetAllocatorList(Rm_Handle rmHandle)
1376     Rm_Inst      *rmInst = (Rm_Inst *)rmHandle;
1377     Rm_Allocator *list = NULL;
1379     if ((rmInst->instType == Rm_instType_SERVER) ||
1380         (rmInst->instType == Rm_instType_SHARED_SERVER)) {
1381         list = rmInst->u.server.allocators;
1382     }
1383     else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1384         list = rmInst->u.cd.allocators;
1385     }
1386     return(list);
1389 /* FUNCTION PURPOSE: Finds an allocator
1390  ***********************************************************************
1391  * DESCRIPTION: Returns a pointer to an allocator that matches the 
1392  *              provided resource name.
1393  */
1394 Rm_Allocator *rmAllocatorFind(Rm_Handle rmHandle, const char *resourceName)
1396     Rm_Inst      *rmInst = (Rm_Inst *)rmHandle;
1397     Rm_Allocator *allocatorList = rmAllocatorGetAllocatorList(rmHandle);
1398     
1399     while (allocatorList) {
1400         RM_SS_OBJ_INV(allocatorList, Rm_Allocator);
1401         if (strncmp(allocatorList->resourceName, resourceName, RM_NAME_MAX_CHARS) == 0) {
1402             break;             
1403         }
1404         allocatorList = allocatorList->nextAllocator;
1405     }
1407     return (allocatorList);
1410 /* FUNCTION PURPOSE: Checks if a resource node is localized
1411  ***********************************************************************
1412  * DESCRIPTION: Checks if a resource node is localized.  A localized
1413  *              node is one that is free and has no neighboring nodes
1414  *              or neighboring nodes that do not have resource values
1415  *              contiguous with the node being checked.  The function
1416  *              will return RM_TRUE is the node is localized.  
1417  *              Otherwise, the function returns RM_FALSE
1418  */
1419 int rmAllocatorGetNodeLocalization(Rm_Handle rmHandle, char *resourceName, 
1420                                    int32_t *resBase, uint32_t *resLen)
1422     Rm_Inst         *rmInst = (Rm_Inst *)rmHandle;
1423     void *           policy = rmPolicyGetPolicy((Rm_Handle)rmInst);
1424     int32_t          resOffsetInPolicy = rmPolicyGetResourceOffset(policy, resourceName);
1425     uint32_t         allocSize = rmPolicyGetResourceCdAllocSize(policy, resOffsetInPolicy);    
1426     Rm_Allocator    *allocator = rmAllocatorFind(rmHandle, resourceName);
1427     Rm_ResourceNode  findNode;
1428     Rm_ResourceNode *matchingNode = NULL;
1429     Rm_ResourceNode *neighborNode = NULL;   
1430     int              nodeIsLocalized;
1432     memset((void *)&findNode, 0, sizeof(findNode));
1433     findNode.base = *resBase;
1434     findNode.length = *resLen;
1435     matchingNode = RB_FIND(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, &findNode);
1437     if (matchingNode) {
1438         /* Node can be freed back to Server from CD if:
1439          * - allocationCount == 0
1440          * - node's resource range is multiple of policy allocation size
1441          * - node's resource range boundaries are not contiguous with surrounding nodes */
1442         if (matchingNode->allocationCount) {
1443             nodeIsLocalized = RM_FALSE;
1444             goto exitLocalization;
1445         }
1446             
1447         if (matchingNode->length % allocSize) {
1448             nodeIsLocalized = RM_FALSE;
1449             goto exitLocalization;        
1450         }
1452         /* Check left neighbor */
1453         neighborNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
1454         if (neighborNode && allocatorResNodeBoundaryCompare(neighborNode, matchingNode)) {
1455             nodeIsLocalized = RM_FALSE;
1456             goto exitLocalization; 
1457         }
1459         /* Check right neighbor */
1460         neighborNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
1461         if (neighborNode && allocatorResNodeBoundaryCompare(neighborNode, matchingNode)) {
1462             nodeIsLocalized = RM_FALSE;
1463             goto exitLocalization; 
1464         }
1466         /* All localization checks passed.  Return the base and length of localized node. */
1467         nodeIsLocalized = RM_TRUE;
1468         *resBase = matchingNode->base;
1469         *resLen = matchingNode->length;
1470     }
1471     else {
1472         nodeIsLocalized = RM_FALSE;
1473     }
1475 exitLocalization:
1476     return (nodeIsLocalized);
1479 /* FUNCTION PURPOSE: Issues an allocator operation
1480  ***********************************************************************
1481  * DESCRIPTION: Issues an allocator preallocate, allocate, or free
1482  *              for an RM resource.
1483  */
1484 int32_t rmAllocatorOperation(Rm_Handle rmHandle, Rm_AllocatorOpInfo *opInfo)
1486     Rm_Inst      *rmInst = (Rm_Inst *)rmHandle;
1487     Rm_Allocator *allocator = NULL;
1488     int32_t       resourceOffsetInPolicy;
1489     int32_t       retVal;
1490     
1491     resourceOffsetInPolicy = rmPolicyGetResourceOffset(opInfo->policy, opInfo->resourceInfo->name);
1492     allocator = rmAllocatorFind(rmHandle, opInfo->resourceInfo->name);
1493     
1494     if ((resourceOffsetInPolicy > 0) && allocator) {
1495         if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1496             rmResourceTreeInv(allocator->allocatorRootEntry);
1497         }
1499         if (opInfo->operation == Rm_allocatorOp_GET_STATUS) {
1500             retVal = allocatorStatus(allocator, opInfo);
1501         }
1502         else if ((opInfo->operation == Rm_allocatorOp_PRE_ALLOCATE_INIT) ||
1503                  (opInfo->operation == Rm_allocatorOp_PRE_ALLOCATE_USE)) {
1504             retVal = allocatorPreAllocate(rmHandle, allocator, resourceOffsetInPolicy, opInfo);
1505         }               
1506         else if ((opInfo->operation == Rm_allocatorOp_ALLOCATE_INIT) ||
1507                  (opInfo->operation == Rm_allocatorOp_ALLOCATE_USE)) {
1508             retVal = allocatorAllocate(rmHandle, allocator, resourceOffsetInPolicy, opInfo);
1509         }
1510         else if (opInfo->operation == Rm_allocatorOp_FREE) {
1511             retVal = allocatorFree(rmHandle, allocator, opInfo);
1512         } 
1514         if ((rmInst->instType == Rm_instType_SHARED_SERVER) &&
1515             (opInfo->operation != Rm_allocatorOp_GET_STATUS) &&
1516             (retVal == RM_SERVICE_APPROVED)) {
1517             rmResourceTreeWb(allocator->allocatorRootEntry);
1518         }        
1519     }
1520     else {
1521         /* Resource could not be found in policy and/or allocator */
1522         retVal = RM_SERVICE_DENIED_RES_DOES_NOT_EXIST;
1523     }
1524     return(retVal);
1527 /* FUNCTION PURPOSE: Initializes server allocators
1528  ***********************************************************************
1529  * DESCRIPTION: Creates and initializes a server instance's
1530  *              resource allocators using the GRL and, if
1531  *              provided, Linux DTB.
1532  */
1533 int32_t rmAllocatorInitializeResources(Rm_Handle rmHandle, void *globalResourceDtb, void *linuxDtb)
1535     int32_t                nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;
1536     int32_t                nodeDepth = RM_DTB_UTIL_STARTING_DEPTH;
1537     Rm_ResourceProperties  resProperties;    
1538     int32_t                propOffset;
1539     int32_t                propertyLen;
1540     const char            *propertyName;
1541     const void            *propertyData;
1542     Rm_ResourcePropType    propertyType;  
1543     int32_t                retVal = RM_OK;
1545     /* Parse the Global Resource List, creating an allocator for each specified resource node */
1546     while ((nodeOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) && (nodeDepth >= RM_DTB_UTIL_STARTING_DEPTH)) {
1547         memset((void *)&resProperties, 0, sizeof(resProperties));
1548         /* Get properties of resource node */
1549         propOffset = fdt_first_property_offset(globalResourceDtb, nodeOffset);
1550         while (propOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) {
1551             propertyData = fdt_getprop_by_offset(globalResourceDtb, propOffset, &propertyName, &propertyLen);
1552             propertyType = rmDtbUtilResGetPropertyType(propertyName);
1553             if (propertyType == Rm_resourcePropType_RESOURCE_RANGE) {
1554                 resProperties.rangeData = propertyData;
1555                 resProperties.rangeLen = propertyLen;
1556             }
1557             else if (propertyType == Rm_resourcePropType_NSASSIGNMENT) {
1558                 resProperties.nsAssignData = propertyData;
1559                 resProperties.nsAssignLen = propertyLen;
1560             }
1561             else if (propertyType == Rm_resourcePropType_RESOURCE_LINUX_ALIAS) {
1562                 resProperties.linuxAliasData = propertyData;
1563                 resProperties.linuxAliasLen = propertyLen;
1564             }        
1565             else {
1566                 retVal = RM_ERROR_GRL_UNKNOWN_RESOURCE_PROPERTY;
1567                 goto exitAllocInit;
1568             }
1570             propOffset = fdt_next_property_offset(globalResourceDtb, propOffset);
1571             if (propOffset == -FDT_ERR_NOTFOUND) {
1572                 /* No more resource properties but at least one found.  Extract the property values */
1573                 retVal = allocatorExtractGrlResProps(rmHandle, fdt_get_name(globalResourceDtb, nodeOffset, NULL), 
1574                                                      &resProperties, linuxDtb);
1575                 if (retVal < RM_OK) {
1576                     goto exitAllocInit;
1577                 }
1578             }
1579             else if (propOffset < -FDT_ERR_NOTFOUND) {
1580                 /* Error returned by LIBFDT */
1581                 retVal = propOffset;
1582                 goto exitAllocInit;
1583             }
1584         }
1585         if (propOffset < -FDT_ERR_NOTFOUND) {
1586             /* Error returned by LIBFDT */
1587             retVal = propOffset;
1588             goto exitAllocInit;
1589         }
1591         nodeOffset = fdt_next_node(globalResourceDtb, nodeOffset, &nodeDepth);
1592         if (nodeOffset < -FDT_ERR_NOTFOUND) {
1593             /* Error returned by LIBFDT */
1594             retVal = nodeOffset;
1595             goto exitAllocInit;
1596         }
1597     }
1598 exitAllocInit:    
1599     return(retVal);
1602 /* FUNCTION PURPOSE: Deletes a resource allocator resource node
1603  ***********************************************************************
1604  * DESCRIPTION: Deletes a resource allocator's node based on the given
1605  *              resource name, base and length.
1606  */
1607 void rmAllocatorDeleteNode(Rm_Handle rmHandle, const char *resName, int32_t resBase, uint32_t resLen)
1609     Rm_Allocator    *allocator = rmAllocatorFind(rmHandle, resName);
1610     Rm_ResourceNode  findNode;
1611     Rm_ResourceNode *matchingNode;
1613     memset((void *)&findNode, 0, sizeof(findNode));
1614     findNode.base = resBase;
1615     findNode.length = resLen;
1616     matchingNode = RB_FIND(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, &findNode);
1617     
1618     if (matchingNode) {
1619         RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
1620         rmResourceNodeFree(matchingNode);
1621     }
1624 /* FUNCTION PURPOSE: Deletes a resource allocator
1625  ***********************************************************************
1626  * DESCRIPTION: Deletes a resource allocator based on the given
1627  *              resource name.  The resource allocator will be
1628  *              removed from the RM instance allocator list.
1629  */
1630 int32_t rmAllocatorDelete(Rm_Handle rmHandle, const char *resourceName)
1632     Rm_Inst         *rmInst = (Rm_Inst *)rmHandle;    
1633     Rm_Allocator    *allocator = rmAllocatorGetAllocatorList(rmHandle);
1634     Rm_Allocator    *prevAllocator = NULL;
1635     Rm_ResourceTree *treeRoot;
1636     Rm_ResourceNode *node = NULL;
1637     Rm_ResourceNode *nextNode = NULL;
1638     int32_t          retVal = RM_OK;
1640     while (allocator) {
1641         if (strncmp(allocator->resourceName, resourceName, RM_NAME_MAX_CHARS) == 0) {
1642             break;             
1643         }
1644         prevAllocator = allocator;
1645         allocator = allocator->nextAllocator;
1646     }
1648     if (allocator) {
1649         if (prevAllocator == NULL) {
1650             if ((rmInst->instType == Rm_instType_SERVER) ||
1651                 (rmInst->instType == Rm_instType_SHARED_SERVER)) {
1652                 rmInst->u.server.allocators = allocator->nextAllocator;
1653             }
1654             else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1655                 rmInst->u.cd.allocators = allocator->nextAllocator;
1656             }              
1657         }
1658         else {
1659             prevAllocator->nextAllocator = allocator->nextAllocator;
1660             RM_SS_OBJ_WB(prevAllocator, Rm_Allocator);
1661         }
1662             
1663         /* Destroy tree and return error */
1664         treeRoot = allocator->allocatorRootEntry;
1665         for (node = RB_MIN(_Rm_AllocatorResourceTree, treeRoot); node != NULL; node = nextNode) {
1666                 nextNode = RB_NEXT(_Rm_AllocatorResourceTree, treeRoot, node);
1667                 RB_REMOVE(_Rm_AllocatorResourceTree, treeRoot, nextNode);
1668             rmResourceNodeFree(node);
1669         }
1670         Rm_osalFree((void *)treeRoot, sizeof(*treeRoot));        
1671         Rm_osalFree((void *)allocator, sizeof(*allocator));
1672     }
1673     else {
1674         retVal = RM_ERROR_RES_ALLOCATOR_DOES_NOT_EXIST;
1675     }
1676     return (retVal);
1679 /* FUNCTION PURPOSE: Deletes server allocators
1680  ***********************************************************************
1681  * DESCRIPTION: Removes all resource nodes for each
1682  *              resource allocator and then deletes the allocator
1683  *              itself.  Used to free all memory consumed
1684  *              by the allocators.
1685  */
1686 void rmAllocatorDeleteResources(Rm_Handle rmHandle)
1688     Rm_Inst         *rmInst = (Rm_Inst *)rmHandle;
1689     Rm_Allocator    *allocatorList = rmAllocatorGetAllocatorList(rmHandle);
1690     Rm_Allocator    *nextAllocator;
1691     Rm_ResourceTree *resTree;
1692     Rm_ResourceNode *resNode;
1693     Rm_ResourceNode *nextResNode;
1695     while (allocatorList) {
1696         RM_SS_OBJ_INV(allocatorList, Rm_Allocator);
1697         nextAllocator = allocatorList->nextAllocator;
1698         resTree = allocatorList->allocatorRootEntry;
1700         if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1701             rmResourceTreeInv(resTree);
1702         }
1703         /* Delete each resource node in the allocator */
1704         for (resNode = RB_MIN(_Rm_AllocatorResourceTree, resTree); resNode != NULL; resNode = nextResNode) {
1705             nextResNode = RB_NEXT(_Rm_AllocatorResourceTree, resTree, resNode);
1706             RB_REMOVE(_Rm_AllocatorResourceTree, resTree, resNode);
1707             if (resNode->allocationCount) {
1708                 /* Delete all the owners in the resource's owner list */
1709                 allocatorResNodeOwnerClear(rmHandle, resNode);
1710             }
1711             rmResourceNodeFree(resNode);
1712         }        
1714         Rm_osalFree((void *)resTree, sizeof(*resTree));
1715         Rm_osalFree((void *)allocatorList, sizeof(*allocatorList));
1716         allocatorList = nextAllocator;
1717     }