Fixed task blocking routine not working more than once
authorJustin Sobota <jsobota@ti.com>
Tue, 5 Mar 2013 23:27:56 +0000 (18:27 -0500)
committerJustin Sobota <jsobota@ti.com>
Tue, 5 Mar 2013 23:27:56 +0000 (18:27 -0500)
include/rm_loc.h
rm_osal.h
rm_services.h
src/rm.c
src/rm_services.c
test/rm_osal.c
test/rm_test.c

index d351977c2f6f97a1b645ac0aee6607cb0ad5ab8f..69e197d72bfc38890a408b57f273ba8c86b2e19f 100644 (file)
@@ -147,9 +147,10 @@ typedef struct {
     uint32_t          transactionSeqNum;
     /* Service transaction linked list queue */
     Rm_Transaction   *transactionQueue; 
-    /* Local gate key provided through OSAL when RM needs to block due to
-     * a service request that requires a blocking operation to complete */
-    uint32_t          localGateKey;
+    /* Block handle provided through OSAL for when RM needs to block due to
+     * a service request that requires a blocking operation to complete and
+     * a service callback function has not been provided */
+    void             *blockHandle;
     /* Instance-type specific constructs */
     union {
         /* Server-specific instance data */
index 843b5edc0657d1318a3be83161b57841022b8017..8825204def9eb63dd86ce62625397f2d58c34dd6 100644 (file)
--- a/rm_osal.h
+++ b/rm_osal.h
  ************************* Extern Declarations ************************
  **********************************************************************/
 
-extern void     *Osal_rmMalloc (uint32_t num_bytes);
-extern void      Osal_rmFree (void *ptr, uint32_t size);
-extern uint32_t  Osal_rmLocalGateEnter (void);
-extern void      Osal_rmLocalGateLeave (uint32_t localGateKey);
-extern void      Osal_rmLog (char *fmt, ... );
+extern void *Osal_rmMalloc (uint32_t num_bytes);
+extern void  Osal_rmFree (void *ptr, uint32_t size);
+extern void *Osal_rmTaskBlockCreate (void);
+extern void  Osal_rmTaskBlock (void *handle);
+extern void  Osal_rmTaskUnblock (void *handle);
+extern void  Osal_rmTaskBlockDelete (void *handle);
+extern void  Osal_rmLog (char *fmt, ... );
 
 /**
  * @brief   The macro is used by RM to allocate memory of specified
@@ -120,9 +122,89 @@ extern void      Osal_rmLog (char *fmt, ... );
  */
 #define Rm_osalFree               Osal_rmFree
 
-#define Rm_osalLocalGateEnter     Osal_rmLocalGateEnter
+/**
+ * @brief   The macro is used by RM to create a task blocking
+ *          mechanism allowing a RM instance to block when it
+ *          has not been provided a service callback function
+ *          and it must send a packet to remote RM instance 
+ *          to complete a service.
+ *
+ * <b> Prototype: </b>
+ *  The following is the C prototype for the expected OSAL API.
+ *
+ *  @verbatim
+       void *Osal_rmTaskBlockCreate (void)
+    @endverbatim
+ *      
+ *  <b> Parameter </b>
+ *  @n  Not applicable.
+ *
+ *  <b> Return Value </b>
+ *  @n  Task blocking mechanism handle cast as a void pointer
+ */
+#define Rm_osalTaskBlockCreate    Osal_rmTaskBlockCreate
+
+/**
+ * @brief   The macro is used by a RM instance to block when it
+ *          has not been provided a service callback function
+ *          and it must send a packet to remote RM instance 
+ *          to complete a service.  The blocking operation
+ *          should block the current RM instance's task/thread
+ *          from executing until a task/thread from which the
+ *          RM receive code runs unblocks the RM instance
+ *
+ * <b> Prototype: </b>
+ *  The following is the C prototype for the expected OSAL API.
+ *
+ *  @verbatim
+       void  Osal_rmTaskBlock (void *handle)
+    @endverbatim
+ *      
+ *  <b> Parameter </b>
+ *  @n  Task blocking mechanism handle cast as a void pointer
+ *
+ *  <b> Return Value </b>
+ *  @n  Not applicable.
+ */
+#define Rm_osalTaskBlock          Osal_rmTaskBlock
 
-#define Rm_osalLocalGateLeave     Osal_rmLocalGateLeave
+/**
+ * @brief   The macro is used by a RM instance to unblock from 
+ *          a previous block operation.
+ *
+ * <b> Prototype: </b>
+ *  The following is the C prototype for the expected OSAL API.
+ *
+ *  @verbatim
+       void  Osal_rmTaskUnblock (void *handle)
+    @endverbatim
+ *      
+ *  <b> Parameter </b>
+ *  @n  Task blocking mechanism handle cast as a void pointer
+ *
+ *  <b> Return Value </b>
+ *  @n  Not applicable.
+ */
+#define Rm_osalTaskUnblock        Osal_rmTaskUnblock
+
+/**
+ * @brief   The macro is used by a RM instance to delete its
+ *          task blocking mechanism.
+ *
+ * <b> Prototype: </b>
+ *  The following is the C prototype for the expected OSAL API.
+ *
+ *  @verbatim
+       void  Osal_rmTaskBlockDelete (void *handle)
+    @endverbatim
+ *      
+ *  <b> Parameter </b>
+ *  @n  Task blocking mechanism handle cast as a void pointer
+ *
+ *  <b> Return Value </b>
+ *  @n  Not applicable.
+ */
+#define Rm_osalTaskBlockDelete    Osal_rmTaskBlockDelete
 
 /**
  * @brief   The macro is used by RM to log various 
index 67c1670391fa2ca1a2ae1a2eda505fbefd80fac3..2968a97891184b955a91f104e756fea1cf141eaf 100644 (file)
@@ -141,8 +141,7 @@ typedef struct {
  *     property defined.
  *  b) The default alignment of 1 if no alignment is specified in the policy
  *     for the resource.
- *  This value is only valid if resourceBase is set to 
- *  #RM_RESOURCE_BASE_UNSPECIFIED */
+ *  This value is only valid if resourceBase is set to #RM_RESOURCE_BASE_UNSPECIFIED */
 #define RM_RESOURCE_ALIGNMENT_UNSPECIFIED (-1)      
     /** Alignment of the resource affected by the service request.  Only valid
      *  if resourceBase is set to #RM_RESOURCE_BASE_UNSPECIFIED.
@@ -154,7 +153,9 @@ typedef struct {
      *  occur. */
     const char         *resourceNsName;
     /** Callback function used by RM to provide responses back to application
-     *  components after a service request resulted in a blocking operation. */
+     *  components after a service request resulted in a blocking operation.
+     *  If no callback function is provided the RM instance will block until
+     *  the service response is ready. */
     Rm_ServiceCallback  callback;
 } Rm_ServiceReqInfo;
 
index bb6e697a7709aa6fc3f1f1a0191d759de4e77df2..e10403316261c28095a217b3d2f0876aacd2574c 100644 (file)
--- a/src/rm.c
+++ b/src/rm.c
@@ -1055,6 +1055,10 @@ Rm_Handle Rm_init(const Rm_InitCfg *initCfg, int32_t *result)
             }
         }
     }
+
+    /* Create the instance's task blocking mechanism */
+    rmInst->blockHandle = Rm_osalTaskBlockCreate();
+    
     return ((Rm_Handle) rmInst);
 errorExit:
     if (rmInst) {
@@ -1099,6 +1103,11 @@ int32_t Rm_delete(Rm_Handle rmHandle, bool ignorePendingServices)
     while(rmInst->transactionQueue) {
         rmTransactionQueueDelete(rmInst, rmInst->transactionQueue->localId);
     }
+    
+    /* Delete the instance's task blocking mechanism */
+    Rm_osalTaskBlockDelete(rmInst->blockHandle);
+
+    Rm_osalFree((void *)rmInst, sizeof(Rm_Inst)); 
     return (RM_OK);
 }
 
index 3a2b7844394db33987a22179fc9a0f1a43aabc98..c689ee4a3f5de036806755fdf61b543f0f84a38b 100644 (file)
  ********************** Internal Functions ****************************
  **********************************************************************/
 
+/* 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 the serviceHandler can provide the response to the application */
-    Rm_osalLocalGateLeave(rmInst->localGateKey);
+    /* Unblock so Rm_serviceHandler can provide response to application */
+    Rm_osalTaskUnblock(rmInst->blockHandle);
 }
 
 /**********************************************************************
@@ -118,7 +128,7 @@ void Rm_serviceHandler (void *rmHandle, const Rm_ServiceReqInfo *serviceRequest,
 
         if ((transaction->state == RM_SERVICE_PROCESSING) && (transaction->callback.serviceCallback == NULL)) {
             /* Block until response is received.  Response will be received in transaction. */
-            rmInst->localGateKey = Rm_osalLocalGateEnter();
+            Rm_osalTaskBlock(rmInst->blockHandle);
         }
 
         serviceResponse->rmHandle = rmHandle;
index 99bcc0f32f40b28a1fb1fb91ce94f91bb835c423..5a0812b6e96381d7aeb568250107141f010c2a52 100644 (file)
@@ -41,6 +41,7 @@
 
 /* Standard Includes */
 #include <stdarg.h>
+#include <stdbool.h>
 
 /* XDC Includes */
 #include <xdc/std.h>
 #include <xdc/runtime/System.h>
 
 /* BIOS Includes */
-#include <ti/sysbios/gates/GateMutex.h>
+#include <ti/sysbios/BIOS.h>
+#include <ti/sysbios/knl/Task.h>
+#include <ti/sysbios/knl/Semaphore.h>
 
 /**********************************************************************
  ****************************** Defines *******************************
  **********************************************************************/
-#define RM_INTERNAL_GATE_NAME "rmInternalLocalGate"
+
+/* Specifies the number of test tasks running that have at least one
+ * RM running instance running within their context */
+#define NUM_TASKS_CONTAINING_RM_INSTANCES 2
+
+/* Structure that maps a semaphore to a task */
+typedef struct {
+    /* Task handle */
+    Task_Handle      task;
+    /* Semaphore handle */
+    Semaphore_Handle sem;
+    /* Number of times semaphore has been returned via create API */
+    uint32_t         ownerCount;
+} Semaphore_Owner;
 
 /**********************************************************************
  ************************** Global Variables **************************
@@ -62,7 +78,8 @@
 uint32_t rmMallocCounter = 0;
 uint32_t rmFreeCounter   = 0;
 
-GateMutex_Handle rmInternalGateHandle;
+Semaphore_Owner semOwners[NUM_TASKS_CONTAINING_RM_INSTANCES] = {{NULL, NULL, 0},
+                                                                {NULL, NULL, 0}};
 
 /**********************************************************************
  *************************** OSAL Functions **************************
@@ -73,7 +90,7 @@ GateMutex_Handle rmInternalGateHandle;
  * DESCRIPTION: The function is used to allocate a memory block of the
  *              specified size.
  */
-voidOsal_rmMalloc (uint32_t num_bytes)
+void *Osal_rmMalloc (uint32_t num_bytes)
 {
        Error_Block     errorBlock;
 
@@ -96,26 +113,53 @@ void Osal_rmFree (void *ptr, uint32_t size)
        Memory_free(NULL, ptr, size);
 }
 
-void Osal_rmLocalGateInit (void)
+void *Osal_rmTaskBlockCreate(void)
+{
+    Semaphore_Params semParams;    
+#if 0    
+    Task_Handle      currentTask = Task_self();
+    uint32_t         ownerIndex;    
+
+    /* See if task from which create has been called already has a sem */
+    for (ownerIndex = 0; ownerIndex < NUM_TASKS_CONTAINING_RM_INSTANCES; ownerIndex++) {
+        if (semOwners[ownerIndex].task == currentTask) {
+            break;
+        }
+    }
+    if (ownerIndex == NUM_TASKS_CONTAINING_RM_INSTANCES) {
+        /* First time create called within this task context.  Find next
+         * available slot in semOwners array */
+        ownerIndex = 0;
+        while(semOwners[ownerIndex].task) {
+            ownerIndex++;
+        }
+        semOwners[ownerIndex].task = currentTask;
+    }
+
+    if (semOwners[ownerIndex].sem == NULL) {
+        Semaphore_Params_init(&semParams);
+        semOwners[ownerIndex].sem = Semaphore_create(0, &semParams, NULL);        
+    }
+    semOwners[ownerIndex].ownerCount++;
+    return((void *)semOwners[ownerIndex].sem);
+#endif
+    Semaphore_Params_init(&semParams);
+    return((void *)Semaphore_create(0, &semParams, NULL));
+}
+
+void Osal_rmTaskBlock(void *handle)
 {
-    Error_Block eb;
-    GateMutex_Params gateParams;
-
-    /* Create a GateMutex object to be use as a resource lock */
-    GateMutex_Params_init(&gateParams);  
-    rmInternalGateHandle = GateMutex_create(&gateParams, &eb);
-    /* Immediately take the gate so that calls from within RM will block */
-    GateMutex_enter(rmInternalGateHandle);
+    Semaphore_pend((Semaphore_Handle)handle, BIOS_WAIT_FOREVER);
 }
 
-uint32_t Osal_rmLocalGateEnter (void)
+void Osal_rmTaskUnblock(void *handle)
 {
-    return ((uint32_t)GateMutex_enter(rmInternalGateHandle));
+    Semaphore_post((Semaphore_Handle)handle);
 }
 
-void Osal_rmLocalGateLeave (uint32_t localGateKey)
+void Osal_rmTaskBlockDelete(void *handle)
 {
-    GateMutex_leave(rmInternalGateHandle, (IArg)localGateKey);
+    Semaphore_delete((Semaphore_Handle *)&handle);
 }
 
 /* FUNCTION PURPOSE: Prints a variable list
index 1e12b99028e5358825727c23b042b32a8fe472d9..baccd589d85bc5bf4d4126c22bcbf2bf8125b3f4 100644 (file)
@@ -958,7 +958,7 @@ void rmClientTsk(UArg arg0, UArg arg1)
         System_printf("FAILED : denial or error : %d\n", responseInfo.serviceState);
     }     
 
-    /* Allocate a resource without providing a callback function.  RM should block and not return until the result
+    /* BEGIN Allocating some resources without providing a callback function.  RM should block and not return until the result
      * is returned by the server. */
     setRmRequest(&requestInfo, Rm_service_RESOURCE_ALLOCATE_INIT, resourceNameGpQ, 
                  7000, 1, 0, NULL, FALSE, &responseInfo);     
@@ -968,15 +968,61 @@ void rmClientTsk(UArg arg0, UArg arg1)
                                                                                                 resourceNameGpQ,
                                                                                                 requestInfo.resourceBase, 
                                                                                                 (requestInfo.resourceBase + requestInfo.resourceLength - 1));
-    if (responseInfo.serviceState == RM_SERVICE_PROCESSING) {
-        waitForResponse(&responseInfo);
+    if (responseInfo.serviceState == RM_SERVICE_APPROVED) {
+        System_printf("PASSED\n");
     }
+    else {
+        System_printf("FAILED : denial or error : %d\n", responseInfo.serviceState);
+    }   
+
+    setRmRequest(&requestInfo, Rm_service_RESOURCE_ALLOCATE_USE, resourceNameGpQ, 
+                 7005, 25, 0, NULL, FALSE, &responseInfo);     
+    rmCdServiceHandle->Rm_serviceHandler(rmCdServiceHandle->rmHandle, &requestInfo, &responseInfo);   
+    System_printf("Core %d : %s use allocation (without callback specified) of %s %d - %d : ", coreNum,
+                                                                                               rmCdName,
+                                                                                               resourceNameGpQ,
+                                                                                               requestInfo.resourceBase, 
+                                                                                               (requestInfo.resourceBase + requestInfo.resourceLength - 1));
     if (responseInfo.serviceState == RM_SERVICE_APPROVED) {
         System_printf("PASSED\n");
     }
     else {
         System_printf("FAILED : denial or error : %d\n", responseInfo.serviceState);
-    }      
+    }
+    
+    setRmRequest(&requestInfo, Rm_service_RESOURCE_ALLOCATE_USE, resourceNameGpQ, 
+                 7010, 5, 0, NULL, FALSE, &responseInfo);     
+    rmClientServiceHandle->Rm_serviceHandler(rmClientServiceHandle->rmHandle, &requestInfo, &responseInfo);   
+    System_printf("Core %d : %s use allocation (without callback specified) of %s %d - %d : ", coreNum,
+                                                                                               rmClientName,
+                                                                                               resourceNameGpQ,
+                                                                                               requestInfo.resourceBase, 
+                                                                                               (requestInfo.resourceBase + requestInfo.resourceLength - 1));
+    if (responseInfo.serviceState == RM_SERVICE_APPROVED) {
+        System_printf("PASSED\n");
+    }
+    else {
+        System_printf("FAILED : denial or error : %d\n", responseInfo.serviceState);
+    }
+
+    /* Init allocation of resource already owned by Client should return approved and the resource should
+     * only be shown as allocated once to the instance in the resource print out */
+    setRmRequest(&requestInfo, Rm_service_RESOURCE_ALLOCATE_INIT, resourceNameGpQ, 
+                 7011, 1, 0, NULL, FALSE, &responseInfo);     
+    rmClientServiceHandle->Rm_serviceHandler(rmClientServiceHandle->rmHandle, &requestInfo, &responseInfo);   
+    System_printf("Core %d : %s use allocation (without callback specified) of %s %d - %d : ", coreNum,
+                                                                                               rmClientName,
+                                                                                               resourceNameGpQ,
+                                                                                               requestInfo.resourceBase, 
+                                                                                               (requestInfo.resourceBase + requestInfo.resourceLength - 1));
+    if (responseInfo.serviceState == RM_SERVICE_APPROVED) {
+        System_printf("PASSED\n");
+    }
+    else {
+        System_printf("FAILED : denial or error : %d\n", responseInfo.serviceState);
+    }
+    /* END Allocating some resources without providing a callback function.  RM should block and not return until the result
+     * is returned by the server. */    
 
     GateMP_leave(gateHandle, gateKey);           
 
@@ -1037,13 +1083,7 @@ void rmStartupTsk(UArg arg0, UArg arg1)
     /* Initialize the transport map */
     for (i = 0; i < MAX_MAPPING_ENTRIES; i++) {
         rmTransportMap[i].transportHandle = NULL;
-    }
-
-    /* Create the gate internal to RM for service requests not specifying a callback function
-     * and needing a blocking operation to complete.
-     *
-     * Must be created from a different task than the test tasks to allow proper blocking. */
-    Osal_rmLocalGateInit();  
+    } 
 
     if (coreNum == 0) {
         GateMP_Params_init(&gateParams);