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