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