[rtems-central commit] spec: Specify signal manager

Sebastian Huber sebh at rtems.org
Fri Feb 19 06:05:32 UTC 2021


Module:    rtems-central
Branch:    master
Commit:    b70d121ac69f6e627481d25ecf7d22eeb690ba0c
Changeset: http://git.rtems.org/rtems-central/commit/?id=b70d121ac69f6e627481d25ecf7d22eeb690ba0c

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Mon Feb 15 14:02:22 2021 +0100

spec: Specify signal manager

---

 spec/rtems/signal/req/catch.yml | 982 ++++++++++++++++++++++++++++++++++++++++
 spec/rtems/signal/req/send.yml  | 647 ++++++++++++++++++++++++++
 2 files changed, 1629 insertions(+)

diff --git a/spec/rtems/signal/req/catch.yml b/spec/rtems/signal/req/catch.yml
new file mode 100644
index 0000000..fb1509c
--- /dev/null
+++ b/spec/rtems/signal/req/catch.yml
@@ -0,0 +1,982 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+enabled-by: true
+functional-type: action
+links:
+- role: interface-function
+  uid: ../if/catch
+post-conditions:
+- name: Status
+  states:
+  - name: Ok
+    test-code: |
+      T_rsc_success( ctx->catch_status );
+    text: |
+      The return status of ${../if/catch:/name} shall be
+      ${../../status/if/successful:/name}.
+  - name: NotImplNoPreempt
+    test-code: |
+      #if defined(RTEMS_SMP)
+      if ( rtems_configuration_get_maximum_processors() > 1 ) {
+        T_rsc( ctx->catch_status, RTEMS_NOT_IMPLEMENTED );
+      } else {
+        T_rsc_success( ctx->catch_status );
+      }
+      #else
+      T_rsc_success( ctx->catch_status );
+      #endif
+    text: |
+      Where the system is configured with SMP support, if the scheduler does
+      not support the no-preempt mode, then the return status of
+      ${../if/catch:/name} shall be ${../../status/if/not-implemented:/name},
+      otherwise the return status shall be ${../../status/if/successful:/name}.
+  - name: NotImplIntLvl
+    test-code: |
+      #if CPU_ENABLE_ROBUST_THREAD_DISPATCH == TRUE
+      T_rsc( ctx->catch_status, RTEMS_NOT_IMPLEMENTED );
+      #elif defined(RTEMS_SMP)
+      if ( rtems_configuration_get_maximum_processors() > 1 ) {
+        T_rsc( ctx->catch_status, RTEMS_NOT_IMPLEMENTED );
+      } else {
+        T_rsc_success( ctx->catch_status );
+      }
+      #else
+      T_rsc_success( ctx->catch_status );
+      #endif
+    text: |
+      Where the system is configured with SMP support and the configured
+      processor maximum is greater than one, or the CPU port enabled robust
+      thread dispatching, the return status of ${../if/catch:/name} shall be
+      ${../../status/if/not-implemented:/name}, otherwise the return status
+      shall be ${../../status/if/successful:/name}.
+  test-epilogue: null
+  test-prologue: null
+- name: Send
+  states:
+  - name: New
+    test-code: |
+      T_rsc_success( ctx->send_status );
+
+      if ( ctx->catch_status == RTEMS_SUCCESSFUL ) {
+        T_eq_u32( ctx->default_handler_calls, 0 );
+        T_eq_u32( ctx->handler_calls, 1 );
+        T_ne_u32( ctx->handler_mode, 0xffffffff );
+      } else {
+        T_eq_u32( ctx->default_handler_calls, 1 );
+        T_eq_u32( ctx->handler_calls, 0 );
+        T_eq_u32( ctx->handler_mode, 0xffffffff );
+      }
+    text: |
+      When a signal set is sent to the caller of ${../if/catch:/name} and the
+      call was successful, the ASR processing shall be done with the specified
+      handler, otherwise the ASR information of the caller shall be unchanged.
+  - name: NotDef
+    test-code: |
+      if ( ctx->catch_status == RTEMS_SUCCESSFUL ) {
+        T_rsc( ctx->send_status, RTEMS_NOT_DEFINED );
+        T_eq_u32( ctx->default_handler_calls, 0 );
+        T_eq_u32( ctx->handler_calls, 0 );
+        T_eq_u32( ctx->handler_mode, 0xffffffff );
+      } else {
+        T_rsc_success( ctx->send_status );
+        T_eq_u32( ctx->default_handler_calls, 1 );
+        T_eq_u32( ctx->handler_calls, 0 );
+        T_eq_u32( ctx->handler_mode, 0xffffffff );
+      }
+    text: |
+      When a signal set is sent to the caller of ${../if/catch:/name} and the
+      call was successful, the ASR processing shall be deactivated and all
+      pending signals shall be cleared, otherwise the ASR information of the
+      caller shall be unchanged.
+  test-epilogue: null
+  test-prologue: null
+- name: Preempt
+  states:
+  - name: 'Yes'
+    test-code: |
+      CheckHandlerMode( ctx, RTEMS_PREEMPT_MASK, RTEMS_PREEMPT );
+    text: |
+      When a signal set is sent to the caller of ${../if/catch:/name} and the
+      call with a valid handler was successful, the ASR processing shall be
+      done with preemption enabled.
+  - name: 'No'
+    test-code: |
+      CheckHandlerMode( ctx, RTEMS_PREEMPT_MASK, RTEMS_NO_PREEMPT );
+    text: |
+      When a signal set is sent to the caller of ${../if/catch:/name} and the
+      call with a valid handler was successful, the ASR processing shall be
+      done with preemption disabled.
+  test-epilogue: null
+  test-prologue: null
+- name: Timeslice
+  states:
+  - name: 'Yes'
+    test-code: |
+      CheckHandlerMode( ctx, RTEMS_TIMESLICE_MASK, RTEMS_TIMESLICE );
+    text: |
+      When a signal set is sent to the caller of ${../if/catch:/name} and the
+      call with a valid handler was successful, the ASR processing shall be
+      done with timeslicing enabled.
+  - name: 'No'
+    test-code: |
+      CheckHandlerMode( ctx, RTEMS_TIMESLICE_MASK, RTEMS_NO_TIMESLICE );
+    text: |
+      When a signal set is sent to the caller of ${../if/catch:/name} and the
+      call with a valid handler was successful, the ASR processing shall be
+      done with timeslicing disabled.
+  test-epilogue: null
+  test-prologue: null
+- name: ASR
+  states:
+  - name: 'Yes'
+    test-code: |
+      CheckHandlerMode( ctx, RTEMS_ASR_MASK, RTEMS_ASR );
+    text: |
+      When a signal set is sent to the caller of ${../if/catch:/name} and the
+      call with a valid handler was successful, the ASR processing shall be
+      done with ASR processing enabled.
+  - name: 'No'
+    test-code: |
+      CheckHandlerMode( ctx, RTEMS_ASR_MASK, RTEMS_NO_ASR );
+    text: |
+      When a signal set is sent to the caller of ${../if/catch:/name} and the
+      call with a valid handler was successful, the ASR processing shall be
+      done with ASR processing disabled.
+  test-epilogue: null
+  test-prologue: null
+- name: IntLvl
+  states:
+  - name: Zero
+    test-code: |
+      CheckHandlerMode( ctx, RTEMS_INTERRUPT_MASK, RTEMS_INTERRUPT_LEVEL( 0 ) );
+    text: |
+      When a signal set is sent to the caller of ${../if/catch:/name} and the
+      call with a valid handler was successful, the ASR processing shall be
+      done with interrupts enabled.
+  - name: Positive
+    test-code: |
+      CheckHandlerMode( ctx, RTEMS_INTERRUPT_MASK, RTEMS_INTERRUPT_LEVEL( 1 ) );
+    text: |
+      When a signal set is sent to the caller of ${../if/catch:/name} and the
+      call with a valid handler was successful, the ASR processing shall be
+      done with interrupts disabled according to the specified interrupt level.
+  test-epilogue: null
+  test-prologue: null
+pre-conditions:
+- name: Handler
+  states:
+  - name: Invalid
+    test-code: |
+      ctx->handler = NULL;
+    text: |
+      The ${../if/catch:/params[0]/name} parameter shall be ${/c/if/null:/name}.
+  - name: Valid
+    test-code: |
+      ctx->handler = SignalHandler;
+    text: |
+      The ${../if/catch:/params[0]/name} parameter shall be a valid ASR handler.
+  test-epilogue: null
+  test-prologue: null
+- name: Preempt
+  states:
+  - name: 'Yes'
+    test-code: |
+      #if defined(RTEMS_SMP)
+      if ( rtems_configuration_get_maximum_processors() == 1 ) {
+        ctx->normal_mode |= RTEMS_NO_PREEMPT;
+      }
+      #else
+      ctx->normal_mode |= RTEMS_NO_PREEMPT;
+      #endif
+    text: |
+      The ${../if/catch:/params[1]/name} parameter shall specify that
+      preemption is enabled.
+  - name: 'No'
+    test-code: |
+      ctx->mode |= RTEMS_NO_PREEMPT;
+    text: |
+      The ${../if/catch:/params[1]/name} parameter shall specify that
+      preemption is disabled.
+  test-epilogue: null
+  test-prologue: null
+- name: Timeslice
+  states:
+  - name: 'Yes'
+    test-code: |
+      ctx->mode |= RTEMS_TIMESLICE;
+    text: |
+      The ${../if/catch:/params[1]/name} parameter shall specify that
+      timeslicing is enabled.
+  - name: 'No'
+    test-code: |
+      ctx->normal_mode |= RTEMS_TIMESLICE;
+    text: |
+      The ${../if/catch:/params[1]/name} parameter shall specify that
+      timeslicing is disabled.
+  test-epilogue: null
+  test-prologue: null
+- name: ASR
+  states:
+  - name: 'Yes'
+    test-code: |
+      /* We cannot disable ASR processing at normal task level for this test */
+    text: |
+      The ${../if/catch:/params[1]/name} parameter shall specify that
+      ASR processing is enabled.
+  - name: 'No'
+    test-code: |
+      ctx->mode |= RTEMS_NO_ASR;
+    text: |
+      The ${../if/catch:/params[1]/name} parameter shall specify that
+      ASR processing is disabled.
+  test-epilogue: null
+  test-prologue: null
+- name: IntLvl
+  states:
+  - name: Zero
+    test-code: |
+      #if !defined(RTEMS_SMP) && CPU_ENABLE_ROBUST_THREAD_DISPATCH == FALSE
+      ctx->normal_mode |= RTEMS_INTERRUPT_LEVEL( 1 );
+      #endif
+    text: |
+      The ${../if/catch:/params[1]/name} parameter shall specify an interrupt
+      level of zero.
+  - name: Positive
+    test-code: |
+      ctx->mode |= RTEMS_INTERRUPT_LEVEL( 1 );
+    text: |
+      The ${../if/catch:/params[1]/name} parameter shall specify a positive
+      interrupt level.
+  test-epilogue: null
+  test-prologue: null
+rationale: null
+references: []
+requirement-type: functional
+skip-reasons: {}
+test-action: |
+  rtems_status_code sc;
+  rtems_mode        mode;
+
+  ctx->catch_status = rtems_signal_catch( ctx->handler, ctx->mode );
+
+  sc = rtems_task_mode( ctx->normal_mode, RTEMS_ALL_MODE_MASKS, &mode );
+  T_rsc_success( sc );
+
+  ctx->send_status = rtems_signal_send( RTEMS_SELF, 0xdeadbeef );
+
+  sc = rtems_task_mode( mode, RTEMS_ALL_MODE_MASKS, &mode );
+  T_rsc_success( sc );
+test-brief: null
+test-cleanup: null
+test-context:
+- brief: null
+  description: null
+  member: |
+    uint32_t default_handler_calls
+- brief: null
+  description: null
+  member: |
+    uint32_t handler_calls
+- brief: null
+  description: null
+  member: |
+    rtems_mode handler_mode
+- brief: null
+  description: null
+  member: |
+    rtems_mode normal_mode
+- brief: null
+  description: null
+  member: |
+    rtems_asr_entry handler
+- brief: null
+  description: null
+  member: |
+    rtems_mode mode
+- brief: null
+  description: null
+  member: |
+    rtems_status_code catch_status
+- brief: null
+  description: null
+  member: |
+    rtems_status_code send_status
+test-context-support: null
+test-description: null
+test-header: null
+test-includes:
+- rtems.h
+test-local-includes: []
+test-prepare: |
+  rtems_status_code sc;
+
+  ctx->default_handler_calls = 0;
+  ctx->handler_calls = 0;
+  ctx->handler_mode = 0xffffffff;
+  ctx->normal_mode = RTEMS_DEFAULT_MODES;
+  ctx->handler = NULL;
+  ctx->mode = RTEMS_DEFAULT_MODES;
+
+  sc = rtems_signal_catch( DefaultHandler, RTEMS_NO_ASR );
+  T_rsc_success( sc );
+test-setup: null
+test-stop: null
+test-support: |
+  typedef RtemsSignalReqCatch_Context Context;
+
+  static void DefaultHandler( rtems_signal_set signal_set )
+  {
+    Context *ctx;
+
+    ctx = T_fixture_context();
+    ++ctx->default_handler_calls;
+
+    T_eq_u32( signal_set, 0xdeadbeef );
+  }
+
+  static void SignalHandler( rtems_signal_set signal_set )
+  {
+    Context          *ctx;
+    rtems_status_code sc;
+
+    ctx = T_fixture_context();
+    ++ctx->handler_calls;
+
+    sc = rtems_task_mode(
+      RTEMS_DEFAULT_MODES,
+      RTEMS_CURRENT_MODE,
+      &ctx->handler_mode
+    );
+    T_rsc_success( sc );
+
+    T_eq_u32( signal_set, 0xdeadbeef );
+  }
+
+  static void CheckHandlerMode( Context *ctx, rtems_mode mask, rtems_mode mode )
+  {
+    if ( ctx->catch_status == RTEMS_SUCCESSFUL && ctx->handler != NULL ) {
+      T_ne_u32( ctx->handler_mode, 0xffffffff );
+      T_eq_u32( ctx->handler_mode & mask, mode );
+    }
+  }
+test-target: testsuites/validation/tc-signal-catch.c
+test-teardown:
+  brief: null
+  code: |
+    rtems_status_code sc;
+
+    sc = rtems_signal_catch( NULL, RTEMS_DEFAULT_MODES );
+    T_rsc_success( sc );
+  description: null
+text: ${.:text-template}
+transition-map:
+- enabled-by: true
+  post-conditions:
+    Status: Ok
+    Send: NotDef
+    Preempt: 'Yes'
+    Timeslice: 'Yes'
+    ASR: 'Yes'
+    IntLvl: Zero
+  pre-conditions:
+    Handler:
+    - Invalid
+    Preempt:
+    - 'Yes'
+    Timeslice:
+    - 'Yes'
+    ASR:
+    - 'Yes'
+    IntLvl:
+    - Zero
+- enabled-by: true
+  post-conditions:
+    Status: NotImplIntLvl
+    Send: NotDef
+    Preempt: 'Yes'
+    Timeslice: 'Yes'
+    ASR: 'Yes'
+    IntLvl: Positive
+  pre-conditions:
+    Handler:
+    - Invalid
+    Preempt:
+    - 'Yes'
+    Timeslice:
+    - 'Yes'
+    ASR:
+    - 'Yes'
+    IntLvl:
+    - Positive
+- enabled-by: true
+  post-conditions:
+    Status: Ok
+    Send: NotDef
+    Preempt: 'Yes'
+    Timeslice: 'Yes'
+    ASR: 'No'
+    IntLvl: Zero
+  pre-conditions:
+    Handler:
+    - Invalid
+    Preempt:
+    - 'Yes'
+    Timeslice:
+    - 'Yes'
+    ASR:
+    - 'No'
+    IntLvl:
+    - Zero
+- enabled-by: true
+  post-conditions:
+    Status: NotImplIntLvl
+    Send: NotDef
+    Preempt: 'Yes'
+    Timeslice: 'Yes'
+    ASR: 'No'
+    IntLvl: Positive
+  pre-conditions:
+    Handler:
+    - Invalid
+    Preempt:
+    - 'Yes'
+    Timeslice:
+    - 'Yes'
+    ASR:
+    - 'No'
+    IntLvl:
+    - Positive
+- enabled-by: true
+  post-conditions:
+    Status: Ok
+    Send: NotDef
+    Preempt: 'Yes'
+    Timeslice: 'No'
+    ASR: 'Yes'
+    IntLvl: Zero
+  pre-conditions:
+    Handler:
+    - Invalid
+    Preempt:
+    - 'Yes'
+    Timeslice:
+    - 'No'
+    ASR:
+    - 'Yes'
+    IntLvl:
+    - Zero
+- enabled-by: true
+  post-conditions:
+    Status: NotImplIntLvl
+    Send: NotDef
+    Preempt: 'Yes'
+    Timeslice: 'No'
+    ASR: 'Yes'
+    IntLvl: Positive
+  pre-conditions:
+    Handler:
+    - Invalid
+    Preempt:
+    - 'Yes'
+    Timeslice:
+    - 'No'
+    ASR:
+    - 'Yes'
+    IntLvl:
+    - Positive
+- enabled-by: true
+  post-conditions:
+    Status: Ok
+    Send: NotDef
+    Preempt: 'Yes'
+    Timeslice: 'No'
+    ASR: 'No'
+    IntLvl: Zero
+  pre-conditions:
+    Handler:
+    - Invalid
+    Preempt:
+    - 'Yes'
+    Timeslice:
+    - 'No'
+    ASR:
+    - 'No'
+    IntLvl:
+    - Zero
+- enabled-by: true
+  post-conditions:
+    Status: NotImplIntLvl
+    Send: NotDef
+    Preempt: 'Yes'
+    Timeslice: 'No'
+    ASR: 'No'
+    IntLvl: Positive
+  pre-conditions:
+    Handler:
+    - Invalid
+    Preempt:
+    - 'Yes'
+    Timeslice:
+    - 'No'
+    ASR:
+    - 'No'
+    IntLvl:
+    - Positive
+- enabled-by: true
+  post-conditions:
+    Status: NotImplNoPreempt
+    Send: NotDef
+    Preempt: 'No'
+    Timeslice: 'Yes'
+    ASR: 'Yes'
+    IntLvl: Zero
+  pre-conditions:
+    Handler:
+    - Invalid
+    Preempt:
+    - 'No'
+    Timeslice:
+    - 'Yes'
+    ASR:
+    - 'Yes'
+    IntLvl:
+    - Zero
+- enabled-by: true
+  post-conditions:
+    Status: NotImplIntLvl
+    Send: NotDef
+    Preempt: 'No'
+    Timeslice: 'Yes'
+    ASR: 'Yes'
+    IntLvl: Positive
+  pre-conditions:
+    Handler:
+    - Invalid
+    Preempt:
+    - 'No'
+    Timeslice:
+    - 'Yes'
+    ASR:
+    - 'Yes'
+    IntLvl:
+    - Positive
+- enabled-by: true
+  post-conditions:
+    Status: NotImplNoPreempt
+    Send: NotDef
+    Preempt: 'No'
+    Timeslice: 'Yes'
+    ASR: 'No'
+    IntLvl: Zero
+  pre-conditions:
+    Handler:
+    - Invalid
+    Preempt:
+    - 'No'
+    Timeslice:
+    - 'Yes'
+    ASR:
+    - 'No'
+    IntLvl:
+    - Zero
+- enabled-by: true
+  post-conditions:
+    Status: NotImplIntLvl
+    Send: NotDef
+    Preempt: 'No'
+    Timeslice: 'Yes'
+    ASR: 'No'
+    IntLvl: Positive
+  pre-conditions:
+    Handler:
+    - Invalid
+    Preempt:
+    - 'No'
+    Timeslice:
+    - 'Yes'
+    ASR:
+    - 'No'
+    IntLvl:
+    - Positive
+- enabled-by: true
+  post-conditions:
+    Status: NotImplNoPreempt
+    Send: NotDef
+    Preempt: 'No'
+    Timeslice: 'No'
+    ASR: 'Yes'
+    IntLvl: Zero
+  pre-conditions:
+    Handler:
+    - Invalid
+    Preempt:
+    - 'No'
+    Timeslice:
+    - 'No'
+    ASR:
+    - 'Yes'
+    IntLvl:
+    - Zero
+- enabled-by: true
+  post-conditions:
+    Status: NotImplIntLvl
+    Send: NotDef
+    Preempt: 'No'
+    Timeslice: 'No'
+    ASR: 'Yes'
+    IntLvl: Positive
+  pre-conditions:
+    Handler:
+    - Invalid
+    Preempt:
+    - 'No'
+    Timeslice:
+    - 'No'
+    ASR:
+    - 'Yes'
+    IntLvl:
+    - Positive
+- enabled-by: true
+  post-conditions:
+    Status: NotImplNoPreempt
+    Send: NotDef
+    Preempt: 'No'
+    Timeslice: 'No'
+    ASR: 'No'
+    IntLvl: Zero
+  pre-conditions:
+    Handler:
+    - Invalid
+    Preempt:
+    - 'No'
+    Timeslice:
+    - 'No'
+    ASR:
+    - 'No'
+    IntLvl:
+    - Zero
+- enabled-by: true
+  post-conditions:
+    Status: NotImplIntLvl
+    Send: NotDef
+    Preempt: 'No'
+    Timeslice: 'No'
+    ASR: 'No'
+    IntLvl: Positive
+  pre-conditions:
+    Handler:
+    - Invalid
+    Preempt:
+    - 'No'
+    Timeslice:
+    - 'No'
+    ASR:
+    - 'No'
+    IntLvl:
+    - Positive
+- enabled-by: true
+  post-conditions:
+    Status: Ok
+    Send: New
+    Preempt: 'Yes'
+    Timeslice: 'Yes'
+    ASR: 'Yes'
+    IntLvl: Zero
+  pre-conditions:
+    Handler:
+    - Valid
+    Preempt:
+    - 'Yes'
+    Timeslice:
+    - 'Yes'
+    ASR:
+    - 'Yes'
+    IntLvl:
+    - Zero
+- enabled-by: true
+  post-conditions:
+    Status: NotImplIntLvl
+    Send: New
+    Preempt: 'Yes'
+    Timeslice: 'Yes'
+    ASR: 'Yes'
+    IntLvl: Positive
+  pre-conditions:
+    Handler:
+    - Valid
+    Preempt:
+    - 'Yes'
+    Timeslice:
+    - 'Yes'
+    ASR:
+    - 'Yes'
+    IntLvl:
+    - Positive
+- enabled-by: true
+  post-conditions:
+    Status: Ok
+    Send: New
+    Preempt: 'Yes'
+    Timeslice: 'Yes'
+    ASR: 'No'
+    IntLvl: Zero
+  pre-conditions:
+    Handler:
+    - Valid
+    Preempt:
+    - 'Yes'
+    Timeslice:
+    - 'Yes'
+    ASR:
+    - 'No'
+    IntLvl:
+    - Zero
+- enabled-by: true
+  post-conditions:
+    Status: NotImplIntLvl
+    Send: New
+    Preempt: 'Yes'
+    Timeslice: 'Yes'
+    ASR: 'No'
+    IntLvl: Positive
+  pre-conditions:
+    Handler:
+    - Valid
+    Preempt:
+    - 'Yes'
+    Timeslice:
+    - 'Yes'
+    ASR:
+    - 'No'
+    IntLvl:
+    - Positive
+- enabled-by: true
+  post-conditions:
+    Status: Ok
+    Send: New
+    Preempt: 'Yes'
+    Timeslice: 'No'
+    ASR: 'Yes'
+    IntLvl: Zero
+  pre-conditions:
+    Handler:
+    - Valid
+    Preempt:
+    - 'Yes'
+    Timeslice:
+    - 'No'
+    ASR:
+    - 'Yes'
+    IntLvl:
+    - Zero
+- enabled-by: true
+  post-conditions:
+    Status: NotImplIntLvl
+    Send: New
+    Preempt: 'Yes'
+    Timeslice: 'No'
+    ASR: 'Yes'
+    IntLvl: Positive
+  pre-conditions:
+    Handler:
+    - Valid
+    Preempt:
+    - 'Yes'
+    Timeslice:
+    - 'No'
+    ASR:
+    - 'Yes'
+    IntLvl:
+    - Positive
+- enabled-by: true
+  post-conditions:
+    Status: Ok
+    Send: New
+    Preempt: 'Yes'
+    Timeslice: 'No'
+    ASR: 'No'
+    IntLvl: Zero
+  pre-conditions:
+    Handler:
+    - Valid
+    Preempt:
+    - 'Yes'
+    Timeslice:
+    - 'No'
+    ASR:
+    - 'No'
+    IntLvl:
+    - Zero
+- enabled-by: true
+  post-conditions:
+    Status: NotImplIntLvl
+    Send: New
+    Preempt: 'Yes'
+    Timeslice: 'No'
+    ASR: 'No'
+    IntLvl: Positive
+  pre-conditions:
+    Handler:
+    - Valid
+    Preempt:
+    - 'Yes'
+    Timeslice:
+    - 'No'
+    ASR:
+    - 'No'
+    IntLvl:
+    - Positive
+- enabled-by: true
+  post-conditions:
+    Status: NotImplNoPreempt
+    Send: New
+    Preempt: 'No'
+    Timeslice: 'Yes'
+    ASR: 'Yes'
+    IntLvl: Zero
+  pre-conditions:
+    Handler:
+    - Valid
+    Preempt:
+    - 'No'
+    Timeslice:
+    - 'Yes'
+    ASR:
+    - 'Yes'
+    IntLvl:
+    - Zero
+- enabled-by: true
+  post-conditions:
+    Status: NotImplIntLvl
+    Send: New
+    Preempt: 'No'
+    Timeslice: 'Yes'
+    ASR: 'Yes'
+    IntLvl: Positive
+  pre-conditions:
+    Handler:
+    - Valid
+    Preempt:
+    - 'No'
+    Timeslice:
+    - 'Yes'
+    ASR:
+    - 'Yes'
+    IntLvl:
+    - Positive
+- enabled-by: true
+  post-conditions:
+    Status: NotImplNoPreempt
+    Send: New
+    Preempt: 'No'
+    Timeslice: 'Yes'
+    ASR: 'No'
+    IntLvl: Zero
+  pre-conditions:
+    Handler:
+    - Valid
+    Preempt:
+    - 'No'
+    Timeslice:
+    - 'Yes'
+    ASR:
+    - 'No'
+    IntLvl:
+    - Zero
+- enabled-by: true
+  post-conditions:
+    Status: NotImplIntLvl
+    Send: New
+    Preempt: 'No'
+    Timeslice: 'Yes'
+    ASR: 'No'
+    IntLvl: Positive
+  pre-conditions:
+    Handler:
+    - Valid
+    Preempt:
+    - 'No'
+    Timeslice:
+    - 'Yes'
+    ASR:
+    - 'No'
+    IntLvl:
+    - Positive
+- enabled-by: true
+  post-conditions:
+    Status: NotImplNoPreempt
+    Send: New
+    Preempt: 'No'
+    Timeslice: 'No'
+    ASR: 'Yes'
+    IntLvl: Zero
+  pre-conditions:
+    Handler:
+    - Valid
+    Preempt:
+    - 'No'
+    Timeslice:
+    - 'No'
+    ASR:
+    - 'Yes'
+    IntLvl:
+    - Zero
+- enabled-by: true
+  post-conditions:
+    Status: NotImplIntLvl
+    Send: New
+    Preempt: 'No'
+    Timeslice: 'No'
+    ASR: 'Yes'
+    IntLvl: Positive
+  pre-conditions:
+    Handler:
+    - Valid
+    Preempt:
+    - 'No'
+    Timeslice:
+    - 'No'
+    ASR:
+    - 'Yes'
+    IntLvl:
+    - Positive
+- enabled-by: true
+  post-conditions:
+    Status: NotImplNoPreempt
+    Send: New
+    Preempt: 'No'
+    Timeslice: 'No'
+    ASR: 'No'
+    IntLvl: Zero
+  pre-conditions:
+    Handler:
+    - Valid
+    Preempt:
+    - 'No'
+    Timeslice:
+    - 'No'
+    ASR:
+    - 'No'
+    IntLvl:
+    - Zero
+- enabled-by: true
+  post-conditions:
+    Status: NotImplIntLvl
+    Send: New
+    Preempt: 'No'
+    Timeslice: 'No'
+    ASR: 'No'
+    IntLvl: Positive
+  pre-conditions:
+    Handler:
+    - Valid
+    Preempt:
+    - 'No'
+    Timeslice:
+    - 'No'
+    ASR:
+    - 'No'
+    IntLvl:
+    - Positive
+type: requirement
diff --git a/spec/rtems/signal/req/send.yml b/spec/rtems/signal/req/send.yml
new file mode 100644
index 0000000..ff74b14
--- /dev/null
+++ b/spec/rtems/signal/req/send.yml
@@ -0,0 +1,647 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+enabled-by: true
+functional-type: action
+links:
+- role: interface-function
+  uid: ../if/send
+post-conditions:
+- name: Status
+  states:
+  - name: Ok
+    test-code: |
+      T_rsc_success( ctx->status );
+    text: |
+      The return status of ${../if/send:/name} shall be
+      ${../../status/if/successful:/name}.
+  - name: InvNum
+    test-code: |
+      T_rsc( ctx->status, RTEMS_INVALID_NUMBER );
+    text: |
+      The return status of ${../if/send:/name} shall be
+      ${../../status/if/invalid-number:/name}.
+  - name: InvId
+    test-code: |
+      T_rsc( ctx->status, RTEMS_INVALID_ID );
+    text: |
+      The return status of ${../if/send:/name} shall be
+      ${../../status/if/invalid-id:/name}.
+  - name: NotDef
+    test-code: |
+      T_rsc( ctx->status, RTEMS_NOT_DEFINED );
+    text: |
+      The return status of ${../if/send:/name} shall be
+      ${../../status/if/not-defined:/name}.
+  test-epilogue: null
+  test-prologue: null
+- name: Handler
+  states:
+  - name: NoCall
+    test-code: |
+      T_eq_sz( ctx->calls_after_send, ctx->nested );
+      T_eq_sz( ctx->calls_after_dispatch, ctx->nested );
+      T_eq_sz( ctx->calls_after_enable, ctx->nested );
+    text: |
+      While the ASR processing is disabled, the ASR handler shall not be
+      called.
+  - name: DuringSend
+    test-code: |
+      ++expected_calls;
+      T_eq_sz( ctx->calls_after_send, ctx->nested + 1 );
+      T_eq_sz( ctx->calls_after_dispatch, ctx->nested + 1 );
+      T_eq_sz( ctx->calls_after_enable, ctx->nested + 1 );
+    text: |
+      The ASR handler shall be called during the ${../if/send:/name} call.
+  - name: AfterDispatch
+    test-code: |
+      ++expected_calls;
+      T_eq_sz( ctx->calls_after_send, ctx->nested );
+      T_eq_sz( ctx->calls_after_dispatch, ctx->nested + 1 );
+      T_eq_sz( ctx->calls_after_enable, ctx->nested + 1 );
+    text: |
+      When the next thread dispatch of the target task of the
+      ${../if/send:/name} call takes place, the ASR handler shall be called.
+  - name: AfterEnable
+    test-code: |
+      ++expected_calls;
+      T_eq_sz( ctx->calls_after_send, ctx->nested );
+      T_eq_sz( ctx->calls_after_dispatch, ctx->nested );
+      T_eq_sz( ctx->calls_after_enable, ctx->nested + 1 );
+    text: |
+      When the target task of the ${../if/send:/name} call re-enables ASR
+      processing, the ASR handler shall be called.
+  test-epilogue: |
+    T_eq_sz( ctx->handler_calls, expected_calls );
+
+    if ( ctx->nested != 0 ) {
+      T_eq_u32( ctx->processed_signal_sets[ 0 ], 0x600df00d );
+    }
+
+    if ( expected_calls > ctx->nested ) {
+      T_eq_u32( ctx->processed_signal_sets[ ctx->nested ], 0xdeadbeef );
+    }
+  test-prologue: |
+    size_t expected_calls;
+
+    expected_calls = ctx->nested;
+- name: Recursive
+  states:
+  - name: 'Yes'
+    test-code: |
+      T_eq_sz( ctx->handler_calls, 2 );
+      T_ne_uptr( ctx->stack_pointers[ 0 ], 0 );
+      T_ne_uptr( ctx->stack_pointers[ 1 ], 0 );
+      T_ne_uptr( ctx->stack_pointers[ 0 ], ctx->stack_pointers[ 1 ] );
+    text: |
+      The ASR handler shall be called recursively.
+  - name: 'No'
+    test-code: |
+      if ( ctx->handler_calls == 2 ) {
+        T_ne_uptr( ctx->stack_pointers[ 0 ], 0 );
+        T_ne_uptr( ctx->stack_pointers[ 1 ], 0 );
+        T_eq_uptr( ctx->stack_pointers[ 0 ], ctx->stack_pointers[ 1 ] );
+      }
+    text: |
+      The ASR handler shall not be called recursively.
+  test-epilogue: null
+  test-prologue: null
+pre-conditions:
+- name: Task
+  states:
+  - name: NoObj
+    test-code: |
+      ctx->id = 0xffffffff;
+    text: |
+      The ${../if/send:/params[0]/name} parameter shall be invalid.
+  - name: Self
+    test-code: |
+      ctx->id = RTEMS_SELF;
+    text: |
+      The ${../if/send:/params[0]/name} parameter shall be associated with
+      the calling task.
+  - name: Other
+    test-code: |
+      ctx->id = ctx->worker_id;
+    text: |
+      The ${../if/send:/params[0]/name} parameter shall be associated with a
+      task other than the calling task.
+  test-epilogue: null
+  test-prologue: null
+- name: Set
+  states:
+  - name: Zero
+    test-code: |
+      ctx->signal_set = 0;
+    text: |
+      The ${../if/send:/params[1]/name} parameter shall be zero.
+  - name: NonZero
+    test-code: |
+      ctx->signal_set = 0xdeadbeef;
+    text: |
+      The ${../if/send:/params[1]/name} parameter shall be non-zero.
+  test-epilogue: null
+  test-prologue: null
+- name: Handler
+  states:
+  - name: Invalid
+    test-code: |
+      ctx->handler = NULL;
+    text: |
+      When the target task has no valid ASR handler installed, the
+      ${../if/send:/name} directive shall be called.
+  - name: Valid
+    test-code: |
+      ctx->handler = SignalHandler;
+    text: |
+      When the target task has a valid ASR handler installed, the
+      ${../if/send:/name} directive shall be called.
+  test-epilogue: null
+  test-prologue: null
+- name: ASR
+  states:
+  - name: Enabled
+    test-code: |
+      ctx->mode = RTEMS_DEFAULT_MODES;
+    text: |
+      When the target task has ASR processing enabled, the ${../if/send:/name}
+      directive shall be called.
+  - name: Disabled
+    test-code: |
+      ctx->mode = RTEMS_NO_ASR;
+    text: |
+      When the target task has ASR processing disabled, the ${../if/send:/name}
+      directive shall be called.
+  test-epilogue: null
+  test-prologue: null
+- name: Nested
+  states:
+  - name: 'Yes'
+    test-code: |
+      ctx->nested = 1;
+    text: |
+      When the target task processes an asynchronous signal set, the
+      ${../if/send:/name} directive shall be called.
+  - name: 'No'
+    test-code: |
+      ctx->nested = 0;
+    text: |
+      When the target task does not process an asynchronous signal set, the
+      ${../if/send:/name} directive shall be called.
+  test-epilogue: null
+  test-prologue: null
+rationale: null
+references: []
+requirement-type: functional
+skip-reasons: {}
+test-action: |
+  rtems_status_code sc;
+
+  if ( ctx->id == ctx->worker_id ) {
+    SendEventsToWorker( ctx, EVENT_START );
+
+    ctx->status = rtems_signal_send( ctx->id, ctx->signal_set );
+    ctx->calls_after_send = ctx->handler_calls;
+
+    SendEventsToWorker( ctx, EVENT_SEND_DONE );
+    ctx->calls_after_dispatch = ctx->handler_calls;
+    SendEventsToWorker( ctx, EVENT_DO_ENABLE );
+    ctx->calls_after_enable = ctx->handler_calls;
+    SendEventsToWorker( ctx, EVENT_END );
+  } else if ( ctx->nested != 0 ) {
+    sc = rtems_signal_catch( SignalHandler, ctx->mode );
+    T_rsc_success( sc );
+
+    sc = rtems_signal_send( RTEMS_SELF, 0x600df00d );
+    T_rsc_success( sc );
+
+    ctx->calls_after_enable = ctx->handler_calls;
+  } else {
+    rtems_mode mode;
+
+    sc = rtems_task_mode( ctx->mode, RTEMS_ASR_MASK, &mode );
+    T_rsc_success( sc );
+
+    sc = rtems_signal_catch( ctx->handler, RTEMS_NO_ASR );
+    T_rsc_success( sc );
+
+    ctx->status = rtems_signal_send( ctx->id, ctx->signal_set );
+    ctx->calls_after_send = ctx->handler_calls;
+    ctx->calls_after_dispatch = ctx->handler_calls;
+
+    sc = rtems_task_mode( mode, RTEMS_ASR_MASK, &mode );
+    T_rsc_success( sc );
+
+    ctx->calls_after_enable = ctx->handler_calls;
+  }
+test-brief: null
+test-cleanup: null
+test-context:
+- brief: null
+  description: null
+  member: |
+    rtems_id runner_id
+- brief: null
+  description: null
+  member: |
+    rtems_id worker_id
+- brief: null
+  description: null
+  member: |
+    rtems_asr_entry handler
+- brief: null
+  description: null
+  member: |
+    size_t nested
+- brief: null
+  description: null
+  member: |
+    size_t handler_calls
+- brief: null
+  description: null
+  member: |
+    size_t calls_after_send
+- brief: null
+  description: null
+  member: |
+    size_t calls_after_dispatch
+- brief: null
+  description: null
+  member: |
+    size_t calls_after_enable
+- brief: null
+  description: null
+  member: |
+    rtems_signal_set processed_signal_sets[ 2 ]
+- brief: null
+  description: null
+  member: |
+    uintptr_t stack_pointers[ 2 ];
+- brief: null
+  description: null
+  member: |
+    rtems_mode mode;
+- brief: null
+  description: null
+  member: |
+    rtems_status_code status
+- brief: null
+  description: null
+  member: |
+    rtems_id id
+- brief: null
+  description: null
+  member: |
+    rtems_signal_set signal_set
+test-context-support: null
+test-description: null
+test-header: null
+test-includes:
+- rtems.h
+test-local-includes: []
+test-prepare: |
+  ctx->handler_calls = 0;
+  ctx->calls_after_send = 0;
+  ctx->calls_after_dispatch = 0;
+  ctx->calls_after_enable = 0;
+  memset( &ctx->processed_signal_sets, 0, sizeof( ctx->processed_signal_sets ) );
+  memset( &ctx->stack_pointers, 0, sizeof( ctx->stack_pointers ) );
+test-setup:
+  brief: null
+  code: |
+    rtems_status_code   sc;
+    rtems_task_priority prio;
+
+    memset( ctx, 0, sizeof( *ctx ) );
+    ctx->runner_id = rtems_task_self();
+
+    prio = 0;
+    sc = rtems_task_set_priority( RTEMS_SELF, PRIO_NORMAL, &prio );
+    T_rsc_success( sc );
+    T_eq_u32( prio, PRIO_HIGH );
+
+    sc = rtems_task_create(
+      rtems_build_name( 'W', 'O', 'R', 'K' ),
+      PRIO_HIGH,
+      RTEMS_MINIMUM_STACK_SIZE,
+      RTEMS_DEFAULT_MODES,
+      RTEMS_DEFAULT_ATTRIBUTES,
+      &ctx->worker_id
+    );
+    T_assert_rsc_success( sc );
+
+    #if defined(RTEMS_SMP)
+    if ( rtems_scheduler_get_processor_maximum() > 1 ) {
+      rtems_id scheduler_id;
+
+      sc = rtems_scheduler_ident_by_processor( 1, &scheduler_id );
+      T_assert_rsc_success( sc );
+
+      sc = rtems_task_set_scheduler( ctx->worker_id, scheduler_id, PRIO_HIGH );
+      T_assert_rsc_success( sc );
+    }
+    #endif
+
+    sc = rtems_task_start( ctx->worker_id, Worker, (rtems_task_argument) ctx );
+    T_assert_rsc_success( sc );
+  description: null
+test-stop: null
+test-support: |
+  #define EVENT_START RTEMS_EVENT_0
+
+  #define EVENT_SEND_DONE RTEMS_EVENT_1
+
+  #define EVENT_DO_ENABLE RTEMS_EVENT_2
+
+  #define EVENT_END RTEMS_EVENT_3
+
+  #define EVENT_WORKER_DONE RTEMS_EVENT_4
+
+  typedef RtemsSignalReqSend_Context Context;
+
+  typedef enum {
+    PRIO_HIGH = 1,
+    PRIO_NORMAL
+  } Priorities;
+
+  static rtems_event_set Wait( void )
+  {
+    rtems_status_code sc;
+    rtems_event_set   events;
+
+    events = 0;
+    sc = rtems_event_receive(
+      RTEMS_ALL_EVENTS,
+      RTEMS_EVENT_ANY | RTEMS_WAIT,
+      RTEMS_NO_TIMEOUT,
+      &events
+    );
+    T_rsc_success( sc );
+
+    return events;
+  }
+
+  static void SendEvents( rtems_id id, rtems_event_set events )
+  {
+    rtems_status_code sc;
+
+    sc = rtems_event_send( id, events );
+    T_rsc_success( sc );
+  }
+
+  static void WorkerDone( const Context *ctx )
+  {
+  #if defined(RTEMS_SMP)
+    if ( rtems_scheduler_get_processor_maximum() > 1 ) {
+      SendEvents( ctx->runner_id, EVENT_WORKER_DONE );
+    }
+  #endif
+  }
+
+  static void SendEventsToWorker( const Context *ctx, rtems_event_set events )
+  {
+    SendEvents( ctx->worker_id, events );
+
+  #if defined(RTEMS_SMP)
+    if ( rtems_scheduler_get_processor_maximum() > 1 ) {
+      events = Wait();
+      T_eq_u32( events, EVENT_WORKER_DONE );
+    }
+  #endif
+  }
+
+  static void SignalHandler( rtems_signal_set signal_set )
+  {
+    Context *ctx;
+    size_t   i;
+    size_t   n;
+
+    ctx = T_fixture_context();
+    i = ctx->handler_calls;
+    n = RTEMS_ARRAY_SIZE( ctx->processed_signal_sets );
+    ctx->processed_signal_sets[ i % n ] = signal_set;
+    ctx->stack_pointers[ i % n ] = (uintptr_t) __builtin_frame_address( 0 );
+    T_lt_sz( i, n );
+    ctx->handler_calls = i + 1;
+
+    if ( ctx->nested != 0 && i == 0 ) {
+      rtems_status_code sc;
+
+      if ( ctx->id == ctx->worker_id ) {
+        rtems_event_set events;
+
+        sc = rtems_signal_catch( ctx->handler, RTEMS_NO_ASR );
+        T_rsc_success( sc );
+
+        WorkerDone( ctx );
+
+        events = Wait();
+        T_eq_u32( events, EVENT_SEND_DONE );
+
+        WorkerDone( ctx );
+
+        events = Wait();
+        T_eq_u32( events, EVENT_DO_ENABLE );
+      } else {
+        sc = rtems_signal_catch( ctx->handler, RTEMS_NO_ASR );
+        T_rsc_success( sc );
+
+        ctx->status = rtems_signal_send( ctx->id, ctx->signal_set );
+        ctx->calls_after_send = ctx->handler_calls;
+        ctx->calls_after_dispatch = ctx->handler_calls;
+      }
+    }
+  }
+
+  static void Worker( rtems_task_argument arg )
+  {
+    Context *ctx;
+
+    ctx = (Context *) arg;
+
+    while ( true ) {
+      rtems_status_code sc;
+      rtems_event_set   events;
+
+      events = Wait();
+      T_eq_u32( events, EVENT_START );
+
+      if ( ctx->nested != 0 ) {
+        sc = rtems_signal_catch( SignalHandler, ctx->mode );
+        T_rsc_success( sc );
+
+        sc = rtems_signal_send( RTEMS_SELF, 0x600df00d );
+        T_rsc_success( sc );
+
+        WorkerDone( ctx );
+      } else {
+        rtems_mode mode;
+
+        sc = rtems_task_mode( ctx->mode, RTEMS_ASR_MASK, &mode );
+        T_rsc_success( sc );
+
+        sc = rtems_signal_catch( ctx->handler, RTEMS_NO_ASR );
+        T_rsc_success( sc );
+
+        WorkerDone( ctx );
+
+        events = Wait();
+        T_eq_u32( events, EVENT_SEND_DONE );
+
+        WorkerDone( ctx );
+
+        events = Wait();
+        T_eq_u32( events, EVENT_DO_ENABLE );
+
+        sc = rtems_task_mode( mode, RTEMS_ASR_MASK, &mode );
+        T_rsc_success( sc );
+
+        WorkerDone( ctx );
+      }
+
+      events = Wait();
+      T_eq_u32( events, EVENT_END );
+
+      WorkerDone( ctx );
+    }
+  }
+test-target: testsuites/validation/tc-signal-send.c
+test-teardown:
+  brief: null
+  code: |
+    rtems_status_code   sc;
+    rtems_task_priority prio;
+
+    prio = 0;
+    sc = rtems_task_set_priority( RTEMS_SELF, PRIO_HIGH, &prio );
+    T_rsc_success( sc );
+    T_eq_u32( prio, PRIO_NORMAL );
+
+    if ( ctx->worker_id != 0 ) {
+      sc = rtems_task_delete( ctx->worker_id );
+      T_rsc_success( sc );
+    }
+  description: null
+text: ${.:text-template}
+transition-map:
+- enabled-by: true
+  post-conditions:
+    Status: InvNum
+    Handler: NoCall
+    Recursive: 'No'
+  pre-conditions:
+    Task: all
+    Set:
+    - Zero
+    Handler: all
+    ASR: all
+    Nested: all
+- enabled-by: true
+  post-conditions:
+    Status: InvId
+    Handler: NoCall
+    Recursive: 'No'
+  pre-conditions:
+    Task:
+    - NoObj
+    Set:
+    - NonZero
+    Handler: all
+    ASR: all
+    Nested: all
+- enabled-by: true
+  post-conditions:
+    Status: NotDef
+    Handler: NoCall
+    Recursive: 'No'
+  pre-conditions:
+    Task:
+    - Self
+    - Other
+    Set:
+    - NonZero
+    Handler:
+    - Invalid
+    ASR: all
+    Nested: all
+- enabled-by: true
+  post-conditions:
+    Status: Ok
+    Handler: AfterEnable
+    Recursive: 'No'
+  pre-conditions:
+    Task:
+    - Self
+    - Other
+    Set:
+    - NonZero
+    Handler:
+    - Valid
+    ASR:
+    - Disabled
+    Nested: all
+- enabled-by: true
+  post-conditions:
+    Status: Ok
+    Handler: DuringSend
+    Recursive: 'No'
+  pre-conditions:
+    Task:
+    - Self
+    Set:
+    - NonZero
+    Handler:
+    - Valid
+    ASR:
+    - Enabled
+    Nested:
+    - 'No'
+- enabled-by: true
+  post-conditions:
+    Status: Ok
+    Handler: AfterDispatch
+    Recursive: 'No'
+  pre-conditions:
+    Task:
+    - Other
+    Set:
+    - NonZero
+    Handler:
+    - Valid
+    ASR:
+    - Enabled
+    Nested:
+    - 'No'
+- enabled-by: true
+  post-conditions:
+    Status: Ok
+    Handler: DuringSend
+    Recursive: 'Yes'
+  pre-conditions:
+    Task:
+    - Self
+    Set:
+    - NonZero
+    Handler:
+    - Valid
+    ASR:
+    - Enabled
+    Nested:
+    - 'Yes'
+- enabled-by: true
+  post-conditions:
+    Status: Ok
+    Handler: AfterDispatch
+    Recursive: 'Yes'
+  pre-conditions:
+    Task:
+    - Other
+    Set:
+    - NonZero
+    Handler:
+    - Valid
+    ASR:
+    - Enabled
+    Nested:
+    - 'Yes'
+type: requirement



More information about the vc mailing list