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