diff options
| -rw-r--r-- | fs/select.c | 31 | ||||
| -rw-r--r-- | include/net/ll_poll.h | 55 |
2 files changed, 38 insertions, 48 deletions
diff --git a/fs/select.c b/fs/select.c index 25cac5faf6d6..50a804b6839f 100644 --- a/fs/select.c +++ b/fs/select.c | |||
| @@ -403,8 +403,7 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time) | |||
| 403 | int retval, i, timed_out = 0; | 403 | int retval, i, timed_out = 0; |
| 404 | unsigned long slack = 0; | 404 | unsigned long slack = 0; |
| 405 | unsigned int busy_flag = net_busy_loop_on() ? POLL_BUSY_LOOP : 0; | 405 | unsigned int busy_flag = net_busy_loop_on() ? POLL_BUSY_LOOP : 0; |
| 406 | u64 busy_start = busy_loop_start_time(busy_flag); | 406 | unsigned long busy_end = 0; |
| 407 | u64 busy_end = busy_loop_end_time(); | ||
| 408 | 407 | ||
| 409 | rcu_read_lock(); | 408 | rcu_read_lock(); |
| 410 | retval = max_select_fd(n, fds); | 409 | retval = max_select_fd(n, fds); |
| @@ -506,9 +505,15 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time) | |||
| 506 | } | 505 | } |
| 507 | 506 | ||
| 508 | /* only if found POLL_BUSY_LOOP sockets && not out of time */ | 507 | /* only if found POLL_BUSY_LOOP sockets && not out of time */ |
| 509 | if (!need_resched() && can_busy_loop && | 508 | if (can_busy_loop && !need_resched()) { |
| 510 | busy_loop_range(busy_start, busy_end)) | 509 | if (!busy_end) { |
| 511 | continue; | 510 | busy_end = busy_loop_end_time(); |
| 511 | continue; | ||
| 512 | } | ||
| 513 | if (!busy_loop_timeout(busy_end)) | ||
| 514 | continue; | ||
| 515 | } | ||
| 516 | busy_flag = 0; | ||
| 512 | 517 | ||
| 513 | /* | 518 | /* |
| 514 | * If this is the first loop and we have a timeout | 519 | * If this is the first loop and we have a timeout |
| @@ -780,9 +785,7 @@ static int do_poll(unsigned int nfds, struct poll_list *list, | |||
| 780 | int timed_out = 0, count = 0; | 785 | int timed_out = 0, count = 0; |
| 781 | unsigned long slack = 0; | 786 | unsigned long slack = 0; |
| 782 | unsigned int busy_flag = net_busy_loop_on() ? POLL_BUSY_LOOP : 0; | 787 | unsigned int busy_flag = net_busy_loop_on() ? POLL_BUSY_LOOP : 0; |
| 783 | u64 busy_start = busy_loop_start_time(busy_flag); | 788 | unsigned long busy_end = 0; |
| 784 | u64 busy_end = busy_loop_end_time(); | ||
| 785 | |||
| 786 | 789 | ||
| 787 | /* Optimise the no-wait case */ | 790 | /* Optimise the no-wait case */ |
| 788 | if (end_time && !end_time->tv_sec && !end_time->tv_nsec) { | 791 | if (end_time && !end_time->tv_sec && !end_time->tv_nsec) { |
| @@ -834,9 +837,15 @@ static int do_poll(unsigned int nfds, struct poll_list *list, | |||
| 834 | break; | 837 | break; |
| 835 | 838 | ||
| 836 | /* only if found POLL_BUSY_LOOP sockets && not out of time */ | 839 | /* only if found POLL_BUSY_LOOP sockets && not out of time */ |
| 837 | if (!need_resched() && can_busy_loop && | 840 | if (can_busy_loop && !need_resched()) { |
| 838 | busy_loop_range(busy_start, busy_end)) | 841 | if (!busy_end) { |
| 839 | continue; | 842 | busy_end = busy_loop_end_time(); |
| 843 | continue; | ||
| 844 | } | ||
| 845 | if (!busy_loop_timeout(busy_end)) | ||
| 846 | continue; | ||
| 847 | } | ||
| 848 | busy_flag = 0; | ||
| 840 | 849 | ||
| 841 | /* | 850 | /* |
| 842 | * If this is the first loop and we have a timeout | 851 | * If this is the first loop and we have a timeout |
diff --git a/include/net/ll_poll.h b/include/net/ll_poll.h index f14dd88dafc8..76f034087743 100644 --- a/include/net/ll_poll.h +++ b/include/net/ll_poll.h | |||
| @@ -47,7 +47,7 @@ static inline bool net_busy_loop_on(void) | |||
| 47 | * we only care that the average is bounded | 47 | * we only care that the average is bounded |
| 48 | */ | 48 | */ |
| 49 | #ifdef CONFIG_DEBUG_PREEMPT | 49 | #ifdef CONFIG_DEBUG_PREEMPT |
| 50 | static inline u64 busy_loop_sched_clock(void) | 50 | static inline u64 busy_loop_us_clock(void) |
| 51 | { | 51 | { |
| 52 | u64 rc; | 52 | u64 rc; |
| 53 | 53 | ||
| @@ -55,37 +55,24 @@ static inline u64 busy_loop_sched_clock(void) | |||
| 55 | rc = sched_clock(); | 55 | rc = sched_clock(); |
| 56 | preempt_enable_no_resched_notrace(); | 56 | preempt_enable_no_resched_notrace(); |
| 57 | 57 | ||
| 58 | return rc; | 58 | return rc >> 10; |
| 59 | } | 59 | } |
| 60 | #else /* CONFIG_DEBUG_PREEMPT */ | 60 | #else /* CONFIG_DEBUG_PREEMPT */ |
| 61 | static inline u64 busy_loop_sched_clock(void) | 61 | static inline u64 busy_loop_us_clock(void) |
| 62 | { | 62 | { |
| 63 | return sched_clock(); | 63 | return sched_clock() >> 10; |
| 64 | } | 64 | } |
| 65 | #endif /* CONFIG_DEBUG_PREEMPT */ | 65 | #endif /* CONFIG_DEBUG_PREEMPT */ |
| 66 | 66 | ||
| 67 | /* we don't mind a ~2.5% imprecision so <<10 instead of *1000 | 67 | static inline unsigned long sk_busy_loop_end_time(struct sock *sk) |
| 68 | * sk->sk_ll_usec is a u_int so this can't overflow | ||
| 69 | */ | ||
| 70 | static inline u64 sk_busy_loop_end_time(struct sock *sk) | ||
| 71 | { | 68 | { |
| 72 | return (u64)ACCESS_ONCE(sk->sk_ll_usec) << 10; | 69 | return busy_loop_us_clock() + ACCESS_ONCE(sk->sk_ll_usec); |
| 73 | } | 70 | } |
| 74 | 71 | ||
| 75 | /* in poll/select we use the global sysctl_net_ll_poll value | 72 | /* in poll/select we use the global sysctl_net_ll_poll value */ |
| 76 | * only call sched_clock() if enabled | 73 | static inline unsigned long busy_loop_end_time(void) |
| 77 | */ | ||
| 78 | static inline u64 busy_loop_end_time(void) | ||
| 79 | { | ||
| 80 | return (u64)ACCESS_ONCE(sysctl_net_ll_poll) << 10; | ||
| 81 | } | ||
| 82 | |||
| 83 | /* if flag is not set we don't need to know the time | ||
| 84 | * so we want to avoid a potentially expensive sched_clock() | ||
| 85 | */ | ||
| 86 | static inline u64 busy_loop_start_time(unsigned int flag) | ||
| 87 | { | 74 | { |
| 88 | return flag ? busy_loop_sched_clock() : 0; | 75 | return busy_loop_us_clock() + ACCESS_ONCE(sysctl_net_ll_poll); |
| 89 | } | 76 | } |
| 90 | 77 | ||
| 91 | static inline bool sk_can_busy_loop(struct sock *sk) | 78 | static inline bool sk_can_busy_loop(struct sock *sk) |
| @@ -94,12 +81,12 @@ static inline bool sk_can_busy_loop(struct sock *sk) | |||
| 94 | !need_resched() && !signal_pending(current); | 81 | !need_resched() && !signal_pending(current); |
| 95 | } | 82 | } |
| 96 | 83 | ||
| 97 | /* careful! time_in_range64 will evaluate now twice */ | 84 | |
| 98 | static inline bool busy_loop_range(u64 start_time, u64 run_time) | 85 | static inline bool busy_loop_timeout(unsigned long end_time) |
| 99 | { | 86 | { |
| 100 | u64 now = busy_loop_sched_clock(); | 87 | unsigned long now = busy_loop_us_clock(); |
| 101 | 88 | ||
| 102 | return time_in_range64(now, start_time, start_time + run_time); | 89 | return time_after(now, end_time); |
| 103 | } | 90 | } |
| 104 | 91 | ||
| 105 | /* when used in sock_poll() nonblock is known at compile time to be true | 92 | /* when used in sock_poll() nonblock is known at compile time to be true |
| @@ -107,8 +94,7 @@ static inline bool busy_loop_range(u64 start_time, u64 run_time) | |||
| 107 | */ | 94 | */ |
| 108 | static inline bool sk_busy_loop(struct sock *sk, int nonblock) | 95 | static inline bool sk_busy_loop(struct sock *sk, int nonblock) |
| 109 | { | 96 | { |
| 110 | u64 start_time = busy_loop_start_time(!nonblock); | 97 | unsigned long end_time = !nonblock ? sk_busy_loop_end_time(sk) : 0; |
| 111 | u64 end_time = sk_busy_loop_end_time(sk); | ||
| 112 | const struct net_device_ops *ops; | 98 | const struct net_device_ops *ops; |
| 113 | struct napi_struct *napi; | 99 | struct napi_struct *napi; |
| 114 | int rc = false; | 100 | int rc = false; |
| @@ -139,7 +125,7 @@ static inline bool sk_busy_loop(struct sock *sk, int nonblock) | |||
| 139 | LINUX_MIB_LOWLATENCYRXPACKETS, rc); | 125 | LINUX_MIB_LOWLATENCYRXPACKETS, rc); |
| 140 | 126 | ||
| 141 | } while (!nonblock && skb_queue_empty(&sk->sk_receive_queue) && | 127 | } while (!nonblock && skb_queue_empty(&sk->sk_receive_queue) && |
| 142 | busy_loop_range(start_time, end_time)); | 128 | !need_resched() && !busy_loop_timeout(end_time)); |
| 143 | 129 | ||
| 144 | rc = !skb_queue_empty(&sk->sk_receive_queue); | 130 | rc = !skb_queue_empty(&sk->sk_receive_queue); |
| 145 | out: | 131 | out: |
| @@ -165,12 +151,7 @@ static inline unsigned long net_busy_loop_on(void) | |||
| 165 | return 0; | 151 | return 0; |
| 166 | } | 152 | } |
| 167 | 153 | ||
| 168 | static inline u64 busy_loop_start_time(unsigned int flag) | 154 | static inline unsigned long busy_loop_end_time(void) |
| 169 | { | ||
| 170 | return 0; | ||
| 171 | } | ||
| 172 | |||
| 173 | static inline u64 busy_loop_end_time(void) | ||
| 174 | { | 155 | { |
| 175 | return 0; | 156 | return 0; |
| 176 | } | 157 | } |
| @@ -193,9 +174,9 @@ static inline void sk_mark_ll(struct sock *sk, struct sk_buff *skb) | |||
| 193 | { | 174 | { |
| 194 | } | 175 | } |
| 195 | 176 | ||
| 196 | static inline bool busy_loop_range(u64 start_time, u64 run_time) | 177 | static inline bool busy_loop_timeout(unsigned long end_time) |
| 197 | { | 178 | { |
| 198 | return false; | 179 | return true; |
| 199 | } | 180 | } |
| 200 | 181 | ||
| 201 | #endif /* CONFIG_NET_LL_RX_POLL */ | 182 | #endif /* CONFIG_NET_LL_RX_POLL */ |
