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