]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - keystone-rtos/rm-lld.git/blob - src/rm.c
Fixed UNSPECIFIED alloc exclusion review feedback
[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.negCheck       = RM_FALSE;
464             privCheckCfg.validInstNode  = rmPolicyGetValidInstNode(rmHandle,
465                                                               rmInst->instName);
466             privCheckCfg.polTree        = allocNode->policyRoot;
467             privCheckCfg.resourceBase   = transaction->resourceInfo.base;
468             privCheckCfg.resourceLength = transaction->resourceInfo.length;
470             if (rmPolicyCheckPrivilege(&privCheckCfg)) {
471                 transaction->state = RM_SERVICE_APPROVED_STATIC;
472             } else {
473                 transaction->state = RM_SERVICE_DENIED_BY_STATIC_POLICY;
474             }
475         } else {
476             transaction->state = RM_SERVICE_DENIED_INVALID_STATIC_REQUEST;
477         }
478     } else {
479         transaction->state = RM_ERROR_REQ_FAILED_NO_STATIC_POLICY;
480     }
483 /* FUNCTION PURPOSE: Requests resources from Server for CD
484  ***********************************************************************
485  * DESCRIPTION: Function creates a service request to allocate resources
486  *              from the Server for local management by the CD.  The
487  *              transaction which causes this request is put in the
488  *              pending state in order to wait for the response from the 
489  *              Server
490  */
491 static int32_t cdRequestServerResources(Rm_Inst *rmInst,
492                                         Rm_Transaction *transaction)
494     Rm_AllocatorNode *allocNode = NULL;
495     Rm_Transaction   *newTrans = NULL;
496     uint32_t          allocSize = 0;
497     int32_t           retVal;
499     allocNode = rmAllocatorFind((Rm_Handle)rmInst,
500                                 transaction->resourceInfo.name);
502     if (allocNode) {
503         if ((allocSize = rmPolicyGetCdAllocSize(allocNode->policyRoot))) {
504             if ((newTrans = rmTransactionQueueAdd(rmInst))) {
505                 newTrans->type = transaction->type;
506                 rm_strncpy(newTrans->serviceSrcInstName, rmInst->instName,
507                            RM_NAME_MAX_CHARS);
508                 newTrans->state = RM_SERVICE_PROCESSING;
509                 rm_strncpy(newTrans->resourceInfo.name,
510                            transaction->resourceInfo.name,
511                            RM_NAME_MAX_CHARS);
512                 newTrans->resourceInfo.base = RM_RESOURCE_BASE_UNSPECIFIED;
513                 /* Make sure request length will satisfy transaction length */
514                 newTrans->resourceInfo.length = allocSize;
515                 while (newTrans->resourceInfo.length <
516                        transaction->resourceInfo.length) {
517                     newTrans->resourceInfo.length += allocSize;
518                 }
519                 newTrans->resourceInfo.alignment = transaction->resourceInfo.alignment;
520                 newTrans->pendingTransactionId = transaction->localId;
521                 transactionForwarder(rmInst, newTrans);
523                 retVal = RM_SERVICE_PENDING_SERVER_RESPONSE;
524             } else {
525                 retVal = RM_ERROR_TRANS_REQ_TO_SERVER_NOT_CREATED;
526             }
527         } else {
528             /* Forward request to Server for completion if policy has 
529              * no allocation size for resource */
530             retVal = RM_SERVICE_PROCESSING;
531         }
532     } else {
533         /* Resource could not be found in policy */
534         retVal = RM_SERVICE_DENIED_RES_DOES_NOT_EXIST;
535     }
536     return(retVal);
539 /* FUNCTION PURPOSE: Frees local resources to Server from CD
540  ***********************************************************************
541  * DESCRIPTION: Function creates a service request to free locally
542  *              managed resources that are now localized back to
543  *              the Server.
544  */
545 static int32_t cdFreeResourcesToServer(Rm_Inst *rmInst,
546                                        Rm_Transaction *transaction)
548     int32_t         baseToFree = transaction->resourceInfo.base;
549     uint32_t        lenToFree = transaction->resourceInfo.length;
550     Rm_Transaction *newTrans = NULL; 
551     /* This function should only be called after a free was approved */
552     int32_t         retVal = RM_SERVICE_APPROVED;    
554     /* Did free result in a localized free node that can be given back to
555      * Server?  If so create transaction to Server to free localized
556      * resource node */
557     if (rmAllocatorGetNodeLocalization((Rm_Handle)rmInst,
558                                        transaction->resourceInfo.name,
559                                        &baseToFree, &lenToFree)) {
560         if ((newTrans = rmTransactionQueueAdd(rmInst))) {
561             newTrans->type = transaction->type;
562             rm_strncpy(newTrans->serviceSrcInstName, rmInst->instName,
563                        RM_NAME_MAX_CHARS);
564             newTrans->state = RM_SERVICE_PROCESSING;
565             rm_strncpy(newTrans->resourceInfo.name,
566                        transaction->resourceInfo.name, RM_NAME_MAX_CHARS);
567             newTrans->resourceInfo.base = baseToFree;
568             newTrans->resourceInfo.length = lenToFree;
569             newTrans->pendingTransactionId = transaction->localId;
570             transactionForwarder(rmInst, newTrans);
572             retVal = RM_SERVICE_PENDING_SERVER_RESPONSE;
573         } else {
574             /* Error: Need to re-allocate what was freed */
575             retVal = RM_ERROR_TRANS_REQ_TO_SERVER_NOT_CREATED;
576         }
577     }
578     return(retVal);
581 /* FUNCTION PURPOSE: Arbitrates allocation service requests
582  ***********************************************************************
583  * DESCRIPTION: Issues a set of allocator operations in order to
584  *              handle a received allocation request.  Allocation
585  *              requests are always forwarded to the Server on Client
586  *              CD instances.  If a request is made with a NameServer
587  *              name the resource base and length parameters are
588  *              retrieved from the NameServer prior to the allocation
589  *              attempt.
590  */
591 static void allocationHandler (Rm_Inst *rmInst, Rm_Transaction *transaction)
593     Rm_AllocatorOpInfo   opInfo;
594     Rm_NameServerObjCfg  nameServerObjCfg;
595     int32_t              retVal = transaction->state;
597     memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));
598     opInfo.resourceInfo = &transaction->resourceInfo;
599     opInfo.serviceInstNode = rmPolicyGetValidInstNode((Rm_Handle)rmInst,
600                                               transaction->serviceSrcInstName);
601     if (opInfo.serviceInstNode == NULL) {
602         retVal = RM_SERVICE_DENIED_INST_NAME_NOT_VALID;
603         goto errorExit;
604     }
606     if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
607         if (transaction->resourceInfo.base != RM_RESOURCE_BASE_UNSPECIFIED) {
608             if (rmAllocatorFind((Rm_Handle)rmInst,
609                                 transaction->resourceInfo.name)) {
610                 /* Attempt to allocate from local resources that were provided
611                  * by Server */
612                 if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
613                     opInfo.operation = Rm_allocatorOp_ALLOCATE_INIT;
614                 } else if (transaction->type ==
615                            Rm_service_RESOURCE_ALLOCATE_USE) {
616                     opInfo.operation = Rm_allocatorOp_ALLOCATE_USE;
617                 } else {
618                     retVal = RM_ERROR_INVALID_SERVICE_TYPE;
619                     goto errorExit;
620                 }
621                 retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
623                 if (retVal == RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST) {
624                     /* Request resource range was not found within local
625                      * resources provided by Server.  Set back to PROCESSING so
626                      * request is forwarded to Server */
627                     retVal = RM_SERVICE_PROCESSING;
628                 }
629             }
630         } else {
631             if (rmAllocatorFind((Rm_Handle)rmInst,
632                                 transaction->resourceInfo.name)) {
633                 int32_t oldAlign = transaction->resourceInfo.alignment;
635                 /* Attempt to allocate from local resources that were provided
636                  * by Server */
637                 if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
638                     opInfo.operation = Rm_allocatorOp_PRE_ALLOCATE_INIT;
639                 } else if (transaction->type ==
640                          Rm_service_RESOURCE_ALLOCATE_USE) {
641                     opInfo.operation = Rm_allocatorOp_PRE_ALLOCATE_USE;
642                 } else {
643                     retVal = RM_ERROR_INVALID_SERVICE_TYPE;
644                     goto errorExit;
645                 }
646                 retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
648                 if (retVal == RM_SERVICE_PROCESSING) {
649                     if (transaction->type ==
650                         Rm_service_RESOURCE_ALLOCATE_INIT) {
651                         opInfo.operation = Rm_allocatorOp_ALLOCATE_INIT;
652                     } else if (transaction->type ==
653                                Rm_service_RESOURCE_ALLOCATE_USE) {
654                         opInfo.operation = Rm_allocatorOp_ALLOCATE_USE;
655                     } else {
656                         retVal = RM_ERROR_INVALID_SERVICE_TYPE;
657                         goto errorExit;
658                     }
659                     retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
661                     if (retVal == RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST) {
662                         /* Request resource range was not found within local
663                          * resources provided by Server.  Set back to
664                          * PROCESSING so request is forwarded to Server */
665                         retVal = RM_SERVICE_PROCESSING;
666                     }
667                 } else if (retVal == RM_SERVICE_DENIED_RES_ALLOC_REQS_NOT_MET) {
668                     if (transaction->pendingTransactionId) {
669                         /* Request to Server for resources to complete
670                          * transaction locally performed once already.  Forward
671                          * transaction to Server for completion */
672                         retVal = RM_SERVICE_PROCESSING;
673                     } else {
674                         /* Restore base and alignment since they were replaced
675                          * in pre-allocate routine */
676                         transaction->resourceInfo.base = RM_RESOURCE_BASE_UNSPECIFIED;
677                         transaction->resourceInfo.alignment = oldAlign;
679                         retVal = cdRequestServerResources(rmInst, transaction);
680                     }
681                 }
682                 /* else: fall through to return */
683             } else {
684                 retVal = cdRequestServerResources(rmInst, transaction);
685             }
686         }
687     } else if ((rmInst->instType == Rm_instType_SERVER)||
688                (rmInst->instType == Rm_instType_SHARED_SERVER)) {
689         /* Populated NameServer name has precedence over base */
690         if (strlen(transaction->resourceInfo.nameServerName) > 0) {
691             if (rmInst->instType == Rm_instType_SHARED_SERVER) {
692                 rmNameServerTreeInv(rmInst->u.server.nameServer);
693             }
694             memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
695             nameServerObjCfg.nameServerTree = rmInst->u.server.nameServer;
696             nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
697             if ((retVal = rmNameServerFindObject(&nameServerObjCfg)) ==
698                 RM_SERVICE_PROCESSING) {
699                 rm_strncpy(transaction->resourceInfo.name,
700                            nameServerObjCfg.nodeCfg.resourceName,
701                            RM_NAME_MAX_CHARS);
702                 transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;
703                 transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;
704             } else {
705                 goto errorExit;
706             }
707         }
709         if (transaction->resourceInfo.base == RM_RESOURCE_BASE_UNSPECIFIED) {
710             if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
711                 opInfo.operation = Rm_allocatorOp_PRE_ALLOCATE_INIT;
712             } else if (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) {
713                 opInfo.operation = Rm_allocatorOp_PRE_ALLOCATE_USE;
714             } else {
715                 retVal = RM_ERROR_INVALID_SERVICE_TYPE;
716                 goto errorExit;
717             }
718             retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
719         }
721         if (retVal == RM_SERVICE_PROCESSING) {
722             if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
723                 opInfo.operation = Rm_allocatorOp_ALLOCATE_INIT;
724             } else if (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) {
725                 opInfo.operation = Rm_allocatorOp_ALLOCATE_USE;
726             } else {
727                 retVal = RM_ERROR_INVALID_SERVICE_TYPE;
728                 goto errorExit;
729             }
730             retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
731         }
732     } else {
733         retVal = RM_ERROR_INVALID_INST_TYPE;
734     }
735 errorExit:
736     transaction->state = retVal;
739 /* FUNCTION PURPOSE: Handles resource status service requests
740  ***********************************************************************
741  * DESCRIPTION: Issues a set of allocator operations to retrieve the
742  *              current status (currently just owner reference count)
743  *              for the resource specified in the transaction
744  */
745 static void statusHandler(Rm_Inst *rmInst, Rm_Transaction *transaction)
747     Rm_AllocatorOpInfo  opInfo;
748     Rm_NameServerObjCfg nameServerObjCfg;
749     int32_t             retVal = transaction->state;
751     memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));
752     opInfo.operation = Rm_allocatorOp_GET_STATUS;
753     opInfo.resourceInfo = &transaction->resourceInfo;
754     opInfo.serviceInstNode = rmPolicyGetValidInstNode((Rm_Handle)rmInst,
755                                             transaction->serviceSrcInstName);
756     if (opInfo.serviceInstNode == NULL) {
757         retVal = RM_SERVICE_DENIED_INST_NAME_NOT_VALID;
758         goto errorExit;
759     }
761     if ((strlen(transaction->resourceInfo.nameServerName) == 0) &&
762         ((transaction->resourceInfo.base == RM_RESOURCE_BASE_UNSPECIFIED) ||
763          (transaction->resourceInfo.length == 0))) {
764         retVal = RM_SERVICE_DENIED_RES_DOES_NOT_EXIST;
765         goto errorExit;
766     }
768     if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
769         if (rmAllocatorFind((Rm_Handle)rmInst,
770                             transaction->resourceInfo.name)) {
771             /* Attempt to get status from local resources that were provided by
772              * Server */
773             retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
775             if (retVal == RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST) {
776                 /* Request resource range was not found within local allocator
777                  * resources provided by Server.  Set back to PROCESSING so
778                  * request is forwarded to Server */
779                 retVal = RM_SERVICE_PROCESSING;
780             }
781         }
782     } else if ((rmInst->instType == Rm_instType_SERVER)||
783                (rmInst->instType == Rm_instType_SHARED_SERVER)) {
784         /* Populated NameServer name has precedence over base and length
785          * values */
786         if (strlen(transaction->resourceInfo.nameServerName) > 0) {
787             if (rmInst->instType == Rm_instType_SHARED_SERVER) {
788                 rmNameServerTreeInv(rmInst->u.server.nameServer);
789             }
790             memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
791             nameServerObjCfg.nameServerTree = rmInst->u.server.nameServer;
792             nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
793             if ((retVal = rmNameServerFindObject(&nameServerObjCfg)) ==
794                 RM_SERVICE_PROCESSING) {
795                 rm_strncpy(transaction->resourceInfo.name,
796                            nameServerObjCfg.nodeCfg.resourceName,
797                            RM_NAME_MAX_CHARS);
798                 transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;
799                 transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;
800             } else {
801                 goto errorExit;
802             }
803         }
804         retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
805     } else {
806         retVal = RM_ERROR_INVALID_INST_TYPE;
807     }
808 errorExit:
809     transaction->state = retVal;
812 /* FUNCTION PURPOSE: Arbitrates free service requests
813  ***********************************************************************
814  * DESCRIPTION: Issues a set of allocator operations in order to
815  *              handle a received free request.  Free
816  *              requests are always forwarded to the Server on Client
817  *              CD instances.  If a request is made with a NameServer
818  *              name the resource base and length parameters are
819  *              retrieved from the NameServer prior to the free
820  *              attempt.
821  */
822 static void freeHandler(Rm_Inst *rmInst, Rm_Transaction *transaction)
824     Rm_AllocatorOpInfo  opInfo; 
825     Rm_NameServerObjCfg nameServerObjCfg;
826     int32_t             retVal = transaction->state;
828     memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));
829     opInfo.operation = Rm_allocatorOp_FREE;
830     opInfo.resourceInfo = &transaction->resourceInfo;
831     opInfo.serviceInstNode = rmPolicyGetValidInstNode((Rm_Handle)rmInst,
832                                             transaction->serviceSrcInstName);
833     if (opInfo.serviceInstNode == NULL) {
834         retVal = RM_SERVICE_DENIED_INST_NAME_NOT_VALID;
835         goto errorExit;
836     }
838     if ((strlen(transaction->resourceInfo.nameServerName) == 0) &&
839         ((transaction->resourceInfo.base == RM_RESOURCE_BASE_UNSPECIFIED) ||
840          (transaction->resourceInfo.length == 0))) {
841         retVal = RM_SERVICE_DENIED_RES_DOES_NOT_EXIST;
842         goto errorExit;
843     }
845     if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
846         /* Attempt to free from local resources that were provided by Server */
847         retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
849         if (retVal == RM_SERVICE_APPROVED) {
850             /* Check if free allows local resources to be freed back to
851              * Server */
852             retVal = cdFreeResourcesToServer(rmInst, transaction);
853         } else if ((retVal == RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST) ||
854                  (retVal == RM_SERVICE_DENIED_RES_DOES_NOT_EXIST)) {
855             /* Requested resource or its range were not found within local
856              * allocator resources provided by Server.  Set back to PROCESSING
857              * so request is forwarded to Server */
858             retVal = RM_SERVICE_PROCESSING;
859         }
860         /* else: fall through to exit */
861     } else if ((rmInst->instType == Rm_instType_SERVER) ||
862              (rmInst->instType == Rm_instType_SHARED_SERVER)) {
863         /* Populated NameServer name has precedence over base */
864         if (strlen(transaction->resourceInfo.nameServerName) > 0) {
865             if (rmInst->instType == Rm_instType_SHARED_SERVER) {
866                 rmNameServerTreeInv(rmInst->u.server.nameServer);
867             }                    
868             memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
869             nameServerObjCfg.nameServerTree = rmInst->u.server.nameServer;
870             nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
871             if ((retVal = rmNameServerFindObject(&nameServerObjCfg)) ==
872                 RM_SERVICE_PROCESSING) {
873                 rm_strncpy(transaction->resourceInfo.name,
874                            nameServerObjCfg.nodeCfg.resourceName,
875                            RM_NAME_MAX_CHARS);
876                 transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;
877                 transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;
878             } else {
879                 goto errorExit;
880             }
881         }
882         retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
883     } else {
884         retVal = RM_ERROR_INVALID_INST_TYPE;
885     }
886 errorExit:
887     transaction->state = retVal;
890 /* FUNCTION PURPOSE: Client transaction handling process
891  ***********************************************************************
892  * DESCRIPTION: Client process for handling transactions created
893  *              from services received via the service handle or the
894  *              transport.  The Client process:
895  *                  - Performs static allocations if no transport
896  *                    to CD or Server has been registered
897  *                  - Forwards all service requests to CD or Server
898  *                    once transport has been registered
899  */
900 static void clientProcess(Rm_Inst *rmInst, Rm_Transaction *transaction)
902     Rm_Transaction *transQ;
904     if (!rmInst->registeredWithDelegateOrServer) {
905         staticAllocationHandler((Rm_Handle)rmInst, transaction);
906     } else {
907         if (transaction->state == RM_SERVICE_PROCESSING) {
908             /* Forward all new transactions to CD or Server */
909             transactionForwarder(rmInst, transaction);
910         } else {
911             /* Transaction validated.  Return result. */
912             serviceResponder(rmInst, transaction);
913         }
915         /* Forward any queued static requests that weren't forwarded */
916         transQ = rmInst->transactionQueue;
917         while(transQ) {
918             if ((transQ->state == RM_SERVICE_APPROVED_STATIC) &&
919                 (!transQ->hasBeenForwarded)) {
920                 transactionForwarder(rmInst, transQ);
921             }
922             transQ = transQ->nextTransaction;
923         }
924     }
925     /* Let call stack return transaction result app via Rm_serviceHandler */
928 /* FUNCTION PURPOSE: Client Delegate transaction handling process
929  ***********************************************************************
930  * DESCRIPTION: Client Delegate process for handling transactions created
931  *              from services received via the service handle or the
932  *              transport.  The Client Delegate process:
933  *                  - Performs static allocations if no transport
934  *                    to Server has been registered
935  *                  - Forwards all NameServer related service requests 
936  *                    to Server once transport has been registered
937  *                  - Attempts to complete resource service requests
938  *                    received from registered Clients
939  */
940 static void cdProcess(Rm_Inst *rmInst, Rm_Transaction *transaction)
941 {      
942     Rm_Transaction   *newTrans = NULL;
943     Rm_AllocatorNode *allocator = NULL;
944     Rm_Transaction   *transQ;
946     if (!rmInst->registeredWithDelegateOrServer) {
947         if ((transaction->state == RM_SERVICE_PROCESSING) &&
948             (strncmp(transaction->serviceSrcInstName, rmInst->instName,
949              RM_NAME_MAX_CHARS) == 0)) {
950             /* Attempt static allocation of requests originating from CD inst */
951             staticAllocationHandler((Rm_Handle)rmInst, transaction);
952         }
953         /* Everything else left in transaction queue for forwarding once
954          * transport to Server is registered */
955     } else {
956         if (transaction->pendingTransactionId) {
957             Rm_Transaction *pendingTrans = rmTransactionQueueFind(rmInst,
958                                              transaction->pendingTransactionId);
960             /* Transaction is response from Server for transaction sent to get
961              * information in order to complete pending transaction */
962             if (transaction->state == RM_SERVICE_APPROVED) {
963                 if (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) {
964                     /* Transfer resource data tied to name to pending
965                      * transaction */
966                     rm_strncpy(pendingTrans->resourceInfo.name,
967                                transaction->resourceInfo.name,
968                                RM_NAME_MAX_CHARS);
969                     pendingTrans->resourceInfo.base   = transaction->resourceInfo.base;
970                     pendingTrans->resourceInfo.length = transaction->resourceInfo.length;
971                     /* Delete NS name from pending transaction so Server isn't
972                      * queried again */
973                     memset(pendingTrans->resourceInfo.nameServerName, 0,
974                            RM_NAME_MAX_CHARS);
975                     /* Now that resource values have been retrieved clear
976                      * pending transaction ID so CD doesn't think a resource
977                      * request was sent to Server already for more local
978                      * resources */
979                     pendingTrans->pendingTransactionId = 0;
981                     /* Return original transaction to processing state to
982                      * attempt completion. */
983                     pendingTrans->state = RM_SERVICE_PROCESSING;
984                 } else if ((transaction->type ==
985                             Rm_service_RESOURCE_ALLOCATE_INIT) ||
986                            (transaction->type ==
987                             Rm_service_RESOURCE_ALLOCATE_USE)) {
988                     /* Add resources provided by Server to those managed by
989                      * CD */
990                     if ((allocator = rmAllocatorFind((Rm_Handle)rmInst,
991                                              transaction->resourceInfo.name))) {
992                         rmAllocatorAddResNode((Rm_Handle)rmInst,
993                                               allocator,
994                                               transaction->resourceInfo.base,
995                                               transaction->resourceInfo.length);
996                     }
998                     /* Return original transaction to processing state to
999                      * attempt completion */
1000                     pendingTrans->state = RM_SERVICE_PROCESSING;
1001                 } else if (transaction->type == Rm_service_RESOURCE_FREE) {
1002                     allocator = rmAllocatorFind((Rm_Handle)rmInst,
1003                                                 transaction->resourceInfo.name);
1005                     /* Local resource freed on Server.  Remove node in
1006                      * local allocator's resource tree as well */
1007                     rmAllocatorDeleteResNode((Rm_Handle)rmInst,
1008                                              allocator,
1009                                              transaction->resourceInfo.base,
1010                                              transaction->resourceInfo.length);
1012                     /* Allow original free to complete */
1013                     pendingTrans->state = RM_SERVICE_APPROVED;
1014                 } else {
1015                     pendingTrans->state = RM_ERROR_SERVER_RESP_INVALID_SERVICE_TYPE;
1016                 }
1017             } else {
1018                 if (transaction->type == Rm_service_RESOURCE_FREE) {
1019                     /* Error occurred when trying to free local resource on
1020                      * Server.  Reinsert local resources freed by original
1021                      * request */
1022                     Rm_AllocatorOpInfo   opInfo;
1024                     memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));
1025                     opInfo.resourceInfo = &pendingTrans->resourceInfo;
1026                     opInfo.serviceInstNode = rmPolicyGetValidInstNode((Rm_Handle)rmInst,
1027                                               pendingTrans->serviceSrcInstName);
1028                     /* Can't regain the original type of allocate.  Default to
1029                      * init */
1030                     opInfo.operation = Rm_allocatorOp_ALLOCATE_INIT;
1031                     if (rmAllocatorOperation((Rm_Handle)rmInst, &opInfo) !=
1032                         RM_SERVICE_APPROVED) {
1033                         transaction->state = RM_ERROR_LOST_RESOURCES_ON_CD;
1034                     }
1035                 }
1036                 /* Transfer error or denial to pending transaction */
1037                 pendingTrans->state = transaction->state;
1038             }
1039             rmTransactionQueueDelete(rmInst, transaction->localId);
1040             /* Switch to pending transaction */
1041             transaction = pendingTrans;
1042         }
1044         if ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||
1045             (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) ||
1046             (transaction->type == Rm_service_RESOURCE_STATUS) ||
1047             (transaction->type == Rm_service_RESOURCE_FREE)) {
1048             if ((transaction->state == RM_SERVICE_PROCESSING) &&
1049                 (strlen(transaction->resourceInfo.nameServerName) > 0)) {
1050                 /* Create and forward new transaction to Server to
1051                  * retrieve resource data mapped to name */
1052                 if ((newTrans = rmTransactionQueueAdd(rmInst))) {
1053                     newTrans->type = Rm_service_RESOURCE_GET_BY_NAME;
1054                     rm_strncpy(newTrans->serviceSrcInstName, rmInst->instName,
1055                                RM_NAME_MAX_CHARS);
1056                     newTrans->state = RM_SERVICE_PROCESSING;
1057                     rm_strncpy(newTrans->resourceInfo.nameServerName,
1058                                transaction->resourceInfo.nameServerName,
1059                                RM_NAME_MAX_CHARS);
1060                     newTrans->pendingTransactionId = transaction->localId;
1061                     transactionForwarder(rmInst, newTrans);
1063                     transaction->state = RM_SERVICE_PENDING_SERVER_RESPONSE;
1064                 } else {
1065                     transaction->state = RM_ERROR_TRANS_REQ_TO_SERVER_NOT_CREATED;
1066                 }
1067             }
1068         }
1070         if (transaction->state == RM_SERVICE_PROCESSING) {
1071             switch(transaction->type) {
1072                 case Rm_service_RESOURCE_ALLOCATE_INIT:
1073                 case Rm_service_RESOURCE_ALLOCATE_USE:
1074                     allocationHandler(rmInst, transaction);
1075                     break;
1076                 case Rm_service_RESOURCE_FREE:
1077                     freeHandler(rmInst, transaction);
1078                     break;
1079                 case Rm_service_RESOURCE_STATUS:
1080                     statusHandler(rmInst, transaction);
1081                     break;
1082                 case Rm_service_RESOURCE_MAP_TO_NAME:
1083                 case Rm_service_RESOURCE_GET_BY_NAME:
1084                 case Rm_service_RESOURCE_UNMAP_NAME:
1085                     /* Forward all NameServer-based transactions */
1086                     break;
1087                 default:
1088                     transaction->state = RM_ERROR_INVALID_SERVICE_TYPE;
1089                     break;
1090             }
1091         }
1093         if (transaction->state == RM_SERVICE_PROCESSING) {
1094             uint32_t transId = transaction->localId;
1096             /* NameServer transaction or CD could not complete alloc/free
1097              * transaction.  Forward to Server */
1098             transactionForwarder(rmInst, transaction);
1100             /* Refresh transaction for reentrancy of cases where mix of Client
1101              * CD and Server are running on the same core and connected via
1102              * transport implemented over direct function calls instead of
1103              * traditional transport that returns after sending the data */
1104             transaction = rmTransactionQueueFind(rmInst, transId);
1105         }
1107         if (transaction) {
1108             if ((transaction->state != RM_SERVICE_PROCESSING) &&
1109                 (transaction->state != RM_SERVICE_PENDING_SERVER_RESPONSE)) {
1110                 /* Transaction completed by CD or completed response received
1111                  * from Server.  Return result */
1112                 if (strncmp(transaction->serviceSrcInstName, rmInst->instName,
1113                     RM_NAME_MAX_CHARS)) {
1114                     /* Transaction did not originate on this instance */
1115                     transactionResponder(rmInst, transaction);
1116                 } else {
1117                     /* Transaction originated on this instance */
1118                     serviceResponder(rmInst, transaction);
1119                 }
1120             }
1121         }
1123         /* Attempt allocation of any queued static requests:
1124          * RM_SERVICE_APPROVED_STATIC - Originated locally
1125          * RM_SERVICE_PROCESSING - Received from any registered Clients */
1126         transQ = rmInst->transactionQueue;
1127         while(transQ) {
1128             if (((transQ->state == RM_SERVICE_PROCESSING) ||
1129                  (transQ->state == RM_SERVICE_APPROVED_STATIC)) &&
1130                 (!transQ->hasBeenForwarded)) {
1131                 transactionForwarder(rmInst, transQ);
1132             }
1133             transQ = transQ->nextTransaction;
1134         }
1135     }
1138 /* FUNCTION PURPOSE: Server transaction handling process
1139  ***********************************************************************
1140  * DESCRIPTION: Server process for handling transactions created
1141  *              from services received via the service handle or the
1142  *              transport.  The Server process:
1143  *                  - Validates all service requests received from
1144  *                    the service handle and registered CDs and
1145  *                    Clients
1146  */
1147 static void serverProcess(Rm_Inst *rmInst, Rm_Transaction *transaction)
1149     Rm_NameServerObjCfg  nameServerObjCfg;
1151     switch (transaction->type) {
1152         case Rm_service_RESOURCE_STATUS:
1153             statusHandler(rmInst, transaction);
1154             break;
1155         case Rm_service_RESOURCE_ALLOCATE_INIT:
1156         case Rm_service_RESOURCE_ALLOCATE_USE:
1157             allocationHandler(rmInst, transaction);
1158             break;
1159         case Rm_service_RESOURCE_FREE:
1160             freeHandler(rmInst, transaction);
1161             break;
1162         case Rm_service_RESOURCE_MAP_TO_NAME:
1163         case Rm_service_RESOURCE_GET_BY_NAME:
1164         case Rm_service_RESOURCE_UNMAP_NAME:
1165             if (rmInst->u.server.nameServer) {
1166                 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1167                     rmNameServerTreeInv(rmInst->u.server.nameServer);
1168                 }                
1169                 memset((void *)&nameServerObjCfg, 0,
1170                        sizeof(Rm_NameServerObjCfg));
1171                 nameServerObjCfg.nameServerTree = rmInst->u.server.nameServer;
1172                 nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
1173                 if (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) {
1174                     nameServerObjCfg.nodeCfg.resourceName = transaction->resourceInfo.name;
1175                     nameServerObjCfg.nodeCfg.resourceBase= transaction->resourceInfo.base;
1176                     nameServerObjCfg.nodeCfg.resourceLength = transaction->resourceInfo.length;
1177                     transaction->state = rmNameServerAddObject(&nameServerObjCfg);
1178                 } else if (transaction->type ==
1179                            Rm_service_RESOURCE_GET_BY_NAME) {
1180                     if ((transaction->state = rmNameServerFindObject(&nameServerObjCfg)) ==
1181                         RM_SERVICE_PROCESSING) {
1182                         rm_strncpy(transaction->resourceInfo.name,
1183                                    nameServerObjCfg.nodeCfg.resourceName,
1184                                    RM_NAME_MAX_CHARS);
1185                         transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;
1186                         transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;
1187                         transaction->state = RM_SERVICE_APPROVED;
1188                     }
1189                 } else if (transaction->type ==
1190                            Rm_service_RESOURCE_UNMAP_NAME) {
1191                     transaction->state = rmNameServerDeleteObject(&nameServerObjCfg);
1192                 } else {
1193                     transaction->state = RM_ERROR_INVALID_SERVICE_TYPE;
1194                 }
1196                 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1197                     rmNameServerTreeWb(rmInst->u.server.nameServer);
1198                 }
1199             } else {
1200                 transaction->state = RM_ERROR_NAMESERVER_DOES_NOT_EXIST;
1201             }
1202             break;
1203         default:
1204             transaction->state = RM_ERROR_INVALID_SERVICE_TYPE;
1205             break;
1206     }
1208     /* Source of shared server transaction will always be local. */
1209     if (rmInst->instType != Rm_instType_SHARED_SERVER) {
1210         if (strncmp(transaction->serviceSrcInstName, rmInst->instName,
1211                     RM_NAME_MAX_CHARS)) {
1212             /* Source of transaction was not Server, return transaction via
1213              * responder */
1214             transactionResponder(rmInst, transaction);
1215         }
1216     }
1217     /* Otherwise let call stack return transaction result app via
1218      * Rm_serviceHandler */ 
1221 /**********************************************************************
1222  ********************** Internal Functions ****************************
1223  **********************************************************************/
1225 /* FUNCTION PURPOSE: Adds a transaction
1226  ***********************************************************************
1227  * DESCRIPTION: Returns a pointer to a newly created transaction.
1228  *              The transaction is created based on a new service
1229  *              request received via the service API or the
1230  *              transport API (service forwarded from another instance)
1231  */
1232 Rm_Transaction *rmTransactionQueueAdd(Rm_Inst *rmInst)
1234     Rm_Transaction *transactionQueue = rmInst->transactionQueue;
1235     Rm_Transaction *newTransaction   = NULL;
1237     newTransaction = Rm_osalMalloc(sizeof(Rm_Transaction));
1238     if (newTransaction) {
1239         memset((void *)newTransaction, 0, sizeof(Rm_Transaction));
1241         newTransaction->localId = transactionGetSequenceNum(rmInst);
1242         newTransaction->nextTransaction = NULL;  
1243         if (transactionQueue) {
1244             while (transactionQueue->nextTransaction) {
1245                 transactionQueue = transactionQueue->nextTransaction;
1246             }
1247             transactionQueue->nextTransaction = newTransaction;
1248         } else {
1249             rmInst->transactionQueue = newTransaction;
1250         }
1251     }
1252     return(newTransaction);
1255 /* FUNCTION PURPOSE: Finds a transaction
1256  ***********************************************************************
1257  * DESCRIPTION: Returns a pointer to a transaction resident
1258  *              in the transaction queue that matches the provided
1259  *              transaction ID.
1260  */
1261 Rm_Transaction *rmTransactionQueueFind(Rm_Inst *rmInst, uint32_t transactionId)
1263     Rm_Transaction *transaction = rmInst->transactionQueue;
1265     while (transaction) {
1266         if (transaction->localId == transactionId) {
1267             break;
1268         }
1269         transaction = transaction->nextTransaction;
1270     }
1272     return(transaction);
1275 /* FUNCTION PURPOSE: Deletes a transaction
1276  ***********************************************************************
1277  * DESCRIPTION: Deletes the transaction with the provided transaction
1278  *              ID from the instance's transaction queue.
1279  */
1280 int32_t rmTransactionQueueDelete(Rm_Inst *rmInst, uint32_t transactionId)
1282     Rm_Transaction *transaction = rmInst->transactionQueue;
1283     Rm_Transaction *prevTransaction = NULL;
1284     int32_t         retVal = RM_OK;
1286     while (transaction) {
1287         if (transaction->localId == transactionId) {
1288             break;
1289         }
1291         prevTransaction = transaction;
1292         transaction = transaction->nextTransaction;
1293     }
1295     if (transaction) {
1296         if (prevTransaction == NULL) {
1297             /* Transaction at start of queue. Map second transaction to start
1298              * of queue as long as more than one transactions. */
1299             rmInst->transactionQueue = transaction->nextTransaction;
1300         } else {
1301             /* Transaction in middle or end of queue. */
1302             prevTransaction->nextTransaction = transaction->nextTransaction;
1303         }
1304         Rm_osalFree((void *)transaction, sizeof(Rm_Transaction));
1305     } else {
1306         retVal = RM_ERROR_SERVICE_TRANS_DOES_NOT_EXIST;
1307     }
1308     return(retVal);
1311 /* FUNCTION PURPOSE: Routes a transaction for processing
1312  ***********************************************************************
1313  * DESCRIPTION: Routes a received transaction to the appropriate
1314  *              instance processing routine
1315  */
1316 void rmProcessRouter(Rm_Inst *rmInst, Rm_Transaction *transaction)
1318     if (rmInst->instType == Rm_instType_CLIENT) {
1319         clientProcess(rmInst, transaction);
1320     } else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1321         cdProcess(rmInst, transaction);
1322     } else if ((rmInst->instType == Rm_instType_SERVER) ||
1323                (rmInst->instType == Rm_instType_SHARED_SERVER)) {
1324         serverProcess(rmInst, transaction);
1325     } else {
1326         transaction->state = RM_ERROR_INVALID_INST_TYPE;
1327     }
1330 /**********************************************************************
1331  ********************** Application visible APIs **********************
1332  **********************************************************************/
1334 /* FUNCTION PURPOSE: Display status of managed resources
1335  ***********************************************************************
1336  * DESCRIPTION: Prints the status (allocate/free status, as well as
1337  *              owners) for all resources managed by the RM 
1338  *              instance network.  Also, prints the NameServer name
1339  *              entries.  The number of resource range owners is
1340  *              returned as well.  This function is only available on
1341  *              Server and CD instances.
1342  */
1343 int32_t Rm_resourceStatus(Rm_Handle rmHandle, int printResources)
1345     Rm_Inst          *rmInst = (Rm_Inst *)rmHandle;
1346     Rm_AllocatorTree *allocTree = NULL;
1347     Rm_AllocatorNode *allocator;
1348     Rm_Owner         *owners;
1349     Rm_ResourceTree  *treeRoot;
1350     Rm_ResourceNode  *treeNode;
1351     int32_t           totalResOwners = 0;
1352     void             *key;
1353     void             *mtKey;
1355     RM_SS_INST_INV_ENTER_CS(rmInst, key);
1356     RM_SC_INST_INV_ENTER_CS(rmInst, key);
1357     if (rmInst->mtSemObj) {
1358         mtKey = Rm_osalMtCsEnter(rmInst->mtSemObj);
1359     }
1361     if (rmInst->instType != Rm_instType_CLIENT) {
1362         Rm_osalLog("Instance name: %s\n", rmInst->instName);
1363         Rm_osalLog("Handle: 0x%08x\n", rmHandle);
1364         if (rmInst->instType == Rm_instType_SERVER) {
1365             Rm_osalLog("Type:   Server\n");
1366         } else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1367             Rm_osalLog("Type:   Client Delegate\n");
1368         } else if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1369             Rm_osalLog("Type:   Shared Server\n");
1370         } else if (rmInst->instType == Rm_instType_SHARED_CLIENT) {
1371             Rm_osalLog("Type:   Shared Client\n");
1372         } else {
1373             Rm_osalLog("Type:   UNKNOWN\n");
1374             goto errorExit;
1375         }
1377         Rm_osalLog("\nResource Status:\n\n");
1378     }
1380     if (rmInst->instType == Rm_instType_SHARED_CLIENT) {
1381         /* Transfer control to shared server instance */
1382         rmInst = rmInst->u.sharedClient.sharedServerHandle;
1383     }
1385     if ((rmInst->instType == Rm_instType_SERVER) ||
1386         (rmInst->instType == Rm_instType_SHARED_SERVER) ||
1387         (rmInst->instType == Rm_instType_CLIENT_DELEGATE)) {
1389         allocTree = rmInst->allocatorTree;
1390         if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1391             rmAllocatorTreeInv(allocTree);
1392         }
1394         RB_FOREACH(allocator, _Rm_AllocatorTree, allocTree) {
1395             RM_SS_OBJ_INV(rmInst, allocator, Rm_AllocatorNode);
1396             if (printResources) {
1397                 Rm_osalLog("Resource: %s\n", allocator->resourceName);
1398             }
1400             treeRoot = allocator->resourceRoot;
1401             if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1402                 rmResourceTreeInv(treeRoot);
1403             }
1404             RB_FOREACH(treeNode, _Rm_AllocatorResourceTree, treeRoot) {
1405                 if (printResources) {
1406                     if ((treeNode->base >= 65536) ||
1407                         ((treeNode->base + treeNode->length - 1) >= 65536)) {
1408                         /* Print in hex if number is very large */
1409                         Rm_osalLog("          0x%08x - 0x%08x ",
1410                                    treeNode->base,
1411                                    treeNode->base + treeNode->length - 1);
1412                     } else {
1413                         Rm_osalLog("          %10d - %10d ",
1414                                    treeNode->base,
1415                                    treeNode->base + treeNode->length - 1);
1416                     }
1417                 }
1419                 if (treeNode->allocationCount == 0) {
1420                     if (printResources) {
1421                         Rm_osalLog("FREE\n");
1422                     }
1423                 } else {
1424                     owners = treeNode->ownerList;
1425                     while (owners) {
1426                         RM_SS_OBJ_INV(rmInst, owners, Rm_Owner);
1427                         if (printResources) {
1428                             Rm_osalLog("%s (%d) ", owners->instNameNode->name,
1429                                        owners->refCnt);
1430                         }
1431                         totalResOwners++;
1432                         owners = owners->nextOwner;
1433                     }
1434                     if (printResources) {
1435                         Rm_osalLog("\n");
1436                     }
1437                 }
1438             }
1439         }
1441         if ((rmInst->instType == Rm_instType_SERVER) ||
1442             (rmInst->instType == Rm_instType_SHARED_SERVER)) {
1443             if (printResources) {
1444                 rmNameServerPrintObjects((Rm_Handle)rmInst);
1445             }
1446         }
1447     } else {
1448         totalResOwners = RM_ERROR_INVALID_RES_STATUS_INSTANCE;
1449     }
1451 errorExit:
1452     /* Free sem object using originating instance in case the Shared Client to Shared
1453      * Server instance switch took place */
1454     if (((Rm_Inst *)rmHandle)->mtSemObj) {
1455         Rm_osalMtCsExit(((Rm_Inst *)rmHandle)->mtSemObj, mtKey);
1456     }
1457     RM_SS_INST_WB_EXIT_CS(rmInst, key);
1458     return(totalResOwners);
1461 /* FUNCTION PURPOSE: Display status of a RM instance
1462  ***********************************************************************
1463  * DESCRIPTION: Prints the current status of various RM instance
1464  *              properties such as the state of all transactions
1465  *              in the transaction queue and registered transports
1466  */
1467 void Rm_instanceStatus(Rm_Handle rmHandle)
1469     Rm_Inst        *rmInst = (Rm_Inst *)rmHandle;
1470     Rm_Transport   *transportList = NULL;
1471     Rm_Transaction *transactionQ = NULL;
1472     void           *key;
1473     void           *mtKey;
1475     RM_SS_INST_INV_ENTER_CS(rmInst, key);
1476     RM_SC_INST_INV_ENTER_CS(rmInst, key);
1477     if (rmInst->mtSemObj) {
1478         mtKey = Rm_osalMtCsEnter(rmInst->mtSemObj);
1479     }
1481     Rm_osalLog("Instance name: %s\n", rmInst->instName);
1482     Rm_osalLog("Handle: 0x%08x\n", rmHandle);    
1483     if (rmInst->instType == Rm_instType_SERVER) {
1484         Rm_osalLog("Type:   Server\n");
1485     } else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1486         Rm_osalLog("Type:   Client Delegate\n");
1487     } else if (rmInst->instType == Rm_instType_CLIENT) {
1488         Rm_osalLog("Type:   Client\n");
1489     } else if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1490         Rm_osalLog("Type:   Shared Server\n");
1491     } else if (rmInst->instType == Rm_instType_SHARED_CLIENT) {
1492         Rm_osalLog("Type:   Shared Client\n");
1494         Rm_osalLog("\nShared Server Properties:\n");
1495         /* Transfer to Shared Server instance to print out transport and
1496          * transaction status */
1497         rmInst = rmInst->u.sharedClient.sharedServerHandle;
1498         Rm_osalLog("Instance name: %s\n", rmInst->instName);
1499         Rm_osalLog("Handle: 0x%08x\n", rmHandle);
1500     } else {
1501         Rm_osalLog("Type:   UNKNOWN\n");
1502         goto errorExit;
1503     }
1505     transportList = rmInst->transports;
1506     if (transportList) {
1507         Rm_osalLog("\nRegistered Transports:\n");
1508         while (transportList) {
1509             RM_SS_OBJ_INV(rmInst, transportList, Rm_Transport);
1510             if (transportList->remoteInstType == Rm_instType_SERVER) {
1511                 Rm_osalLog("    Remote instType:    Server\n");
1512             } else if (transportList->remoteInstType ==
1513                        Rm_instType_CLIENT_DELEGATE) {
1514                 Rm_osalLog("    Remote instType:    Client Delegate\n");
1515             } else {
1516                 Rm_osalLog("    Remote instType:    Client\n");
1517             }
1518             Rm_osalLog("    appTransportHandle: 0x%08x\n",
1519                        transportList->appTransportHandle);
1520             Rm_osalLog("\n");
1521             transportList = transportList->nextTransport;
1522         }
1523     }
1525     transactionQ = rmInst->transactionQueue;
1526     if (transactionQ) {
1527         Rm_osalLog("\nQueued Service Transactions:\n");
1528         while (transactionQ) {
1529             RM_SS_OBJ_INV(rmInst, transactionQ, Rm_Transaction);
1530             Rm_osalLog("    Service type:       %d\n",
1531                        transactionQ->type);
1532             Rm_osalLog("    Service ID:         %d\n", transactionQ->localId);
1533             Rm_osalLog("    Service srcInstName %s\n",
1534                        transactionQ->serviceSrcInstName);
1535             Rm_osalLog("    Service state:      %d\n", transactionQ->state);
1536             Rm_osalLog("    Resource name:      %s\n",
1537                        transactionQ->resourceInfo.name);
1538             Rm_osalLog("    Resource base:      %d\n",
1539                        transactionQ->resourceInfo.base);
1540             Rm_osalLog("    Resource length:    %d\n",
1541                        transactionQ->resourceInfo.length);
1542             Rm_osalLog("    Resource alignment: %d\n",
1543                        transactionQ->resourceInfo.alignment);
1544             Rm_osalLog("    Resource NS name:   %s\n",
1545                        transactionQ->resourceInfo.nameServerName);
1546             Rm_osalLog("\n");
1547             transactionQ = transactionQ->nextTransaction;
1548         }
1549     }
1551 errorExit:
1552     /* Free sem object using originating instance in case the Shared Client
1553      * to Shared Server instance switch took place */
1554     if (((Rm_Inst *)rmHandle)->mtSemObj) {
1555         Rm_osalMtCsExit(((Rm_Inst *)rmHandle)->mtSemObj, mtKey);
1556     }
1557     RM_SS_INST_WB_EXIT_CS(rmInst, key);
1560 /* FUNCTION PURPOSE: RM instance creation and initialization
1561  ***********************************************************************
1562  * DESCRIPTION: Returns a new RM instance created and initialized
1563  *              using the parameters provided via the initCfg
1564  *              structure.
1565  */
1566 Rm_Handle Rm_init(const Rm_InitCfg *initCfg, int32_t *result)
1568     Rm_Inst  *rmInst = NULL;
1569     void     *grlDtb = NULL;
1570     void     *policyDtb = NULL;
1571     void     *linuxDtb = NULL;
1572     int       addLinux = RM_FALSE;
1573     void     *key;
1575     *result = RM_OK;
1577     if ((initCfg->instName == NULL) ||
1578         ((strlen(initCfg->instName) + 1) > RM_NAME_MAX_CHARS)) {
1579         *result = RM_ERROR_INVALID_INST_NAME;
1580         goto errorExit;
1581     }
1583     if (initCfg->instType >= Rm_instType_LAST) {
1584         *result = RM_ERROR_INVALID_INST_TYPE;
1585         goto errorExit;
1586     }
1588     /* Create and initialize instance */
1589     rmInst = Rm_osalMalloc(sizeof(*rmInst));
1590     memset((void *)rmInst, 0, sizeof(*rmInst));
1591     rmInst->isLocked = RM_FALSE;
1592     rmInst->registeredWithDelegateOrServer = RM_FALSE;
1593     rmInst->transactionSeqNum = transactionInitSequenceNum();
1595     rmInst->instType = initCfg->instType;
1596     rm_strncpy(rmInst->instName, initCfg->instName, RM_NAME_MAX_CHARS);
1597     rmInst->mtSemObj = initCfg->mtSemObj;
1599     if ((rmInst->instType == Rm_instType_SERVER) ||
1600         (rmInst->instType == Rm_instType_SHARED_SERVER)) {
1601         if (!initCfg->instCfg.serverCfg.globalResourceList ||
1602             !initCfg->instCfg.serverCfg.globalPolicy) {
1603             *result = RM_ERROR_INVALID_SERVER_CONFIGURATION;
1604             goto errorExit;
1605         }
1607         if (initCfg->instCfg.serverCfg.linuxDtb) {
1608             linuxDtb = initCfg->instCfg.serverCfg.linuxDtb;
1609             addLinux = RM_TRUE;
1610         }
1612         /* Create valid instance list from policy.  Must be done prior to
1613          * parsing GRL so that Linux resources can be reserved correctly */
1614         policyDtb = initCfg->instCfg.serverCfg.globalPolicy;
1615         rmInst->validInstTree = rmPolicyVInstTreeInit(rmInst, policyDtb,
1616                                                       addLinux, result);
1617         if (*result != RM_OK) {
1618             goto errorExit;
1619         }
1621         rmNameServerInit((Rm_Handle)rmInst);
1622         grlDtb = initCfg->instCfg.serverCfg.globalResourceList;
1623         if ((*result = rmAllocatorTreeInit(rmInst, grlDtb,
1624                                            policyDtb, linuxDtb)) != RM_OK) {
1625             goto errorExit;
1626         }
1627     } else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1628         if (!initCfg->instCfg.cdCfg.cdPolicy) {
1629             *result = RM_ERROR_INVALID_CD_CONFIGURATION;
1630             goto errorExit;
1631         }
1633         policyDtb = initCfg->instCfg.cdCfg.cdPolicy;
1634         rmInst->validInstTree = rmPolicyVInstTreeInit(rmInst, policyDtb,
1635                                                       addLinux, result);
1636         if (*result != RM_OK) {
1637             goto errorExit;
1638         }
1640         if ((*result = rmAllocatorTreeInit(rmInst, NULL,
1641                                            policyDtb, NULL)) != RM_OK) {
1642             goto errorExit;
1643         }
1645         /* Remove once CD instance is stable - tracked by SDOCM00100797 */
1646         *result = RM_WARNING_CD_INSTANCE_NOT_STABLE;
1648     } else if (rmInst->instType == Rm_instType_CLIENT) {
1649         if (initCfg->instCfg.clientCfg.staticPolicy) {
1650             policyDtb = initCfg->instCfg.clientCfg.staticPolicy;
1651             rmInst->validInstTree = rmPolicyVInstTreeInit(rmInst, policyDtb,
1652                                                           addLinux, result);
1653             if (*result != RM_OK) {
1654                 goto errorExit;
1655             }
1657             if ((*result = rmAllocatorTreeInit(rmInst, NULL,
1658                                                policyDtb, NULL)) != RM_OK) {
1659                 goto errorExit;
1660             }
1661         }
1662         
1663     } else if (rmInst->instType == Rm_instType_SHARED_CLIENT) {
1664         Rm_Handle  sHdl = initCfg->instCfg.sharedClientCfg.sharedServerHandle;
1665         Rm_Inst   *ssInst = NULL;
1667         if (sHdl) {
1668             rmInst->u.sharedClient.sharedServerHandle = sHdl;
1669             /* Invalidate the Shared server instance structure on this core to
1670              * get the latest instance data. */
1671             key = Rm_osalCsEnter();
1672             Rm_osalBeginMemAccess((void *)sHdl, sizeof(Rm_Inst));
1673             ssInst = rmInst->u.sharedClient.sharedServerHandle;
1674             if (ssInst->instType != Rm_instType_SHARED_SERVER) {
1675                 *result = RM_ERROR_INVALID_SHARED_SERVER_HANDLE;
1676                 Rm_osalCsExit(key);
1677                 goto errorExit;
1678             } else {
1679                 /* Invalidate all the trees */
1680                 rmPolicyValidInstTreeInv(ssInst->validInstTree);
1681                 rmAllocatorTreeInv(ssInst->allocatorTree);
1682                 rmNameServerTreeInv(ssInst->u.server.nameServer);
1683             }
1684             Rm_osalCsExit(key);
1685         } else {
1686             *result = RM_ERROR_INVALID_SHARED_SERVER_HANDLE;
1687             goto errorExit;
1688         }
1689     } else {
1690         *result = RM_ERROR_INVALID_INST_TYPE;
1691         goto errorExit;
1692     }
1694     if (initCfg->instType == Rm_instType_SHARED_SERVER) {
1695         /* Writeback instance and trees for other cores */
1696         rmPolicyValidInstTreeWb(rmInst->validInstTree);
1697         rmAllocatorTreeWb(rmInst->allocatorTree);
1698         rmNameServerTreeWb(rmInst->u.server.nameServer);
1699         Rm_osalEndMemAccess((void *)rmInst, sizeof(*rmInst));
1700     } else if (rmInst->instType != Rm_instType_SHARED_CLIENT) {
1701         /* Create the instance's task blocking mechanism */
1702         rmInst->blockHandle = Rm_osalTaskBlockCreate();
1703     }
1704     /* else: fall through */
1706     return((Rm_Handle)rmInst);
1708 errorExit:
1709     if (rmInst) {
1710         rmAllocatorTreeDelete((Rm_Handle)rmInst);
1711         rmNameServerDelete((Rm_Handle)rmInst);
1712         rmPolicyVInstTreeDelete((Rm_Handle)rmInst);
1713         Rm_osalFree((void *)rmInst, sizeof(*rmInst));
1714     }
1715     return(NULL);
1718 /* FUNCTION PURPOSE: Deletes an RM instance
1719  ***********************************************************************
1720  * DESCRIPTION: Frees all memory associated with an RM instance
1721  *              as long as all transports have been unregistered
1722  *              and the service handle has been closed
1723  */
1724 int32_t Rm_delete(Rm_Handle rmHandle, int ignorePendingServices)
1726     Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
1727     void    *key;
1729     key = Rm_osalCsEnter();
1730     if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1731         Rm_osalBeginMemAccess((void *)rmInst, sizeof(*rmInst));
1732     }
1734     if (rmInst->serviceHandle) {
1735         return(RM_ERROR_CANT_DELETE_WITH_OPEN_SERV_HNDL);
1736     } else if (rmInst->transports) {
1737         return(RM_ERROR_CANT_DELETE_WITH_REGD_TRANSPORT);
1738     } else if (rmInst->transactionQueue && !ignorePendingServices) {
1739         return(RM_ERROR_CANT_DELETE_PENDING_TRANSACTIONS);
1740     }
1741     /* else: delete instance since no more deletion failure cases */
1743     if (rmInst->instType != Rm_instType_SHARED_CLIENT) {
1744         rmNameServerDelete(rmHandle);
1745         rmAllocatorTreeDelete(rmHandle);
1746         rmPolicyVInstTreeDelete(rmHandle);
1748         /* Delete any transactions */
1749         while(rmInst->transactionQueue) {
1750             rmTransactionQueueDelete(rmInst, rmInst->transactionQueue->localId);
1751         }
1753         if (rmInst->instType != Rm_instType_SHARED_SERVER) {
1754             /* Delete the instance's task blocking mechanism */
1755             Rm_osalTaskBlockDelete(rmInst->blockHandle);
1756         } else {
1757             rmInst->allocatorTree       = NULL;
1758             rmInst->validInstTree       = NULL;
1759             rmInst->u.server.nameServer = NULL;
1760             Rm_osalEndMemAccess((void *)rmInst, sizeof(*rmInst));
1761         }
1762     }
1764     Rm_osalFree((void *)rmInst, sizeof(*rmInst));
1765     Rm_osalCsExit(key);
1766     return(RM_OK);
1769 /* FUNCTION PURPOSE: Returns RM version information
1770  ***********************************************************************
1771  */
1772 uint32_t Rm_getVersion(void)
1774     return(RM_VERSION_ID);
1777 /* FUNCTION PURPOSE: Returns RM version string
1778  ***********************************************************************
1779  */
1780 const char* Rm_getVersionStr(void)
1782     return(rmVersionStr);