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 count will only be set within RM under certain circumstances. Most of time
224 * it will be RM_RESOURCE_NUM_OWNERS_INVALID */
225 serviceResponse.resourceNumOwners = transaction->resourceInfo.ownerCount;
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 = rmInst->transactionQueue;
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 while(transQ) {
836 if ((transQ->state == RM_SERVICE_APPROVED_STATIC) &&
837 (!transQ->hasBeenForwarded)) {
838 transactionForwarder(rmInst, transQ);
839 }
840 transQ = transQ->nextTransaction;
841 }
842 }
843 /* Let call stack return transaction result app via Rm_serviceHandler */
844 }
846 /* FUNCTION PURPOSE: Client Delegate transaction handling process
847 ***********************************************************************
848 * DESCRIPTION: Client Delegate process for handling transactions created
849 * from services received via the service handle or the
850 * transport. The Client Delegate process:
851 * - Performs static allocations if no transport
852 * to Server has been registered
853 * - Forwards all NameServer related service requests
854 * to Server once transport has been registered
855 * - Attempts to complete resource service requests
856 * received from registered Clients
857 */
858 static void cdProcess (Rm_Inst *rmInst, Rm_Transaction *transaction)
859 {
860 Rm_Transaction *newTrans = NULL;
861 Rm_Allocator *allocator = NULL;
862 Rm_Transaction *transQ = rmInst->transactionQueue;
864 if (!rmInst->registeredWithDelegateOrServer) {
865 if ((transaction->state == RM_SERVICE_PROCESSING) &&
866 (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS) == 0)) {
867 /* Attempt static allocation of requests originating from CD inst */
868 staticAllocationHandler((Rm_Handle)rmInst, transaction);
869 }
870 /* Everything else left in transaction queue for forwarding once transport to
871 * Server is registered */
872 }
873 else {
874 if (transaction->pendingTransactionId) {
875 Rm_Transaction *pendingTrans = rmTransactionQueueFind(rmInst, transaction->pendingTransactionId);
877 /* Transaction is response from Server for transaction sent to get
878 * information in order to complete pending transaction */
879 if (transaction->state == RM_SERVICE_APPROVED) {
880 if (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) {
881 /* Transfer resource data tied to name to pending transaction */
882 strncpy(pendingTrans->resourceInfo.name, transaction->resourceInfo.name, RM_NAME_MAX_CHARS);
883 pendingTrans->resourceInfo.base = transaction->resourceInfo.base;
884 pendingTrans->resourceInfo.length = transaction->resourceInfo.length;
885 /* Delete NS name from pending transaction so Server isn't queried again */
886 memset(pendingTrans->resourceInfo.nameServerName, 0, RM_NAME_MAX_CHARS);
887 /* Now that resource values have been retrieved clear pending transaction ID so
888 * CD doesn't think a resource request was sent to Server already for more local resources */
889 pendingTrans->pendingTransactionId = 0;
891 /* Return original transaction to processing state to attempt completion. */
892 pendingTrans->state = RM_SERVICE_PROCESSING;
893 }
894 else if ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||
895 (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE)) {
896 /* Add resources provided by Server to those managed by CD */
897 if (allocator = rmAllocatorFind((Rm_Handle)rmInst, transaction->resourceInfo.name)) {
898 Rm_ResourceNode *treeNode = NULL;
900 treeNode = rmResourceNodeNew(transaction->resourceInfo.base, transaction->resourceInfo.length);
901 RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, treeNode);
902 }
903 else {
904 Rm_ResourceRange resRange;
906 memset((void *)&resRange, 0, sizeof(resRange));
907 resRange.base = transaction->resourceInfo.base;
908 resRange.length = transaction->resourceInfo.length;
910 rmAllocatorCreate((Rm_Handle)rmInst, transaction->resourceInfo.name, &resRange);
911 }
913 /* Return original transaction to processing state to attempt completion */
914 pendingTrans->state = RM_SERVICE_PROCESSING;
915 }
916 else if (transaction->type == Rm_service_RESOURCE_FREE) {
917 /* Local resource freed on Server. Need to remove from local allocator. */
918 rmAllocatorDeleteNode((Rm_Handle)rmInst, transaction->resourceInfo.name,
919 transaction->resourceInfo.base, transaction->resourceInfo.length);
921 /* Delete the allocator if there are no nodes left in the tree */
922 allocator = rmAllocatorFind((Rm_Handle)rmInst, transaction->resourceInfo.name);
923 if (RB_MIN(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry) == NULL) {
924 rmAllocatorDelete((Rm_Handle)rmInst, transaction->resourceInfo.name);
925 }
927 /* Allow original free to complete */
928 pendingTrans->state = RM_SERVICE_APPROVED;
929 }
930 }
931 else {
932 if (transaction->type == Rm_service_RESOURCE_FREE) {
933 /* Error occurred when trying to free local resource on Server. Reinsert local
934 * resources freed by original request */
935 Rm_AllocatorOpInfo opInfo;
937 memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));
938 opInfo.policy = rmPolicyGetPolicy((Rm_Handle)rmInst);
939 opInfo.resourceInfo = &pendingTrans->resourceInfo;
940 opInfo.serviceSrcInstNode = rmPolicyGetValidInstNode((Rm_Handle)rmInst, pendingTrans->serviceSrcInstName);
941 /* Can't regain the original type of allocate. Default to init */
942 opInfo.operation = Rm_allocatorOp_ALLOCATE_INIT;
943 if (rmAllocatorOperation((Rm_Handle)rmInst, &opInfo) != RM_SERVICE_APPROVED) {
944 transaction->state = RM_ERROR_LOST_RESOURCES_ON_CD;
945 }
946 }
947 /* Transfer error or denial to pending transaction */
948 pendingTrans->state = transaction->state;
949 }
950 rmTransactionQueueDelete(rmInst, transaction->localId);
951 /* Switch to pending transaction */
952 transaction = pendingTrans;
953 }
955 if ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||
956 (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) ||
957 (transaction->type == Rm_service_RESOURCE_STATUS) ||
958 (transaction->type == Rm_service_RESOURCE_FREE)) {
959 if ((transaction->state == RM_SERVICE_PROCESSING) &&
960 (strlen(transaction->resourceInfo.nameServerName) > 0)) {
961 /* Create and forward new transaction to Server to
962 * retrieve resource data mapped to name */
963 if (newTrans = rmTransactionQueueAdd(rmInst)) {
964 newTrans->type = Rm_service_RESOURCE_GET_BY_NAME;
965 strncpy(newTrans->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS);
966 newTrans->state = RM_SERVICE_PROCESSING;
967 strncpy(newTrans->resourceInfo.nameServerName, transaction->resourceInfo.nameServerName,
968 RM_NAME_MAX_CHARS);
969 newTrans->pendingTransactionId = transaction->localId;
970 transactionForwarder(rmInst, newTrans);
972 transaction->state = RM_SERVICE_PENDING_SERVER_RESPONSE;
973 }
974 else {
975 transaction->state = RM_ERROR_TRANS_REQ_TO_SERVER_NOT_CREATED;
976 }
977 }
978 }
980 if ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||
981 (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE)) {
982 if (transaction->state == RM_SERVICE_PROCESSING) {
983 allocationHandler(rmInst, transaction);
984 }
985 }
986 else if (transaction->type == Rm_service_RESOURCE_STATUS) {
987 if (transaction->state == RM_SERVICE_PROCESSING) {
988 statusHandler(rmInst, transaction);
989 }
990 }
991 else if (transaction->type == Rm_service_RESOURCE_FREE) {
992 if (transaction->state == RM_SERVICE_PROCESSING) {
993 freeHandler(rmInst, transaction);
994 }
995 }
996 /* Forward all NameServer-based transactions */
998 if (transaction->state == RM_SERVICE_PROCESSING) {
999 /* CD could not complete transaction. Forward to Server */
1000 transactionForwarder(rmInst, transaction);
1001 }
1002 else if (transaction->state != RM_SERVICE_PENDING_SERVER_RESPONSE) {
1003 /* Transaction completed by CD or completed response received from Server. Return result */
1004 if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {
1005 /* Transaction did not originate on this instance */
1006 transactionResponder(rmInst, transaction);
1007 }
1008 else {
1009 /* Transaction originated on this instance */
1010 serviceResponder(rmInst, transaction);
1011 }
1012 }
1014 /* Attempt allocation of any queued static requests:
1015 * RM_SERVICE_APPROVED_STATIC - Originated locally
1016 * RM_SERVICE_PROCESSING - Received from any registered Clients */
1017 while(transQ) {
1018 if (((transQ->state == RM_SERVICE_PROCESSING) ||
1019 (transQ->state == RM_SERVICE_APPROVED_STATIC)) &&
1020 (!transQ->hasBeenForwarded)) {
1021 transactionForwarder(rmInst, transQ);
1022 }
1023 transQ = transQ->nextTransaction;
1024 }
1025 }
1026 }
1028 /* FUNCTION PURPOSE: Server transaction handling process
1029 ***********************************************************************
1030 * DESCRIPTION: Server process for handling transactions created
1031 * from services received via the service handle or the
1032 * transport. The Server process:
1033 * - Validates all service requests received from
1034 * the service handle and registered CDs and
1035 * Clients
1036 */
1037 static void serverProcess (Rm_Inst *rmInst, Rm_Transaction *transaction)
1038 {
1039 Rm_NameServerObjCfg nameServerObjCfg;
1041 switch (transaction->type) {
1042 case Rm_service_RESOURCE_STATUS:
1043 statusHandler(rmInst, transaction);
1044 break;
1045 case Rm_service_RESOURCE_ALLOCATE_INIT:
1046 case Rm_service_RESOURCE_ALLOCATE_USE:
1047 allocationHandler(rmInst, transaction);
1048 break;
1049 case Rm_service_RESOURCE_FREE:
1050 freeHandler(rmInst, transaction);
1051 break;
1052 case Rm_service_RESOURCE_MAP_TO_NAME:
1053 case Rm_service_RESOURCE_GET_BY_NAME:
1054 case Rm_service_RESOURCE_UNMAP_NAME:
1055 if (rmInst->u.server.nameServer) {
1056 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1057 rmNameServerTreeInv(rmInst->u.server.nameServer);
1058 }
1059 memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
1060 nameServerObjCfg.nameServerTree = rmInst->u.server.nameServer;
1061 nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
1062 if (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) {
1063 nameServerObjCfg.nodeCfg.resourceName = transaction->resourceInfo.name;
1064 nameServerObjCfg.nodeCfg.resourceBase= transaction->resourceInfo.base;
1065 nameServerObjCfg.nodeCfg.resourceLength = transaction->resourceInfo.length;
1066 transaction->state = rmNameServerAddObject(&nameServerObjCfg);
1067 }
1068 else if (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) {
1069 if ((transaction->state = rmNameServerFindObject(&nameServerObjCfg)) ==
1070 RM_SERVICE_PROCESSING) {
1071 strncpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName, RM_NAME_MAX_CHARS);
1072 transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;
1073 transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;
1074 transaction->state = RM_SERVICE_APPROVED;
1075 }
1076 }
1077 else if (transaction->type == Rm_service_RESOURCE_UNMAP_NAME) {
1078 transaction->state = rmNameServerDeleteObject(&nameServerObjCfg);
1079 }
1081 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1082 rmNameServerTreeWb(rmInst->u.server.nameServer);
1083 }
1084 }
1085 else {
1086 transaction->state = RM_ERROR_NAMESERVER_DOES_NOT_EXIST;
1087 }
1088 break;
1089 }
1091 /* Source of shared server transaction will always be local. */
1092 if (rmInst->instType != Rm_instType_SHARED_SERVER) {
1093 if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {
1094 /* Source of transaction was not Server, return transaction via responder */
1095 transactionResponder(rmInst, transaction);
1096 }
1097 }
1098 /* Otherwise let call stack return transaction result app via Rm_serviceHandler */
1099 }
1101 /**********************************************************************
1102 ********************** Internal Functions ****************************
1103 **********************************************************************/
1105 /* FUNCTION PURPOSE: Adds a transaction
1106 ***********************************************************************
1107 * DESCRIPTION: Returns a pointer to a newly created transaction.
1108 * The transaction is created based on a new service
1109 * request received via the service API or the
1110 * transport API (service forwarded from another instance)
1111 */
1112 Rm_Transaction *rmTransactionQueueAdd(Rm_Inst *rmInst)
1113 {
1114 Rm_Transaction *transactionQueue = rmInst->transactionQueue;
1115 Rm_Transaction *newTransaction = NULL;
1117 newTransaction = Rm_osalMalloc(sizeof(Rm_Transaction));
1118 if (newTransaction) {
1119 memset((void *)newTransaction, 0, sizeof(Rm_Transaction));
1121 newTransaction->localId = transactionGetSequenceNum(rmInst);
1122 newTransaction->nextTransaction = NULL;
1123 if (transactionQueue) {
1124 while (transactionQueue->nextTransaction) {
1125 transactionQueue = transactionQueue->nextTransaction;
1126 }
1127 transactionQueue->nextTransaction = newTransaction;
1128 }
1129 else {
1130 rmInst->transactionQueue = newTransaction;
1131 }
1132 }
1133 return (newTransaction);
1134 }
1136 /* FUNCTION PURPOSE: Finds a transaction
1137 ***********************************************************************
1138 * DESCRIPTION: Returns a pointer to a transaction resident
1139 * in the transaction queue that matches the provided
1140 * transaction ID.
1141 */
1142 Rm_Transaction *rmTransactionQueueFind(Rm_Inst *rmInst, uint32_t transactionId)
1143 {
1144 Rm_Transaction *transaction = rmInst->transactionQueue;
1146 while (transaction) {
1147 if (transaction->localId == transactionId) {
1148 break;
1149 }
1150 transaction = transaction->nextTransaction;
1151 }
1153 return (transaction);
1154 }
1156 /* FUNCTION PURPOSE: Deletes a transaction
1157 ***********************************************************************
1158 * DESCRIPTION: Deletes the transaction with the provided transaction
1159 * ID from the instance's transaction queue.
1160 */
1161 int32_t rmTransactionQueueDelete(Rm_Inst *rmInst, uint32_t transactionId)
1162 {
1163 Rm_Transaction *transaction = rmInst->transactionQueue;
1164 Rm_Transaction *prevTransaction = NULL;
1165 int32_t retVal = RM_OK;
1167 while (transaction) {
1168 if (transaction->localId == transactionId) {
1169 break;
1170 }
1172 prevTransaction = transaction;
1173 transaction = transaction->nextTransaction;
1174 }
1176 if (transaction) {
1177 if (prevTransaction == NULL) {
1178 /* Transaction at start of queue. Map second transaction to start of queue
1179 * as long as more than one transactions. */
1180 rmInst->transactionQueue = transaction->nextTransaction;
1181 }
1182 else {
1183 /* Transaction in middle or end of queue. */
1184 prevTransaction->nextTransaction = transaction->nextTransaction;
1185 }
1186 Rm_osalFree((void *)transaction, sizeof(Rm_Transaction));
1187 }
1188 else {
1189 retVal = RM_ERROR_SERVICE_TRANS_DOES_NOT_EXIST;
1190 }
1191 return (retVal);
1192 }
1194 /* FUNCTION PURPOSE: Routes a transaction for processing
1195 ***********************************************************************
1196 * DESCRIPTION: Routes a received transaction to the appropriate
1197 * instance processing routine
1198 */
1199 void rmProcessRouter (Rm_Inst *rmInst, Rm_Transaction *transaction)
1200 {
1201 if (rmInst->instType == Rm_instType_CLIENT) {
1202 clientProcess(rmInst, transaction);
1203 }
1204 else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1205 cdProcess(rmInst, transaction);
1206 }
1207 else if ((rmInst->instType == Rm_instType_SERVER) ||
1208 (rmInst->instType == Rm_instType_SHARED_SERVER)) {
1209 serverProcess(rmInst, transaction);
1210 }
1211 }
1213 /**********************************************************************
1214 ********************** Application visible APIs **********************
1215 **********************************************************************/
1217 /* FUNCTION PURPOSE: Display status of managed resources
1218 ***********************************************************************
1219 * DESCRIPTION: Prints the status (allocate/free status, as well as
1220 * owners) for all resources managed by the RM
1221 * instance network. Also, prints the NameServer name
1222 * entries. The number of resource range owners is
1223 * returned as well. This function is only available on
1224 * Server and CD instances.
1225 */
1226 int32_t Rm_resourceStatus(Rm_Handle rmHandle, int printResources)
1227 {
1228 Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
1229 Rm_Allocator *allocator = NULL;
1230 Rm_Owner *owners;
1231 Rm_ResourceTree *treeRoot;
1232 Rm_ResourceNode *treeNode;
1233 int32_t totalResOwners = 0;
1234 void *key;
1236 RM_SS_INST_INV_ENTER_CS(key);
1237 RM_SC_INST_INV_ENTER_CS(key);
1239 if (rmInst->instType != Rm_instType_CLIENT) {
1240 Rm_osalLog("Instance name: %s\n", rmInst->instName);
1241 Rm_osalLog("Handle: 0x%08x\n", rmHandle);
1242 if (rmInst->instType == Rm_instType_SERVER) {
1243 Rm_osalLog("Type: Server\n");
1244 }
1245 else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1246 Rm_osalLog("Type: Client Delegate\n");
1247 }
1248 else if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1249 Rm_osalLog("Type: Shared Server\n");
1250 }
1251 else if (rmInst->instType == Rm_instType_SHARED_CLIENT) {
1252 Rm_osalLog("Type: Shared Client\n");
1253 }
1255 Rm_osalLog("\nResource Status:\n\n");
1256 }
1258 if (rmInst->instType == Rm_instType_SHARED_CLIENT) {
1259 /* Transfer control to shared server instance */
1260 rmInst = rmInst->u.sharedClient.sharedServerHandle;
1261 }
1263 if ((rmInst->instType == Rm_instType_SERVER) ||
1264 (rmInst->instType == Rm_instType_SHARED_SERVER) ||
1265 (rmInst->instType == Rm_instType_CLIENT_DELEGATE)) {
1266 allocator = rmAllocatorGetAllocatorList(rmHandle);
1268 if (!allocator) {
1269 Rm_osalLog("No resources managed by instance at the moment\n\n");
1270 }
1272 while (allocator) {
1273 RM_SS_OBJ_INV(allocator, Rm_Allocator);
1274 if (printResources) {
1275 Rm_osalLog("Resource: %s\n", allocator->resourceName);
1276 }
1278 treeRoot = allocator->allocatorRootEntry;
1279 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1280 rmResourceTreeInv(treeRoot);
1281 }
1282 RB_FOREACH(treeNode, _Rm_AllocatorResourceTree, treeRoot) {
1283 if (printResources) {
1284 if ((treeNode->base >= 65536) ||
1285 ((treeNode->base + treeNode->length - 1) >= 65536)) {
1286 /* Print in hex if number is very large */
1287 Rm_osalLog(" 0x%08x - 0x%08x ", treeNode->base,
1288 treeNode->base + treeNode->length - 1);
1289 }
1290 else {
1291 Rm_osalLog(" %10d - %10d ", treeNode->base,
1292 treeNode->base + treeNode->length - 1);
1293 }
1294 }
1296 if (treeNode->allocationCount == 0) {
1297 if (printResources) {
1298 Rm_osalLog("FREE\n");
1299 }
1300 }
1301 else {
1302 owners = treeNode->ownerList;
1303 while (owners) {
1304 RM_SS_OBJ_INV(owners, Rm_Owner);
1305 if (printResources) {
1306 Rm_osalLog("%s (%d) ", owners->instNameNode->name, owners->refCnt);
1307 }
1308 totalResOwners++;
1309 owners = owners->nextOwner;
1310 }
1311 if (printResources) {
1312 Rm_osalLog("\n");
1313 }
1314 }
1315 }
1316 allocator = allocator->nextAllocator;
1317 }
1319 if ((rmInst->instType == Rm_instType_SERVER) ||
1320 (rmInst->instType == Rm_instType_SHARED_SERVER)) {
1321 if (printResources) {
1322 rmNameServerPrintObjects((Rm_Handle)rmInst);
1323 }
1324 }
1325 }
1326 else {
1327 totalResOwners = RM_ERROR_INVALID_RES_STATUS_INSTANCE;
1328 }
1330 RM_SS_INST_WB_EXIT_CS(key);
1331 return(totalResOwners);
1332 }
1334 /* FUNCTION PURPOSE: Display status of a RM instance
1335 ***********************************************************************
1336 * DESCRIPTION: Prints the current status of various RM instance
1337 * properties such as the state of all transactions
1338 * in the transaction queue and registered transports
1339 */
1340 void Rm_instanceStatus(Rm_Handle rmHandle)
1341 {
1342 Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
1343 Rm_Transport *transportList = NULL;
1344 Rm_Transaction *transactionQ = NULL;
1345 void *key;
1347 RM_SS_INST_INV_ENTER_CS(key);
1348 RM_SC_INST_INV_ENTER_CS(key);
1350 Rm_osalLog("Instance name: %s\n", rmInst->instName);
1351 Rm_osalLog("Handle: 0x%08x\n", rmHandle);
1352 if (rmInst->instType == Rm_instType_SERVER) {
1353 Rm_osalLog("Type: Server\n");
1354 }
1355 else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1356 Rm_osalLog("Type: Client Delegate\n");
1357 }
1358 else if (rmInst->instType == Rm_instType_CLIENT) {
1359 Rm_osalLog("Type: Client\n");
1360 }
1361 else if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1362 Rm_osalLog("Type: Shared Server\n");
1363 }
1364 else if (rmInst->instType == Rm_instType_SHARED_CLIENT) {
1365 Rm_osalLog("Type: Shared Client\n");
1367 Rm_osalLog("\nShared Server Properties:\n");
1368 /* Transfer to Shared Server instance to print out transport and
1369 * transaction status */
1370 rmInst = rmInst->u.sharedClient.sharedServerHandle;
1371 Rm_osalLog("Instance name: %s\n", rmInst->instName);
1372 Rm_osalLog("Handle: 0x%08x\n", rmHandle);
1373 }
1375 transportList = rmInst->transports;
1376 if (transportList) {
1377 Rm_osalLog("\nRegistered Transports:\n");
1378 while (transportList) {
1379 RM_SS_OBJ_INV(transportList, Rm_Transport);
1380 if (transportList->remoteInstType == Rm_instType_SERVER) {
1381 Rm_osalLog(" Remote instType: Server\n");
1382 }
1383 else if (transportList->remoteInstType == Rm_instType_CLIENT_DELEGATE) {
1384 Rm_osalLog(" Remote instType: Client Delegate\n");
1385 }
1386 else {
1387 Rm_osalLog(" Remote instType: Client\n");
1388 }
1389 Rm_osalLog(" appTransportHandle: 0x%08x\n", transportList->appTransportHandle);
1390 Rm_osalLog("\n");
1391 transportList = transportList->nextTransport;
1392 }
1393 }
1395 transactionQ = rmInst->transactionQueue;
1396 if (transactionQ) {
1397 Rm_osalLog("\nQueued Service Transactions:\n");
1398 while (transactionQ) {
1399 RM_SS_OBJ_INV(transactionQ, Rm_Transaction);
1400 Rm_osalLog(" Service type: %d\n", transactionQ->type);
1401 Rm_osalLog(" Service ID: %d\n", transactionQ->localId);
1402 Rm_osalLog(" Service srcInstName %s\n", transactionQ->serviceSrcInstName);
1403 Rm_osalLog(" Service state: %d\n", transactionQ->state);
1404 Rm_osalLog(" Resource name: %s\n", transactionQ->resourceInfo.name);
1405 Rm_osalLog(" Resource base: %d\n", transactionQ->resourceInfo.base);
1406 Rm_osalLog(" Resource length: %d\n", transactionQ->resourceInfo.length);
1407 Rm_osalLog(" Resource alignment: %d\n", transactionQ->resourceInfo.alignment);
1408 Rm_osalLog(" Resource NS name: %s\n", transactionQ->resourceInfo.nameServerName);
1409 Rm_osalLog("\n");
1410 transactionQ = transactionQ->nextTransaction;
1411 }
1412 }
1413 RM_SS_INST_WB_EXIT_CS(key);
1414 }
1416 /* FUNCTION PURPOSE: RM instance creation and initialization
1417 ***********************************************************************
1418 * DESCRIPTION: Returns a new RM instance created and initialized
1419 * using the parameters provided via the initCfg
1420 * structure.
1421 */
1422 Rm_Handle Rm_init(const Rm_InitCfg *initCfg, int32_t *result)
1423 {
1424 Rm_Inst *rmInst = NULL;
1425 Rm_Inst *sharedServerInst = NULL;
1426 uint32_t policySize;
1427 void *globalResourceDtb = NULL;
1428 void *linuxResourceDtb = NULL;
1429 int addLinux = RM_FALSE;
1430 void *key;
1432 *result = RM_OK;
1434 if ((initCfg->instName == NULL) ||
1435 ((strlen(initCfg->instName) + 1) > RM_NAME_MAX_CHARS)) {
1436 *result = RM_ERROR_INVALID_INST_NAME;
1437 goto errorExit;
1438 }
1440 if (initCfg->instType >= Rm_instType_LAST) {
1441 *result = RM_ERROR_INVALID_INST_TYPE;
1442 goto errorExit;
1443 }
1445 /* Create and initialize instance */
1446 rmInst = Rm_osalMalloc(sizeof(*rmInst));
1447 memset ((void *)rmInst, 0, sizeof(*rmInst));
1448 rmInst->isLocked = RM_FALSE;
1449 rmInst->registeredWithDelegateOrServer = RM_FALSE;
1450 rmInst->transactionSeqNum = transactionInitSequenceNum();
1452 rmInst->instType = initCfg->instType;
1453 strncpy (rmInst->instName, initCfg->instName, RM_NAME_MAX_CHARS);
1455 if ((rmInst->instType == Rm_instType_SERVER) ||
1456 (rmInst->instType == Rm_instType_SHARED_SERVER)) {
1457 if (!initCfg->instCfg.serverCfg.globalResourceList ||
1458 !initCfg->instCfg.serverCfg.globalPolicy) {
1459 *result = RM_ERROR_INVALID_SERVER_CONFIGURATION;
1460 goto errorExit;
1461 }
1463 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1464 /* Shared Server makes copy of policy in shared memory for Shared Clients
1465 * on other cores */
1466 policySize = fdt_totalsize(initCfg->instCfg.serverCfg.globalPolicy);
1467 /* Align policy size to cache boundary */
1468 if (policySize % RM_MAX_CACHE_ALIGN) {
1469 policySize += (RM_MAX_CACHE_ALIGN - (policySize % RM_MAX_CACHE_ALIGN));
1470 }
1471 rmInst->u.server.policySize = policySize;
1472 rmInst->u.server.globalPolicy = Rm_osalMalloc(rmInst->u.server.policySize);
1473 memcpy(rmInst->u.server.globalPolicy, initCfg->instCfg.serverCfg.globalPolicy, rmInst->u.server.policySize);
1474 }
1475 else {
1476 rmInst->u.server.globalPolicy = initCfg->instCfg.serverCfg.globalPolicy;
1477 }
1479 if (initCfg->instCfg.serverCfg.linuxDtb) {
1480 linuxResourceDtb = initCfg->instCfg.serverCfg.linuxDtb;
1481 addLinux = RM_TRUE;
1482 }
1484 /* Create valid instance list from policy. Must be done prior to parsing
1485 * GRL so that Linux resources can be reserved correctly */
1486 rmInst->u.server.globalValidInstTree = rmPolicyCreateValidInstTree((Rm_Handle)rmInst, addLinux, result);
1487 if (*result == RM_OK) {
1488 *result = rmPolicyValidatePolicy((Rm_Handle)rmInst);
1489 }
1491 if (*result != RM_OK) {
1492 if (rmInst->u.server.globalValidInstTree) {
1493 rmPolicyFreeValidInstTree((Rm_Handle)rmInst);
1494 }
1495 goto errorExit;
1496 }
1497 else {
1498 rmNameServerInit((Rm_Handle)rmInst);
1500 globalResourceDtb = initCfg->instCfg.serverCfg.globalResourceList;
1502 if ((*result = rmAllocatorInitializeResources((Rm_Handle) rmInst, globalResourceDtb, linuxResourceDtb)) == RM_OK) {
1503 *result = rmPolicyValidatePolicyResourceNames((Rm_Handle)rmInst);
1504 }
1506 if (*result != RM_OK) {
1507 rmAllocatorDeleteResources((Rm_Handle)rmInst);
1508 rmNameServerDelete((Rm_Handle)rmInst);
1509 goto errorExit;
1510 }
1511 }
1512 }
1513 else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1514 if (!initCfg->instCfg.cdCfg.cdPolicy) {
1515 *result = RM_ERROR_INVALID_CD_CONFIGURATION;
1516 goto errorExit;
1517 }
1519 rmInst->u.cd.cdPolicy = initCfg->instCfg.cdCfg.cdPolicy;
1520 rmInst->u.cd.cdValidInstTree = 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.cd.cdValidInstTree) {
1527 rmPolicyFreeValidInstTree((Rm_Handle)rmInst);
1528 }
1529 goto errorExit;
1530 }
1532 rmInst->u.cd.allocators = NULL;
1534 /* Remove once CD instance is stable - tracked by SDOCM00100797 */
1535 *result = RM_WARNING_CD_INSTANCE_NOT_STABLE;
1536 }
1537 else if (rmInst->instType == Rm_instType_CLIENT) {
1538 if (initCfg->instCfg.clientCfg.staticPolicy) {
1539 rmInst->u.client.staticPolicy = initCfg->instCfg.clientCfg.staticPolicy;
1540 rmInst->u.client.staticValidInstTree = rmPolicyCreateValidInstTree((Rm_Handle)rmInst, addLinux, result);
1541 if (*result == RM_OK) {
1542 *result = rmPolicyValidatePolicy((Rm_Handle)rmInst);
1543 }
1545 if (*result != RM_OK) {
1546 if (rmInst->u.client.staticValidInstTree) {
1547 rmPolicyFreeValidInstTree((Rm_Handle)rmInst);
1548 }
1549 goto errorExit;
1550 }
1551 }
1552 }
1553 else if (rmInst->instType == Rm_instType_SHARED_CLIENT) {
1554 if (initCfg->instCfg.sharedClientCfg.sharedServerHandle) {
1555 rmInst->u.sharedClient.sharedServerHandle = initCfg->instCfg.sharedClientCfg.sharedServerHandle;
1556 /* Invalidate the Shared server instance structure on this core to get the latest
1557 * instance data. */
1558 key = Rm_osalCsEnter();
1559 Rm_osalBeginMemAccess((void *)rmInst->u.sharedClient.sharedServerHandle, sizeof(Rm_Inst));
1560 sharedServerInst = rmInst->u.sharedClient.sharedServerHandle;
1561 if (sharedServerInst->instType != Rm_instType_SHARED_SERVER) {
1562 *result = RM_ERROR_INVALID_SHARED_SERVER_HANDLE;
1563 Rm_osalCsExit(key);
1564 goto errorExit;
1565 }
1566 else {
1567 /* Invalidate the policy */
1568 Rm_osalBeginMemAccess((void *)sharedServerInst->u.server.globalPolicy,
1569 sharedServerInst->u.server.policySize);
1570 }
1571 Rm_osalCsExit(key);
1572 }
1573 else {
1574 *result = RM_ERROR_INVALID_SHARED_SERVER_HANDLE;
1575 goto errorExit;
1576 }
1577 }
1579 if (initCfg->instType == Rm_instType_SHARED_SERVER) {
1580 /* Writeback the instance and policy for other cores */
1581 Rm_osalEndMemAccess ((void *)rmInst, sizeof(Rm_Inst));
1582 Rm_osalEndMemAccess ((void *)rmInst->u.server.globalPolicy, rmInst->u.server.policySize);
1583 }
1584 else if (rmInst->instType != Rm_instType_SHARED_CLIENT) {
1585 /* Create the instance's task blocking mechanism */
1586 rmInst->blockHandle = Rm_osalTaskBlockCreate();
1587 }
1589 return ((Rm_Handle) rmInst);
1590 errorExit:
1591 if (rmInst) {
1592 Rm_osalFree((void *)rmInst, sizeof(Rm_Inst));
1593 }
1594 return (NULL);
1595 }
1597 /* FUNCTION PURPOSE: Deletes an RM instance
1598 ***********************************************************************
1599 * DESCRIPTION: Frees all memory associated with an RM instance
1600 * as long as all transports have been unregistered
1601 * and the service handle has been closed
1602 */
1603 int32_t Rm_delete(Rm_Handle rmHandle, int ignorePendingServices)
1604 {
1605 Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
1606 void *key;
1608 key = Rm_osalCsEnter();
1609 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1610 Rm_osalBeginMemAccess((void *)rmInst, sizeof(Rm_Inst));
1611 }
1613 if (rmInst->serviceHandle) {
1614 return (RM_ERROR_CANT_DELETE_WITH_OPEN_SERV_HNDL);
1615 }
1616 else if (rmInst->transports) {
1617 return (RM_ERROR_CANT_DELETE_WITH_REGD_TRANSPORT);
1618 }
1619 else if (rmInst->transactionQueue && !ignorePendingServices) {
1620 return (RM_ERROR_CANT_DELETE_PENDING_TRANSACTIONS);
1621 }
1623 if ((rmInst->instType == Rm_instType_SERVER) ||
1624 (rmInst->instType == Rm_instType_SHARED_SERVER)) {
1625 rmAllocatorDeleteResources(rmHandle);
1626 rmNameServerDelete(rmHandle);
1627 rmInst->u.server.allocators = NULL;
1629 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1630 Rm_osalFree((void *)rmInst->u.server.globalPolicy, rmInst->u.server.policySize);
1631 }
1632 }
1633 else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1634 rmAllocatorDeleteResources(rmHandle);
1635 rmInst->u.cd.allocators = NULL;
1636 }
1638 if (rmInst->instType != Rm_instType_SHARED_CLIENT) {
1639 /* Delete valid instance tree */
1640 rmPolicyFreeValidInstTree(rmHandle);
1642 /* Delete any transactions */
1643 while(rmInst->transactionQueue) {
1644 rmTransactionQueueDelete(rmInst, rmInst->transactionQueue->localId);
1645 }
1647 if (rmInst->instType != Rm_instType_SHARED_SERVER) {
1648 /* Delete the instance's task blocking mechanism */
1649 Rm_osalTaskBlockDelete(rmInst->blockHandle);
1650 }
1651 else {
1652 Rm_osalEndMemAccess((void *)rmInst, sizeof(Rm_Inst));
1653 }
1654 }
1656 Rm_osalFree((void *)rmInst, sizeof(Rm_Inst));
1658 Rm_osalCsExit(key);
1659 return (RM_OK);
1660 }
1662 /* FUNCTION PURPOSE: Returns RM version information
1663 ***********************************************************************
1664 */
1665 uint32_t Rm_getVersion(void)
1666 {
1667 return RM_VERSION_ID;
1668 }
1670 /* FUNCTION PURPOSE: Returns RM version string
1671 ***********************************************************************
1672 */
1673 const char* Rm_getVersionStr(void)
1674 {
1675 return rmVersionStr;
1676 }