[PATCH 2/3] score: Add Beacon Handler

Sebastian Huber sebastian.huber at embedded-brains.de
Tue Oct 16 14:45:28 UTC 2012


A Beacon is a synchronization primitive which helps to solve simple
request handling by asynchronous mechanisms like interrupts or other
tasks.  The Beacon is available for every task similar to the Events.
---
 cpukit/rtems/Makefile.am                       |    4 +
 cpukit/rtems/include/rtems.h                   |    2 +-
 cpukit/rtems/include/rtems/rtems/beacon.h      |  182 ++++++++++++++++++++++++
 cpukit/rtems/include/rtems/rtems/tasks.h       |    3 +
 cpukit/rtems/preinstall.am                     |    4 +
 cpukit/rtems/src/beacon.c                      |  105 ++++++++++++++
 cpukit/rtems/src/tasks.c                       |    2 +
 cpukit/score/Makefile.am                       |    5 +
 cpukit/score/include/rtems/score/beacon-impl.h |  145 +++++++++++++++++++
 cpukit/score/include/rtems/score/beacon.h      |   50 +++++++
 cpukit/score/include/rtems/score/states.h      |    3 +
 cpukit/score/inline/rtems/score/states.inl     |   15 ++
 cpukit/score/preinstall.am                     |    8 +
 cpukit/score/src/beacon.c                      |   53 +++++++
 doc/ada_user/ada_user.texi                     |    2 +
 doc/user/Makefile.am                           |   12 ++-
 doc/user/beacon.t                              |  107 ++++++++++++++
 doc/user/c_user.texi                           |    2 +
 testsuites/sptests/Makefile.am                 |    1 +
 testsuites/sptests/configure.ac                |    1 +
 testsuites/sptests/spbeacon01/Makefile.am      |   19 +++
 testsuites/sptests/spbeacon01/init.c           |  111 ++++++++++++++
 testsuites/sptests/spbeacon01/spbeacon01.doc   |   13 ++
 testsuites/sptests/spbeacon01/spbeacon01.scn   |    2 +
 24 files changed, 847 insertions(+), 4 deletions(-)
 create mode 100644 cpukit/rtems/include/rtems/rtems/beacon.h
 create mode 100644 cpukit/rtems/src/beacon.c
 create mode 100644 cpukit/score/include/rtems/score/beacon-impl.h
 create mode 100644 cpukit/score/include/rtems/score/beacon.h
 create mode 100644 cpukit/score/src/beacon.c
 create mode 100644 doc/user/beacon.t
 create mode 100644 testsuites/sptests/spbeacon01/Makefile.am
 create mode 100644 testsuites/sptests/spbeacon01/init.c
 create mode 100644 testsuites/sptests/spbeacon01/spbeacon01.doc
 create mode 100644 testsuites/sptests/spbeacon01/spbeacon01.scn

diff --git a/cpukit/rtems/Makefile.am b/cpukit/rtems/Makefile.am
index bbf8611..6fc398c 100644
--- a/cpukit/rtems/Makefile.am
+++ b/cpukit/rtems/Makefile.am
@@ -17,6 +17,7 @@ include_rtems_rtems_HEADERS =
 include_rtems_rtems_HEADERS += include/rtems/rtems/asr.h
 include_rtems_rtems_HEADERS += include/rtems/rtems/attr.h
 include_rtems_rtems_HEADERS += include/rtems/rtems/barrier.h
+include_rtems_rtems_HEADERS += include/rtems/rtems/beacon.h
 include_rtems_rtems_HEADERS += include/rtems/rtems/cache.h
 include_rtems_rtems_HEADERS += include/rtems/rtems/clock.h
 include_rtems_rtems_HEADERS += include/rtems/rtems/config.h
@@ -136,6 +137,9 @@ librtems_a_SOURCES += src/ratemondata.c
 librtems_a_SOURCES += src/intrbody.c
 librtems_a_SOURCES += src/intrcatch.c
 
+## BEACON_C_FILES
+librtems_a_SOURCES += src/beacon.c
+
 ## BARRIER_C_FILES
 librtems_a_SOURCES += src/barrier.c
 librtems_a_SOURCES += src/barriercreate.c
diff --git a/cpukit/rtems/include/rtems.h b/cpukit/rtems/include/rtems.h
index 68c6a0b..653160d 100644
--- a/cpukit/rtems/include/rtems.h
+++ b/cpukit/rtems/include/rtems.h
@@ -60,8 +60,8 @@ extern "C" {
 #include <rtems/rtems/sem.h>
 #include <rtems/rtems/message.h>
 #include <rtems/rtems/event.h>
+#include <rtems/rtems/beacon.h>
 #include <rtems/rtems/signal.h>
-#include <rtems/rtems/event.h>
 #include <rtems/rtems/object.h>
 #include <rtems/rtems/part.h>
 #include <rtems/rtems/region.h>
diff --git a/cpukit/rtems/include/rtems/rtems/beacon.h b/cpukit/rtems/include/rtems/rtems/beacon.h
new file mode 100644
index 0000000..3e8e07c
--- /dev/null
+++ b/cpukit/rtems/include/rtems/rtems/beacon.h
@@ -0,0 +1,182 @@
+/**
+ * @file
+ *
+ * @ingroup ClassicBeacon
+ *
+ * @brief Classic Beacon API.
+ */
+
+/*
+ * Copyright (c) 2012 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Obere Lagerstr. 30
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifndef _RTEMS_RTEMS_BEACON_H
+#define _RTEMS_RTEMS_BEACON_H
+
+#include <rtems.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup ClassicBeacon Beacon
+ *
+ * @ingroup ClassicRTEMS
+ *
+ * A Beacon is a synchronization primitive which helps to solve simple request
+ * handling by asynchronous mechanisms like interrupts or other tasks.  The
+ * Beacon is available for every task similar to the Events.
+ *
+ * @msc
+ *   hscale="1.6";
+ *   M [label="Main Task"], IDLE [label="Idle Task"], IRQ [label="Interrupt Handler"], TIME [label="System Tick Handler"];
+ *   |||;
+ *   --- [label="sequence with request completion"];
+ *   M box M [label="prepare request\nissue request\ncall rtems_beacon_watch()"];
+ *   M=>>IDLE [label="blocking operation"];
+ *   IDLE=>>IRQ [label="request completion event"];
+ *   IRQ box IRQ [label="finish request\ncall rtems_beacon_signal()"];
+ *   IRQ=>>M [label="task is ready again"];
+ *   M box M [label="clean up request\ncall rtems_beacon_clear()"];
+ *   |||;
+ *   --- [label="sequence with early request completion"];
+ *   M box M [label="prepare request\nissue request"];
+ *   M=>>IRQ [label="request completion event"];
+ *   IRQ box IRQ [label="finish request\ncall rtems_beacon_signal()"];
+ *   IRQ=>>M [label="beacon is now signalled"];
+ *   M box M [label="call rtems_beacon_watch()\nclean up request\ncall rtems_beacon_clear()"];
+ *   |||;
+ *   --- [label="sequence with timeout event"];
+ *   M box M [label="prepare request\nissue request\ncall rtems_beacon_watch()"];
+ *   M=>>IDLE [label="blocking operation"];
+ *   IDLE=>>TIME [label="timeout expired"];
+ *   TIME box TIME [label="cancel blocking operation"];
+ *   TIME=>>M [label="task is ready again"];
+ *   M box M [label="cancel request\ncall rtems_beacon_clear()"];
+ * @endmsc
+ *
+ * Suppose you have a task that wants to issue a certain request and then waits
+ * for request completion.  It can create a request structure and store its
+ * task identifier there.  Now it can place the request on a work queue of
+ * another task (or interrupt handler).  Afterwards the task watches for the
+ * beacon to get signalled.  Once the worker task is finished with the request
+ * it can signal the beacon.
+ *
+ * @code
+ * #include <assert.h>
+ * #include <rtems.h>
+ *
+ * typedef struct {
+ *   rtems_id task_id;
+ *   bool work_done;
+ * } request;
+ *
+ * void worker_task(rtems_task_argument arg)
+ * {
+ *   rtems_status_code sc;
+ *   request *req = (request *) arg;
+ *
+ *   req->work_done = true;
+ *
+ *   sc = rtems_beacon_signal(req->task_id);
+ *   assert(sc == RTEMS_SUCCESSFUL);
+ *
+ *   sc = rtems_task_delete(RTEMS_SELF);
+ *   assert(sc == RTEMS_SUCCESSFUL);
+ * }
+ *
+ * void issue_request_and_wait_for_completion(void)
+ * {
+ *   rtems_status_code sc;
+ *   rtems_id id;
+ *   request req;
+ *
+ *   req.task_id = rtems_task_self();
+ *   req.work_done = false;
+ *
+ *   sc = rtems_task_create(
+ *     rtems_build_name('W', 'O', 'R', 'K'),
+ *     1,
+ *     RTEMS_MINIMUM_STACK_SIZE,
+ *     RTEMS_DEFAULT_MODES,
+ *     RTEMS_DEFAULT_ATTRIBUTES,
+ *     &id
+ *   );
+ *   assert(sc == RTEMS_SUCCESSFUL);
+ *
+ *   sc = rtems_task_start(id, worker_task, (rtems_task_argument) &req);
+ *   assert(sc == RTEMS_SUCCESSFUL);
+ *
+ *   sc = rtems_beacon_watch(RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ *   assert(sc == RTEMS_SUCCESSFUL);
+ *
+ *   assert(req.work_done);
+ *
+ *   sc = rtems_beacon_clear();
+ *   assert(sc == RTEMS_SUCCESSFUL);
+ * }
+ * @endcode
+ *
+ * @{
+ */
+
+/**
+ * @brief Clears the beacon of the executing task.
+ *
+ * @retval RTEMS_SUCCESSFUL Operation successful.
+ */
+rtems_status_code rtems_beacon_clear( void );
+
+/**
+ * @brief Signals the beacon of the corresponding task.
+ *
+ * @param[in] task_id Task identifier selecting the beacon.
+ *
+ * @retval RTEMS_SUCCESSFUL Operation successful.
+ * @retval RTEMS_INVALID_ID Invalid task identifier.
+ * @retval RTEMS_ILLEGAL_ON_REMOTE_OBJECT Not implemented on remote objects.
+ */
+rtems_status_code rtems_beacon_signal( rtems_id task_id );
+
+/**
+ * @brief Watches the beacon of the executing task to get signalled.
+ *
+ * After a timeout the request must be cancelled.  The request handler must not
+ * call rtems_beacon_signal() afterwards.
+ *
+ * The beacon must be cleared with rtems_beacon_clear() after request
+ * completion or cancellation.  It is a fatal program error to leave the beacon
+ * in a potentially signalled state.
+ *
+ * @param[in] option_set Supported options are RTEMS_NO_WAIT to not wait for
+ * the signal and RTEMS_WAIT to wait for the signal.
+ * @param[in] ticks If the RTEMS_WAIT option is set, then this is the timeout
+ * in ticks.  Use RTEMS_NO_TIMEOUT to wait forever.
+ *
+ * @retval RTEMS_SUCCESSFUL Operation successful.
+ * @retval RTEMS_UNSATISFIED The beacon is not signalled.
+ * @retval RTEMS_TIMEOUT Operation timed out.  The beacon state is undefined.
+ */
+rtems_status_code rtems_beacon_watch(
+  rtems_option option_set,
+  rtems_interval ticks
+);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _RTEMS_RTEMS_BEACON_H */
diff --git a/cpukit/rtems/include/rtems/rtems/tasks.h b/cpukit/rtems/include/rtems/rtems/tasks.h
index b6f51a1..b14ca92 100644
--- a/cpukit/rtems/include/rtems/rtems/tasks.h
+++ b/cpukit/rtems/include/rtems/rtems/tasks.h
@@ -37,6 +37,7 @@
 #include <rtems/score/object.h>
 #include <rtems/score/states.h>
 #include <rtems/score/thread.h>
+#include <rtems/score/beacon.h>
 #include <rtems/rtems/types.h>
 #include <rtems/rtems/eventset.h>
 #include <rtems/rtems/asr.h>
@@ -216,6 +217,8 @@ typedef struct {
   rtems_event_set          event_condition;
   /** This field contains the Classic API Signal information for this task. */
   ASR_Information          Signal;
+  /** This field contains the Classic API Beacon control for this task. */
+  Beacon_Control           Beacon;
   /**
    *  This field contains the notepads for this task.
    *
diff --git a/cpukit/rtems/preinstall.am b/cpukit/rtems/preinstall.am
index c91e508..be266b7 100644
--- a/cpukit/rtems/preinstall.am
+++ b/cpukit/rtems/preinstall.am
@@ -39,6 +39,10 @@ $(PROJECT_INCLUDE)/rtems/rtems/barrier.h: include/rtems/rtems/barrier.h $(PROJEC
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/barrier.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/barrier.h
 
+$(PROJECT_INCLUDE)/rtems/rtems/beacon.h: include/rtems/rtems/beacon.h $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/beacon.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/beacon.h
+
 $(PROJECT_INCLUDE)/rtems/rtems/cache.h: include/rtems/rtems/cache.h $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/cache.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/cache.h
diff --git a/cpukit/rtems/src/beacon.c b/cpukit/rtems/src/beacon.c
new file mode 100644
index 0000000..ed6a7c9
--- /dev/null
+++ b/cpukit/rtems/src/beacon.c
@@ -0,0 +1,105 @@
+/**
+ * @file
+ *
+ * @ingroup ClassicBeacon
+ *
+ * @brief Classic Beacon implementation.
+ */
+
+/*
+ * Copyright (c) 2012 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Obere Lagerstr. 30
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <rtems/rtems/beacon.h>
+#include <rtems/rtems/tasks.h>
+#include <rtems/score/beacon-impl.h>
+
+RTEMS_STATIC_ASSERT(
+  (uint32_t) RTEMS_SUCCESSFUL == (uint32_t) BEACON_STATUS_SUCCESSFUL,
+  beacon_status_successful
+);
+
+RTEMS_STATIC_ASSERT(
+  (uint32_t) RTEMS_TIMEOUT == (uint32_t) BEACON_STATUS_TIMEOUT,
+  beacon_status_timeout
+);
+
+RTEMS_STATIC_ASSERT(
+  (uint32_t) RTEMS_UNSATISFIED == (uint32_t) BEACON_STATUS_UNSATISFIED,
+  beacon_status_unsatisfied
+);
+
+static rtems_status_code translate_beacon_status_code( Beacon_Status status )
+{
+  return (rtems_status_code) status;
+}
+
+rtems_status_code rtems_beacon_clear( void )
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+  Thread_Control *executing = _Thread_Executing;
+  RTEMS_API_Control *api = executing->API_Extensions[ THREAD_API_RTEMS ];
+
+  _Beacon_Initialize( &api->Beacon );
+
+  return sc;
+}
+
+rtems_status_code rtems_beacon_signal( rtems_id task_id )
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+  Objects_Locations location;
+  Thread_Control *thread;
+  RTEMS_API_Control *api;
+
+  thread = _Thread_Get( task_id, &location );
+
+  switch ( location ) {
+    case OBJECTS_LOCAL:
+      api = thread->API_Extensions[ THREAD_API_RTEMS ];
+      _Beacon_Signal( thread, &api->Beacon );
+      break;
+#ifdef RTEMS_MULTIPROCESSING
+    case OBJECTS_REMOTE:
+      sc = RTEMS_ILLEGAL_ON_REMOTE_OBJECT;
+      break;
+#endif
+    default:
+      sc = RTEMS_INVALID_ID;
+      break;
+  }
+
+  _Thread_Enable_dispatch();
+
+  return sc;
+}
+
+rtems_status_code rtems_beacon_watch(
+  rtems_option option_set,
+  rtems_interval ticks
+)
+{
+  Thread_Control *executing = _Thread_Executing;
+  RTEMS_API_Control *api = executing->API_Extensions[ THREAD_API_RTEMS ];
+
+  _Thread_Disable_dispatch();
+  _Beacon_Watch(
+    !_Options_Is_no_wait( option_set ),
+    ticks,
+    executing,
+    &api->Beacon
+  );
+  _Thread_Enable_dispatch();
+
+  return translate_beacon_status_code( executing->Wait.return_code );
+}
diff --git a/cpukit/rtems/src/tasks.c b/cpukit/rtems/src/tasks.c
index 663a02c..0fb2102 100644
--- a/cpukit/rtems/src/tasks.c
+++ b/cpukit/rtems/src/tasks.c
@@ -29,6 +29,7 @@
 #include <rtems/score/wkspace.h>
 #include <rtems/score/apiext.h>
 #include <rtems/score/sysstate.h>
+#include <rtems/score/beacon-impl.h>
 
 /*
  *  _RTEMS_tasks_Create_extension
@@ -67,6 +68,7 @@ static bool _RTEMS_tasks_Create_extension(
   api->pending_events = EVENT_SETS_NONE_PENDING;
   api->event_condition = 0;
   _ASR_Initialize( &api->Signal );
+  _Beacon_Initialize( &api->Beacon );
   created->task_variables = NULL;
 
   if ( rtems_configuration_get_notepads_enabled() ) {
diff --git a/cpukit/score/Makefile.am b/cpukit/score/Makefile.am
index 6f9f94f..282a3c6 100644
--- a/cpukit/score/Makefile.am
+++ b/cpukit/score/Makefile.am
@@ -17,6 +17,8 @@ include_rtems_scoredir = $(includedir)/rtems/score
 include_rtems_score_HEADERS = include/rtems/score/address.h
 include_rtems_score_HEADERS += include/rtems/score/apiext.h
 include_rtems_score_HEADERS += include/rtems/score/apimutex.h
+include_rtems_score_HEADERS += include/rtems/score/beacon.h
+include_rtems_score_HEADERS += include/rtems/score/beacon-impl.h
 include_rtems_score_HEADERS += include/rtems/score/bitfield.h
 include_rtems_score_HEADERS += include/rtems/score/chain.h
 include_rtems_score_HEADERS += include/rtems/score/context.h
@@ -144,6 +146,9 @@ libscore_a_SOURCES += src/apimutex.c src/apimutexallocate.c \
 libscore_a_SOURCES += src/corebarrier.c src/corebarrierrelease.c \
     src/corebarrierwait.c
 
+## BEACON_C_FILES
+libscore_a_SOURCES += src/beacon.c
+
 ## CORE_MESSAGE_QUEUE_C_FILES
 libscore_a_SOURCES += src/coremsg.c src/coremsgbroadcast.c \
     src/coremsgclose.c src/coremsgflush.c src/coremsgflushwait.c \
diff --git a/cpukit/score/include/rtems/score/beacon-impl.h b/cpukit/score/include/rtems/score/beacon-impl.h
new file mode 100644
index 0000000..d60800b
--- /dev/null
+++ b/cpukit/score/include/rtems/score/beacon-impl.h
@@ -0,0 +1,145 @@
+/**
+ * @file
+ *
+ * @ingroup ScoreBeacon
+ *
+ * @brief Beacon Handler implementation API.
+ */
+
+/*
+ * Copyright (c) 2012 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Obere Lagerstr. 30
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifndef _RTEMS_SCORE_BEACON_IMPL_H
+#define _RTEMS_SCORE_BEACON_IMPL_H
+
+#include <rtems/score/beacon.h>
+#include <rtems/score/thread.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @addtogroup ScoreBeacon
+ *
+ * @{
+ */
+
+typedef enum {
+  BEACON_STATUS_SUCCESSFUL = 0,
+  BEACON_STATUS_TIMEOUT = 6,
+  BEACON_STATUS_UNSATISFIED = 13
+} Beacon_Status;
+
+extern Thread_blocking_operation_States _Beacon_Sync_state;
+
+RTEMS_INLINE_ROUTINE void _Beacon_Handler_initialization( void )
+{
+  /* Do nothing */
+}
+
+RTEMS_INLINE_ROUTINE void _Beacon_Initialize( Beacon_Control *beacon )
+{
+  beacon->on_fire = false;
+}
+
+RTEMS_INLINE_ROUTINE void _Beacon_Signal(
+  Thread_Control *thread,
+  Beacon_Control *beacon
+)
+{
+  ISR_Level level;
+
+  beacon->on_fire = true;
+
+  _ISR_Disable( level );
+  if (
+    _Thread_blocking_operation_Is_critical( thread, _Beacon_Sync_state )
+  ) {
+    _Beacon_Sync_state = THREAD_BLOCKING_OPERATION_SATISFIED;
+    _ISR_Enable( level );
+  } else if ( _States_Is_waiting_for_beacon( thread->current_state ) ) {
+    _ISR_Flash( level );
+
+    if ( !_Watchdog_Is_active( &thread->Timer ) ) {
+      _ISR_Enable( level );
+    } else {
+      _Watchdog_Deactivate( &thread->Timer );
+      _ISR_Enable( level );
+      _Watchdog_Remove( &thread->Timer );
+    }
+
+    _Thread_Unblock( thread );
+  } else {
+    _ISR_Enable( level );
+  }
+}
+
+void _Beacon_Timeout( Objects_Id task_id, void *arg );
+
+RTEMS_INLINE_ROUTINE void _Beacon_Watch(
+  bool wait,
+  Watchdog_Interval ticks,
+  Thread_Control *thread,
+  const Beacon_Control *beacon
+)
+{
+  ISR_Level level;
+
+  thread->Wait.return_code = BEACON_STATUS_SUCCESSFUL;
+
+  _ISR_Disable( level );
+  if ( beacon->on_fire ) {
+    _ISR_Enable( level );
+  } else {
+    if ( wait ) {
+      Thread_blocking_operation_States sync_state;
+
+      _Beacon_Sync_state = THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED;
+      _ISR_Enable( level );
+
+      if ( ticks > 0) {
+        _Watchdog_Initialize(
+          &thread->Timer,
+          _Beacon_Timeout,
+          thread->Object.id,
+          NULL
+        );
+        _Watchdog_Insert_ticks( &thread->Timer, ticks );
+      }
+
+      _Thread_Set_state( thread, STATES_WAITING_FOR_BEACON );
+
+      _ISR_Disable( level );
+      sync_state = _Beacon_Sync_state;
+      _Beacon_Sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED;
+      if ( sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED ) {
+        _ISR_Enable( level );
+      } else {
+        _Thread_blocking_operation_Cancel( sync_state, thread, level );
+      }
+    } else {
+      _ISR_Enable( level );
+      thread->Wait.return_code = BEACON_STATUS_UNSATISFIED;
+    }
+  }
+}
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _RTEMS_SCORE_BEACON_IMPL_H */
diff --git a/cpukit/score/include/rtems/score/beacon.h b/cpukit/score/include/rtems/score/beacon.h
new file mode 100644
index 0000000..3aaa9c0
--- /dev/null
+++ b/cpukit/score/include/rtems/score/beacon.h
@@ -0,0 +1,50 @@
+/**
+ * @file
+ *
+ * @ingroup ScoreBeacon
+ *
+ * @brief Beacon Handler API.
+ */
+
+/*
+ * Copyright (c) 2012 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Obere Lagerstr. 30
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifndef _RTEMS_SCORE_BEACON_H
+#define _RTEMS_SCORE_BEACON_H
+
+#include <rtems/score/basedefs.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup ScoreBeacon Beacon Handler
+ *
+ * @ingroup Score
+ *
+ * @{
+ */
+
+typedef struct {
+  bool on_fire;
+} Beacon_Control;
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _RTEMS_SCORE_BEACON_H */
diff --git a/cpukit/score/include/rtems/score/states.h b/cpukit/score/include/rtems/score/states.h
index eb4658e..8167356 100644
--- a/cpukit/score/include/rtems/score/states.h
+++ b/cpukit/score/include/rtems/score/states.h
@@ -81,6 +81,8 @@ typedef uint32_t   States_Control;
 #define STATES_WAITING_FOR_BARRIER             0x10000
 /** This macro corresponds to a task waiting for a RWLock. */
 #define STATES_WAITING_FOR_RWLOCK              0x20000
+/** This macro corresponds to a task waiting for a beacon. */
+#define STATES_WAITING_FOR_BEACON              0x40000
 
 /** This macro corresponds to a task which is in an interruptible
  *  blocking state.
@@ -110,6 +112,7 @@ typedef uint32_t   States_Control;
                                  STATES_WAITING_FOR_TIME        | \
                                  STATES_WAITING_FOR_PERIOD      | \
                                  STATES_WAITING_FOR_EVENT       | \
+                                 STATES_WAITING_FOR_BEACON      | \
                                  STATES_WAITING_ON_THREAD_QUEUE | \
                                  STATES_INTERRUPTIBLE_BY_SIGNAL )
 
diff --git a/cpukit/score/inline/rtems/score/states.inl b/cpukit/score/inline/rtems/score/states.inl
index 7bad0c9..e916308 100644
--- a/cpukit/score/inline/rtems/score/states.inl
+++ b/cpukit/score/inline/rtems/score/states.inl
@@ -213,6 +213,21 @@ RTEMS_INLINE_ROUTINE bool _States_Is_waiting_for_event (
 }
 
 /**
+ *  This function returns true if the WAITING_FOR_BEACON state is set in
+ *  the_states, and false otherwise.
+ *
+ *  @param[in] the_states is the task state set to test
+ *
+ *  @return This method returns true if the desired state condition is set.
+ */
+RTEMS_INLINE_ROUTINE bool _States_Is_waiting_for_beacon (
+  States_Control the_states
+)
+{
+   return (the_states & STATES_WAITING_FOR_BEACON);
+}
+
+/**
  *  This function returns true if the WAITING_FOR_MUTEX state
  *  is set in the_states, and false otherwise.
  *
diff --git a/cpukit/score/preinstall.am b/cpukit/score/preinstall.am
index 09c6fa9..e4fa185 100644
--- a/cpukit/score/preinstall.am
+++ b/cpukit/score/preinstall.am
@@ -51,6 +51,14 @@ $(PROJECT_INCLUDE)/rtems/score/apimutex.h: include/rtems/score/apimutex.h $(PROJ
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/apimutex.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/apimutex.h
 
+$(PROJECT_INCLUDE)/rtems/score/beacon.h: include/rtems/score/beacon.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/beacon.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/beacon.h
+
+$(PROJECT_INCLUDE)/rtems/score/beacon-impl.h: include/rtems/score/beacon-impl.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/beacon-impl.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/beacon-impl.h
+
 $(PROJECT_INCLUDE)/rtems/score/bitfield.h: include/rtems/score/bitfield.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/bitfield.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/bitfield.h
diff --git a/cpukit/score/src/beacon.c b/cpukit/score/src/beacon.c
new file mode 100644
index 0000000..530861a
--- /dev/null
+++ b/cpukit/score/src/beacon.c
@@ -0,0 +1,53 @@
+/**
+ * @file
+ *
+ * @ingroup ScoreBeacon
+ *
+ * @brief Beacon Handler implementation.
+ */
+
+/*
+ * Copyright (c) 2012 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Obere Lagerstr. 30
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <rtems/score/beacon-impl.h>
+
+Thread_blocking_operation_States _Beacon_Sync_state;
+
+void _Beacon_Timeout( Objects_Id task_id, void *arg )
+{
+  Objects_Locations location;
+  Thread_Control *thread;
+  ISR_Level level;
+
+  thread = _Thread_Get( task_id, &location );
+
+  switch ( location ) {
+    case OBJECTS_LOCAL:
+      _ISR_Disable( level );
+      if (
+        _Thread_Is_executing( thread )
+          && _Beacon_Sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED
+      ) {
+          _Beacon_Sync_state = THREAD_BLOCKING_OPERATION_TIMEOUT;
+      }
+      thread->Wait.return_code = BEACON_STATUS_TIMEOUT;
+      _ISR_Enable( level );
+      _Thread_Unblock( thread );
+      break;
+    default:
+      break;
+  }
+
+  _Thread_Unnest_dispatch();
+}
diff --git a/doc/ada_user/ada_user.texi b/doc/ada_user/ada_user.texi
index c86b595..028156f 100644
--- a/doc/ada_user/ada_user.texi
+++ b/doc/ada_user/ada_user.texi
@@ -92,6 +92,7 @@
 @include user/sem.texi
 @include user/msg.texi
 @include user/event.texi
+ at include user/beacon.texi
 @include user/signal.texi
 @include user/part.texi
 @include user/region.texi
@@ -131,6 +132,7 @@
 * Semaphore Manager::
 * Message Manager::
 * Event Manager::
+* Beacon Manager::
 * Signal Manager::
 * Partition Manager::
 * Region Manager::
diff --git a/doc/user/Makefile.am b/doc/user/Makefile.am
index ddf2f07..f312b53 100644
--- a/doc/user/Makefile.am
+++ b/doc/user/Makefile.am
@@ -15,7 +15,7 @@ GENERATED_FILES = overview.texi concepts.texi datatypes.texi init.texi \
     signal.texi part.texi region.texi dpmem.texi io.texi fatal.texi \
     schedule.texi rtmon.texi barrier.texi bsp.texi userext.texi conf.texi \
     mp.texi stackchk.texi cpuuse.texi object.texi chains.texi timespec.texi \
-    cbs.texi
+    cbs.texi beacon.texi
 
 COMMON_FILES += $(top_srcdir)/common/cpright.texi
 
@@ -109,10 +109,16 @@ event.texi: event.t
 	$(BMENU2) \
 	-p "Message Manager MESSAGE_QUEUE_FLUSH - Flush all messages on a queue" \
 	    -u "Top" \
+	    -n "Beacon Manager" < $< > $@
+
+beacon.texi: beacon.t
+	$(BMENU2) \
+	    -p "Event Manager EVENT_RECEIVE - Receive event condition" \
+	    -u "Top" \
 	    -n "Signal Manager" < $< > $@
 
 signal.texi: signal.t
-	$(BMENU2) -p "Event Manager EVENT_RECEIVE - Receive event condition" \
+	$(BMENU2) -p "Beacon Manager BEACON_WATCH - Watch a beacon" \
 	    -u "Top" \
 	    -n "Partition Manager" < $< > $@
 
@@ -196,7 +202,7 @@ cbs.texi: cbs.t
 EXTRA_DIST = bsp.t cbs.t clock.t chains.t concepts.t cpuuse.t datatypes.t conf.t \
     dpmem.t event.t fatal.t init.t intr.t io.t mp.t msg.t overview.t \
     part.t region.t rtmon.t sem.t schedule.t signal.t stackchk.t \
-    task.t timer.t userext.t $(TXT_FILES) $(PNG_FILES) $(EPS_IMAGES) \
+    task.t timer.t userext.t beacon.t $(TXT_FILES) $(PNG_FILES) $(EPS_IMAGES) \
     $(noinst_DATA)
 
 CLEANFILES += c_user.info c_user.info-? c_user.info-??
diff --git a/doc/user/beacon.t b/doc/user/beacon.t
new file mode 100644
index 0000000..8afd9cf
--- /dev/null
+++ b/doc/user/beacon.t
@@ -0,0 +1,107 @@
+ at c Copyright (c) 2012 embedded brains GmbH.  All rights reserved.
+
+ at chapter Beacon Manager
+
+ at cindex beacon
+
+ at section Introduction
+
+A beacon is a synchronization primitive which helps to solve simple request
+handling by asynchronous mechanisms like interrupts or other tasks.  The beacon
+is available for every task similar to the event manager.  The directives provided by
+the beacon manager are:
+
+ at itemize @bullet
+ at item @code{@value{DIRPREFIX}beacon_clear} - Clear a beacon
+ at item @code{@value{DIRPREFIX}beacon_signal} - Signal a beacon
+ at item @code{@value{DIRPREFIX}beacon_watch} - Watch a beacon
+ at end itemize
+
+ at section Directives
+
+This section details the beacon manager's directives.
+A subsection is dedicated to each of this manager's directives
+and describes the calling sequence, related constants, usage,
+and status codes.
+
+ at c
+ at c
+ at c
+ at page
+ at subsection BEACON_CLEAR - Clear a beacon
+
+ at cindex clear a beacon
+
+ at subheading CALLING SEQUENCE:
+
+ at ifset is-C
+ at findex rtems_beacon_clear
+ at example
+rtems_status_code rtems_beacon_clear( void );
+ at end example
+ at end ifset
+
+ at subheading DIRECTIVE STATUS CODES:
+
+ at code{@value{RPREFIX}SUCCESSFUL} - Operation successful.
+
+ at subheading DESCRIPTION:
+
+This directive clears a beacon.
+
+ at c
+ at c
+ at c
+ at page
+ at subsection BEACON_SIGNAL - Signal a beacon
+
+ at cindex signal a beacon
+
+ at subheading CALLING SEQUENCE:
+
+ at ifset is-C
+ at findex rtems_beacon_signal
+ at example
+rtems_status_code rtems_beacon_signal( rtems_id task_id );
+ at end example
+ at end ifset
+
+ at subheading DIRECTIVE STATUS CODES:
+
+ at code{@value{RPREFIX}SUCCESSFUL} - Operation successful.@*
+ at code{@value{RPREFIX}INVALID_ID} - Invalid task identifier.@*
+ at code{@value{RPREFIX}ILLEGAL_ON_REMOTE_OBJECT} - Not implemented on remote objects.
+
+ at subheading DESCRIPTION:
+
+This directive signals a beacon.
+
+ at c
+ at c
+ at c
+ at page
+ at subsection BEACON_WATCH - Watch a beacon
+
+ at cindex watch a beacon
+
+ at subheading CALLING SEQUENCE:
+
+ at ifset is-C
+ at findex rtems_beacon_watch
+ at example
+rtems_status_code rtems_beacon_watch(
+  rtems_option option_set,
+  rtems_interval ticks
+);
+ at end example
+ at end ifset
+
+ at subheading DIRECTIVE STATUS CODES:
+
+ at code{@value{RPREFIX}SUCCESSFUL} - Operation successful.@*
+ at code{@value{RPREFIX}UNSATISFIED} - The beacon is not signalled.@*
+ at code{@value{RPREFIX}TIMEOUT} - Operation timed out.  The beacon state is undefined.
+
+ at subheading DESCRIPTION:
+
+This directive watches a beacon.
diff --git a/doc/user/c_user.texi b/doc/user/c_user.texi
index 123ade2..4d8aa81 100644
--- a/doc/user/c_user.texi
+++ b/doc/user/c_user.texi
@@ -94,6 +94,7 @@
 @include barrier.texi
 @include msg.texi
 @include event.texi
+ at include beacon.texi
 @include signal.texi
 @include part.texi
 @include region.texi
@@ -133,6 +134,7 @@
 * Barrier Manager::
 * Message Manager::
 * Event Manager::
+* Beacon Manager::
 * Signal Manager::
 * Partition Manager::
 * Region Manager::
diff --git a/testsuites/sptests/Makefile.am b/testsuites/sptests/Makefile.am
index 479cdf6..cd06657 100644
--- a/testsuites/sptests/Makefile.am
+++ b/testsuites/sptests/Makefile.am
@@ -28,6 +28,7 @@ SUBDIRS = \
     spsimplesched01 spsimplesched02 spsimplesched03 spnsext01 \
     spedfsched01 spedfsched02 spedfsched03 \
     spcbssched01 spcbssched02 spcbssched03 spqreslib sptimespec01
+SUBDIRS += spbeacon01
 
 include $(top_srcdir)/../automake/subdirs.am
 include $(top_srcdir)/../automake/local.am
diff --git a/testsuites/sptests/configure.ac b/testsuites/sptests/configure.ac
index 33a0755..e9a1acf 100644
--- a/testsuites/sptests/configure.ac
+++ b/testsuites/sptests/configure.ac
@@ -27,6 +27,7 @@ AC_CHECK_SIZEOF([time_t])
 
 # Explicitly list all Makefiles here
 AC_CONFIG_FILES([Makefile
+spbeacon01/Makefile
 spintrcritical18/Makefile
 sp01/Makefile
 sp02/Makefile
diff --git a/testsuites/sptests/spbeacon01/Makefile.am b/testsuites/sptests/spbeacon01/Makefile.am
new file mode 100644
index 0000000..55b2cf8
--- /dev/null
+++ b/testsuites/sptests/spbeacon01/Makefile.am
@@ -0,0 +1,19 @@
+rtems_tests_PROGRAMS = spbeacon01
+spbeacon01_SOURCES = init.c
+
+dist_rtems_tests_DATA = spbeacon01.scn spbeacon01.doc
+
+include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP at .cfg
+include $(top_srcdir)/../automake/compile.am
+include $(top_srcdir)/../automake/leaf.am
+
+AM_CPPFLAGS += -I$(top_srcdir)/../support/include
+
+LINK_OBJS = $(spbeacon01_OBJECTS)
+LINK_LIBS = $(spbeacon01_LDLIBS)
+
+spbeacon01$(EXEEXT): $(spbeacon01_OBJECTS) $(spbeacon01_DEPENDENCIES)
+	@rm -f spbeacon01$(EXEEXT)
+	$(make-exe)
+
+include $(top_srcdir)/../automake/local.am
diff --git a/testsuites/sptests/spbeacon01/init.c b/testsuites/sptests/spbeacon01/init.c
new file mode 100644
index 0000000..9ee06f1
--- /dev/null
+++ b/testsuites/sptests/spbeacon01/init.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2012 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Obere Lagerstr. 30
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+  #include "config.h"
+#endif
+
+#include <rtems.h>
+
+#include "tmacros.h"
+
+typedef struct {
+  rtems_id client;
+  bool complete;
+} request;
+
+static void request_handler_task(rtems_task_argument arg)
+{
+  rtems_status_code sc;
+  request *req = (request *) arg;
+
+  req->complete = true;
+
+  sc = rtems_beacon_signal(req->client);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  sc = rtems_task_delete(RTEMS_SELF);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static void test_with_request_handler_task(void)
+{
+  rtems_status_code sc;
+  rtems_id id;
+  request req;
+
+  sc = rtems_beacon_watch(RTEMS_NO_WAIT, 0);
+  rtems_test_assert(sc == RTEMS_UNSATISFIED);
+
+  req.client = rtems_task_self();
+  req.complete = false;
+
+  sc = rtems_task_create(
+    rtems_build_name('B', 'E', 'A', 'C'),
+    1,
+    RTEMS_MINIMUM_STACK_SIZE,
+    RTEMS_DEFAULT_MODES,
+    RTEMS_DEFAULT_ATTRIBUTES,
+    &id
+  );
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  sc = rtems_task_start(id, request_handler_task, (rtems_task_argument) &req);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  sc = rtems_beacon_watch(RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  rtems_test_assert(req.complete);
+
+  sc = rtems_beacon_clear();
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static void test_with_timeout(void)
+{
+  rtems_status_code sc;
+
+  sc = rtems_beacon_watch(RTEMS_NO_WAIT, 0);
+  rtems_test_assert(sc == RTEMS_UNSATISFIED);
+
+  sc = rtems_beacon_watch(RTEMS_WAIT, 1);
+  rtems_test_assert(sc == RTEMS_TIMEOUT);
+
+  sc = rtems_beacon_watch(RTEMS_NO_WAIT, 0);
+  rtems_test_assert(sc == RTEMS_UNSATISFIED);
+}
+
+static void Init(rtems_task_argument arg)
+{
+  puts("\n\n*** TEST SPBEACON 1 ***");
+
+  test_with_request_handler_task();
+  test_with_timeout();
+
+  puts("*** END OF TEST SPBEACON 1 ***");
+
+  rtems_test_exit(0);
+}
+
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+
+#define CONFIGURE_MAXIMUM_TASKS 2
+
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+
+#define CONFIGURE_INIT
+
+#include <rtems/confdefs.h>
diff --git a/testsuites/sptests/spbeacon01/spbeacon01.doc b/testsuites/sptests/spbeacon01/spbeacon01.doc
new file mode 100644
index 0000000..3e0288a
--- /dev/null
+++ b/testsuites/sptests/spbeacon01/spbeacon01.doc
@@ -0,0 +1,13 @@
+This file describes the directives and concepts tested by this test set.
+
+test set name: spbeacon01
+
+directives:
+
+  - rtems_beacon_signal()
+  - rtems_beacon_watch()
+  - rtems_beacon_clear()
+
+concepts:
+
+  Ensure that the Classic Beacon works.
diff --git a/testsuites/sptests/spbeacon01/spbeacon01.scn b/testsuites/sptests/spbeacon01/spbeacon01.scn
new file mode 100644
index 0000000..368d959
--- /dev/null
+++ b/testsuites/sptests/spbeacon01/spbeacon01.scn
@@ -0,0 +1,2 @@
+*** TEST SPBEACON 1 ***
+*** END OF TEST SPBEACON 1 ***
-- 
1.7.7




More information about the devel mailing list