f75e5d5f55f76b595ba18c3ce72e487801ad5584
1 /**
2 * @file rm.c
3 *
4 * @brief
5 * This is the Resource Manager source.
6 *
7 * \par
8 * ============================================================================
9 * @n (C) Copyright 2012-2015, Texas Instruments, Inc.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 *
15 * Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 *
18 * Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the
21 * distribution.
22 *
23 * Neither the name of Texas Instruments Incorporated nor the names of
24 * its contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
32 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
33 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 *
39 * \par
40 */
42 /* Standard includes */
43 #include <stdint.h>
45 /* RM external includes */
46 #include <ti/drv/rm/rm.h>
47 #include <ti/drv/rm/rmver.h>
48 #include <ti/drv/rm/rm_services.h>
49 #include <ti/drv/rm/rm_transport.h>
51 /* RM internal includes */
52 #include <ti/drv/rm/include/rm_internal.h>
53 #include <ti/drv/rm/include/rm_loc.h>
54 #include <ti/drv/rm/include/rm_allocatorloc.h>
55 #include <ti/drv/rm/include/rm_transportloc.h>
56 #include <ti/drv/rm/include/rm_nameserverloc.h>
57 #include <ti/drv/rm/include/rm_servicesloc.h>
59 /* RM LIBFDT includes */
60 #include <ti/drv/rm/util/libfdt/libfdt.h>
62 /* RM OSAL layer */
63 #include <rm_osal.h>
65 /**********************************************************************
66 ************************** Globals ***********************************
67 **********************************************************************/
69 /* Global Variable which describes the RM Version Information */
70 const char rmVersionStr[] = RM_VERSION_STR ":" __DATE__ ":" __TIME__;
72 /**********************************************************************
73 ************************ Local Functions *****************************
74 **********************************************************************/
76 /* FUNCTION PURPOSE: Initializes a RM inst's transaction sequence number
77 ***********************************************************************
78 * DESCRIPTION: The RM instance transaction sequence number can never
79 * have a value of 0 to avoid conflicts with transactions
80 * that have a remoteOriginatingId of 0 (transaction ID
81 * will be used as the remoteOriginatingId for
82 * transactions that are responses to requests).
83 */
84 static uint32_t transactionInitSequenceNum(void)
85 {
86 return (1);
87 }
89 /* FUNCTION PURPOSE: Provides a sequence number for new transactions
90 ***********************************************************************
91 * DESCRIPTION: Returns a sequence number for a new transaction
92 * specific to a RM instance. Handles rollover of
93 * sequence number.
94 */
95 static uint32_t transactionGetSequenceNum(Rm_Inst *rmInst)
96 {
97 rmInst->transactionSeqNum++;
98 if (!rmInst->transactionSeqNum) {
99 rmInst->transactionSeqNum++;
100 }
101 return (rmInst->transactionSeqNum);
102 }
104 /* FUNCTION PURPOSE: Creates a resource request packet
105 ***********************************************************************
106 * DESCRIPTION: Returns a RM packet handle that points to a RM
107 * resource request packet that has been prepared
108 * for sending to another RM instance. The packet
109 * is allocated via the rmAllocPkt API using the
110 * appTransport handle provided by the application
111 */
112 void createResourceReqPkt(Rm_Packet *rmPkt, char *localInstName, Rm_Transaction *transaction)
113 {
114 Rm_ResourceRequestPkt *resourceReqPkt = NULL;
116 rmPkt->pktType = Rm_pktType_RESOURCE_REQUEST;
117 resourceReqPkt = (Rm_ResourceRequestPkt *) rmPkt->data;
118 resourceReqPkt->requestId = transaction->localId;
119 if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
120 resourceReqPkt->resourceReqType = Rm_resReqPktType_ALLOCATE_INIT;
121 }
122 else if (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) {
123 resourceReqPkt->resourceReqType = Rm_resReqPktType_ALLOCATE_USE;
124 }
125 else if (transaction->type == Rm_service_RESOURCE_STATUS) {
126 resourceReqPkt->resourceReqType = Rm_resReqPktType_GET_STATUS;
127 }
128 else if (transaction->type == Rm_service_RESOURCE_FREE) {
129 resourceReqPkt->resourceReqType = Rm_resReqPktType_FREE;
130 }
131 else if (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) {
132 resourceReqPkt->resourceReqType = Rm_resReqPktType_GET_NAMED;
133 }
134 rm_strncpy(resourceReqPkt->pktSrcInstName, localInstName, RM_NAME_MAX_CHARS);
135 rm_strncpy(resourceReqPkt->serviceSrcInstName, transaction->serviceSrcInstName, RM_NAME_MAX_CHARS);
136 memcpy ((void *)&(resourceReqPkt->resourceInfo), (void *)&(transaction->resourceInfo),
137 sizeof(Rm_ResourceInfo));
138 }
140 /* FUNCTION PURPOSE: Creates a resource response packet
141 ***********************************************************************
142 * DESCRIPTION: Returns a RM packet handle that points to a RM
143 * resource response packet that has been prepared
144 * for sending to another RM instance. The packet
145 * is allocated via the rmAllocPkt API using the
146 * appTransport handle provided by the application
147 */
148 void createResourceResponsePkt(Rm_Packet *rmPkt, Rm_Transaction *transaction)
149 {
150 Rm_ResourceResponsePkt *resourceRespPkt = NULL;
152 rmPkt->pktType = Rm_pktType_RESOURCE_RESPONSE;
153 resourceRespPkt = (Rm_ResourceResponsePkt *)rmPkt->data;
154 resourceRespPkt->responseId = transaction->remoteOriginatingId;
155 resourceRespPkt->requestState = transaction->state;
156 memcpy ((void *)&(resourceRespPkt->resourceInfo), (void *)&(transaction->resourceInfo),
157 sizeof(Rm_ResourceInfo));
158 }
160 /* FUNCTION PURPOSE: Creates a NameServer request packet
161 ***********************************************************************
162 * DESCRIPTION: Returns a RM packet handle that points to a RM
163 * NameServer request packet that has been prepared
164 * for sending to another RM instance. The packet
165 * is allocated via the rmAllocPkt API using the
166 * appTransport handle provided by the application
167 */
168 void createNsRequestPkt(Rm_Packet *rmPkt, char *localInstName, Rm_Transaction *transaction)
169 {
170 Rm_NsRequestPkt *nsReqPkt = NULL;
172 rmPkt->pktType = Rm_pktType_NAMESERVER_REQUEST;
173 nsReqPkt = (Rm_NsRequestPkt *)rmPkt->data;
174 nsReqPkt->requestId = transaction->localId;
175 if (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) {
176 nsReqPkt->nsRequestType = Rm_nsReqPktType_MAP_RESOURCE;
177 }
178 else if (transaction->type == Rm_service_RESOURCE_UNMAP_NAME) {
179 nsReqPkt->nsRequestType = Rm_nsReqPktType_UNMAP_RESOURCE;
180 }
181 rm_strncpy(nsReqPkt->pktSrcInstName, localInstName, RM_NAME_MAX_CHARS);
182 rm_strncpy(nsReqPkt->serviceSrcInstName, transaction->serviceSrcInstName, RM_NAME_MAX_CHARS);
183 memcpy ((void *)&(nsReqPkt->resourceInfo), (void *)&(transaction->resourceInfo),
184 sizeof(Rm_ResourceInfo));
185 }
187 /* FUNCTION PURPOSE: Creates a NameServer response packet
188 ***********************************************************************
189 * DESCRIPTION: Returns a RM packet handle that points to a RM
190 * NameServer response packet that has been prepared
191 * for sending to another RM instance. The packet
192 * is allocated via the rmAllocPkt API using the
193 * appTransport handle provided by the application
194 */
195 void createNsResponsePkt(Rm_Packet *rmPkt, Rm_Transaction *transaction)
196 {
197 Rm_NsResponsePkt *nsRespPkt = NULL;
199 rmPkt->pktType = Rm_pktType_NAMESERVER_RESPONSE;
200 nsRespPkt = (Rm_NsResponsePkt *)rmPkt->data;
201 nsRespPkt->responseId = transaction->remoteOriginatingId;
202 nsRespPkt->requestState = transaction->state;
203 }
205 /* FUNCTION PURPOSE: Issues a service response to application
206 ***********************************************************************
207 * DESCRIPTION: Provides a service response back to the application
208 * using the service callback function provided to
209 * the RM instance at the time of the service request.
210 */
211 static void serviceResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)
212 {
213 Rm_ServiceRespInfo serviceResponse;
215 serviceResponse.rmHandle = (Rm_Handle)rmInst;
216 /* The responseTransaction will contain the resultant state details of
217 * the requestTransaction's service request */
218 serviceResponse.serviceState = transaction->state;
219 /* Pass back the ID that was provided to the component when it requested
220 * the service */
221 serviceResponse.serviceId = transaction->localId;
222 /* Owner and instance allocation count will only be set within RM under certain circumstances. */
223 serviceResponse.resourceNumOwners = transaction->resourceInfo.ownerCount;
224 serviceResponse.instAllocCount = transaction->resourceInfo.instAllocCount;
226 /* Service was approved and service was an allocate request. The resource
227 * data is passed back to the component */
228 if ((serviceResponse.serviceState == RM_SERVICE_APPROVED) &&
229 ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||
230 (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) ||
231 (transaction->type == Rm_service_RESOURCE_FREE) ||
232 (transaction->type == Rm_service_RESOURCE_STATUS) ||
233 (transaction->type == Rm_service_RESOURCE_GET_BY_NAME)))
234 {
235 rm_strncpy(serviceResponse.resourceName, transaction->resourceInfo.name, RM_NAME_MAX_CHARS);
236 serviceResponse.resourceBase = transaction->resourceInfo.base;
237 serviceResponse.resourceLength = transaction->resourceInfo.length;
238 }
240 if (transaction->u.callback.serviceCallback) {
241 /* Issue the callback to the requesting component with the response information */
242 transaction->u.callback.serviceCallback(&serviceResponse);
243 /* Delete the transaction from the transaction queue */
244 rmTransactionQueueDelete(rmInst, transaction->localId);
245 }
246 else {
247 rmServiceInternalCallback((Rm_Handle)rmInst);
248 }
250 return;
251 }
253 /* FUNCTION PURPOSE: Sends RM response packets
254 ***********************************************************************
255 * DESCRIPTION: Sends RM response packets to RM instance's that sent
256 * RM request packets to the RM instance. The response
257 * is sent via the RM transport API which is plugged
258 * with an application created transport path.
259 */
260 static void transactionResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)
261 {
262 Rm_Transport *dstTransport = transaction->u.respTrans;
263 Rm_Packet *rmPkt = NULL;
264 Rm_PacketHandle pktHandle = NULL;
266 rmPkt = dstTransport->callouts.rmAllocPkt(dstTransport->appTransportHandle,
267 sizeof(Rm_Packet), &pktHandle);
268 if (!rmPkt || !pktHandle) {
269 transaction->state = RM_ERROR_TRANSPORT_ALLOC_PKT_ERROR;
270 goto errorExit;
271 }
273 switch (transaction->type) {
274 case Rm_service_RESOURCE_ALLOCATE_INIT:
275 case Rm_service_RESOURCE_ALLOCATE_USE:
276 case Rm_service_RESOURCE_STATUS:
277 case Rm_service_RESOURCE_FREE:
278 case Rm_service_RESOURCE_GET_BY_NAME:
279 createResourceResponsePkt(rmPkt, transaction);
280 break;
281 case Rm_service_RESOURCE_MAP_TO_NAME:
282 case Rm_service_RESOURCE_UNMAP_NAME:
283 createNsResponsePkt(rmPkt, transaction);
284 break;
285 }
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;
1236 void *mtKey;
1238 RM_SS_INST_INV_ENTER_CS(rmInst, key);
1239 RM_SC_INST_INV_ENTER_CS(rmInst, key);
1240 if (rmInst->mtSemObj) {
1241 mtKey = Rm_osalMtCsEnter(rmInst->mtSemObj);
1242 }
1244 if (rmInst->instType != Rm_instType_CLIENT) {
1245 Rm_osalLog("Instance name: %s\n", rmInst->instName);
1246 Rm_osalLog("Handle: 0x%08x\n", rmHandle);
1247 if (rmInst->instType == Rm_instType_SERVER) {
1248 Rm_osalLog("Type: Server\n");
1249 }
1250 else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1251 Rm_osalLog("Type: Client Delegate\n");
1252 }
1253 else if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1254 Rm_osalLog("Type: Shared Server\n");
1255 }
1256 else if (rmInst->instType == Rm_instType_SHARED_CLIENT) {
1257 Rm_osalLog("Type: Shared Client\n");
1258 }
1260 Rm_osalLog("\nResource Status:\n\n");
1261 }
1263 if (rmInst->instType == Rm_instType_SHARED_CLIENT) {
1264 /* Transfer control to shared server instance */
1265 rmInst = rmInst->u.sharedClient.sharedServerHandle;
1266 }
1268 if ((rmInst->instType == Rm_instType_SERVER) ||
1269 (rmInst->instType == Rm_instType_SHARED_SERVER) ||
1270 (rmInst->instType == Rm_instType_CLIENT_DELEGATE)) {
1271 allocator = rmAllocatorGetAllocatorList((Rm_Handle)rmInst);
1273 if (!allocator) {
1274 Rm_osalLog("No resources managed by instance at the moment\n\n");
1275 }
1277 while (allocator) {
1278 RM_SS_OBJ_INV(rmInst, allocator, Rm_Allocator);
1279 if (printResources) {
1280 Rm_osalLog("Resource: %s\n", allocator->resourceName);
1281 }
1283 treeRoot = allocator->allocatorRootEntry;
1284 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1285 rmResourceTreeInv(treeRoot);
1286 }
1287 RB_FOREACH(treeNode, _Rm_AllocatorResourceTree, treeRoot) {
1288 if (printResources) {
1289 if ((treeNode->base >= 65536) ||
1290 ((treeNode->base + treeNode->length - 1) >= 65536)) {
1291 /* Print in hex if number is very large */
1292 Rm_osalLog(" 0x%08x - 0x%08x ", treeNode->base,
1293 treeNode->base + treeNode->length - 1);
1294 }
1295 else {
1296 Rm_osalLog(" %10d - %10d ", treeNode->base,
1297 treeNode->base + treeNode->length - 1);
1298 }
1299 }
1301 if (treeNode->allocationCount == 0) {
1302 if (printResources) {
1303 Rm_osalLog("FREE\n");
1304 }
1305 }
1306 else {
1307 owners = treeNode->ownerList;
1308 while (owners) {
1309 RM_SS_OBJ_INV(rmInst, owners, Rm_Owner);
1310 if (printResources) {
1311 Rm_osalLog("%s (%d) ", owners->instNameNode->name, owners->refCnt);
1312 }
1313 totalResOwners++;
1314 owners = owners->nextOwner;
1315 }
1316 if (printResources) {
1317 Rm_osalLog("\n");
1318 }
1319 }
1320 }
1321 allocator = allocator->nextAllocator;
1322 }
1324 if ((rmInst->instType == Rm_instType_SERVER) ||
1325 (rmInst->instType == Rm_instType_SHARED_SERVER)) {
1326 if (printResources) {
1327 rmNameServerPrintObjects((Rm_Handle)rmInst);
1328 }
1329 }
1330 }
1331 else {
1332 totalResOwners = RM_ERROR_INVALID_RES_STATUS_INSTANCE;
1333 }
1335 /* Free sem object using originating instance in case the Shared Client to Shared
1336 * Server instance switch took place */
1337 if (((Rm_Inst *)rmHandle)->mtSemObj) {
1338 Rm_osalMtCsExit(((Rm_Inst *)rmHandle)->mtSemObj, mtKey);
1339 }
1340 RM_SS_INST_WB_EXIT_CS(rmInst, key);
1341 return(totalResOwners);
1342 }
1344 /* FUNCTION PURPOSE: Display status of a RM instance
1345 ***********************************************************************
1346 * DESCRIPTION: Prints the current status of various RM instance
1347 * properties such as the state of all transactions
1348 * in the transaction queue and registered transports
1349 */
1350 void Rm_instanceStatus(Rm_Handle rmHandle)
1351 {
1352 Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
1353 Rm_Transport *transportList = NULL;
1354 Rm_Transaction *transactionQ = NULL;
1355 void *key;
1356 void *mtKey;
1358 RM_SS_INST_INV_ENTER_CS(rmInst, key);
1359 RM_SC_INST_INV_ENTER_CS(rmInst, key);
1360 if (rmInst->mtSemObj) {
1361 mtKey = Rm_osalMtCsEnter(rmInst->mtSemObj);
1362 }
1364 Rm_osalLog("Instance name: %s\n", rmInst->instName);
1365 Rm_osalLog("Handle: 0x%08x\n", rmHandle);
1366 if (rmInst->instType == Rm_instType_SERVER) {
1367 Rm_osalLog("Type: Server\n");
1368 }
1369 else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1370 Rm_osalLog("Type: Client Delegate\n");
1371 }
1372 else if (rmInst->instType == Rm_instType_CLIENT) {
1373 Rm_osalLog("Type: Client\n");
1374 }
1375 else if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1376 Rm_osalLog("Type: Shared Server\n");
1377 }
1378 else if (rmInst->instType == Rm_instType_SHARED_CLIENT) {
1379 Rm_osalLog("Type: Shared Client\n");
1381 Rm_osalLog("\nShared Server Properties:\n");
1382 /* Transfer to Shared Server instance to print out transport and
1383 * transaction status */
1384 rmInst = rmInst->u.sharedClient.sharedServerHandle;
1385 Rm_osalLog("Instance name: %s\n", rmInst->instName);
1386 Rm_osalLog("Handle: 0x%08x\n", rmHandle);
1387 }
1389 transportList = rmInst->transports;
1390 if (transportList) {
1391 Rm_osalLog("\nRegistered Transports:\n");
1392 while (transportList) {
1393 RM_SS_OBJ_INV(rmInst, transportList, Rm_Transport);
1394 if (transportList->remoteInstType == Rm_instType_SERVER) {
1395 Rm_osalLog(" Remote instType: Server\n");
1396 }
1397 else if (transportList->remoteInstType == Rm_instType_CLIENT_DELEGATE) {
1398 Rm_osalLog(" Remote instType: Client Delegate\n");
1399 }
1400 else {
1401 Rm_osalLog(" Remote instType: Client\n");
1402 }
1403 Rm_osalLog(" appTransportHandle: 0x%08x\n", transportList->appTransportHandle);
1404 Rm_osalLog("\n");
1405 transportList = transportList->nextTransport;
1406 }
1407 }
1409 transactionQ = rmInst->transactionQueue;
1410 if (transactionQ) {
1411 Rm_osalLog("\nQueued Service Transactions:\n");
1412 while (transactionQ) {
1413 RM_SS_OBJ_INV(rmInst, transactionQ, Rm_Transaction);
1414 Rm_osalLog(" Service type: %d\n", transactionQ->type);
1415 Rm_osalLog(" Service ID: %d\n", transactionQ->localId);
1416 Rm_osalLog(" Service srcInstName %s\n", transactionQ->serviceSrcInstName);
1417 Rm_osalLog(" Service state: %d\n", transactionQ->state);
1418 Rm_osalLog(" Resource name: %s\n", transactionQ->resourceInfo.name);
1419 Rm_osalLog(" Resource base: %d\n", transactionQ->resourceInfo.base);
1420 Rm_osalLog(" Resource length: %d\n", transactionQ->resourceInfo.length);
1421 Rm_osalLog(" Resource alignment: %d\n", transactionQ->resourceInfo.alignment);
1422 Rm_osalLog(" Resource NS name: %s\n", transactionQ->resourceInfo.nameServerName);
1423 Rm_osalLog("\n");
1424 transactionQ = transactionQ->nextTransaction;
1425 }
1426 }
1428 /* Free sem object using originating instance in case the Shared Client to Shared
1429 * Server instance switch took place */
1430 if (((Rm_Inst *)rmHandle)->mtSemObj) {
1431 Rm_osalMtCsExit(((Rm_Inst *)rmHandle)->mtSemObj, mtKey);
1432 }
1433 RM_SS_INST_WB_EXIT_CS(rmInst, key);
1434 }
1436 /* FUNCTION PURPOSE: RM instance creation and initialization
1437 ***********************************************************************
1438 * DESCRIPTION: Returns a new RM instance created and initialized
1439 * using the parameters provided via the initCfg
1440 * structure.
1441 */
1442 Rm_Handle Rm_init(const Rm_InitCfg *initCfg, int32_t *result)
1443 {
1444 Rm_Inst *rmInst = NULL;
1445 Rm_Inst *sharedServerInst = NULL;
1446 uint32_t policySize;
1447 void *globalResourceDtb = NULL;
1448 void *linuxResourceDtb = NULL;
1449 int addLinux = RM_FALSE;
1450 void *key;
1452 *result = RM_OK;
1454 if ((initCfg->instName == NULL) ||
1455 ((strlen(initCfg->instName) + 1) > RM_NAME_MAX_CHARS)) {
1456 *result = RM_ERROR_INVALID_INST_NAME;
1457 goto errorExit;
1458 }
1460 if (initCfg->instType >= Rm_instType_LAST) {
1461 *result = RM_ERROR_INVALID_INST_TYPE;
1462 goto errorExit;
1463 }
1465 /* Create and initialize instance */
1466 rmInst = Rm_osalMalloc(sizeof(*rmInst));
1467 memset ((void *)rmInst, 0, sizeof(*rmInst));
1468 rmInst->isLocked = RM_FALSE;
1469 rmInst->registeredWithDelegateOrServer = RM_FALSE;
1470 rmInst->transactionSeqNum = transactionInitSequenceNum();
1472 rmInst->instType = initCfg->instType;
1473 rm_strncpy (rmInst->instName, initCfg->instName, RM_NAME_MAX_CHARS);
1474 rmInst->mtSemObj = initCfg->mtSemObj;
1476 if ((rmInst->instType == Rm_instType_SERVER) ||
1477 (rmInst->instType == Rm_instType_SHARED_SERVER)) {
1478 if (!initCfg->instCfg.serverCfg.globalResourceList ||
1479 !initCfg->instCfg.serverCfg.globalPolicy) {
1480 *result = RM_ERROR_INVALID_SERVER_CONFIGURATION;
1481 goto errorExit;
1482 }
1484 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1485 /* Shared Server makes copy of policy in shared memory for Shared Clients
1486 * on other cores */
1487 policySize = fdt_totalsize(initCfg->instCfg.serverCfg.globalPolicy);
1488 /* Align policy size to cache boundary */
1489 if (policySize % RM_MAX_CACHE_ALIGN) {
1490 policySize += (RM_MAX_CACHE_ALIGN - (policySize % RM_MAX_CACHE_ALIGN));
1491 }
1492 rmInst->u.server.policySize = policySize;
1493 rmInst->u.server.globalPolicy = Rm_osalMalloc(rmInst->u.server.policySize);
1494 memcpy(rmInst->u.server.globalPolicy, initCfg->instCfg.serverCfg.globalPolicy, rmInst->u.server.policySize);
1495 }
1496 else {
1497 rmInst->u.server.globalPolicy = initCfg->instCfg.serverCfg.globalPolicy;
1498 }
1500 if (initCfg->instCfg.serverCfg.linuxDtb) {
1501 linuxResourceDtb = initCfg->instCfg.serverCfg.linuxDtb;
1502 addLinux = RM_TRUE;
1503 }
1505 /* Create valid instance list from policy. Must be done prior to parsing
1506 * GRL so that Linux resources can be reserved correctly */
1507 rmInst->u.server.globalValidInstTree = rmPolicyCreateValidInstTree((Rm_Handle)rmInst, addLinux, result);
1508 if (*result == RM_OK) {
1509 *result = rmPolicyValidatePolicy((Rm_Handle)rmInst);
1510 }
1512 if (*result != RM_OK) {
1513 if (rmInst->u.server.globalValidInstTree) {
1514 rmPolicyFreeValidInstTree((Rm_Handle)rmInst);
1515 }
1516 goto errorExit;
1517 }
1518 else {
1519 rmNameServerInit((Rm_Handle)rmInst);
1521 globalResourceDtb = initCfg->instCfg.serverCfg.globalResourceList;
1523 if ((*result = rmAllocatorInitializeResources((Rm_Handle) rmInst, globalResourceDtb, linuxResourceDtb)) == RM_OK) {
1524 *result = rmPolicyValidatePolicyResourceNames((Rm_Handle)rmInst);
1525 }
1527 if (*result != RM_OK) {
1528 rmAllocatorDeleteResources((Rm_Handle)rmInst);
1529 rmNameServerDelete((Rm_Handle)rmInst);
1530 goto errorExit;
1531 }
1532 }
1533 }
1534 else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1535 if (!initCfg->instCfg.cdCfg.cdPolicy) {
1536 *result = RM_ERROR_INVALID_CD_CONFIGURATION;
1537 goto errorExit;
1538 }
1540 rmInst->u.cd.cdPolicy = initCfg->instCfg.cdCfg.cdPolicy;
1541 rmInst->u.cd.cdValidInstTree = 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.cd.cdValidInstTree) {
1548 rmPolicyFreeValidInstTree((Rm_Handle)rmInst);
1549 }
1550 goto errorExit;
1551 }
1553 rmInst->u.cd.allocators = NULL;
1555 /* Remove once CD instance is stable - tracked by SDOCM00100797 */
1556 *result = RM_WARNING_CD_INSTANCE_NOT_STABLE;
1557 }
1558 else if (rmInst->instType == Rm_instType_CLIENT) {
1559 if (initCfg->instCfg.clientCfg.staticPolicy) {
1560 rmInst->u.client.staticPolicy = initCfg->instCfg.clientCfg.staticPolicy;
1561 rmInst->u.client.staticValidInstTree = rmPolicyCreateValidInstTree((Rm_Handle)rmInst, addLinux, result);
1562 if (*result == RM_OK) {
1563 *result = rmPolicyValidatePolicy((Rm_Handle)rmInst);
1564 }
1566 if (*result != RM_OK) {
1567 if (rmInst->u.client.staticValidInstTree) {
1568 rmPolicyFreeValidInstTree((Rm_Handle)rmInst);
1569 }
1570 goto errorExit;
1571 }
1572 }
1573 }
1574 else if (rmInst->instType == Rm_instType_SHARED_CLIENT) {
1575 if (initCfg->instCfg.sharedClientCfg.sharedServerHandle) {
1576 rmInst->u.sharedClient.sharedServerHandle = initCfg->instCfg.sharedClientCfg.sharedServerHandle;
1577 /* Invalidate the Shared server instance structure on this core to get the latest
1578 * instance data. */
1579 key = Rm_osalCsEnter();
1580 Rm_osalBeginMemAccess((void *)rmInst->u.sharedClient.sharedServerHandle, sizeof(Rm_Inst));
1581 sharedServerInst = rmInst->u.sharedClient.sharedServerHandle;
1582 if (sharedServerInst->instType != Rm_instType_SHARED_SERVER) {
1583 *result = RM_ERROR_INVALID_SHARED_SERVER_HANDLE;
1584 Rm_osalCsExit(key);
1585 goto errorExit;
1586 }
1587 else {
1588 /* Invalidate the policy */
1589 Rm_osalBeginMemAccess((void *)sharedServerInst->u.server.globalPolicy,
1590 sharedServerInst->u.server.policySize);
1591 }
1592 Rm_osalCsExit(key);
1593 }
1594 else {
1595 *result = RM_ERROR_INVALID_SHARED_SERVER_HANDLE;
1596 goto errorExit;
1597 }
1598 }
1600 if (initCfg->instType == Rm_instType_SHARED_SERVER) {
1601 /* Writeback the instance and policy for other cores */
1602 Rm_osalEndMemAccess ((void *)rmInst, sizeof(Rm_Inst));
1603 Rm_osalEndMemAccess ((void *)rmInst->u.server.globalPolicy, rmInst->u.server.policySize);
1604 }
1605 else if (rmInst->instType != Rm_instType_SHARED_CLIENT) {
1606 /* Create the instance's task blocking mechanism */
1607 rmInst->blockHandle = Rm_osalTaskBlockCreate();
1608 }
1610 return ((Rm_Handle) rmInst);
1611 errorExit:
1612 if (rmInst) {
1613 Rm_osalFree((void *)rmInst, sizeof(Rm_Inst));
1614 }
1615 return (NULL);
1616 }
1618 /* FUNCTION PURPOSE: Deletes an RM instance
1619 ***********************************************************************
1620 * DESCRIPTION: Frees all memory associated with an RM instance
1621 * as long as all transports have been unregistered
1622 * and the service handle has been closed
1623 */
1624 int32_t Rm_delete(Rm_Handle rmHandle, int ignorePendingServices)
1625 {
1626 Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
1627 void *key;
1629 key = Rm_osalCsEnter();
1630 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1631 Rm_osalBeginMemAccess((void *)rmInst, sizeof(Rm_Inst));
1632 }
1634 if (rmInst->serviceHandle) {
1635 return (RM_ERROR_CANT_DELETE_WITH_OPEN_SERV_HNDL);
1636 }
1637 else if (rmInst->transports) {
1638 return (RM_ERROR_CANT_DELETE_WITH_REGD_TRANSPORT);
1639 }
1640 else if (rmInst->transactionQueue && !ignorePendingServices) {
1641 return (RM_ERROR_CANT_DELETE_PENDING_TRANSACTIONS);
1642 }
1644 if ((rmInst->instType == Rm_instType_SERVER) ||
1645 (rmInst->instType == Rm_instType_SHARED_SERVER)) {
1646 rmAllocatorDeleteResources(rmHandle);
1647 rmNameServerDelete(rmHandle);
1648 rmInst->u.server.allocators = NULL;
1650 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1651 Rm_osalFree((void *)rmInst->u.server.globalPolicy, rmInst->u.server.policySize);
1652 }
1653 }
1654 else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1655 rmAllocatorDeleteResources(rmHandle);
1656 rmInst->u.cd.allocators = NULL;
1657 }
1659 if (rmInst->instType != Rm_instType_SHARED_CLIENT) {
1660 /* Delete valid instance tree */
1661 rmPolicyFreeValidInstTree(rmHandle);
1663 /* Delete any transactions */
1664 while(rmInst->transactionQueue) {
1665 rmTransactionQueueDelete(rmInst, rmInst->transactionQueue->localId);
1666 }
1668 if (rmInst->instType != Rm_instType_SHARED_SERVER) {
1669 /* Delete the instance's task blocking mechanism */
1670 Rm_osalTaskBlockDelete(rmInst->blockHandle);
1671 }
1672 else {
1673 Rm_osalEndMemAccess((void *)rmInst, sizeof(Rm_Inst));
1674 }
1675 }
1677 Rm_osalFree((void *)rmInst, sizeof(Rm_Inst));
1679 Rm_osalCsExit(key);
1680 return (RM_OK);
1681 }
1683 /* FUNCTION PURPOSE: Returns RM version information
1684 ***********************************************************************
1685 */
1686 uint32_t Rm_getVersion(void)
1687 {
1688 return RM_VERSION_ID;
1689 }
1691 /* FUNCTION PURPOSE: Returns RM version string
1692 ***********************************************************************
1693 */
1694 const char* Rm_getVersionStr(void)
1695 {
1696 return rmVersionStr;
1697 }