Test: addition of TEST_TYPE_6 to CORE_TEST_INTERACTIVE suite

-- A new test scenario is added to CORE_TEST_INTERACTIVE test
   suite to highlight the effects of TFM Core prioritization
   on the NS world behaviour.
-- Fixes a problem with CORE_TEST_INTERACTIVE specific test
   code throwing a warning treated as error which results in
   build failure.

Change-Id: Iab27d715129ea10dc6c882b817d8cb8a19bb736a
Signed-off-by: Antonio de Angelis <antonio.deangelis@arm.com>
diff --git a/app/tfm_integ_test.c b/app/tfm_integ_test.c
index 5509af7..4ddf082 100644
--- a/app/tfm_integ_test.c
+++ b/app/tfm_integ_test.c
@@ -84,6 +84,11 @@
     TEST_TYPE_5,     /*!< non-NS lock, core locked: high priority tries to
                           overcome the NS lock but finds TFM core locked by
                           lower priority task and fails */
+    TEST_TYPE_6      /*!< Like TEST_TYPE_2, but the high priority task has now a
+                          timeout to acquire the NS lock. The timeout will
+                          expire only if TFM Core is built with the
+                          de-prioritization disabled (i.e. TFM_API_SVCCLEAR
+                          defined) */
 };
 
 static const osThreadAttr_t tattr_seq = {
@@ -139,13 +144,26 @@
 }
 
 /**
+ * \brief TFM NS lock options
+ *
+ * \details Options used while acquiring the NS lock
+ */
+struct tfm_ns_lock_options
+{
+    bool use_ns_lock;
+    uint32_t timeout;
+};
+
+/**
  * \brief tfm_service_request
  *
  * \details This function is used to request a TFM
  *          service in handler mode, using SVC.
- *          Optionally uses the NS lock
+ *          Optionally uses the NS lock and specifies
+ *          a timeout for obtaining the NS lock
  */
-static void tfm_service_request(enum tfm_svc_num svc_num, bool use_ns_lock)
+static void tfm_service_request(enum tfm_svc_num svc_num,
+                                struct tfm_ns_lock_options *ns_lock_options_p)
 {
     osStatus_t result;
 
@@ -160,23 +178,47 @@
 
     LOG_MSG_THREAD("Trying to acquire the TFM core from NS");
 
-    if (use_ns_lock) {
+    if (ns_lock_options_p->use_ns_lock) {
         result = osMutexAcquire(mutex_id,0);
         if (result == osOK) {
             LOG_MSG_THREAD("NS Lock: acquired");
+            /* Add a delay here just to let the pri_task try to
+             * acquire the NS lock before seq_task enters secure world
+             */
+            if (!strcmp(osThreadGetName(osThreadGetId()),"seq_task")) {
+                osDelay(100U);
+            }
             svc_dispatch(svc_num);
             LOG_MSG_THREAD("NS Lock: releasing...");
             osMutexRelease(mutex_id);
         } else {
-            LOG_MSG_THREAD("Failed to acquire the NS lock");
 
-            osMutexAcquire(mutex_id,osWaitForever);
-            LOG_MSG_THREAD("NS Lock: acquired");
-            svc_dispatch(svc_num);
-            LOG_MSG_THREAD("NS Lock: releasing...");
-            osMutexRelease(mutex_id);
+            if (ns_lock_options_p->timeout == osWaitForever) {
+                LOG_MSG_THREAD("Failed to acquire NS lock, keep waiting");
+            } else {
+                LOG_MSG_THREAD("Failed to acquire NS lock, wait with timeout");
+            }
+
+            result = osMutexAcquire(mutex_id,ns_lock_options_p->timeout);
+            if (result == osOK) {
+                LOG_MSG_THREAD("NS Lock: acquired");
+                svc_dispatch(svc_num);
+                LOG_MSG_THREAD("NS Lock: releasing...");
+                osMutexRelease(mutex_id);
+            } else if (result == osErrorTimeout) {
+                LOG_MSG_THREAD("NS Lock: failed to acquire, timeout expired");
+            } else {
+                LOG_MSG_THREAD("NS Lock: unexpected failure trying to acquire");
+            }
         }
     } else {
+        /* Add a delay here to let the seq_task (which always uses the NS lock)
+         * enter secure world before the pri_task (which can try to overcome the
+         * NS lock in test scenario 5)
+         */
+        if (!strcmp(osThreadGetName(osThreadGetId()),"pri_task")) {
+            osDelay(100U);
+        }
         svc_dispatch(svc_num);
     }
 }
@@ -227,7 +269,8 @@
     osDelay(100U);
 
     /* After wake up, try to get hold of the NS lock */
-    tfm_service_request(SVC_SECURE_DECREMENT_NS_LOCK_2, *((bool *)argument));
+    tfm_service_request(SVC_SECURE_DECREMENT_NS_LOCK_2,
+                            (struct tfm_ns_lock_options *)argument);
 
     osThreadExit();
 }
@@ -240,40 +283,43 @@
 static void seq_task(void *argument)
 {
     osThreadId_t thread_id, thread_id_mid;
-    bool use_ns_lock, use_ns_lock_pri;
     enum test_type test_type;
 
+    /* By default, use NS lock and wait forever if busy, i.e. until unblocked */
+    struct tfm_ns_lock_options ns_lock_opt =
+                                  {.use_ns_lock=true, .timeout=osWaitForever};
+    struct tfm_ns_lock_options ns_lock_opt_pri =
+                                  {.use_ns_lock=true, .timeout=osWaitForever};
+
     test_type = *((enum test_type *)argument);
 
     if (test_type == TEST_TYPE_1) {
         LOG_MSG("Scenario 1 - Sequential");
-        use_ns_lock = true;
     } else if (test_type == TEST_TYPE_2) {
         LOG_MSG("Scenario 2 - Priority");
-        use_ns_lock = true;
-        use_ns_lock_pri = true;
-        thread_id = osThreadNew(pri_task, &use_ns_lock_pri, &tattr_pri);
+        thread_id = osThreadNew(pri_task, &ns_lock_opt_pri, &tattr_pri);
     } else if (test_type == TEST_TYPE_3) {
         LOG_MSG("Scenario 3 - Priority inversion");
-        use_ns_lock = true;
-        use_ns_lock_pri = true;
-        thread_id = osThreadNew(pri_task, &use_ns_lock_pri, &tattr_pri);
+        thread_id = osThreadNew(pri_task, &ns_lock_opt_pri, &tattr_pri);
         thread_id_mid = osThreadNew(mid_task, &thread_id, &tattr_mid);
     } else if (test_type == TEST_TYPE_4) {
         LOG_MSG("Scenario 4 - non-NS lock");
-        use_ns_lock = false;
+        ns_lock_opt.use_ns_lock = false;
     } else if (test_type == TEST_TYPE_5) {
         LOG_MSG("Scenario 5 - non-NS lock, core locked");
-        use_ns_lock = true;
-        use_ns_lock_pri = false;
-        thread_id = osThreadNew(pri_task, &use_ns_lock_pri, &tattr_pri);
+        ns_lock_opt_pri.use_ns_lock = false;
+        thread_id = osThreadNew(pri_task, &ns_lock_opt_pri, &tattr_pri);
+    } else if (test_type == TEST_TYPE_6) {
+        LOG_MSG("Scenario 6 - Core prioritization effects on NS world");
+        ns_lock_opt_pri.timeout = 0x10000; /* timed_wait for NS lock */
+        thread_id = osThreadNew(pri_task, &ns_lock_opt_pri, &tattr_pri);
     } else {
         LOG_MSG("Scenario not supported");
         osThreadExit();
     }
 
     /* Try to acquire the NS lock */
-    tfm_service_request(SVC_SECURE_DECREMENT_NS_LOCK_1, use_ns_lock);
+    tfm_service_request(SVC_SECURE_DECREMENT_NS_LOCK_1, &ns_lock_opt);
 
     if (test_type == TEST_TYPE_1) {
         LOG_MSG("Scenario 1 - test finished\n");
@@ -289,6 +335,9 @@
     } else if (test_type == TEST_TYPE_5) {
         osThreadJoin(thread_id);
         LOG_MSG("Scenario 5 - test finished\n");
+    } else if (test_type == TEST_TYPE_6) {
+        osThreadJoin(thread_id);
+        LOG_MSG("Scenario 6 - test finished\n");
     }
 
     osThreadExit();
@@ -306,7 +355,7 @@
 
     /* Test type list */
     enum test_type test_type[] = {TEST_TYPE_1, TEST_TYPE_2, TEST_TYPE_3,
-                                  TEST_TYPE_4, TEST_TYPE_5};
+                                  TEST_TYPE_4, TEST_TYPE_5, TEST_TYPE_6};
 
     /* Create the NS lock -- shared among testing scenarios */
     mutex_id = osMutexNew(&mattr_ns_lock);