diff options
author | Tung Nguyen <tung.q.nguyen@dektech.com.au> | 2019-02-18 23:20:48 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-02-21 16:58:05 -0500 |
commit | 48766a583c7961af080de2df692f476624a9a21a (patch) | |
tree | 2ebebb66de46f9d47e2a65ce00b93da76c7a69d9 /net/tipc/socket.c | |
parent | 223b7329ec6a0dae1b7f7db7b770e93f4a069ef9 (diff) |
tipc: improve function tipc_wait_for_rcvmsg()
This commit replaces schedule_timeout() with wait_woken()
in function tipc_wait_for_rcvmsg(). wait_woken() uses
memory barriers in its implementation to avoid potential
race condition when putting a process into sleeping state
and then waking it up.
Acked-by: Ying Xue <ying.xue@windriver.com>
Acked-by: Jon Maloy <jon.maloy@ericsson.com>
Signed-off-by: Tung Nguyen <tung.q.nguyen@dektech.com.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc/socket.c')
-rw-r--r-- | net/tipc/socket.c | 9 |
1 files changed, 5 insertions, 4 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 81b87916a0eb..684f2125fc6b 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
@@ -1677,7 +1677,7 @@ static void tipc_sk_send_ack(struct tipc_sock *tsk) | |||
1677 | static int tipc_wait_for_rcvmsg(struct socket *sock, long *timeop) | 1677 | static int tipc_wait_for_rcvmsg(struct socket *sock, long *timeop) |
1678 | { | 1678 | { |
1679 | struct sock *sk = sock->sk; | 1679 | struct sock *sk = sock->sk; |
1680 | DEFINE_WAIT(wait); | 1680 | DEFINE_WAIT_FUNC(wait, woken_wake_function); |
1681 | long timeo = *timeop; | 1681 | long timeo = *timeop; |
1682 | int err = sock_error(sk); | 1682 | int err = sock_error(sk); |
1683 | 1683 | ||
@@ -1685,15 +1685,17 @@ static int tipc_wait_for_rcvmsg(struct socket *sock, long *timeop) | |||
1685 | return err; | 1685 | return err; |
1686 | 1686 | ||
1687 | for (;;) { | 1687 | for (;;) { |
1688 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | ||
1689 | if (timeo && skb_queue_empty(&sk->sk_receive_queue)) { | 1688 | if (timeo && skb_queue_empty(&sk->sk_receive_queue)) { |
1690 | if (sk->sk_shutdown & RCV_SHUTDOWN) { | 1689 | if (sk->sk_shutdown & RCV_SHUTDOWN) { |
1691 | err = -ENOTCONN; | 1690 | err = -ENOTCONN; |
1692 | break; | 1691 | break; |
1693 | } | 1692 | } |
1693 | add_wait_queue(sk_sleep(sk), &wait); | ||
1694 | release_sock(sk); | 1694 | release_sock(sk); |
1695 | timeo = schedule_timeout(timeo); | 1695 | timeo = wait_woken(&wait, TASK_INTERRUPTIBLE, timeo); |
1696 | sched_annotate_sleep(); | ||
1696 | lock_sock(sk); | 1697 | lock_sock(sk); |
1698 | remove_wait_queue(sk_sleep(sk), &wait); | ||
1697 | } | 1699 | } |
1698 | err = 0; | 1700 | err = 0; |
1699 | if (!skb_queue_empty(&sk->sk_receive_queue)) | 1701 | if (!skb_queue_empty(&sk->sk_receive_queue)) |
@@ -1709,7 +1711,6 @@ static int tipc_wait_for_rcvmsg(struct socket *sock, long *timeop) | |||
1709 | if (err) | 1711 | if (err) |
1710 | break; | 1712 | break; |
1711 | } | 1713 | } |
1712 | finish_wait(sk_sleep(sk), &wait); | ||
1713 | *timeop = timeo; | 1714 | *timeop = timeo; |
1714 | return err; | 1715 | return err; |
1715 | } | 1716 | } |