]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - keystone-rtos/rm-lld.git/blobdiff - src/rm_services.c
Made requesting instance's allocation count for resource available via the service...
[keystone-rtos/rm-lld.git] / src / rm_services.c
index dd85f95a0fa8f781bb05de2e0c13b21b979c9754..a2d13e79fd6e013c6892345b388f3d4991c566fb 100644 (file)
@@ -1,12 +1,12 @@
 /**
- *   @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->serviceSrcInstName, 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))
-            {
-                strcpy(serviceResponse->resourceName, transaction->resourceInfo.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)))
-    {
-        strcpy(serviceResponse.resourceName, transaction->resourceInfo.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);
 }
 
-/**
-@}
-*/