public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] tty: fix stall caused by missing memory barrier in drivers/tty/n_tty.c
@ 2015-09-29  1:59 Kosuke Tatsukawa
  2015-09-30 13:39 ` Peter Hurley
  0 siblings, 1 reply; 4+ messages in thread
From: Kosuke Tatsukawa @ 2015-09-29  1:59 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Jiri Slaby; +Cc: linux-kernel@vger.kernel.org

My colleague ran into a program stall on a x86_64 server, where
n_tty_read() was waiting for data even if there was data in the buffer
in the pty.  kernel stack for the stuck process looks like below.
 #0 [ffff88303d107b58] __schedule at ffffffff815c4b20
 #1 [ffff88303d107bd0] schedule at ffffffff815c513e
 #2 [ffff88303d107bf0] schedule_timeout at ffffffff815c7818
 #3 [ffff88303d107ca0] wait_woken at ffffffff81096bd2
 #4 [ffff88303d107ce0] n_tty_read at ffffffff8136fa23
 #5 [ffff88303d107dd0] tty_read at ffffffff81368013
 #6 [ffff88303d107e20] __vfs_read at ffffffff811a3704
 #7 [ffff88303d107ec0] vfs_read at ffffffff811a3a57
 #8 [ffff88303d107f00] sys_read at ffffffff811a4306
 #9 [ffff88303d107f50] entry_SYSCALL_64_fastpath at ffffffff815c86d7

There seems to be two problems causing this issue.

First, in drivers/tty/n_tty.c, __receive_buf() stores the data and
updates ldata->commit_head using smp_store_release() and then checks
the wait queue using waitqueue_active().  However, since there is no
memory barrier, __receive_buf() could return without calling
wake_up_interactive_poll(), and at the same time, n_tty_read() could
start to wait in wait_woken() as in the following chart.

        __receive_buf()                         n_tty_read()
------------------------------------------------------------------------
if (waitqueue_active(&tty->read_wait))
/* Memory operations issued after the
   RELEASE may be completed before the
   RELEASE operation has completed */
                                        add_wait_queue(&tty->read_wait, &wait);
                                        ...
                                        if (!input_available_p(tty, 0)) {
smp_store_release(&ldata->commit_head,
                  ldata->read_head);
                                        ...
                                        timeout = wait_woken(&wait,
                                          TASK_INTERRUPTIBLE, timeout);
------------------------------------------------------------------------

The second problem is that n_tty_read() also lacks a memory barrier
call and could also cause __receive_buf() to return without calling
wake_up_interactive_poll(), and n_tty_read() to wait in wait_woken()
as in the chart below.

        __receive_buf()                         n_tty_read()
------------------------------------------------------------------------
                                        spin_lock_irqsave(&q->lock, flags);
                                        /* from add_wait_queue() */
                                        ...
                                        if (!input_available_p(tty, 0)) {
                                        /* Memory operations issued after the
                                           RELEASE may be completed before the
                                           RELEASE operation has completed */
smp_store_release(&ldata->commit_head,
                  ldata->read_head);
if (waitqueue_active(&tty->read_wait))
                                        __add_wait_queue(q, wait);
                                        spin_unlock_irqrestore(&q->lock,flags);
                                        /* from add_wait_queue() */
                                        ...
                                        timeout = wait_woken(&wait,
                                          TASK_INTERRUPTIBLE, timeout);
------------------------------------------------------------------------

There are also other places in drivers/tty/n_tty.c which have similar
calls to waitqueue_active(), so instead of adding many memory barrier
calls, this patch simply removes the call to waitqueue_active(),
leaving just wake_up*() behind.

This fixes both problems because, even though the memory access before
or after the spinlocks in both wake_up*() and add_wait_queue() can
sneak into the critical section, it cannot go past it and the critical
section assures that they will be serialized (please see "INTER-CPU
ACQUIRING BARRIER EFFECTS" in Documentation/memory-barriers.txt for a
better explanation).  Moreover, the resulting code is much simpler.

Latency measurement using a ping-pong test over a pty doesn't show any
visible performance drop.

Signed-off-by: Kosuke Tatsukawa <tatsu@ab.jp.nec.com>
Cc: stable@vger.kernel.org
---
 drivers/tty/n_tty.c |   24 ++++++++----------------
 1 files changed, 8 insertions(+), 16 deletions(-)

diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index 20932cc..41eb3ab 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -266,8 +266,7 @@ static void n_tty_check_unthrottle(struct tty_struct *tty)
 			return;
 		n_tty_kick_worker(tty);
 		n_tty_write_wakeup(tty->link);
-		if (waitqueue_active(&tty->link->write_wait))
-			wake_up_interruptible_poll(&tty->link->write_wait, POLLOUT);
+		wake_up_interruptible_poll(&tty->link->write_wait, POLLOUT);
 		return;
 	}
 
@@ -343,8 +342,7 @@ static void n_tty_packet_mode_flush(struct tty_struct *tty)
 		spin_lock_irqsave(&tty->ctrl_lock, flags);
 		tty->ctrl_status |= TIOCPKT_FLUSHREAD;
 		spin_unlock_irqrestore(&tty->ctrl_lock, flags);
-		if (waitqueue_active(&tty->link->read_wait))
-			wake_up_interruptible(&tty->link->read_wait);
+		wake_up_interruptible(&tty->link->read_wait);
 	}
 }
 
@@ -1180,8 +1178,7 @@ static void n_tty_receive_break(struct tty_struct *tty)
 		put_tty_queue('\0', ldata);
 	}
 	put_tty_queue('\0', ldata);
-	if (waitqueue_active(&tty->read_wait))
-		wake_up_interruptible_poll(&tty->read_wait, POLLIN);
+	wake_up_interruptible_poll(&tty->read_wait, POLLIN);
 }
 
 /**
@@ -1238,8 +1235,7 @@ static void n_tty_receive_parity_error(struct tty_struct *tty, unsigned char c)
 			put_tty_queue('\0', ldata);
 	} else
 		put_tty_queue(c, ldata);
-	if (waitqueue_active(&tty->read_wait))
-		wake_up_interruptible_poll(&tty->read_wait, POLLIN);
+	wake_up_interruptible_poll(&tty->read_wait, POLLIN);
 }
 
 static void
@@ -1382,8 +1378,7 @@ handle_newline:
 			put_tty_queue(c, ldata);
 			smp_store_release(&ldata->canon_head, ldata->read_head);
 			kill_fasync(&tty->fasync, SIGIO, POLL_IN);
-			if (waitqueue_active(&tty->read_wait))
-				wake_up_interruptible_poll(&tty->read_wait, POLLIN);
+			wake_up_interruptible_poll(&tty->read_wait, POLLIN);
 			return 0;
 		}
 	}
@@ -1667,8 +1662,7 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp,
 
 	if ((read_cnt(ldata) >= ldata->minimum_to_wake) || L_EXTPROC(tty)) {
 		kill_fasync(&tty->fasync, SIGIO, POLL_IN);
-		if (waitqueue_active(&tty->read_wait))
-			wake_up_interruptible_poll(&tty->read_wait, POLLIN);
+		wake_up_interruptible_poll(&tty->read_wait, POLLIN);
 	}
 }
 
@@ -1887,10 +1881,8 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
 	}
 
 	/* The termios change make the tty ready for I/O */
-	if (waitqueue_active(&tty->write_wait))
-		wake_up_interruptible(&tty->write_wait);
-	if (waitqueue_active(&tty->read_wait))
-		wake_up_interruptible(&tty->read_wait);
+	wake_up_interruptible(&tty->write_wait);
+	wake_up_interruptible(&tty->read_wait);
 }
 
 /**
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH] tty: fix stall caused by missing memory barrier in drivers/tty/n_tty.c
  2015-09-29  1:59 [PATCH] tty: fix stall caused by missing memory barrier in drivers/tty/n_tty.c Kosuke Tatsukawa
@ 2015-09-30 13:39 ` Peter Hurley
  2015-10-01  1:55   ` Kosuke Tatsukawa
  2015-10-01  1:55   ` Kosuke Tatsukawa
  0 siblings, 2 replies; 4+ messages in thread
From: Peter Hurley @ 2015-09-30 13:39 UTC (permalink / raw)
  To: Kosuke Tatsukawa
  Cc: Greg Kroah-Hartman, Jiri Slaby, linux-kernel@vger.kernel.org

On 09/28/2015 09:59 PM, Kosuke Tatsukawa wrote:
> My colleague ran into a program stall on a x86_64 server, where
> n_tty_read() was waiting for data even if there was data in the buffer
> in the pty.  kernel stack for the stuck process looks like below.
>  #0 [ffff88303d107b58] __schedule at ffffffff815c4b20
>  #1 [ffff88303d107bd0] schedule at ffffffff815c513e
>  #2 [ffff88303d107bf0] schedule_timeout at ffffffff815c7818
>  #3 [ffff88303d107ca0] wait_woken at ffffffff81096bd2
>  #4 [ffff88303d107ce0] n_tty_read at ffffffff8136fa23
>  #5 [ffff88303d107dd0] tty_read at ffffffff81368013
>  #6 [ffff88303d107e20] __vfs_read at ffffffff811a3704
>  #7 [ffff88303d107ec0] vfs_read at ffffffff811a3a57
>  #8 [ffff88303d107f00] sys_read at ffffffff811a4306
>  #9 [ffff88303d107f50] entry_SYSCALL_64_fastpath at ffffffff815c86d7
> 
> There seems to be two problems causing this issue.
> 
> First, in drivers/tty/n_tty.c, __receive_buf() stores the data and
> updates ldata->commit_head using smp_store_release() and then checks
> the wait queue using waitqueue_active().  However, since there is no
> memory barrier, __receive_buf() could return without calling
> wake_up_interactive_poll(), and at the same time, n_tty_read() could
> start to wait in wait_woken() as in the following chart.
> 
>         __receive_buf()                         n_tty_read()
> ------------------------------------------------------------------------
> if (waitqueue_active(&tty->read_wait))
> /* Memory operations issued after the
>    RELEASE may be completed before the
>    RELEASE operation has completed */
>                                         add_wait_queue(&tty->read_wait, &wait);
>                                         ...
>                                         if (!input_available_p(tty, 0)) {
> smp_store_release(&ldata->commit_head,
>                   ldata->read_head);
>                                         ...
>                                         timeout = wait_woken(&wait,
>                                           TASK_INTERRUPTIBLE, timeout);

Thank you for reporting this, Tatsukawa-san.

While I agree that a read memory barrier is required before checking
waitqueue_active() in __receive_buf() and n_tty_receive_char_special(),
on x86/64 that sequence would never have been reordered by the CPU, and
thus cannot be the cause of the observed stall.

Further, the compiler should not have been able to reorder the
load of tty->read_wait before the store of ldata->commit_head since it
has no visibility into kill_fasync().

So I'm concerned that some other cause is to blame.

To eliminate a compiler problem, would you please attach a combined listing
for drivers/tty/n_tty.c for the machine this occurred on?

What kernel version was the stall observed?


> ------------------------------------------------------------------------
> 
> The second problem is that n_tty_read() also lacks a memory barrier
> call and could also cause __receive_buf() to return without calling
> wake_up_interactive_poll(), and n_tty_read() to wait in wait_woken()
> as in the chart below.
> 
>         __receive_buf()                         n_tty_read()
> ------------------------------------------------------------------------
>                                         spin_lock_irqsave(&q->lock, flags);
>                                         /* from add_wait_queue() */
>                                         ...
>                                         if (!input_available_p(tty, 0)) {
>                                         /* Memory operations issued after the
>                                            RELEASE may be completed before the
>                                            RELEASE operation has completed */
> smp_store_release(&ldata->commit_head,
>                   ldata->read_head);
> if (waitqueue_active(&tty->read_wait))
>                                         __add_wait_queue(q, wait);
>                                         spin_unlock_irqrestore(&q->lock,flags);
>                                         /* from add_wait_queue() */
>                                         ...
>                                         timeout = wait_woken(&wait,
>                                           TASK_INTERRUPTIBLE, timeout);

This problem was introduced by the wait_woken() mess; prior to that
there was a full memory barrier in n_tty_read() loop to set the task state
_before evaluating conditions_.

Though, again, the sequence above is not possible at all on x86/64 since
neither the CPU nor the compiler can produce the hypothetical code in
n_tty_read() above.

I need to think further on the consequences of the missing full memory
barrier in n_tty_read().

Other notes below.


> ------------------------------------------------------------------------
> 
> There are also other places in drivers/tty/n_tty.c which have similar
> calls to waitqueue_active(), so instead of adding many memory barrier
> calls, this patch simply removes the call to waitqueue_active(),
> leaving just wake_up*() behind.
> 
> This fixes both problems because, even though the memory access before
> or after the spinlocks in both wake_up*() and add_wait_queue() can
> sneak into the critical section, it cannot go past it and the critical
> section assures that they will be serialized (please see "INTER-CPU
> ACQUIRING BARRIER EFFECTS" in Documentation/memory-barriers.txt for a
> better explanation).  Moreover, the resulting code is much simpler.
> 
> Latency measurement using a ping-pong test over a pty doesn't show any
> visible performance drop.
> 
> Signed-off-by: Kosuke Tatsukawa <tatsu@ab.jp.nec.com>
> Cc: stable@vger.kernel.org
> ---
>  drivers/tty/n_tty.c |   24 ++++++++----------------
>  1 files changed, 8 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
> index 20932cc..41eb3ab 100644
> --- a/drivers/tty/n_tty.c
> +++ b/drivers/tty/n_tty.c
> @@ -266,8 +266,7 @@ static void n_tty_check_unthrottle(struct tty_struct *tty)
>  			return;
>  		n_tty_kick_worker(tty);
>  		n_tty_write_wakeup(tty->link);
> -		if (waitqueue_active(&tty->link->write_wait))
> -			wake_up_interruptible_poll(&tty->link->write_wait, POLLOUT);
> +		wake_up_interruptible_poll(&tty->link->write_wait, POLLOUT);

Please remove this blob. I/O performed via the write_wait queue is not lockless.


>  		return;
>  	}
>  
> @@ -343,8 +342,7 @@ static void n_tty_packet_mode_flush(struct tty_struct *tty)
>  		spin_lock_irqsave(&tty->ctrl_lock, flags);
>  		tty->ctrl_status |= TIOCPKT_FLUSHREAD;
>  		spin_unlock_irqrestore(&tty->ctrl_lock, flags);
> -		if (waitqueue_active(&tty->link->read_wait))
> -			wake_up_interruptible(&tty->link->read_wait);
> +		wake_up_interruptible(&tty->link->read_wait);

Ok.

>  	}
>  }
>  
> @@ -1180,8 +1178,7 @@ static void n_tty_receive_break(struct tty_struct *tty)
>  		put_tty_queue('\0', ldata);
>  	}
>  	put_tty_queue('\0', ldata);
> -	if (waitqueue_active(&tty->read_wait))
> -		wake_up_interruptible_poll(&tty->read_wait, POLLIN);
> +	wake_up_interruptible_poll(&tty->read_wait, POLLIN);

Please remove this blob and the one below.

I had a patch to completely remove this wakeup and the one below because
they're superfluous. I thought I submitted it some time ago; I'll find out
what happened to that patch.

Obviously not a cause of the observed stall because neither BRK nor
parity error can be generated on a pty.

>  }
>  
>  /**
> @@ -1238,8 +1235,7 @@ static void n_tty_receive_parity_error(struct tty_struct *tty, unsigned char c)
>  			put_tty_queue('\0', ldata);
>  	} else
>  		put_tty_queue(c, ldata);
> -	if (waitqueue_active(&tty->read_wait))
> -		wake_up_interruptible_poll(&tty->read_wait, POLLIN);
> +	wake_up_interruptible_poll(&tty->read_wait, POLLIN);
>  }
>  
>  static void
> @@ -1382,8 +1378,7 @@ handle_newline:
>  			put_tty_queue(c, ldata);
>  			smp_store_release(&ldata->canon_head, ldata->read_head);
>  			kill_fasync(&tty->fasync, SIGIO, POLL_IN);
> -			if (waitqueue_active(&tty->read_wait))
> -				wake_up_interruptible_poll(&tty->read_wait, POLLIN);
> +			wake_up_interruptible_poll(&tty->read_wait, POLLIN);
>  			return 0;
>  		}
>  	}
> @@ -1667,8 +1662,7 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp,
>  
>  	if ((read_cnt(ldata) >= ldata->minimum_to_wake) || L_EXTPROC(tty)) {
>  		kill_fasync(&tty->fasync, SIGIO, POLL_IN);
> -		if (waitqueue_active(&tty->read_wait))
> -			wake_up_interruptible_poll(&tty->read_wait, POLLIN);
> +		wake_up_interruptible_poll(&tty->read_wait, POLLIN);
>  	}
>  }
>  
> @@ -1887,10 +1881,8 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
>  	}
>  
>  	/* The termios change make the tty ready for I/O */
> -	if (waitqueue_active(&tty->write_wait))
> -		wake_up_interruptible(&tty->write_wait);
> -	if (waitqueue_active(&tty->read_wait))
> -		wake_up_interruptible(&tty->read_wait);
> +	wake_up_interruptible(&tty->write_wait);
> +	wake_up_interruptible(&tty->read_wait);

n_tty_set_termios() cannot be concurrent with __receive_buf() or n_tty_read()
since this caller holds termios_rwsem write-locked. That said, this code
is not performance-sensitive so this is a don't-care.

Regards,
Peter Hurley

>  }
>  
>  /**
> 


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] tty: fix stall caused by missing memory barrier in drivers/tty/n_tty.c
  2015-09-30 13:39 ` Peter Hurley
@ 2015-10-01  1:55   ` Kosuke Tatsukawa
  2015-10-01  1:55   ` Kosuke Tatsukawa
  1 sibling, 0 replies; 4+ messages in thread
From: Kosuke Tatsukawa @ 2015-10-01  1:55 UTC (permalink / raw)
  To: Peter Hurley; +Cc: Greg Kroah-Hartman, Jiri Slaby, linux-kernel@vger.kernel.org

Peter-san,
thank you for the reply.

In message <560BE5FE.50505@hurleysoftware.com> Peter Hurley <peter@hurleysoftware.com> wrote:
> On 09/28/2015 09:59 PM, Kosuke Tatsukawa wrote:
>> My colleague ran into a program stall on a x86_64 server, where
>> n_tty_read() was waiting for data even if there was data in the buffer
>> in the pty.  kernel stack for the stuck process looks like below.
>>  #0 [ffff88303d107b58] __schedule at ffffffff815c4b20
>>  #1 [ffff88303d107bd0] schedule at ffffffff815c513e
>>  #2 [ffff88303d107bf0] schedule_timeout at ffffffff815c7818
>>  #3 [ffff88303d107ca0] wait_woken at ffffffff81096bd2
>>  #4 [ffff88303d107ce0] n_tty_read at ffffffff8136fa23
>>  #5 [ffff88303d107dd0] tty_read at ffffffff81368013
>>  #6 [ffff88303d107e20] __vfs_read at ffffffff811a3704
>>  #7 [ffff88303d107ec0] vfs_read at ffffffff811a3a57
>>  #8 [ffff88303d107f00] sys_read at ffffffff811a4306
>>  #9 [ffff88303d107f50] entry_SYSCALL_64_fastpath at ffffffff815c86d7
>> 
>> There seems to be two problems causing this issue.
>> 
>> First, in drivers/tty/n_tty.c, __receive_buf() stores the data and
>> updates ldata->commit_head using smp_store_release() and then checks
>> the wait queue using waitqueue_active().  However, since there is no
>> memory barrier, __receive_buf() could return without calling
>> wake_up_interactive_poll(), and at the same time, n_tty_read() could
>> start to wait in wait_woken() as in the following chart.
>> 
>>         __receive_buf()                         n_tty_read()
>> ------------------------------------------------------------------------
>> if (waitqueue_active(&tty->read_wait))
>> /* Memory operations issued after the
>>    RELEASE may be completed before the
>>    RELEASE operation has completed */
>>                                         add_wait_queue(&tty->read_wait, &wait);
>>                                         ...
>>                                         if (!input_available_p(tty, 0)) {
>> smp_store_release(&ldata->commit_head,
>>                   ldata->read_head);
>>                                         ...
>>                                         timeout = wait_woken(&wait,
>>                                           TASK_INTERRUPTIBLE, timeout);
> 
> Thank you for reporting this, Tatsukawa-san.
> 
> While I agree that a read memory barrier is required before checking
> waitqueue_active() in __receive_buf() and n_tty_receive_char_special(),
> on x86/64 that sequence would never have been reordered by the CPU, and
> thus cannot be the cause of the observed stall.
> 
> Further, the compiler should not have been able to reorder the
> load of tty->read_wait before the store of ldata->commit_head since it
> has no visibility into kill_fasync().
> 
> So I'm concerned that some other cause is to blame.
> 
> To eliminate a compiler problem, would you please attach a combined listing
> for drivers/tty/n_tty.c for the machine this occurred on?
>
> What kernel version was the stall observed?

I'm testing now on linux-4.3-rc3, but it also occurs on release kernels
such as linux-4.2.

I've attached "dis -l __receive_buf" output from crash at the bottom of
this message.  The code produced looks fine to me.  I think it's the CPU
that is doing the reordering (or more precisely, delaying the store).

I have a reproducer for this issue.  I'll send that in a separate
message.


>> ------------------------------------------------------------------------
>> 
>> The second problem is that n_tty_read() also lacks a memory barrier
>> call and could also cause __receive_buf() to return without calling
>> wake_up_interactive_poll(), and n_tty_read() to wait in wait_woken()
>> as in the chart below.
>> 
>>         __receive_buf()                         n_tty_read()
>> ------------------------------------------------------------------------
>>                                         spin_lock_irqsave(&q->lock, flags);
>>                                         /* from add_wait_queue() */
>>                                         ...
>>                                         if (!input_available_p(tty, 0)) {
>>                                         /* Memory operations issued after the
>>                                            RELEASE may be completed before the
>>                                            RELEASE operation has completed */
>> smp_store_release(&ldata->commit_head,
>>                   ldata->read_head);
>> if (waitqueue_active(&tty->read_wait))
>>                                         __add_wait_queue(q, wait);
>>                                         spin_unlock_irqrestore(&q->lock,flags);
>>                                         /* from add_wait_queue() */
>>                                         ...
>>                                         timeout = wait_woken(&wait,
>>                                           TASK_INTERRUPTIBLE, timeout);
> 
> This problem was introduced by the wait_woken() mess; prior to that
> there was a full memory barrier in n_tty_read() loop to set the task state
> _before evaluating conditions_.
> 
> Though, again, the sequence above is not possible at all on x86/64 since
> neither the CPU nor the compiler can produce the hypothetical code in
> n_tty_read() above.
> 
> I need to think further on the consequences of the missing full memory
> barrier in n_tty_read().
> 
> Other notes below.
<snip>

Thank you for the comments.  I'll reflect your comments in the next
version.

Best regards.
---
Kosuke TATSUKAWA  | 3rd IT Platform Department
                  | IT Platform Division, NEC Corporation
                  | tatsu@ab.jp.nec.com

------------------------------------------------------------------------
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1632
0xffffffff8136ef40 <__receive_buf>:	push   %rbp
0xffffffff8136ef41 <__receive_buf+1>:	mov    %rsp,%rbp
0xffffffff8136ef44 <__receive_buf+4>:	push   %r15
0xffffffff8136ef46 <__receive_buf+6>:	push   %r14
0xffffffff8136ef48 <__receive_buf+8>:	push   %r13
0xffffffff8136ef4a <__receive_buf+10>:	push   %r12
0xffffffff8136ef4c <__receive_buf+12>:	push   %rbx
0xffffffff8136ef4d <__receive_buf+13>:	sub    $0x28,%rsp
0xffffffff8136ef51 <__receive_buf+17>:	nopl   0x0(%rax,%rax,1)
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1634
0xffffffff8136ef56 <__receive_buf+22>:	mov    0x130(%rdi),%eax
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1633
0xffffffff8136ef5c <__receive_buf+28>:	mov    0x280(%rdi),%rbx
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1634
0xffffffff8136ef63 <__receive_buf+35>:	mov    $0x1,%r15d
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1632
0xffffffff8136ef69 <__receive_buf+41>:	mov    %rdi,%r12
0xffffffff8136ef6c <__receive_buf+44>:	mov    %rsi,%r13
0xffffffff8136ef6f <__receive_buf+47>:	mov    %rdx,%r14
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1634
0xffffffff8136ef72 <__receive_buf+50>:	test   $0x20,%al
0xffffffff8136ef74 <__receive_buf+52>:	jne    0xffffffff8136ef82 <__receive_buf+66>
0xffffffff8136ef76 <__receive_buf+54>:	xor    %r15d,%r15d
0xffffffff8136ef79 <__receive_buf+57>:	test   $0x2,%ah
0xffffffff8136ef7c <__receive_buf+60>:	jne    0xffffffff8136f146 <__receive_buf+518>
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1636
0xffffffff8136ef82 <__receive_buf+66>:	movzbl 0x5d(%rbx),%eax
0xffffffff8136ef86 <__receive_buf+70>:	test   $0x8,%al
0xffffffff8136ef88 <__receive_buf+72>:	jne    0xffffffff8136f161 <__receive_buf+545>
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1638
0xffffffff8136ef8e <__receive_buf+78>:	test   $0x4,%al
0xffffffff8136ef90 <__receive_buf+80>:	je     0xffffffff8136f069 <__receive_buf+297>
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 143
0xffffffff8136ef96 <__receive_buf+86>:	lea    0x5e(%rbx),%r15
0xffffffff8136ef9a <__receive_buf+90>:	add    $0x1,%r13
0xffffffff8136ef9e <__receive_buf+94>:	xor    %eax,%eax
0xffffffff8136efa0 <__receive_buf+96>:	jmp    0xffffffff8136efd4 <__receive_buf+148>
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1545
0xffffffff8136efa2 <__receive_buf+98>:	test   %r14,%r14
0xffffffff8136efa5 <__receive_buf+101>:	je     0xffffffff8136efaf <__receive_buf+111>
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1546
0xffffffff8136efa7 <__receive_buf+103>:	movzbl (%r14),%eax
0xffffffff8136efab <__receive_buf+107>:	add    $0x1,%r14
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1547
0xffffffff8136efaf <__receive_buf+111>:	test   %al,%al
0xffffffff8136efb1 <__receive_buf+113>:	jne    0xffffffff8136f1ff <__receive_buf+703>
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 310
0xffffffff8136efb7 <__receive_buf+119>:	mov    (%rbx),%rdx
0xffffffff8136efba <__receive_buf+122>:	movzbl -0x1(%r13),%esi
0xffffffff8136efbf <__receive_buf+127>:	and    $0xfff,%edx
0xffffffff8136efc5 <__receive_buf+133>:	mov    %sil,(%r15,%rdx,1)
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 311
0xffffffff8136efc9 <__receive_buf+137>:	addq   $0x1,(%rbx)
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1550
0xffffffff8136efcd <__receive_buf+141>:	sub    $0x1,%ecx
0xffffffff8136efd0 <__receive_buf+144>:	add    $0x1,%r13
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1544
0xffffffff8136efd4 <__receive_buf+148>:	test   %ecx,%ecx
0xffffffff8136efd6 <__receive_buf+150>:	jne    0xffffffff8136efa2 <__receive_buf+98>
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1662
0xffffffff8136efd8 <__receive_buf+152>:	testb  $0x10,0x5d(%rbx)
0xffffffff8136efdc <__receive_buf+156>:	je     0xffffffff8136efe9 <__receive_buf+169>
0xffffffff8136efde <__receive_buf+158>:	testb  $0x1,0x13e(%r12)
0xffffffff8136efe7 <__receive_buf+167>:	je     0xffffffff8136f05a <__receive_buf+282>
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1666
0xffffffff8136efe9 <__receive_buf+169>:	mov    (%rbx),%rax
0xffffffff8136efec <__receive_buf+172>:	mov    %rax,-0x40(%rbp)
/root/linux-4.3-rc3/include/linux/compiler.h: 221
0xffffffff8136eff0 <__receive_buf+176>:	mov    %rax,0x8(%rbx)
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1668
0xffffffff8136eff4 <__receive_buf+180>:	movslq 0x2260(%rbx),%rdx
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 133
0xffffffff8136effb <__receive_buf+187>:	mov    (%rbx),%rax
0xffffffff8136effe <__receive_buf+190>:	sub    0x2268(%rbx),%rax
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1668
0xffffffff8136f005 <__receive_buf+197>:	cmp    %rax,%rdx
0xffffffff8136f008 <__receive_buf+200>:	jbe    0xffffffff8136f015 <__receive_buf+213>
0xffffffff8136f00a <__receive_buf+202>:	testb  $0x1,0x13e(%r12)
0xffffffff8136f013 <__receive_buf+211>:	je     0xffffffff8136f05a <__receive_buf+282>
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1669
0xffffffff8136f015 <__receive_buf+213>:	lea    0x220(%r12),%rdi
0xffffffff8136f01d <__receive_buf+221>:	mov    $0x20001,%edx
0xffffffff8136f022 <__receive_buf+226>:	mov    $0x1d,%esi
0xffffffff8136f027 <__receive_buf+231>:	callq  0xffffffff811b4a60 <kill_fasync>
/root/linux-4.3-rc3/include/linux/wait.h: 107
0xffffffff8136f02c <__receive_buf+236>:	lea    0x250(%r12),%rax
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1670
0xffffffff8136f034 <__receive_buf+244>:	cmp    %rax,0x250(%r12)
0xffffffff8136f03c <__receive_buf+252>:	je     0xffffffff8136f05a <__receive_buf+282>
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1671
0xffffffff8136f03e <__receive_buf+254>:	lea    0x248(%r12),%rdi
0xffffffff8136f046 <__receive_buf+262>:	mov    $0x1,%ecx
0xffffffff8136f04b <__receive_buf+267>:	mov    $0x1,%edx
0xffffffff8136f050 <__receive_buf+272>:	mov    $0x1,%esi
0xffffffff8136f055 <__receive_buf+277>:	callq  0xffffffff81096eb0 <__wake_up>
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1673
0xffffffff8136f05a <__receive_buf+282>:	add    $0x28,%rsp
0xffffffff8136f05e <__receive_buf+286>:	pop    %rbx
0xffffffff8136f05f <__receive_buf+287>:	pop    %r12
0xffffffff8136f061 <__receive_buf+289>:	pop    %r13
0xffffffff8136f063 <__receive_buf+291>:	pop    %r14
0xffffffff8136f065 <__receive_buf+293>:	pop    %r15
0xffffffff8136f067 <__receive_buf+295>:	leaveq 
0xffffffff8136f068 <__receive_buf+296>:	retq   
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1638
0xffffffff8136f069 <__receive_buf+297>:	mov    0x13c(%r12),%edx
0xffffffff8136f071 <__receive_buf+305>:	and    $0x10000,%edx
0xffffffff8136f077 <__receive_buf+311>:	je     0xffffffff8136f082 <__receive_buf+322>
0xffffffff8136f079 <__receive_buf+313>:	test   %r15b,%r15b
0xffffffff8136f07c <__receive_buf+316>:	je     0xffffffff8136ef96 <__receive_buf+86>
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1640
0xffffffff8136f082 <__receive_buf+322>:	mov    0x2a0(%r12),%r10d
0xffffffff8136f08a <__receive_buf+330>:	test   %r10d,%r10d
0xffffffff8136f08d <__receive_buf+333>:	je     0xffffffff8136f097 <__receive_buf+343>
0xffffffff8136f08f <__receive_buf+335>:	test   %edx,%edx
0xffffffff8136f091 <__receive_buf+337>:	je     0xffffffff8136f1d9 <__receive_buf+665>
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1643
0xffffffff8136f097 <__receive_buf+343>:	test   $0x1,%al
0xffffffff8136f099 <__receive_buf+345>:	je     0xffffffff8136f0c4 <__receive_buf+388>
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1646
0xffffffff8136f09b <__receive_buf+347>:	xor    %edx,%edx
0xffffffff8136f09d <__receive_buf+349>:	test   %r14,%r14
0xffffffff8136f0a0 <__receive_buf+352>:	je     0xffffffff8136f0aa <__receive_buf+362>
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1647
0xffffffff8136f0a2 <__receive_buf+354>:	movsbl (%r14),%edx
0xffffffff8136f0a6 <__receive_buf+358>:	add    $0x1,%r14
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1648
0xffffffff8136f0aa <__receive_buf+362>:	movzbl 0x0(%r13),%esi
0xffffffff8136f0af <__receive_buf+367>:	mov    %r12,%rdi
0xffffffff8136f0b2 <__receive_buf+370>:	mov    %ecx,-0x48(%rbp)
0xffffffff8136f0b5 <__receive_buf+373>:	add    $0x1,%r13
0xffffffff8136f0b9 <__receive_buf+377>:	callq  0xffffffff8136de10 <n_tty_receive_char_lnext>
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1649
0xffffffff8136f0be <__receive_buf+382>:	mov    -0x48(%rbp),%ecx
0xffffffff8136f0c1 <__receive_buf+385>:	sub    $0x1,%ecx
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1652
0xffffffff8136f0c4 <__receive_buf+388>:	test   %r15b,%r15b
0xffffffff8136f0c7 <__receive_buf+391>:	jne    0xffffffff8136f0d8 <__receive_buf+408>
0xffffffff8136f0c9 <__receive_buf+393>:	testb  $0x8,0x130(%r12)
0xffffffff8136f0d2 <__receive_buf+402>:	je     0xffffffff8136f1ec <__receive_buf+684>
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1655
0xffffffff8136f0d8 <__receive_buf+408>:	mov    %r14,%rdx
0xffffffff8136f0db <__receive_buf+411>:	mov    %r13,%rsi
0xffffffff8136f0de <__receive_buf+414>:	mov    %r12,%rdi
0xffffffff8136f0e1 <__receive_buf+417>:	callq  0xffffffff8136ec70 <n_tty_receive_buf_standard>
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 825
0xffffffff8136f0e6 <__receive_buf+422>:	testb  $0x48,0x13c(%r12)
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 823
0xffffffff8136f0ef <__receive_buf+431>:	mov    0x280(%r12),%r14
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 825
0xffffffff8136f0f7 <__receive_buf+439>:	je     0xffffffff8136f12a <__receive_buf+490>
0xffffffff8136f0f9 <__receive_buf+441>:	mov    0x18(%r14),%rax
0xffffffff8136f0fd <__receive_buf+445>:	cmp    %rax,0x20(%r14)
0xffffffff8136f101 <__receive_buf+449>:	je     0xffffffff8136f12a <__receive_buf+490>
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 829
0xffffffff8136f103 <__receive_buf+451>:	lea    0x22b0(%r14),%r13
0xffffffff8136f10a <__receive_buf+458>:	mov    %r13,%rdi
0xffffffff8136f10d <__receive_buf+461>:	callq  0xffffffff815c6940 <mutex_lock>
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 830
0xffffffff8136f112 <__receive_buf+466>:	mov    0x18(%r14),%rax
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 831
0xffffffff8136f116 <__receive_buf+470>:	mov    %r12,%rdi
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 830
0xffffffff8136f119 <__receive_buf+473>:	mov    %rax,0x20(%r14)
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 831
0xffffffff8136f11d <__receive_buf+477>:	callq  0xffffffff8136ca60 <__process_echoes>
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 832
0xffffffff8136f122 <__receive_buf+482>:	mov    %r13,%rdi
0xffffffff8136f125 <__receive_buf+485>:	callq  0xffffffff815c61f0 <mutex_unlock>
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1658
0xffffffff8136f12a <__receive_buf+490>:	mov    0x18(%r12),%rax
0xffffffff8136f12f <__receive_buf+495>:	mov    0x48(%rax),%rax
0xffffffff8136f133 <__receive_buf+499>:	test   %rax,%rax
0xffffffff8136f136 <__receive_buf+502>:	je     0xffffffff8136efd8 <__receive_buf+152>
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1659
0xffffffff8136f13c <__receive_buf+508>:	mov    %r12,%rdi
0xffffffff8136f13f <__receive_buf+511>:	callq  *%rax
0xffffffff8136f141 <__receive_buf+513>:	jmpq   0xffffffff8136efd8 <__receive_buf+152>
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1630
0xffffffff8136f146 <__receive_buf+518>:	mov    0x13c(%rdi),%r15d
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1636
0xffffffff8136f14d <__receive_buf+525>:	movzbl 0x5d(%rbx),%eax
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1630
0xffffffff8136f151 <__receive_buf+529>:	shr    $0xf,%r15d
0xffffffff8136f155 <__receive_buf+533>:	and    $0x1,%r15d
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1636
0xffffffff8136f159 <__receive_buf+537>:	test   $0x8,%al
0xffffffff8136f15b <__receive_buf+539>:	je     0xffffffff8136ef8e <__receive_buf+78>
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1524
0xffffffff8136f161 <__receive_buf+545>:	mov    (%rbx),%rdi
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1525
0xffffffff8136f164 <__receive_buf+548>:	mov    $0x1000,%r15d
0xffffffff8136f16a <__receive_buf+554>:	movslq %ecx,%r14
0xffffffff8136f16d <__receive_buf+557>:	mov    %r15,%rax
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 143
0xffffffff8136f170 <__receive_buf+560>:	lea    0x5e(%rbx),%r8
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1526
0xffffffff8136f174 <__receive_buf+564>:	mov    %r13,%rsi
0xffffffff8136f177 <__receive_buf+567>:	mov    %ecx,-0x48(%rbp)
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1524
0xffffffff8136f17a <__receive_buf+570>:	and    $0xfff,%edi
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1526
0xffffffff8136f180 <__receive_buf+576>:	mov    %r8,-0x50(%rbp)
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1525
0xffffffff8136f184 <__receive_buf+580>:	sub    %rdi,%rax
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1526
0xffffffff8136f187 <__receive_buf+583>:	lea    (%r8,%rdi,1),%rdi
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1525
0xffffffff8136f18b <__receive_buf+587>:	cmp    %rax,%r14
0xffffffff8136f18e <__receive_buf+590>:	cmova  %rax,%r14
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1526
0xffffffff8136f192 <__receive_buf+594>:	mov    %r14,%rdx
0xffffffff8136f195 <__receive_buf+597>:	callq  0xffffffff812b2210 <__memcpy>
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1527
0xffffffff8136f19a <__receive_buf+602>:	mov    %r14,%rdi
0xffffffff8136f19d <__receive_buf+605>:	add    (%rbx),%rdi
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1533
0xffffffff8136f1a0 <__receive_buf+608>:	lea    0x0(%r13,%r14,1),%rsi
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1527
0xffffffff8136f1a5 <__receive_buf+613>:	mov    %rdi,(%rbx)
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1532
0xffffffff8136f1a8 <__receive_buf+616>:	mov    -0x48(%rbp),%ecx
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1531
0xffffffff8136f1ab <__receive_buf+619>:	and    $0xfff,%edi
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1533
0xffffffff8136f1b1 <__receive_buf+625>:	mov    -0x50(%rbp),%r8
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1532
0xffffffff8136f1b5 <__receive_buf+629>:	sub    %rdi,%r15
0xffffffff8136f1b8 <__receive_buf+632>:	sub    %r14d,%ecx
0xffffffff8136f1bb <__receive_buf+635>:	movslq %ecx,%rcx
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1533
0xffffffff8136f1be <__receive_buf+638>:	lea    (%r8,%rdi,1),%rdi
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1532
0xffffffff8136f1c2 <__receive_buf+642>:	cmp    %r15,%rcx
0xffffffff8136f1c5 <__receive_buf+645>:	cmovbe %rcx,%r15
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1533
0xffffffff8136f1c9 <__receive_buf+649>:	mov    %r15,%rdx
0xffffffff8136f1cc <__receive_buf+652>:	callq  0xffffffff812b2210 <__memcpy>
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1534
0xffffffff8136f1d1 <__receive_buf+657>:	add    %r15,(%rbx)
0xffffffff8136f1d4 <__receive_buf+660>:	jmpq   0xffffffff8136efd8 <__receive_buf+152>
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1641
0xffffffff8136f1d9 <__receive_buf+665>:	mov    %r14,%rdx
0xffffffff8136f1dc <__receive_buf+668>:	mov    %r13,%rsi
0xffffffff8136f1df <__receive_buf+671>:	mov    %r12,%rdi
0xffffffff8136f1e2 <__receive_buf+674>:	callq  0xffffffff8136dce0 <n_tty_receive_buf_closing>
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1640
0xffffffff8136f1e7 <__receive_buf+679>:	jmpq   0xffffffff8136efd8 <__receive_buf+152>
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1653
0xffffffff8136f1ec <__receive_buf+684>:	mov    %r14,%rdx
0xffffffff8136f1ef <__receive_buf+687>:	mov    %r13,%rsi
0xffffffff8136f1f2 <__receive_buf+690>:	mov    %r12,%rdi
0xffffffff8136f1f5 <__receive_buf+693>:	callq  0xffffffff8136e620 <n_tty_receive_buf_fast>
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1652
0xffffffff8136f1fa <__receive_buf+698>:	jmpq   0xffffffff8136f0e6 <__receive_buf+422>
/root/linux-4.3-rc3/drivers/tty/n_tty.c: 1550
0xffffffff8136f1ff <__receive_buf+703>:	movzbl -0x1(%r13),%esi
0xffffffff8136f204 <__receive_buf+708>:	movsbl %al,%edx
0xffffffff8136f207 <__receive_buf+711>:	mov    %r12,%rdi
0xffffffff8136f20a <__receive_buf+714>:	mov    %al,-0x50(%rbp)
0xffffffff8136f20d <__receive_buf+717>:	mov    %ecx,-0x48(%rbp)
0xffffffff8136f210 <__receive_buf+720>:	callq  0xffffffff8136dae0 <n_tty_receive_char_flagged>
0xffffffff8136f215 <__receive_buf+725>:	mov    -0x48(%rbp),%ecx
0xffffffff8136f218 <__receive_buf+728>:	movzbl -0x50(%rbp),%eax
0xffffffff8136f21c <__receive_buf+732>:	jmpq   0xffffffff8136efcd <__receive_buf+141>
0xffffffff8136f221 <__receive_buf+737>:	data32 data32 data32 data32 data32 nopw %cs:0x0(%rax,%rax,1)

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] tty: fix stall caused by missing memory barrier in drivers/tty/n_tty.c
  2015-09-30 13:39 ` Peter Hurley
  2015-10-01  1:55   ` Kosuke Tatsukawa
@ 2015-10-01  1:55   ` Kosuke Tatsukawa
  1 sibling, 0 replies; 4+ messages in thread
From: Kosuke Tatsukawa @ 2015-10-01  1:55 UTC (permalink / raw)
  To: Peter Hurley; +Cc: Greg Kroah-Hartman, Jiri Slaby, linux-kernel@vger.kernel.org

This is a reproducer for the stall problem in drivers/tty/n_tty.c

To reproduce the problem, save the program below as pty.c, compile it,
and run it in parallel.

# cc -o pty pty.c
# for i in {1..16}; do ./pty& done; wait

The problem can be reproduced on a multi-socket server with recent CPUs.
The program always stalled during the first run when I used a server
with the following CPU.
  Intel(R) Xeon(R) CPU E5-2698 v3 @ 2.30GHz
  2-sockets x 16-cores x 2-threads

Best regards.
---
Kosuke TATSUKAWA  | 3rd IT Platform Department
                  | IT Platform Division, NEC Corporation
                  | tatsu@ab.jp.nec.com

--------------------------------< pty.c >--------------------------------
#define _XOPEN_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/wait.h>
#include <sys/time.h>

#define COUNT	300000
#define SIZE	1

char	data[SIZE];

int
main(
	int	argc,
	char	**argv)
{
	int		i, fdp, fdt, status;
	char		*slavename;
	struct termios	t;
	pid_t		pid;
	struct timeval	tv1, tv2;

	if ((fdp = open("/dev/ptmx", 2)) < 0) {
		perror("ptmx open");
		exit(1);
	}
	grantpt(fdp);
	unlockpt(fdp);
	slavename = ptsname(fdp);
	if ((fdt = open(slavename, 2)) < 0) {
		perror("pty open");
		close(fdp);
		exit(1);
	}
	tcgetattr(fdt, &t);
	t.c_lflag &= ~ECHO;
	t.c_oflag &= ~OPOST;
	t.c_lflag &= ~ICANON;
	t.c_cc[VMIN] = 1;
	t.c_cc[VTIME] = 0;
	tcsetattr(fdt, TCSANOW, &t);

	tcgetattr(fdp, &t);
	t.c_lflag &= ~ECHO;
	t.c_oflag &= ~OPOST;
	t.c_lflag &= ~ICANON;
	t.c_cc[VMIN] = 1;
	t.c_cc[VTIME] = 0;
	tcsetattr(fdp, TCSANOW, &t);

	memset(data, 'A', SIZE);

	if ((pid = fork()) < 0) {
		perror("fork");
		close(fdt);
		close(fdp);
		exit(1);
	}
	if (pid == 0) {		/* Child */
		sleep(1);
		for (i = 0; i < COUNT; i++) {
			if (write(fdt, data, SIZE) != SIZE) {
				perror("write fdt");
				exit(1);
			}
			if (read(fdt, data, SIZE) != SIZE) {
				perror("read fdt");
				exit(1);
			}
		}
		exit(0);
	} else {		/* Parent */
		for (i = 0; i < COUNT; i++) {
			if (i == 1)
				gettimeofday(&tv1, NULL);
			if (read(fdp, data, SIZE) != SIZE) {
				perror("read fdp");
				exit(1);
			}
			if (write(fdp, data, SIZE) != SIZE) {
				perror("write fdp");
				exit(1);
			}
		}
	}
	gettimeofday(&tv2, NULL);
#if 0
	printf("%d\n", (tv2.tv_sec - tv1.tv_sec) * 1000000 +
		tv2.tv_usec - tv1.tv_usec);
#endif
	wait(&status);
	exit(0);
}

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2015-10-01  1:56 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-09-29  1:59 [PATCH] tty: fix stall caused by missing memory barrier in drivers/tty/n_tty.c Kosuke Tatsukawa
2015-09-30 13:39 ` Peter Hurley
2015-10-01  1:55   ` Kosuke Tatsukawa
2015-10-01  1:55   ` Kosuke Tatsukawa

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox