Added policy tree elements
[keystone-rtos/rm-lld.git] / src / rm.c
1 /**
2  *   @file  rm.c
3  *
4  *   @brief   
5  *      This is the Resource Manager source.
6  *
7  *  \par
8  *  ============================================================================
9  *  @n   (C) Copyright 2012-2015, 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 /* Standard includes */
43 #include <stdint.h>
45 /* RM external includes */
46 #include <ti/drv/rm/rm.h>
47 #include <ti/drv/rm/rmver.h>
48 #include <ti/drv/rm/rm_services.h>
49 #include <ti/drv/rm/rm_transport.h>
51 /* RM internal includes */
52 #include <ti/drv/rm/include/rm_internal.h>
53 #include <ti/drv/rm/include/rm_loc.h>
54 #include <ti/drv/rm/include/rm_allocatorloc.h>
55 #include <ti/drv/rm/include/rm_transportloc.h>
56 #include <ti/drv/rm/include/rm_nameserverloc.h>
57 #include <ti/drv/rm/include/rm_servicesloc.h>
59 /* RM LIBFDT includes */
60 #include <ti/drv/rm/util/libfdt/libfdt.h>
62 /* RM OSAL layer */
63 #include <rm_osal.h>
65 /**********************************************************************
66  ************************** Globals ***********************************
67  **********************************************************************/
69 /* Global Variable which describes the RM Version Information */
70 const char  rmVersionStr[] = RM_VERSION_STR ":" __DATE__  ":" __TIME__;
72 /**********************************************************************
73  ************************ Local Functions *****************************
74  **********************************************************************/
76 /* FUNCTION PURPOSE: Initializes a RM inst's transaction sequence number
77  ***********************************************************************
78  * DESCRIPTION: The RM instance transaction sequence number can never
79  *              have a value of 0 to avoid conflicts with transactions
80  *              that have a remoteOriginatingId of 0 (transaction ID
81  *              will be used as the remoteOriginatingId for
82  *              transactions that are responses to requests).
83  */
84 static uint32_t transactionInitSequenceNum(void)
85 {
86     return (1);
87 }
89 /* FUNCTION PURPOSE: Provides a sequence number for new transactions
90  ***********************************************************************
91  * DESCRIPTION: Returns a sequence number for a new transaction
92  *              specific to a RM instance.  Handles rollover of
93  *              sequence number.
94  */
95 static uint32_t transactionGetSequenceNum(Rm_Inst *rmInst)
96 {
97     rmInst->transactionSeqNum++;
98     if (!rmInst->transactionSeqNum) {
99         rmInst->transactionSeqNum++;
100     }    
101     return (rmInst->transactionSeqNum);
104 /* FUNCTION PURPOSE: Creates a resource request packet
105  ***********************************************************************
106  * DESCRIPTION: Returns a RM packet handle that points to a RM
107  *              resource request packet that has been prepared
108  *              for sending to another RM instance.  The packet
109  *              is allocated via the rmAllocPkt API using the
110  *              appTransport handle provided by the application
111  */
112 void createResourceReqPkt(Rm_Packet *rmPkt, char *localInstName, Rm_Transaction *transaction)
114     Rm_ResourceRequestPkt *resourceReqPkt = NULL;
115        
116     rmPkt->pktType = Rm_pktType_RESOURCE_REQUEST;
117     resourceReqPkt = (Rm_ResourceRequestPkt *) rmPkt->data;
118     resourceReqPkt->requestId = transaction->localId;
119     if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
120         resourceReqPkt->resourceReqType = Rm_resReqPktType_ALLOCATE_INIT;
121     }
122     else if (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) {
123         resourceReqPkt->resourceReqType = Rm_resReqPktType_ALLOCATE_USE;
124     }   
125     else if (transaction->type == Rm_service_RESOURCE_STATUS) {
126         resourceReqPkt->resourceReqType = Rm_resReqPktType_GET_STATUS;
127     }
128     else if (transaction->type == Rm_service_RESOURCE_FREE) {
129         resourceReqPkt->resourceReqType = Rm_resReqPktType_FREE;
130     }
131     else if (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) {
132         resourceReqPkt->resourceReqType = Rm_resReqPktType_GET_NAMED;
133     }
134     rm_strncpy(resourceReqPkt->pktSrcInstName, localInstName, RM_NAME_MAX_CHARS);
135     rm_strncpy(resourceReqPkt->serviceSrcInstName, transaction->serviceSrcInstName, RM_NAME_MAX_CHARS);
136     memcpy ((void *)&(resourceReqPkt->resourceInfo), (void *)&(transaction->resourceInfo),
137             sizeof(Rm_ResourceInfo));
140 /* FUNCTION PURPOSE: Creates a resource response packet
141  ***********************************************************************
142  * DESCRIPTION: Returns a RM packet handle that points to a RM
143  *              resource response packet that has been prepared
144  *              for sending to another RM instance.  The packet
145  *              is allocated via the rmAllocPkt API using the
146  *              appTransport handle provided by the application
147  */
148 void createResourceResponsePkt(Rm_Packet *rmPkt, Rm_Transaction *transaction)
150     Rm_ResourceResponsePkt *resourceRespPkt = NULL;
151      
152     rmPkt->pktType = Rm_pktType_RESOURCE_RESPONSE;                 
153     resourceRespPkt = (Rm_ResourceResponsePkt *)rmPkt->data;
154     resourceRespPkt->responseId = transaction->remoteOriginatingId;
155     resourceRespPkt->requestState = transaction->state;
156     memcpy ((void *)&(resourceRespPkt->resourceInfo), (void *)&(transaction->resourceInfo),
157             sizeof(Rm_ResourceInfo));
160 /* FUNCTION PURPOSE: Creates a NameServer request packet
161  ***********************************************************************
162  * DESCRIPTION: Returns a RM packet handle that points to a RM
163  *              NameServer request packet that has been prepared
164  *              for sending to another RM instance.  The packet
165  *              is allocated via the rmAllocPkt API using the
166  *              appTransport handle provided by the application
167  */
168 void createNsRequestPkt(Rm_Packet *rmPkt, char *localInstName, Rm_Transaction *transaction)
169
170     Rm_NsRequestPkt *nsReqPkt = NULL;
172     rmPkt->pktType = Rm_pktType_NAMESERVER_REQUEST;                   
173     nsReqPkt = (Rm_NsRequestPkt *)rmPkt->data;
174     nsReqPkt->requestId = transaction->localId;
175     if (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) {
176         nsReqPkt->nsRequestType = Rm_nsReqPktType_MAP_RESOURCE;
177     }
178     else if (transaction->type == Rm_service_RESOURCE_UNMAP_NAME) {
179         nsReqPkt->nsRequestType = Rm_nsReqPktType_UNMAP_RESOURCE;
180     }
181     rm_strncpy(nsReqPkt->pktSrcInstName, localInstName, RM_NAME_MAX_CHARS);
182     rm_strncpy(nsReqPkt->serviceSrcInstName, transaction->serviceSrcInstName, RM_NAME_MAX_CHARS);
183     memcpy ((void *)&(nsReqPkt->resourceInfo), (void *)&(transaction->resourceInfo),
184             sizeof(Rm_ResourceInfo));
187 /* FUNCTION PURPOSE: Creates a NameServer response packet
188  ***********************************************************************
189  * DESCRIPTION: Returns a RM packet handle that points to a RM
190  *              NameServer response packet that has been prepared
191  *              for sending to another RM instance.  The packet
192  *              is allocated via the rmAllocPkt API using the
193  *              appTransport handle provided by the application
194  */
195 void createNsResponsePkt(Rm_Packet *rmPkt, Rm_Transaction *transaction)
197     Rm_NsResponsePkt *nsRespPkt = NULL;
199     rmPkt->pktType = Rm_pktType_NAMESERVER_RESPONSE;                
200     nsRespPkt = (Rm_NsResponsePkt *)rmPkt->data;
201     nsRespPkt->responseId = transaction->remoteOriginatingId;
202     nsRespPkt->requestState = transaction->state;
205 /* FUNCTION PURPOSE: Issues a service response to application
206  ***********************************************************************
207  * DESCRIPTION: Provides a service response back to the application
208  *              using the service callback function provided to
209  *              the RM instance at the time of the service request.
210  */
211 static void serviceResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)
213     Rm_ServiceRespInfo serviceResponse;
215     serviceResponse.rmHandle = (Rm_Handle)rmInst;
216     /* The responseTransaction will contain the resultant state details of
217      * the requestTransaction's service request */
218     serviceResponse.serviceState = transaction->state;
219     /* Pass back the ID that was provided to the component when it requested
220      * the service */
221     serviceResponse.serviceId = transaction->localId;
222     /* Owner and instance allocation count will only be set within RM under certain circumstances. */
223     serviceResponse.resourceNumOwners = transaction->resourceInfo.ownerCount;
224     serviceResponse.instAllocCount = transaction->resourceInfo.instAllocCount;
226     /* Service was approved and service was an allocate request.  The resource
227      * data is passed back to the component */
228     if ((serviceResponse.serviceState == RM_SERVICE_APPROVED) &&
229         ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||
230          (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) ||
231          (transaction->type == Rm_service_RESOURCE_FREE) ||
232          (transaction->type == Rm_service_RESOURCE_STATUS) ||
233          (transaction->type == Rm_service_RESOURCE_GET_BY_NAME)))
234     {
235         rm_strncpy(serviceResponse.resourceName, transaction->resourceInfo.name, RM_NAME_MAX_CHARS);
236         serviceResponse.resourceBase = transaction->resourceInfo.base;
237         serviceResponse.resourceLength = transaction->resourceInfo.length;
238     }
240     if (transaction->u.callback.serviceCallback) {
241         /* Issue the callback to the requesting component with the response information */
242         transaction->u.callback.serviceCallback(&serviceResponse);
243         /* Delete the transaction from the transaction queue */
244         rmTransactionQueueDelete(rmInst, transaction->localId);
245     }
246     else {
247         rmServiceInternalCallback((Rm_Handle)rmInst);
248     }
249     
250     return;
253 /* FUNCTION PURPOSE: Sends RM response packets
254  ***********************************************************************
255  * DESCRIPTION: Sends RM response packets to RM instance's that sent
256  *              RM request packets to the RM instance.  The response
257  *              is sent via the RM transport API which is plugged
258  *              with an application created transport path.
259  */
260 static void transactionResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)
262     Rm_Transport    *dstTransport = transaction->u.respTrans;
263     Rm_Packet       *rmPkt = NULL;
264     Rm_PacketHandle  pktHandle = NULL;
266     rmPkt = dstTransport->callouts.rmAllocPkt(dstTransport->appTransportHandle, 
267                                               sizeof(Rm_Packet), &pktHandle);
268     if (!rmPkt || !pktHandle) {
269         transaction->state = RM_ERROR_TRANSPORT_ALLOC_PKT_ERROR;
270         goto errorExit;
271     }
273     switch (transaction->type) {
274         case Rm_service_RESOURCE_ALLOCATE_INIT:
275         case Rm_service_RESOURCE_ALLOCATE_USE:
276         case Rm_service_RESOURCE_STATUS:
277         case Rm_service_RESOURCE_FREE:
278         case Rm_service_RESOURCE_GET_BY_NAME:
279             createResourceResponsePkt(rmPkt, transaction);
280             break;
281         case Rm_service_RESOURCE_MAP_TO_NAME:
282         case Rm_service_RESOURCE_UNMAP_NAME:
283             createNsResponsePkt(rmPkt, transaction);
284             break;
285         default:
286             transaction->state = RM_ERROR_INVALID_SERVICE_TYPE;
287             goto errorExit;
288     }
289     if (dstTransport->callouts.rmSendPkt(dstTransport->appTransportHandle, pktHandle) < RM_OK) {
290         transaction->state = RM_ERROR_TRANSPORT_SEND_ERROR;
291         goto errorExit;
292     }
293     
294     /* Response packet sent: Delete transaction from queue */
295     rmTransactionQueueDelete(rmInst, transaction->localId);
297 errorExit:
298     /* Do not delete transaction on transport error.  Transport error transactions should be visible
299      * from Rm_printInstanceStatus() */
300     return;
303 /* FUNCTION PURPOSE: Sends RM request packets
304  ***********************************************************************
305  * DESCRIPTION: Sends RM request packets to RM instance's that are
306  *              capable of forwarding or validating service requests.
307  *              The request is sent via the RM transport API which is
308  *              plugged with an application created transport path.
309  */
310 static void transactionForwarder (Rm_Inst *rmInst, Rm_Transaction *transaction)
312     Rm_Transport    *dstTransport = NULL;
313     Rm_Packet       *rmPkt = NULL;    
314     Rm_PacketHandle  pktHandle = NULL;
316     if (rmInst->instType == Rm_instType_CLIENT) {
317         dstTransport = rmTransportFindRemoteInstType(rmInst->transports, Rm_instType_CLIENT_DELEGATE);
319         if (!dstTransport) {
320             dstTransport = rmTransportFindRemoteInstType(rmInst->transports, Rm_instType_SERVER);
321         }
322     } 
323     else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
324         dstTransport = rmTransportFindRemoteInstType(rmInst->transports, Rm_instType_SERVER);
325     }
327     /* Just queue transaction if transport hasn't been registered.  Do not return error */
328     if (dstTransport) {            
329         rmPkt = dstTransport->callouts.rmAllocPkt(dstTransport->appTransportHandle, 
330                                                   sizeof(Rm_Packet), &pktHandle);
331         if (!rmPkt || !pktHandle) {
332             transaction->state = RM_ERROR_TRANSPORT_ALLOC_PKT_ERROR;
333             goto errorExit;
334         }
336         switch (transaction->type) {
337             case Rm_service_RESOURCE_ALLOCATE_INIT:
338             case Rm_service_RESOURCE_ALLOCATE_USE:
339             case Rm_service_RESOURCE_STATUS:
340             case Rm_service_RESOURCE_FREE:
341             case Rm_service_RESOURCE_GET_BY_NAME:
342                 createResourceReqPkt(rmPkt, rmInst->instName, transaction);
343                 break;
344             case Rm_service_RESOURCE_MAP_TO_NAME:
345             case Rm_service_RESOURCE_UNMAP_NAME:
346                 createNsRequestPkt(rmPkt, rmInst->instName, transaction);
347                 break;
348             default:
349                 transaction->state = RM_ERROR_INVALID_SERVICE_TYPE;
350                 goto errorExit;
351         }
352   
353         if (dstTransport->callouts.rmSendPkt(dstTransport->appTransportHandle, pktHandle) < RM_OK) {
354             transaction->state = RM_ERROR_TRANSPORT_SEND_ERROR;
355             goto errorExit;
356         }              
357         transaction->hasBeenForwarded = RM_TRUE;
358         /* Transaction not deleted.  Waiting for response from RM CD or Server */
359     }
360 errorExit: 
361     /* Do not delete transaction on transport error.  Transport error transactions should be visible
362      * from Rm_printInstanceStatus() */               
363     return;
366 /* FUNCTION PURPOSE: Handles static allocation requests
367  ***********************************************************************
368  * DESCRIPTION: Validates allocation requests received on CDs and
369  *              Clients prior to the instance's registering
370  *              with a Server.  The allocation request is validated
371  *              against a static policy.
372  */
373 static void staticAllocationHandler (Rm_Handle rmHandle, Rm_Transaction *transaction)
375     Rm_Inst           *rmInst = (Rm_Inst *)rmHandle;
376     void              *staticPolicy = rmPolicyGetPolicy(rmHandle);
377     Rm_PolicyCheckCfg  privCheckCfg;
378     int32_t            result;
379     
380     if (staticPolicy) {
381         if ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||
382             (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE)) {
383             /* Check request against static policy */
384             memset((void *)&privCheckCfg, 0, sizeof(Rm_PolicyCheckCfg));
385     
386             if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
387                 privCheckCfg.type = Rm_policyCheck_INIT;
388             }
389             else {
390                 privCheckCfg.type = Rm_policyCheck_USE;
391             }
392             privCheckCfg.policyDtb = staticPolicy;
393             privCheckCfg.validInstNode = rmPolicyGetValidInstNode(rmHandle, rmInst->instName);
394             privCheckCfg.resourceOffset = rmPolicyGetResourceOffset(staticPolicy,
395                                                                     transaction->resourceInfo.name);
396             privCheckCfg.resourceBase = transaction->resourceInfo.base;
397             privCheckCfg.resourceLength = transaction->resourceInfo.length;
398     
399             if (rmPolicyCheckPrivilege(&privCheckCfg, &result)) {
400                 transaction->state = RM_SERVICE_APPROVED_STATIC;
401             }
402             else if (result == RM_OK) {
403                 /* Privilege check returned false without error */
404                 transaction->state = RM_SERVICE_DENIED_BY_STATIC_POLICY;
405             }
406             else {
407                 /* Privilege check returned false with error */
408                 transaction->state = result;
409             }
410         }
411         else {
412             transaction->state = RM_SERVICE_DENIED_INVALID_STATIC_REQUEST;
413         }
414     }
415     else {
416         transaction->state = RM_ERROR_REQ_FAILED_NO_STATIC_POLICY;
417     } 
420 /* FUNCTION PURPOSE: Requests resources from Server for CD
421  ***********************************************************************
422  * DESCRIPTION: Function creates a service request to allocate resources
423  *              from the Server for local management by the CD.  The
424  *              transaction which causes this request is put in the
425  *              pending state in order to wait for the response from the 
426  *              Server
427  */
428 static int32_t cdRequestServerResources(Rm_Inst *rmInst, Rm_Transaction *transaction)
430     Rm_Transaction *newTrans = NULL;
431     void *          policy = rmPolicyGetPolicy((Rm_Handle)rmInst);
432     int32_t         resourceOffsetInPolicy;
433     uint32_t        allocSize = 0;
434     int32_t         retVal;
436     resourceOffsetInPolicy = rmPolicyGetResourceOffset(policy, transaction->resourceInfo.name);
437     if (resourceOffsetInPolicy > 0) {
438         if ((allocSize = rmPolicyGetResourceCdAllocSize(policy, resourceOffsetInPolicy))) {
439             if ((newTrans = rmTransactionQueueAdd(rmInst))) {
440                 newTrans->type = transaction->type;
441                 rm_strncpy(newTrans->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS);
442                 newTrans->state = RM_SERVICE_PROCESSING;       
443                 rm_strncpy(newTrans->resourceInfo.name, transaction->resourceInfo.name, RM_NAME_MAX_CHARS);
444                 newTrans->resourceInfo.base = RM_RESOURCE_BASE_UNSPECIFIED;
445                 /* Make sure request length will satisfy transaction length */
446                 newTrans->resourceInfo.length = allocSize;
447                 while (newTrans->resourceInfo.length < transaction->resourceInfo.length) {
448                     newTrans->resourceInfo.length += allocSize;
449                 }
450                 newTrans->resourceInfo.alignment = transaction->resourceInfo.alignment;
451                 newTrans->pendingTransactionId = transaction->localId;
452                 transactionForwarder(rmInst, newTrans);
454                 retVal = RM_SERVICE_PENDING_SERVER_RESPONSE;
455             }
456             else {
457                 retVal = RM_ERROR_TRANS_REQ_TO_SERVER_NOT_CREATED;
458             }
459         }
460         else {
461             /* Forward request to Server for completion if policy has 
462              * no allocation size for resource */
463             retVal = RM_SERVICE_PROCESSING;
464         }
465     }
466     else {
467         /* Resource could not be found in policy */
468         retVal = RM_SERVICE_DENIED_RES_DOES_NOT_EXIST;
469     }
470     return (retVal);
473 /* FUNCTION PURPOSE: Frees local resources to Server from CD
474  ***********************************************************************
475  * DESCRIPTION: Function creates a service request to free locally
476  *              managed resources that are now localized back to
477  *              the Server.
478  */
479 static int32_t cdFreeResourcesToServer(Rm_Inst *rmInst, Rm_Transaction *transaction)
481     int32_t         baseToFree = transaction->resourceInfo.base;
482     uint32_t        lenToFree = transaction->resourceInfo.length;
483     Rm_Transaction *newTrans = NULL; 
484     /* This function should only be called after a free was approved */
485     int32_t         retVal = RM_SERVICE_APPROVED;    
486     
487     /* Did free result in a localized free node that can be given back to Server?  If
488      * so create transaction to Server to free localized resource node */
489     if (rmAllocatorGetNodeLocalization((Rm_Handle)rmInst, transaction->resourceInfo.name,
490                                        &baseToFree, &lenToFree)) {
491         if ((newTrans = rmTransactionQueueAdd(rmInst))) {
492             newTrans->type = transaction->type;
493             rm_strncpy(newTrans->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS);
494             newTrans->state = RM_SERVICE_PROCESSING;
495             rm_strncpy(newTrans->resourceInfo.name, transaction->resourceInfo.name, RM_NAME_MAX_CHARS);
496             newTrans->resourceInfo.base = baseToFree;
497             newTrans->resourceInfo.length = lenToFree;
498             newTrans->pendingTransactionId = transaction->localId;
499             transactionForwarder(rmInst, newTrans);
501             retVal = RM_SERVICE_PENDING_SERVER_RESPONSE;
502         }
503         else {
504             /* Error: Need to re-allocate what was freed */
505             retVal = RM_ERROR_TRANS_REQ_TO_SERVER_NOT_CREATED;    
506         }
507     }    
508     return (retVal);
511 /* FUNCTION PURPOSE: Arbitrates allocation service requests
512  ***********************************************************************
513  * DESCRIPTION: Issues a set of allocator operations in order to
514  *              handle a received allocation request.  Allocation
515  *              requests are always forwarded to the Server on Client
516  *              CD instances.  If a request is made with a NameServer
517  *              name the resource base and length parameters are
518  *              retrieved from the NameServer prior to the allocation
519  *              attempt.
520  */
521 static void allocationHandler (Rm_Inst *rmInst, Rm_Transaction *transaction)
523     Rm_AllocatorOpInfo   opInfo;
524     Rm_NameServerObjCfg  nameServerObjCfg;
525     int32_t              retVal = transaction->state;
527     memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));
528     opInfo.policy = rmPolicyGetPolicy((Rm_Handle)rmInst);
529     opInfo.resourceInfo = &transaction->resourceInfo;
530     opInfo.serviceSrcInstNode = rmPolicyGetValidInstNode((Rm_Handle)rmInst, transaction->serviceSrcInstName);
531     if (opInfo.serviceSrcInstNode == NULL) {
532         retVal = RM_SERVICE_DENIED_INST_NAME_NOT_VALID;
533         goto errorExit;
534     }        
535                 
536     if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
537         if (transaction->resourceInfo.base != RM_RESOURCE_BASE_UNSPECIFIED) {
538             if (rmAllocatorFind((Rm_Handle)rmInst, transaction->resourceInfo.name)) {
539                 /* Attempt to allocate from local resources that were provided by Server */
540                 if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
541                     opInfo.operation = Rm_allocatorOp_ALLOCATE_INIT;
542                 }
543                 else if (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) {
544                     opInfo.operation = Rm_allocatorOp_ALLOCATE_USE;
545                 }
546                 else {
547                     retVal = RM_ERROR_INVALID_SERVICE_TYPE;
548                     goto errorExit;
549                 }
550                 retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
552                 if (retVal == RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST) {
553                     /* Request resource range was not found within local resources
554                      * provided by Server.  Set back to PROCESSING so request is forwarded to
555                      * Server */
556                     retVal = RM_SERVICE_PROCESSING;
557                 }
558             }
559         }
560         else {
561             if (rmAllocatorFind((Rm_Handle)rmInst, transaction->resourceInfo.name)) {
562                 int32_t oldAlign = transaction->resourceInfo.alignment;
563                 
564                 /* Attempt to allocate from local resources that were provided by Server */
565                 if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
566                     opInfo.operation = Rm_allocatorOp_PRE_ALLOCATE_INIT;
567                 }
568                 else if (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) {
569                     opInfo.operation = Rm_allocatorOp_PRE_ALLOCATE_USE;
570                 }
571                 else {
572                     retVal = RM_ERROR_INVALID_SERVICE_TYPE;
573                     goto errorExit;
574                 }
575                 retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
576                 
577                 if (retVal == RM_SERVICE_PROCESSING) {
578                     if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
579                         opInfo.operation = Rm_allocatorOp_ALLOCATE_INIT;
580                     }
581                     else if (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) {
582                         opInfo.operation = Rm_allocatorOp_ALLOCATE_USE;
583                     }
584                     else {
585                         retVal = RM_ERROR_INVALID_SERVICE_TYPE;
586                         goto errorExit;
587                     }
588                     retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
590                     if (retVal == RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST) {
591                         /* Request resource range was not found within local resources
592                          * provided by Server.  Set back to PROCESSING so request is forwarded to
593                          * Server */
594                         retVal = RM_SERVICE_PROCESSING;
595                     }                    
596                 }
597                 else if (retVal == RM_SERVICE_DENIED_RES_ALLOC_REQS_NOT_MET) {
598                     if (transaction->pendingTransactionId) {
599                         /* Request to Server for resources to complete transaction locally
600                          * performed once already.  Forward transaction to Server for completion */
601                         retVal = RM_SERVICE_PROCESSING;
602                     }
603                     else {
604                         /* Restore base and alignment since they were replaced in pre-allocate routine */
605                         transaction->resourceInfo.base = RM_RESOURCE_BASE_UNSPECIFIED;
606                         transaction->resourceInfo.alignment = oldAlign;
607                         
608                         retVal = cdRequestServerResources(rmInst, transaction);
609                     }
610                 }
611             }
612             else {
613                 retVal = cdRequestServerResources(rmInst, transaction);
614             }                
615         }
616     }
617     else if ((rmInst->instType == Rm_instType_SERVER)||
618              (rmInst->instType == Rm_instType_SHARED_SERVER)) {
619         /* Populated NameServer name has precedence over base */
620         if (strlen(transaction->resourceInfo.nameServerName) > 0) {
621             if (rmInst->instType == Rm_instType_SHARED_SERVER) {
622                 rmNameServerTreeInv(rmInst->u.server.nameServer);
623             }
624             memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
625             nameServerObjCfg.nameServerTree = rmInst->u.server.nameServer;
626             nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
627             if ((retVal = rmNameServerFindObject(&nameServerObjCfg)) == RM_SERVICE_PROCESSING) {
628                 rm_strncpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName, RM_NAME_MAX_CHARS);
629                 transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;
630                 transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;
631             }
632             else {
633                 goto errorExit;
634             }
635         }
637         if (transaction->resourceInfo.base == RM_RESOURCE_BASE_UNSPECIFIED) {
638             if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
639                 opInfo.operation = Rm_allocatorOp_PRE_ALLOCATE_INIT;
640             }
641             else if (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) {
642                 opInfo.operation = Rm_allocatorOp_PRE_ALLOCATE_USE;
643             }
644             else {
645                 retVal = RM_ERROR_INVALID_SERVICE_TYPE;
646                 goto errorExit;
647             }
648             retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
649         }
650     
651         if (retVal == RM_SERVICE_PROCESSING) {
652             if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
653                 opInfo.operation = Rm_allocatorOp_ALLOCATE_INIT;
654             }
655             else if (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) {
656                 opInfo.operation = Rm_allocatorOp_ALLOCATE_USE;
657             }
658             else {
659                 retVal = RM_ERROR_INVALID_SERVICE_TYPE;
660                 goto errorExit;
661             }
662             retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
663         }             
664     }
665 errorExit:        
666     transaction->state = retVal;      
669 /* FUNCTION PURPOSE: Handles resource status service requests
670  ***********************************************************************
671  * DESCRIPTION: Issues a set of allocator operations to retrieve the
672  *              current status (currently just owner reference count)
673  *              for the resource specified in the transaction
674  */
675 static void statusHandler (Rm_Inst *rmInst, Rm_Transaction *transaction)
677     Rm_AllocatorOpInfo  opInfo;
678     Rm_NameServerObjCfg nameServerObjCfg;
679     int32_t             retVal = transaction->state;
681     memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));
682     opInfo.operation = Rm_allocatorOp_GET_STATUS;
683     opInfo.policy = rmPolicyGetPolicy((Rm_Handle)rmInst);
684     opInfo.resourceInfo = &transaction->resourceInfo;
685     opInfo.serviceSrcInstNode = rmPolicyGetValidInstNode((Rm_Handle)rmInst, transaction->serviceSrcInstName);
686     if (opInfo.serviceSrcInstNode == NULL) {
687         retVal = RM_SERVICE_DENIED_INST_NAME_NOT_VALID;
688         goto errorExit;
689     }     
691     if ((strlen(transaction->resourceInfo.nameServerName) == 0) &&
692         ((transaction->resourceInfo.base == RM_RESOURCE_BASE_UNSPECIFIED) ||
693          (transaction->resourceInfo.length == 0))) {
694         retVal = RM_SERVICE_DENIED_RES_DOES_NOT_EXIST;
695         goto errorExit;
696     }
698     if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
699         if (rmAllocatorFind((Rm_Handle)rmInst, transaction->resourceInfo.name)) {
700             /* Attempt to get status from local resources that were provided by Server */
701             retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
703             if (retVal == RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST) {
704                 /* Request resource range was not found within local allocator resources
705                  * provided by Server.  Set back to PROCESSING so request is forwarded to
706                  * Server */
707                 retVal = RM_SERVICE_PROCESSING;
708             }            
709         }
710     }
711     else if ((rmInst->instType == Rm_instType_SERVER)||
712              (rmInst->instType == Rm_instType_SHARED_SERVER)) {
713         /* Populated NameServer name has precedence over base and length values */
714         if (strlen(transaction->resourceInfo.nameServerName) > 0) {
715             if (rmInst->instType == Rm_instType_SHARED_SERVER) {
716                 rmNameServerTreeInv(rmInst->u.server.nameServer);
717             }
718             memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
719             nameServerObjCfg.nameServerTree = rmInst->u.server.nameServer;
720             nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
721             if ((retVal = rmNameServerFindObject(&nameServerObjCfg)) == RM_SERVICE_PROCESSING) {
722                 rm_strncpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName, RM_NAME_MAX_CHARS);
723                 transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;
724                 transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;
725             }
726             else {
727                 goto errorExit;
728             }
729         }
730         retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);                 
731     }
732 errorExit:        
733     transaction->state = retVal;       
736 /* FUNCTION PURPOSE: Arbitrates free service requests
737  ***********************************************************************
738  * DESCRIPTION: Issues a set of allocator operations in order to
739  *              handle a received free request.  Free
740  *              requests are always forwarded to the Server on Client
741  *              CD instances.  If a request is made with a NameServer
742  *              name the resource base and length parameters are
743  *              retrieved from the NameServer prior to the free
744  *              attempt.
745  */
746 static void freeHandler (Rm_Inst *rmInst, Rm_Transaction *transaction)
748     Rm_AllocatorOpInfo  opInfo; 
749     Rm_NameServerObjCfg nameServerObjCfg;    
750     int32_t             retVal = transaction->state;
752     memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));
753     opInfo.operation = Rm_allocatorOp_FREE;
754     opInfo.policy = rmPolicyGetPolicy((Rm_Handle)rmInst);
755     opInfo.resourceInfo = &transaction->resourceInfo;
756     opInfo.serviceSrcInstNode = rmPolicyGetValidInstNode((Rm_Handle)rmInst, transaction->serviceSrcInstName);
757     if (opInfo.serviceSrcInstNode == NULL) {
758         retVal = RM_SERVICE_DENIED_INST_NAME_NOT_VALID;
759         goto errorExit;
760     }
762     if ((strlen(transaction->resourceInfo.nameServerName) == 0) &&
763         ((transaction->resourceInfo.base == RM_RESOURCE_BASE_UNSPECIFIED) ||
764          (transaction->resourceInfo.length == 0))) {
765         retVal = RM_SERVICE_DENIED_RES_DOES_NOT_EXIST;
766         goto errorExit;
767     }
769     if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
770         if (rmAllocatorFind((Rm_Handle)rmInst, transaction->resourceInfo.name)) {
771             /* Attempt to free from local resources that were provided by Server */
772             retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
774             if (retVal == RM_SERVICE_APPROVED) {
775                 /* Check if free allows local resources to be freed back to Server */
776                 retVal = cdFreeResourcesToServer(rmInst, transaction);
777             }
778             else if (retVal == RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST) {
779                 /* Request resource range was not found within local allocator resources
780                  * provided by Server.  Set back to PROCESSING so request is forwarded to
781                  * Server */
782                 retVal = RM_SERVICE_PROCESSING;
783             }  
784         } 
785     }
786     else if ((rmInst->instType == Rm_instType_SERVER) ||
787              (rmInst->instType == Rm_instType_SHARED_SERVER)) {
788         /* Populated NameServer name has precedence over base */
789         if (strlen(transaction->resourceInfo.nameServerName) > 0) {
790             if (rmInst->instType == Rm_instType_SHARED_SERVER) {
791                 rmNameServerTreeInv(rmInst->u.server.nameServer);
792             }                    
793             memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
794             nameServerObjCfg.nameServerTree = rmInst->u.server.nameServer;
795             nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
796             if ((retVal = rmNameServerFindObject(&nameServerObjCfg)) == RM_SERVICE_PROCESSING) {
797                 rm_strncpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName, RM_NAME_MAX_CHARS);
798                 transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;
799                 transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;
800             }
801             else {
802                 goto errorExit;
803             }             
804         }
805              
806         retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);     
807     }   
808 errorExit:
809     transaction->state = retVal;       
812 /* FUNCTION PURPOSE: Client transaction handling process
813  ***********************************************************************
814  * DESCRIPTION: Client process for handling transactions created
815  *              from services received via the service handle or the
816  *              transport.  The Client process:
817  *                  - Performs static allocations if no transport
818  *                    to CD or Server has been registered
819  *                  - Forwards all service requests to CD or Server
820  *                    once transport has been registered
821  */
822 static void clientProcess (Rm_Inst *rmInst, Rm_Transaction *transaction)
824     Rm_Transaction *transQ;
825     
826     if (!rmInst->registeredWithDelegateOrServer) {
827         staticAllocationHandler((Rm_Handle)rmInst, transaction);
828     }
829     else {
830         if (transaction->state == RM_SERVICE_PROCESSING) {
831             /* Forward all new transactions to CD or Server */
832             transactionForwarder(rmInst, transaction);                
833         }
834         else {
835             /* Transaction validated.  Return result. */
836             serviceResponder(rmInst, transaction);
837         }
839         /* Forward any queued static requests that weren't forwarded */
840         transQ = rmInst->transactionQueue;
841         while(transQ) {
842             if ((transQ->state == RM_SERVICE_APPROVED_STATIC) &&
843                 (!transQ->hasBeenForwarded)) {
844                 transactionForwarder(rmInst, transQ);
845             }
846             transQ = transQ->nextTransaction;
847         }        
848     }
849     /* Let call stack return transaction result app via Rm_serviceHandler */
852 /* FUNCTION PURPOSE: Client Delegate transaction handling process
853  ***********************************************************************
854  * DESCRIPTION: Client Delegate process for handling transactions created
855  *              from services received via the service handle or the
856  *              transport.  The Client Delegate process:
857  *                  - Performs static allocations if no transport
858  *                    to Server has been registered
859  *                  - Forwards all NameServer related service requests 
860  *                    to Server once transport has been registered
861  *                  - Attempts to complete resource service requests
862  *                    received from registered Clients
863  */
864 static void cdProcess (Rm_Inst *rmInst, Rm_Transaction *transaction)
865 {      
866     Rm_Transaction   *newTrans = NULL;
867     Rm_AllocatorNode *allocator = NULL;
868     Rm_Transaction   *transQ;
870     if (!rmInst->registeredWithDelegateOrServer) {
871         if ((transaction->state == RM_SERVICE_PROCESSING) &&
872             (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS) == 0)) {
873             /* Attempt static allocation of requests originating from CD inst */
874             staticAllocationHandler((Rm_Handle)rmInst, transaction);
875         }
876         /* Everything else left in transaction queue for forwarding once transport to
877          * Server is registered */
878     }
879     else {
880         if (transaction->pendingTransactionId) {
881             Rm_Transaction *pendingTrans = rmTransactionQueueFind(rmInst, transaction->pendingTransactionId);
882             
883             /* Transaction is response from Server for transaction sent to get
884              * information in order to complete pending transaction */
885             if (transaction->state == RM_SERVICE_APPROVED) {
886                 if (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) {
887                     /* Transfer resource data tied to name to pending transaction */
888                     rm_strncpy(pendingTrans->resourceInfo.name, transaction->resourceInfo.name, RM_NAME_MAX_CHARS);
889                     pendingTrans->resourceInfo.base = transaction->resourceInfo.base;
890                     pendingTrans->resourceInfo.length = transaction->resourceInfo.length;
891                     /* Delete NS name from pending transaction so Server isn't queried again */
892                     memset(pendingTrans->resourceInfo.nameServerName, 0, RM_NAME_MAX_CHARS);
893                     /* Now that resource values have been retrieved clear pending transaction ID so 
894                      * CD doesn't think a resource request was sent to Server already for more local resources */
895                     pendingTrans->pendingTransactionId = 0;
897                     /* Return original transaction to processing state to attempt completion. */
898                     pendingTrans->state = RM_SERVICE_PROCESSING;
899                 }
900                 else if ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||
901                          (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE)) {
902                     /* Add resources provided by Server to those managed by CD */
903                     if ((allocator = rmAllocatorFind((Rm_Handle)rmInst, transaction->resourceInfo.name))) {
904                         Rm_ResourceNode *treeNode = NULL;
905                         
906                         treeNode = rmResourceNodeNew(transaction->resourceInfo.base, transaction->resourceInfo.length);
907                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->resourceRoot, treeNode);
908                     }
909                     else {
910                         Rm_ResourceRange resRange;
912                         memset((void *)&resRange, 0, sizeof(resRange));
913                         resRange.base = transaction->resourceInfo.base;
914                         resRange.length = transaction->resourceInfo.length;
915                         
916                         rmAllocatorCreate((Rm_Handle)rmInst, transaction->resourceInfo.name, &resRange);
917                     }
919                     /* Return original transaction to processing state to attempt completion */
920                     pendingTrans->state = RM_SERVICE_PROCESSING;
921                 }
922                 else if (transaction->type == Rm_service_RESOURCE_FREE) {
923                     allocator = rmAllocatorFind((Rm_Handle)rmInst,
924                                                 transaction->resourceInfo.name);
926                     /* Local resource freed on Server.  Need to remove from
927                      * local allocator's resource tree as well */
928                     rmAllocatorDeleteResNode((Rm_Handle)rmInst,
929                                              allocator,
930                                              transaction->resourceInfo.base,
931                                              transaction->resourceInfo.length);
933                     /* Delete the allocator's resource tree if there are no
934                      * nodes left in the resource tree */
935                     if (RB_MIN(_Rm_AllocatorResourceTree,
936                                allocator->resourceRoot) == NULL) {
937                         rmAllocatorDelete((Rm_Handle)rmInst,
938                                           transaction->resourceInfo.name);
939                     }
941                     /* Allow original free to complete */
942                     pendingTrans->state = RM_SERVICE_APPROVED;
943                 }
944             }
945             else {
946                 if (transaction->type == Rm_service_RESOURCE_FREE) {
947                     /* Error occurred when trying to free local resource on Server.  Reinsert local
948                      * resources freed by original request */
949                     Rm_AllocatorOpInfo   opInfo;
951                     memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));
952                     opInfo.policy = rmPolicyGetPolicy((Rm_Handle)rmInst);
953                     opInfo.resourceInfo = &pendingTrans->resourceInfo;
954                     opInfo.serviceSrcInstNode = rmPolicyGetValidInstNode((Rm_Handle)rmInst, pendingTrans->serviceSrcInstName);
955                     /* Can't regain the original type of allocate.  Default to init */
956                     opInfo.operation = Rm_allocatorOp_ALLOCATE_INIT;
957                     if (rmAllocatorOperation((Rm_Handle)rmInst, &opInfo) != RM_SERVICE_APPROVED) {
958                         transaction->state = RM_ERROR_LOST_RESOURCES_ON_CD;
959                     }                    
960                 }
961                 /* Transfer error or denial to pending transaction */
962                 pendingTrans->state = transaction->state;
963             }
964             rmTransactionQueueDelete(rmInst, transaction->localId);
965             /* Switch to pending transaction */
966             transaction = pendingTrans;
967         }
968         
969         if ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||
970             (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) ||
971             (transaction->type == Rm_service_RESOURCE_STATUS) ||
972             (transaction->type == Rm_service_RESOURCE_FREE)) {
973             if ((transaction->state == RM_SERVICE_PROCESSING) &&
974                 (strlen(transaction->resourceInfo.nameServerName) > 0)) {   
975                 /* Create and forward new transaction to Server to
976                  * retrieve resource data mapped to name */
977                 if ((newTrans = rmTransactionQueueAdd(rmInst))) {
978                     newTrans->type = Rm_service_RESOURCE_GET_BY_NAME;
979                     rm_strncpy(newTrans->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS);
980                     newTrans->state = RM_SERVICE_PROCESSING;       
981                     rm_strncpy(newTrans->resourceInfo.nameServerName, transaction->resourceInfo.nameServerName, 
982                             RM_NAME_MAX_CHARS);
983                     newTrans->pendingTransactionId = transaction->localId;
984                     transactionForwarder(rmInst, newTrans);
986                     transaction->state = RM_SERVICE_PENDING_SERVER_RESPONSE;
987                 }
988                 else {
989                     transaction->state = RM_ERROR_TRANS_REQ_TO_SERVER_NOT_CREATED;    
990                 }        
991             }                
992         }
994         if ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||
995             (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE)) {
996             if (transaction->state == RM_SERVICE_PROCESSING) {   
997                 allocationHandler(rmInst, transaction);
998             }
999         }
1000         else if (transaction->type == Rm_service_RESOURCE_STATUS) {
1001             if (transaction->state == RM_SERVICE_PROCESSING) {   
1002                 statusHandler(rmInst, transaction);
1003             }               
1004         }        
1005         else if (transaction->type == Rm_service_RESOURCE_FREE) {     
1006             if (transaction->state == RM_SERVICE_PROCESSING) {
1007                 freeHandler(rmInst, transaction);
1008             }     
1009         }
1010         /* Forward all NameServer-based transactions */
1012         if (transaction->state == RM_SERVICE_PROCESSING) {
1013             /* CD could not complete transaction.  Forward to Server */
1014             transactionForwarder(rmInst, transaction);
1015         }
1016         else if (transaction->state != RM_SERVICE_PENDING_SERVER_RESPONSE) {
1017             /* Transaction completed by CD or completed response received from Server.  Return result */
1018             if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {
1019                 /* Transaction did not originate on this instance */
1020                 transactionResponder(rmInst, transaction);
1021             }
1022             else {
1023                 /* Transaction originated on this instance */
1024                 serviceResponder(rmInst, transaction);
1025             }                    
1026         }           
1028         /* Attempt allocation of any queued static requests:
1029          * RM_SERVICE_APPROVED_STATIC - Originated locally
1030          * RM_SERVICE_PROCESSING - Received from any registered Clients */
1031         transQ = rmInst->transactionQueue;
1032         while(transQ) {
1033             if (((transQ->state == RM_SERVICE_PROCESSING) ||
1034                  (transQ->state == RM_SERVICE_APPROVED_STATIC)) &&
1035                 (!transQ->hasBeenForwarded)) {
1036                 transactionForwarder(rmInst, transQ);
1037             }
1038             transQ = transQ->nextTransaction;
1039         }        
1040     }
1043 /* FUNCTION PURPOSE: Server transaction handling process
1044  ***********************************************************************
1045  * DESCRIPTION: Server process for handling transactions created
1046  *              from services received via the service handle or the
1047  *              transport.  The Server process:
1048  *                  - Validates all service requests received from
1049  *                    the service handle and registered CDs and
1050  *                    Clients
1051  */
1052 static void serverProcess (Rm_Inst *rmInst, Rm_Transaction *transaction)
1054     Rm_NameServerObjCfg  nameServerObjCfg;
1056     switch (transaction->type) {
1057         case Rm_service_RESOURCE_STATUS:
1058             statusHandler(rmInst, transaction);
1059             break;
1060         case Rm_service_RESOURCE_ALLOCATE_INIT:
1061         case Rm_service_RESOURCE_ALLOCATE_USE:
1062             allocationHandler(rmInst, transaction);
1063             break;
1064         case Rm_service_RESOURCE_FREE:
1065             freeHandler(rmInst, transaction);
1066             break;
1067         case Rm_service_RESOURCE_MAP_TO_NAME:
1068         case Rm_service_RESOURCE_GET_BY_NAME:
1069         case Rm_service_RESOURCE_UNMAP_NAME:
1070             if (rmInst->u.server.nameServer) {
1071                 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1072                     rmNameServerTreeInv(rmInst->u.server.nameServer);
1073                 }                
1074                 memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
1075                 nameServerObjCfg.nameServerTree = rmInst->u.server.nameServer;
1076                 nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
1077                 if (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) {
1078                     nameServerObjCfg.nodeCfg.resourceName = transaction->resourceInfo.name;
1079                     nameServerObjCfg.nodeCfg.resourceBase= transaction->resourceInfo.base;
1080                     nameServerObjCfg.nodeCfg.resourceLength = transaction->resourceInfo.length;
1081                     transaction->state = rmNameServerAddObject(&nameServerObjCfg);
1082                 }
1083                 else if (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) {
1084                     if ((transaction->state = rmNameServerFindObject(&nameServerObjCfg)) ==
1085                         RM_SERVICE_PROCESSING) {
1086                         rm_strncpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName, RM_NAME_MAX_CHARS);
1087                         transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;
1088                         transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;
1089                         transaction->state = RM_SERVICE_APPROVED;
1090                     } 
1091                 }
1092                 else if (transaction->type == Rm_service_RESOURCE_UNMAP_NAME) {
1093                     transaction->state = rmNameServerDeleteObject(&nameServerObjCfg);
1094                 }
1095                 
1096                 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1097                     rmNameServerTreeWb(rmInst->u.server.nameServer);
1098                 }
1099             }
1100             else {
1101                 transaction->state = RM_ERROR_NAMESERVER_DOES_NOT_EXIST;
1102             }
1103             break;
1104         default:
1105             transaction->state = RM_ERROR_INVALID_SERVICE_TYPE;
1106             break;
1107     }
1109     /* Source of shared server transaction will always be local. */
1110     if (rmInst->instType != Rm_instType_SHARED_SERVER) {
1111         if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {
1112             /* Source of transaction was not Server, return transaction via responder */
1113             transactionResponder(rmInst, transaction);
1114         }
1115     }
1116     /* Otherwise let call stack return transaction result app via Rm_serviceHandler */ 
1119 /**********************************************************************
1120  ********************** Internal Functions ****************************
1121  **********************************************************************/
1123 /* FUNCTION PURPOSE: Adds a transaction
1124  ***********************************************************************
1125  * DESCRIPTION: Returns a pointer to a newly created transaction.
1126  *              The transaction is created based on a new service
1127  *              request received via the service API or the
1128  *              transport API (service forwarded from another instance)
1129  */
1130 Rm_Transaction *rmTransactionQueueAdd(Rm_Inst *rmInst)
1132     Rm_Transaction *transactionQueue = rmInst->transactionQueue;
1133     Rm_Transaction *newTransaction   = NULL;
1135     newTransaction = Rm_osalMalloc(sizeof(Rm_Transaction));
1136     if (newTransaction) {
1137         memset((void *)newTransaction, 0, sizeof(Rm_Transaction));
1139         newTransaction->localId = transactionGetSequenceNum(rmInst);
1140         newTransaction->nextTransaction = NULL;  
1141         if (transactionQueue) {
1142             while (transactionQueue->nextTransaction) {
1143                 transactionQueue = transactionQueue->nextTransaction;
1144             }
1145             transactionQueue->nextTransaction = newTransaction;
1146         }
1147         else {
1148             rmInst->transactionQueue = newTransaction;
1149         }
1150     }
1151     return (newTransaction);
1154 /* FUNCTION PURPOSE: Finds a transaction
1155  ***********************************************************************
1156  * DESCRIPTION: Returns a pointer to a transaction resident
1157  *              in the transaction queue that matches the provided
1158  *              transaction ID.
1159  */
1160 Rm_Transaction *rmTransactionQueueFind(Rm_Inst *rmInst, uint32_t transactionId)
1162     Rm_Transaction *transaction = rmInst->transactionQueue;
1164     while (transaction) {
1165         if (transaction->localId == transactionId) {
1166             break;             
1167         }
1168         transaction = transaction->nextTransaction;
1169     }
1171     return (transaction);
1174 /* FUNCTION PURPOSE: Deletes a transaction
1175  ***********************************************************************
1176  * DESCRIPTION: Deletes the transaction with the provided transaction
1177  *              ID from the instance's transaction queue.
1178  */
1179 int32_t rmTransactionQueueDelete(Rm_Inst *rmInst, uint32_t transactionId)
1181     Rm_Transaction *transaction     = rmInst->transactionQueue;
1182     Rm_Transaction *prevTransaction = NULL;
1183     int32_t         retVal          = RM_OK;
1185     while (transaction) {
1186         if (transaction->localId == transactionId) {
1187             break;             
1188         }
1190         prevTransaction = transaction;
1191         transaction = transaction->nextTransaction;
1192     }
1194     if (transaction) {
1195         if (prevTransaction == NULL) {
1196             /* Transaction at start of queue. Map second transaction to start of queue 
1197              * as long as more than one transactions. */
1198             rmInst->transactionQueue = transaction->nextTransaction;
1199         }
1200         else {
1201             /* Transaction in middle or end of queue. */
1202             prevTransaction->nextTransaction = transaction->nextTransaction;
1203         }
1204         Rm_osalFree((void *)transaction, sizeof(Rm_Transaction));
1205     }
1206     else {
1207         retVal = RM_ERROR_SERVICE_TRANS_DOES_NOT_EXIST;
1208     }    
1209     return (retVal);
1212 /* FUNCTION PURPOSE: Routes a transaction for processing
1213  ***********************************************************************
1214  * DESCRIPTION: Routes a received transaction to the appropriate
1215  *              instance processing routine
1216  */
1217 void rmProcessRouter (Rm_Inst *rmInst, Rm_Transaction *transaction)
1219     if (rmInst->instType == Rm_instType_CLIENT) {
1220         clientProcess(rmInst, transaction);
1221     }
1222     else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1223         cdProcess(rmInst, transaction);
1224     }
1225     else if ((rmInst->instType == Rm_instType_SERVER) ||
1226              (rmInst->instType == Rm_instType_SHARED_SERVER)) {
1227         serverProcess(rmInst, transaction);
1228     } 
1230      
1231 /**********************************************************************
1232  ********************** Application visible APIs **********************
1233  **********************************************************************/
1235 /* FUNCTION PURPOSE: Display status of managed resources
1236  ***********************************************************************
1237  * DESCRIPTION: Prints the status (allocate/free status, as well as
1238  *              owners) for all resources managed by the RM 
1239  *              instance network.  Also, prints the NameServer name
1240  *              entries.  The number of resource range owners is
1241  *              returned as well.  This function is only available on
1242  *              Server and CD instances.
1243  */
1244 int32_t Rm_resourceStatus(Rm_Handle rmHandle, int printResources)
1246     Rm_Inst          *rmInst = (Rm_Inst *)rmHandle;
1247     Rm_AllocatorTree *allocTree = NULL;
1248     Rm_AllocatorNode *allocator;
1249     Rm_Owner         *owners;
1250     Rm_ResourceTree  *treeRoot;
1251     Rm_ResourceNode  *treeNode;
1252     int32_t           totalResOwners = 0;
1253     void             *key;
1254     void             *mtKey;
1256     RM_SS_INST_INV_ENTER_CS(rmInst, key);
1257     RM_SC_INST_INV_ENTER_CS(rmInst, key);
1258     if (rmInst->mtSemObj) {
1259         mtKey = Rm_osalMtCsEnter(rmInst->mtSemObj);
1260     }
1262     if (rmInst->instType != Rm_instType_CLIENT) {
1263         Rm_osalLog("Instance name: %s\n", rmInst->instName);
1264         Rm_osalLog("Handle: 0x%08x\n", rmHandle);    
1265         if (rmInst->instType == Rm_instType_SERVER) {
1266             Rm_osalLog("Type:   Server\n");
1267         } else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1268             Rm_osalLog("Type:   Client Delegate\n");
1269         } else if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1270             Rm_osalLog("Type:   Shared Server\n");
1271         } else if (rmInst->instType == Rm_instType_SHARED_CLIENT) {
1272             Rm_osalLog("Type:   Shared Client\n");
1273         }
1275         Rm_osalLog("\nResource Status:\n\n");
1276     }
1278     if (rmInst->instType == Rm_instType_SHARED_CLIENT) {
1279         /* Transfer control to shared server instance */
1280         rmInst = rmInst->u.sharedClient.sharedServerHandle;
1281     }
1283     if ((rmInst->instType == Rm_instType_SERVER) ||
1284         (rmInst->instType == Rm_instType_SHARED_SERVER) ||
1285         (rmInst->instType == Rm_instType_CLIENT_DELEGATE)) {
1286         
1287         allocTree = rmAllocatorGetTree((Rm_Handle)rmInst);
1288         if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1289             rmAllocatorTreeInv(allocTree);
1290         }
1292         RB_FOREACH(allocator, _Rm_AllocatorTree, allocTree) {
1293             RM_SS_OBJ_INV(rmInst, allocator, Rm_AllocatorNode);
1294             if (printResources) {
1295                 Rm_osalLog("Resource: %s\n", allocator->resourceName);
1296             }
1298             treeRoot = allocator->resourceRoot;
1299             if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1300                 rmResourceTreeInv(treeRoot);
1301             }
1302             RB_FOREACH(treeNode, _Rm_AllocatorResourceTree, treeRoot) {
1303                 if (printResources) {
1304                     if ((treeNode->base >= 65536) ||
1305                         ((treeNode->base + treeNode->length - 1) >= 65536)) {
1306                         /* Print in hex if number is very large */
1307                         Rm_osalLog("          0x%08x - 0x%08x ",
1308                                    treeNode->base,
1309                                    treeNode->base + treeNode->length - 1);
1310                     } else {
1311                         Rm_osalLog("          %10d - %10d ",
1312                                    treeNode->base,
1313                                    treeNode->base + treeNode->length - 1);
1314                     }
1315                 }
1317                 if (treeNode->allocationCount == 0) {
1318                     if (printResources) {
1319                         Rm_osalLog("FREE\n");
1320                     }
1321                 } else {
1322                     owners = treeNode->ownerList;
1323                     while (owners) {
1324                         RM_SS_OBJ_INV(rmInst, owners, Rm_Owner);
1325                         if (printResources) {
1326                             Rm_osalLog("%s (%d) ", owners->instNameNode->name,
1327                                        owners->refCnt);
1328                         }
1329                         totalResOwners++;
1330                         owners = owners->nextOwner;
1331                     }
1332                     if (printResources) {
1333                         Rm_osalLog("\n");
1334                     }
1335                 }
1336             }
1337         }
1339         if ((rmInst->instType == Rm_instType_SERVER) ||
1340             (rmInst->instType == Rm_instType_SHARED_SERVER)) {
1341             if (printResources) {
1342                 rmNameServerPrintObjects((Rm_Handle)rmInst);
1343             }
1344         }
1345     } else {
1346         totalResOwners = RM_ERROR_INVALID_RES_STATUS_INSTANCE;
1347     }
1349     /* Free sem object using originating instance in case the Shared Client to Shared
1350      * Server instance switch took place */
1351     if (((Rm_Inst *)rmHandle)->mtSemObj) {
1352         Rm_osalMtCsExit(((Rm_Inst *)rmHandle)->mtSemObj, mtKey);
1353     }
1354     RM_SS_INST_WB_EXIT_CS(rmInst, key);
1355     return(totalResOwners);
1358 /* FUNCTION PURPOSE: Display status of a RM instance
1359  ***********************************************************************
1360  * DESCRIPTION: Prints the current status of various RM instance
1361  *              properties such as the state of all transactions
1362  *              in the transaction queue and registered transports
1363  */
1364 void Rm_instanceStatus(Rm_Handle rmHandle)
1366     Rm_Inst        *rmInst = (Rm_Inst *)rmHandle;
1367     Rm_Transport   *transportList = NULL;
1368     Rm_Transaction *transactionQ = NULL;
1369     void           *key;
1370     void           *mtKey;
1372     RM_SS_INST_INV_ENTER_CS(rmInst, key);
1373     RM_SC_INST_INV_ENTER_CS(rmInst, key);
1374     if (rmInst->mtSemObj) {
1375         mtKey = Rm_osalMtCsEnter(rmInst->mtSemObj);
1376     }
1378     Rm_osalLog("Instance name: %s\n", rmInst->instName);
1379     Rm_osalLog("Handle: 0x%08x\n", rmHandle);    
1380     if (rmInst->instType == Rm_instType_SERVER) {
1381         Rm_osalLog("Type:   Server\n");
1382     }
1383     else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1384         Rm_osalLog("Type:   Client Delegate\n");
1385     }
1386     else if (rmInst->instType == Rm_instType_CLIENT) {
1387         Rm_osalLog("Type:   Client\n");
1388     }
1389     else if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1390         Rm_osalLog("Type:   Shared Server\n");
1391     }
1392     else if (rmInst->instType == Rm_instType_SHARED_CLIENT) {
1393         Rm_osalLog("Type:   Shared Client\n");
1395         Rm_osalLog("\nShared Server Properties:\n");
1396         /* Transfer to Shared Server instance to print out transport and
1397          * transaction status */
1398         rmInst = rmInst->u.sharedClient.sharedServerHandle;
1399         Rm_osalLog("Instance name: %s\n", rmInst->instName);
1400         Rm_osalLog("Handle: 0x%08x\n", rmHandle);
1401     }
1402     
1403     transportList = rmInst->transports;
1404     if (transportList) {
1405         Rm_osalLog("\nRegistered Transports:\n");
1406         while (transportList) {
1407             RM_SS_OBJ_INV(rmInst, transportList, Rm_Transport);
1408             if (transportList->remoteInstType == Rm_instType_SERVER) {
1409                 Rm_osalLog("    Remote instType:    Server\n");
1410             }
1411             else if (transportList->remoteInstType == Rm_instType_CLIENT_DELEGATE) {
1412                 Rm_osalLog("    Remote instType:    Client Delegate\n");
1413             }
1414             else {
1415                 Rm_osalLog("    Remote instType:    Client\n");
1416             }
1417             Rm_osalLog("    appTransportHandle: 0x%08x\n", transportList->appTransportHandle);
1418             Rm_osalLog("\n");
1419             transportList = transportList->nextTransport;
1420         }
1421     }
1423     transactionQ = rmInst->transactionQueue;
1424     if (transactionQ) {
1425         Rm_osalLog("\nQueued Service Transactions:\n");
1426         while (transactionQ) {
1427             RM_SS_OBJ_INV(rmInst, transactionQ, Rm_Transaction);
1428             Rm_osalLog("    Service type:       %d\n", transactionQ->type);
1429             Rm_osalLog("    Service ID:         %d\n", transactionQ->localId);
1430             Rm_osalLog("    Service srcInstName %s\n", transactionQ->serviceSrcInstName);
1431             Rm_osalLog("    Service state:      %d\n", transactionQ->state);
1432             Rm_osalLog("    Resource name:      %s\n", transactionQ->resourceInfo.name);
1433             Rm_osalLog("    Resource base:      %d\n", transactionQ->resourceInfo.base);
1434             Rm_osalLog("    Resource length:    %d\n", transactionQ->resourceInfo.length);
1435             Rm_osalLog("    Resource alignment: %d\n", transactionQ->resourceInfo.alignment);
1436             Rm_osalLog("    Resource NS name:   %s\n", transactionQ->resourceInfo.nameServerName);
1437             Rm_osalLog("\n");
1438             transactionQ = transactionQ->nextTransaction;
1439         }    
1440     }
1441     
1442     /* Free sem object using originating instance in case the Shared Client to Shared
1443      * Server instance switch took place */
1444     if (((Rm_Inst *)rmHandle)->mtSemObj) {
1445         Rm_osalMtCsExit(((Rm_Inst *)rmHandle)->mtSemObj, mtKey);
1446     }    
1447     RM_SS_INST_WB_EXIT_CS(rmInst, key);    
1450 /* FUNCTION PURPOSE: RM instance creation and initialization
1451  ***********************************************************************
1452  * DESCRIPTION: Returns a new RM instance created and initialized
1453  *              using the parameters provided via the initCfg
1454  *              structure.
1455  */
1456 Rm_Handle Rm_init(const Rm_InitCfg *initCfg, int32_t *result)
1458     Rm_Inst  *rmInst = NULL;
1459     Rm_Inst  *sharedServerInst = NULL;
1460     uint32_t  policySize;
1461     void     *globalResourceDtb = NULL;
1462     void     *linuxResourceDtb = NULL;
1463     int       addLinux = RM_FALSE;
1464     void     *key;
1466     *result = RM_OK;
1468     if ((initCfg->instName == NULL) ||
1469         ((strlen(initCfg->instName) + 1) > RM_NAME_MAX_CHARS)) {
1470         *result = RM_ERROR_INVALID_INST_NAME;
1471         goto errorExit;
1472     }
1474     if (initCfg->instType >= Rm_instType_LAST) {
1475         *result = RM_ERROR_INVALID_INST_TYPE;
1476         goto errorExit;
1477     }
1479     /* Create and initialize instance */
1480     rmInst = Rm_osalMalloc(sizeof(*rmInst));
1481     memset((void *)rmInst, 0, sizeof(*rmInst));
1482     rmInst->isLocked = RM_FALSE;
1483     rmInst->registeredWithDelegateOrServer = RM_FALSE;
1484     rmInst->transactionSeqNum = transactionInitSequenceNum();
1486     rmInst->instType = initCfg->instType;
1487     rm_strncpy(rmInst->instName, initCfg->instName, RM_NAME_MAX_CHARS);
1488     rmInst->mtSemObj = initCfg->mtSemObj;
1490     if ((rmInst->instType == Rm_instType_SERVER) ||
1491         (rmInst->instType == Rm_instType_SHARED_SERVER)) {
1492         if (!initCfg->instCfg.serverCfg.globalResourceList ||
1493             !initCfg->instCfg.serverCfg.globalPolicy) {
1494             *result = RM_ERROR_INVALID_SERVER_CONFIGURATION;
1495             goto errorExit;
1496         }
1498         if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1499             /* Shared Server makes copy of policy in shared memory for Shared
1500              * Clients on other cores */
1501             policySize = fdt_totalsize(initCfg->instCfg.serverCfg.globalPolicy);
1502             /* Align policy size to cache boundary */
1503             if (policySize % RM_MAX_CACHE_ALIGN) {
1504                 policySize += (RM_MAX_CACHE_ALIGN - (policySize % RM_MAX_CACHE_ALIGN));
1505             }
1506             rmInst->u.server.policySize = policySize;
1507             rmInst->u.server.globalPolicy = Rm_osalMalloc(rmInst->u.server.policySize);
1508             memcpy(rmInst->u.server.globalPolicy, initCfg->instCfg.serverCfg.globalPolicy, rmInst->u.server.policySize);
1509         } else {
1510             rmInst->u.server.globalPolicy = initCfg->instCfg.serverCfg.globalPolicy;
1511         }
1513         if (initCfg->instCfg.serverCfg.linuxDtb) {
1514             linuxResourceDtb = initCfg->instCfg.serverCfg.linuxDtb;
1515             addLinux = RM_TRUE;
1516         }
1518         /* Create valid instance list from policy.  Must be done prior to parsing
1519          * GRL so that Linux resources can be reserved correctly */
1520         rmInst->u.server.validInstTree = rmPolicyCreateValidInstTree((Rm_Handle)rmInst, addLinux, result);
1521         if (*result == RM_OK) {
1522             *result = rmPolicyValidatePolicy((Rm_Handle)rmInst);
1523         }
1524         
1525         if (*result != RM_OK) {
1526             if (rmInst->u.server.validInstTree) {
1527                 rmPolicyFreeValidInstTree((Rm_Handle)rmInst);
1528             }
1529             goto errorExit;
1530         } else {
1531             rmNameServerInit((Rm_Handle)rmInst);
1533             globalResourceDtb = initCfg->instCfg.serverCfg.globalResourceList;
1535             if ((*result = rmAllocatorInitTree((Rm_Handle) rmInst)) == RM_OK) {
1536                 if ((*result = rmAllocatorPopulateTree((Rm_Handle)rmInst,
1537                                                         globalResourceDtb,
1538                                                         linuxResourceDtb)) ==
1539                                                         RM_OK) {
1540                     *result = rmPolicyValidateResNames((Rm_Handle)rmInst);
1541                 }
1542             }
1544             if (*result != RM_OK) {
1545                 rmAllocatorDeleteTree((Rm_Handle)rmInst);
1546                 rmNameServerDelete((Rm_Handle)rmInst);
1547                 if (rmInst->u.server.validInstTree) {
1548                     rmPolicyFreeValidInstTree((Rm_Handle)rmInst);
1549                 }
1550                 goto errorExit;
1551             }
1552         }
1553     } else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1554         if (!initCfg->instCfg.cdCfg.cdPolicy) {
1555             *result = RM_ERROR_INVALID_CD_CONFIGURATION;
1556             goto errorExit;
1557         }
1559         rmInst->u.cd.cdPolicy = initCfg->instCfg.cdCfg.cdPolicy;
1560         rmInst->u.cd.validInstTree = rmPolicyCreateValidInstTree((Rm_Handle)rmInst, addLinux, result);
1561         if (*result == RM_OK) {
1562             *result = rmPolicyValidatePolicy((Rm_Handle)rmInst);
1563         }
1565         if (*result != RM_OK) {
1566             if (rmInst->u.cd.validInstTree) {
1567                 rmPolicyFreeValidInstTree((Rm_Handle)rmInst);
1568             }
1569             goto errorExit;
1570         }
1572         if ((*result = rmAllocatorInitTree((Rm_Handle) rmInst)) != RM_OK) {
1573             if (rmInst->u.cd.validInstTree) {
1574                 rmPolicyFreeValidInstTree((Rm_Handle)rmInst);
1575             }
1576             goto errorExit;
1577         }
1579         /* Remove once CD instance is stable - tracked by SDOCM00100797 */
1580         *result = RM_WARNING_CD_INSTANCE_NOT_STABLE;
1581     } else if (rmInst->instType == Rm_instType_CLIENT) {
1582         if (initCfg->instCfg.clientCfg.staticPolicy) {
1583             rmInst->u.client.staticPolicy = initCfg->instCfg.clientCfg.staticPolicy;
1584             rmInst->u.client.staticValidInstTree = rmPolicyCreateValidInstTree((Rm_Handle)rmInst, addLinux, result);        
1585             if (*result == RM_OK) {
1586                 *result = rmPolicyValidatePolicy((Rm_Handle)rmInst);
1587             }
1588             
1589             if (*result != RM_OK) {
1590                 if (rmInst->u.client.staticValidInstTree) {
1591                     rmPolicyFreeValidInstTree((Rm_Handle)rmInst);
1592                 }
1593                 goto errorExit;
1594             }
1595         }
1596     } else if (rmInst->instType == Rm_instType_SHARED_CLIENT) {
1597         if (initCfg->instCfg.sharedClientCfg.sharedServerHandle) {
1598             rmInst->u.sharedClient.sharedServerHandle = initCfg->instCfg.sharedClientCfg.sharedServerHandle;
1599             /* Invalidate the Shared server instance structure on this core to get the latest
1600              * instance data. */
1601             key = Rm_osalCsEnter();
1602             Rm_osalBeginMemAccess((void *)rmInst->u.sharedClient.sharedServerHandle, sizeof(Rm_Inst));
1603             sharedServerInst = rmInst->u.sharedClient.sharedServerHandle;
1604             if (sharedServerInst->instType != Rm_instType_SHARED_SERVER) {
1605                 *result = RM_ERROR_INVALID_SHARED_SERVER_HANDLE;
1606                 Rm_osalCsExit(key);
1607                 goto errorExit;
1608             } else {
1609                 /* Invalidate the policy */
1610                 Rm_osalBeginMemAccess((void *)sharedServerInst->u.server.globalPolicy, 
1611                                       sharedServerInst->u.server.policySize);
1612             }
1613             Rm_osalCsExit(key);
1614         } else {
1615             *result = RM_ERROR_INVALID_SHARED_SERVER_HANDLE;
1616             goto errorExit;
1617         }
1618     }
1620     if (initCfg->instType == Rm_instType_SHARED_SERVER) {
1621         /* Writeback the instance and policy for other cores */
1622         Rm_osalEndMemAccess ((void *)rmInst, sizeof(Rm_Inst));
1623         Rm_osalEndMemAccess ((void *)rmInst->u.server.globalPolicy, rmInst->u.server.policySize);
1624     } else if (rmInst->instType != Rm_instType_SHARED_CLIENT) {
1625         /* Create the instance's task blocking mechanism */
1626         rmInst->blockHandle = Rm_osalTaskBlockCreate();
1627     }
1629     return ((Rm_Handle) rmInst);
1630 errorExit:
1631     if (rmInst) {
1632         Rm_osalFree((void *)rmInst, sizeof(Rm_Inst));
1633     }
1634     return (NULL); 
1637 /* FUNCTION PURPOSE: Deletes an RM instance
1638  ***********************************************************************
1639  * DESCRIPTION: Frees all memory associated with an RM instance
1640  *              as long as all transports have been unregistered
1641  *              and the service handle has been closed
1642  */
1643 int32_t Rm_delete(Rm_Handle rmHandle, int ignorePendingServices)
1645     Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
1646     void    *key;
1648     key = Rm_osalCsEnter();
1649     if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1650         Rm_osalBeginMemAccess((void *)rmInst, sizeof(Rm_Inst));
1651     }
1653     if (rmInst->serviceHandle) {
1654         return (RM_ERROR_CANT_DELETE_WITH_OPEN_SERV_HNDL);
1655     }
1656     else if (rmInst->transports) {
1657         return (RM_ERROR_CANT_DELETE_WITH_REGD_TRANSPORT);
1658     }
1659     else if (rmInst->transactionQueue && !ignorePendingServices) {
1660         return (RM_ERROR_CANT_DELETE_PENDING_TRANSACTIONS);
1661     }
1663     if ((rmInst->instType == Rm_instType_SERVER) ||
1664         (rmInst->instType == Rm_instType_SHARED_SERVER)) {
1665         rmAllocatorDeleteTree(rmHandle);
1666         rmNameServerDelete(rmHandle);
1667         rmInst->u.server.allocatorTree = NULL;
1669         if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1670             Rm_osalFree((void *)rmInst->u.server.globalPolicy,
1671                         rmInst->u.server.policySize);
1672         }
1673     }
1674     else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1675         rmAllocatorDeleteTree(rmHandle);
1676         rmInst->u.cd.allocatorTree = NULL;
1677     }
1679     if (rmInst->instType != Rm_instType_SHARED_CLIENT) {
1680         /* Delete valid instance tree */
1681         rmPolicyFreeValidInstTree(rmHandle);
1683         /* Delete any transactions */
1684         while(rmInst->transactionQueue) {
1685             rmTransactionQueueDelete(rmInst, rmInst->transactionQueue->localId);
1686         }
1688         if (rmInst->instType != Rm_instType_SHARED_SERVER) {
1689             /* Delete the instance's task blocking mechanism */
1690             Rm_osalTaskBlockDelete(rmInst->blockHandle);
1691         }
1692         else {
1693             Rm_osalEndMemAccess((void *)rmInst, sizeof(Rm_Inst));
1694         }
1695     }
1697     Rm_osalFree((void *)rmInst, sizeof(Rm_Inst));
1698    
1699     Rm_osalCsExit(key);
1700     return (RM_OK);
1703 /* FUNCTION PURPOSE: Returns RM version information
1704  ***********************************************************************
1705  */
1706 uint32_t Rm_getVersion(void)
1708     return RM_VERSION_ID;
1711 /* FUNCTION PURPOSE: Returns RM version string
1712  ***********************************************************************
1713  */
1714 const char* Rm_getVersionStr(void)
1716     return rmVersionStr;