diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-22 19:17:32 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-22 19:17:32 -0400 |
commit | f23eb2b2b28547fc70df82dd5049eb39bec5ba12 (patch) | |
tree | 144dce462b34d8a232a06f766786ebfb0235fa87 /drivers/tty/tty_buffer.c | |
parent | f741a79e982cf56d7584435bad663553ffe6715f (diff) |
tty: stop using "delayed_work" in the tty layer
Using delayed-work for tty flip buffers ends up causing us to wait for
the next tick to complete some actions. That's usually not all that
noticeable, but for certain latency-critical workloads it ends up being
totally unacceptable.
As an extreme case of this, passing a token back-and-forth over a pty
will take two ticks per iteration, so even just a thousand iterations
will take 8 seconds assuming a common 250Hz configuration.
Avoiding the whole delayed work issue brings that ping-pong test-case
down to 0.009s on my machine.
In more practical terms, this latency has been a performance problem for
things like dive computer simulators (simulating the serial interface
using the ptys) and for other environments (Alan mentions a CP/M emulator).
Reported-by: Jef Driesen <jefdriesen@telenet.be>
Acked-by: Greg KH <gregkh@suse.de>
Acked-by: Alan Cox <alan@lxorguk.ukuu.org.uk>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/tty/tty_buffer.c')
-rw-r--r-- | drivers/tty/tty_buffer.c | 14 |
1 files changed, 7 insertions, 7 deletions
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index d8210ca00720..b9451219528b 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c | |||
@@ -322,7 +322,7 @@ void tty_schedule_flip(struct tty_struct *tty) | |||
322 | if (tty->buf.tail != NULL) | 322 | if (tty->buf.tail != NULL) |
323 | tty->buf.tail->commit = tty->buf.tail->used; | 323 | tty->buf.tail->commit = tty->buf.tail->used; |
324 | spin_unlock_irqrestore(&tty->buf.lock, flags); | 324 | spin_unlock_irqrestore(&tty->buf.lock, flags); |
325 | schedule_delayed_work(&tty->buf.work, 1); | 325 | schedule_work(&tty->buf.work); |
326 | } | 326 | } |
327 | EXPORT_SYMBOL(tty_schedule_flip); | 327 | EXPORT_SYMBOL(tty_schedule_flip); |
328 | 328 | ||
@@ -402,7 +402,7 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags); | |||
402 | static void flush_to_ldisc(struct work_struct *work) | 402 | static void flush_to_ldisc(struct work_struct *work) |
403 | { | 403 | { |
404 | struct tty_struct *tty = | 404 | struct tty_struct *tty = |
405 | container_of(work, struct tty_struct, buf.work.work); | 405 | container_of(work, struct tty_struct, buf.work); |
406 | unsigned long flags; | 406 | unsigned long flags; |
407 | struct tty_ldisc *disc; | 407 | struct tty_ldisc *disc; |
408 | 408 | ||
@@ -443,7 +443,7 @@ static void flush_to_ldisc(struct work_struct *work) | |||
443 | if (test_bit(TTY_FLUSHPENDING, &tty->flags)) | 443 | if (test_bit(TTY_FLUSHPENDING, &tty->flags)) |
444 | break; | 444 | break; |
445 | if (!tty->receive_room || seen_tail) { | 445 | if (!tty->receive_room || seen_tail) { |
446 | schedule_delayed_work(&tty->buf.work, 1); | 446 | schedule_work(&tty->buf.work); |
447 | break; | 447 | break; |
448 | } | 448 | } |
449 | if (count > tty->receive_room) | 449 | if (count > tty->receive_room) |
@@ -481,7 +481,7 @@ static void flush_to_ldisc(struct work_struct *work) | |||
481 | */ | 481 | */ |
482 | void tty_flush_to_ldisc(struct tty_struct *tty) | 482 | void tty_flush_to_ldisc(struct tty_struct *tty) |
483 | { | 483 | { |
484 | flush_delayed_work(&tty->buf.work); | 484 | flush_work(&tty->buf.work); |
485 | } | 485 | } |
486 | 486 | ||
487 | /** | 487 | /** |
@@ -506,9 +506,9 @@ void tty_flip_buffer_push(struct tty_struct *tty) | |||
506 | spin_unlock_irqrestore(&tty->buf.lock, flags); | 506 | spin_unlock_irqrestore(&tty->buf.lock, flags); |
507 | 507 | ||
508 | if (tty->low_latency) | 508 | if (tty->low_latency) |
509 | flush_to_ldisc(&tty->buf.work.work); | 509 | flush_to_ldisc(&tty->buf.work); |
510 | else | 510 | else |
511 | schedule_delayed_work(&tty->buf.work, 1); | 511 | schedule_work(&tty->buf.work); |
512 | } | 512 | } |
513 | EXPORT_SYMBOL(tty_flip_buffer_push); | 513 | EXPORT_SYMBOL(tty_flip_buffer_push); |
514 | 514 | ||
@@ -529,6 +529,6 @@ void tty_buffer_init(struct tty_struct *tty) | |||
529 | tty->buf.tail = NULL; | 529 | tty->buf.tail = NULL; |
530 | tty->buf.free = NULL; | 530 | tty->buf.free = NULL; |
531 | tty->buf.memory_used = 0; | 531 | tty->buf.memory_used = 0; |
532 | INIT_DELAYED_WORK(&tty->buf.work, flush_to_ldisc); | 532 | INIT_WORK(&tty->buf.work, flush_to_ldisc); |
533 | } | 533 | } |
534 | 534 | ||