SPM: Add STATUS_NEED_SCHEDULE to manage scheduler

THRD_EXPECTING_SCHEDULE() calls thrd_next() to decide whether
scheduling is required and when it is required, PendSV will
call thrd_next() again in ipc_schedule(). This duplicated
call of thrd_next() can be avoided by returning a status of
STATUS_NEED_SCHDULABLE from backend in these locations:

 - SVC_Handler
 - SPM cross API
 - Interrupt handler

Signed-off-by: Jianliang Shen <jianliang.shen@arm.com>
Change-Id: I3f1fccbb045938624089e856b5a98c3365c76fcc
diff --git a/secure_fw/spm/ffm/backend_ipc.c b/secure_fw/spm/ffm/backend_ipc.c
index fe6e2c3..07b01f5 100644
--- a/secure_fw/spm/ffm/backend_ipc.c
+++ b/secure_fw/spm/ffm/backend_ipc.c
@@ -26,6 +26,7 @@
 #include "load/service_defs.h"
 #include "load/spm_load_api.h"
 #include "psa/error.h"
+#include "internal_status_code.h"
 
 /* Declare the global component list */
 struct partition_head_t partition_listhead;
@@ -151,6 +152,7 @@
 {
     struct partition_t *p_owner = NULL;
     psa_signal_t signal = 0;
+    psa_status_t ret = PSA_SUCCESS;
 
     if (!handle || !service || !service->p_ldinf || !service->partition) {
         return PSA_ERROR_PROGRAMMER_ERROR;
@@ -162,7 +164,7 @@
     UNI_LIST_INSERT_AFTER(p_owner, handle, p_handles);
 
     /* Messages put. Update signals */
-    backend_assert_signal(p_owner, signal);
+    ret = backend_assert_signal(p_owner, signal);
 
     /*
      * If it is a NS request via RPC, it is unnecessary to block current
@@ -170,12 +172,14 @@
      */
 
     if (!is_tfm_rpc_msg(handle)) {
-        backend_wait_signals(handle->p_client, TFM_IPC_REPLY_SIGNAL);
+        ret = backend_wait_signals(handle->p_client, TFM_IPC_REPLY_SIGNAL);
+    } else {
+        ret = PSA_SUCCESS;
     }
 
     handle->status = TFM_HANDLE_STATUS_ACTIVE;
 
-    return PSA_SUCCESS;
+    return ret;
 }
 
 psa_status_t backend_replying(struct connection_t *handle, int32_t status)
@@ -184,7 +188,7 @@
         tfm_rpc_client_call_reply(handle, status);
     } else {
         handle->p_client->reply_value = (uintptr_t)status;
-        backend_assert_signal(handle->p_client, TFM_IPC_REPLY_SIGNAL);
+        return backend_assert_signal(handle->p_client, TFM_IPC_REPLY_SIGNAL);
     }
 
     /*
@@ -263,10 +267,10 @@
     return control;
 }
 
-psa_signal_t backend_wait_signals(struct partition_t *p_pt, psa_signal_t signals)
+psa_status_t backend_wait_signals(struct partition_t *p_pt, psa_signal_t signals)
 {
     struct critical_section_t cs_signal = CRITICAL_SECTION_STATIC_INIT;
-    psa_signal_t ret_signal;
+    psa_status_t ret = PSA_SUCCESS;
 
     if (!p_pt) {
         tfm_core_panic();
@@ -274,19 +278,21 @@
 
     CRITICAL_SECTION_ENTER(cs_signal);
 
-    ret_signal = p_pt->signals_asserted & signals;
-    if (ret_signal == 0) {
+    ret = p_pt->signals_asserted & signals;
+    if (ret == 0) {
         p_pt->signals_waiting = signals;
+        ret = STATUS_NEED_SCHEDULE;
     }
 
     CRITICAL_SECTION_LEAVE(cs_signal);
 
-    return ret_signal;
+    return ret;
 }
 
-uint32_t backend_assert_signal(struct partition_t *p_pt, psa_signal_t signal)
+psa_status_t backend_assert_signal(struct partition_t *p_pt, psa_signal_t signal)
 {
     struct critical_section_t cs_signal = CRITICAL_SECTION_STATIC_INIT;
+    psa_status_t ret = PSA_SUCCESS;
 
     if (!p_pt) {
         tfm_core_panic();
@@ -294,9 +300,13 @@
 
     CRITICAL_SECTION_ENTER(cs_signal);
     p_pt->signals_asserted |= signal;
+
+    if (p_pt->signals_asserted & p_pt->signals_waiting) {
+        ret = STATUS_NEED_SCHEDULE;
+    }
     CRITICAL_SECTION_LEAVE(cs_signal);
 
-    return PSA_SUCCESS;
+    return ret;
 }
 
 uint64_t ipc_schedule(void)
diff --git a/secure_fw/spm/ffm/backend_sfn.c b/secure_fw/spm/ffm/backend_sfn.c
index 81e60f5..c9d9d6d 100644
--- a/secure_fw/spm/ffm/backend_sfn.c
+++ b/secure_fw/spm/ffm/backend_sfn.c
@@ -148,7 +148,7 @@
     return EXC_RETURN_THREAD_PSP;
 }
 
-psa_signal_t backend_wait_signals(struct partition_t *p_pt, psa_signal_t signals)
+psa_status_t backend_wait_signals(struct partition_t *p_pt, psa_signal_t signals)
 {
     while (!(p_pt->signals_asserted & signals))
         ;
@@ -156,7 +156,7 @@
     return p_pt->signals_asserted & signals;
 }
 
-uint32_t backend_assert_signal(struct partition_t *p_pt, psa_signal_t signal)
+psa_status_t backend_assert_signal(struct partition_t *p_pt, psa_signal_t signal)
 {
     p_pt->signals_asserted |= signal;
 
diff --git a/secure_fw/spm/ffm/interrupt.c b/secure_fw/spm/ffm/interrupt.c
index 7ec611e..0b5e043 100644
--- a/secure_fw/spm/ffm/interrupt.c
+++ b/secure_fw/spm/ffm/interrupt.c
@@ -21,6 +21,7 @@
 
 #include "load/spm_load_api.h"
 #include "ffm/backend.h"
+#include "internal_status_code.h"
 
 extern uintptr_t spm_boundary;
 
@@ -142,6 +143,7 @@
 {
     psa_flih_result_t flih_result;
     struct partition_t *p_part;
+    psa_status_t ret = 0;
 
     if (!p_pt || !p_ildi) {
         tfm_core_panic();
@@ -175,10 +177,10 @@
     }
 
     if (flih_result == PSA_FLIH_SIGNAL) {
-        backend_assert_signal(p_pt, p_ildi->signal);
+        ret = backend_assert_signal(p_pt, p_ildi->signal);
         /* In SFN backend, there is only one thread, no thread switch. */
 #if CONFIG_TFM_SPM_BACKEND_SFN != 1
-        if (THRD_EXPECTING_SCHEDULE()) {
+        if (ret == STATUS_NEED_SCHEDULE) {
             tfm_arch_trigger_pendsv();
         }
 #endif
diff --git a/secure_fw/spm/ffm/psa_api.c b/secure_fw/spm/ffm/psa_api.c
index 1f1c715..7a46c04 100644
--- a/secure_fw/spm/ffm/psa_api.c
+++ b/secure_fw/spm/ffm/psa_api.c
@@ -530,11 +530,11 @@
 }
 
 #if CONFIG_TFM_DOORBELL_API == 1
-void tfm_spm_partition_psa_notify(int32_t partition_id)
+psa_status_t tfm_spm_partition_psa_notify(int32_t partition_id)
 {
     struct partition_t *p_pt = tfm_spm_get_partition_by_id(partition_id);
 
-    backend_assert_signal(p_pt, PSA_DOORBELL);
+    return backend_assert_signal(p_pt, PSA_DOORBELL);
 }
 
 void tfm_spm_partition_psa_clear(void)