1439 lines · 34.5 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0/* * This file contains the procedures for the handling of select and poll * * Created for Linux based loosely upon Mathius Lattner's minix * patches by Peter MacDonald. Heavily edited by Linus. * *  4 February 1994 *     COFF/ELF binary emulation. If the process has the STICKY_TIMEOUTS *     flag set in its personality we do *not* modify the given timeout *     parameter to reflect time remaining. * *  24 January 2000 *     Changed sys_poll()/do_poll() to use PAGE_SIZE chunk-based allocation  *     of fds to overcome nfds < 16390 descriptors limit (Tigran Aivazian). */ #include <linux/kernel.h>#include <linux/sched/signal.h>#include <linux/sched/rt.h>#include <linux/syscalls.h>#include <linux/export.h>#include <linux/slab.h>#include <linux/poll.h>#include <linux/personality.h> /* for STICKY_TIMEOUTS */#include <linux/file.h>#include <linux/fdtable.h>#include <linux/fs.h>#include <linux/rcupdate.h>#include <linux/hrtimer.h>#include <linux/freezer.h>#include <net/busy_poll.h>#include <linux/vmalloc.h> #include <linux/uaccess.h>  /* * Estimate expected accuracy in ns from a timeval. * * After quite a bit of churning around, we've settled on * a simple thing of taking 0.1% of the timeout as the * slack, with a cap of 100 msec. * "nice" tasks get a 0.5% slack instead. * * Consider this comment an open invitation to come up with even * better solutions.. */ #define MAX_SLACK	(100 * NSEC_PER_MSEC) static long __estimate_accuracy(struct timespec64 *tv){	long slack;	int divfactor = 1000; 	if (tv->tv_sec < 0)		return 0; 	if (task_nice(current) > 0)		divfactor = divfactor / 5; 	if (tv->tv_sec > MAX_SLACK / (NSEC_PER_SEC/divfactor))		return MAX_SLACK; 	slack = tv->tv_nsec / divfactor;	slack += tv->tv_sec * (NSEC_PER_SEC/divfactor); 	if (slack > MAX_SLACK)		return MAX_SLACK; 	return slack;} u64 select_estimate_accuracy(struct timespec64 *tv){	u64 ret;	struct timespec64 now; 	/*	 * Realtime tasks get a slack of 0 for obvious reasons.	 */ 	if (rt_task(current))		return 0; 	ktime_get_ts64(&now);	now = timespec64_sub(*tv, now);	ret = __estimate_accuracy(&now);	if (ret < current->timer_slack_ns)		return current->timer_slack_ns;	return ret;}   struct poll_table_page {	struct poll_table_page * next;	struct poll_table_entry * entry;	struct poll_table_entry entries[0];}; #define POLL_TABLE_FULL(table) \	((unsigned long)((table)->entry+1) > PAGE_SIZE + (unsigned long)(table)) /* * Ok, Peter made a complicated, but straightforward multiple_wait() function. * I have rewritten this, taking some shortcuts: This code may not be easy to * follow, but it should be free of race-conditions, and it's practical. If you * understand what I'm doing here, then you understand how the linux * sleep/wakeup mechanism works. * * Two very simple procedures, poll_wait() and poll_freewait() make all the * work.  poll_wait() is an inline-function defined in <linux/poll.h>, * as all select/poll functions have to call it to add an entry to the * poll table. */static void __pollwait(struct file *filp, wait_queue_head_t *wait_address,		       poll_table *p); void poll_initwait(struct poll_wqueues *pwq){	init_poll_funcptr(&pwq->pt, __pollwait);	pwq->polling_task = current;	pwq->triggered = 0;	pwq->error = 0;	pwq->table = NULL;	pwq->inline_index = 0;}EXPORT_SYMBOL(poll_initwait); static void free_poll_entry(struct poll_table_entry *entry){	remove_wait_queue(entry->wait_address, &entry->wait);	fput(entry->filp);} void poll_freewait(struct poll_wqueues *pwq){	struct poll_table_page * p = pwq->table;	int i;	for (i = 0; i < pwq->inline_index; i++)		free_poll_entry(pwq->inline_entries + i);	while (p) {		struct poll_table_entry * entry;		struct poll_table_page *old; 		entry = p->entry;		do {			entry--;			free_poll_entry(entry);		} while (entry > p->entries);		old = p;		p = p->next;		free_page((unsigned long) old);	}}EXPORT_SYMBOL(poll_freewait); static struct poll_table_entry *poll_get_entry(struct poll_wqueues *p){	struct poll_table_page *table = p->table; 	if (p->inline_index < N_INLINE_POLL_ENTRIES)		return p->inline_entries + p->inline_index++; 	if (!table || POLL_TABLE_FULL(table)) {		struct poll_table_page *new_table; 		new_table = (struct poll_table_page *) __get_free_page(GFP_KERNEL);		if (!new_table) {			p->error = -ENOMEM;			return NULL;		}		new_table->entry = new_table->entries;		new_table->next = table;		p->table = new_table;		table = new_table;	} 	return table->entry++;} static int __pollwake(wait_queue_entry_t *wait, unsigned mode, int sync, void *key){	struct poll_wqueues *pwq = wait->private;	DECLARE_WAITQUEUE(dummy_wait, pwq->polling_task); 	/*	 * Although this function is called under waitqueue lock, LOCK	 * doesn't imply write barrier and the users expect write	 * barrier semantics on wakeup functions.  The following	 * smp_wmb() is equivalent to smp_wmb() in try_to_wake_up()	 * and is paired with smp_store_mb() in poll_schedule_timeout.	 */	smp_wmb();	pwq->triggered = 1; 	/*	 * Perform the default wake up operation using a dummy	 * waitqueue.	 *	 * TODO: This is hacky but there currently is no interface to	 * pass in @sync.  @sync is scheduled to be removed and once	 * that happens, wake_up_process() can be used directly.	 */	return default_wake_function(&dummy_wait, mode, sync, key);} static int pollwake(wait_queue_entry_t *wait, unsigned mode, int sync, void *key){	struct poll_table_entry *entry; 	entry = container_of(wait, struct poll_table_entry, wait);	if (key && !(key_to_poll(key) & entry->key))		return 0;	return __pollwake(wait, mode, sync, key);} /* Add a new entry */static void __pollwait(struct file *filp, wait_queue_head_t *wait_address,				poll_table *p){	struct poll_wqueues *pwq = container_of(p, struct poll_wqueues, pt);	struct poll_table_entry *entry = poll_get_entry(pwq);	if (!entry)		return;	entry->filp = get_file(filp);	entry->wait_address = wait_address;	entry->key = p->_key;	init_waitqueue_func_entry(&entry->wait, pollwake);	entry->wait.private = pwq;	add_wait_queue(wait_address, &entry->wait);} static int poll_schedule_timeout(struct poll_wqueues *pwq, int state,			  ktime_t *expires, unsigned long slack){	int rc = -EINTR; 	set_current_state(state);	if (!pwq->triggered)		rc = schedule_hrtimeout_range(expires, slack, HRTIMER_MODE_ABS);	__set_current_state(TASK_RUNNING); 	/*	 * Prepare for the next iteration.	 *	 * The following smp_store_mb() serves two purposes.  First, it's	 * the counterpart rmb of the wmb in pollwake() such that data	 * written before wake up is always visible after wake up.	 * Second, the full barrier guarantees that triggered clearing	 * doesn't pass event check of the next iteration.  Note that	 * this problem doesn't exist for the first iteration as	 * add_wait_queue() has full barrier semantics.	 */	smp_store_mb(pwq->triggered, 0); 	return rc;} /** * poll_select_set_timeout - helper function to setup the timeout value * @to:		pointer to timespec64 variable for the final timeout * @sec:	seconds (from user space) * @nsec:	nanoseconds (from user space) * * Note, we do not use a timespec for the user space value here, That * way we can use the function for timeval and compat interfaces as well. * * Returns -EINVAL if sec/nsec are not normalized. Otherwise 0. */int poll_select_set_timeout(struct timespec64 *to, time64_t sec, long nsec){	struct timespec64 ts = {.tv_sec = sec, .tv_nsec = nsec}; 	if (!timespec64_valid(&ts))		return -EINVAL; 	/* Optimize for the zero timeout value here */	if (!sec && !nsec) {		to->tv_sec = to->tv_nsec = 0;	} else {		ktime_get_ts64(to);		*to = timespec64_add_safe(*to, ts);	}	return 0;} enum poll_time_type {	PT_TIMEVAL = 0,	PT_OLD_TIMEVAL = 1,	PT_TIMESPEC = 2,	PT_OLD_TIMESPEC = 3,}; static int poll_select_finish(struct timespec64 *end_time,			      void __user *p,			      enum poll_time_type pt_type, int ret){	struct timespec64 rts; 	restore_saved_sigmask_unless(ret == -ERESTARTNOHAND); 	if (!p)		return ret; 	if (current->personality & STICKY_TIMEOUTS)		goto sticky; 	/* No update for zero timeout */	if (!end_time->tv_sec && !end_time->tv_nsec)		return ret; 	ktime_get_ts64(&rts);	rts = timespec64_sub(*end_time, rts);	if (rts.tv_sec < 0)		rts.tv_sec = rts.tv_nsec = 0;  	switch (pt_type) {	case PT_TIMEVAL:		{			struct __kernel_old_timeval rtv; 			if (sizeof(rtv) > sizeof(rtv.tv_sec) + sizeof(rtv.tv_usec))				memset(&rtv, 0, sizeof(rtv));			rtv.tv_sec = rts.tv_sec;			rtv.tv_usec = rts.tv_nsec / NSEC_PER_USEC;			if (!copy_to_user(p, &rtv, sizeof(rtv)))				return ret;		}		break;	case PT_OLD_TIMEVAL:		{			struct old_timeval32 rtv; 			rtv.tv_sec = rts.tv_sec;			rtv.tv_usec = rts.tv_nsec / NSEC_PER_USEC;			if (!copy_to_user(p, &rtv, sizeof(rtv)))				return ret;		}		break;	case PT_TIMESPEC:		if (!put_timespec64(&rts, p))			return ret;		break;	case PT_OLD_TIMESPEC:		if (!put_old_timespec32(&rts, p))			return ret;		break;	default:		BUG();	}	/*	 * If an application puts its timeval in read-only memory, we	 * don't want the Linux-specific update to the timeval to	 * cause a fault after the select has completed	 * successfully. However, because we're not updating the	 * timeval, we can't restart the system call.	 */ sticky:	if (ret == -ERESTARTNOHAND)		ret = -EINTR;	return ret;} /* * Scalable version of the fd_set. */ typedef struct {	unsigned long *in, *out, *ex;	unsigned long *res_in, *res_out, *res_ex;} fd_set_bits; /* * How many longwords for "nr" bits? */#define FDS_BITPERLONG	(8*sizeof(long))#define FDS_LONGS(nr)	(((nr)+FDS_BITPERLONG-1)/FDS_BITPERLONG)#define FDS_BYTES(nr)	(FDS_LONGS(nr)*sizeof(long)) /* * Use "unsigned long" accesses to let user-mode fd_set's be long-aligned. */static inlineint get_fd_set(unsigned long nr, void __user *ufdset, unsigned long *fdset){	nr = FDS_BYTES(nr);	if (ufdset)		return copy_from_user(fdset, ufdset, nr) ? -EFAULT : 0; 	memset(fdset, 0, nr);	return 0;} static inline unsigned long __must_checkset_fd_set(unsigned long nr, void __user *ufdset, unsigned long *fdset){	if (ufdset)		return __copy_to_user(ufdset, fdset, FDS_BYTES(nr));	return 0;} static inlinevoid zero_fd_set(unsigned long nr, unsigned long *fdset){	memset(fdset, 0, FDS_BYTES(nr));} #define FDS_IN(fds, n)		(fds->in + n)#define FDS_OUT(fds, n)		(fds->out + n)#define FDS_EX(fds, n)		(fds->ex + n) #define BITS(fds, n)	(*FDS_IN(fds, n)|*FDS_OUT(fds, n)|*FDS_EX(fds, n)) static int max_select_fd(unsigned long n, fd_set_bits *fds){	unsigned long *open_fds;	unsigned long set;	int max;	struct fdtable *fdt; 	/* handle last in-complete long-word first */	set = ~(~0UL << (n & (BITS_PER_LONG-1)));	n /= BITS_PER_LONG;	fdt = files_fdtable(current->files);	open_fds = fdt->open_fds + n;	max = 0;	if (set) {		set &= BITS(fds, n);		if (set) {			if (!(set & ~*open_fds))				goto get_max;			return -EBADF;		}	}	while (n) {		open_fds--;		n--;		set = BITS(fds, n);		if (!set)			continue;		if (set & ~*open_fds)			return -EBADF;		if (max)			continue;get_max:		do {			max++;			set >>= 1;		} while (set);		max += n * BITS_PER_LONG;	} 	return max;} #define POLLIN_SET (EPOLLRDNORM | EPOLLRDBAND | EPOLLIN | EPOLLHUP | EPOLLERR)#define POLLOUT_SET (EPOLLWRBAND | EPOLLWRNORM | EPOLLOUT | EPOLLERR)#define POLLEX_SET (EPOLLPRI) static inline void wait_key_set(poll_table *wait, unsigned long in,				unsigned long out, unsigned long bit,				__poll_t ll_flag){	wait->_key = POLLEX_SET | ll_flag;	if (in & bit)		wait->_key |= POLLIN_SET;	if (out & bit)		wait->_key |= POLLOUT_SET;} static int do_select(int n, fd_set_bits *fds, struct timespec64 *end_time){	ktime_t expire, *to = NULL;	struct poll_wqueues table;	poll_table *wait;	int retval, i, timed_out = 0;	u64 slack = 0;	__poll_t busy_flag = net_busy_loop_on() ? POLL_BUSY_LOOP : 0;	unsigned long busy_start = 0; 	rcu_read_lock();	retval = max_select_fd(n, fds);	rcu_read_unlock(); 	if (retval < 0)		return retval;	n = retval; 	poll_initwait(&table);	wait = &table.pt;	if (end_time && !end_time->tv_sec && !end_time->tv_nsec) {		wait->_qproc = NULL;		timed_out = 1;	} 

Lines 1–500 of 1439.