lockup in delta chain using signal timers

Martin Werner martin.werner at aacmicrotec.com
Mon Feb 15 15:53:11 UTC 2016


Hi,

We're seeing an issue in RTEMS where heavy use of signal timers causes
the internal RTEMS delta chain (_Watchdog_Ticks_chain) to end up with a
self-referencing node, which subsequently blocks insertion and locks the
application.

I've cobbled together a testcase[1] based on samples/ticker, and have
seen the issue when running on qemu/i386.

Is this testcase valid, or is the usage of the signal timers here
incorrect?

If it is valid, does anyone have a suggestion as to what may be the core
issue, assuming that the delta chain behaviour is only a symptom?

We originally saw this issue on our custom or1k hardware, where due to
various circumstances it seems much more easy to provoke (there with
only 3 threads), and from there have tracked it back to something which
seems to be non-or1k-specific.

[1] (Also attached since I don't trust our mail server not to mangle
this)
commit e12d669456ebe74a7dee970d1e0e987bdce4c179
Author: Martin Erik Werner <martin.werner at aacmicrotec.com>
Date:   Mon Feb 15 13:49:41 2016 +0100

    Create sigwaitticker sample from ticker template
    
    Create a sample using sigwait often with many threads, attempting to
    reproduce an issue where the Watchdog_Ticks_Chain, ends up with a
    self-referencing node, and thus locks the application.
    
    Compared to ticker:
    * Only print time from first thread
    * Switch to POSIX threading
    * Use sigtimedwait instead of normal timed wait
    * Add print statement on each alarm
    * Set amount of threads to 300

diff --git a/testsuites/samples/Makefile.am b/testsuites/samples/Makefile.am
index 08455d3..fc9ad3c 100644
--- a/testsuites/samples/Makefile.am
+++ b/testsuites/samples/Makefile.am
@@ -1,6 +1,6 @@
 ACLOCAL_AMFLAGS = -I ../aclocal
 
-_SUBDIRS = hello capture ticker base_sp unlimited minimum fileio
+_SUBDIRS = hello capture ticker base_sp unlimited minimum fileio sigwaitticker
 
 if MPTESTS
 ## base_mp is a sample multiprocessing test
diff --git a/testsuites/samples/configure.ac b/testsuites/samples/configure.ac
index 3089e3f..ffff624 100644
--- a/testsuites/samples/configure.ac
+++ b/testsuites/samples/configure.ac
@@ -74,5 +74,6 @@ iostream/Makefile
 cdtest/Makefile
 pppd/Makefile
 capture/Makefile
+sigwaitticker/Makefile
 ])
 AC_OUTPUT
diff --git a/testsuites/samples/sigwaitticker/Makefile.am b/testsuites/samples/sigwaitticker/Makefile.am
new file mode 100644
index 0000000..798e318
--- /dev/null
+++ b/testsuites/samples/sigwaitticker/Makefile.am
@@ -0,0 +1,19 @@
+
+rtems_tests_PROGRAMS = sigwaitticker
+sigwaitticker_SOURCES = init.c tasks.c system.h
+
+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 = $(sigwaitticker_OBJECTS)
+LINK_LIBS = $(sigwaitticker_LDLIBS)
+
+sigwaitticker$(EXEEXT): $(sigwaitticker_OBJECTS) $(sigwaitticker_DEPENDENCIES)
+	@rm -f sigwaitticker$(EXEEXT)
+	$(make-exe)
+
+include $(top_srcdir)/../automake/local.am
diff --git a/testsuites/samples/sigwaitticker/init.c b/testsuites/samples/sigwaitticker/init.c
new file mode 100644
index 0000000..ae56b55
--- /dev/null
+++ b/testsuites/samples/sigwaitticker/init.c
@@ -0,0 +1,55 @@
+/*
+ *  COPYRIGHT (c) 1989-2012.
+ *  On-Line Applications Research Corporation (OAR).
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.org/license/LICENSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define CONFIGURE_INIT
+#include "system.h"
+
+const char rtems_test_name[] = "CLOCK TICK";
+
+/*
+ *  Keep the names and IDs in global variables so another task can use them.
+ */
+
+char Task_name[ NUM_TASKS ][ 10 ];
+pthread_t Task_id[ NUM_TASKS ];
+
+void *POSIX_Init(
+  void *argument
+)
+{
+  rtems_status_code status;
+  rtems_time_of_day time;
+  uint32_t i;
+
+  TEST_BEGIN();
+
+  time.year   = 1988;
+  time.month  = 12;
+  time.day    = 31;
+  time.hour   = 9;
+  time.minute = 0;
+  time.second = 0;
+  time.ticks  = 0;
+
+  status = rtems_clock_set( &time );
+  directive_failed( status, "clock get" );
+
+  for ( i = 0; i < NUM_TASKS; i++ ) {
+    sprintf(Task_name[ i ], "TA%zu", i);
+  }
+
+  for ( i = 0; i < NUM_TASKS; i++ ) {
+    if (pthread_create(Task_id + i, NULL, Test_task, NULL))
+      perror("Error creating pthread");
+  }
+}
diff --git a/testsuites/samples/sigwaitticker/system.h b/testsuites/samples/sigwaitticker/system.h
new file mode 100644
index 0000000..4bd9bd0
--- /dev/null
+++ b/testsuites/samples/sigwaitticker/system.h
@@ -0,0 +1,72 @@
+/*  system.h
+ *
+ *  This include file contains information that is included in every
+ *  function in the test set.
+ *
+ *  COPYRIGHT (c) 1989-2009.
+ *  On-Line Applications Research Corporation (OAR).
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.org/license/LICENSE.
+ */
+
+#include <rtems.h>
+#include <rtems/test.h>
+#include <inttypes.h>
+#include "tmacros.h"
+
+/* functions */
+
+void *POSIX_Init(
+  void *argument
+);
+
+void *Test_task(
+  void *argument
+);
+
+/* global variables */
+
+/*
+ *  Keep the names and IDs in global variables so another task can use them.
+ */
+
+#define NUM_TASKS 300
+
+extern pthread_t Task_id[ NUM_TASKS ];
+extern char Task_name[ NUM_TASKS ][ 10 ];
+
+
+/* configuration information */
+
+#include <bsp.h> /* for device driver prototypes */
+
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+
+#define CONFIGURE_MAXIMUM_POSIX_THREADS     1 + NUM_TASKS
+#define CONFIGURE_MAXIMUM_POSIX_TIMERS      NUM_TASKS
+
+#define CONFIGURE_POSIX_INIT_THREAD_TABLE
+
+#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
+
+#include <rtems/confdefs.h>
+
+/*
+ *  This allows us to view the "Test_task" instantiations as a set
+ *  of numbered tasks by eliminating the number of application
+ *  tasks created.
+ *
+ *  In reality, this is too complex for the purposes of this
+ *  example.  It would have been easier to pass a task argument. :)
+ *  But it shows how rtems_id's can sometimes be used.
+ */
+
+#define task_number( tid ) \
+  ( rtems_object_id_get_index( tid ) - \
+      rtems_configuration_get_rtems_api_configuration()-> \
+        number_of_initialization_tasks )
+
+/* end of include file */
diff --git a/testsuites/samples/sigwaitticker/tasks.c b/testsuites/samples/sigwaitticker/tasks.c
new file mode 100644
index 0000000..6749594
--- /dev/null
+++ b/testsuites/samples/sigwaitticker/tasks.c
@@ -0,0 +1,96 @@
+/*  Test_task
+ *
+ *  This routine serves as a test task.  It verifies the basic task
+ *  switching capabilities of the executive.
+ *
+ *  Input parameters:  NONE
+ *
+ *  Output parameters:  NONE
+ *
+ *  COPYRIGHT (c) 1989-2009.
+ *  On-Line Applications Research Corporation (OAR).
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.org/license/LICENSE.
+ */
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "system.h"
+
+void *Test_task(
+  void *unused
+)
+{
+  pthread_t         tid;
+  rtems_time_of_day time;
+  uint32_t          task_index;
+  rtems_status_code status;
+  rtems_interval    sse_time;
+  rtems_interval    last_print_sse_time;
+
+  /* signal timer */
+  int result;
+  sigset_t maskset;
+  struct sigevent event;
+  timer_t timerid;
+  struct itimerspec its;
+  struct timespec timeout;
+
+  /* Blocking alarms until sigtimedwait handles them */
+  sigemptyset(&maskset);
+  sigaddset(&maskset, SIGALRM);
+  pthread_sigmask(SIG_BLOCK, &maskset, NULL);
+
+  /* Create timer to generate alarms */
+  event.sigev_signo = SIGALRM;
+  event.sigev_notify = SIGEV_SIGNAL;
+  result = timer_create(CLOCK_REALTIME, &event, &timerid);
+  if (result)
+    fprintf(stderr, "Could not create timer: %d\n", errno);
+
+  /* Set timer initial and subsequent wait, plus timeout */
+  its.it_value.tv_sec = 1;
+  its.it_value.tv_nsec = 0;
+  its.it_interval.tv_sec = 0;
+  its.it_interval.tv_nsec = rtems_configuration_get_microseconds_per_tick() * 1000;
+  timeout.tv_sec = 3;
+  timeout.tv_nsec = 0;
+
+  /* Start timer generating alarms */
+  timer_settime(timerid, 0, &its, NULL);
+
+  tid = pthread_self();
+  task_index = 0;
+  while (Task_id[task_index] != tid && task_index < NUM_TASKS)
+    task_index++;
+  if (task_index >= NUM_TASKS)
+    perror("Error finding own thread id");
+
+  for ( ; ; ) {
+    status = rtems_clock_get_tod( &time );
+    if ( time.second >= 350 ) {
+      TEST_END();
+      rtems_test_exit( 0 );
+    }
+    rtems_clock_get_seconds_since_epoch(&sse_time);
+    if ( ( sse_time - last_print_sse_time >= 5 ) && task_index == 1 ) {
+      printf("%s", Task_name[task_index]);
+      print_time( " - rtems_clock_get_tod - ", &time, "\n" );
+      last_print_sse_time = sse_time;
+    }
+
+    if (sigtimedwait(&maskset, NULL, &timeout) != SIGALRM) {
+      perror("Timeout or error on sigtimedwait");
+    } else {
+      printf("got alarm\n"); /* Disabling this makes the error go away (wat?) */
+    }
+
+  }
+}


-- 
Martin Erik Werner <martin.werner at aacmicrotec.com>
ÅAC Microtec AB


-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-Create-sigwaitticker-sample-from-ticker-template.patch
Type: text/x-patch
Size: 9096 bytes
Desc: 0001-Create-sigwaitticker-sample-from-ticker-template.patch
URL: <http://lists.rtems.org/pipermail/users/attachments/20160215/b7842a5d/attachment.bin>


More information about the users mailing list