[rtems commit] termios: PR1279: Use first open status

Sebastian Huber sebh at rtems.org
Wed Jul 9 10:52:38 UTC 2014


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

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Wed Jul  9 11:52:56 2014 +0200

termios: PR1279: Use first open status

---

 cpukit/libcsupport/src/termios.c     |  155 ++++++++++++++++++----------------
 testsuites/libtests/termios01/init.c |   50 +++++++++++
 2 files changed, 132 insertions(+), 73 deletions(-)

diff --git a/cpukit/libcsupport/src/termios.c b/cpukit/libcsupport/src/termios.c
index b70060d..2448ea1 100644
--- a/cpukit/libcsupport/src/termios.c
+++ b/cpukit/libcsupport/src/termios.c
@@ -284,6 +284,82 @@ rtems_termios_callback_startRemoteTx (rtems_termios_tty *tty)
   (*tty->device.startRemoteTx) (tty->minor);
 }
 
+/*
+ * Drain output queue
+ */
+static void
+drainOutput (struct rtems_termios_tty *tty)
+{
+  rtems_interrupt_lock_context lock_context;
+  rtems_status_code sc;
+
+  if (tty->handler.mode != TERMIOS_POLLED) {
+    rtems_termios_interrupt_lock_acquire (tty, &lock_context);
+    while (tty->rawOutBuf.Tail != tty->rawOutBuf.Head) {
+      tty->rawOutBufState = rob_wait;
+      rtems_termios_interrupt_lock_release (tty, &lock_context);
+      sc = rtems_semaphore_obtain(
+        tty->rawOutBuf.Semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+      if (sc != RTEMS_SUCCESSFUL)
+        rtems_fatal_error_occurred (sc);
+      rtems_termios_interrupt_lock_acquire (tty, &lock_context);
+    }
+    rtems_termios_interrupt_lock_release (tty, &lock_context);
+  }
+}
+
+static void
+rtems_termios_destroy_tty (rtems_termios_tty *tty, void *arg, bool last_close)
+{
+  rtems_status_code sc;
+
+  if (rtems_termios_linesw[tty->t_line].l_close != NULL) {
+    /*
+     * call discipline-specific close
+     */
+    sc = rtems_termios_linesw[tty->t_line].l_close(tty);
+  } else if (last_close) {
+    /*
+     * default: just flush output buffer
+     */
+    sc = rtems_semaphore_obtain(tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+    if (sc != RTEMS_SUCCESSFUL) {
+      rtems_fatal_error_occurred (sc);
+    }
+    drainOutput (tty);
+    rtems_semaphore_release (tty->osem);
+  }
+
+  if (tty->handler.mode == TERMIOS_TASK_DRIVEN) {
+    /*
+     * send "terminate" to I/O tasks
+     */
+    sc = rtems_event_send( tty->rxTaskId, TERMIOS_RX_TERMINATE_EVENT );
+    if (sc != RTEMS_SUCCESSFUL)
+      rtems_fatal_error_occurred (sc);
+    sc = rtems_event_send( tty->txTaskId, TERMIOS_TX_TERMINATE_EVENT );
+    if (sc != RTEMS_SUCCESSFUL)
+      rtems_fatal_error_occurred (sc);
+  }
+  if (last_close && tty->handler.last_close)
+     (*tty->handler.last_close)(tty, arg);
+
+  if (tty->device_node != NULL)
+    tty->device_node->tty = NULL;
+
+  rtems_semaphore_delete (tty->isem);
+  rtems_semaphore_delete (tty->osem);
+  rtems_semaphore_delete (tty->rawOutBuf.Semaphore);
+  if ((tty->handler.poll_read == NULL) ||
+      (tty->handler.mode == TERMIOS_TASK_DRIVEN))
+    rtems_semaphore_delete (tty->rawInBuf.Semaphore);
+  rtems_interrupt_lock_destroy (&tty->interrupt_lock);
+  free (tty->rawInBuf.theBuf);
+  free (tty->rawOutBuf.theBuf);
+  free (tty->cbuf);
+  free (tty);
+}
+
 static rtems_termios_tty *
 rtems_termios_open_tty(
   rtems_device_major_number      major,
@@ -486,8 +562,11 @@ rtems_termios_open_tty(
   }
   args->iop->data1 = tty;
   if (!tty->refcount++) {
-    if (tty->handler.first_open)
-      (*tty->handler.first_open)(tty, args);
+    if (tty->handler.first_open &&
+        !(*tty->handler.first_open)(tty, args)) {
+      rtems_termios_destroy_tty(tty, args, false);
+      return NULL;
+    }
 
     /*
      * start I/O tasks, if needed
@@ -594,30 +673,6 @@ rtems_termios_open (
   return RTEMS_SUCCESSFUL;
 }
 
-/*
- * Drain output queue
- */
-static void
-drainOutput (struct rtems_termios_tty *tty)
-{
-  rtems_interrupt_lock_context lock_context;
-  rtems_status_code sc;
-
-  if (tty->handler.mode != TERMIOS_POLLED) {
-    rtems_termios_interrupt_lock_acquire (tty, &lock_context);
-    while (tty->rawOutBuf.Tail != tty->rawOutBuf.Head) {
-      tty->rawOutBufState = rob_wait;
-      rtems_termios_interrupt_lock_release (tty, &lock_context);
-      sc = rtems_semaphore_obtain(
-        tty->rawOutBuf.Semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
-      if (sc != RTEMS_SUCCESSFUL)
-        rtems_fatal_error_occurred (sc);
-      rtems_termios_interrupt_lock_acquire (tty, &lock_context);
-    }
-    rtems_termios_interrupt_lock_release (tty, &lock_context);
-  }
-}
-
 static void
 flushOutput (struct rtems_termios_tty *tty)
 {
@@ -644,54 +699,8 @@ flushInput (struct rtems_termios_tty *tty)
 static void
 rtems_termios_close_tty (rtems_termios_tty *tty, void *arg)
 {
-  rtems_status_code sc;
-
   if (--tty->refcount == 0) {
-    if (rtems_termios_linesw[tty->t_line].l_close != NULL) {
-      /*
-       * call discipline-specific close
-       */
-      sc = rtems_termios_linesw[tty->t_line].l_close(tty);
-    } else {
-      /*
-       * default: just flush output buffer
-       */
-      sc = rtems_semaphore_obtain(tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
-      if (sc != RTEMS_SUCCESSFUL) {
-        rtems_fatal_error_occurred (sc);
-      }
-      drainOutput (tty);
-      rtems_semaphore_release (tty->osem);
-    }
-
-    if (tty->handler.mode == TERMIOS_TASK_DRIVEN) {
-      /*
-       * send "terminate" to I/O tasks
-       */
-      sc = rtems_event_send( tty->rxTaskId, TERMIOS_RX_TERMINATE_EVENT );
-      if (sc != RTEMS_SUCCESSFUL)
-        rtems_fatal_error_occurred (sc);
-      sc = rtems_event_send( tty->txTaskId, TERMIOS_TX_TERMINATE_EVENT );
-      if (sc != RTEMS_SUCCESSFUL)
-        rtems_fatal_error_occurred (sc);
-    }
-    if (tty->handler.last_close)
-       (*tty->handler.last_close)(tty, arg);
-
-    if (tty->device_node != NULL)
-      tty->device_node->tty = NULL;
-
-    rtems_semaphore_delete (tty->isem);
-    rtems_semaphore_delete (tty->osem);
-    rtems_semaphore_delete (tty->rawOutBuf.Semaphore);
-    if ((tty->handler.poll_read == NULL) ||
-        (tty->handler.mode == TERMIOS_TASK_DRIVEN))
-      rtems_semaphore_delete (tty->rawInBuf.Semaphore);
-    rtems_interrupt_lock_destroy (&tty->interrupt_lock);
-    free (tty->rawInBuf.theBuf);
-    free (tty->rawOutBuf.theBuf);
-    free (tty->cbuf);
-    free (tty);
+    rtems_termios_destroy_tty (tty, arg, true);
   }
 }
 
diff --git a/testsuites/libtests/termios01/init.c b/testsuites/libtests/termios01/init.c
index 5010c38..8968678 100644
--- a/testsuites/libtests/termios01/init.c
+++ b/testsuites/libtests/termios01/init.c
@@ -605,6 +605,55 @@ static void test_device_install_remove(void)
   rtems_test_assert( rtems_resource_snapshot_check( &snapshot ) );
 }
 
+static bool first_open_error(
+  rtems_termios_tty *tty,
+  rtems_libio_open_close_args_t *args
+)
+{
+  bool *done = rtems_termios_get_device_context( tty );
+
+  (void) args;
+
+  *done = true;
+
+  return false;
+}
+
+static void test_first_open_error(void)
+{
+  static const rtems_termios_device_handler handler = {
+    .first_open = first_open_error
+  };
+  static const rtems_device_major_number major = 123456789;
+  static const rtems_device_minor_number minor = 0xdeadbeef;
+  static const char dev[] = "/foobar";
+
+  rtems_resource_snapshot snapshot;
+  rtems_status_code sc;
+  rtems_libio_t iop;
+  rtems_libio_open_close_args_t args;
+  bool done = false;
+
+  rtems_resource_snapshot_take( &snapshot );
+
+  sc = rtems_termios_device_install( &dev[0], major, minor, &handler, &done );
+  rtems_test_assert( sc == RTEMS_SUCCESSFUL );
+
+  memset( &iop, 0, sizeof( iop ) );
+  memset( &args, 0, sizeof( args ) );
+  args.iop = &iop;
+
+  rtems_test_assert( !done );
+  sc = rtems_termios_device_open( major, minor, &args );
+  rtems_test_assert( sc == RTEMS_NO_MEMORY );
+  rtems_test_assert( done );
+
+  sc = rtems_termios_device_remove( &dev[0], major, minor );
+  rtems_test_assert( sc == RTEMS_SUCCESSFUL );
+
+  rtems_test_assert( rtems_resource_snapshot_check( &snapshot ) );
+}
+
 static bool set_attributes_error(
   rtems_termios_tty *tty,
   const struct termios *term
@@ -821,6 +870,7 @@ static rtems_task Init(
   puts( "" );
 
   test_device_install_remove();
+  test_first_open_error();
   test_set_attributes_error();
 
   TEST_END();



More information about the vc mailing list