]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - keystone-rtos/rm-lld.git/blob - src/rm.c
a46aa058f2512749deea3e024bb8f1a978735dd8
[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     if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {
718         /* Source of transaction was not Server, return transaction via responder */
719         transactionResponder(rmInst, transaction);
720     }
721     /* Otherwise let call stack return transaction result app via Rm_serviceHandler */ 
724 /**********************************************************************
725  ********************** Internal Functions ****************************
726  **********************************************************************/
728 /* FUNCTION PURPOSE: Adds a transaction
729  ***********************************************************************
730  * DESCRIPTION: Returns a pointer to a newly created transaction.
731  *              The transaction is created based on a new service
732  *              request received via the service API or the
733  *              transport API (service forwarded from another instance)
734  */
735 Rm_Transaction *rmTransactionQueueAdd(Rm_Inst *rmInst)
737     Rm_Transaction *transactionQueue = rmInst->transactionQueue;
738     Rm_Transaction *newTransaction   = NULL;
740     newTransaction = Rm_osalMalloc(sizeof(Rm_Transaction));
741     if (newTransaction) {
742         memset((void *)newTransaction, 0, sizeof(Rm_Transaction));
744         newTransaction->localId = transactionGetSequenceNum(rmInst);
745         newTransaction->nextTransaction = NULL;  
746         if (transactionQueue) {
747             while (transactionQueue->nextTransaction) {
748                 transactionQueue = transactionQueue->nextTransaction;
749             }
750             transactionQueue->nextTransaction = newTransaction;
751         }
752         else {
753             rmInst->transactionQueue = newTransaction;
754         }
755     }
756     return (newTransaction);
759 /* FUNCTION PURPOSE: Finds a transaction
760  ***********************************************************************
761  * DESCRIPTION: Returns a pointer to a transaction resident
762  *              in the transaction queue that matches the provided
763  *              transaction ID.
764  */
765 Rm_Transaction *rmTransactionQueueFind(Rm_Inst *rmInst, uint32_t transactionId)
767     Rm_Transaction *transaction = rmInst->transactionQueue;
769     while (transaction) {
770         if (transaction->localId == transactionId) {
771             break;             
772         }
773         transaction = transaction->nextTransaction;
774     }
776     return (transaction);
779 /* FUNCTION PURPOSE: Deletes a transaction
780  ***********************************************************************
781  * DESCRIPTION: Deletes the transaction with the provided transaction
782  *              ID from the instance's transaction queue.
783  */
784 int32_t rmTransactionQueueDelete(Rm_Inst *rmInst, uint32_t transactionId)
786     Rm_Transaction *transaction     = rmInst->transactionQueue;
787     Rm_Transaction *prevTransaction = NULL;
788     int32_t         retVal          = RM_OK;
790     while (transaction) {
791         if (transaction->localId == transactionId) {
792             break;             
793         }
795         prevTransaction = transaction;
796         transaction = transaction->nextTransaction;
797     }
799     if (transaction) {
800         if (prevTransaction == NULL) {
801             /* Transaction at start of queue. Map second transaction to start of queue 
802              * as long as more than one transactions. */
803             rmInst->transactionQueue = transaction->nextTransaction;
804         }
805         else {
806             /* Transaction in middle or end of queue. */
807             prevTransaction->nextTransaction = transaction->nextTransaction;
808         }
809         Rm_osalFree((void *)transaction, sizeof(Rm_Transaction));
810     }
811     else {
812         retVal = RM_ERROR_SERVICE_TRANS_DOES_NOT_EXIST;
813     }    
814     return (retVal);
817 /* FUNCTION PURPOSE: Routes a transaction for processing
818  ***********************************************************************
819  * DESCRIPTION: Routes a received transaction to the appropriate
820  *              instance processing routine
821  */
822 void rmProcessRouter (Rm_Inst *rmInst, Rm_Transaction *transaction)
824     if (rmInst->instType == Rm_instType_CLIENT) {
825         clientProcess(rmInst, transaction);
826     }
827     else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
828         clientDelegateProcess(rmInst, transaction);
829     }
830     else if ((rmInst->instType == Rm_instType_SERVER) ||
831              (rmInst->instType == Rm_instType_SHARED_SERVER)) {
832         serverProcess(rmInst, transaction);
833     } 
835      
836 /**********************************************************************
837  ********************** Application visible APIs **********************
838  **********************************************************************/
840 /* FUNCTION PURPOSE: Display status of managed resources
841  ***********************************************************************
842  * DESCRIPTION: Prints the status (allocate/free status, as well as
843  *              owners) for all resources managed by the RM 
844  *              instance network.  Also, prints the NameServer name
845  *              entries.  The number of resource range owners is
846  *              returned as well.  This function is only available on
847  *              server instances.
848  */
849 int32_t Rm_resourceStatus(Rm_Handle rmServerHandle, int printResources)
851     Rm_Inst         *rmInst = (Rm_Inst *)rmServerHandle;
852     Rm_Allocator    *allocator = NULL;
853     Rm_Owner        *owners;
854     Rm_ResourceTree *treeRoot;
855     Rm_ResourceNode *treeNode;
856     int32_t          totalResOwners = 0;
857     void            *key; 
859     RM_SS_INST_INV_ENTER_CS(key);
861     if ((rmInst->instType == Rm_instType_SERVER) ||
862         (rmInst->instType == Rm_instType_SHARED_SERVER)) {
863         allocator = rmInst->u.server.allocators;
864         while (allocator) {
865             RM_SS_OBJ_INV(allocator, Rm_Allocator);
866             if (printResources) {
867                 Rm_osalLog("Resource: %s\n", allocator->resourceName);
868             }
870             treeRoot = allocator->allocatorRootEntry;
871             if (rmInst->instType == Rm_instType_SHARED_SERVER) {
872                 rmResourceTreeInv(treeRoot);
873             }
874             RB_FOREACH(treeNode, _Rm_AllocatorResourceTree, treeRoot) {
875                 if (printResources) {
876                     if ((treeNode->base >= 65536) ||
877                         ((treeNode->base + treeNode->length - 1) >= 65536)) {
878                         /* Print in hex if number is very large */
879                         Rm_osalLog("          0x%08x - 0x%08x ", treeNode->base, 
880                                                                  treeNode->base + treeNode->length - 1);
881                     }
882                     else {
883                         Rm_osalLog("          %10d - %10d ", treeNode->base, 
884                                                              treeNode->base + treeNode->length - 1);
885                     }
886                 }
887                 
888                 if (treeNode->allocationCount == 0) {
889                     if (printResources) {
890                         Rm_osalLog("FREE\n");
891                     }
892                 }
893                 else {
894                     owners = treeNode->ownerList;
895                     while (owners) {
896                         RM_SS_OBJ_INV(owners, Rm_Owner);
897                         if (printResources) {
898                             Rm_osalLog("%s ", owners->instNameNode->name);
899                         }
900                         totalResOwners++;
901                         owners = owners->nextOwner;
902                     }
903                     if (printResources) {
904                         Rm_osalLog("\n");
905                     }
906                 }
907             }        
908             allocator = allocator->nextAllocator; 
909         }
910         if (printResources) {
911             rmNameServerPrintObjects((Rm_Handle)rmInst);
912         }
913     }
914     else {
915         totalResOwners = RM_ERROR_INVALID_RES_STATUS_INSTANCE;
916     }  
918     RM_SS_INST_WB_EXIT_CS(key);
919     return(totalResOwners);
922 /* FUNCTION PURPOSE: Display status of a RM instance
923  ***********************************************************************
924  * DESCRIPTION: Prints the current status of various RM instance
925  *              properties such as the state of all transactions
926  *              in the transaction queue and registered transports
927  */
928 void Rm_instanceStatus(Rm_Handle rmHandle)
930     Rm_Inst        *rmInst = (Rm_Inst *)rmHandle;
931     Rm_Transport   *transportList = NULL;
932     Rm_Transaction *transactionQ = NULL;
933     void           *key; 
935     RM_SS_INST_INV_ENTER_CS(key);
937     Rm_osalLog("Instance name: %s\n", rmInst->instName);
938     Rm_osalLog("Handle: 0x%08x\n", rmHandle);    
939     if (rmInst->instType == Rm_instType_SERVER) {
940         Rm_osalLog("Type:   Server\n");
941     }
942     else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
943         Rm_osalLog("Type:   Client Delegate\n");
944     }
945     else if (rmInst->instType == Rm_instType_CLIENT) {
946         Rm_osalLog("Type:   Client\n");
947     }
948     else if (rmInst->instType == Rm_instType_SHARED_SERVER) {
949         Rm_osalLog("Type:   Shared Server\n");
950     }
951     
952     transportList = rmInst->transports;
953     if (transportList) {
954         Rm_osalLog("\nRegistered Transports:\n");
955         while (transportList) {
956             RM_SS_OBJ_INV(transportList, Rm_Transport);
957             Rm_osalLog("    Remote instName:    %s\n", transportList->remoteInstName);
958             if (transportList->remoteInstType == Rm_instType_SERVER) {
959                 Rm_osalLog("    Remote instType:    Server\n");
960             }
961             else if (transportList->remoteInstType == Rm_instType_CLIENT_DELEGATE) {
962                 Rm_osalLog("    Remote instType:    Client Delegate\n");
963             }
964             else {
965                 Rm_osalLog("    Remote instType:    Client\n");
966             }
967             Rm_osalLog("    appTransportHandle: 0x%08x\n", transportList->appTransportHandle);
968             Rm_osalLog("\n");
969             transportList = transportList->nextTransport;
970         }
971     }
973     transactionQ = rmInst->transactionQueue;
974     if (transactionQ) {
975         Rm_osalLog("\nQueued Service Transactions:\n");
976         while (transactionQ) {
977             RM_SS_OBJ_INV(transactionQ, Rm_Transaction);
978             Rm_osalLog("    Service type:       %d\n", transactionQ->type);
979             Rm_osalLog("    Service ID:         %d\n", transactionQ->localId);
980             Rm_osalLog("    Service srcInstName %s\n", transactionQ->serviceSrcInstName);
981             Rm_osalLog("    Service state:      %d\n", transactionQ->state);
982             Rm_osalLog("    Resource name:      %s\n", transactionQ->resourceInfo.name);
983             Rm_osalLog("    Resource base:      %d\n", transactionQ->resourceInfo.base);
984             Rm_osalLog("    Resource length:    %d\n", transactionQ->resourceInfo.length);
985             Rm_osalLog("    Resource alignment: %d\n", transactionQ->resourceInfo.alignment);
986             Rm_osalLog("    Resource NS name:   %s\n", transactionQ->resourceInfo.nameServerName);
987             Rm_osalLog("\n");
988             transactionQ = transactionQ->nextTransaction;
989         }    
990     }
991     RM_SS_INST_WB_EXIT_CS(key);    
994 /* FUNCTION PURPOSE: RM instance creation and initialization
995  ***********************************************************************
996  * DESCRIPTION: Returns a new RM instance created and initialized
997  *              using the parameters provided via the initCfg
998  *              structure.
999  */
1000 Rm_Handle Rm_init(const Rm_InitCfg *initCfg, int32_t *result)
1002     Rm_Inst *rmInst = NULL;
1003     void    *globalResourceDtb = NULL;
1004     void    *linuxResourceDtb = NULL;
1005     int      addLinux = RM_FALSE;   
1007     *result = RM_OK;
1008     
1009     if ((initCfg->instName == NULL) ||
1010         ((strlen(initCfg->instName) + 1) > RM_NAME_MAX_CHARS)) {
1011         *result = RM_ERROR_INVALID_INST_NAME;
1012         goto errorExit;
1013     }
1015     if (initCfg->instType >= Rm_instType_LAST) {
1016         *result = RM_ERROR_INVALID_INST_TYPE;
1017         goto errorExit;
1018     }
1020     /* Create and initialize instance */
1021     rmInst = Rm_osalMalloc (sizeof(Rm_Inst));
1022     memset ((void *) rmInst, 0, sizeof(Rm_Inst));
1023     rmInst->isLocked = RM_FALSE;
1024     rmInst->registeredWithDelegateOrServer = RM_FALSE;
1025     rmInst->transactionSeqNum = transactionInitSequenceNum();
1027     rmInst->instType = initCfg->instType;    
1028     strncpy (rmInst->instName, initCfg->instName, RM_NAME_MAX_CHARS);
1030     if ((rmInst->instType == Rm_instType_SERVER) ||
1031         (rmInst->instType == Rm_instType_SHARED_SERVER)) {
1032         if (!initCfg->instCfg.serverCfg.globalResourceList ||
1033             !initCfg->instCfg.serverCfg.globalPolicy) {
1034             *result = RM_ERROR_INVALID_SERVER_CONFIGURATION;
1035             goto errorExit;
1036         }
1038         rmInst->u.server.globalPolicy = initCfg->instCfg.serverCfg.globalPolicy;
1040         if (initCfg->instCfg.serverCfg.linuxDtb) {
1041             linuxResourceDtb = initCfg->instCfg.serverCfg.linuxDtb;
1042             addLinux = RM_TRUE;
1043         }
1045         /* Create valid instance list from policy.  Must be done prior to parsing
1046          * GRL so that Linux resources can be reserved correctly */
1047         rmInst->u.server.globalValidInstTree = rmPolicyCreateValidInstTree((Rm_Handle)rmInst, addLinux, result);
1048         if (*result == RM_OK) {
1049             *result = rmPolicyValidatePolicy(rmInst->u.server.globalPolicy, rmInst->u.server.globalValidInstTree);  
1050         }
1051         
1052         if (*result != RM_OK) {
1053             if (rmInst->u.server.globalValidInstTree) {
1054                 rmPolicyFreeValidInstTree((Rm_Handle)rmInst);
1055             }
1056             goto errorExit;
1057         }
1058         else {
1059             rmNameServerInit((Rm_Handle)rmInst);
1061             globalResourceDtb = initCfg->instCfg.serverCfg.globalResourceList;
1063             if ((*result = rmAllocatorInitializeResources((Rm_Handle) rmInst, globalResourceDtb, linuxResourceDtb)) == RM_OK) {  
1064                 *result = rmPolicyValidatePolicyResourceNames((Rm_Handle)rmInst);
1065             }
1067             if (*result != RM_OK) {
1068                 rmAllocatorDeleteResources((Rm_Handle)rmInst);
1069                 rmNameServerDelete((Rm_Handle)rmInst);
1070                 goto errorExit;
1071             }
1072         }
1073     }
1074     else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1075         if (initCfg->instCfg.clientCfg.staticPolicy) {
1076             rmInst->u.cd.staticPolicy = initCfg->instCfg.cdCfg.staticPolicy;
1077             rmInst->u.cd.staticValidInstTree = rmPolicyCreateValidInstTree((Rm_Handle)rmInst, addLinux, result);        
1078             if (*result == RM_OK) {
1079                 *result = rmPolicyValidatePolicy(rmInst->u.cd.staticPolicy, rmInst->u.cd.staticValidInstTree);
1080             }
1082             if (*result != RM_OK) {
1083                 if (rmInst->u.cd.staticValidInstTree) {
1084                     rmPolicyFreeValidInstTree((Rm_Handle)rmInst);
1085                 }
1086                 goto errorExit;
1087             }
1088         }
1089     }
1090     else if (rmInst->instType == Rm_instType_CLIENT) {
1091         if (initCfg->instCfg.cdCfg.staticPolicy) { 
1092             rmInst->u.client.staticPolicy = initCfg->instCfg.clientCfg.staticPolicy;
1093             rmInst->u.client.staticValidInstTree = rmPolicyCreateValidInstTree((Rm_Handle)rmInst, addLinux, result);        
1094             if (*result == RM_OK) {
1095                 *result = rmPolicyValidatePolicy(rmInst->u.client.staticPolicy, rmInst->u.client.staticValidInstTree);
1096             }
1097             
1098             if (*result != RM_OK) {
1099                 if (rmInst->u.client.staticValidInstTree) {
1100                     rmPolicyFreeValidInstTree((Rm_Handle)rmInst);
1101                 }
1102                 goto errorExit;
1103             }
1104         }
1105     }
1107     if (initCfg->instType == Rm_instType_SHARED_SERVER) {
1108         /* Invalidate the instance for other cores */
1109         Rm_osalEndMemAccess ((void *)rmInst, sizeof(Rm_Inst));
1110     }
1111     else {
1112         /* Create the instance's task blocking mechanism */
1113         rmInst->blockHandle = Rm_osalTaskBlockCreate();
1114     }
1116     return ((Rm_Handle) rmInst);
1117 errorExit:
1118     if (rmInst) {
1119         Rm_osalFree((void *)rmInst, sizeof(Rm_Inst));
1120     }
1121     return (NULL); 
1124 /* FUNCTION PURPOSE: Deletes an RM instance
1125  ***********************************************************************
1126  * DESCRIPTION: Frees all memory associated with an RM instance
1127  *              as long as all transports have been unregistered
1128  *              and the service handle has been closed
1129  */
1130 int32_t Rm_delete(Rm_Handle rmHandle, int ignorePendingServices)
1132     Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
1133     void    *key; 
1135     RM_SS_INST_INV_ENTER_CS(key);
1137     if (rmInst->serviceHandle) {
1138         return (RM_ERROR_CANT_DELETE_WITH_OPEN_SERV_HNDL);
1139     }
1140     else if (rmInst->transports) {
1141         return (RM_ERROR_CANT_DELETE_WITH_REGD_TRANSPORT);
1142     }
1143     else if (rmInst->transactionQueue && !ignorePendingServices) {
1144         return (RM_ERROR_CANT_DELETE_PENDING_TRANSACTIONS);
1145     }
1147     if ((rmInst->instType == Rm_instType_SERVER) ||
1148         (rmInst->instType == Rm_instType_SHARED_SERVER)) {
1149         rmAllocatorDeleteResources(rmHandle);
1150         rmNameServerDelete(rmHandle);
1151     }
1153     /* Delete valid instance tree */
1154     rmPolicyFreeValidInstTree(rmHandle);
1156     /* Delete any transactions */
1157     while(rmInst->transactionQueue) {
1158         rmTransactionQueueDelete(rmInst, rmInst->transactionQueue->localId);
1159     }
1161     if (rmInst->instType != Rm_instType_SHARED_SERVER) {
1162         /* Delete the instance's task blocking mechanism */
1163         Rm_osalTaskBlockDelete(rmInst->blockHandle);
1164     }
1165     else {
1166         Rm_osalEndMemAccess((void *)rmInst, sizeof(Rm_Inst));
1167     }
1169     Rm_osalFree((void *)rmInst, sizeof(Rm_Inst));
1170     if (rmInst->instType == Rm_instType_SHARED_SERVER) {    
1171         Rm_osalCsExit(key);   
1172     }
1173     return (RM_OK);
1176 /* FUNCTION PURPOSE: Returns RM version information
1177  ***********************************************************************
1178  */
1179 uint32_t Rm_getVersion(void)
1181     return RM_VERSION_ID;
1184 /* FUNCTION PURPOSE: Returns RM version string
1185  ***********************************************************************
1186  */
1187 const char* Rm_getVersionStr(void)
1189     return rmVersionStr;