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