summaryrefslogtreecommitdiffstats
path: root/cpukit/libcsupport/src/termios.c
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2016-10-05 10:37:56 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2016-12-16 09:04:58 +0100
commitc3764ce80588461d086e844e68002142dbd1ead9 (patch)
treefc03d7a814a4995cff248b0a4c5c0acaa8a3da8b /cpukit/libcsupport/src/termios.c
parentbsp/atsam: Move interrupt setup to PIO_Configure() (diff)
downloadrtems-c3764ce80588461d086e844e68002142dbd1ead9.tar.bz2
termios: Use mutex for task driven mode
Termios has a task driven mode (TERMIOS_TASK_DRIVEN). This mode aims to avoid long sections with disabled interrupts. This is only partly implemented since the device level state is still protected by disabled interrupts. Use a mutex to protect the device level state in task driven mode to fix this issue. Update #2838.
Diffstat (limited to 'cpukit/libcsupport/src/termios.c')
-rw-r--r--cpukit/libcsupport/src/termios.c78
1 files changed, 76 insertions, 2 deletions
diff --git a/cpukit/libcsupport/src/termios.c b/cpukit/libcsupport/src/termios.c
index b972b4f34f..3bc5bb8e1d 100644
--- a/cpukit/libcsupport/src/termios.c
+++ b/cpukit/libcsupport/src/termios.c
@@ -272,6 +272,12 @@ drainOutput (struct rtems_termios_tty *tty)
}
}
+static bool
+needDeviceMutex (rtems_termios_tty *tty)
+{
+ return tty->handler.mode == TERMIOS_TASK_DRIVEN;
+}
+
static void
rtems_termios_destroy_tty (rtems_termios_tty *tty, void *arg, bool last_close)
{
@@ -318,8 +324,11 @@ rtems_termios_destroy_tty (rtems_termios_tty *tty, void *arg, bool last_close)
(tty->handler.mode == TERMIOS_TASK_DRIVEN))
rtems_semaphore_delete (tty->rawInBuf.Semaphore);
- if (tty->device_context == &tty->legacy_device_context)
- rtems_interrupt_lock_destroy (&tty->legacy_device_context.interrupt_lock);
+ if (needDeviceMutex (tty)) {
+ rtems_semaphore_delete (tty->device_context->lock.mutex);
+ } else if (tty->device_context == &tty->legacy_device_context) {
+ rtems_interrupt_lock_destroy (&tty->legacy_device_context.lock.interrupt);
+ }
free (tty->rawInBuf.theBuf);
free (tty->rawOutBuf.theBuf);
@@ -327,6 +336,50 @@ rtems_termios_destroy_tty (rtems_termios_tty *tty, void *arg, bool last_close)
free (tty);
}
+static void
+deviceAcquireMutex(
+ rtems_termios_device_context *ctx,
+ rtems_interrupt_lock_context *lock_context
+)
+{
+ rtems_status_code sc;
+
+ sc = rtems_semaphore_obtain (ctx->lock.mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ _Assert (sc == RTEMS_SUCCESSFUL);
+ (void) sc;
+}
+
+static void
+deviceReleaseMutex(
+ rtems_termios_device_context *ctx,
+ rtems_interrupt_lock_context *lock_context
+)
+{
+ rtems_status_code sc;
+
+ sc = rtems_semaphore_release (ctx->lock.mutex);
+ _Assert (sc == RTEMS_SUCCESSFUL);
+ (void) sc;
+}
+
+static void
+deviceAcquireInterrupt(
+ rtems_termios_device_context *ctx,
+ rtems_interrupt_lock_context *lock_context
+)
+{
+ rtems_interrupt_lock_acquire (&ctx->lock.interrupt, lock_context);
+}
+
+static void
+deviceReleaseInterrupt(
+ rtems_termios_device_context *ctx,
+ rtems_interrupt_lock_context *lock_context
+)
+{
+ rtems_interrupt_lock_release (&ctx->lock.interrupt, lock_context);
+}
+
static rtems_termios_tty *
rtems_termios_open_tty(
rtems_device_major_number major,
@@ -341,6 +394,7 @@ rtems_termios_open_tty(
if (tty == NULL) {
static char c = 'a';
+ rtems_termios_device_context *ctx;
/*
* Create a new device
@@ -459,6 +513,26 @@ rtems_termios_open_tty(
rtems_termios_device_context_initialize (tty->device_context, "Termios");
}
+ ctx = tty->device_context;
+
+ if (needDeviceMutex (tty)) {
+ sc = rtems_semaphore_create (
+ rtems_build_name ('T', 'l', 'k', c),
+ 1,
+ RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
+ 0,
+ &ctx->lock.mutex);
+ if (sc != RTEMS_SUCCESSFUL) {
+ rtems_fatal_error_occurred (sc);
+ }
+
+ ctx->lock_acquire = deviceAcquireMutex;
+ ctx->lock_release = deviceReleaseMutex;
+ } else {
+ ctx->lock_acquire = deviceAcquireInterrupt;
+ ctx->lock_release = deviceReleaseInterrupt;
+ }
+
/*
* Create I/O tasks
*/