c539fe42ecb5cc6462826c353c7cd967abe9819d
[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 static Rm_Packet *createResourceReqPkt(Rm_ResourceReqPktType resReqType,
113                                        Rm_Transport *dstTrans,
114                                        const char *locInstName,
115                                        Rm_Transaction *transaction,
116                                        Rm_PacketHandle *pktHandle)
118     Rm_Packet             *rmPkt = NULL;
119     Rm_ResourceRequestPkt *resourceReqPkt = NULL;
121     rmPkt = dstTrans->callouts.rmAllocPkt(dstTrans->appTransportHandle,
122                                           sizeof(Rm_Packet), pktHandle);
123     if ((rmPkt == NULL) || (pktHandle == NULL)) {
124         transaction->state = RM_ERROR_TRANSPORT_ALLOC_PKT_ERROR;
125         goto errorExit;
126     }
128     rmPkt->pktType = Rm_pktType_RESOURCE_REQUEST;
129     resourceReqPkt = (Rm_ResourceRequestPkt *) rmPkt->data;
130     resourceReqPkt->requestId       = transaction->localId;
131     resourceReqPkt->resourceReqType = resReqType;
132     rm_strncpy(resourceReqPkt->pktSrcInstName, locInstName,
133                RM_NAME_MAX_CHARS);
134     rm_strncpy(resourceReqPkt->serviceSrcInstName,
135                transaction->serviceSrcInstName, RM_NAME_MAX_CHARS);
136     memcpy((void *)&(resourceReqPkt->resourceInfo),
137            (void *)&(transaction->resourceInfo),
138            sizeof(Rm_ResourceInfo));
140 errorExit:
141     return(rmPkt);
144 /* FUNCTION PURPOSE: Creates a resource response packet
145  ***********************************************************************
146  * DESCRIPTION: Returns a RM packet handle that points to a RM
147  *              resource response packet that has been prepared
148  *              for sending to another RM instance.  The packet
149  *              is allocated via the rmAllocPkt API using the
150  *              appTransport handle provided by the application
151  */
152 static void createResourceResponsePkt(Rm_Packet *rmPkt,
153                                       Rm_Transaction *transaction)
155     Rm_ResourceResponsePkt *resourceRespPkt = NULL;
157     rmPkt->pktType = Rm_pktType_RESOURCE_RESPONSE;
158     resourceRespPkt = (Rm_ResourceResponsePkt *)rmPkt->data;
159     resourceRespPkt->responseId = transaction->remoteOriginatingId;
160     resourceRespPkt->requestState = transaction->state;
161     memcpy((void *)&(resourceRespPkt->resourceInfo),
162            (void *)&(transaction->resourceInfo),
163            sizeof(Rm_ResourceInfo));
166 /* FUNCTION PURPOSE: Creates a NameServer request packet
167  ***********************************************************************
168  * DESCRIPTION: Returns a RM packet handle that points to a RM
169  *              NameServer request packet that has been prepared
170  *              for sending to another RM instance.  The packet
171  *              is allocated via the rmAllocPkt API using the
172  *              appTransport handle provided by the application
173  */
174 static Rm_Packet *createNsRequestPkt(Rm_NsReqPktType nsReqType,
175                                      Rm_Transport *dstTrans,
176                                      const char *locInstName,
177                                      Rm_Transaction *transaction,
178                                      Rm_PacketHandle *pktHandle)
180     Rm_Packet       *rmPkt = NULL;
181     Rm_NsRequestPkt *nsReqPkt = NULL;
184     rmPkt = dstTrans->callouts.rmAllocPkt(dstTrans->appTransportHandle,
185                                           sizeof(Rm_Packet), pktHandle);
186     if ((rmPkt == NULL) || (pktHandle == NULL)) {
187         transaction->state = RM_ERROR_TRANSPORT_ALLOC_PKT_ERROR;
188         goto errorExit;
189     }
191     rmPkt->pktType = Rm_pktType_NAMESERVER_REQUEST;
192     nsReqPkt = (Rm_NsRequestPkt *)rmPkt->data;
193     nsReqPkt->requestId     = transaction->localId;
194     nsReqPkt->nsRequestType = nsReqType;
195     rm_strncpy(nsReqPkt->pktSrcInstName, locInstName, RM_NAME_MAX_CHARS);
196     rm_strncpy(nsReqPkt->serviceSrcInstName, transaction->serviceSrcInstName,
197                RM_NAME_MAX_CHARS);
198     memcpy((void *)&(nsReqPkt->resourceInfo),
199            (void *)&(transaction->resourceInfo),
200            sizeof(Rm_ResourceInfo));
202 errorExit:
203     return(rmPkt);
206 /* FUNCTION PURPOSE: Creates a NameServer response packet
207  ***********************************************************************
208  * DESCRIPTION: Returns a RM packet handle that points to a RM
209  *              NameServer response packet that has been prepared
210  *              for sending to another RM instance.  The packet
211  *              is allocated via the rmAllocPkt API using the
212  *              appTransport handle provided by the application
213  */
214 static void createNsResponsePkt(Rm_Packet *rmPkt, Rm_Transaction *transaction)
216     Rm_NsResponsePkt *nsRespPkt = NULL;
218     rmPkt->pktType = Rm_pktType_NAMESERVER_RESPONSE;
219     nsRespPkt = (Rm_NsResponsePkt *)rmPkt->data;
220     nsRespPkt->responseId = transaction->remoteOriginatingId;
221     nsRespPkt->requestState = transaction->state;
224 /* FUNCTION PURPOSE: Creates a request packet
225  ***********************************************************************
226  * DESCRIPTION: Returns a RM packet handle that points to a request packet.
227  *              The request packet type is based on the transaction type.
228  */
229 static Rm_Packet *createRequestPkt(Rm_Transport *dstTrans,
230                                    const char *locInstName,
231                                    Rm_Transaction *transaction,
232                                    Rm_PacketHandle *pktHandle)
234     Rm_Packet *rmPkt = NULL;
236     switch (transaction->type) {
237         case Rm_service_RESOURCE_ALLOCATE_INIT:
238             rmPkt = createResourceReqPkt(Rm_resReqPktType_ALLOCATE_INIT,
239                                          dstTrans, locInstName, transaction,
240                                          pktHandle);
241             break;
242         case Rm_service_RESOURCE_ALLOCATE_USE:
243             rmPkt = createResourceReqPkt(Rm_resReqPktType_ALLOCATE_USE,
244                                          dstTrans, locInstName, transaction,
245                                          pktHandle);
246             break;
247         case Rm_service_RESOURCE_STATUS:
248             rmPkt = createResourceReqPkt(Rm_resReqPktType_GET_STATUS,
249                                          dstTrans, locInstName, transaction,
250                                          pktHandle);
251             break;
252         case Rm_service_RESOURCE_FREE:
253             rmPkt = createResourceReqPkt(Rm_resReqPktType_FREE,
254                                          dstTrans, locInstName, transaction,
255                                          pktHandle);
256             break;
257         case Rm_service_RESOURCE_GET_BY_NAME:
258             rmPkt = createResourceReqPkt(Rm_resReqPktType_GET_NAMED,
259                                          dstTrans, locInstName, transaction,
260                                          pktHandle);
261             break;
262         case Rm_service_RESOURCE_MAP_TO_NAME:
263             rmPkt = createNsRequestPkt(Rm_nsReqPktType_MAP_RESOURCE,
264                                        dstTrans, locInstName, transaction,
265                                        pktHandle);
266             break;
267         case Rm_service_RESOURCE_UNMAP_NAME:
268             rmPkt = createNsRequestPkt(Rm_nsReqPktType_UNMAP_RESOURCE,
269                                        dstTrans, locInstName, transaction,
270                                        pktHandle);
271             break;
272         default:
273             transaction->state = RM_ERROR_INVALID_SERVICE_TYPE;
274             break;
275     }
277     return(rmPkt);
280 /* FUNCTION PURPOSE: Issues a service response to application
281  ***********************************************************************
282  * DESCRIPTION: Provides a service response back to the application
283  *              using the service callback function provided to
284  *              the RM instance at the time of the service request.
285  */
286 static void serviceResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)
288     Rm_ServiceRespInfo serviceResponse;
290     serviceResponse.rmHandle = (Rm_Handle)rmInst;
291     /* The responseTransaction will contain the resultant state details of
292      * the requestTransaction's service request */
293     serviceResponse.serviceState = transaction->state;
294     /* Pass back the ID that was provided to the component when it requested
295      * the service */
296     serviceResponse.serviceId = transaction->localId;
297     /* Owner and instance allocation count will only be set within RM under
298      * certain circumstances. */
299     serviceResponse.resourceNumOwners = transaction->resourceInfo.ownerCount;
300     serviceResponse.instAllocCount = transaction->resourceInfo.instAllocCount;
302     /* Service was approved and service was an allocate request.  The resource
303      * data is passed back to the component */
304     if ((serviceResponse.serviceState == RM_SERVICE_APPROVED) &&
305         ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||
306          (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) ||
307          (transaction->type == Rm_service_RESOURCE_FREE) ||
308          (transaction->type == Rm_service_RESOURCE_STATUS) ||
309          (transaction->type == Rm_service_RESOURCE_GET_BY_NAME))) {
310         rm_strncpy(serviceResponse.resourceName, transaction->resourceInfo.name,
311                    RM_NAME_MAX_CHARS);
312         serviceResponse.resourceBase = transaction->resourceInfo.base;
313         serviceResponse.resourceLength = transaction->resourceInfo.length;
314     }
316     if (transaction->u.callback.serviceCallback) {
317         /* Issue the callback to the requesting component with the response
318          * information */
319         transaction->u.callback.serviceCallback(&serviceResponse);
320         /* Delete the transaction from the transaction queue */
321         rmTransactionQueueDelete(rmInst, transaction->localId);
322     } else {
323         rmServiceInternalCallback((Rm_Handle)rmInst);
324     }
326     return;
329 /* FUNCTION PURPOSE: Sends RM response packets
330  ***********************************************************************
331  * DESCRIPTION: Sends RM response packets to RM instance's that sent
332  *              RM request packets to the RM instance.  The response
333  *              is sent via the RM transport API which is plugged
334  *              with an application created transport path.
335  */
336 static void transactionResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)
338     Rm_Transport    *dstTransport = transaction->u.respTrans;
339     Rm_Packet       *rmPkt = NULL;
340     Rm_PacketHandle  pktHandle = NULL;
342     rmPkt = dstTransport->callouts.rmAllocPkt(dstTransport->appTransportHandle,
343                                               sizeof(Rm_Packet), &pktHandle);
344     if (!rmPkt || !pktHandle) {
345         transaction->state = RM_ERROR_TRANSPORT_ALLOC_PKT_ERROR;
346         goto errorExit;
347     }
349     switch (transaction->type) {
350         case Rm_service_RESOURCE_ALLOCATE_INIT:
351         case Rm_service_RESOURCE_ALLOCATE_USE:
352         case Rm_service_RESOURCE_STATUS:
353         case Rm_service_RESOURCE_FREE:
354         case Rm_service_RESOURCE_GET_BY_NAME:
355             createResourceResponsePkt(rmPkt, transaction);
356             break;
357         case Rm_service_RESOURCE_MAP_TO_NAME:
358         case Rm_service_RESOURCE_UNMAP_NAME:
359             createNsResponsePkt(rmPkt, transaction);
360             break;
361         default:
362             transaction->state = RM_ERROR_INVALID_SERVICE_TYPE;
363             goto errorExit;
364     }
365     if (dstTransport->callouts.rmSendPkt(dstTransport->appTransportHandle,
366                                          pktHandle) < RM_OK) {
367         transaction->state = RM_ERROR_TRANSPORT_SEND_ERROR;
368         goto errorExit;
369     }
371     /* Response packet sent: Delete transaction from queue */
372     rmTransactionQueueDelete(rmInst, transaction->localId);
374 errorExit:
375     /* Do not delete transaction on transport error.  Transport error
376      * transactions should be visible from Rm_printInstanceStatus() */
377     return;
380 /* FUNCTION PURPOSE: Sends RM request packets
381  ***********************************************************************
382  * DESCRIPTION: Sends RM request packets to RM instance's that are
383  *              capable of forwarding or validating service requests.
384  *              The request is sent via the RM transport API which is
385  *              plugged with an application created transport path.
386  */
387 static void transactionForwarder(Rm_Inst *rmInst, Rm_Transaction *transaction)
389     Rm_Transport *dstTrans;
391     if (rmInst->instType == Rm_instType_CLIENT) {
392         dstTrans = rmTransportFindRemoteInstType(rmInst->transports,
393                                                  Rm_instType_CLIENT_DELEGATE);
394         if (dstTrans == NULL) {
395             dstTrans = rmTransportFindRemoteInstType(rmInst->transports,
396                                                      Rm_instType_SERVER);
397         }
398     } else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
399         dstTrans = rmTransportFindRemoteInstType(rmInst->transports,
400                                                  Rm_instType_SERVER);
401     } else {
402         dstTrans = NULL;
403     }
405     /* Just queue transaction if transport hasn't been registered.  Do not
406      * return error */
407     if (dstTrans) {
408         Rm_Packet       *rmPkt = NULL;
409         Rm_PacketHandle  pktHandle = NULL;
411         rmPkt = createRequestPkt(dstTrans, rmInst->instName, transaction,
412                                  &pktHandle);
413         if ((rmPkt == NULL) || (pktHandle == NULL)) {
414             /* Error returned via transaction->state */
415             goto errorExit;
416         }
418         if (dstTrans->callouts.rmSendPkt(dstTrans->appTransportHandle,
419                                          pktHandle) < RM_OK) {
420             transaction->state = RM_ERROR_TRANSPORT_SEND_ERROR;
421             goto errorExit;
422         }
423         transaction->hasBeenForwarded = RM_TRUE;
424         /* Transaction not deleted.  Waiting for response from RM CD or
425          * Server */
426     } else {
427         transaction->state = RM_ERROR_TRANSPORT_HANDLE_DOES_NOT_EXIST;
428     }
429 errorExit:
430     /* Do not delete transaction on transport error.  Transport error
431      * transactions should be visible from Rm_printInstanceStatus() */
432     return;
435 /* FUNCTION PURPOSE: Handles static allocation requests
436  ***********************************************************************
437  * DESCRIPTION: Validates allocation requests received on CDs and
438  *              Clients prior to the instance's registering
439  *              with a Server.  The allocation request is validated
440  *              against a static policy.
441  */
442 static void staticAllocationHandler(Rm_Handle rmHandle,
443                                     Rm_Transaction *transaction)
445     Rm_Inst           *rmInst = (Rm_Inst *)rmHandle;
446     Rm_AllocatorNode  *allocNode = NULL;
447     Rm_PolicyCheckCfg  privCheckCfg;
449     if (rmInst->allocatorTree) {
450         allocNode = rmAllocatorFind(rmHandle, transaction->resourceInfo.name);
452         if (allocNode &&
453             ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||
454              (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE))) {
455             /* Check request against static policy */
456             memset((void *)&privCheckCfg, 0, sizeof(Rm_PolicyCheckCfg));
458             if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
459                 privCheckCfg.type = Rm_policyCheck_INIT;
460             } else {
461                 privCheckCfg.type = Rm_policyCheck_USE;
462             }
463             privCheckCfg.validInstNode  = rmPolicyGetValidInstNode(rmHandle,
464                                                               rmInst->instName);
465             privCheckCfg.polTree        = allocNode->policyRoot;
466             privCheckCfg.resourceBase   = transaction->resourceInfo.base;
467             privCheckCfg.resourceLength = transaction->resourceInfo.length;
469             if (rmPolicyCheckPrivilege(&privCheckCfg)) {
470                 transaction->state = RM_SERVICE_APPROVED_STATIC;
471             } else {
472                 transaction->state = RM_SERVICE_DENIED_BY_STATIC_POLICY;
473             }
474         } else {
475             transaction->state = RM_SERVICE_DENIED_INVALID_STATIC_REQUEST;
476         }
477     } else {
478         transaction->state = RM_ERROR_REQ_FAILED_NO_STATIC_POLICY;
479     }
482 /* FUNCTION PURPOSE: Requests resources from Server for CD
483  ***********************************************************************
484  * DESCRIPTION: Function creates a service request to allocate resources
485  *              from the Server for local management by the CD.  The
486  *              transaction which causes this request is put in the
487  *              pending state in order to wait for the response from the 
488  *              Server
489  */
490 static int32_t cdRequestServerResources(Rm_Inst *rmInst,
491                                         Rm_Transaction *transaction)
493     Rm_AllocatorNode *allocNode = NULL;
494     Rm_Transaction   *newTrans = NULL;
495     uint32_t          allocSize = 0;
496     int32_t           retVal;
498     allocNode = rmAllocatorFind((Rm_Handle)rmInst,
499                                 transaction->resourceInfo.name);
501     if (allocNode) {
502         if ((allocSize = rmPolicyGetCdAllocSize(allocNode->policyRoot))) {
503             if ((newTrans = rmTransactionQueueAdd(rmInst))) {
504                 newTrans->type = transaction->type;
505                 rm_strncpy(newTrans->serviceSrcInstName, rmInst->instName,
506                            RM_NAME_MAX_CHARS);
507                 newTrans->state = RM_SERVICE_PROCESSING;
508                 rm_strncpy(newTrans->resourceInfo.name,
509                            transaction->resourceInfo.name,
510                            RM_NAME_MAX_CHARS);
511                 newTrans->resourceInfo.base = RM_RESOURCE_BASE_UNSPECIFIED;
512                 /* Make sure request length will satisfy transaction length */
513                 newTrans->resourceInfo.length = allocSize;
514                 while (newTrans->resourceInfo.length <
515                        transaction->resourceInfo.length) {
516                     newTrans->resourceInfo.length += allocSize;
517                 }
518                 newTrans->resourceInfo.alignment = transaction->resourceInfo.alignment;
519                 newTrans->pendingTransactionId = transaction->localId;
520                 transactionForwarder(rmInst, newTrans);
522                 retVal = RM_SERVICE_PENDING_SERVER_RESPONSE;
523             } else {
524                 retVal = RM_ERROR_TRANS_REQ_TO_SERVER_NOT_CREATED;
525             }
526         } else {
527             /* Forward request to Server for completion if policy has 
528              * no allocation size for resource */
529             retVal = RM_SERVICE_PROCESSING;
530         }
531     } else {
532         /* Resource could not be found in policy */
533         retVal = RM_SERVICE_DENIED_RES_DOES_NOT_EXIST;
534     }
535     return(retVal);
538 /* FUNCTION PURPOSE: Frees local resources to Server from CD
539  ***********************************************************************
540  * DESCRIPTION: Function creates a service request to free locally
541  *              managed resources that are now localized back to
542  *              the Server.
543  */
544 static int32_t cdFreeResourcesToServer(Rm_Inst *rmInst,
545                                        Rm_Transaction *transaction)
547     int32_t         baseToFree = transaction->resourceInfo.base;
548     uint32_t        lenToFree = transaction->resourceInfo.length;
549     Rm_Transaction *newTrans = NULL; 
550     /* This function should only be called after a free was approved */
551     int32_t         retVal = RM_SERVICE_APPROVED;    
553     /* Did free result in a localized free node that can be given back to
554      * Server?  If so create transaction to Server to free localized
555      * resource node */
556     if (rmAllocatorGetNodeLocalization((Rm_Handle)rmInst,
557                                        transaction->resourceInfo.name,
558                                        &baseToFree, &lenToFree)) {
559         if ((newTrans = rmTransactionQueueAdd(rmInst))) {
560             newTrans->type = transaction->type;
561             rm_strncpy(newTrans->serviceSrcInstName, rmInst->instName,
562                        RM_NAME_MAX_CHARS);
563             newTrans->state = RM_SERVICE_PROCESSING;
564             rm_strncpy(newTrans->resourceInfo.name,
565                        transaction->resourceInfo.name, RM_NAME_MAX_CHARS);
566             newTrans->resourceInfo.base = baseToFree;
567             newTrans->resourceInfo.length = lenToFree;
568             newTrans->pendingTransactionId = transaction->localId;
569             transactionForwarder(rmInst, newTrans);
571             retVal = RM_SERVICE_PENDING_SERVER_RESPONSE;
572         } else {
573             /* Error: Need to re-allocate what was freed */
574             retVal = RM_ERROR_TRANS_REQ_TO_SERVER_NOT_CREATED;
575         }
576     }
577     return(retVal);
580 /* FUNCTION PURPOSE: Arbitrates allocation service requests
581  ***********************************************************************
582  * DESCRIPTION: Issues a set of allocator operations in order to
583  *              handle a received allocation request.  Allocation
584  *              requests are always forwarded to the Server on Client
585  *              CD instances.  If a request is made with a NameServer
586  *              name the resource base and length parameters are
587  *              retrieved from the NameServer prior to the allocation
588  *              attempt.
589  */
590 static void allocationHandler (Rm_Inst *rmInst, Rm_Transaction *transaction)
592     Rm_AllocatorOpInfo   opInfo;
593     Rm_NameServerObjCfg  nameServerObjCfg;
594     int32_t              retVal = transaction->state;
596     memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));
597     opInfo.resourceInfo = &transaction->resourceInfo;
598     opInfo.serviceInstNode = rmPolicyGetValidInstNode((Rm_Handle)rmInst,
599                                               transaction->serviceSrcInstName);
600     if (opInfo.serviceInstNode == NULL) {
601         retVal = RM_SERVICE_DENIED_INST_NAME_NOT_VALID;
602         goto errorExit;
603     }
605     if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
606         if (transaction->resourceInfo.base != RM_RESOURCE_BASE_UNSPECIFIED) {
607             if (rmAllocatorFind((Rm_Handle)rmInst,
608                                 transaction->resourceInfo.name)) {
609                 /* Attempt to allocate from local resources that were provided
610                  * by Server */
611                 if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
612                     opInfo.operation = Rm_allocatorOp_ALLOCATE_INIT;
613                 } else if (transaction->type ==
614                            Rm_service_RESOURCE_ALLOCATE_USE) {
615                     opInfo.operation = Rm_allocatorOp_ALLOCATE_USE;
616                 } else {
617                     retVal = RM_ERROR_INVALID_SERVICE_TYPE;
618                     goto errorExit;
619                 }
620                 retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
622                 if (retVal == RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST) {
623                     /* Request resource range was not found within local
624                      * resources provided by Server.  Set back to PROCESSING so
625                      * request is forwarded to Server */
626                     retVal = RM_SERVICE_PROCESSING;
627                 }
628             }
629         } else {
630             if (rmAllocatorFind((Rm_Handle)rmInst,
631                                 transaction->resourceInfo.name)) {
632                 int32_t oldAlign = transaction->resourceInfo.alignment;
634                 /* Attempt to allocate from local resources that were provided
635                  * by Server */
636                 if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
637                     opInfo.operation = Rm_allocatorOp_PRE_ALLOCATE_INIT;
638                 } else if (transaction->type ==
639                          Rm_service_RESOURCE_ALLOCATE_USE) {
640                     opInfo.operation = Rm_allocatorOp_PRE_ALLOCATE_USE;
641                 } else {
642                     retVal = RM_ERROR_INVALID_SERVICE_TYPE;
643                     goto errorExit;
644                 }
645                 retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
647                 if (retVal == RM_SERVICE_PROCESSING) {
648                     if (transaction->type ==
649                         Rm_service_RESOURCE_ALLOCATE_INIT) {
650                         opInfo.operation = Rm_allocatorOp_ALLOCATE_INIT;
651                     } else if (transaction->type ==
652                                Rm_service_RESOURCE_ALLOCATE_USE) {
653                         opInfo.operation = Rm_allocatorOp_ALLOCATE_USE;
654                     } else {
655                         retVal = RM_ERROR_INVALID_SERVICE_TYPE;
656                         goto errorExit;
657                     }
658                     retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
660                     if (retVal == RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST) {
661                         /* Request resource range was not found within local
662                          * resources provided by Server.  Set back to
663                          * PROCESSING so request is forwarded to Server */
664                         retVal = RM_SERVICE_PROCESSING;
665                     }
666                 } else if (retVal == RM_SERVICE_DENIED_RES_ALLOC_REQS_NOT_MET) {
667                     if (transaction->pendingTransactionId) {
668                         /* Request to Server for resources to complete
669                          * transaction locally performed once already.  Forward
670                          * transaction to Server for completion */
671                         retVal = RM_SERVICE_PROCESSING;
672                     } else {
673                         /* Restore base and alignment since they were replaced
674                          * in pre-allocate routine */
675                         transaction->resourceInfo.base = RM_RESOURCE_BASE_UNSPECIFIED;
676                         transaction->resourceInfo.alignment = oldAlign;
678                         retVal = cdRequestServerResources(rmInst, transaction);
679                     }
680                 }
681                 /* else: fall through to return */
682             } else {
683                 retVal = cdRequestServerResources(rmInst, transaction);
684             }
685         }
686     } else if ((rmInst->instType == Rm_instType_SERVER)||
687                (rmInst->instType == Rm_instType_SHARED_SERVER)) {
688         /* Populated NameServer name has precedence over base */
689         if (strlen(transaction->resourceInfo.nameServerName) > 0) {
690             if (rmInst->instType == Rm_instType_SHARED_SERVER) {
691                 rmNameServerTreeInv(rmInst->u.server.nameServer);
692             }
693             memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
694             nameServerObjCfg.nameServerTree = rmInst->u.server.nameServer;
695             nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
696             if ((retVal = rmNameServerFindObject(&nameServerObjCfg)) ==
697                 RM_SERVICE_PROCESSING) {
698                 rm_strncpy(transaction->resourceInfo.name,
699                            nameServerObjCfg.nodeCfg.resourceName,
700                            RM_NAME_MAX_CHARS);
701                 transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;
702                 transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;
703             } else {
704                 goto errorExit;
705             }
706         }
708         if (transaction->resourceInfo.base == RM_RESOURCE_BASE_UNSPECIFIED) {
709             if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
710                 opInfo.operation = Rm_allocatorOp_PRE_ALLOCATE_INIT;
711             } else if (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) {
712                 opInfo.operation = Rm_allocatorOp_PRE_ALLOCATE_USE;
713             } else {
714                 retVal = RM_ERROR_INVALID_SERVICE_TYPE;
715                 goto errorExit;
716             }
717             retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
718         }
720         if (retVal == RM_SERVICE_PROCESSING) {
721             if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
722                 opInfo.operation = Rm_allocatorOp_ALLOCATE_INIT;
723             } else if (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) {
724                 opInfo.operation = Rm_allocatorOp_ALLOCATE_USE;
725             } else {
726                 retVal = RM_ERROR_INVALID_SERVICE_TYPE;
727                 goto errorExit;
728             }
729             retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
730         }
731     } else {
732         retVal = RM_ERROR_INVALID_INST_TYPE;
733     }
734 errorExit:
735     transaction->state = retVal;
738 /* FUNCTION PURPOSE: Handles resource status service requests
739  ***********************************************************************
740  * DESCRIPTION: Issues a set of allocator operations to retrieve the
741  *              current status (currently just owner reference count)
742  *              for the resource specified in the transaction
743  */
744 static void statusHandler(Rm_Inst *rmInst, Rm_Transaction *transaction)
746     Rm_AllocatorOpInfo  opInfo;
747     Rm_NameServerObjCfg nameServerObjCfg;
748     int32_t             retVal = transaction->state;
750     memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));
751     opInfo.operation = Rm_allocatorOp_GET_STATUS;
752     opInfo.resourceInfo = &transaction->resourceInfo;
753     opInfo.serviceInstNode = rmPolicyGetValidInstNode((Rm_Handle)rmInst,
754                                             transaction->serviceSrcInstName);
755     if (opInfo.serviceInstNode == NULL) {
756         retVal = RM_SERVICE_DENIED_INST_NAME_NOT_VALID;
757         goto errorExit;
758     }
760     if ((strlen(transaction->resourceInfo.nameServerName) == 0) &&
761         ((transaction->resourceInfo.base == RM_RESOURCE_BASE_UNSPECIFIED) ||
762          (transaction->resourceInfo.length == 0))) {
763         retVal = RM_SERVICE_DENIED_RES_DOES_NOT_EXIST;
764         goto errorExit;
765     }
767     if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
768         if (rmAllocatorFind((Rm_Handle)rmInst,
769                             transaction->resourceInfo.name)) {
770             /* Attempt to get status from local resources that were provided by
771              * Server */
772             retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
774             if (retVal == RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST) {
775                 /* Request resource range was not found within local allocator
776                  * resources provided by Server.  Set back to PROCESSING so
777                  * request is forwarded to Server */
778                 retVal = RM_SERVICE_PROCESSING;
779             }
780         }
781     } else if ((rmInst->instType == Rm_instType_SERVER)||
782                (rmInst->instType == Rm_instType_SHARED_SERVER)) {
783         /* Populated NameServer name has precedence over base and length
784          * values */
785         if (strlen(transaction->resourceInfo.nameServerName) > 0) {
786             if (rmInst->instType == Rm_instType_SHARED_SERVER) {
787                 rmNameServerTreeInv(rmInst->u.server.nameServer);
788             }
789             memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
790             nameServerObjCfg.nameServerTree = rmInst->u.server.nameServer;
791             nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
792             if ((retVal = rmNameServerFindObject(&nameServerObjCfg)) ==
793                 RM_SERVICE_PROCESSING) {
794                 rm_strncpy(transaction->resourceInfo.name,
795                            nameServerObjCfg.nodeCfg.resourceName,
796                            RM_NAME_MAX_CHARS);
797                 transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;
798                 transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;
799             } else {
800                 goto errorExit;
801             }
802         }
803         retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
804     } else {
805         retVal = RM_ERROR_INVALID_INST_TYPE;
806     }
807 errorExit:
808     transaction->state = retVal;
811 /* FUNCTION PURPOSE: Arbitrates free service requests
812  ***********************************************************************
813  * DESCRIPTION: Issues a set of allocator operations in order to
814  *              handle a received free request.  Free
815  *              requests are always forwarded to the Server on Client
816  *              CD instances.  If a request is made with a NameServer
817  *              name the resource base and length parameters are
818  *              retrieved from the NameServer prior to the free
819  *              attempt.
820  */
821 static void freeHandler(Rm_Inst *rmInst, Rm_Transaction *transaction)
823     Rm_AllocatorOpInfo  opInfo; 
824     Rm_NameServerObjCfg nameServerObjCfg;
825     int32_t             retVal = transaction->state;
827     memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));
828     opInfo.operation = Rm_allocatorOp_FREE;
829     opInfo.resourceInfo = &transaction->resourceInfo;
830     opInfo.serviceInstNode = rmPolicyGetValidInstNode((Rm_Handle)rmInst,
831                                             transaction->serviceSrcInstName);
832     if (opInfo.serviceInstNode == NULL) {
833         retVal = RM_SERVICE_DENIED_INST_NAME_NOT_VALID;
834         goto errorExit;
835     }
837     if ((strlen(transaction->resourceInfo.nameServerName) == 0) &&
838         ((transaction->resourceInfo.base == RM_RESOURCE_BASE_UNSPECIFIED) ||
839          (transaction->resourceInfo.length == 0))) {
840         retVal = RM_SERVICE_DENIED_RES_DOES_NOT_EXIST;
841         goto errorExit;
842     }
844     if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
845         /* Attempt to free from local resources that were provided by Server */
846         retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
848         if (retVal == RM_SERVICE_APPROVED) {
849             /* Check if free allows local resources to be freed back to
850              * Server */
851             retVal = cdFreeResourcesToServer(rmInst, transaction);
852         } else if ((retVal == RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST) ||
853                  (retVal == RM_SERVICE_DENIED_RES_DOES_NOT_EXIST)) {
854             /* Requested resource or its range were not found within local
855              * allocator resources provided by Server.  Set back to PROCESSING
856              * so request is forwarded to Server */
857             retVal = RM_SERVICE_PROCESSING;
858         }
859         /* else: fall through to exit */
860     } else if ((rmInst->instType == Rm_instType_SERVER) ||
861              (rmInst->instType == Rm_instType_SHARED_SERVER)) {
862         /* Populated NameServer name has precedence over base */
863         if (strlen(transaction->resourceInfo.nameServerName) > 0) {
864             if (rmInst->instType == Rm_instType_SHARED_SERVER) {
865                 rmNameServerTreeInv(rmInst->u.server.nameServer);
866             }                    
867             memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
868             nameServerObjCfg.nameServerTree = rmInst->u.server.nameServer;
869             nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
870             if ((retVal = rmNameServerFindObject(&nameServerObjCfg)) ==
871                 RM_SERVICE_PROCESSING) {
872                 rm_strncpy(transaction->resourceInfo.name,
873                            nameServerObjCfg.nodeCfg.resourceName,
874                            RM_NAME_MAX_CHARS);
875                 transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;
876                 transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;
877             } else {
878                 goto errorExit;
879             }
880         }
881         retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
882     } else {
883         retVal = RM_ERROR_INVALID_INST_TYPE;
884     }
885 errorExit:
886     transaction->state = retVal;
889 /* FUNCTION PURPOSE: Client transaction handling process
890  ***********************************************************************
891  * DESCRIPTION: Client process for handling transactions created
892  *              from services received via the service handle or the
893  *              transport.  The Client process:
894  *                  - Performs static allocations if no transport
895  *                    to CD or Server has been registered
896  *                  - Forwards all service requests to CD or Server
897  *                    once transport has been registered
898  */
899 static void clientProcess(Rm_Inst *rmInst, Rm_Transaction *transaction)
901     Rm_Transaction *transQ;
903     if (!rmInst->registeredWithDelegateOrServer) {
904         staticAllocationHandler((Rm_Handle)rmInst, transaction);
905     } else {
906         if (transaction->state == RM_SERVICE_PROCESSING) {
907             /* Forward all new transactions to CD or Server */
908             transactionForwarder(rmInst, transaction);
909         } else {
910             /* Transaction validated.  Return result. */
911             serviceResponder(rmInst, transaction);
912         }
914         /* Forward any queued static requests that weren't forwarded */
915         transQ = rmInst->transactionQueue;
916         while(transQ) {
917             if ((transQ->state == RM_SERVICE_APPROVED_STATIC) &&
918                 (!transQ->hasBeenForwarded)) {
919                 transactionForwarder(rmInst, transQ);
920             }
921             transQ = transQ->nextTransaction;
922         }
923     }
924     /* Let call stack return transaction result app via Rm_serviceHandler */
927 /* FUNCTION PURPOSE: Client Delegate transaction handling process
928  ***********************************************************************
929  * DESCRIPTION: Client Delegate process for handling transactions created
930  *              from services received via the service handle or the
931  *              transport.  The Client Delegate process:
932  *                  - Performs static allocations if no transport
933  *                    to Server has been registered
934  *                  - Forwards all NameServer related service requests 
935  *                    to Server once transport has been registered
936  *                  - Attempts to complete resource service requests
937  *                    received from registered Clients
938  */
939 static void cdProcess(Rm_Inst *rmInst, Rm_Transaction *transaction)
940 {      
941     Rm_Transaction   *newTrans = NULL;
942     Rm_AllocatorNode *allocator = NULL;
943     Rm_Transaction   *transQ;
945     if (!rmInst->registeredWithDelegateOrServer) {
946         if ((transaction->state == RM_SERVICE_PROCESSING) &&
947             (strncmp(transaction->serviceSrcInstName, rmInst->instName,
948              RM_NAME_MAX_CHARS) == 0)) {
949             /* Attempt static allocation of requests originating from CD inst */
950             staticAllocationHandler((Rm_Handle)rmInst, transaction);
951         }
952         /* Everything else left in transaction queue for forwarding once
953          * transport to Server is registered */
954     } else {
955         if (transaction->pendingTransactionId) {
956             Rm_Transaction *pendingTrans = rmTransactionQueueFind(rmInst,
957                                              transaction->pendingTransactionId);
959             /* Transaction is response from Server for transaction sent to get
960              * information in order to complete pending transaction */
961             if (transaction->state == RM_SERVICE_APPROVED) {
962                 if (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) {
963                     /* Transfer resource data tied to name to pending
964                      * transaction */
965                     rm_strncpy(pendingTrans->resourceInfo.name,
966                                transaction->resourceInfo.name,
967                                RM_NAME_MAX_CHARS);
968                     pendingTrans->resourceInfo.base   = transaction->resourceInfo.base;
969                     pendingTrans->resourceInfo.length = transaction->resourceInfo.length;
970                     /* Delete NS name from pending transaction so Server isn't
971                      * queried again */
972                     memset(pendingTrans->resourceInfo.nameServerName, 0,
973                            RM_NAME_MAX_CHARS);
974                     /* Now that resource values have been retrieved clear
975                      * pending transaction ID so CD doesn't think a resource
976                      * request was sent to Server already for more local
977                      * resources */
978                     pendingTrans->pendingTransactionId = 0;
980                     /* Return original transaction to processing state to
981                      * attempt completion. */
982                     pendingTrans->state = RM_SERVICE_PROCESSING;
983                 } else if ((transaction->type ==
984                             Rm_service_RESOURCE_ALLOCATE_INIT) ||
985                            (transaction->type ==
986                             Rm_service_RESOURCE_ALLOCATE_USE)) {
987                     /* Add resources provided by Server to those managed by
988                      * CD */
989                     if ((allocator = rmAllocatorFind((Rm_Handle)rmInst,
990                                              transaction->resourceInfo.name))) {
991                         rmAllocatorAddResNode((Rm_Handle)rmInst,
992                                               allocator,
993                                               transaction->resourceInfo.base,
994                                               transaction->resourceInfo.length);
995                     }
997                     /* Return original transaction to processing state to
998                      * attempt completion */
999                     pendingTrans->state = RM_SERVICE_PROCESSING;
1000                 } else if (transaction->type == Rm_service_RESOURCE_FREE) {
1001                     allocator = rmAllocatorFind((Rm_Handle)rmInst,
1002                                                 transaction->resourceInfo.name);
1004                     /* Local resource freed on Server.  Remove node in
1005                      * local allocator's resource tree as well */
1006                     rmAllocatorDeleteResNode((Rm_Handle)rmInst,
1007                                              allocator,
1008                                              transaction->resourceInfo.base,
1009                                              transaction->resourceInfo.length);
1011                     /* Allow original free to complete */
1012                     pendingTrans->state = RM_SERVICE_APPROVED;
1013                 } else {
1014                     pendingTrans->state = RM_ERROR_SERVER_RESP_INVALID_SERVICE_TYPE;
1015                 }
1016             } else {
1017                 if (transaction->type == Rm_service_RESOURCE_FREE) {
1018                     /* Error occurred when trying to free local resource on
1019                      * Server.  Reinsert local resources freed by original
1020                      * request */
1021                     Rm_AllocatorOpInfo   opInfo;
1023                     memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));
1024                     opInfo.resourceInfo = &pendingTrans->resourceInfo;
1025                     opInfo.serviceInstNode = rmPolicyGetValidInstNode((Rm_Handle)rmInst,
1026                                               pendingTrans->serviceSrcInstName);
1027                     /* Can't regain the original type of allocate.  Default to
1028                      * init */
1029                     opInfo.operation = Rm_allocatorOp_ALLOCATE_INIT;
1030                     if (rmAllocatorOperation((Rm_Handle)rmInst, &opInfo) !=
1031                         RM_SERVICE_APPROVED) {
1032                         transaction->state = RM_ERROR_LOST_RESOURCES_ON_CD;
1033                     }
1034                 }
1035                 /* Transfer error or denial to pending transaction */
1036                 pendingTrans->state = transaction->state;
1037             }
1038             rmTransactionQueueDelete(rmInst, transaction->localId);
1039             /* Switch to pending transaction */
1040             transaction = pendingTrans;
1041         }
1043         if ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||
1044             (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) ||
1045             (transaction->type == Rm_service_RESOURCE_STATUS) ||
1046             (transaction->type == Rm_service_RESOURCE_FREE)) {
1047             if ((transaction->state == RM_SERVICE_PROCESSING) &&
1048                 (strlen(transaction->resourceInfo.nameServerName) > 0)) {
1049                 /* Create and forward new transaction to Server to
1050                  * retrieve resource data mapped to name */
1051                 if ((newTrans = rmTransactionQueueAdd(rmInst))) {
1052                     newTrans->type = Rm_service_RESOURCE_GET_BY_NAME;
1053                     rm_strncpy(newTrans->serviceSrcInstName, rmInst->instName,
1054                                RM_NAME_MAX_CHARS);
1055                     newTrans->state = RM_SERVICE_PROCESSING;
1056                     rm_strncpy(newTrans->resourceInfo.nameServerName,
1057                                transaction->resourceInfo.nameServerName,
1058                                RM_NAME_MAX_CHARS);
1059                     newTrans->pendingTransactionId = transaction->localId;
1060                     transactionForwarder(rmInst, newTrans);
1062                     transaction->state = RM_SERVICE_PENDING_SERVER_RESPONSE;
1063                 } else {
1064                     transaction->state = RM_ERROR_TRANS_REQ_TO_SERVER_NOT_CREATED;
1065                 }
1066             }
1067         }
1069         if (transaction->state == RM_SERVICE_PROCESSING) {
1070             switch(transaction->type) {
1071                 case Rm_service_RESOURCE_ALLOCATE_INIT:
1072                 case Rm_service_RESOURCE_ALLOCATE_USE:
1073                     allocationHandler(rmInst, transaction);
1074                     break;
1075                 case Rm_service_RESOURCE_FREE:
1076                     freeHandler(rmInst, transaction);
1077                     break;
1078                 case Rm_service_RESOURCE_STATUS:
1079                     statusHandler(rmInst, transaction);
1080                     break;
1081                 case Rm_service_RESOURCE_MAP_TO_NAME:
1082                 case Rm_service_RESOURCE_GET_BY_NAME:
1083                 case Rm_service_RESOURCE_UNMAP_NAME:
1084                     /* Forward all NameServer-based transactions */
1085                     break;
1086                 default:
1087                     transaction->state = RM_ERROR_INVALID_SERVICE_TYPE;
1088                     break;
1089             }
1090         }
1092         if (transaction->state == RM_SERVICE_PROCESSING) {
1093             uint32_t transId = transaction->localId;
1095             /* NameServer transaction or CD could not complete alloc/free
1096              * transaction.  Forward to Server */
1097             transactionForwarder(rmInst, transaction);
1099             /* Refresh transaction for reentrancy of cases where mix of Client
1100              * CD and Server are running on the same core and connected via
1101              * transport implemented over direct function calls instead of
1102              * traditional transport that returns after sending the data */
1103             transaction = rmTransactionQueueFind(rmInst, transId);
1104         }
1106         if (transaction) {
1107             if ((transaction->state != RM_SERVICE_PROCESSING) &&
1108                 (transaction->state != RM_SERVICE_PENDING_SERVER_RESPONSE)) {
1109                 /* Transaction completed by CD or completed response received
1110                  * from Server.  Return result */
1111                 if (strncmp(transaction->serviceSrcInstName, rmInst->instName,
1112                     RM_NAME_MAX_CHARS)) {
1113                     /* Transaction did not originate on this instance */
1114                     transactionResponder(rmInst, transaction);
1115                 } else {
1116                     /* Transaction originated on this instance */
1117                     serviceResponder(rmInst, transaction);
1118                 }
1119             }
1120         }
1122         /* Attempt allocation of any queued static requests:
1123          * RM_SERVICE_APPROVED_STATIC - Originated locally
1124          * RM_SERVICE_PROCESSING - Received from any registered Clients */
1125         transQ = rmInst->transactionQueue;
1126         while(transQ) {
1127             if (((transQ->state == RM_SERVICE_PROCESSING) ||
1128                  (transQ->state == RM_SERVICE_APPROVED_STATIC)) &&
1129                 (!transQ->hasBeenForwarded)) {
1130                 transactionForwarder(rmInst, transQ);
1131             }
1132             transQ = transQ->nextTransaction;
1133         }
1134     }
1137 /* FUNCTION PURPOSE: Server transaction handling process
1138  ***********************************************************************
1139  * DESCRIPTION: Server process for handling transactions created
1140  *              from services received via the service handle or the
1141  *              transport.  The Server process:
1142  *                  - Validates all service requests received from
1143  *                    the service handle and registered CDs and
1144  *                    Clients
1145  */
1146 static void serverProcess(Rm_Inst *rmInst, Rm_Transaction *transaction)
1148     Rm_NameServerObjCfg  nameServerObjCfg;
1150     switch (transaction->type) {
1151         case Rm_service_RESOURCE_STATUS:
1152             statusHandler(rmInst, transaction);
1153             break;
1154         case Rm_service_RESOURCE_ALLOCATE_INIT:
1155         case Rm_service_RESOURCE_ALLOCATE_USE:
1156             allocationHandler(rmInst, transaction);
1157             break;
1158         case Rm_service_RESOURCE_FREE:
1159             freeHandler(rmInst, transaction);
1160             break;
1161         case Rm_service_RESOURCE_MAP_TO_NAME:
1162         case Rm_service_RESOURCE_GET_BY_NAME:
1163         case Rm_service_RESOURCE_UNMAP_NAME:
1164             if (rmInst->u.server.nameServer) {
1165                 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1166                     rmNameServerTreeInv(rmInst->u.server.nameServer);
1167                 }                
1168                 memset((void *)&nameServerObjCfg, 0,
1169                        sizeof(Rm_NameServerObjCfg));
1170                 nameServerObjCfg.nameServerTree = rmInst->u.server.nameServer;
1171                 nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
1172                 if (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) {
1173                     nameServerObjCfg.nodeCfg.resourceName = transaction->resourceInfo.name;
1174                     nameServerObjCfg.nodeCfg.resourceBase= transaction->resourceInfo.base;
1175                     nameServerObjCfg.nodeCfg.resourceLength = transaction->resourceInfo.length;
1176                     transaction->state = rmNameServerAddObject(&nameServerObjCfg);
1177                 } else if (transaction->type ==
1178                            Rm_service_RESOURCE_GET_BY_NAME) {
1179                     if ((transaction->state = rmNameServerFindObject(&nameServerObjCfg)) ==
1180                         RM_SERVICE_PROCESSING) {
1181                         rm_strncpy(transaction->resourceInfo.name,
1182                                    nameServerObjCfg.nodeCfg.resourceName,
1183                                    RM_NAME_MAX_CHARS);
1184                         transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;
1185                         transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;
1186                         transaction->state = RM_SERVICE_APPROVED;
1187                     }
1188                 } else if (transaction->type ==
1189                            Rm_service_RESOURCE_UNMAP_NAME) {
1190                     transaction->state = rmNameServerDeleteObject(&nameServerObjCfg);
1191                 } else {
1192                     transaction->state = RM_ERROR_INVALID_SERVICE_TYPE;
1193                 }
1195                 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1196                     rmNameServerTreeWb(rmInst->u.server.nameServer);
1197                 }
1198             } else {
1199                 transaction->state = RM_ERROR_NAMESERVER_DOES_NOT_EXIST;
1200             }
1201             break;
1202         default:
1203             transaction->state = RM_ERROR_INVALID_SERVICE_TYPE;
1204             break;
1205     }
1207     /* Source of shared server transaction will always be local. */
1208     if (rmInst->instType != Rm_instType_SHARED_SERVER) {
1209         if (strncmp(transaction->serviceSrcInstName, rmInst->instName,
1210                     RM_NAME_MAX_CHARS)) {
1211             /* Source of transaction was not Server, return transaction via
1212              * responder */
1213             transactionResponder(rmInst, transaction);
1214         }
1215     }
1216     /* Otherwise let call stack return transaction result app via
1217      * Rm_serviceHandler */ 
1220 /**********************************************************************
1221  ********************** Internal Functions ****************************
1222  **********************************************************************/
1224 /* FUNCTION PURPOSE: Adds a transaction
1225  ***********************************************************************
1226  * DESCRIPTION: Returns a pointer to a newly created transaction.
1227  *              The transaction is created based on a new service
1228  *              request received via the service API or the
1229  *              transport API (service forwarded from another instance)
1230  */
1231 Rm_Transaction *rmTransactionQueueAdd(Rm_Inst *rmInst)
1233     Rm_Transaction *transactionQueue = rmInst->transactionQueue;
1234     Rm_Transaction *newTransaction   = NULL;
1236     newTransaction = Rm_osalMalloc(sizeof(Rm_Transaction));
1237     if (newTransaction) {
1238         memset((void *)newTransaction, 0, sizeof(Rm_Transaction));
1240         newTransaction->localId = transactionGetSequenceNum(rmInst);
1241         newTransaction->nextTransaction = NULL;  
1242         if (transactionQueue) {
1243             while (transactionQueue->nextTransaction) {
1244                 transactionQueue = transactionQueue->nextTransaction;
1245             }
1246             transactionQueue->nextTransaction = newTransaction;
1247         } else {
1248             rmInst->transactionQueue = newTransaction;
1249         }
1250     }
1251     return(newTransaction);
1254 /* FUNCTION PURPOSE: Finds a transaction
1255  ***********************************************************************
1256  * DESCRIPTION: Returns a pointer to a transaction resident
1257  *              in the transaction queue that matches the provided
1258  *              transaction ID.
1259  */
1260 Rm_Transaction *rmTransactionQueueFind(Rm_Inst *rmInst, uint32_t transactionId)
1262     Rm_Transaction *transaction = rmInst->transactionQueue;
1264     while (transaction) {
1265         if (transaction->localId == transactionId) {
1266             break;
1267         }
1268         transaction = transaction->nextTransaction;
1269     }
1271     return(transaction);
1274 /* FUNCTION PURPOSE: Deletes a transaction
1275  ***********************************************************************
1276  * DESCRIPTION: Deletes the transaction with the provided transaction
1277  *              ID from the instance's transaction queue.
1278  */
1279 int32_t rmTransactionQueueDelete(Rm_Inst *rmInst, uint32_t transactionId)
1281     Rm_Transaction *transaction = rmInst->transactionQueue;
1282     Rm_Transaction *prevTransaction = NULL;
1283     int32_t         retVal = RM_OK;
1285     while (transaction) {
1286         if (transaction->localId == transactionId) {
1287             break;
1288         }
1290         prevTransaction = transaction;
1291         transaction = transaction->nextTransaction;
1292     }
1294     if (transaction) {
1295         if (prevTransaction == NULL) {
1296             /* Transaction at start of queue. Map second transaction to start
1297              * of queue as long as more than one transactions. */
1298             rmInst->transactionQueue = transaction->nextTransaction;
1299         } else {
1300             /* Transaction in middle or end of queue. */
1301             prevTransaction->nextTransaction = transaction->nextTransaction;
1302         }
1303         Rm_osalFree((void *)transaction, sizeof(Rm_Transaction));
1304     } else {
1305         retVal = RM_ERROR_SERVICE_TRANS_DOES_NOT_EXIST;
1306     }
1307     return(retVal);
1310 /* FUNCTION PURPOSE: Routes a transaction for processing
1311  ***********************************************************************
1312  * DESCRIPTION: Routes a received transaction to the appropriate
1313  *              instance processing routine
1314  */
1315 void rmProcessRouter(Rm_Inst *rmInst, Rm_Transaction *transaction)
1317     if (rmInst->instType == Rm_instType_CLIENT) {
1318         clientProcess(rmInst, transaction);
1319     } else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1320         cdProcess(rmInst, transaction);
1321     } else if ((rmInst->instType == Rm_instType_SERVER) ||
1322                (rmInst->instType == Rm_instType_SHARED_SERVER)) {
1323         serverProcess(rmInst, transaction);
1324     } else {
1325         transaction->state = RM_ERROR_INVALID_INST_TYPE;
1326     }
1329 /**********************************************************************
1330  ********************** Application visible APIs **********************
1331  **********************************************************************/
1333 /* FUNCTION PURPOSE: Display status of managed resources
1334  ***********************************************************************
1335  * DESCRIPTION: Prints the status (allocate/free status, as well as
1336  *              owners) for all resources managed by the RM 
1337  *              instance network.  Also, prints the NameServer name
1338  *              entries.  The number of resource range owners is
1339  *              returned as well.  This function is only available on
1340  *              Server and CD instances.
1341  */
1342 int32_t Rm_resourceStatus(Rm_Handle rmHandle, int printResources)
1344     Rm_Inst          *rmInst = (Rm_Inst *)rmHandle;
1345     Rm_AllocatorTree *allocTree = NULL;
1346     Rm_AllocatorNode *allocator;
1347     Rm_Owner         *owners;
1348     Rm_ResourceTree  *treeRoot;
1349     Rm_ResourceNode  *treeNode;
1350     int32_t           totalResOwners = 0;
1351     void             *key;
1352     void             *mtKey;
1354     RM_SS_INST_INV_ENTER_CS(rmInst, key);
1355     RM_SC_INST_INV_ENTER_CS(rmInst, key);
1356     if (rmInst->mtSemObj) {
1357         mtKey = Rm_osalMtCsEnter(rmInst->mtSemObj);
1358     }
1360     if (rmInst->instType != Rm_instType_CLIENT) {
1361         Rm_osalLog("Instance name: %s\n", rmInst->instName);
1362         Rm_osalLog("Handle: 0x%08x\n", rmHandle);
1363         if (rmInst->instType == Rm_instType_SERVER) {
1364             Rm_osalLog("Type:   Server\n");
1365         } else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1366             Rm_osalLog("Type:   Client Delegate\n");
1367         } else if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1368             Rm_osalLog("Type:   Shared Server\n");
1369         } else if (rmInst->instType == Rm_instType_SHARED_CLIENT) {
1370             Rm_osalLog("Type:   Shared Client\n");
1371         } else {
1372             Rm_osalLog("Type:   UNKNOWN\n");
1373             goto errorExit;
1374         }
1376         Rm_osalLog("\nResource Status:\n\n");
1377     }
1379     if (rmInst->instType == Rm_instType_SHARED_CLIENT) {
1380         /* Transfer control to shared server instance */
1381         rmInst = rmInst->u.sharedClient.sharedServerHandle;
1382     }
1384     if ((rmInst->instType == Rm_instType_SERVER) ||
1385         (rmInst->instType == Rm_instType_SHARED_SERVER) ||
1386         (rmInst->instType == Rm_instType_CLIENT_DELEGATE)) {
1388         allocTree = rmInst->allocatorTree;
1389         if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1390             rmAllocatorTreeInv(allocTree);
1391         }
1393         RB_FOREACH(allocator, _Rm_AllocatorTree, allocTree) {
1394             RM_SS_OBJ_INV(rmInst, allocator, Rm_AllocatorNode);
1395             if (printResources) {
1396                 Rm_osalLog("Resource: %s\n", allocator->resourceName);
1397             }
1399             treeRoot = allocator->resourceRoot;
1400             if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1401                 rmResourceTreeInv(treeRoot);
1402             }
1403             RB_FOREACH(treeNode, _Rm_AllocatorResourceTree, treeRoot) {
1404                 if (printResources) {
1405                     if ((treeNode->base >= 65536) ||
1406                         ((treeNode->base + treeNode->length - 1) >= 65536)) {
1407                         /* Print in hex if number is very large */
1408                         Rm_osalLog("          0x%08x - 0x%08x ",
1409                                    treeNode->base,
1410                                    treeNode->base + treeNode->length - 1);
1411                     } else {
1412                         Rm_osalLog("          %10d - %10d ",
1413                                    treeNode->base,
1414                                    treeNode->base + treeNode->length - 1);
1415                     }
1416                 }
1418                 if (treeNode->allocationCount == 0) {
1419                     if (printResources) {
1420                         Rm_osalLog("FREE\n");
1421                     }
1422                 } else {
1423                     owners = treeNode->ownerList;
1424                     while (owners) {
1425                         RM_SS_OBJ_INV(rmInst, owners, Rm_Owner);
1426                         if (printResources) {
1427                             Rm_osalLog("%s (%d) ", owners->instNameNode->name,
1428                                        owners->refCnt);
1429                         }
1430                         totalResOwners++;
1431                         owners = owners->nextOwner;
1432                     }
1433                     if (printResources) {
1434                         Rm_osalLog("\n");
1435                     }
1436                 }
1437             }
1438         }
1440         if ((rmInst->instType == Rm_instType_SERVER) ||
1441             (rmInst->instType == Rm_instType_SHARED_SERVER)) {
1442             if (printResources) {
1443                 rmNameServerPrintObjects((Rm_Handle)rmInst);
1444             }
1445         }
1446     } else {
1447         totalResOwners = RM_ERROR_INVALID_RES_STATUS_INSTANCE;
1448     }
1450 errorExit:
1451     /* Free sem object using originating instance in case the Shared Client to Shared
1452      * Server instance switch took place */
1453     if (((Rm_Inst *)rmHandle)->mtSemObj) {
1454         Rm_osalMtCsExit(((Rm_Inst *)rmHandle)->mtSemObj, mtKey);
1455     }
1456     RM_SS_INST_WB_EXIT_CS(rmInst, key);
1457     return(totalResOwners);
1460 /* FUNCTION PURPOSE: Display status of a RM instance
1461  ***********************************************************************
1462  * DESCRIPTION: Prints the current status of various RM instance
1463  *              properties such as the state of all transactions
1464  *              in the transaction queue and registered transports
1465  */
1466 void Rm_instanceStatus(Rm_Handle rmHandle)
1468     Rm_Inst        *rmInst = (Rm_Inst *)rmHandle;
1469     Rm_Transport   *transportList = NULL;
1470     Rm_Transaction *transactionQ = NULL;
1471     void           *key;
1472     void           *mtKey;
1474     RM_SS_INST_INV_ENTER_CS(rmInst, key);
1475     RM_SC_INST_INV_ENTER_CS(rmInst, key);
1476     if (rmInst->mtSemObj) {
1477         mtKey = Rm_osalMtCsEnter(rmInst->mtSemObj);
1478     }
1480     Rm_osalLog("Instance name: %s\n", rmInst->instName);
1481     Rm_osalLog("Handle: 0x%08x\n", rmHandle);    
1482     if (rmInst->instType == Rm_instType_SERVER) {
1483         Rm_osalLog("Type:   Server\n");
1484     } else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1485         Rm_osalLog("Type:   Client Delegate\n");
1486     } else if (rmInst->instType == Rm_instType_CLIENT) {
1487         Rm_osalLog("Type:   Client\n");
1488     } else if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1489         Rm_osalLog("Type:   Shared Server\n");
1490     } else if (rmInst->instType == Rm_instType_SHARED_CLIENT) {
1491         Rm_osalLog("Type:   Shared Client\n");
1493         Rm_osalLog("\nShared Server Properties:\n");
1494         /* Transfer to Shared Server instance to print out transport and
1495          * transaction status */
1496         rmInst = rmInst->u.sharedClient.sharedServerHandle;
1497         Rm_osalLog("Instance name: %s\n", rmInst->instName);
1498         Rm_osalLog("Handle: 0x%08x\n", rmHandle);
1499     } else {
1500         Rm_osalLog("Type:   UNKNOWN\n");
1501         goto errorExit;
1502     }
1504     transportList = rmInst->transports;
1505     if (transportList) {
1506         Rm_osalLog("\nRegistered Transports:\n");
1507         while (transportList) {
1508             RM_SS_OBJ_INV(rmInst, transportList, Rm_Transport);
1509             if (transportList->remoteInstType == Rm_instType_SERVER) {
1510                 Rm_osalLog("    Remote instType:    Server\n");
1511             } else if (transportList->remoteInstType ==
1512                        Rm_instType_CLIENT_DELEGATE) {
1513                 Rm_osalLog("    Remote instType:    Client Delegate\n");
1514             } else {
1515                 Rm_osalLog("    Remote instType:    Client\n");
1516             }
1517             Rm_osalLog("    appTransportHandle: 0x%08x\n",
1518                        transportList->appTransportHandle);
1519             Rm_osalLog("\n");
1520             transportList = transportList->nextTransport;
1521         }
1522     }
1524     transactionQ = rmInst->transactionQueue;
1525     if (transactionQ) {
1526         Rm_osalLog("\nQueued Service Transactions:\n");
1527         while (transactionQ) {
1528             RM_SS_OBJ_INV(rmInst, transactionQ, Rm_Transaction);
1529             Rm_osalLog("    Service type:       %d\n",
1530                        transactionQ->type);
1531             Rm_osalLog("    Service ID:         %d\n", transactionQ->localId);
1532             Rm_osalLog("    Service srcInstName %s\n",
1533                        transactionQ->serviceSrcInstName);
1534             Rm_osalLog("    Service state:      %d\n", transactionQ->state);
1535             Rm_osalLog("    Resource name:      %s\n",
1536                        transactionQ->resourceInfo.name);
1537             Rm_osalLog("    Resource base:      %d\n",
1538                        transactionQ->resourceInfo.base);
1539             Rm_osalLog("    Resource length:    %d\n",
1540                        transactionQ->resourceInfo.length);
1541             Rm_osalLog("    Resource alignment: %d\n",
1542                        transactionQ->resourceInfo.alignment);
1543             Rm_osalLog("    Resource NS name:   %s\n",
1544                        transactionQ->resourceInfo.nameServerName);
1545             Rm_osalLog("\n");
1546             transactionQ = transactionQ->nextTransaction;
1547         }
1548     }
1550 errorExit:
1551     /* Free sem object using originating instance in case the Shared Client
1552      * to Shared Server instance switch took place */
1553     if (((Rm_Inst *)rmHandle)->mtSemObj) {
1554         Rm_osalMtCsExit(((Rm_Inst *)rmHandle)->mtSemObj, mtKey);
1555     }
1556     RM_SS_INST_WB_EXIT_CS(rmInst, key);
1559 /* FUNCTION PURPOSE: RM instance creation and initialization
1560  ***********************************************************************
1561  * DESCRIPTION: Returns a new RM instance created and initialized
1562  *              using the parameters provided via the initCfg
1563  *              structure.
1564  */
1565 Rm_Handle Rm_init(const Rm_InitCfg *initCfg, int32_t *result)
1567     Rm_Inst  *rmInst = NULL;
1568     void     *grlDtb = NULL;
1569     void     *policyDtb = NULL;
1570     void     *linuxDtb = NULL;
1571     int       addLinux = RM_FALSE;
1572     void     *key;
1574     *result = RM_OK;
1576     if ((initCfg->instName == NULL) ||
1577         ((strlen(initCfg->instName) + 1) > RM_NAME_MAX_CHARS)) {
1578         *result = RM_ERROR_INVALID_INST_NAME;
1579         goto errorExit;
1580     }
1582     if (initCfg->instType >= Rm_instType_LAST) {
1583         *result = RM_ERROR_INVALID_INST_TYPE;
1584         goto errorExit;
1585     }
1587     /* Create and initialize instance */
1588     rmInst = Rm_osalMalloc(sizeof(*rmInst));
1589     memset((void *)rmInst, 0, sizeof(*rmInst));
1590     rmInst->isLocked = RM_FALSE;
1591     rmInst->registeredWithDelegateOrServer = RM_FALSE;
1592     rmInst->transactionSeqNum = transactionInitSequenceNum();
1594     rmInst->instType = initCfg->instType;
1595     rm_strncpy(rmInst->instName, initCfg->instName, RM_NAME_MAX_CHARS);
1596     rmInst->mtSemObj = initCfg->mtSemObj;
1598     if ((rmInst->instType == Rm_instType_SERVER) ||
1599         (rmInst->instType == Rm_instType_SHARED_SERVER)) {
1600         if (!initCfg->instCfg.serverCfg.globalResourceList ||
1601             !initCfg->instCfg.serverCfg.globalPolicy) {
1602             *result = RM_ERROR_INVALID_SERVER_CONFIGURATION;
1603             goto errorExit;
1604         }
1606         if (initCfg->instCfg.serverCfg.linuxDtb) {
1607             linuxDtb = initCfg->instCfg.serverCfg.linuxDtb;
1608             addLinux = RM_TRUE;
1609         }
1611         /* Create valid instance list from policy.  Must be done prior to
1612          * parsing GRL so that Linux resources can be reserved correctly */
1613         policyDtb = initCfg->instCfg.serverCfg.globalPolicy;
1614         rmInst->validInstTree = rmPolicyVInstTreeInit(rmInst, policyDtb,
1615                                                       addLinux, result);
1616         if (*result != RM_OK) {
1617             goto errorExit;
1618         }
1620         rmNameServerInit((Rm_Handle)rmInst);
1621         grlDtb = initCfg->instCfg.serverCfg.globalResourceList;
1622         if ((*result = rmAllocatorTreeInit(rmInst, grlDtb,
1623                                            policyDtb, linuxDtb)) != RM_OK) {
1624             goto errorExit;
1625         }
1626     } else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1627         if (!initCfg->instCfg.cdCfg.cdPolicy) {
1628             *result = RM_ERROR_INVALID_CD_CONFIGURATION;
1629             goto errorExit;
1630         }
1632         policyDtb = initCfg->instCfg.cdCfg.cdPolicy;
1633         rmInst->validInstTree = rmPolicyVInstTreeInit(rmInst, policyDtb,
1634                                                       addLinux, result);
1635         if (*result != RM_OK) {
1636             goto errorExit;
1637         }
1639         if ((*result = rmAllocatorTreeInit(rmInst, NULL,
1640                                            policyDtb, NULL)) != RM_OK) {
1641             goto errorExit;
1642         }
1644         /* Remove once CD instance is stable - tracked by SDOCM00100797 */
1645         *result = RM_WARNING_CD_INSTANCE_NOT_STABLE;
1647     } else if (rmInst->instType == Rm_instType_CLIENT) {
1648         if (initCfg->instCfg.clientCfg.staticPolicy) {
1649             policyDtb = initCfg->instCfg.clientCfg.staticPolicy;
1650             rmInst->validInstTree = rmPolicyVInstTreeInit(rmInst, policyDtb,
1651                                                           addLinux, result);
1652             if (*result != RM_OK) {
1653                 goto errorExit;
1654             }
1656             if ((*result = rmAllocatorTreeInit(rmInst, NULL,
1657                                                policyDtb, NULL)) != RM_OK) {
1658                 goto errorExit;
1659             }
1660         }
1661         
1662     } else if (rmInst->instType == Rm_instType_SHARED_CLIENT) {
1663         Rm_Handle  sHdl = initCfg->instCfg.sharedClientCfg.sharedServerHandle;
1664         Rm_Inst   *ssInst = NULL;
1666         if (sHdl) {
1667             rmInst->u.sharedClient.sharedServerHandle = sHdl;
1668             /* Invalidate the Shared server instance structure on this core to
1669              * get the latest instance data. */
1670             key = Rm_osalCsEnter();
1671             Rm_osalBeginMemAccess((void *)sHdl, sizeof(Rm_Inst));
1672             ssInst = rmInst->u.sharedClient.sharedServerHandle;
1673             if (ssInst->instType != Rm_instType_SHARED_SERVER) {
1674                 *result = RM_ERROR_INVALID_SHARED_SERVER_HANDLE;
1675                 Rm_osalCsExit(key);
1676                 goto errorExit;
1677             } else {
1678                 /* Invalidate all the trees */
1679                 rmPolicyValidInstTreeInv(ssInst->validInstTree);
1680                 rmAllocatorTreeInv(ssInst->allocatorTree);
1681                 rmNameServerTreeInv(ssInst->u.server.nameServer);
1682             }
1683             Rm_osalCsExit(key);
1684         } else {
1685             *result = RM_ERROR_INVALID_SHARED_SERVER_HANDLE;
1686             goto errorExit;
1687         }
1688     } else {
1689         *result = RM_ERROR_INVALID_INST_TYPE;
1690         goto errorExit;
1691     }
1693     if (initCfg->instType == Rm_instType_SHARED_SERVER) {
1694         /* Writeback instance and trees for other cores */
1695         rmPolicyValidInstTreeWb(rmInst->validInstTree);
1696         rmAllocatorTreeWb(rmInst->allocatorTree);
1697         rmNameServerTreeWb(rmInst->u.server.nameServer);
1698         Rm_osalEndMemAccess((void *)rmInst, sizeof(*rmInst));
1699     } else if (rmInst->instType != Rm_instType_SHARED_CLIENT) {
1700         /* Create the instance's task blocking mechanism */
1701         rmInst->blockHandle = Rm_osalTaskBlockCreate();
1702     }
1703     /* else: fall through */
1705     return((Rm_Handle)rmInst);
1707 errorExit:
1708     if (rmInst) {
1709         rmAllocatorTreeDelete((Rm_Handle)rmInst);
1710         rmNameServerDelete((Rm_Handle)rmInst);
1711         rmPolicyVInstTreeDelete((Rm_Handle)rmInst);
1712         Rm_osalFree((void *)rmInst, sizeof(*rmInst));
1713     }
1714     return(NULL);
1717 /* FUNCTION PURPOSE: Deletes an RM instance
1718  ***********************************************************************
1719  * DESCRIPTION: Frees all memory associated with an RM instance
1720  *              as long as all transports have been unregistered
1721  *              and the service handle has been closed
1722  */
1723 int32_t Rm_delete(Rm_Handle rmHandle, int ignorePendingServices)
1725     Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
1726     void    *key;
1728     key = Rm_osalCsEnter();
1729     if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1730         Rm_osalBeginMemAccess((void *)rmInst, sizeof(*rmInst));
1731     }
1733     if (rmInst->serviceHandle) {
1734         return(RM_ERROR_CANT_DELETE_WITH_OPEN_SERV_HNDL);
1735     } else if (rmInst->transports) {
1736         return(RM_ERROR_CANT_DELETE_WITH_REGD_TRANSPORT);
1737     } else if (rmInst->transactionQueue && !ignorePendingServices) {
1738         return(RM_ERROR_CANT_DELETE_PENDING_TRANSACTIONS);
1739     }
1740     /* else: delete instance since no more deletion failure cases */
1742     if (rmInst->instType != Rm_instType_SHARED_CLIENT) {
1743         rmNameServerDelete(rmHandle);
1744         rmAllocatorTreeDelete(rmHandle);
1745         rmPolicyVInstTreeDelete(rmHandle);
1747         /* Delete any transactions */
1748         while(rmInst->transactionQueue) {
1749             rmTransactionQueueDelete(rmInst, rmInst->transactionQueue->localId);
1750         }
1752         if (rmInst->instType != Rm_instType_SHARED_SERVER) {
1753             /* Delete the instance's task blocking mechanism */
1754             Rm_osalTaskBlockDelete(rmInst->blockHandle);
1755         } else {
1756             rmInst->allocatorTree       = NULL;
1757             rmInst->validInstTree       = NULL;
1758             rmInst->u.server.nameServer = NULL;
1759             Rm_osalEndMemAccess((void *)rmInst, sizeof(*rmInst));
1760         }
1761     }
1763     Rm_osalFree((void *)rmInst, sizeof(*rmInst));
1764     Rm_osalCsExit(key);
1765     return(RM_OK);
1768 /* FUNCTION PURPOSE: Returns RM version information
1769  ***********************************************************************
1770  */
1771 uint32_t Rm_getVersion(void)
1773     return(RM_VERSION_ID);
1776 /* FUNCTION PURPOSE: Returns RM version string
1777  ***********************************************************************
1778  */
1779 const char* Rm_getVersionStr(void)
1781     return(rmVersionStr);