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>
45 /* RM external includes */
46 #include <ti/drv/rm/rm.h>
47 #include <ti/drv/rm/rmver.h>
48 #include <ti/drv/rm/rm_services.h>
49 #include <ti/drv/rm/rm_transport.h>
51 /* RM internal includes */
52 #include <ti/drv/rm/include/rm_internal.h>
53 #include <ti/drv/rm/include/rm_loc.h>
54 #include <ti/drv/rm/include/rm_allocatorloc.h>
55 #include <ti/drv/rm/include/rm_transportloc.h>
56 #include <ti/drv/rm/include/rm_nameserverloc.h>
57 #include <ti/drv/rm/include/rm_servicesloc.h>
59 /* RM LIBFDT includes */
60 #include <ti/drv/rm/util/libfdt/libfdt.h>
62 /* RM OSAL layer */
63 #include <rm_osal.h>
65 /**********************************************************************
66 ************************** Globals ***********************************
67 **********************************************************************/
69 /* Global Variable which describes the RM Version Information */
70 const char rmVersionStr[] = RM_VERSION_STR ":" __DATE__ ":" __TIME__;
72 /**********************************************************************
73 ************************ Local Functions *****************************
74 **********************************************************************/
76 /* FUNCTION PURPOSE: Initializes a RM inst's transaction sequence number
77 ***********************************************************************
78 * DESCRIPTION: The RM instance transaction sequence number can never
79 * have a value of 0 to avoid conflicts with transactions
80 * that have a remoteOriginatingId of 0 (transaction ID
81 * will be used as the remoteOriginatingId for
82 * transactions that are responses to requests).
83 */
84 static uint32_t transactionInitSequenceNum(void)
85 {
86 return (1);
87 }
89 /* FUNCTION PURPOSE: Provides a sequence number for new transactions
90 ***********************************************************************
91 * DESCRIPTION: Returns a sequence number for a new transaction
92 * specific to a RM instance. Handles rollover of
93 * sequence number.
94 */
95 static uint32_t transactionGetSequenceNum(Rm_Inst *rmInst)
96 {
97 rmInst->transactionSeqNum++;
98 if (!rmInst->transactionSeqNum) {
99 rmInst->transactionSeqNum++;
100 }
101 return (rmInst->transactionSeqNum);
102 }
104 /* FUNCTION PURPOSE: Creates a resource request packet
105 ***********************************************************************
106 * DESCRIPTION: Returns a RM packet handle that points to a RM
107 * resource request packet that has been prepared
108 * for sending to another RM instance. The packet
109 * is allocated via the rmAllocPkt API using the
110 * appTransport handle provided by the application
111 */
112 void createResourceReqPkt(Rm_Packet *rmPkt, char *localInstName, Rm_Transaction *transaction)
113 {
114 Rm_ResourceRequestPkt *resourceReqPkt = NULL;
116 rmPkt->pktType = Rm_pktType_RESOURCE_REQUEST;
117 resourceReqPkt = (Rm_ResourceRequestPkt *) rmPkt->data;
118 resourceReqPkt->requestId = transaction->localId;
119 if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
120 resourceReqPkt->resourceReqType = Rm_resReqPktType_ALLOCATE_INIT;
121 }
122 else if (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) {
123 resourceReqPkt->resourceReqType = Rm_resReqPktType_ALLOCATE_USE;
124 }
125 else if (transaction->type == Rm_service_RESOURCE_STATUS) {
126 resourceReqPkt->resourceReqType = Rm_resReqPktType_GET_STATUS;
127 }
128 else if (transaction->type == Rm_service_RESOURCE_FREE) {
129 resourceReqPkt->resourceReqType = Rm_resReqPktType_FREE;
130 }
131 else if (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) {
132 resourceReqPkt->resourceReqType = Rm_resReqPktType_GET_NAMED;
133 }
134 rm_strncpy(resourceReqPkt->pktSrcInstName, localInstName, RM_NAME_MAX_CHARS);
135 rm_strncpy(resourceReqPkt->serviceSrcInstName, transaction->serviceSrcInstName, RM_NAME_MAX_CHARS);
136 memcpy ((void *)&(resourceReqPkt->resourceInfo), (void *)&(transaction->resourceInfo),
137 sizeof(Rm_ResourceInfo));
138 }
140 /* FUNCTION PURPOSE: Creates a resource response packet
141 ***********************************************************************
142 * DESCRIPTION: Returns a RM packet handle that points to a RM
143 * resource response packet that has been prepared
144 * for sending to another RM instance. The packet
145 * is allocated via the rmAllocPkt API using the
146 * appTransport handle provided by the application
147 */
148 void createResourceResponsePkt(Rm_Packet *rmPkt, Rm_Transaction *transaction)
149 {
150 Rm_ResourceResponsePkt *resourceRespPkt = NULL;
152 rmPkt->pktType = Rm_pktType_RESOURCE_RESPONSE;
153 resourceRespPkt = (Rm_ResourceResponsePkt *)rmPkt->data;
154 resourceRespPkt->responseId = transaction->remoteOriginatingId;
155 resourceRespPkt->requestState = transaction->state;
156 memcpy ((void *)&(resourceRespPkt->resourceInfo), (void *)&(transaction->resourceInfo),
157 sizeof(Rm_ResourceInfo));
158 }
160 /* FUNCTION PURPOSE: Creates a NameServer request packet
161 ***********************************************************************
162 * DESCRIPTION: Returns a RM packet handle that points to a RM
163 * NameServer request packet that has been prepared
164 * for sending to another RM instance. The packet
165 * is allocated via the rmAllocPkt API using the
166 * appTransport handle provided by the application
167 */
168 void createNsRequestPkt(Rm_Packet *rmPkt, char *localInstName, Rm_Transaction *transaction)
169 {
170 Rm_NsRequestPkt *nsReqPkt = NULL;
172 rmPkt->pktType = Rm_pktType_NAMESERVER_REQUEST;
173 nsReqPkt = (Rm_NsRequestPkt *)rmPkt->data;
174 nsReqPkt->requestId = transaction->localId;
175 if (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) {
176 nsReqPkt->nsRequestType = Rm_nsReqPktType_MAP_RESOURCE;
177 }
178 else if (transaction->type == Rm_service_RESOURCE_UNMAP_NAME) {
179 nsReqPkt->nsRequestType = Rm_nsReqPktType_UNMAP_RESOURCE;
180 }
181 rm_strncpy(nsReqPkt->pktSrcInstName, localInstName, RM_NAME_MAX_CHARS);
182 rm_strncpy(nsReqPkt->serviceSrcInstName, transaction->serviceSrcInstName, RM_NAME_MAX_CHARS);
183 memcpy ((void *)&(nsReqPkt->resourceInfo), (void *)&(transaction->resourceInfo),
184 sizeof(Rm_ResourceInfo));
185 }
187 /* FUNCTION PURPOSE: Creates a NameServer response packet
188 ***********************************************************************
189 * DESCRIPTION: Returns a RM packet handle that points to a RM
190 * NameServer response packet that has been prepared
191 * for sending to another RM instance. The packet
192 * is allocated via the rmAllocPkt API using the
193 * appTransport handle provided by the application
194 */
195 void createNsResponsePkt(Rm_Packet *rmPkt, Rm_Transaction *transaction)
196 {
197 Rm_NsResponsePkt *nsRespPkt = NULL;
199 rmPkt->pktType = Rm_pktType_NAMESERVER_RESPONSE;
200 nsRespPkt = (Rm_NsResponsePkt *)rmPkt->data;
201 nsRespPkt->responseId = transaction->remoteOriginatingId;
202 nsRespPkt->requestState = transaction->state;
203 }
205 /* FUNCTION PURPOSE: Issues a service response to application
206 ***********************************************************************
207 * DESCRIPTION: Provides a service response back to the application
208 * using the service callback function provided to
209 * the RM instance at the time of the service request.
210 */
211 static void serviceResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)
212 {
213 Rm_ServiceRespInfo serviceResponse;
215 serviceResponse.rmHandle = (Rm_Handle)rmInst;
216 /* The responseTransaction will contain the resultant state details of
217 * the requestTransaction's service request */
218 serviceResponse.serviceState = transaction->state;
219 /* Pass back the ID that was provided to the component when it requested
220 * the service */
221 serviceResponse.serviceId = transaction->localId;
222 /* Owner and instance allocation count will only be set within RM under certain circumstances. */
223 serviceResponse.resourceNumOwners = transaction->resourceInfo.ownerCount;
224 serviceResponse.instAllocCount = transaction->resourceInfo.instAllocCount;
226 /* Service was approved and service was an allocate request. The resource
227 * data is passed back to the component */
228 if ((serviceResponse.serviceState == RM_SERVICE_APPROVED) &&
229 ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||
230 (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) ||
231 (transaction->type == Rm_service_RESOURCE_FREE) ||
232 (transaction->type == Rm_service_RESOURCE_STATUS) ||
233 (transaction->type == Rm_service_RESOURCE_GET_BY_NAME)))
234 {
235 rm_strncpy(serviceResponse.resourceName, transaction->resourceInfo.name, RM_NAME_MAX_CHARS);
236 serviceResponse.resourceBase = transaction->resourceInfo.base;
237 serviceResponse.resourceLength = transaction->resourceInfo.length;
238 }
240 if (transaction->u.callback.serviceCallback) {
241 /* Issue the callback to the requesting component with the response information */
242 transaction->u.callback.serviceCallback(&serviceResponse);
243 /* Delete the transaction from the transaction queue */
244 rmTransactionQueueDelete(rmInst, transaction->localId);
245 }
246 else {
247 rmServiceInternalCallback((Rm_Handle)rmInst);
248 }
250 return;
251 }
253 /* FUNCTION PURPOSE: Sends RM response packets
254 ***********************************************************************
255 * DESCRIPTION: Sends RM response packets to RM instance's that sent
256 * RM request packets to the RM instance. The response
257 * is sent via the RM transport API which is plugged
258 * with an application created transport path.
259 */
260 static void transactionResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)
261 {
262 Rm_Transport *dstTransport = transaction->u.respTrans;
263 Rm_Packet *rmPkt = NULL;
264 Rm_PacketHandle pktHandle = NULL;
266 rmPkt = dstTransport->callouts.rmAllocPkt(dstTransport->appTransportHandle,
267 sizeof(Rm_Packet), &pktHandle);
268 if (!rmPkt || !pktHandle) {
269 transaction->state = RM_ERROR_TRANSPORT_ALLOC_PKT_ERROR;
270 goto errorExit;
271 }
273 switch (transaction->type) {
274 case Rm_service_RESOURCE_ALLOCATE_INIT:
275 case Rm_service_RESOURCE_ALLOCATE_USE:
276 case Rm_service_RESOURCE_STATUS:
277 case Rm_service_RESOURCE_FREE:
278 case Rm_service_RESOURCE_GET_BY_NAME:
279 createResourceResponsePkt(rmPkt, transaction);
280 break;
281 case Rm_service_RESOURCE_MAP_TO_NAME:
282 case Rm_service_RESOURCE_UNMAP_NAME:
283 createNsResponsePkt(rmPkt, transaction);
284 break;
285 }
286 if (dstTransport->callouts.rmSendPkt(dstTransport->appTransportHandle, pktHandle) < RM_OK) {
287 transaction->state = RM_ERROR_TRANSPORT_SEND_ERROR;
288 goto errorExit;
289 }
291 /* Response packet sent: Delete transaction from queue */
292 rmTransactionQueueDelete(rmInst, transaction->localId);
294 errorExit:
295 /* Do not delete transaction on transport error. Transport error transactions should be visible
296 * from Rm_printInstanceStatus() */
297 return;
298 }
300 /* FUNCTION PURPOSE: Sends RM request packets
301 ***********************************************************************
302 * DESCRIPTION: Sends RM request packets to RM instance's that are
303 * capable of forwarding or validating service requests.
304 * The request is sent via the RM transport API which is
305 * plugged with an application created transport path.
306 */
307 static void transactionForwarder (Rm_Inst *rmInst, Rm_Transaction *transaction)
308 {
309 Rm_Transport *dstTransport = NULL;
310 Rm_Packet *rmPkt = NULL;
311 Rm_PacketHandle pktHandle = NULL;
313 if (rmInst->instType == Rm_instType_CLIENT) {
314 dstTransport = rmTransportFindRemoteInstType(rmInst->transports, Rm_instType_CLIENT_DELEGATE);
316 if (!dstTransport) {
317 dstTransport = rmTransportFindRemoteInstType(rmInst->transports, Rm_instType_SERVER);
318 }
319 }
320 else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
321 dstTransport = rmTransportFindRemoteInstType(rmInst->transports, Rm_instType_SERVER);
322 }
324 /* Just queue transaction if transport hasn't been registered. Do not return error */
325 if (dstTransport) {
326 rmPkt = dstTransport->callouts.rmAllocPkt(dstTransport->appTransportHandle,
327 sizeof(Rm_Packet), &pktHandle);
328 if (!rmPkt || !pktHandle) {
329 transaction->state = RM_ERROR_TRANSPORT_ALLOC_PKT_ERROR;
330 goto errorExit;
331 }
333 switch (transaction->type) {
334 case Rm_service_RESOURCE_ALLOCATE_INIT:
335 case Rm_service_RESOURCE_ALLOCATE_USE:
336 case Rm_service_RESOURCE_STATUS:
337 case Rm_service_RESOURCE_FREE:
338 case Rm_service_RESOURCE_GET_BY_NAME:
339 createResourceReqPkt(rmPkt, rmInst->instName, transaction);
340 break;
341 case Rm_service_RESOURCE_MAP_TO_NAME:
342 case Rm_service_RESOURCE_UNMAP_NAME:
343 createNsRequestPkt(rmPkt, rmInst->instName, transaction);
344 break;
345 }
347 if (dstTransport->callouts.rmSendPkt(dstTransport->appTransportHandle, pktHandle) < RM_OK) {
348 transaction->state = RM_ERROR_TRANSPORT_SEND_ERROR;
349 goto errorExit;
350 }
351 transaction->hasBeenForwarded = RM_TRUE;
352 /* Transaction not deleted. Waiting for response from RM CD or Server */
353 }
354 errorExit:
355 /* Do not delete transaction on transport error. Transport error transactions should be visible
356 * from Rm_printInstanceStatus() */
357 return;
358 }
360 /* FUNCTION PURPOSE: Handles static allocation requests
361 ***********************************************************************
362 * DESCRIPTION: Validates allocation requests received on CDs and
363 * Clients prior to the instance's registering
364 * with a Server. The allocation request is validated
365 * against a static policy.
366 */
367 static void staticAllocationHandler (Rm_Handle rmHandle, Rm_Transaction *transaction)
368 {
369 Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
370 void *staticPolicy = rmPolicyGetPolicy(rmHandle);
371 Rm_PolicyCheckCfg privCheckCfg;
372 int32_t result;
374 if (staticPolicy) {
375 if ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||
376 (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE)) {
377 /* Check request against static policy */
378 memset((void *)&privCheckCfg, 0, sizeof(Rm_PolicyCheckCfg));
380 if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
381 privCheckCfg.type = Rm_policyCheck_INIT;
382 }
383 else {
384 privCheckCfg.type = Rm_policyCheck_USE;
385 }
386 privCheckCfg.policyDtb = staticPolicy;
387 privCheckCfg.validInstNode = rmPolicyGetValidInstNode(rmHandle, rmInst->instName);
388 privCheckCfg.resourceOffset = rmPolicyGetResourceOffset(staticPolicy,
389 transaction->resourceInfo.name);
390 privCheckCfg.resourceBase = transaction->resourceInfo.base;
391 privCheckCfg.resourceLength = transaction->resourceInfo.length;
393 if (rmPolicyCheckPrivilege(&privCheckCfg, &result)) {
394 transaction->state = RM_SERVICE_APPROVED_STATIC;
395 }
396 else if (result == RM_OK) {
397 /* Privilege check returned false without error */
398 transaction->state = RM_SERVICE_DENIED_BY_STATIC_POLICY;
399 }
400 else {
401 /* Privilege check returned false with error */
402 transaction->state = result;
403 }
404 }
405 else {
406 transaction->state = RM_SERVICE_DENIED_INVALID_STATIC_REQUEST;
407 }
408 }
409 else {
410 transaction->state = RM_ERROR_REQ_FAILED_NO_STATIC_POLICY;
411 }
412 }
414 /* FUNCTION PURPOSE: Requests resources from Server for CD
415 ***********************************************************************
416 * DESCRIPTION: Function creates a service request to allocate resources
417 * from the Server for local management by the CD. The
418 * transaction which causes this request is put in the
419 * pending state in order to wait for the response from the
420 * Server
421 */
422 static int32_t cdRequestServerResources(Rm_Inst *rmInst, Rm_Transaction *transaction)
423 {
424 Rm_Transaction *newTrans = NULL;
425 void * policy = rmPolicyGetPolicy((Rm_Handle)rmInst);
426 int32_t resourceOffsetInPolicy;
427 uint32_t allocSize = 0;
428 int32_t retVal;
430 resourceOffsetInPolicy = rmPolicyGetResourceOffset(policy, transaction->resourceInfo.name);
431 if (resourceOffsetInPolicy > 0) {
432 if (allocSize = rmPolicyGetResourceCdAllocSize(policy, resourceOffsetInPolicy)) {
433 if (newTrans = rmTransactionQueueAdd(rmInst)) {
434 newTrans->type = transaction->type;
435 rm_strncpy(newTrans->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS);
436 newTrans->state = RM_SERVICE_PROCESSING;
437 rm_strncpy(newTrans->resourceInfo.name, transaction->resourceInfo.name, RM_NAME_MAX_CHARS);
438 newTrans->resourceInfo.base = RM_RESOURCE_BASE_UNSPECIFIED;
439 /* Make sure request length will satisfy transaction length */
440 newTrans->resourceInfo.length = allocSize;
441 while (newTrans->resourceInfo.length < transaction->resourceInfo.length) {
442 newTrans->resourceInfo.length += allocSize;
443 }
444 newTrans->resourceInfo.alignment = transaction->resourceInfo.alignment;
445 newTrans->pendingTransactionId = transaction->localId;
446 transactionForwarder(rmInst, newTrans);
448 retVal = RM_SERVICE_PENDING_SERVER_RESPONSE;
449 }
450 else {
451 retVal = RM_ERROR_TRANS_REQ_TO_SERVER_NOT_CREATED;
452 }
453 }
454 else {
455 /* Forward request to Server for completion if policy has
456 * no allocation size for resource */
457 retVal = RM_SERVICE_PROCESSING;
458 }
459 }
460 else {
461 /* Resource could not be found in policy */
462 retVal = RM_SERVICE_DENIED_RES_DOES_NOT_EXIST;
463 }
464 return (retVal);
465 }
467 /* FUNCTION PURPOSE: Frees local resources to Server from CD
468 ***********************************************************************
469 * DESCRIPTION: Function creates a service request to free locally
470 * managed resources that are now localized back to
471 * the Server.
472 */
473 static int32_t cdFreeResourcesToServer(Rm_Inst *rmInst, Rm_Transaction *transaction)
474 {
475 int32_t baseToFree = transaction->resourceInfo.base;
476 uint32_t lenToFree = transaction->resourceInfo.length;
477 Rm_Transaction *newTrans = NULL;
478 /* This function should only be called after a free was approved */
479 int32_t retVal = RM_SERVICE_APPROVED;
481 /* Did free result in a localized free node that can be given back to Server? If
482 * so create transaction to Server to free localized resource node */
483 if (rmAllocatorGetNodeLocalization((Rm_Handle)rmInst, transaction->resourceInfo.name,
484 &baseToFree, &lenToFree)) {
485 if (newTrans = rmTransactionQueueAdd(rmInst)) {
486 newTrans->type = transaction->type;
487 rm_strncpy(newTrans->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS);
488 newTrans->state = RM_SERVICE_PROCESSING;
489 rm_strncpy(newTrans->resourceInfo.name, transaction->resourceInfo.name, RM_NAME_MAX_CHARS);
490 newTrans->resourceInfo.base = baseToFree;
491 newTrans->resourceInfo.length = lenToFree;
492 newTrans->pendingTransactionId = transaction->localId;
493 transactionForwarder(rmInst, newTrans);
495 retVal = RM_SERVICE_PENDING_SERVER_RESPONSE;
496 }
497 else {
498 /* Error: Need to re-allocate what was freed */
499 retVal = RM_ERROR_TRANS_REQ_TO_SERVER_NOT_CREATED;
500 }
501 }
502 return (retVal);
503 }
505 /* FUNCTION PURPOSE: Arbitrates allocation service requests
506 ***********************************************************************
507 * DESCRIPTION: Issues a set of allocator operations in order to
508 * handle a received allocation request. Allocation
509 * requests are always forwarded to the Server on Client
510 * CD instances. If a request is made with a NameServer
511 * name the resource base and length parameters are
512 * retrieved from the NameServer prior to the allocation
513 * attempt.
514 */
515 static void allocationHandler (Rm_Inst *rmInst, Rm_Transaction *transaction)
516 {
517 Rm_AllocatorOpInfo opInfo;
518 Rm_NameServerObjCfg nameServerObjCfg;
519 int32_t retVal = transaction->state;
521 memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));
522 opInfo.policy = rmPolicyGetPolicy((Rm_Handle)rmInst);
523 opInfo.resourceInfo = &transaction->resourceInfo;
524 opInfo.serviceSrcInstNode = rmPolicyGetValidInstNode((Rm_Handle)rmInst, transaction->serviceSrcInstName);
525 if (opInfo.serviceSrcInstNode == NULL) {
526 retVal = RM_SERVICE_DENIED_INST_NAME_NOT_VALID;
527 goto errorExit;
528 }
530 if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
531 if (transaction->resourceInfo.base != RM_RESOURCE_BASE_UNSPECIFIED) {
532 if (rmAllocatorFind((Rm_Handle)rmInst, transaction->resourceInfo.name)) {
533 /* Attempt to allocate from local resources that were provided by Server */
534 if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
535 opInfo.operation = Rm_allocatorOp_ALLOCATE_INIT;
536 }
537 else if (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) {
538 opInfo.operation = Rm_allocatorOp_ALLOCATE_USE;
539 }
540 else {
541 retVal = RM_ERROR_INVALID_SERVICE_TYPE;
542 goto errorExit;
543 }
544 retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
546 if (retVal == RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST) {
547 /* Request resource range was not found within local resources
548 * provided by Server. Set back to PROCESSING so request is forwarded to
549 * Server */
550 retVal = RM_SERVICE_PROCESSING;
551 }
552 }
553 }
554 else {
555 if (rmAllocatorFind((Rm_Handle)rmInst, transaction->resourceInfo.name)) {
556 int32_t oldAlign = transaction->resourceInfo.alignment;
558 /* Attempt to allocate from local resources that were provided by Server */
559 if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
560 opInfo.operation = Rm_allocatorOp_PRE_ALLOCATE_INIT;
561 }
562 else if (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) {
563 opInfo.operation = Rm_allocatorOp_PRE_ALLOCATE_USE;
564 }
565 else {
566 retVal = RM_ERROR_INVALID_SERVICE_TYPE;
567 goto errorExit;
568 }
569 retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
571 if (retVal == RM_SERVICE_PROCESSING) {
572 if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
573 opInfo.operation = Rm_allocatorOp_ALLOCATE_INIT;
574 }
575 else if (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) {
576 opInfo.operation = Rm_allocatorOp_ALLOCATE_USE;
577 }
578 else {
579 retVal = RM_ERROR_INVALID_SERVICE_TYPE;
580 goto errorExit;
581 }
582 retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
584 if (retVal == RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST) {
585 /* Request resource range was not found within local resources
586 * provided by Server. Set back to PROCESSING so request is forwarded to
587 * Server */
588 retVal = RM_SERVICE_PROCESSING;
589 }
590 }
591 else if (retVal == RM_SERVICE_DENIED_RES_ALLOC_REQS_NOT_MET) {
592 if (transaction->pendingTransactionId) {
593 /* Request to Server for resources to complete transaction locally
594 * performed once already. Forward transaction to Server for completion */
595 retVal = RM_SERVICE_PROCESSING;
596 }
597 else {
598 /* Restore base and alignment since they were replaced in pre-allocate routine */
599 transaction->resourceInfo.base = RM_RESOURCE_BASE_UNSPECIFIED;
600 transaction->resourceInfo.alignment = oldAlign;
602 retVal = cdRequestServerResources(rmInst, transaction);
603 }
604 }
605 }
606 else {
607 retVal = cdRequestServerResources(rmInst, transaction);
608 }
609 }
610 }
611 else if ((rmInst->instType == Rm_instType_SERVER)||
612 (rmInst->instType == Rm_instType_SHARED_SERVER)) {
613 /* Populated NameServer name has precedence over base */
614 if (strlen(transaction->resourceInfo.nameServerName) > 0) {
615 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
616 rmNameServerTreeInv(rmInst->u.server.nameServer);
617 }
618 memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
619 nameServerObjCfg.nameServerTree = rmInst->u.server.nameServer;
620 nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
621 if ((retVal = rmNameServerFindObject(&nameServerObjCfg)) == RM_SERVICE_PROCESSING) {
622 rm_strncpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName, RM_NAME_MAX_CHARS);
623 transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;
624 transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;
625 }
626 else {
627 goto errorExit;
628 }
629 }
631 if (transaction->resourceInfo.base == RM_RESOURCE_BASE_UNSPECIFIED) {
632 if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
633 opInfo.operation = Rm_allocatorOp_PRE_ALLOCATE_INIT;
634 }
635 else if (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) {
636 opInfo.operation = Rm_allocatorOp_PRE_ALLOCATE_USE;
637 }
638 else {
639 retVal = RM_ERROR_INVALID_SERVICE_TYPE;
640 goto errorExit;
641 }
642 retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
643 }
645 if (retVal == RM_SERVICE_PROCESSING) {
646 if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
647 opInfo.operation = Rm_allocatorOp_ALLOCATE_INIT;
648 }
649 else if (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) {
650 opInfo.operation = Rm_allocatorOp_ALLOCATE_USE;
651 }
652 else {
653 retVal = RM_ERROR_INVALID_SERVICE_TYPE;
654 goto errorExit;
655 }
656 retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
657 }
658 }
659 errorExit:
660 transaction->state = retVal;
661 }
663 /* FUNCTION PURPOSE: Handles resource status service requests
664 ***********************************************************************
665 * DESCRIPTION: Issues a set of allocator operations to retrieve the
666 * current status (currently just owner reference count)
667 * for the resource specified in the transaction
668 */
669 static void statusHandler (Rm_Inst *rmInst, Rm_Transaction *transaction)
670 {
671 Rm_AllocatorOpInfo opInfo;
672 Rm_NameServerObjCfg nameServerObjCfg;
673 int32_t retVal = transaction->state;
675 memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));
676 opInfo.operation = Rm_allocatorOp_GET_STATUS;
677 opInfo.policy = rmPolicyGetPolicy((Rm_Handle)rmInst);
678 opInfo.resourceInfo = &transaction->resourceInfo;
679 opInfo.serviceSrcInstNode = rmPolicyGetValidInstNode((Rm_Handle)rmInst, transaction->serviceSrcInstName);
680 if (opInfo.serviceSrcInstNode == NULL) {
681 retVal = RM_SERVICE_DENIED_INST_NAME_NOT_VALID;
682 goto errorExit;
683 }
685 if ((strlen(transaction->resourceInfo.nameServerName) == 0) &&
686 ((transaction->resourceInfo.base == RM_RESOURCE_BASE_UNSPECIFIED) ||
687 (transaction->resourceInfo.length == 0))) {
688 retVal = RM_SERVICE_DENIED_RES_DOES_NOT_EXIST;
689 goto errorExit;
690 }
692 if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
693 if (rmAllocatorFind((Rm_Handle)rmInst, transaction->resourceInfo.name)) {
694 /* Attempt to get status from local resources that were provided by Server */
695 retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
697 if (retVal == RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST) {
698 /* Request resource range was not found within local allocator resources
699 * provided by Server. Set back to PROCESSING so request is forwarded to
700 * Server */
701 retVal = RM_SERVICE_PROCESSING;
702 }
703 }
704 }
705 else if ((rmInst->instType == Rm_instType_SERVER)||
706 (rmInst->instType == Rm_instType_SHARED_SERVER)) {
707 /* Populated NameServer name has precedence over base and length values */
708 if (strlen(transaction->resourceInfo.nameServerName) > 0) {
709 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
710 rmNameServerTreeInv(rmInst->u.server.nameServer);
711 }
712 memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
713 nameServerObjCfg.nameServerTree = rmInst->u.server.nameServer;
714 nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
715 if ((retVal = rmNameServerFindObject(&nameServerObjCfg)) == RM_SERVICE_PROCESSING) {
716 rm_strncpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName, RM_NAME_MAX_CHARS);
717 transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;
718 transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;
719 }
720 else {
721 goto errorExit;
722 }
723 }
724 retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
725 }
726 errorExit:
727 transaction->state = retVal;
728 }
730 /* FUNCTION PURPOSE: Arbitrates free service requests
731 ***********************************************************************
732 * DESCRIPTION: Issues a set of allocator operations in order to
733 * handle a received free request. Free
734 * requests are always forwarded to the Server on Client
735 * CD instances. If a request is made with a NameServer
736 * name the resource base and length parameters are
737 * retrieved from the NameServer prior to the free
738 * attempt.
739 */
740 static void freeHandler (Rm_Inst *rmInst, Rm_Transaction *transaction)
741 {
742 Rm_AllocatorOpInfo opInfo;
743 Rm_NameServerObjCfg nameServerObjCfg;
744 int32_t retVal = transaction->state;
746 memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));
747 opInfo.operation = Rm_allocatorOp_FREE;
748 opInfo.policy = rmPolicyGetPolicy((Rm_Handle)rmInst);
749 opInfo.resourceInfo = &transaction->resourceInfo;
750 opInfo.serviceSrcInstNode = rmPolicyGetValidInstNode((Rm_Handle)rmInst, transaction->serviceSrcInstName);
751 if (opInfo.serviceSrcInstNode == NULL) {
752 retVal = RM_SERVICE_DENIED_INST_NAME_NOT_VALID;
753 goto errorExit;
754 }
756 if ((strlen(transaction->resourceInfo.nameServerName) == 0) &&
757 ((transaction->resourceInfo.base == RM_RESOURCE_BASE_UNSPECIFIED) ||
758 (transaction->resourceInfo.length == 0))) {
759 retVal = RM_SERVICE_DENIED_RES_DOES_NOT_EXIST;
760 goto errorExit;
761 }
763 if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
764 if (rmAllocatorFind((Rm_Handle)rmInst, transaction->resourceInfo.name)) {
765 /* Attempt to free from local resources that were provided by Server */
766 retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
768 if (retVal == RM_SERVICE_APPROVED) {
769 /* Check if free allows local resources to be freed back to Server */
770 retVal = cdFreeResourcesToServer(rmInst, transaction);
771 }
772 else if (retVal == RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST) {
773 /* Request resource range was not found within local allocator resources
774 * provided by Server. Set back to PROCESSING so request is forwarded to
775 * Server */
776 retVal = RM_SERVICE_PROCESSING;
777 }
778 }
779 }
780 else if ((rmInst->instType == Rm_instType_SERVER) ||
781 (rmInst->instType == Rm_instType_SHARED_SERVER)) {
782 /* Populated NameServer name has precedence over base */
783 if (strlen(transaction->resourceInfo.nameServerName) > 0) {
784 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
785 rmNameServerTreeInv(rmInst->u.server.nameServer);
786 }
787 memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
788 nameServerObjCfg.nameServerTree = rmInst->u.server.nameServer;
789 nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
790 if ((retVal = rmNameServerFindObject(&nameServerObjCfg)) == RM_SERVICE_PROCESSING) {
791 rm_strncpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName, RM_NAME_MAX_CHARS);
792 transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;
793 transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;
794 }
795 else {
796 goto errorExit;
797 }
798 }
800 retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
801 }
802 errorExit:
803 transaction->state = retVal;
804 }
806 /* FUNCTION PURPOSE: Client transaction handling process
807 ***********************************************************************
808 * DESCRIPTION: Client process for handling transactions created
809 * from services received via the service handle or the
810 * transport. The Client process:
811 * - Performs static allocations if no transport
812 * to CD or Server has been registered
813 * - Forwards all service requests to CD or Server
814 * once transport has been registered
815 */
816 static void clientProcess (Rm_Inst *rmInst, Rm_Transaction *transaction)
817 {
818 Rm_Transaction *transQ;
820 if (!rmInst->registeredWithDelegateOrServer) {
821 staticAllocationHandler((Rm_Handle)rmInst, transaction);
822 }
823 else {
824 if (transaction->state == RM_SERVICE_PROCESSING) {
825 /* Forward all new transactions to CD or Server */
826 transactionForwarder(rmInst, transaction);
827 }
828 else {
829 /* Transaction validated. Return result. */
830 serviceResponder(rmInst, transaction);
831 }
833 /* Forward any queued static requests that weren't forwarded */
834 transQ = rmInst->transactionQueue;
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;
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 rm_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 rm_strncpy(newTrans->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS);
966 newTrans->state = RM_SERVICE_PROCESSING;
967 rm_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 transQ = rmInst->transactionQueue;
1018 while(transQ) {
1019 if (((transQ->state == RM_SERVICE_PROCESSING) ||
1020 (transQ->state == RM_SERVICE_APPROVED_STATIC)) &&
1021 (!transQ->hasBeenForwarded)) {
1022 transactionForwarder(rmInst, transQ);
1023 }
1024 transQ = transQ->nextTransaction;
1025 }
1026 }
1027 }
1029 /* FUNCTION PURPOSE: Server transaction handling process
1030 ***********************************************************************
1031 * DESCRIPTION: Server process for handling transactions created
1032 * from services received via the service handle or the
1033 * transport. The Server process:
1034 * - Validates all service requests received from
1035 * the service handle and registered CDs and
1036 * Clients
1037 */
1038 static void serverProcess (Rm_Inst *rmInst, Rm_Transaction *transaction)
1039 {
1040 Rm_NameServerObjCfg nameServerObjCfg;
1042 switch (transaction->type) {
1043 case Rm_service_RESOURCE_STATUS:
1044 statusHandler(rmInst, transaction);
1045 break;
1046 case Rm_service_RESOURCE_ALLOCATE_INIT:
1047 case Rm_service_RESOURCE_ALLOCATE_USE:
1048 allocationHandler(rmInst, transaction);
1049 break;
1050 case Rm_service_RESOURCE_FREE:
1051 freeHandler(rmInst, transaction);
1052 break;
1053 case Rm_service_RESOURCE_MAP_TO_NAME:
1054 case Rm_service_RESOURCE_GET_BY_NAME:
1055 case Rm_service_RESOURCE_UNMAP_NAME:
1056 if (rmInst->u.server.nameServer) {
1057 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1058 rmNameServerTreeInv(rmInst->u.server.nameServer);
1059 }
1060 memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
1061 nameServerObjCfg.nameServerTree = rmInst->u.server.nameServer;
1062 nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
1063 if (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) {
1064 nameServerObjCfg.nodeCfg.resourceName = transaction->resourceInfo.name;
1065 nameServerObjCfg.nodeCfg.resourceBase= transaction->resourceInfo.base;
1066 nameServerObjCfg.nodeCfg.resourceLength = transaction->resourceInfo.length;
1067 transaction->state = rmNameServerAddObject(&nameServerObjCfg);
1068 }
1069 else if (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) {
1070 if ((transaction->state = rmNameServerFindObject(&nameServerObjCfg)) ==
1071 RM_SERVICE_PROCESSING) {
1072 rm_strncpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName, RM_NAME_MAX_CHARS);
1073 transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;
1074 transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;
1075 transaction->state = RM_SERVICE_APPROVED;
1076 }
1077 }
1078 else if (transaction->type == Rm_service_RESOURCE_UNMAP_NAME) {
1079 transaction->state = rmNameServerDeleteObject(&nameServerObjCfg);
1080 }
1082 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1083 rmNameServerTreeWb(rmInst->u.server.nameServer);
1084 }
1085 }
1086 else {
1087 transaction->state = RM_ERROR_NAMESERVER_DOES_NOT_EXIST;
1088 }
1089 break;
1090 }
1092 /* Source of shared server transaction will always be local. */
1093 if (rmInst->instType != Rm_instType_SHARED_SERVER) {
1094 if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {
1095 /* Source of transaction was not Server, return transaction via responder */
1096 transactionResponder(rmInst, transaction);
1097 }
1098 }
1099 /* Otherwise let call stack return transaction result app via Rm_serviceHandler */
1100 }
1102 /**********************************************************************
1103 ********************** Internal Functions ****************************
1104 **********************************************************************/
1106 /* FUNCTION PURPOSE: Adds a transaction
1107 ***********************************************************************
1108 * DESCRIPTION: Returns a pointer to a newly created transaction.
1109 * The transaction is created based on a new service
1110 * request received via the service API or the
1111 * transport API (service forwarded from another instance)
1112 */
1113 Rm_Transaction *rmTransactionQueueAdd(Rm_Inst *rmInst)
1114 {
1115 Rm_Transaction *transactionQueue = rmInst->transactionQueue;
1116 Rm_Transaction *newTransaction = NULL;
1118 newTransaction = Rm_osalMalloc(sizeof(Rm_Transaction));
1119 if (newTransaction) {
1120 memset((void *)newTransaction, 0, sizeof(Rm_Transaction));
1122 newTransaction->localId = transactionGetSequenceNum(rmInst);
1123 newTransaction->nextTransaction = NULL;
1124 if (transactionQueue) {
1125 while (transactionQueue->nextTransaction) {
1126 transactionQueue = transactionQueue->nextTransaction;
1127 }
1128 transactionQueue->nextTransaction = newTransaction;
1129 }
1130 else {
1131 rmInst->transactionQueue = newTransaction;
1132 }
1133 }
1134 return (newTransaction);
1135 }
1137 /* FUNCTION PURPOSE: Finds a transaction
1138 ***********************************************************************
1139 * DESCRIPTION: Returns a pointer to a transaction resident
1140 * in the transaction queue that matches the provided
1141 * transaction ID.
1142 */
1143 Rm_Transaction *rmTransactionQueueFind(Rm_Inst *rmInst, uint32_t transactionId)
1144 {
1145 Rm_Transaction *transaction = rmInst->transactionQueue;
1147 while (transaction) {
1148 if (transaction->localId == transactionId) {
1149 break;
1150 }
1151 transaction = transaction->nextTransaction;
1152 }
1154 return (transaction);
1155 }
1157 /* FUNCTION PURPOSE: Deletes a transaction
1158 ***********************************************************************
1159 * DESCRIPTION: Deletes the transaction with the provided transaction
1160 * ID from the instance's transaction queue.
1161 */
1162 int32_t rmTransactionQueueDelete(Rm_Inst *rmInst, uint32_t transactionId)
1163 {
1164 Rm_Transaction *transaction = rmInst->transactionQueue;
1165 Rm_Transaction *prevTransaction = NULL;
1166 int32_t retVal = RM_OK;
1168 while (transaction) {
1169 if (transaction->localId == transactionId) {
1170 break;
1171 }
1173 prevTransaction = transaction;
1174 transaction = transaction->nextTransaction;
1175 }
1177 if (transaction) {
1178 if (prevTransaction == NULL) {
1179 /* Transaction at start of queue. Map second transaction to start of queue
1180 * as long as more than one transactions. */
1181 rmInst->transactionQueue = transaction->nextTransaction;
1182 }
1183 else {
1184 /* Transaction in middle or end of queue. */
1185 prevTransaction->nextTransaction = transaction->nextTransaction;
1186 }
1187 Rm_osalFree((void *)transaction, sizeof(Rm_Transaction));
1188 }
1189 else {
1190 retVal = RM_ERROR_SERVICE_TRANS_DOES_NOT_EXIST;
1191 }
1192 return (retVal);
1193 }
1195 /* FUNCTION PURPOSE: Routes a transaction for processing
1196 ***********************************************************************
1197 * DESCRIPTION: Routes a received transaction to the appropriate
1198 * instance processing routine
1199 */
1200 void rmProcessRouter (Rm_Inst *rmInst, Rm_Transaction *transaction)
1201 {
1202 if (rmInst->instType == Rm_instType_CLIENT) {
1203 clientProcess(rmInst, transaction);
1204 }
1205 else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1206 cdProcess(rmInst, transaction);
1207 }
1208 else if ((rmInst->instType == Rm_instType_SERVER) ||
1209 (rmInst->instType == Rm_instType_SHARED_SERVER)) {
1210 serverProcess(rmInst, transaction);
1211 }
1212 }
1214 /**********************************************************************
1215 ********************** Application visible APIs **********************
1216 **********************************************************************/
1218 /* FUNCTION PURPOSE: Display status of managed resources
1219 ***********************************************************************
1220 * DESCRIPTION: Prints the status (allocate/free status, as well as
1221 * owners) for all resources managed by the RM
1222 * instance network. Also, prints the NameServer name
1223 * entries. The number of resource range owners is
1224 * returned as well. This function is only available on
1225 * Server and CD instances.
1226 */
1227 int32_t Rm_resourceStatus(Rm_Handle rmHandle, int printResources)
1228 {
1229 Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
1230 Rm_Allocator *allocator = NULL;
1231 Rm_Owner *owners;
1232 Rm_ResourceTree *treeRoot;
1233 Rm_ResourceNode *treeNode;
1234 int32_t totalResOwners = 0;
1235 void *key;
1237 RM_SS_INST_INV_ENTER_CS(key);
1238 RM_SC_INST_INV_ENTER_CS(key);
1240 if (rmInst->instType != Rm_instType_CLIENT) {
1241 Rm_osalLog("Instance name: %s\n", rmInst->instName);
1242 Rm_osalLog("Handle: 0x%08x\n", rmHandle);
1243 if (rmInst->instType == Rm_instType_SERVER) {
1244 Rm_osalLog("Type: Server\n");
1245 }
1246 else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1247 Rm_osalLog("Type: Client Delegate\n");
1248 }
1249 else if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1250 Rm_osalLog("Type: Shared Server\n");
1251 }
1252 else if (rmInst->instType == Rm_instType_SHARED_CLIENT) {
1253 Rm_osalLog("Type: Shared Client\n");
1254 }
1256 Rm_osalLog("\nResource Status:\n\n");
1257 }
1259 if (rmInst->instType == Rm_instType_SHARED_CLIENT) {
1260 /* Transfer control to shared server instance */
1261 rmInst = rmInst->u.sharedClient.sharedServerHandle;
1262 }
1264 if ((rmInst->instType == Rm_instType_SERVER) ||
1265 (rmInst->instType == Rm_instType_SHARED_SERVER) ||
1266 (rmInst->instType == Rm_instType_CLIENT_DELEGATE)) {
1267 allocator = rmAllocatorGetAllocatorList((Rm_Handle)rmInst);
1269 if (!allocator) {
1270 Rm_osalLog("No resources managed by instance at the moment\n\n");
1271 }
1273 while (allocator) {
1274 RM_SS_OBJ_INV(allocator, Rm_Allocator);
1275 if (printResources) {
1276 Rm_osalLog("Resource: %s\n", allocator->resourceName);
1277 }
1279 treeRoot = allocator->allocatorRootEntry;
1280 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1281 rmResourceTreeInv(treeRoot);
1282 }
1283 RB_FOREACH(treeNode, _Rm_AllocatorResourceTree, treeRoot) {
1284 if (printResources) {
1285 if ((treeNode->base >= 65536) ||
1286 ((treeNode->base + treeNode->length - 1) >= 65536)) {
1287 /* Print in hex if number is very large */
1288 Rm_osalLog(" 0x%08x - 0x%08x ", treeNode->base,
1289 treeNode->base + treeNode->length - 1);
1290 }
1291 else {
1292 Rm_osalLog(" %10d - %10d ", treeNode->base,
1293 treeNode->base + treeNode->length - 1);
1294 }
1295 }
1297 if (treeNode->allocationCount == 0) {
1298 if (printResources) {
1299 Rm_osalLog("FREE\n");
1300 }
1301 }
1302 else {
1303 owners = treeNode->ownerList;
1304 while (owners) {
1305 RM_SS_OBJ_INV(owners, Rm_Owner);
1306 if (printResources) {
1307 Rm_osalLog("%s (%d) ", owners->instNameNode->name, owners->refCnt);
1308 }
1309 totalResOwners++;
1310 owners = owners->nextOwner;
1311 }
1312 if (printResources) {
1313 Rm_osalLog("\n");
1314 }
1315 }
1316 }
1317 allocator = allocator->nextAllocator;
1318 }
1320 if ((rmInst->instType == Rm_instType_SERVER) ||
1321 (rmInst->instType == Rm_instType_SHARED_SERVER)) {
1322 if (printResources) {
1323 rmNameServerPrintObjects((Rm_Handle)rmInst);
1324 }
1325 }
1326 }
1327 else {
1328 totalResOwners = RM_ERROR_INVALID_RES_STATUS_INSTANCE;
1329 }
1331 RM_SS_INST_WB_EXIT_CS(key);
1332 return(totalResOwners);
1333 }
1335 /* FUNCTION PURPOSE: Display status of a RM instance
1336 ***********************************************************************
1337 * DESCRIPTION: Prints the current status of various RM instance
1338 * properties such as the state of all transactions
1339 * in the transaction queue and registered transports
1340 */
1341 void Rm_instanceStatus(Rm_Handle rmHandle)
1342 {
1343 Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
1344 Rm_Transport *transportList = NULL;
1345 Rm_Transaction *transactionQ = NULL;
1346 void *key;
1348 RM_SS_INST_INV_ENTER_CS(key);
1349 RM_SC_INST_INV_ENTER_CS(key);
1351 Rm_osalLog("Instance name: %s\n", rmInst->instName);
1352 Rm_osalLog("Handle: 0x%08x\n", rmHandle);
1353 if (rmInst->instType == Rm_instType_SERVER) {
1354 Rm_osalLog("Type: Server\n");
1355 }
1356 else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1357 Rm_osalLog("Type: Client Delegate\n");
1358 }
1359 else if (rmInst->instType == Rm_instType_CLIENT) {
1360 Rm_osalLog("Type: Client\n");
1361 }
1362 else if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1363 Rm_osalLog("Type: Shared Server\n");
1364 }
1365 else if (rmInst->instType == Rm_instType_SHARED_CLIENT) {
1366 Rm_osalLog("Type: Shared Client\n");
1368 Rm_osalLog("\nShared Server Properties:\n");
1369 /* Transfer to Shared Server instance to print out transport and
1370 * transaction status */
1371 rmInst = rmInst->u.sharedClient.sharedServerHandle;
1372 Rm_osalLog("Instance name: %s\n", rmInst->instName);
1373 Rm_osalLog("Handle: 0x%08x\n", rmHandle);
1374 }
1376 transportList = rmInst->transports;
1377 if (transportList) {
1378 Rm_osalLog("\nRegistered Transports:\n");
1379 while (transportList) {
1380 RM_SS_OBJ_INV(transportList, Rm_Transport);
1381 if (transportList->remoteInstType == Rm_instType_SERVER) {
1382 Rm_osalLog(" Remote instType: Server\n");
1383 }
1384 else if (transportList->remoteInstType == Rm_instType_CLIENT_DELEGATE) {
1385 Rm_osalLog(" Remote instType: Client Delegate\n");
1386 }
1387 else {
1388 Rm_osalLog(" Remote instType: Client\n");
1389 }
1390 Rm_osalLog(" appTransportHandle: 0x%08x\n", transportList->appTransportHandle);
1391 Rm_osalLog("\n");
1392 transportList = transportList->nextTransport;
1393 }
1394 }
1396 transactionQ = rmInst->transactionQueue;
1397 if (transactionQ) {
1398 Rm_osalLog("\nQueued Service Transactions:\n");
1399 while (transactionQ) {
1400 RM_SS_OBJ_INV(transactionQ, Rm_Transaction);
1401 Rm_osalLog(" Service type: %d\n", transactionQ->type);
1402 Rm_osalLog(" Service ID: %d\n", transactionQ->localId);
1403 Rm_osalLog(" Service srcInstName %s\n", transactionQ->serviceSrcInstName);
1404 Rm_osalLog(" Service state: %d\n", transactionQ->state);
1405 Rm_osalLog(" Resource name: %s\n", transactionQ->resourceInfo.name);
1406 Rm_osalLog(" Resource base: %d\n", transactionQ->resourceInfo.base);
1407 Rm_osalLog(" Resource length: %d\n", transactionQ->resourceInfo.length);
1408 Rm_osalLog(" Resource alignment: %d\n", transactionQ->resourceInfo.alignment);
1409 Rm_osalLog(" Resource NS name: %s\n", transactionQ->resourceInfo.nameServerName);
1410 Rm_osalLog("\n");
1411 transactionQ = transactionQ->nextTransaction;
1412 }
1413 }
1414 RM_SS_INST_WB_EXIT_CS(key);
1415 }
1417 /* FUNCTION PURPOSE: RM instance creation and initialization
1418 ***********************************************************************
1419 * DESCRIPTION: Returns a new RM instance created and initialized
1420 * using the parameters provided via the initCfg
1421 * structure.
1422 */
1423 Rm_Handle Rm_init(const Rm_InitCfg *initCfg, int32_t *result)
1424 {
1425 Rm_Inst *rmInst = NULL;
1426 Rm_Inst *sharedServerInst = NULL;
1427 uint32_t policySize;
1428 void *globalResourceDtb = NULL;
1429 void *linuxResourceDtb = NULL;
1430 int addLinux = RM_FALSE;
1431 void *key;
1433 *result = RM_OK;
1435 if ((initCfg->instName == NULL) ||
1436 ((strlen(initCfg->instName) + 1) > RM_NAME_MAX_CHARS)) {
1437 *result = RM_ERROR_INVALID_INST_NAME;
1438 goto errorExit;
1439 }
1441 if (initCfg->instType >= Rm_instType_LAST) {
1442 *result = RM_ERROR_INVALID_INST_TYPE;
1443 goto errorExit;
1444 }
1446 /* Create and initialize instance */
1447 rmInst = Rm_osalMalloc(sizeof(*rmInst));
1448 memset ((void *)rmInst, 0, sizeof(*rmInst));
1449 rmInst->isLocked = RM_FALSE;
1450 rmInst->registeredWithDelegateOrServer = RM_FALSE;
1451 rmInst->transactionSeqNum = transactionInitSequenceNum();
1453 rmInst->instType = initCfg->instType;
1454 rm_strncpy (rmInst->instName, initCfg->instName, RM_NAME_MAX_CHARS);
1456 if ((rmInst->instType == Rm_instType_SERVER) ||
1457 (rmInst->instType == Rm_instType_SHARED_SERVER)) {
1458 if (!initCfg->instCfg.serverCfg.globalResourceList ||
1459 !initCfg->instCfg.serverCfg.globalPolicy) {
1460 *result = RM_ERROR_INVALID_SERVER_CONFIGURATION;
1461 goto errorExit;
1462 }
1464 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1465 /* Shared Server makes copy of policy in shared memory for Shared Clients
1466 * on other cores */
1467 policySize = fdt_totalsize(initCfg->instCfg.serverCfg.globalPolicy);
1468 /* Align policy size to cache boundary */
1469 if (policySize % RM_MAX_CACHE_ALIGN) {
1470 policySize += (RM_MAX_CACHE_ALIGN - (policySize % RM_MAX_CACHE_ALIGN));
1471 }
1472 rmInst->u.server.policySize = policySize;
1473 rmInst->u.server.globalPolicy = Rm_osalMalloc(rmInst->u.server.policySize);
1474 memcpy(rmInst->u.server.globalPolicy, initCfg->instCfg.serverCfg.globalPolicy, rmInst->u.server.policySize);
1475 }
1476 else {
1477 rmInst->u.server.globalPolicy = initCfg->instCfg.serverCfg.globalPolicy;
1478 }
1480 if (initCfg->instCfg.serverCfg.linuxDtb) {
1481 linuxResourceDtb = initCfg->instCfg.serverCfg.linuxDtb;
1482 addLinux = RM_TRUE;
1483 }
1485 /* Create valid instance list from policy. Must be done prior to parsing
1486 * GRL so that Linux resources can be reserved correctly */
1487 rmInst->u.server.globalValidInstTree = rmPolicyCreateValidInstTree((Rm_Handle)rmInst, addLinux, result);
1488 if (*result == RM_OK) {
1489 *result = rmPolicyValidatePolicy((Rm_Handle)rmInst);
1490 }
1492 if (*result != RM_OK) {
1493 if (rmInst->u.server.globalValidInstTree) {
1494 rmPolicyFreeValidInstTree((Rm_Handle)rmInst);
1495 }
1496 goto errorExit;
1497 }
1498 else {
1499 rmNameServerInit((Rm_Handle)rmInst);
1501 globalResourceDtb = initCfg->instCfg.serverCfg.globalResourceList;
1503 if ((*result = rmAllocatorInitializeResources((Rm_Handle) rmInst, globalResourceDtb, linuxResourceDtb)) == RM_OK) {
1504 *result = rmPolicyValidatePolicyResourceNames((Rm_Handle)rmInst);
1505 }
1507 if (*result != RM_OK) {
1508 rmAllocatorDeleteResources((Rm_Handle)rmInst);
1509 rmNameServerDelete((Rm_Handle)rmInst);
1510 goto errorExit;
1511 }
1512 }
1513 }
1514 else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1515 if (!initCfg->instCfg.cdCfg.cdPolicy) {
1516 *result = RM_ERROR_INVALID_CD_CONFIGURATION;
1517 goto errorExit;
1518 }
1520 rmInst->u.cd.cdPolicy = initCfg->instCfg.cdCfg.cdPolicy;
1521 rmInst->u.cd.cdValidInstTree = rmPolicyCreateValidInstTree((Rm_Handle)rmInst, addLinux, result);
1522 if (*result == RM_OK) {
1523 *result = rmPolicyValidatePolicy((Rm_Handle)rmInst);
1524 }
1526 if (*result != RM_OK) {
1527 if (rmInst->u.cd.cdValidInstTree) {
1528 rmPolicyFreeValidInstTree((Rm_Handle)rmInst);
1529 }
1530 goto errorExit;
1531 }
1533 rmInst->u.cd.allocators = NULL;
1535 /* Remove once CD instance is stable - tracked by SDOCM00100797 */
1536 *result = RM_WARNING_CD_INSTANCE_NOT_STABLE;
1537 }
1538 else if (rmInst->instType == Rm_instType_CLIENT) {
1539 if (initCfg->instCfg.clientCfg.staticPolicy) {
1540 rmInst->u.client.staticPolicy = initCfg->instCfg.clientCfg.staticPolicy;
1541 rmInst->u.client.staticValidInstTree = rmPolicyCreateValidInstTree((Rm_Handle)rmInst, addLinux, result);
1542 if (*result == RM_OK) {
1543 *result = rmPolicyValidatePolicy((Rm_Handle)rmInst);
1544 }
1546 if (*result != RM_OK) {
1547 if (rmInst->u.client.staticValidInstTree) {
1548 rmPolicyFreeValidInstTree((Rm_Handle)rmInst);
1549 }
1550 goto errorExit;
1551 }
1552 }
1553 }
1554 else if (rmInst->instType == Rm_instType_SHARED_CLIENT) {
1555 if (initCfg->instCfg.sharedClientCfg.sharedServerHandle) {
1556 rmInst->u.sharedClient.sharedServerHandle = initCfg->instCfg.sharedClientCfg.sharedServerHandle;
1557 /* Invalidate the Shared server instance structure on this core to get the latest
1558 * instance data. */
1559 key = Rm_osalCsEnter();
1560 Rm_osalBeginMemAccess((void *)rmInst->u.sharedClient.sharedServerHandle, sizeof(Rm_Inst));
1561 sharedServerInst = rmInst->u.sharedClient.sharedServerHandle;
1562 if (sharedServerInst->instType != Rm_instType_SHARED_SERVER) {
1563 *result = RM_ERROR_INVALID_SHARED_SERVER_HANDLE;
1564 Rm_osalCsExit(key);
1565 goto errorExit;
1566 }
1567 else {
1568 /* Invalidate the policy */
1569 Rm_osalBeginMemAccess((void *)sharedServerInst->u.server.globalPolicy,
1570 sharedServerInst->u.server.policySize);
1571 }
1572 Rm_osalCsExit(key);
1573 }
1574 else {
1575 *result = RM_ERROR_INVALID_SHARED_SERVER_HANDLE;
1576 goto errorExit;
1577 }
1578 }
1580 if (initCfg->instType == Rm_instType_SHARED_SERVER) {
1581 /* Writeback the instance and policy for other cores */
1582 Rm_osalEndMemAccess ((void *)rmInst, sizeof(Rm_Inst));
1583 Rm_osalEndMemAccess ((void *)rmInst->u.server.globalPolicy, rmInst->u.server.policySize);
1584 }
1585 else if (rmInst->instType != Rm_instType_SHARED_CLIENT) {
1586 /* Create the instance's task blocking mechanism */
1587 rmInst->blockHandle = Rm_osalTaskBlockCreate();
1588 }
1590 return ((Rm_Handle) rmInst);
1591 errorExit:
1592 if (rmInst) {
1593 Rm_osalFree((void *)rmInst, sizeof(Rm_Inst));
1594 }
1595 return (NULL);
1596 }
1598 /* FUNCTION PURPOSE: Deletes an RM instance
1599 ***********************************************************************
1600 * DESCRIPTION: Frees all memory associated with an RM instance
1601 * as long as all transports have been unregistered
1602 * and the service handle has been closed
1603 */
1604 int32_t Rm_delete(Rm_Handle rmHandle, int ignorePendingServices)
1605 {
1606 Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
1607 void *key;
1609 key = Rm_osalCsEnter();
1610 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1611 Rm_osalBeginMemAccess((void *)rmInst, sizeof(Rm_Inst));
1612 }
1614 if (rmInst->serviceHandle) {
1615 return (RM_ERROR_CANT_DELETE_WITH_OPEN_SERV_HNDL);
1616 }
1617 else if (rmInst->transports) {
1618 return (RM_ERROR_CANT_DELETE_WITH_REGD_TRANSPORT);
1619 }
1620 else if (rmInst->transactionQueue && !ignorePendingServices) {
1621 return (RM_ERROR_CANT_DELETE_PENDING_TRANSACTIONS);
1622 }
1624 if ((rmInst->instType == Rm_instType_SERVER) ||
1625 (rmInst->instType == Rm_instType_SHARED_SERVER)) {
1626 rmAllocatorDeleteResources(rmHandle);
1627 rmNameServerDelete(rmHandle);
1628 rmInst->u.server.allocators = NULL;
1630 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1631 Rm_osalFree((void *)rmInst->u.server.globalPolicy, rmInst->u.server.policySize);
1632 }
1633 }
1634 else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1635 rmAllocatorDeleteResources(rmHandle);
1636 rmInst->u.cd.allocators = NULL;
1637 }
1639 if (rmInst->instType != Rm_instType_SHARED_CLIENT) {
1640 /* Delete valid instance tree */
1641 rmPolicyFreeValidInstTree(rmHandle);
1643 /* Delete any transactions */
1644 while(rmInst->transactionQueue) {
1645 rmTransactionQueueDelete(rmInst, rmInst->transactionQueue->localId);
1646 }
1648 if (rmInst->instType != Rm_instType_SHARED_SERVER) {
1649 /* Delete the instance's task blocking mechanism */
1650 Rm_osalTaskBlockDelete(rmInst->blockHandle);
1651 }
1652 else {
1653 Rm_osalEndMemAccess((void *)rmInst, sizeof(Rm_Inst));
1654 }
1655 }
1657 Rm_osalFree((void *)rmInst, sizeof(Rm_Inst));
1659 Rm_osalCsExit(key);
1660 return (RM_OK);
1661 }
1663 /* FUNCTION PURPOSE: Returns RM version information
1664 ***********************************************************************
1665 */
1666 uint32_t Rm_getVersion(void)
1667 {
1668 return RM_VERSION_ID;
1669 }
1671 /* FUNCTION PURPOSE: Returns RM version string
1672 ***********************************************************************
1673 */
1674 const char* Rm_getVersionStr(void)
1675 {
1676 return rmVersionStr;
1677 }