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 void createResourceReqPkt(Rm_Packet *rmPkt, char *localInstName, Rm_Transaction *transaction)
113 {
114 Rm_ResourceRequestPkt *resourceReqPkt = NULL;
116 rmPkt->pktType = Rm_pktType_RESOURCE_REQUEST;
117 resourceReqPkt = (Rm_ResourceRequestPkt *) rmPkt->data;
118 resourceReqPkt->requestId = transaction->localId;
119 if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
120 resourceReqPkt->resourceReqType = Rm_resReqPktType_ALLOCATE_INIT;
121 }
122 else if (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) {
123 resourceReqPkt->resourceReqType = Rm_resReqPktType_ALLOCATE_USE;
124 }
125 else if (transaction->type == Rm_service_RESOURCE_STATUS) {
126 resourceReqPkt->resourceReqType = Rm_resReqPktType_GET_STATUS;
127 }
128 else if (transaction->type == Rm_service_RESOURCE_FREE) {
129 resourceReqPkt->resourceReqType = Rm_resReqPktType_FREE;
130 }
131 else if (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) {
132 resourceReqPkt->resourceReqType = Rm_resReqPktType_GET_NAMED;
133 }
134 rm_strncpy(resourceReqPkt->pktSrcInstName, localInstName, RM_NAME_MAX_CHARS);
135 rm_strncpy(resourceReqPkt->serviceSrcInstName, transaction->serviceSrcInstName, RM_NAME_MAX_CHARS);
136 memcpy ((void *)&(resourceReqPkt->resourceInfo), (void *)&(transaction->resourceInfo),
137 sizeof(Rm_ResourceInfo));
138 }
140 /* FUNCTION PURPOSE: Creates a resource response packet
141 ***********************************************************************
142 * DESCRIPTION: Returns a RM packet handle that points to a RM
143 * resource response packet that has been prepared
144 * for sending to another RM instance. The packet
145 * is allocated via the rmAllocPkt API using the
146 * appTransport handle provided by the application
147 */
148 void createResourceResponsePkt(Rm_Packet *rmPkt, Rm_Transaction *transaction)
149 {
150 Rm_ResourceResponsePkt *resourceRespPkt = NULL;
152 rmPkt->pktType = Rm_pktType_RESOURCE_RESPONSE;
153 resourceRespPkt = (Rm_ResourceResponsePkt *)rmPkt->data;
154 resourceRespPkt->responseId = transaction->remoteOriginatingId;
155 resourceRespPkt->requestState = transaction->state;
156 memcpy ((void *)&(resourceRespPkt->resourceInfo), (void *)&(transaction->resourceInfo),
157 sizeof(Rm_ResourceInfo));
158 }
160 /* FUNCTION PURPOSE: Creates a NameServer request packet
161 ***********************************************************************
162 * DESCRIPTION: Returns a RM packet handle that points to a RM
163 * NameServer request packet that has been prepared
164 * for sending to another RM instance. The packet
165 * is allocated via the rmAllocPkt API using the
166 * appTransport handle provided by the application
167 */
168 void createNsRequestPkt(Rm_Packet *rmPkt, char *localInstName, Rm_Transaction *transaction)
169 {
170 Rm_NsRequestPkt *nsReqPkt = NULL;
172 rmPkt->pktType = Rm_pktType_NAMESERVER_REQUEST;
173 nsReqPkt = (Rm_NsRequestPkt *)rmPkt->data;
174 nsReqPkt->requestId = transaction->localId;
175 if (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) {
176 nsReqPkt->nsRequestType = Rm_nsReqPktType_MAP_RESOURCE;
177 }
178 else if (transaction->type == Rm_service_RESOURCE_UNMAP_NAME) {
179 nsReqPkt->nsRequestType = Rm_nsReqPktType_UNMAP_RESOURCE;
180 }
181 rm_strncpy(nsReqPkt->pktSrcInstName, localInstName, RM_NAME_MAX_CHARS);
182 rm_strncpy(nsReqPkt->serviceSrcInstName, transaction->serviceSrcInstName, RM_NAME_MAX_CHARS);
183 memcpy ((void *)&(nsReqPkt->resourceInfo), (void *)&(transaction->resourceInfo),
184 sizeof(Rm_ResourceInfo));
185 }
187 /* FUNCTION PURPOSE: Creates a NameServer response packet
188 ***********************************************************************
189 * DESCRIPTION: Returns a RM packet handle that points to a RM
190 * NameServer response packet that has been prepared
191 * for sending to another RM instance. The packet
192 * is allocated via the rmAllocPkt API using the
193 * appTransport handle provided by the application
194 */
195 void createNsResponsePkt(Rm_Packet *rmPkt, Rm_Transaction *transaction)
196 {
197 Rm_NsResponsePkt *nsRespPkt = NULL;
199 rmPkt->pktType = Rm_pktType_NAMESERVER_RESPONSE;
200 nsRespPkt = (Rm_NsResponsePkt *)rmPkt->data;
201 nsRespPkt->responseId = transaction->remoteOriginatingId;
202 nsRespPkt->requestState = transaction->state;
203 }
205 /* FUNCTION PURPOSE: Issues a service response to application
206 ***********************************************************************
207 * DESCRIPTION: Provides a service response back to the application
208 * using the service callback function provided to
209 * the RM instance at the time of the service request.
210 */
211 static void serviceResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)
212 {
213 Rm_ServiceRespInfo serviceResponse;
215 serviceResponse.rmHandle = (Rm_Handle)rmInst;
216 /* The responseTransaction will contain the resultant state details of
217 * the requestTransaction's service request */
218 serviceResponse.serviceState = transaction->state;
219 /* Pass back the ID that was provided to the component when it requested
220 * the service */
221 serviceResponse.serviceId = transaction->localId;
222 /* Owner and instance allocation count will only be set within RM under certain circumstances. */
223 serviceResponse.resourceNumOwners = transaction->resourceInfo.ownerCount;
224 serviceResponse.instAllocCount = transaction->resourceInfo.instAllocCount;
226 /* Service was approved and service was an allocate request. The resource
227 * data is passed back to the component */
228 if ((serviceResponse.serviceState == RM_SERVICE_APPROVED) &&
229 ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||
230 (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) ||
231 (transaction->type == Rm_service_RESOURCE_FREE) ||
232 (transaction->type == Rm_service_RESOURCE_STATUS) ||
233 (transaction->type == Rm_service_RESOURCE_GET_BY_NAME)))
234 {
235 rm_strncpy(serviceResponse.resourceName, transaction->resourceInfo.name, RM_NAME_MAX_CHARS);
236 serviceResponse.resourceBase = transaction->resourceInfo.base;
237 serviceResponse.resourceLength = transaction->resourceInfo.length;
238 }
240 if (transaction->u.callback.serviceCallback) {
241 /* Issue the callback to the requesting component with the response information */
242 transaction->u.callback.serviceCallback(&serviceResponse);
243 /* Delete the transaction from the transaction queue */
244 rmTransactionQueueDelete(rmInst, transaction->localId);
245 }
246 else {
247 rmServiceInternalCallback((Rm_Handle)rmInst);
248 }
250 return;
251 }
253 /* FUNCTION PURPOSE: Sends RM response packets
254 ***********************************************************************
255 * DESCRIPTION: Sends RM response packets to RM instance's that sent
256 * RM request packets to the RM instance. The response
257 * is sent via the RM transport API which is plugged
258 * with an application created transport path.
259 */
260 static void transactionResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)
261 {
262 Rm_Transport *dstTransport = transaction->u.respTrans;
263 Rm_Packet *rmPkt = NULL;
264 Rm_PacketHandle pktHandle = NULL;
266 rmPkt = dstTransport->callouts.rmAllocPkt(dstTransport->appTransportHandle,
267 sizeof(Rm_Packet), &pktHandle);
268 if (!rmPkt || !pktHandle) {
269 transaction->state = RM_ERROR_TRANSPORT_ALLOC_PKT_ERROR;
270 goto errorExit;
271 }
273 switch (transaction->type) {
274 case Rm_service_RESOURCE_ALLOCATE_INIT:
275 case Rm_service_RESOURCE_ALLOCATE_USE:
276 case Rm_service_RESOURCE_STATUS:
277 case Rm_service_RESOURCE_FREE:
278 case Rm_service_RESOURCE_GET_BY_NAME:
279 createResourceResponsePkt(rmPkt, transaction);
280 break;
281 case Rm_service_RESOURCE_MAP_TO_NAME:
282 case Rm_service_RESOURCE_UNMAP_NAME:
283 createNsResponsePkt(rmPkt, transaction);
284 break;
285 default:
286 transaction->state = RM_ERROR_INVALID_SERVICE_TYPE;
287 goto errorExit;
288 }
289 if (dstTransport->callouts.rmSendPkt(dstTransport->appTransportHandle, pktHandle) < RM_OK) {
290 transaction->state = RM_ERROR_TRANSPORT_SEND_ERROR;
291 goto errorExit;
292 }
294 /* Response packet sent: Delete transaction from queue */
295 rmTransactionQueueDelete(rmInst, transaction->localId);
297 errorExit:
298 /* Do not delete transaction on transport error. Transport error transactions should be visible
299 * from Rm_printInstanceStatus() */
300 return;
301 }
303 /* FUNCTION PURPOSE: Sends RM request packets
304 ***********************************************************************
305 * DESCRIPTION: Sends RM request packets to RM instance's that are
306 * capable of forwarding or validating service requests.
307 * The request is sent via the RM transport API which is
308 * plugged with an application created transport path.
309 */
310 static void transactionForwarder (Rm_Inst *rmInst, Rm_Transaction *transaction)
311 {
312 Rm_Transport *dstTransport = NULL;
313 Rm_Packet *rmPkt = NULL;
314 Rm_PacketHandle pktHandle = NULL;
316 if (rmInst->instType == Rm_instType_CLIENT) {
317 dstTransport = rmTransportFindRemoteInstType(rmInst->transports, Rm_instType_CLIENT_DELEGATE);
319 if (!dstTransport) {
320 dstTransport = rmTransportFindRemoteInstType(rmInst->transports, Rm_instType_SERVER);
321 }
322 }
323 else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
324 dstTransport = rmTransportFindRemoteInstType(rmInst->transports, Rm_instType_SERVER);
325 }
327 /* Just queue transaction if transport hasn't been registered. Do not return error */
328 if (dstTransport) {
329 rmPkt = dstTransport->callouts.rmAllocPkt(dstTransport->appTransportHandle,
330 sizeof(Rm_Packet), &pktHandle);
331 if (!rmPkt || !pktHandle) {
332 transaction->state = RM_ERROR_TRANSPORT_ALLOC_PKT_ERROR;
333 goto errorExit;
334 }
336 switch (transaction->type) {
337 case Rm_service_RESOURCE_ALLOCATE_INIT:
338 case Rm_service_RESOURCE_ALLOCATE_USE:
339 case Rm_service_RESOURCE_STATUS:
340 case Rm_service_RESOURCE_FREE:
341 case Rm_service_RESOURCE_GET_BY_NAME:
342 createResourceReqPkt(rmPkt, rmInst->instName, transaction);
343 break;
344 case Rm_service_RESOURCE_MAP_TO_NAME:
345 case Rm_service_RESOURCE_UNMAP_NAME:
346 createNsRequestPkt(rmPkt, rmInst->instName, transaction);
347 break;
348 default:
349 transaction->state = RM_ERROR_INVALID_SERVICE_TYPE;
350 goto errorExit;
351 }
353 if (dstTransport->callouts.rmSendPkt(dstTransport->appTransportHandle, pktHandle) < RM_OK) {
354 transaction->state = RM_ERROR_TRANSPORT_SEND_ERROR;
355 goto errorExit;
356 }
357 transaction->hasBeenForwarded = RM_TRUE;
358 /* Transaction not deleted. Waiting for response from RM CD or Server */
359 }
360 errorExit:
361 /* Do not delete transaction on transport error. Transport error transactions should be visible
362 * from Rm_printInstanceStatus() */
363 return;
364 }
366 /* FUNCTION PURPOSE: Handles static allocation requests
367 ***********************************************************************
368 * DESCRIPTION: Validates allocation requests received on CDs and
369 * Clients prior to the instance's registering
370 * with a Server. The allocation request is validated
371 * against a static policy.
372 */
373 static void staticAllocationHandler (Rm_Handle rmHandle, Rm_Transaction *transaction)
374 {
375 Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
376 void *staticPolicy = rmPolicyGetPolicy(rmHandle);
377 Rm_PolicyCheckCfg privCheckCfg;
378 int32_t result;
380 if (staticPolicy) {
381 if ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||
382 (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE)) {
383 /* Check request against static policy */
384 memset((void *)&privCheckCfg, 0, sizeof(Rm_PolicyCheckCfg));
386 if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
387 privCheckCfg.type = Rm_policyCheck_INIT;
388 }
389 else {
390 privCheckCfg.type = Rm_policyCheck_USE;
391 }
392 privCheckCfg.policyDtb = staticPolicy;
393 privCheckCfg.validInstNode = rmPolicyGetValidInstNode(rmHandle, rmInst->instName);
394 privCheckCfg.resourceOffset = rmPolicyGetResourceOffset(staticPolicy,
395 transaction->resourceInfo.name);
396 privCheckCfg.resourceBase = transaction->resourceInfo.base;
397 privCheckCfg.resourceLength = transaction->resourceInfo.length;
399 if (rmPolicyCheckPrivilege(&privCheckCfg, &result)) {
400 transaction->state = RM_SERVICE_APPROVED_STATIC;
401 }
402 else if (result == RM_OK) {
403 /* Privilege check returned false without error */
404 transaction->state = RM_SERVICE_DENIED_BY_STATIC_POLICY;
405 }
406 else {
407 /* Privilege check returned false with error */
408 transaction->state = result;
409 }
410 }
411 else {
412 transaction->state = RM_SERVICE_DENIED_INVALID_STATIC_REQUEST;
413 }
414 }
415 else {
416 transaction->state = RM_ERROR_REQ_FAILED_NO_STATIC_POLICY;
417 }
418 }
420 /* FUNCTION PURPOSE: Requests resources from Server for CD
421 ***********************************************************************
422 * DESCRIPTION: Function creates a service request to allocate resources
423 * from the Server for local management by the CD. The
424 * transaction which causes this request is put in the
425 * pending state in order to wait for the response from the
426 * Server
427 */
428 static int32_t cdRequestServerResources(Rm_Inst *rmInst, Rm_Transaction *transaction)
429 {
430 Rm_Transaction *newTrans = NULL;
431 void * policy = rmPolicyGetPolicy((Rm_Handle)rmInst);
432 int32_t resourceOffsetInPolicy;
433 uint32_t allocSize = 0;
434 int32_t retVal;
436 resourceOffsetInPolicy = rmPolicyGetResourceOffset(policy, transaction->resourceInfo.name);
437 if (resourceOffsetInPolicy > 0) {
438 if ((allocSize = rmPolicyGetResourceCdAllocSize(policy, resourceOffsetInPolicy))) {
439 if ((newTrans = rmTransactionQueueAdd(rmInst))) {
440 newTrans->type = transaction->type;
441 rm_strncpy(newTrans->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS);
442 newTrans->state = RM_SERVICE_PROCESSING;
443 rm_strncpy(newTrans->resourceInfo.name, transaction->resourceInfo.name, RM_NAME_MAX_CHARS);
444 newTrans->resourceInfo.base = RM_RESOURCE_BASE_UNSPECIFIED;
445 /* Make sure request length will satisfy transaction length */
446 newTrans->resourceInfo.length = allocSize;
447 while (newTrans->resourceInfo.length < transaction->resourceInfo.length) {
448 newTrans->resourceInfo.length += allocSize;
449 }
450 newTrans->resourceInfo.alignment = transaction->resourceInfo.alignment;
451 newTrans->pendingTransactionId = transaction->localId;
452 transactionForwarder(rmInst, newTrans);
454 retVal = RM_SERVICE_PENDING_SERVER_RESPONSE;
455 }
456 else {
457 retVal = RM_ERROR_TRANS_REQ_TO_SERVER_NOT_CREATED;
458 }
459 }
460 else {
461 /* Forward request to Server for completion if policy has
462 * no allocation size for resource */
463 retVal = RM_SERVICE_PROCESSING;
464 }
465 }
466 else {
467 /* Resource could not be found in policy */
468 retVal = RM_SERVICE_DENIED_RES_DOES_NOT_EXIST;
469 }
470 return (retVal);
471 }
473 /* FUNCTION PURPOSE: Frees local resources to Server from CD
474 ***********************************************************************
475 * DESCRIPTION: Function creates a service request to free locally
476 * managed resources that are now localized back to
477 * the Server.
478 */
479 static int32_t cdFreeResourcesToServer(Rm_Inst *rmInst, Rm_Transaction *transaction)
480 {
481 int32_t baseToFree = transaction->resourceInfo.base;
482 uint32_t lenToFree = transaction->resourceInfo.length;
483 Rm_Transaction *newTrans = NULL;
484 /* This function should only be called after a free was approved */
485 int32_t retVal = RM_SERVICE_APPROVED;
487 /* Did free result in a localized free node that can be given back to Server? If
488 * so create transaction to Server to free localized resource node */
489 if (rmAllocatorGetNodeLocalization((Rm_Handle)rmInst, transaction->resourceInfo.name,
490 &baseToFree, &lenToFree)) {
491 if ((newTrans = rmTransactionQueueAdd(rmInst))) {
492 newTrans->type = transaction->type;
493 rm_strncpy(newTrans->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS);
494 newTrans->state = RM_SERVICE_PROCESSING;
495 rm_strncpy(newTrans->resourceInfo.name, transaction->resourceInfo.name, RM_NAME_MAX_CHARS);
496 newTrans->resourceInfo.base = baseToFree;
497 newTrans->resourceInfo.length = lenToFree;
498 newTrans->pendingTransactionId = transaction->localId;
499 transactionForwarder(rmInst, newTrans);
501 retVal = RM_SERVICE_PENDING_SERVER_RESPONSE;
502 }
503 else {
504 /* Error: Need to re-allocate what was freed */
505 retVal = RM_ERROR_TRANS_REQ_TO_SERVER_NOT_CREATED;
506 }
507 }
508 return (retVal);
509 }
511 /* FUNCTION PURPOSE: Arbitrates allocation service requests
512 ***********************************************************************
513 * DESCRIPTION: Issues a set of allocator operations in order to
514 * handle a received allocation request. Allocation
515 * requests are always forwarded to the Server on Client
516 * CD instances. If a request is made with a NameServer
517 * name the resource base and length parameters are
518 * retrieved from the NameServer prior to the allocation
519 * attempt.
520 */
521 static void allocationHandler (Rm_Inst *rmInst, Rm_Transaction *transaction)
522 {
523 Rm_AllocatorOpInfo opInfo;
524 Rm_NameServerObjCfg nameServerObjCfg;
525 int32_t retVal = transaction->state;
527 memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));
528 opInfo.policy = rmPolicyGetPolicy((Rm_Handle)rmInst);
529 opInfo.resourceInfo = &transaction->resourceInfo;
530 opInfo.serviceSrcInstNode = rmPolicyGetValidInstNode((Rm_Handle)rmInst, transaction->serviceSrcInstName);
531 if (opInfo.serviceSrcInstNode == NULL) {
532 retVal = RM_SERVICE_DENIED_INST_NAME_NOT_VALID;
533 goto errorExit;
534 }
536 if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
537 if (transaction->resourceInfo.base != RM_RESOURCE_BASE_UNSPECIFIED) {
538 if (rmAllocatorFind((Rm_Handle)rmInst, transaction->resourceInfo.name)) {
539 /* Attempt to allocate from local resources that were provided by Server */
540 if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
541 opInfo.operation = Rm_allocatorOp_ALLOCATE_INIT;
542 }
543 else if (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) {
544 opInfo.operation = Rm_allocatorOp_ALLOCATE_USE;
545 }
546 else {
547 retVal = RM_ERROR_INVALID_SERVICE_TYPE;
548 goto errorExit;
549 }
550 retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
552 if (retVal == RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST) {
553 /* Request resource range was not found within local resources
554 * provided by Server. Set back to PROCESSING so request is forwarded to
555 * Server */
556 retVal = RM_SERVICE_PROCESSING;
557 }
558 }
559 }
560 else {
561 if (rmAllocatorFind((Rm_Handle)rmInst, transaction->resourceInfo.name)) {
562 int32_t oldAlign = transaction->resourceInfo.alignment;
564 /* Attempt to allocate from local resources that were provided by Server */
565 if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
566 opInfo.operation = Rm_allocatorOp_PRE_ALLOCATE_INIT;
567 }
568 else if (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) {
569 opInfo.operation = Rm_allocatorOp_PRE_ALLOCATE_USE;
570 }
571 else {
572 retVal = RM_ERROR_INVALID_SERVICE_TYPE;
573 goto errorExit;
574 }
575 retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
577 if (retVal == RM_SERVICE_PROCESSING) {
578 if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
579 opInfo.operation = Rm_allocatorOp_ALLOCATE_INIT;
580 }
581 else if (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) {
582 opInfo.operation = Rm_allocatorOp_ALLOCATE_USE;
583 }
584 else {
585 retVal = RM_ERROR_INVALID_SERVICE_TYPE;
586 goto errorExit;
587 }
588 retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
590 if (retVal == RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST) {
591 /* Request resource range was not found within local resources
592 * provided by Server. Set back to PROCESSING so request is forwarded to
593 * Server */
594 retVal = RM_SERVICE_PROCESSING;
595 }
596 }
597 else if (retVal == RM_SERVICE_DENIED_RES_ALLOC_REQS_NOT_MET) {
598 if (transaction->pendingTransactionId) {
599 /* Request to Server for resources to complete transaction locally
600 * performed once already. Forward transaction to Server for completion */
601 retVal = RM_SERVICE_PROCESSING;
602 }
603 else {
604 /* Restore base and alignment since they were replaced in pre-allocate routine */
605 transaction->resourceInfo.base = RM_RESOURCE_BASE_UNSPECIFIED;
606 transaction->resourceInfo.alignment = oldAlign;
608 retVal = cdRequestServerResources(rmInst, transaction);
609 }
610 }
611 }
612 else {
613 retVal = cdRequestServerResources(rmInst, transaction);
614 }
615 }
616 }
617 else if ((rmInst->instType == Rm_instType_SERVER)||
618 (rmInst->instType == Rm_instType_SHARED_SERVER)) {
619 /* Populated NameServer name has precedence over base */
620 if (strlen(transaction->resourceInfo.nameServerName) > 0) {
621 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
622 rmNameServerTreeInv(rmInst->u.server.nameServer);
623 }
624 memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
625 nameServerObjCfg.nameServerTree = rmInst->u.server.nameServer;
626 nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
627 if ((retVal = rmNameServerFindObject(&nameServerObjCfg)) == RM_SERVICE_PROCESSING) {
628 rm_strncpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName, RM_NAME_MAX_CHARS);
629 transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;
630 transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;
631 }
632 else {
633 goto errorExit;
634 }
635 }
637 if (transaction->resourceInfo.base == RM_RESOURCE_BASE_UNSPECIFIED) {
638 if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
639 opInfo.operation = Rm_allocatorOp_PRE_ALLOCATE_INIT;
640 }
641 else if (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) {
642 opInfo.operation = Rm_allocatorOp_PRE_ALLOCATE_USE;
643 }
644 else {
645 retVal = RM_ERROR_INVALID_SERVICE_TYPE;
646 goto errorExit;
647 }
648 retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
649 }
651 if (retVal == RM_SERVICE_PROCESSING) {
652 if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
653 opInfo.operation = Rm_allocatorOp_ALLOCATE_INIT;
654 }
655 else if (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) {
656 opInfo.operation = Rm_allocatorOp_ALLOCATE_USE;
657 }
658 else {
659 retVal = RM_ERROR_INVALID_SERVICE_TYPE;
660 goto errorExit;
661 }
662 retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
663 }
664 }
665 errorExit:
666 transaction->state = retVal;
667 }
669 /* FUNCTION PURPOSE: Handles resource status service requests
670 ***********************************************************************
671 * DESCRIPTION: Issues a set of allocator operations to retrieve the
672 * current status (currently just owner reference count)
673 * for the resource specified in the transaction
674 */
675 static void statusHandler (Rm_Inst *rmInst, Rm_Transaction *transaction)
676 {
677 Rm_AllocatorOpInfo opInfo;
678 Rm_NameServerObjCfg nameServerObjCfg;
679 int32_t retVal = transaction->state;
681 memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));
682 opInfo.operation = Rm_allocatorOp_GET_STATUS;
683 opInfo.policy = rmPolicyGetPolicy((Rm_Handle)rmInst);
684 opInfo.resourceInfo = &transaction->resourceInfo;
685 opInfo.serviceSrcInstNode = rmPolicyGetValidInstNode((Rm_Handle)rmInst, transaction->serviceSrcInstName);
686 if (opInfo.serviceSrcInstNode == NULL) {
687 retVal = RM_SERVICE_DENIED_INST_NAME_NOT_VALID;
688 goto errorExit;
689 }
691 if ((strlen(transaction->resourceInfo.nameServerName) == 0) &&
692 ((transaction->resourceInfo.base == RM_RESOURCE_BASE_UNSPECIFIED) ||
693 (transaction->resourceInfo.length == 0))) {
694 retVal = RM_SERVICE_DENIED_RES_DOES_NOT_EXIST;
695 goto errorExit;
696 }
698 if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
699 if (rmAllocatorFind((Rm_Handle)rmInst, transaction->resourceInfo.name)) {
700 /* Attempt to get status from local resources that were provided by Server */
701 retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
703 if (retVal == RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST) {
704 /* Request resource range was not found within local allocator resources
705 * provided by Server. Set back to PROCESSING so request is forwarded to
706 * Server */
707 retVal = RM_SERVICE_PROCESSING;
708 }
709 }
710 }
711 else if ((rmInst->instType == Rm_instType_SERVER)||
712 (rmInst->instType == Rm_instType_SHARED_SERVER)) {
713 /* Populated NameServer name has precedence over base and length values */
714 if (strlen(transaction->resourceInfo.nameServerName) > 0) {
715 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
716 rmNameServerTreeInv(rmInst->u.server.nameServer);
717 }
718 memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
719 nameServerObjCfg.nameServerTree = rmInst->u.server.nameServer;
720 nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
721 if ((retVal = rmNameServerFindObject(&nameServerObjCfg)) == RM_SERVICE_PROCESSING) {
722 rm_strncpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName, RM_NAME_MAX_CHARS);
723 transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;
724 transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;
725 }
726 else {
727 goto errorExit;
728 }
729 }
730 retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
731 }
732 errorExit:
733 transaction->state = retVal;
734 }
736 /* FUNCTION PURPOSE: Arbitrates free service requests
737 ***********************************************************************
738 * DESCRIPTION: Issues a set of allocator operations in order to
739 * handle a received free request. Free
740 * requests are always forwarded to the Server on Client
741 * CD instances. If a request is made with a NameServer
742 * name the resource base and length parameters are
743 * retrieved from the NameServer prior to the free
744 * attempt.
745 */
746 static void freeHandler (Rm_Inst *rmInst, Rm_Transaction *transaction)
747 {
748 Rm_AllocatorOpInfo opInfo;
749 Rm_NameServerObjCfg nameServerObjCfg;
750 int32_t retVal = transaction->state;
752 memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));
753 opInfo.operation = Rm_allocatorOp_FREE;
754 opInfo.policy = rmPolicyGetPolicy((Rm_Handle)rmInst);
755 opInfo.resourceInfo = &transaction->resourceInfo;
756 opInfo.serviceSrcInstNode = rmPolicyGetValidInstNode((Rm_Handle)rmInst, transaction->serviceSrcInstName);
757 if (opInfo.serviceSrcInstNode == NULL) {
758 retVal = RM_SERVICE_DENIED_INST_NAME_NOT_VALID;
759 goto errorExit;
760 }
762 if ((strlen(transaction->resourceInfo.nameServerName) == 0) &&
763 ((transaction->resourceInfo.base == RM_RESOURCE_BASE_UNSPECIFIED) ||
764 (transaction->resourceInfo.length == 0))) {
765 retVal = RM_SERVICE_DENIED_RES_DOES_NOT_EXIST;
766 goto errorExit;
767 }
769 if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
770 if (rmAllocatorFind((Rm_Handle)rmInst, transaction->resourceInfo.name)) {
771 /* Attempt to free from local resources that were provided by Server */
772 retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
774 if (retVal == RM_SERVICE_APPROVED) {
775 /* Check if free allows local resources to be freed back to Server */
776 retVal = cdFreeResourcesToServer(rmInst, transaction);
777 }
778 else if (retVal == RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST) {
779 /* Request resource range was not found within local allocator resources
780 * provided by Server. Set back to PROCESSING so request is forwarded to
781 * Server */
782 retVal = RM_SERVICE_PROCESSING;
783 }
784 }
785 }
786 else if ((rmInst->instType == Rm_instType_SERVER) ||
787 (rmInst->instType == Rm_instType_SHARED_SERVER)) {
788 /* Populated NameServer name has precedence over base */
789 if (strlen(transaction->resourceInfo.nameServerName) > 0) {
790 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
791 rmNameServerTreeInv(rmInst->u.server.nameServer);
792 }
793 memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
794 nameServerObjCfg.nameServerTree = rmInst->u.server.nameServer;
795 nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
796 if ((retVal = rmNameServerFindObject(&nameServerObjCfg)) == RM_SERVICE_PROCESSING) {
797 rm_strncpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName, RM_NAME_MAX_CHARS);
798 transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;
799 transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;
800 }
801 else {
802 goto errorExit;
803 }
804 }
806 retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
807 }
808 errorExit:
809 transaction->state = retVal;
810 }
812 /* FUNCTION PURPOSE: Client transaction handling process
813 ***********************************************************************
814 * DESCRIPTION: Client process for handling transactions created
815 * from services received via the service handle or the
816 * transport. The Client process:
817 * - Performs static allocations if no transport
818 * to CD or Server has been registered
819 * - Forwards all service requests to CD or Server
820 * once transport has been registered
821 */
822 static void clientProcess (Rm_Inst *rmInst, Rm_Transaction *transaction)
823 {
824 Rm_Transaction *transQ;
826 if (!rmInst->registeredWithDelegateOrServer) {
827 staticAllocationHandler((Rm_Handle)rmInst, transaction);
828 }
829 else {
830 if (transaction->state == RM_SERVICE_PROCESSING) {
831 /* Forward all new transactions to CD or Server */
832 transactionForwarder(rmInst, transaction);
833 }
834 else {
835 /* Transaction validated. Return result. */
836 serviceResponder(rmInst, transaction);
837 }
839 /* Forward any queued static requests that weren't forwarded */
840 transQ = rmInst->transactionQueue;
841 while(transQ) {
842 if ((transQ->state == RM_SERVICE_APPROVED_STATIC) &&
843 (!transQ->hasBeenForwarded)) {
844 transactionForwarder(rmInst, transQ);
845 }
846 transQ = transQ->nextTransaction;
847 }
848 }
849 /* Let call stack return transaction result app via Rm_serviceHandler */
850 }
852 /* FUNCTION PURPOSE: Client Delegate transaction handling process
853 ***********************************************************************
854 * DESCRIPTION: Client Delegate process for handling transactions created
855 * from services received via the service handle or the
856 * transport. The Client Delegate process:
857 * - Performs static allocations if no transport
858 * to Server has been registered
859 * - Forwards all NameServer related service requests
860 * to Server once transport has been registered
861 * - Attempts to complete resource service requests
862 * received from registered Clients
863 */
864 static void cdProcess (Rm_Inst *rmInst, Rm_Transaction *transaction)
865 {
866 Rm_Transaction *newTrans = NULL;
867 Rm_AllocatorNode *allocator = NULL;
868 Rm_Transaction *transQ;
870 if (!rmInst->registeredWithDelegateOrServer) {
871 if ((transaction->state == RM_SERVICE_PROCESSING) &&
872 (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS) == 0)) {
873 /* Attempt static allocation of requests originating from CD inst */
874 staticAllocationHandler((Rm_Handle)rmInst, transaction);
875 }
876 /* Everything else left in transaction queue for forwarding once transport to
877 * Server is registered */
878 }
879 else {
880 if (transaction->pendingTransactionId) {
881 Rm_Transaction *pendingTrans = rmTransactionQueueFind(rmInst, transaction->pendingTransactionId);
883 /* Transaction is response from Server for transaction sent to get
884 * information in order to complete pending transaction */
885 if (transaction->state == RM_SERVICE_APPROVED) {
886 if (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) {
887 /* Transfer resource data tied to name to pending transaction */
888 rm_strncpy(pendingTrans->resourceInfo.name, transaction->resourceInfo.name, RM_NAME_MAX_CHARS);
889 pendingTrans->resourceInfo.base = transaction->resourceInfo.base;
890 pendingTrans->resourceInfo.length = transaction->resourceInfo.length;
891 /* Delete NS name from pending transaction so Server isn't queried again */
892 memset(pendingTrans->resourceInfo.nameServerName, 0, RM_NAME_MAX_CHARS);
893 /* Now that resource values have been retrieved clear pending transaction ID so
894 * CD doesn't think a resource request was sent to Server already for more local resources */
895 pendingTrans->pendingTransactionId = 0;
897 /* Return original transaction to processing state to attempt completion. */
898 pendingTrans->state = RM_SERVICE_PROCESSING;
899 }
900 else if ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||
901 (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE)) {
902 /* Add resources provided by Server to those managed by CD */
903 if ((allocator = rmAllocatorFind((Rm_Handle)rmInst, transaction->resourceInfo.name))) {
904 Rm_ResourceNode *treeNode = NULL;
906 treeNode = rmResourceNodeNew(transaction->resourceInfo.base, transaction->resourceInfo.length);
907 RB_INSERT(_Rm_AllocatorResourceTree, allocator->resourceRoot, treeNode);
908 }
909 else {
910 Rm_ResourceRange resRange;
912 memset((void *)&resRange, 0, sizeof(resRange));
913 resRange.base = transaction->resourceInfo.base;
914 resRange.length = transaction->resourceInfo.length;
916 rmAllocatorCreate((Rm_Handle)rmInst, transaction->resourceInfo.name, &resRange);
917 }
919 /* Return original transaction to processing state to attempt completion */
920 pendingTrans->state = RM_SERVICE_PROCESSING;
921 }
922 else if (transaction->type == Rm_service_RESOURCE_FREE) {
923 allocator = rmAllocatorFind((Rm_Handle)rmInst,
924 transaction->resourceInfo.name);
926 /* Local resource freed on Server. Need to remove from
927 * local allocator's resource tree as well */
928 rmAllocatorDeleteResNode((Rm_Handle)rmInst,
929 allocator,
930 transaction->resourceInfo.base,
931 transaction->resourceInfo.length);
933 /* Delete the allocator's resource tree if there are no
934 * nodes left in the resource tree */
935 if (RB_MIN(_Rm_AllocatorResourceTree,
936 allocator->resourceRoot) == NULL) {
937 rmAllocatorDelete((Rm_Handle)rmInst,
938 transaction->resourceInfo.name);
939 }
941 /* Allow original free to complete */
942 pendingTrans->state = RM_SERVICE_APPROVED;
943 }
944 }
945 else {
946 if (transaction->type == Rm_service_RESOURCE_FREE) {
947 /* Error occurred when trying to free local resource on Server. Reinsert local
948 * resources freed by original request */
949 Rm_AllocatorOpInfo opInfo;
951 memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));
952 opInfo.policy = rmPolicyGetPolicy((Rm_Handle)rmInst);
953 opInfo.resourceInfo = &pendingTrans->resourceInfo;
954 opInfo.serviceSrcInstNode = rmPolicyGetValidInstNode((Rm_Handle)rmInst, pendingTrans->serviceSrcInstName);
955 /* Can't regain the original type of allocate. Default to init */
956 opInfo.operation = Rm_allocatorOp_ALLOCATE_INIT;
957 if (rmAllocatorOperation((Rm_Handle)rmInst, &opInfo) != RM_SERVICE_APPROVED) {
958 transaction->state = RM_ERROR_LOST_RESOURCES_ON_CD;
959 }
960 }
961 /* Transfer error or denial to pending transaction */
962 pendingTrans->state = transaction->state;
963 }
964 rmTransactionQueueDelete(rmInst, transaction->localId);
965 /* Switch to pending transaction */
966 transaction = pendingTrans;
967 }
969 if ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||
970 (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) ||
971 (transaction->type == Rm_service_RESOURCE_STATUS) ||
972 (transaction->type == Rm_service_RESOURCE_FREE)) {
973 if ((transaction->state == RM_SERVICE_PROCESSING) &&
974 (strlen(transaction->resourceInfo.nameServerName) > 0)) {
975 /* Create and forward new transaction to Server to
976 * retrieve resource data mapped to name */
977 if ((newTrans = rmTransactionQueueAdd(rmInst))) {
978 newTrans->type = Rm_service_RESOURCE_GET_BY_NAME;
979 rm_strncpy(newTrans->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS);
980 newTrans->state = RM_SERVICE_PROCESSING;
981 rm_strncpy(newTrans->resourceInfo.nameServerName, transaction->resourceInfo.nameServerName,
982 RM_NAME_MAX_CHARS);
983 newTrans->pendingTransactionId = transaction->localId;
984 transactionForwarder(rmInst, newTrans);
986 transaction->state = RM_SERVICE_PENDING_SERVER_RESPONSE;
987 }
988 else {
989 transaction->state = RM_ERROR_TRANS_REQ_TO_SERVER_NOT_CREATED;
990 }
991 }
992 }
994 if ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||
995 (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE)) {
996 if (transaction->state == RM_SERVICE_PROCESSING) {
997 allocationHandler(rmInst, transaction);
998 }
999 }
1000 else if (transaction->type == Rm_service_RESOURCE_STATUS) {
1001 if (transaction->state == RM_SERVICE_PROCESSING) {
1002 statusHandler(rmInst, transaction);
1003 }
1004 }
1005 else if (transaction->type == Rm_service_RESOURCE_FREE) {
1006 if (transaction->state == RM_SERVICE_PROCESSING) {
1007 freeHandler(rmInst, transaction);
1008 }
1009 }
1010 /* Forward all NameServer-based transactions */
1012 if (transaction->state == RM_SERVICE_PROCESSING) {
1013 /* CD could not complete transaction. Forward to Server */
1014 transactionForwarder(rmInst, transaction);
1015 }
1016 else if (transaction->state != RM_SERVICE_PENDING_SERVER_RESPONSE) {
1017 /* Transaction completed by CD or completed response received from Server. Return result */
1018 if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {
1019 /* Transaction did not originate on this instance */
1020 transactionResponder(rmInst, transaction);
1021 }
1022 else {
1023 /* Transaction originated on this instance */
1024 serviceResponder(rmInst, transaction);
1025 }
1026 }
1028 /* Attempt allocation of any queued static requests:
1029 * RM_SERVICE_APPROVED_STATIC - Originated locally
1030 * RM_SERVICE_PROCESSING - Received from any registered Clients */
1031 transQ = rmInst->transactionQueue;
1032 while(transQ) {
1033 if (((transQ->state == RM_SERVICE_PROCESSING) ||
1034 (transQ->state == RM_SERVICE_APPROVED_STATIC)) &&
1035 (!transQ->hasBeenForwarded)) {
1036 transactionForwarder(rmInst, transQ);
1037 }
1038 transQ = transQ->nextTransaction;
1039 }
1040 }
1041 }
1043 /* FUNCTION PURPOSE: Server transaction handling process
1044 ***********************************************************************
1045 * DESCRIPTION: Server process for handling transactions created
1046 * from services received via the service handle or the
1047 * transport. The Server process:
1048 * - Validates all service requests received from
1049 * the service handle and registered CDs and
1050 * Clients
1051 */
1052 static void serverProcess (Rm_Inst *rmInst, Rm_Transaction *transaction)
1053 {
1054 Rm_NameServerObjCfg nameServerObjCfg;
1056 switch (transaction->type) {
1057 case Rm_service_RESOURCE_STATUS:
1058 statusHandler(rmInst, transaction);
1059 break;
1060 case Rm_service_RESOURCE_ALLOCATE_INIT:
1061 case Rm_service_RESOURCE_ALLOCATE_USE:
1062 allocationHandler(rmInst, transaction);
1063 break;
1064 case Rm_service_RESOURCE_FREE:
1065 freeHandler(rmInst, transaction);
1066 break;
1067 case Rm_service_RESOURCE_MAP_TO_NAME:
1068 case Rm_service_RESOURCE_GET_BY_NAME:
1069 case Rm_service_RESOURCE_UNMAP_NAME:
1070 if (rmInst->u.server.nameServer) {
1071 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1072 rmNameServerTreeInv(rmInst->u.server.nameServer);
1073 }
1074 memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
1075 nameServerObjCfg.nameServerTree = rmInst->u.server.nameServer;
1076 nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
1077 if (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) {
1078 nameServerObjCfg.nodeCfg.resourceName = transaction->resourceInfo.name;
1079 nameServerObjCfg.nodeCfg.resourceBase= transaction->resourceInfo.base;
1080 nameServerObjCfg.nodeCfg.resourceLength = transaction->resourceInfo.length;
1081 transaction->state = rmNameServerAddObject(&nameServerObjCfg);
1082 }
1083 else if (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) {
1084 if ((transaction->state = rmNameServerFindObject(&nameServerObjCfg)) ==
1085 RM_SERVICE_PROCESSING) {
1086 rm_strncpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName, RM_NAME_MAX_CHARS);
1087 transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;
1088 transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;
1089 transaction->state = RM_SERVICE_APPROVED;
1090 }
1091 }
1092 else if (transaction->type == Rm_service_RESOURCE_UNMAP_NAME) {
1093 transaction->state = rmNameServerDeleteObject(&nameServerObjCfg);
1094 }
1096 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1097 rmNameServerTreeWb(rmInst->u.server.nameServer);
1098 }
1099 }
1100 else {
1101 transaction->state = RM_ERROR_NAMESERVER_DOES_NOT_EXIST;
1102 }
1103 break;
1104 default:
1105 transaction->state = RM_ERROR_INVALID_SERVICE_TYPE;
1106 break;
1107 }
1109 /* Source of shared server transaction will always be local. */
1110 if (rmInst->instType != Rm_instType_SHARED_SERVER) {
1111 if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {
1112 /* Source of transaction was not Server, return transaction via responder */
1113 transactionResponder(rmInst, transaction);
1114 }
1115 }
1116 /* Otherwise let call stack return transaction result app via Rm_serviceHandler */
1117 }
1119 /**********************************************************************
1120 ********************** Internal Functions ****************************
1121 **********************************************************************/
1123 /* FUNCTION PURPOSE: Adds a transaction
1124 ***********************************************************************
1125 * DESCRIPTION: Returns a pointer to a newly created transaction.
1126 * The transaction is created based on a new service
1127 * request received via the service API or the
1128 * transport API (service forwarded from another instance)
1129 */
1130 Rm_Transaction *rmTransactionQueueAdd(Rm_Inst *rmInst)
1131 {
1132 Rm_Transaction *transactionQueue = rmInst->transactionQueue;
1133 Rm_Transaction *newTransaction = NULL;
1135 newTransaction = Rm_osalMalloc(sizeof(Rm_Transaction));
1136 if (newTransaction) {
1137 memset((void *)newTransaction, 0, sizeof(Rm_Transaction));
1139 newTransaction->localId = transactionGetSequenceNum(rmInst);
1140 newTransaction->nextTransaction = NULL;
1141 if (transactionQueue) {
1142 while (transactionQueue->nextTransaction) {
1143 transactionQueue = transactionQueue->nextTransaction;
1144 }
1145 transactionQueue->nextTransaction = newTransaction;
1146 }
1147 else {
1148 rmInst->transactionQueue = newTransaction;
1149 }
1150 }
1151 return (newTransaction);
1152 }
1154 /* FUNCTION PURPOSE: Finds a transaction
1155 ***********************************************************************
1156 * DESCRIPTION: Returns a pointer to a transaction resident
1157 * in the transaction queue that matches the provided
1158 * transaction ID.
1159 */
1160 Rm_Transaction *rmTransactionQueueFind(Rm_Inst *rmInst, uint32_t transactionId)
1161 {
1162 Rm_Transaction *transaction = rmInst->transactionQueue;
1164 while (transaction) {
1165 if (transaction->localId == transactionId) {
1166 break;
1167 }
1168 transaction = transaction->nextTransaction;
1169 }
1171 return (transaction);
1172 }
1174 /* FUNCTION PURPOSE: Deletes a transaction
1175 ***********************************************************************
1176 * DESCRIPTION: Deletes the transaction with the provided transaction
1177 * ID from the instance's transaction queue.
1178 */
1179 int32_t rmTransactionQueueDelete(Rm_Inst *rmInst, uint32_t transactionId)
1180 {
1181 Rm_Transaction *transaction = rmInst->transactionQueue;
1182 Rm_Transaction *prevTransaction = NULL;
1183 int32_t retVal = RM_OK;
1185 while (transaction) {
1186 if (transaction->localId == transactionId) {
1187 break;
1188 }
1190 prevTransaction = transaction;
1191 transaction = transaction->nextTransaction;
1192 }
1194 if (transaction) {
1195 if (prevTransaction == NULL) {
1196 /* Transaction at start of queue. Map second transaction to start of queue
1197 * as long as more than one transactions. */
1198 rmInst->transactionQueue = transaction->nextTransaction;
1199 }
1200 else {
1201 /* Transaction in middle or end of queue. */
1202 prevTransaction->nextTransaction = transaction->nextTransaction;
1203 }
1204 Rm_osalFree((void *)transaction, sizeof(Rm_Transaction));
1205 }
1206 else {
1207 retVal = RM_ERROR_SERVICE_TRANS_DOES_NOT_EXIST;
1208 }
1209 return (retVal);
1210 }
1212 /* FUNCTION PURPOSE: Routes a transaction for processing
1213 ***********************************************************************
1214 * DESCRIPTION: Routes a received transaction to the appropriate
1215 * instance processing routine
1216 */
1217 void rmProcessRouter (Rm_Inst *rmInst, Rm_Transaction *transaction)
1218 {
1219 if (rmInst->instType == Rm_instType_CLIENT) {
1220 clientProcess(rmInst, transaction);
1221 }
1222 else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1223 cdProcess(rmInst, transaction);
1224 }
1225 else if ((rmInst->instType == Rm_instType_SERVER) ||
1226 (rmInst->instType == Rm_instType_SHARED_SERVER)) {
1227 serverProcess(rmInst, transaction);
1228 }
1229 }
1231 /**********************************************************************
1232 ********************** Application visible APIs **********************
1233 **********************************************************************/
1235 /* FUNCTION PURPOSE: Display status of managed resources
1236 ***********************************************************************
1237 * DESCRIPTION: Prints the status (allocate/free status, as well as
1238 * owners) for all resources managed by the RM
1239 * instance network. Also, prints the NameServer name
1240 * entries. The number of resource range owners is
1241 * returned as well. This function is only available on
1242 * Server and CD instances.
1243 */
1244 int32_t Rm_resourceStatus(Rm_Handle rmHandle, int printResources)
1245 {
1246 Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
1247 Rm_AllocatorTree *allocTree = NULL;
1248 Rm_AllocatorNode *allocator;
1249 Rm_Owner *owners;
1250 Rm_ResourceTree *treeRoot;
1251 Rm_ResourceNode *treeNode;
1252 int32_t totalResOwners = 0;
1253 void *key;
1254 void *mtKey;
1256 RM_SS_INST_INV_ENTER_CS(rmInst, key);
1257 RM_SC_INST_INV_ENTER_CS(rmInst, key);
1258 if (rmInst->mtSemObj) {
1259 mtKey = Rm_osalMtCsEnter(rmInst->mtSemObj);
1260 }
1262 if (rmInst->instType != Rm_instType_CLIENT) {
1263 Rm_osalLog("Instance name: %s\n", rmInst->instName);
1264 Rm_osalLog("Handle: 0x%08x\n", rmHandle);
1265 if (rmInst->instType == Rm_instType_SERVER) {
1266 Rm_osalLog("Type: Server\n");
1267 } else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1268 Rm_osalLog("Type: Client Delegate\n");
1269 } else if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1270 Rm_osalLog("Type: Shared Server\n");
1271 } else if (rmInst->instType == Rm_instType_SHARED_CLIENT) {
1272 Rm_osalLog("Type: Shared Client\n");
1273 }
1275 Rm_osalLog("\nResource Status:\n\n");
1276 }
1278 if (rmInst->instType == Rm_instType_SHARED_CLIENT) {
1279 /* Transfer control to shared server instance */
1280 rmInst = rmInst->u.sharedClient.sharedServerHandle;
1281 }
1283 if ((rmInst->instType == Rm_instType_SERVER) ||
1284 (rmInst->instType == Rm_instType_SHARED_SERVER) ||
1285 (rmInst->instType == Rm_instType_CLIENT_DELEGATE)) {
1287 allocTree = rmAllocatorGetTree((Rm_Handle)rmInst);
1288 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1289 rmAllocatorTreeInv(allocTree);
1290 }
1292 RB_FOREACH(allocator, _Rm_AllocatorTree, allocTree) {
1293 RM_SS_OBJ_INV(rmInst, allocator, Rm_AllocatorNode);
1294 if (printResources) {
1295 Rm_osalLog("Resource: %s\n", allocator->resourceName);
1296 }
1298 treeRoot = allocator->resourceRoot;
1299 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1300 rmResourceTreeInv(treeRoot);
1301 }
1302 RB_FOREACH(treeNode, _Rm_AllocatorResourceTree, treeRoot) {
1303 if (printResources) {
1304 if ((treeNode->base >= 65536) ||
1305 ((treeNode->base + treeNode->length - 1) >= 65536)) {
1306 /* Print in hex if number is very large */
1307 Rm_osalLog(" 0x%08x - 0x%08x ",
1308 treeNode->base,
1309 treeNode->base + treeNode->length - 1);
1310 } else {
1311 Rm_osalLog(" %10d - %10d ",
1312 treeNode->base,
1313 treeNode->base + treeNode->length - 1);
1314 }
1315 }
1317 if (treeNode->allocationCount == 0) {
1318 if (printResources) {
1319 Rm_osalLog("FREE\n");
1320 }
1321 } else {
1322 owners = treeNode->ownerList;
1323 while (owners) {
1324 RM_SS_OBJ_INV(rmInst, owners, Rm_Owner);
1325 if (printResources) {
1326 Rm_osalLog("%s (%d) ", owners->instNameNode->name,
1327 owners->refCnt);
1328 }
1329 totalResOwners++;
1330 owners = owners->nextOwner;
1331 }
1332 if (printResources) {
1333 Rm_osalLog("\n");
1334 }
1335 }
1336 }
1337 }
1339 if ((rmInst->instType == Rm_instType_SERVER) ||
1340 (rmInst->instType == Rm_instType_SHARED_SERVER)) {
1341 if (printResources) {
1342 rmNameServerPrintObjects((Rm_Handle)rmInst);
1343 }
1344 }
1345 } else {
1346 totalResOwners = RM_ERROR_INVALID_RES_STATUS_INSTANCE;
1347 }
1349 /* Free sem object using originating instance in case the Shared Client to Shared
1350 * Server instance switch took place */
1351 if (((Rm_Inst *)rmHandle)->mtSemObj) {
1352 Rm_osalMtCsExit(((Rm_Inst *)rmHandle)->mtSemObj, mtKey);
1353 }
1354 RM_SS_INST_WB_EXIT_CS(rmInst, key);
1355 return(totalResOwners);
1356 }
1358 /* FUNCTION PURPOSE: Display status of a RM instance
1359 ***********************************************************************
1360 * DESCRIPTION: Prints the current status of various RM instance
1361 * properties such as the state of all transactions
1362 * in the transaction queue and registered transports
1363 */
1364 void Rm_instanceStatus(Rm_Handle rmHandle)
1365 {
1366 Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
1367 Rm_Transport *transportList = NULL;
1368 Rm_Transaction *transactionQ = NULL;
1369 void *key;
1370 void *mtKey;
1372 RM_SS_INST_INV_ENTER_CS(rmInst, key);
1373 RM_SC_INST_INV_ENTER_CS(rmInst, key);
1374 if (rmInst->mtSemObj) {
1375 mtKey = Rm_osalMtCsEnter(rmInst->mtSemObj);
1376 }
1378 Rm_osalLog("Instance name: %s\n", rmInst->instName);
1379 Rm_osalLog("Handle: 0x%08x\n", rmHandle);
1380 if (rmInst->instType == Rm_instType_SERVER) {
1381 Rm_osalLog("Type: Server\n");
1382 }
1383 else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1384 Rm_osalLog("Type: Client Delegate\n");
1385 }
1386 else if (rmInst->instType == Rm_instType_CLIENT) {
1387 Rm_osalLog("Type: Client\n");
1388 }
1389 else if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1390 Rm_osalLog("Type: Shared Server\n");
1391 }
1392 else if (rmInst->instType == Rm_instType_SHARED_CLIENT) {
1393 Rm_osalLog("Type: Shared Client\n");
1395 Rm_osalLog("\nShared Server Properties:\n");
1396 /* Transfer to Shared Server instance to print out transport and
1397 * transaction status */
1398 rmInst = rmInst->u.sharedClient.sharedServerHandle;
1399 Rm_osalLog("Instance name: %s\n", rmInst->instName);
1400 Rm_osalLog("Handle: 0x%08x\n", rmHandle);
1401 }
1403 transportList = rmInst->transports;
1404 if (transportList) {
1405 Rm_osalLog("\nRegistered Transports:\n");
1406 while (transportList) {
1407 RM_SS_OBJ_INV(rmInst, transportList, Rm_Transport);
1408 if (transportList->remoteInstType == Rm_instType_SERVER) {
1409 Rm_osalLog(" Remote instType: Server\n");
1410 }
1411 else if (transportList->remoteInstType == Rm_instType_CLIENT_DELEGATE) {
1412 Rm_osalLog(" Remote instType: Client Delegate\n");
1413 }
1414 else {
1415 Rm_osalLog(" Remote instType: Client\n");
1416 }
1417 Rm_osalLog(" appTransportHandle: 0x%08x\n", transportList->appTransportHandle);
1418 Rm_osalLog("\n");
1419 transportList = transportList->nextTransport;
1420 }
1421 }
1423 transactionQ = rmInst->transactionQueue;
1424 if (transactionQ) {
1425 Rm_osalLog("\nQueued Service Transactions:\n");
1426 while (transactionQ) {
1427 RM_SS_OBJ_INV(rmInst, transactionQ, Rm_Transaction);
1428 Rm_osalLog(" Service type: %d\n", transactionQ->type);
1429 Rm_osalLog(" Service ID: %d\n", transactionQ->localId);
1430 Rm_osalLog(" Service srcInstName %s\n", transactionQ->serviceSrcInstName);
1431 Rm_osalLog(" Service state: %d\n", transactionQ->state);
1432 Rm_osalLog(" Resource name: %s\n", transactionQ->resourceInfo.name);
1433 Rm_osalLog(" Resource base: %d\n", transactionQ->resourceInfo.base);
1434 Rm_osalLog(" Resource length: %d\n", transactionQ->resourceInfo.length);
1435 Rm_osalLog(" Resource alignment: %d\n", transactionQ->resourceInfo.alignment);
1436 Rm_osalLog(" Resource NS name: %s\n", transactionQ->resourceInfo.nameServerName);
1437 Rm_osalLog("\n");
1438 transactionQ = transactionQ->nextTransaction;
1439 }
1440 }
1442 /* Free sem object using originating instance in case the Shared Client to Shared
1443 * Server instance switch took place */
1444 if (((Rm_Inst *)rmHandle)->mtSemObj) {
1445 Rm_osalMtCsExit(((Rm_Inst *)rmHandle)->mtSemObj, mtKey);
1446 }
1447 RM_SS_INST_WB_EXIT_CS(rmInst, key);
1448 }
1450 /* FUNCTION PURPOSE: RM instance creation and initialization
1451 ***********************************************************************
1452 * DESCRIPTION: Returns a new RM instance created and initialized
1453 * using the parameters provided via the initCfg
1454 * structure.
1455 */
1456 Rm_Handle Rm_init(const Rm_InitCfg *initCfg, int32_t *result)
1457 {
1458 Rm_Inst *rmInst = NULL;
1459 Rm_Inst *sharedServerInst = NULL;
1460 uint32_t policySize;
1461 void *globalResourceDtb = NULL;
1462 void *linuxResourceDtb = NULL;
1463 int addLinux = RM_FALSE;
1464 void *key;
1466 *result = RM_OK;
1468 if ((initCfg->instName == NULL) ||
1469 ((strlen(initCfg->instName) + 1) > RM_NAME_MAX_CHARS)) {
1470 *result = RM_ERROR_INVALID_INST_NAME;
1471 goto errorExit;
1472 }
1474 if (initCfg->instType >= Rm_instType_LAST) {
1475 *result = RM_ERROR_INVALID_INST_TYPE;
1476 goto errorExit;
1477 }
1479 /* Create and initialize instance */
1480 rmInst = Rm_osalMalloc(sizeof(*rmInst));
1481 memset((void *)rmInst, 0, sizeof(*rmInst));
1482 rmInst->isLocked = RM_FALSE;
1483 rmInst->registeredWithDelegateOrServer = RM_FALSE;
1484 rmInst->transactionSeqNum = transactionInitSequenceNum();
1486 rmInst->instType = initCfg->instType;
1487 rm_strncpy(rmInst->instName, initCfg->instName, RM_NAME_MAX_CHARS);
1488 rmInst->mtSemObj = initCfg->mtSemObj;
1490 if ((rmInst->instType == Rm_instType_SERVER) ||
1491 (rmInst->instType == Rm_instType_SHARED_SERVER)) {
1492 if (!initCfg->instCfg.serverCfg.globalResourceList ||
1493 !initCfg->instCfg.serverCfg.globalPolicy) {
1494 *result = RM_ERROR_INVALID_SERVER_CONFIGURATION;
1495 goto errorExit;
1496 }
1498 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1499 /* Shared Server makes copy of policy in shared memory for Shared
1500 * Clients on other cores */
1501 policySize = fdt_totalsize(initCfg->instCfg.serverCfg.globalPolicy);
1502 /* Align policy size to cache boundary */
1503 if (policySize % RM_MAX_CACHE_ALIGN) {
1504 policySize += (RM_MAX_CACHE_ALIGN - (policySize % RM_MAX_CACHE_ALIGN));
1505 }
1506 rmInst->u.server.policySize = policySize;
1507 rmInst->u.server.globalPolicy = Rm_osalMalloc(rmInst->u.server.policySize);
1508 memcpy(rmInst->u.server.globalPolicy, initCfg->instCfg.serverCfg.globalPolicy, rmInst->u.server.policySize);
1509 } else {
1510 rmInst->u.server.globalPolicy = initCfg->instCfg.serverCfg.globalPolicy;
1511 }
1513 if (initCfg->instCfg.serverCfg.linuxDtb) {
1514 linuxResourceDtb = initCfg->instCfg.serverCfg.linuxDtb;
1515 addLinux = RM_TRUE;
1516 }
1518 /* Create valid instance list from policy. Must be done prior to parsing
1519 * GRL so that Linux resources can be reserved correctly */
1520 rmInst->u.server.validInstTree = rmPolicyCreateValidInstTree((Rm_Handle)rmInst, addLinux, result);
1521 if (*result == RM_OK) {
1522 *result = rmPolicyValidatePolicy((Rm_Handle)rmInst);
1523 }
1525 if (*result != RM_OK) {
1526 if (rmInst->u.server.validInstTree) {
1527 rmPolicyFreeValidInstTree((Rm_Handle)rmInst);
1528 }
1529 goto errorExit;
1530 } else {
1531 rmNameServerInit((Rm_Handle)rmInst);
1533 globalResourceDtb = initCfg->instCfg.serverCfg.globalResourceList;
1535 if ((*result = rmAllocatorInitTree((Rm_Handle) rmInst)) == RM_OK) {
1536 if ((*result = rmAllocatorPopulateTree((Rm_Handle)rmInst,
1537 globalResourceDtb,
1538 linuxResourceDtb)) ==
1539 RM_OK) {
1540 *result = rmPolicyValidateResNames((Rm_Handle)rmInst);
1541 }
1542 }
1544 if (*result != RM_OK) {
1545 rmAllocatorDeleteTree((Rm_Handle)rmInst);
1546 rmNameServerDelete((Rm_Handle)rmInst);
1547 if (rmInst->u.server.validInstTree) {
1548 rmPolicyFreeValidInstTree((Rm_Handle)rmInst);
1549 }
1550 goto errorExit;
1551 }
1552 }
1553 } else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1554 if (!initCfg->instCfg.cdCfg.cdPolicy) {
1555 *result = RM_ERROR_INVALID_CD_CONFIGURATION;
1556 goto errorExit;
1557 }
1559 rmInst->u.cd.cdPolicy = initCfg->instCfg.cdCfg.cdPolicy;
1560 rmInst->u.cd.validInstTree = rmPolicyCreateValidInstTree((Rm_Handle)rmInst, addLinux, result);
1561 if (*result == RM_OK) {
1562 *result = rmPolicyValidatePolicy((Rm_Handle)rmInst);
1563 }
1565 if (*result != RM_OK) {
1566 if (rmInst->u.cd.validInstTree) {
1567 rmPolicyFreeValidInstTree((Rm_Handle)rmInst);
1568 }
1569 goto errorExit;
1570 }
1572 if ((*result = rmAllocatorInitTree((Rm_Handle) rmInst)) != RM_OK) {
1573 if (rmInst->u.cd.validInstTree) {
1574 rmPolicyFreeValidInstTree((Rm_Handle)rmInst);
1575 }
1576 goto errorExit;
1577 }
1579 /* Remove once CD instance is stable - tracked by SDOCM00100797 */
1580 *result = RM_WARNING_CD_INSTANCE_NOT_STABLE;
1581 } else if (rmInst->instType == Rm_instType_CLIENT) {
1582 if (initCfg->instCfg.clientCfg.staticPolicy) {
1583 rmInst->u.client.staticPolicy = initCfg->instCfg.clientCfg.staticPolicy;
1584 rmInst->u.client.staticValidInstTree = rmPolicyCreateValidInstTree((Rm_Handle)rmInst, addLinux, result);
1585 if (*result == RM_OK) {
1586 *result = rmPolicyValidatePolicy((Rm_Handle)rmInst);
1587 }
1589 if (*result != RM_OK) {
1590 if (rmInst->u.client.staticValidInstTree) {
1591 rmPolicyFreeValidInstTree((Rm_Handle)rmInst);
1592 }
1593 goto errorExit;
1594 }
1595 }
1596 } else if (rmInst->instType == Rm_instType_SHARED_CLIENT) {
1597 if (initCfg->instCfg.sharedClientCfg.sharedServerHandle) {
1598 rmInst->u.sharedClient.sharedServerHandle = initCfg->instCfg.sharedClientCfg.sharedServerHandle;
1599 /* Invalidate the Shared server instance structure on this core to get the latest
1600 * instance data. */
1601 key = Rm_osalCsEnter();
1602 Rm_osalBeginMemAccess((void *)rmInst->u.sharedClient.sharedServerHandle, sizeof(Rm_Inst));
1603 sharedServerInst = rmInst->u.sharedClient.sharedServerHandle;
1604 if (sharedServerInst->instType != Rm_instType_SHARED_SERVER) {
1605 *result = RM_ERROR_INVALID_SHARED_SERVER_HANDLE;
1606 Rm_osalCsExit(key);
1607 goto errorExit;
1608 } else {
1609 /* Invalidate the policy */
1610 Rm_osalBeginMemAccess((void *)sharedServerInst->u.server.globalPolicy,
1611 sharedServerInst->u.server.policySize);
1612 }
1613 Rm_osalCsExit(key);
1614 } else {
1615 *result = RM_ERROR_INVALID_SHARED_SERVER_HANDLE;
1616 goto errorExit;
1617 }
1618 }
1620 if (initCfg->instType == Rm_instType_SHARED_SERVER) {
1621 /* Writeback the instance and policy for other cores */
1622 Rm_osalEndMemAccess ((void *)rmInst, sizeof(Rm_Inst));
1623 Rm_osalEndMemAccess ((void *)rmInst->u.server.globalPolicy, rmInst->u.server.policySize);
1624 } else if (rmInst->instType != Rm_instType_SHARED_CLIENT) {
1625 /* Create the instance's task blocking mechanism */
1626 rmInst->blockHandle = Rm_osalTaskBlockCreate();
1627 }
1629 return ((Rm_Handle) rmInst);
1630 errorExit:
1631 if (rmInst) {
1632 Rm_osalFree((void *)rmInst, sizeof(Rm_Inst));
1633 }
1634 return (NULL);
1635 }
1637 /* FUNCTION PURPOSE: Deletes an RM instance
1638 ***********************************************************************
1639 * DESCRIPTION: Frees all memory associated with an RM instance
1640 * as long as all transports have been unregistered
1641 * and the service handle has been closed
1642 */
1643 int32_t Rm_delete(Rm_Handle rmHandle, int ignorePendingServices)
1644 {
1645 Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
1646 void *key;
1648 key = Rm_osalCsEnter();
1649 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1650 Rm_osalBeginMemAccess((void *)rmInst, sizeof(Rm_Inst));
1651 }
1653 if (rmInst->serviceHandle) {
1654 return (RM_ERROR_CANT_DELETE_WITH_OPEN_SERV_HNDL);
1655 }
1656 else if (rmInst->transports) {
1657 return (RM_ERROR_CANT_DELETE_WITH_REGD_TRANSPORT);
1658 }
1659 else if (rmInst->transactionQueue && !ignorePendingServices) {
1660 return (RM_ERROR_CANT_DELETE_PENDING_TRANSACTIONS);
1661 }
1663 if ((rmInst->instType == Rm_instType_SERVER) ||
1664 (rmInst->instType == Rm_instType_SHARED_SERVER)) {
1665 rmAllocatorDeleteTree(rmHandle);
1666 rmNameServerDelete(rmHandle);
1667 rmInst->u.server.allocatorTree = NULL;
1669 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1670 Rm_osalFree((void *)rmInst->u.server.globalPolicy,
1671 rmInst->u.server.policySize);
1672 }
1673 }
1674 else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1675 rmAllocatorDeleteTree(rmHandle);
1676 rmInst->u.cd.allocatorTree = NULL;
1677 }
1679 if (rmInst->instType != Rm_instType_SHARED_CLIENT) {
1680 /* Delete valid instance tree */
1681 rmPolicyFreeValidInstTree(rmHandle);
1683 /* Delete any transactions */
1684 while(rmInst->transactionQueue) {
1685 rmTransactionQueueDelete(rmInst, rmInst->transactionQueue->localId);
1686 }
1688 if (rmInst->instType != Rm_instType_SHARED_SERVER) {
1689 /* Delete the instance's task blocking mechanism */
1690 Rm_osalTaskBlockDelete(rmInst->blockHandle);
1691 }
1692 else {
1693 Rm_osalEndMemAccess((void *)rmInst, sizeof(Rm_Inst));
1694 }
1695 }
1697 Rm_osalFree((void *)rmInst, sizeof(Rm_Inst));
1699 Rm_osalCsExit(key);
1700 return (RM_OK);
1701 }
1703 /* FUNCTION PURPOSE: Returns RM version information
1704 ***********************************************************************
1705 */
1706 uint32_t Rm_getVersion(void)
1707 {
1708 return RM_VERSION_ID;
1709 }
1711 /* FUNCTION PURPOSE: Returns RM version string
1712 ***********************************************************************
1713 */
1714 const char* Rm_getVersionStr(void)
1715 {
1716 return rmVersionStr;
1717 }