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