]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - keystone-rtos/rm-lld.git/blob - src/rm.c
84018395caed08999d8f810d7c4ac6672550eef4
[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_FREE) {
127         resourceReqPkt->resourceReqType = Rm_resReqPktType_FREE;
128     }
129     else if (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) {
130         resourceReqPkt->resourceReqType = Rm_resReqPktType_GET_NAMED;
131     }
132     strncpy(resourceReqPkt->pktSrcInstName, localInstName, RM_NAME_MAX_CHARS);
133     strncpy(resourceReqPkt->serviceSrcInstName, transaction->serviceSrcInstName, RM_NAME_MAX_CHARS);
134     memcpy ((void *)&(resourceReqPkt->resourceInfo), (void *)&(transaction->resourceInfo),
135             sizeof(Rm_ResourceInfo));
138 /* FUNCTION PURPOSE: Creates a resource response packet
139  ***********************************************************************
140  * DESCRIPTION: Returns a RM packet handle that points to a RM
141  *              resource response packet that has been prepared
142  *              for sending to another RM instance.  The packet
143  *              is allocated via the rmAllocPkt API using the
144  *              appTransport handle provided by the application
145  */
146 void createResourceResponsePkt(Rm_Packet *rmPkt, Rm_Transaction *transaction)
148     Rm_ResourceResponsePkt *resourceRespPkt = NULL;
149      
150     rmPkt->pktType = Rm_pktType_RESOURCE_RESPONSE;                 
151     resourceRespPkt = (Rm_ResourceResponsePkt *)rmPkt->data;
152     resourceRespPkt->responseId = transaction->remoteOriginatingId;
153     resourceRespPkt->requestState = transaction->state;
154     memcpy ((void *)&(resourceRespPkt->resourceInfo), (void *)&(transaction->resourceInfo),
155             sizeof(Rm_ResourceInfo));
158 /* FUNCTION PURPOSE: Creates a NameServer request packet
159  ***********************************************************************
160  * DESCRIPTION: Returns a RM packet handle that points to a RM
161  *              NameServer request packet that has been prepared
162  *              for sending to another RM instance.  The packet
163  *              is allocated via the rmAllocPkt API using the
164  *              appTransport handle provided by the application
165  */
166 void createNsRequestPkt(Rm_Packet *rmPkt, char *localInstName, Rm_Transaction *transaction)
167
168     Rm_NsRequestPkt *nsReqPkt = NULL;
170     rmPkt->pktType = Rm_pktType_NAMESERVER_REQUEST;                   
171     nsReqPkt = (Rm_NsRequestPkt *)rmPkt->data;
172     nsReqPkt->requestId = transaction->localId;
173     if (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) {
174         nsReqPkt->nsRequestType = Rm_nsReqPktType_MAP_RESOURCE;
175     }
176     else if (transaction->type == Rm_service_RESOURCE_UNMAP_NAME) {
177         nsReqPkt->nsRequestType = Rm_nsReqPktType_UNMAP_RESOURCE;
178     }
179     strncpy(nsReqPkt->pktSrcInstName, localInstName, RM_NAME_MAX_CHARS);
180     strncpy(nsReqPkt->serviceSrcInstName, transaction->serviceSrcInstName, RM_NAME_MAX_CHARS);
181     memcpy ((void *)&(nsReqPkt->resourceInfo), (void *)&(transaction->resourceInfo),
182             sizeof(Rm_ResourceInfo));
185 /* FUNCTION PURPOSE: Creates a NameServer response packet
186  ***********************************************************************
187  * DESCRIPTION: Returns a RM packet handle that points to a RM
188  *              NameServer response packet that has been prepared
189  *              for sending to another RM instance.  The packet
190  *              is allocated via the rmAllocPkt API using the
191  *              appTransport handle provided by the application
192  */
193 void createNsResponsePkt(Rm_Packet *rmPkt, Rm_Transaction *transaction)
195     Rm_NsResponsePkt *nsRespPkt = NULL;
197     rmPkt->pktType = Rm_pktType_NAMESERVER_RESPONSE;                
198     nsRespPkt = (Rm_NsResponsePkt *)rmPkt->data;
199     nsRespPkt->responseId = transaction->remoteOriginatingId;
200     nsRespPkt->requestState = transaction->state;
203 /* FUNCTION PURPOSE: Issues a service response to application
204  ***********************************************************************
205  * DESCRIPTION: Provides a service response back to the application
206  *              using the service callback function provided to
207  *              the RM instance at the time of the service request.
208  */
209 static void serviceResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)
211     Rm_ServiceRespInfo serviceResponse;
213     serviceResponse.rmHandle = (Rm_Handle)rmInst;
214     /* The responseTransaction will contain the resultant state details of
215      * the requestTransaction's service request */
216     serviceResponse.serviceState = transaction->state;
217     /* Pass back the ID that was provided to the component when it requested
218      * the service */
219     serviceResponse.serviceId = transaction->localId;
221     /* Service was approved and service was an allocate request.  The resource
222      * data is passed back to the component */
223     if ((serviceResponse.serviceState == RM_SERVICE_APPROVED) &&
224         ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||
225          (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) ||
226          (transaction->type == Rm_service_RESOURCE_GET_BY_NAME)))
227     {
228         strncpy(serviceResponse.resourceName, transaction->resourceInfo.name, RM_NAME_MAX_CHARS);
229         serviceResponse.resourceBase = transaction->resourceInfo.base;
230         serviceResponse.resourceLength = transaction->resourceInfo.length;
231     }
233     if (transaction->callback.serviceCallback) {
234         /* Issue the callback to the requesting component with the response information */
235         transaction->callback.serviceCallback(&serviceResponse);
236         /* Delete the transaction from the transaction queue */
237         rmTransactionQueueDelete(rmInst, transaction->localId);
238     }
239     else {
240         rmServiceInternalCallback((Rm_Handle)rmInst);
241     }
242     
243     return;
246 /* FUNCTION PURPOSE: Sends RM response packets
247  ***********************************************************************
248  * DESCRIPTION: Sends RM response packets to RM instance's that sent
249  *              RM request packets to the RM instance.  The response
250  *              is sent via the RM transport API which is plugged
251  *              with an application created transport path.
252  */
253 static void transactionResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)
255     Rm_Transport    *dstTransport = NULL;
256     Rm_Packet       *rmPkt = NULL;
257     Rm_PacketHandle  pktHandle = NULL;
259     if (dstTransport = rmTransportFindRemoteName(rmInst->transports, transaction->pktSrcInstName)) {
260         rmPkt = dstTransport->callouts.rmAllocPkt(dstTransport->appTransportHandle, 
261                                                   sizeof(Rm_Packet), &pktHandle);
262         if (!rmPkt || !pktHandle) {
263             transaction->state = RM_ERROR_TRANSPORT_ALLOC_PKT_ERROR;
264             goto errorExit;
265         }
267         switch (transaction->type) {
268             case Rm_service_RESOURCE_ALLOCATE_INIT:
269             case Rm_service_RESOURCE_ALLOCATE_USE:
270             case Rm_service_RESOURCE_FREE:
271             case Rm_service_RESOURCE_GET_BY_NAME:
272                 createResourceResponsePkt(rmPkt, transaction);
273                 break;
274             case Rm_service_RESOURCE_MAP_TO_NAME:
275             case Rm_service_RESOURCE_UNMAP_NAME:
276                 createNsResponsePkt(rmPkt, transaction);
277                 break;
278         }
279         if (dstTransport->callouts.rmSendPkt(dstTransport->appTransportHandle, pktHandle) < RM_OK) {
280             transaction->state = RM_ERROR_TRANSPORT_SEND_ERROR;
281             goto errorExit;
282         }
283         
284         /* Response packet sent: Delete transaction from queue */
285         rmTransactionQueueDelete(rmInst, transaction->localId);
286     }
287     else {
288         transaction->state = RM_ERROR_TRANSPORT_REMOTE_HNDL_NOT_REGD;
289     }
290 errorExit:
291     /* Do not delete transaction on error.  Error transactions should be visible from
292      * from Rm_printInstanceStatus() */
293     return;
296 /* FUNCTION PURPOSE: Sends RM request packets
297  ***********************************************************************
298  * DESCRIPTION: Sends RM request packets to RM instance's that are
299  *              capable of forwarding or validating service requests.
300  *              The request is sent via the RM transport API which is
301  *              plugged with an application created transport path.
302  */
303 static void transactionForwarder (Rm_Inst *rmInst, Rm_Transaction *transaction)
305     Rm_Transport    *dstTransport = NULL;
306     Rm_Packet       *rmPkt = NULL;    
307     Rm_PacketHandle  pktHandle = NULL;
309     if (rmInst->instType == Rm_instType_CLIENT) {
310         dstTransport = rmTransportFindRemoteInstType(rmInst->transports, Rm_instType_CLIENT_DELEGATE);
312         if (!dstTransport) {
313             dstTransport = rmTransportFindRemoteInstType(rmInst->transports, Rm_instType_SERVER);
314         }
315     } 
316     else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
317         dstTransport = rmTransportFindRemoteInstType(rmInst->transports, Rm_instType_SERVER);
318     }
320     /* Just queue transaction if transport hasn't been registered.  Do not return error */
321     if (dstTransport) {            
322         rmPkt = dstTransport->callouts.rmAllocPkt(dstTransport->appTransportHandle, 
323                                                   sizeof(Rm_Packet), &pktHandle);
324         if (!rmPkt || !pktHandle) {
325             transaction->state = RM_ERROR_TRANSPORT_ALLOC_PKT_ERROR;
326             goto errorExit;
327         }
329         switch (transaction->type) {
330             case Rm_service_RESOURCE_ALLOCATE_INIT:
331             case Rm_service_RESOURCE_ALLOCATE_USE:
332             case Rm_service_RESOURCE_FREE:
333             case Rm_service_RESOURCE_GET_BY_NAME:
334                 createResourceReqPkt(rmPkt, rmInst->instName, transaction);
335                 break;
336             case Rm_service_RESOURCE_MAP_TO_NAME:
337             case Rm_service_RESOURCE_UNMAP_NAME:
338                 createNsRequestPkt(rmPkt, rmInst->instName, transaction);
339                 break;
340         }
341   
342         if (dstTransport->callouts.rmSendPkt(dstTransport->appTransportHandle, pktHandle) < RM_OK) {
343             transaction->state = RM_ERROR_TRANSPORT_SEND_ERROR;
344             goto errorExit;
345         }              
346         transaction->hasBeenForwarded = RM_TRUE;
347         /* Transaction not deleted.  Waiting for response from RM CD or Server */
348     }        
349 errorExit: 
350     return;
353 /* FUNCTION PURPOSE: Handles static allocation requests
354  ***********************************************************************
355  * DESCRIPTION: Validates allocation requests received on CDs and
356  *              Clients prior to the instance's registering
357  *              with a Server.  The allocation request is validated
358  *              against a static policy.
359  */
360 static void staticAllocationHandler (Rm_Handle rmHandle, Rm_Transaction *transaction)
362     Rm_Inst                *rmInst = (Rm_Inst *)rmHandle;
363     void                   *staticPolicy = rmPolicyGetPolicy(rmHandle);
364     Rm_PolicyCheckCfg       privCheckCfg;
365     
366     if (staticPolicy) {
367         if ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||
368             (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE)) {
369             /* Check request against startup policy */
370             memset((void *)&privCheckCfg, 0, sizeof(Rm_PolicyCheckCfg));
371     
372             if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
373                 privCheckCfg.type = Rm_policyCheck_INIT;
374             }
375             else {
376                 privCheckCfg.type = Rm_policyCheck_USE;
377             }
378             privCheckCfg.policyDtb = staticPolicy;
379             privCheckCfg.validInstNode = rmPolicyGetValidInstNode(rmHandle, rmInst->instName);
380             privCheckCfg.resourceOffset = rmPolicyGetResourceOffset(staticPolicy,
381                                                                     transaction->resourceInfo.name);
382             privCheckCfg.resourceBase = transaction->resourceInfo.base;
383             privCheckCfg.resourceLength = transaction->resourceInfo.length;
384     
385             if (rmPolicyCheckPrivilege(&privCheckCfg, &transaction->state)) {
386                 transaction->state = RM_SERVICE_APPROVED_STATIC;
387             }
388             else if (transaction->state == RM_SERVICE_PROCESSING) {
389                 /* Privilege check returned false without error */
390                 transaction->state = RM_SERVICE_DENIED_BY_STATIC_POLICY;
391             }
392         }
393         else {
394             transaction->state = RM_SERVICE_DENIED_INVALID_STATIC_REQUEST;
395         }
396     }
397     else {
398         transaction->state = RM_ERROR_REQ_FAILED_NO_STATIC_POLICY;
399     } 
402 /* FUNCTION PURPOSE: Arbitrates allocation service requests
403  ***********************************************************************
404  * DESCRIPTION: Issues a set of allocator operations in order to
405  *              handle a received allocation request.  Allocation
406  *              requests are always forwarded to the Server on Client
407  *              CD instances.  If a request is made with a NameServer
408  *              name the resource base and length parameters are
409  *              retrieved from the NameServer prior to the allocation
410  *              attempt.
411  */
412 static void allocationHandler (Rm_Inst *rmInst, Rm_Transaction *transaction)
414     Rm_AllocatorOpInfo  opInfo;
415     
416     Rm_NameServerObjCfg nameServerObjCfg;
417     int32_t             retVal = transaction->state;
419     if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
420         transactionForwarder(rmInst, transaction);   
421     }
422     else if ((rmInst->instType == Rm_instType_SERVER)||
423              (rmInst->instType == Rm_instType_SHARED_SERVER)) {
424         memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));
425         
426         opInfo.policy = rmInst->u.server.globalPolicy;
427         opInfo.resourceInfo = &transaction->resourceInfo;
428         opInfo.serviceSrcInstNode = rmPolicyGetValidInstNode((Rm_Handle)rmInst, transaction->serviceSrcInstName);
429         if (opInfo.serviceSrcInstNode) {
430             switch (transaction->type) {
431                 case Rm_service_RESOURCE_ALLOCATE_INIT:
432                     RM_policy_SET_PERM(opInfo.allocType, RM_POLICY_PERM_INIT_SHIFT, 1);
433                     break;
434                 case Rm_service_RESOURCE_ALLOCATE_USE:
435                     RM_policy_SET_PERM(opInfo.allocType, RM_POLICY_PERM_USE_SHIFT, 1);    
436                     break;
437             }        
439             /* Populated NameServer name has precedence over base */
440             if (strlen(transaction->resourceInfo.nameServerName) > 0) {
441                 if ((transaction->resourceInfo.base == 0) &&
442                     (transaction->resourceInfo.length == 0) &&
443                     (transaction->resourceInfo.alignment == 0)) {
444                     if (rmInst->instType == Rm_instType_SHARED_SERVER) {
445                         rmNameServerTreeInv(rmInst->u.server.nameServer);
446                     }
447                     memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
448                     nameServerObjCfg.nameServerTree = rmInst->u.server.nameServer;
449                     nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
450                     if ((retVal = rmNameServerFindObject(&nameServerObjCfg)) == RM_SERVICE_PROCESSING) {
451                         strncpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName, RM_NAME_MAX_CHARS);
452                         transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;
453                         transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;
454                     }                
455                 }
456                 else {
457                     retVal = RM_ERROR_NS_NAME_AND_RES_VAL_CONFLICT;
458                 }
459             }
461             if (retVal == RM_SERVICE_PROCESSING) {      
462                 if (transaction->resourceInfo.base == RM_RESOURCE_BASE_UNSPECIFIED) {
463                     opInfo.operation = Rm_allocatorOp_PRE_ALLOCATE;
464                     retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
465                 }
466             
467                 if (retVal == RM_SERVICE_PROCESSING) {
468                     opInfo.operation = Rm_allocatorOp_ALLOCATE;
469                     retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
470                 }      
471             }
472         }
473         else {
474             retVal = RM_SERVICE_DENIED_INST_NAME_NOT_VALID;
475         }
476         
477         transaction->state = retVal;                 
478     }   
481 /* FUNCTION PURPOSE: Arbitrates free service requests
482  ***********************************************************************
483  * DESCRIPTION: Issues a set of allocator operations in order to
484  *              handle a received free request.  Free
485  *              requests are always forwarded to the Server on Client
486  *              CD instances.  If a request is made with a NameServer
487  *              name the resource base and length parameters are
488  *              retrieved from the NameServer prior to the free
489  *              attempt.
490  */
491 static void freeHandler (Rm_Inst *rmInst, Rm_Transaction *transaction)
493     Rm_AllocatorOpInfo  opInfo; 
494     Rm_NameServerObjCfg nameServerObjCfg;    
495     int32_t             retVal = transaction->state;
496     
497     if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
498         transactionForwarder(rmInst, transaction);   
499     }
500     else if ((rmInst->instType == Rm_instType_SERVER) ||
501              (rmInst->instType == Rm_instType_SHARED_SERVER)) {
502         memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));
503         
504         opInfo.policy = rmInst->u.server.globalPolicy;
505         opInfo.resourceInfo = &transaction->resourceInfo;
506         opInfo.serviceSrcInstNode = rmPolicyGetValidInstNode((Rm_Handle)rmInst, transaction->serviceSrcInstName);
507         if (opInfo.serviceSrcInstNode) {
508             /* Populated NameServer name has precedence over base */
509             if (strlen(transaction->resourceInfo.nameServerName) > 0) {
510                 if ((transaction->resourceInfo.base == 0) &&
511                     (transaction->resourceInfo.length == 0) &&
512                     (transaction->resourceInfo.alignment == 0)) {
513                     if (rmInst->instType == Rm_instType_SHARED_SERVER) {
514                         rmNameServerTreeInv(rmInst->u.server.nameServer);
515                     }                    
516                     memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
517                     nameServerObjCfg.nameServerTree = rmInst->u.server.nameServer;
518                     nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
519                     if ((retVal = rmNameServerFindObject(&nameServerObjCfg)) == RM_SERVICE_PROCESSING) {
520                         strncpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName, RM_NAME_MAX_CHARS);
521                         transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;
522                         transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;
523                     } 
524                 }
525                 else {
526                     retVal = RM_ERROR_NS_NAME_AND_RES_VAL_CONFLICT;
527                 }                
528             }
529             
530             if(retVal == RM_SERVICE_PROCESSING) {        
531                 opInfo.operation = Rm_allocatorOp_FREE;
532                 retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
533             }    
534         }
535         else {
536             retVal = RM_SERVICE_DENIED_INST_NAME_NOT_VALID;
537         }
539         transaction->state = retVal;       
540     }   
543 /* FUNCTION PURPOSE: Client transaction handling process
544  ***********************************************************************
545  * DESCRIPTION: Client process for handling transactions created
546  *              from services received via the service handle or the
547  *              transport.  The Client process:
548  *                  - Performs static allocations if no transport
549  *                    to CD or Server has been registered
550  *                  - Forwards all service requests to CD or Server
551  *                    once transport has been registered
552  */
553 static void clientProcess (Rm_Inst *rmInst, Rm_Transaction *transaction)
555     Rm_Transaction    *transQ = rmInst->transactionQueue;
556     
557     if (!rmInst->registeredWithDelegateOrServer) {
558         staticAllocationHandler((Rm_Handle)rmInst, transaction);
559     }
560     else {
561         if (transaction->state == RM_SERVICE_PROCESSING) {
562             /* Forward all new transactions to CD or Server */
563             transactionForwarder(rmInst, transaction);                
564         }
565         else {
566             /* Transaction validated.  Return result. */
567             serviceResponder(rmInst, transaction);
568         }
570         /* Forward any queued static requests that weren't forwarded */
571         while(transQ) {
572             if ((transQ->state == RM_SERVICE_APPROVED_STATIC) &&
573                 (!transQ->hasBeenForwarded)) {
574                 transactionForwarder(rmInst, transQ);
575             }
576             transQ = transQ->nextTransaction;
577         }        
578     }
579     /* Let call stack return transaction result app via Rm_serviceHandler */
582 /* FUNCTION PURPOSE: Client Delegate transaction handling process
583  ***********************************************************************
584  * DESCRIPTION: Client Delegate process for handling transactions created
585  *              from services received via the service handle or the
586  *              transport.  The Client Delegate process:
587  *                  - Performs static allocations if no transport
588  *                    to Server has been registered
589  *                  - Forwards all NameServer related service requests 
590  *                    to Server once transport has been registered
591  *                  - Attempts to complete resource service requests
592  *                    received from registered Clients
593  */
594 static void clientDelegateProcess (Rm_Inst *rmInst, Rm_Transaction *transaction)
595 {        
596     Rm_Transaction *transQ = rmInst->transactionQueue;    
598     if (!rmInst->registeredWithDelegateOrServer) {
599         if ((transaction->state == RM_SERVICE_PROCESSING) &&
600             (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS) == 0)) {           
601             staticAllocationHandler((Rm_Handle)rmInst, transaction);
602         }
603         /* Everything else left in transaction queue for forwarding once transport to
604          * Server is registered */
605     }
606     else {
607         if ((transaction->state == RM_SERVICE_PROCESSING) ||
608             (transaction->state == RM_SERVICE_APPROVED_STATIC)) {        
609             if ((transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) ||
610                 (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) ||
611                 (transaction->type == Rm_service_RESOURCE_UNMAP_NAME)) {
612                 /* Forward all NameServer requests. */
613                 transactionForwarder(rmInst, transaction);
614             }
615             else if (transaction->type == Rm_service_RESOURCE_FREE) {
616                 freeHandler(rmInst, transaction);
617             }
618             else {
619                 allocationHandler(rmInst, transaction);
620             }
621             
622             if ((transaction->state != RM_SERVICE_PROCESSING) &&
623                 (transaction->state != RM_SERVICE_APPROVED_STATIC)) {
624                 /* Transaction error occurred.  Return result */
625                 if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {
626                     /* Source of failed transaction was not CD, return transaction via responder */
627                     transactionResponder(rmInst, transaction);
628                 }
629                 /* Otherwise let call stack return failed transaction result app via Rm_serviceHandler */                
630             }            
631         }
632         else {
633             /* Transaction validated.  Return result. */
634             if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {
635                 /* Transaction did not originate on this instance */
636                 transactionResponder(rmInst, transaction);
637             }
638             else {
639                 /* Transaction originated on this instance */
640                 serviceResponder(rmInst, transaction);
641             }
642         }
644         /* Forward any queued static requests (local and received from any registered
645          * Clients that weren't forwarded */
646         while(transQ) {
647             if (((transQ->state == RM_SERVICE_PROCESSING) ||
648                  (transQ->state == RM_SERVICE_APPROVED_STATIC)) &&
649                 (!transQ->hasBeenForwarded)) {
650                 transactionForwarder(rmInst, transQ);
651             }
652             transQ = transQ->nextTransaction;
653         }        
654     }
657 /* FUNCTION PURPOSE: Server transaction handling process
658  ***********************************************************************
659  * DESCRIPTION: Server process for handling transactions created
660  *              from services received via the service handle or the
661  *              transport.  The Server process:
662  *                  - Validates all service requests received from
663  *                    the service handle and registered CDs and
664  *                    Clients
665  */
666 static void serverProcess (Rm_Inst *rmInst, Rm_Transaction *transaction)
668     Rm_NameServerObjCfg  nameServerObjCfg;        
670     switch (transaction->type) {
671         case Rm_service_RESOURCE_ALLOCATE_INIT:
672         case Rm_service_RESOURCE_ALLOCATE_USE:
673             allocationHandler(rmInst, transaction);
674             break;
675         case Rm_service_RESOURCE_FREE:               
676             freeHandler(rmInst, transaction);
677             break;
678         case Rm_service_RESOURCE_MAP_TO_NAME:
679         case Rm_service_RESOURCE_GET_BY_NAME:
680         case Rm_service_RESOURCE_UNMAP_NAME:             
681             if (rmInst->u.server.nameServer) {
682                 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
683                     rmNameServerTreeInv(rmInst->u.server.nameServer);
684                 }                
685                 memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
686                 nameServerObjCfg.nameServerTree = rmInst->u.server.nameServer;
687                 nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
688                 if (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) {
689                     nameServerObjCfg.nodeCfg.resourceName = transaction->resourceInfo.name;
690                     nameServerObjCfg.nodeCfg.resourceBase= transaction->resourceInfo.base;
691                     nameServerObjCfg.nodeCfg.resourceLength = transaction->resourceInfo.length;
692                     transaction->state = rmNameServerAddObject(&nameServerObjCfg);
693                 }
694                 else if (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) {
695                     if ((transaction->state = rmNameServerFindObject(&nameServerObjCfg)) ==
696                         RM_SERVICE_PROCESSING) {
697                         strncpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName, RM_NAME_MAX_CHARS);
698                         transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;
699                         transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;
700                         transaction->state = RM_SERVICE_APPROVED;
701                     } 
702                 }
703                 else if (transaction->type == Rm_service_RESOURCE_UNMAP_NAME) {
704                     transaction->state = rmNameServerDeleteObject(&nameServerObjCfg);
705                 }
706                 
707                 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
708                     rmNameServerTreeWb(rmInst->u.server.nameServer);
709                 }
710             }
711             else {
712                 transaction->state = RM_ERROR_NAMESERVER_DOES_NOT_EXIST;
713             }
714             break;
715     }
717     /* Source of shared server transaction will always be local. */
718     if (rmInst->instType != Rm_instType_SHARED_SERVER) {
719         if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {
720             /* Source of transaction was not Server, return transaction via responder */
721             transactionResponder(rmInst, transaction);
722         }
723     }
724     /* Otherwise let call stack return transaction result app via Rm_serviceHandler */ 
727 /**********************************************************************
728  ********************** Internal Functions ****************************
729  **********************************************************************/
731 /* FUNCTION PURPOSE: Adds a transaction
732  ***********************************************************************
733  * DESCRIPTION: Returns a pointer to a newly created transaction.
734  *              The transaction is created based on a new service
735  *              request received via the service API or the
736  *              transport API (service forwarded from another instance)
737  */
738 Rm_Transaction *rmTransactionQueueAdd(Rm_Inst *rmInst)
740     Rm_Transaction *transactionQueue = rmInst->transactionQueue;
741     Rm_Transaction *newTransaction   = NULL;
743     newTransaction = Rm_osalMalloc(sizeof(Rm_Transaction));
744     if (newTransaction) {
745         memset((void *)newTransaction, 0, sizeof(Rm_Transaction));
747         newTransaction->localId = transactionGetSequenceNum(rmInst);
748         newTransaction->nextTransaction = NULL;  
749         if (transactionQueue) {
750             while (transactionQueue->nextTransaction) {
751                 transactionQueue = transactionQueue->nextTransaction;
752             }
753             transactionQueue->nextTransaction = newTransaction;
754         }
755         else {
756             rmInst->transactionQueue = newTransaction;
757         }
758     }
759     return (newTransaction);
762 /* FUNCTION PURPOSE: Finds a transaction
763  ***********************************************************************
764  * DESCRIPTION: Returns a pointer to a transaction resident
765  *              in the transaction queue that matches the provided
766  *              transaction ID.
767  */
768 Rm_Transaction *rmTransactionQueueFind(Rm_Inst *rmInst, uint32_t transactionId)
770     Rm_Transaction *transaction = rmInst->transactionQueue;
772     while (transaction) {
773         if (transaction->localId == transactionId) {
774             break;             
775         }
776         transaction = transaction->nextTransaction;
777     }
779     return (transaction);
782 /* FUNCTION PURPOSE: Deletes a transaction
783  ***********************************************************************
784  * DESCRIPTION: Deletes the transaction with the provided transaction
785  *              ID from the instance's transaction queue.
786  */
787 int32_t rmTransactionQueueDelete(Rm_Inst *rmInst, uint32_t transactionId)
789     Rm_Transaction *transaction     = rmInst->transactionQueue;
790     Rm_Transaction *prevTransaction = NULL;
791     int32_t         retVal          = RM_OK;
793     while (transaction) {
794         if (transaction->localId == transactionId) {
795             break;             
796         }
798         prevTransaction = transaction;
799         transaction = transaction->nextTransaction;
800     }
802     if (transaction) {
803         if (prevTransaction == NULL) {
804             /* Transaction at start of queue. Map second transaction to start of queue 
805              * as long as more than one transactions. */
806             rmInst->transactionQueue = transaction->nextTransaction;
807         }
808         else {
809             /* Transaction in middle or end of queue. */
810             prevTransaction->nextTransaction = transaction->nextTransaction;
811         }
812         Rm_osalFree((void *)transaction, sizeof(Rm_Transaction));
813     }
814     else {
815         retVal = RM_ERROR_SERVICE_TRANS_DOES_NOT_EXIST;
816     }    
817     return (retVal);
820 /* FUNCTION PURPOSE: Routes a transaction for processing
821  ***********************************************************************
822  * DESCRIPTION: Routes a received transaction to the appropriate
823  *              instance processing routine
824  */
825 void rmProcessRouter (Rm_Inst *rmInst, Rm_Transaction *transaction)
827     if (rmInst->instType == Rm_instType_CLIENT) {
828         clientProcess(rmInst, transaction);
829     }
830     else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
831         clientDelegateProcess(rmInst, transaction);
832     }
833     else if ((rmInst->instType == Rm_instType_SERVER) ||
834              (rmInst->instType == Rm_instType_SHARED_SERVER)) {
835         serverProcess(rmInst, transaction);
836     } 
838      
839 /**********************************************************************
840  ********************** Application visible APIs **********************
841  **********************************************************************/
843 /* FUNCTION PURPOSE: Display status of managed resources
844  ***********************************************************************
845  * DESCRIPTION: Prints the status (allocate/free status, as well as
846  *              owners) for all resources managed by the RM 
847  *              instance network.  Also, prints the NameServer name
848  *              entries.  The number of resource range owners is
849  *              returned as well.  This function is only available on
850  *              server instances.
851  */
852 int32_t Rm_resourceStatus(Rm_Handle rmServerHandle, int printResources)
854     Rm_Inst         *rmInst = (Rm_Inst *)rmServerHandle;
855     Rm_Allocator    *allocator = NULL;
856     Rm_Owner        *owners;
857     Rm_ResourceTree *treeRoot;
858     Rm_ResourceNode *treeNode;
859     int32_t          totalResOwners = 0;
860     void            *key; 
862     RM_SS_INST_INV_ENTER_CS(key);
863     RM_SC_INST_INV_ENTER_CS(key);
865     if (rmInst->instType == Rm_instType_SHARED_CLIENT) {
866         /* Transfer control to shared server instance */
867         rmInst = rmInst->u.sharedClient.sharedServerHandle;
868     }
870     if ((rmInst->instType == Rm_instType_SERVER) ||
871         (rmInst->instType == Rm_instType_SHARED_SERVER)) {
872         allocator = rmInst->u.server.allocators;
873         while (allocator) {
874             RM_SS_OBJ_INV(allocator, Rm_Allocator);
875             if (printResources) {
876                 Rm_osalLog("Resource: %s\n", allocator->resourceName);
877             }
879             treeRoot = allocator->allocatorRootEntry;
880             if (rmInst->instType == Rm_instType_SHARED_SERVER) {
881                 rmResourceTreeInv(treeRoot);
882             }
883             RB_FOREACH(treeNode, _Rm_AllocatorResourceTree, treeRoot) {
884                 if (printResources) {
885                     if ((treeNode->base >= 65536) ||
886                         ((treeNode->base + treeNode->length - 1) >= 65536)) {
887                         /* Print in hex if number is very large */
888                         Rm_osalLog("          0x%08x - 0x%08x ", treeNode->base, 
889                                                                  treeNode->base + treeNode->length - 1);
890                     }
891                     else {
892                         Rm_osalLog("          %10d - %10d ", treeNode->base, 
893                                                              treeNode->base + treeNode->length - 1);
894                     }
895                 }
896                 
897                 if (treeNode->allocationCount == 0) {
898                     if (printResources) {
899                         Rm_osalLog("FREE\n");
900                     }
901                 }
902                 else {
903                     owners = treeNode->ownerList;
904                     while (owners) {
905                         RM_SS_OBJ_INV(owners, Rm_Owner);
906                         if (printResources) {
907                             Rm_osalLog("%s ", owners->instNameNode->name);
908                         }
909                         totalResOwners++;
910                         owners = owners->nextOwner;
911                     }
912                     if (printResources) {
913                         Rm_osalLog("\n");
914                     }
915                 }
916             }        
917             allocator = allocator->nextAllocator; 
918         }
919         if (printResources) {
920             rmNameServerPrintObjects((Rm_Handle)rmInst);
921         }
922     }
923     else {
924         totalResOwners = RM_ERROR_INVALID_RES_STATUS_INSTANCE;
925     }  
927     RM_SS_INST_WB_EXIT_CS(key);
928     return(totalResOwners);
931 /* FUNCTION PURPOSE: Display status of a RM instance
932  ***********************************************************************
933  * DESCRIPTION: Prints the current status of various RM instance
934  *              properties such as the state of all transactions
935  *              in the transaction queue and registered transports
936  */
937 void Rm_instanceStatus(Rm_Handle rmHandle)
939     Rm_Inst        *rmInst = (Rm_Inst *)rmHandle;
940     Rm_Transport   *transportList = NULL;
941     Rm_Transaction *transactionQ = NULL;
942     void           *key; 
944     RM_SS_INST_INV_ENTER_CS(key);
945     RM_SC_INST_INV_ENTER_CS(key);
947     Rm_osalLog("Instance name: %s\n", rmInst->instName);
948     Rm_osalLog("Handle: 0x%08x\n", rmHandle);    
949     if (rmInst->instType == Rm_instType_SERVER) {
950         Rm_osalLog("Type:   Server\n");
951     }
952     else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
953         Rm_osalLog("Type:   Client Delegate\n");
954     }
955     else if (rmInst->instType == Rm_instType_CLIENT) {
956         Rm_osalLog("Type:   Client\n");
957     }
958     else if (rmInst->instType == Rm_instType_SHARED_SERVER) {
959         Rm_osalLog("Type:   Shared Server\n");
960     }
961     else if (rmInst->instType == Rm_instType_SHARED_CLIENT) {
962         Rm_osalLog("Type:   Shared Client\n");
964         Rm_osalLog("\nShared Server Properties:\n");
965         /* Transfer to Shared Server instance to print out transport and
966          * transaction status */
967         rmInst = rmInst->u.sharedClient.sharedServerHandle;
968         Rm_osalLog("Instance name: %s\n", rmInst->instName);
969         Rm_osalLog("Handle: 0x%08x\n", rmHandle);
970     }
971     
972     transportList = rmInst->transports;
973     if (transportList) {
974         Rm_osalLog("\nRegistered Transports:\n");
975         while (transportList) {
976             RM_SS_OBJ_INV(transportList, Rm_Transport);
977             Rm_osalLog("    Remote instName:    %s\n", transportList->remoteInstName);
978             if (transportList->remoteInstType == Rm_instType_SERVER) {
979                 Rm_osalLog("    Remote instType:    Server\n");
980             }
981             else if (transportList->remoteInstType == Rm_instType_CLIENT_DELEGATE) {
982                 Rm_osalLog("    Remote instType:    Client Delegate\n");
983             }
984             else {
985                 Rm_osalLog("    Remote instType:    Client\n");
986             }
987             Rm_osalLog("    appTransportHandle: 0x%08x\n", transportList->appTransportHandle);
988             Rm_osalLog("\n");
989             transportList = transportList->nextTransport;
990         }
991     }
993     transactionQ = rmInst->transactionQueue;
994     if (transactionQ) {
995         Rm_osalLog("\nQueued Service Transactions:\n");
996         while (transactionQ) {
997             RM_SS_OBJ_INV(transactionQ, Rm_Transaction);
998             Rm_osalLog("    Service type:       %d\n", transactionQ->type);
999             Rm_osalLog("    Service ID:         %d\n", transactionQ->localId);
1000             Rm_osalLog("    Service srcInstName %s\n", transactionQ->serviceSrcInstName);
1001             Rm_osalLog("    Service state:      %d\n", transactionQ->state);
1002             Rm_osalLog("    Resource name:      %s\n", transactionQ->resourceInfo.name);
1003             Rm_osalLog("    Resource base:      %d\n", transactionQ->resourceInfo.base);
1004             Rm_osalLog("    Resource length:    %d\n", transactionQ->resourceInfo.length);
1005             Rm_osalLog("    Resource alignment: %d\n", transactionQ->resourceInfo.alignment);
1006             Rm_osalLog("    Resource NS name:   %s\n", transactionQ->resourceInfo.nameServerName);
1007             Rm_osalLog("\n");
1008             transactionQ = transactionQ->nextTransaction;
1009         }    
1010     }
1011     RM_SS_INST_WB_EXIT_CS(key);    
1014 /* FUNCTION PURPOSE: RM instance creation and initialization
1015  ***********************************************************************
1016  * DESCRIPTION: Returns a new RM instance created and initialized
1017  *              using the parameters provided via the initCfg
1018  *              structure.
1019  */
1020 Rm_Handle Rm_init(const Rm_InitCfg *initCfg, int32_t *result)
1022     Rm_Inst *rmInst = NULL;
1023     Rm_Inst *sharedServerInst = NULL;
1024     void    *globalResourceDtb = NULL;
1025     void    *linuxResourceDtb = NULL;
1026     int      addLinux = RM_FALSE;   
1027     void    *key;     
1029     *result = RM_OK;
1030     
1031     if ((initCfg->instName == NULL) ||
1032         ((strlen(initCfg->instName) + 1) > RM_NAME_MAX_CHARS)) {
1033         *result = RM_ERROR_INVALID_INST_NAME;
1034         goto errorExit;
1035     }
1037     if (initCfg->instType >= Rm_instType_LAST) {
1038         *result = RM_ERROR_INVALID_INST_TYPE;
1039         goto errorExit;
1040     }
1042     /* Create and initialize instance */
1043     rmInst = Rm_osalMalloc (sizeof(Rm_Inst));
1044     memset ((void *) rmInst, 0, sizeof(Rm_Inst));
1045     rmInst->isLocked = RM_FALSE;
1046     rmInst->registeredWithDelegateOrServer = RM_FALSE;
1047     rmInst->transactionSeqNum = transactionInitSequenceNum();
1049     rmInst->instType = initCfg->instType;    
1050     strncpy (rmInst->instName, initCfg->instName, RM_NAME_MAX_CHARS);
1052     if ((rmInst->instType == Rm_instType_SERVER) ||
1053         (rmInst->instType == Rm_instType_SHARED_SERVER)) {
1054         if (!initCfg->instCfg.serverCfg.globalResourceList ||
1055             !initCfg->instCfg.serverCfg.globalPolicy) {
1056             *result = RM_ERROR_INVALID_SERVER_CONFIGURATION;
1057             goto errorExit;
1058         }
1060         rmInst->u.server.globalPolicy = initCfg->instCfg.serverCfg.globalPolicy;
1062         if (initCfg->instCfg.serverCfg.linuxDtb) {
1063             linuxResourceDtb = initCfg->instCfg.serverCfg.linuxDtb;
1064             addLinux = RM_TRUE;
1065         }
1067         /* Create valid instance list from policy.  Must be done prior to parsing
1068          * GRL so that Linux resources can be reserved correctly */
1069         rmInst->u.server.globalValidInstTree = rmPolicyCreateValidInstTree((Rm_Handle)rmInst, addLinux, result);
1070         if (*result == RM_OK) {
1071             *result = rmPolicyValidatePolicy((Rm_Handle)rmInst);  
1072         }
1073         
1074         if (*result != RM_OK) {
1075             if (rmInst->u.server.globalValidInstTree) {
1076                 rmPolicyFreeValidInstTree((Rm_Handle)rmInst);
1077             }
1078             goto errorExit;
1079         }
1080         else {
1081             rmNameServerInit((Rm_Handle)rmInst);
1083             globalResourceDtb = initCfg->instCfg.serverCfg.globalResourceList;
1085             if ((*result = rmAllocatorInitializeResources((Rm_Handle) rmInst, globalResourceDtb, linuxResourceDtb)) == RM_OK) {  
1086                 *result = rmPolicyValidatePolicyResourceNames((Rm_Handle)rmInst);
1087             }
1089             if (*result != RM_OK) {
1090                 rmAllocatorDeleteResources((Rm_Handle)rmInst);
1091                 rmNameServerDelete((Rm_Handle)rmInst);
1092                 goto errorExit;
1093             }
1094         }
1095     }
1096     else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1097         if (initCfg->instCfg.clientCfg.staticPolicy) {
1098             rmInst->u.cd.staticPolicy = initCfg->instCfg.cdCfg.staticPolicy;
1099             rmInst->u.cd.staticValidInstTree = rmPolicyCreateValidInstTree((Rm_Handle)rmInst, addLinux, result);        
1100             if (*result == RM_OK) {
1101                 *result = rmPolicyValidatePolicy((Rm_Handle)rmInst);
1102             }
1104             if (*result != RM_OK) {
1105                 if (rmInst->u.cd.staticValidInstTree) {
1106                     rmPolicyFreeValidInstTree((Rm_Handle)rmInst);
1107                 }
1108                 goto errorExit;
1109             }
1110         }
1111     }
1112     else if (rmInst->instType == Rm_instType_CLIENT) {
1113         if (initCfg->instCfg.cdCfg.staticPolicy) { 
1114             rmInst->u.client.staticPolicy = initCfg->instCfg.clientCfg.staticPolicy;
1115             rmInst->u.client.staticValidInstTree = rmPolicyCreateValidInstTree((Rm_Handle)rmInst, addLinux, result);        
1116             if (*result == RM_OK) {
1117                 *result = rmPolicyValidatePolicy((Rm_Handle)rmInst);
1118             }
1119             
1120             if (*result != RM_OK) {
1121                 if (rmInst->u.client.staticValidInstTree) {
1122                     rmPolicyFreeValidInstTree((Rm_Handle)rmInst);
1123                 }
1124                 goto errorExit;
1125             }
1126         }
1127     }
1128     else if (rmInst->instType == Rm_instType_SHARED_CLIENT) {
1129         if (initCfg->instCfg.sharedClientCfg.sharedServerHandle) {
1130             rmInst->u.sharedClient.sharedServerHandle = initCfg->instCfg.sharedClientCfg.sharedServerHandle;
1131             /* Invalidate the Shared server instance structure on this core to get the latest
1132              * instance data. */
1133             key = Rm_osalCsEnter();
1134             Rm_osalBeginMemAccess((void *)rmInst->u.sharedClient.sharedServerHandle, sizeof(Rm_Inst));
1135             sharedServerInst = rmInst->u.sharedClient.sharedServerHandle;
1136             if (sharedServerInst->instType != Rm_instType_SHARED_SERVER) {
1137                 *result = RM_ERROR_INVALID_SHARED_SERVER_HANDLE;
1138                 Rm_osalCsExit(key);
1139                 goto errorExit;
1140             }
1141             Rm_osalCsExit(key);
1142         }
1143         else {
1144             *result = RM_ERROR_INVALID_SHARED_SERVER_HANDLE;
1145             goto errorExit;
1146         }
1147     }
1149     if (initCfg->instType == Rm_instType_SHARED_SERVER) {
1150         /* Writeback the instance for other cores */
1151         Rm_osalEndMemAccess ((void *)rmInst, sizeof(Rm_Inst));
1152     }
1153     else if (rmInst->instType != Rm_instType_SHARED_CLIENT) {
1154         /* Create the instance's task blocking mechanism */
1155         rmInst->blockHandle = Rm_osalTaskBlockCreate();
1156     }
1158     return ((Rm_Handle) rmInst);
1159 errorExit:
1160     if (rmInst) {
1161         Rm_osalFree((void *)rmInst, sizeof(Rm_Inst));
1162     }
1163     return (NULL); 
1166 /* FUNCTION PURPOSE: Deletes an RM instance
1167  ***********************************************************************
1168  * DESCRIPTION: Frees all memory associated with an RM instance
1169  *              as long as all transports have been unregistered
1170  *              and the service handle has been closed
1171  */
1172 int32_t Rm_delete(Rm_Handle rmHandle, int ignorePendingServices)
1174     Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
1175     void    *key; 
1177     key = Rm_osalCsEnter();
1178     if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1179         Rm_osalBeginMemAccess((void *)rmInst, sizeof(Rm_Inst));
1180     }
1182     if (rmInst->serviceHandle) {
1183         return (RM_ERROR_CANT_DELETE_WITH_OPEN_SERV_HNDL);
1184     }
1185     else if (rmInst->transports) {
1186         return (RM_ERROR_CANT_DELETE_WITH_REGD_TRANSPORT);
1187     }
1188     else if (rmInst->transactionQueue && !ignorePendingServices) {
1189         return (RM_ERROR_CANT_DELETE_PENDING_TRANSACTIONS);
1190     }
1192     if ((rmInst->instType == Rm_instType_SERVER) ||
1193         (rmInst->instType == Rm_instType_SHARED_SERVER)) {
1194         rmAllocatorDeleteResources(rmHandle);
1195         rmNameServerDelete(rmHandle);
1196     }
1198     if (rmInst->instType != Rm_instType_SHARED_CLIENT) {
1199         /* Delete valid instance tree */
1200         rmPolicyFreeValidInstTree(rmHandle);
1202         /* Delete any transactions */
1203         while(rmInst->transactionQueue) {
1204             rmTransactionQueueDelete(rmInst, rmInst->transactionQueue->localId);
1205         }
1207         if (rmInst->instType != Rm_instType_SHARED_SERVER) {
1208             /* Delete the instance's task blocking mechanism */
1209             Rm_osalTaskBlockDelete(rmInst->blockHandle);
1210         }
1211         else {
1212             Rm_osalEndMemAccess((void *)rmInst, sizeof(Rm_Inst));
1213         }
1214     }
1216     Rm_osalFree((void *)rmInst, sizeof(Rm_Inst));
1217    
1218     Rm_osalCsExit(key);   
1219     return (RM_OK);
1222 /* FUNCTION PURPOSE: Returns RM version information
1223  ***********************************************************************
1224  */
1225 uint32_t Rm_getVersion(void)
1227     return RM_VERSION_ID;
1230 /* FUNCTION PURPOSE: Returns RM version string
1231  ***********************************************************************
1232  */
1233 const char* Rm_getVersionStr(void)
1235     return rmVersionStr;