diff --git a/src/rm_services.c b/src/rm_services.c
index a85ab9b8a23a001466195ee9093078553f95b116..a2d13e79fd6e013c6892345b388f3d4991c566fb 100644 (file)
--- a/src/rm_services.c
+++ b/src/rm_services.c
/**
- * @file rmservices.c
+ * @file rm_services.c
*
* @brief
* This is the Resource Manager services source.
*
* \par
* ============================================================================
- * @n (C) Copyright 2012, Texas Instruments, Inc.
+ * @n (C) Copyright 2012-2013, Texas Instruments, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* \par
*/
-/* RM Types */
-#include <ti/drv/rm/rm_types.h>
+/* Standard includes */
+#include <string.h>
/* RM external API includes */
+#include <ti/drv/rm/rm.h>
#include <ti/drv/rm/rm_services.h>
/* RM internal API includes */
********************** Internal Functions ****************************
**********************************************************************/
-void Rm_serviceHandler (void *rmHandle, Rm_ServiceReqInfo *serviceRequest,
- Rm_ServiceRespInfo *serviceResponse)
+/* FUNCTION PURPOSE: Internal Callback to unblock RM instance
+ ***********************************************************************
+ * DESCRIPTION: Internal callback function executed when the result
+ * of a service request has been received from a remote
+ * instance. The original service request did not specify
+ * a callback function so the Rm_serviceHandler is blocked
+ * waiting for the response. This function unblocks the
+ * Rm_serviceHandler to return the response to the
+ * application.
+ */
+void rmServiceInternalCallback(Rm_Handle rmHandle)
{
Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
+
+ /* Unblock so Rm_serviceHandler can provide response to application */
+ Rm_osalTaskUnblock(rmInst->blockHandle);
+}
+
+/**********************************************************************
+ ********************** Application visible APIs **********************
+ **********************************************************************/
+
+/* FUNCTION PURPOSE: Handles application component service requests
+ ***********************************************************************
+ * DESCRIPTION: Receives service requests from application components
+ * and routes them to the transaction processor. If
+ * the service can be handled immediately the response
+ * will be provided in the service response. If the
+ * service requires a blocking operation the handler
+ * will provide a service ID back to the application.
+ * The response will be sent at a later time via the
+ * application supplied callback function.
+ */
+void Rm_serviceHandler (void *rmHandle, const Rm_ServiceReqInfo *serviceRequest,
+ Rm_ServiceRespInfo *serviceResponse)
+{
+ Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
+ char *instanceName;
Rm_Transaction *transaction;
+ void *key;
+
+ RM_SS_INST_INV_ENTER_CS(key);
+ RM_SC_INST_INV_ENTER_CS(key);
- /* Make sure that a callback function has been provided */
- if (serviceRequest->callback.serviceCallback == NULL)
- {
- /* The RM Client and Client Delegate use blocking transports to consult with a
- * high-level RM agent prior to providing a response to the component. It is
- * assumed the component's cannot block. Therefore, all responses must go
- * through the callback function provided by the component. Return an error
- * if the component does not provide a callback function. */
- serviceResponse->serviceState = RM_SERVICE_ERROR_CALLBACK_NOT_PROVIDED;
+ if (rmInst->isLocked) {
+ serviceResponse->serviceState = RM_SERVICE_DENIED_RM_INSTANCE_LOCKED;
return;
}
-
- /* Create a new transaction */
- transaction = Rm_transactionQueueAdd(rmInst);
- if (transaction == NULL)
- {
- /* Failed to create a new transaction */
- serviceResponse->serviceState = RM_SERVICE_ERROR_TRANSACTION_FAILED_TO_ALLOCATE;
+ if (serviceRequest->type >= Rm_service_LAST) {
+ serviceResponse->serviceState = RM_ERROR_INVALID_SERVICE_TYPE;
+ return;
}
- else
- {
- /* Transfer request information into the transaction */
+
+ /* Copy location of instance name to local variable in case Shared Client needs to
+ * transfer control to a shared server */
+ instanceName = rmInst->instName;
+ if (rmInst->instType == Rm_instType_SHARED_CLIENT) {
+ /* Transfer control to shared server instance */
+ rmInst = rmInst->u.sharedClient.sharedServerHandle;
+ }
+
+ transaction = rmTransactionQueueAdd(rmInst);
+ if (transaction) {
transaction->type = serviceRequest->type;
- strcpy(transaction->sourceInstName, rmInst->name);
- transaction->callback.serviceCallback = serviceRequest->callback.serviceCallback;
+ strncpy(transaction->serviceSrcInstName, instanceName, RM_NAME_MAX_CHARS);
+ transaction->u.callback.serviceCallback = serviceRequest->callback.serviceCallback;
transaction->state = RM_SERVICE_PROCESSING;
- strcpy(&(transaction->resourceInfo.name)[0], serviceRequest->resourceName);
+ if (serviceRequest->resourceName) {
+ strncpy(transaction->resourceInfo.name, serviceRequest->resourceName, RM_NAME_MAX_CHARS);
+ }
transaction->resourceInfo.base = serviceRequest->resourceBase;
transaction->resourceInfo.length = serviceRequest->resourceLength;
transaction->resourceInfo.alignment = serviceRequest->resourceAlignment;
- strcpy(&(transaction->resourceInfo.nsName)[0], serviceRequest->resourceNsName);
-
- /* Pass the new transaction to the transaction processor */
- Rm_transactionProcessor (rmInst, transaction);
-
- /* Provide response to the component that requested the service */
- serviceResponse->serviceState = transaction->state;
- if (serviceResponse->serviceState == RM_SERVICE_PROCESSING)
- {
- /* The service is still being processed. Provide the transaction ID
- * back to the component so that it can sort service responses received
- * via the provided callback function */
- serviceResponse->serviceId = transaction->localId;
+ transaction->resourceInfo.ownerCount = RM_RESOURCE_NUM_OWNERS_INVALID;
+ transaction->resourceInfo.instAllocCount = RM_INST_ALLOC_COUNT_INVALID;
+ if (serviceRequest->resourceNsName) {
+ strncpy(transaction->resourceInfo.nameServerName, serviceRequest->resourceNsName, RM_NAME_MAX_CHARS);
+ }
+
+ /* Process received transaction */
+ rmProcessRouter(rmInst, transaction);
+
+ memset((void *)serviceResponse, 0, sizeof(*serviceResponse));
+
+ if ((rmInst->instType == Rm_instType_SHARED_SERVER) &&
+ (transaction->state == RM_SERVICE_PROCESSING)) {
+ /* Shared Server should always return a fully processed transaction */
+ serviceResponse->serviceState = RM_ERROR_SHARED_INSTANCE_UNFINISHED_REQ;
+ rmTransactionQueueDelete(rmInst, transaction->localId);
}
- else if (serviceResponse->serviceState == RM_SERVICE_APPROVED_AND_COMPLETED)
- {
- /* Service was approved and service was an allocate request the resource
- * data is passed back to the component */
- if ((transaction->type == Rm_service_RESOURCE_ALLOCATE) ||
- (transaction->type == Rm_service_RESOURCE_GET_BY_NAME))
- {
+ else {
+ if ((transaction->state == RM_SERVICE_PROCESSING) &&
+ (transaction->u.callback.serviceCallback == NULL)) {
+ /* Block until response is received. Response will be received in transaction. */
+ Rm_osalTaskBlock(rmInst->blockHandle);
+ }
+
+ serviceResponse->rmHandle = rmHandle;
+ serviceResponse->serviceState = transaction->state;
+ /* Owner and instance allocation count will only be set within RM under certain circumstances. */
+ serviceResponse->resourceNumOwners = transaction->resourceInfo.ownerCount;
+ serviceResponse->instAllocCount = transaction->resourceInfo.instAllocCount;
+ if ((serviceResponse->serviceState == RM_SERVICE_PROCESSING) ||
+ (serviceResponse->serviceState == RM_SERVICE_APPROVED_STATIC) ||
+ (serviceResponse->serviceState == RM_SERVICE_PENDING_SERVER_RESPONSE)) {
+ /* Service still being processed. Static requests will have their validation responses sent once
+ * all transports have been established. Provide transaction ID back to component so it can sort
+ * service responses received via callback function */
+ serviceResponse->serviceId = transaction->localId;
+ }
+
+ if ((serviceResponse->serviceState == RM_SERVICE_APPROVED) ||
+ (serviceResponse->serviceState == RM_SERVICE_APPROVED_STATIC)) {
+ strncpy(serviceResponse->resourceName, transaction->resourceInfo.name, RM_NAME_MAX_CHARS);
serviceResponse->resourceBase = transaction->resourceInfo.base;
serviceResponse->resourceLength = transaction->resourceInfo.length;
}
- /* Delete the transaction since a response was received immediately */
- Rm_transactionQueueDelete(rmInst, transaction->localId);
- }
- else
- {
- /* The serviceState field will contain information regarding why the
- * service was denied or what error the service encountered. Just delete
- * the transaction since a response was received immediately */
- Rm_transactionQueueDelete(rmInst, transaction->localId);
+ /* Transactions still processing not deleted from queue including static transactions which will be
+ * verified once all transports are up */
+ if ((serviceResponse->serviceState != RM_SERVICE_PROCESSING) &&
+ (serviceResponse->serviceState != RM_SERVICE_APPROVED_STATIC) &&
+ (serviceResponse->serviceState != RM_SERVICE_PENDING_SERVER_RESPONSE)) {
+ rmTransactionQueueDelete(rmInst, transaction->localId);
+ }
}
}
-
+ else {
+ serviceResponse->serviceState = RM_ERROR_SERVICE_TRANS_NOT_CREATED;
+ }
+ RM_SS_INST_WB_EXIT_CS(key);
return;
}
-/* This function is executed when a RM instance receives a response to one of its requests
- * and the information in the request must be provided to the original requesting component */
-void Rm_serviceResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)
+/* FUNCTION PURPOSE: Opens the RM instance service handle
+ ***********************************************************************
+ * DESCRIPTION: Returns the service handle for an RM instance. Only
+ * one service handle is opened per instance.
+ */
+Rm_ServiceHandle *Rm_serviceOpenHandle(Rm_Handle rmHandle, int32_t *result)
{
- Rm_ServiceRespInfo serviceResponse;
-
- /* The responseTransaction will contain the resultant state details of
- * the requestTransaction's service request */
- serviceResponse.serviceState = transaction->state;
- /* Pass back the ID that was provided to the component when it requested
- * the service */
- serviceResponse.serviceId = transaction->localId;
-
- /* Service was approved and service was an allocate request. The resource
- * data is passed back to the component */
- if ((serviceResponse.serviceState == RM_SERVICE_APPROVED_AND_COMPLETED) &&
- ((transaction->type == Rm_service_RESOURCE_ALLOCATE) ||
- (transaction->type == Rm_service_RESOURCE_GET_BY_NAME)))
- {
- serviceResponse.resourceBase = transaction->resourceInfo.base;
- serviceResponse.resourceLength = transaction->resourceInfo.length;
+ Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
+ Rm_ServiceHandle *serviceHandle = NULL;
+ void *key;
+
+ RM_SS_INST_INV_ENTER_CS(key);
+
+ *result = RM_OK;
+
+ serviceHandle = rmInst->serviceHandle;
+ if (serviceHandle == NULL) {
+ serviceHandle = Rm_osalMalloc(sizeof(*serviceHandle));
+ if (serviceHandle) {
+ serviceHandle->rmHandle = rmHandle;
+ serviceHandle->Rm_serviceHandler = Rm_serviceHandler;
+ RM_SS_OBJ_WB(serviceHandle, Rm_ServiceHandle);
+ rmInst->serviceHandle = serviceHandle;
+ }
+ else {
+ *result = RM_ERROR_SERVICE_HANDLE_MEM_ALLOC_FAILED;
+ }
}
-
- /* Issue the callback to the requesting component with the response information */
- transaction->callback.serviceCallback(&serviceResponse);
-
- /* Delete the transaction from the transaction queue */
- Rm_transactionQueueDelete(rmInst, transaction->localId);
- return;
+ RM_SS_INST_WB_EXIT_CS(key);
+ return (serviceHandle);
}
-/**********************************************************************
- ********************** Application visible APIs **********************
- **********************************************************************/
-
-void Rm_preMainAllocService(Rm_PreMainAllocInfo *preMainAllocInfo,
- Rm_ServiceRespInfo *serviceResponse)
+/* FUNCTION PURPOSE: Closes the RM instance service handle
+ ***********************************************************************
+ * DESCRIPTION: Closes the service handle for an RM instance.
+ */
+int32_t Rm_serviceCloseHandle(Rm_ServiceHandle *rmServiceHandle)
{
+ Rm_Inst *rmInst = (Rm_Inst *)rmServiceHandle->rmHandle;
+ int32_t retVal = RM_OK;
+ void *key;
-}
-
-Rm_ServicePort *Rm_getServicePort(Rm_Handle rmHandle)
-{
- Rm_ServicePort *newServicePort = NULL;
-
- /* Create a new service handle for the specified RM instance */
-
- /* Get memory for a new service port from local memory */
- newServicePort = Rm_osalMalloc (sizeof(Rm_ServicePort));
+ RM_SS_INST_INV_ENTER_CS(key);
- /* Return NULL immediately if malloc returned NULL */
- if (newServicePort == NULL)
- {
- return (newServicePort);
+ if (rmInst->serviceHandle) {
+ Rm_osalFree((void *)rmServiceHandle, sizeof(*rmServiceHandle));
+ rmInst->serviceHandle = NULL;
}
-
- newServicePort->rmHandle = rmHandle;
- newServicePort->rmService = Rm_serviceHandler;
-
- return (newServicePort);
+ else {
+ retVal = RM_ERROR_SERVICE_HANDLE_ALREADY_CLOSED;
+ }
+ RM_SS_INST_WB_EXIT_CS(key);
+ return(retVal);
}
-/**
-@}
-*/