mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-24 15:42:32 +00:00
net: poll/select low latency socket support
select/poll busy-poll support. Split sysctl value into two separate ones, one for read and one for poll. updated Documentation/sysctl/net.txt Add a new poll flag POLL_LL. When this flag is set, sock_poll will call sk_poll_ll if possible. sock_poll sets this flag in its return value to indicate to select/poll when a socket that can busy poll is found. When poll/select have nothing to report, call the low-level sock_poll again until we are out of time or we find something. Once the system call finds something, it stops setting POLL_LL, so it can return the result to the user ASAP. Signed-off-by: Eliezer Tamir <eliezer.tamir@linux.intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
e4f2379db6
commit
2d48d67fa8
7 changed files with 91 additions and 22 deletions
34
fs/select.c
34
fs/select.c
|
@ -27,6 +27,7 @@
|
|||
#include <linux/rcupdate.h>
|
||||
#include <linux/hrtimer.h>
|
||||
#include <linux/sched/rt.h>
|
||||
#include <net/ll_poll.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
|
@ -384,9 +385,10 @@ get_max:
|
|||
#define POLLEX_SET (POLLPRI)
|
||||
|
||||
static inline void wait_key_set(poll_table *wait, unsigned long in,
|
||||
unsigned long out, unsigned long bit)
|
||||
unsigned long out, unsigned long bit,
|
||||
unsigned int ll_flag)
|
||||
{
|
||||
wait->_key = POLLEX_SET;
|
||||
wait->_key = POLLEX_SET | ll_flag;
|
||||
if (in & bit)
|
||||
wait->_key |= POLLIN_SET;
|
||||
if (out & bit)
|
||||
|
@ -400,6 +402,8 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time)
|
|||
poll_table *wait;
|
||||
int retval, i, timed_out = 0;
|
||||
unsigned long slack = 0;
|
||||
unsigned int ll_flag = POLL_LL;
|
||||
u64 ll_time = ll_end_time();
|
||||
|
||||
rcu_read_lock();
|
||||
retval = max_select_fd(n, fds);
|
||||
|
@ -422,6 +426,7 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time)
|
|||
retval = 0;
|
||||
for (;;) {
|
||||
unsigned long *rinp, *routp, *rexp, *inp, *outp, *exp;
|
||||
bool can_ll = false;
|
||||
|
||||
inp = fds->in; outp = fds->out; exp = fds->ex;
|
||||
rinp = fds->res_in; routp = fds->res_out; rexp = fds->res_ex;
|
||||
|
@ -449,7 +454,8 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time)
|
|||
f_op = f.file->f_op;
|
||||
mask = DEFAULT_POLLMASK;
|
||||
if (f_op && f_op->poll) {
|
||||
wait_key_set(wait, in, out, bit);
|
||||
wait_key_set(wait, in, out,
|
||||
bit, ll_flag);
|
||||
mask = (*f_op->poll)(f.file, wait);
|
||||
}
|
||||
fdput(f);
|
||||
|
@ -468,6 +474,11 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time)
|
|||
retval++;
|
||||
wait->_qproc = NULL;
|
||||
}
|
||||
if (mask & POLL_LL)
|
||||
can_ll = true;
|
||||
/* got something, stop busy polling */
|
||||
if (retval)
|
||||
ll_flag = 0;
|
||||
}
|
||||
}
|
||||
if (res_in)
|
||||
|
@ -486,6 +497,9 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time)
|
|||
break;
|
||||
}
|
||||
|
||||
if (can_ll && can_poll_ll(ll_time))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* If this is the first loop and we have a timeout
|
||||
* given, then we convert to ktime_t and set the to
|
||||
|
@ -717,7 +731,8 @@ struct poll_list {
|
|||
* pwait poll_table will be used by the fd-provided poll handler for waiting,
|
||||
* if pwait->_qproc is non-NULL.
|
||||
*/
|
||||
static inline unsigned int do_pollfd(struct pollfd *pollfd, poll_table *pwait)
|
||||
static inline unsigned int do_pollfd(struct pollfd *pollfd, poll_table *pwait,
|
||||
bool *can_ll, unsigned int ll_flag)
|
||||
{
|
||||
unsigned int mask;
|
||||
int fd;
|
||||
|
@ -731,7 +746,10 @@ static inline unsigned int do_pollfd(struct pollfd *pollfd, poll_table *pwait)
|
|||
mask = DEFAULT_POLLMASK;
|
||||
if (f.file->f_op && f.file->f_op->poll) {
|
||||
pwait->_key = pollfd->events|POLLERR|POLLHUP;
|
||||
pwait->_key |= ll_flag;
|
||||
mask = f.file->f_op->poll(f.file, pwait);
|
||||
if (mask & POLL_LL)
|
||||
*can_ll = true;
|
||||
}
|
||||
/* Mask out unneeded events. */
|
||||
mask &= pollfd->events | POLLERR | POLLHUP;
|
||||
|
@ -750,6 +768,8 @@ static int do_poll(unsigned int nfds, struct poll_list *list,
|
|||
ktime_t expire, *to = NULL;
|
||||
int timed_out = 0, count = 0;
|
||||
unsigned long slack = 0;
|
||||
unsigned int ll_flag = POLL_LL;
|
||||
u64 ll_time = ll_end_time();
|
||||
|
||||
/* Optimise the no-wait case */
|
||||
if (end_time && !end_time->tv_sec && !end_time->tv_nsec) {
|
||||
|
@ -762,6 +782,7 @@ static int do_poll(unsigned int nfds, struct poll_list *list,
|
|||
|
||||
for (;;) {
|
||||
struct poll_list *walk;
|
||||
bool can_ll = false;
|
||||
|
||||
for (walk = list; walk != NULL; walk = walk->next) {
|
||||
struct pollfd * pfd, * pfd_end;
|
||||
|
@ -776,9 +797,10 @@ static int do_poll(unsigned int nfds, struct poll_list *list,
|
|||
* this. They'll get immediately deregistered
|
||||
* when we break out and return.
|
||||
*/
|
||||
if (do_pollfd(pfd, pt)) {
|
||||
if (do_pollfd(pfd, pt, &can_ll, ll_flag)) {
|
||||
count++;
|
||||
pt->_qproc = NULL;
|
||||
ll_flag = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -795,6 +817,8 @@ static int do_poll(unsigned int nfds, struct poll_list *list,
|
|||
if (count || timed_out)
|
||||
break;
|
||||
|
||||
if (can_ll && can_poll_ll(ll_time))
|
||||
continue;
|
||||
/*
|
||||
* If this is the first loop and we have a timeout
|
||||
* given, then we convert to ktime_t and set the to
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue