1040 lines · 25.4 KB · C
RawDownload
/* * 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.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/sched/rt.h>#include <linux/freezer.h>#include <net/busy_poll.h> #include <asm/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 timespec *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;} long select_estimate_accuracy(struct timespec *tv){	unsigned long ret;	struct timespec now; 	/*	 * Realtime tasks get a slack of 0 for obvious reasons.	 */ 	if (rt_task(current))		return 0; 	ktime_get_ts(&now);	now = timespec_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_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 set_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_t *wait, unsigned mode, int sync, void *key){	struct poll_table_entry *entry; 	entry = container_of(wait, struct poll_table_entry, wait);	if (key && !((unsigned long)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);} 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 set_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.	 */	set_mb(pwq->triggered, 0); 	return rc;}EXPORT_SYMBOL(poll_schedule_timeout); /** * poll_select_set_timeout - helper function to setup the timeout value * @to:		pointer to timespec 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 timespec *to, long sec, long nsec){	struct timespec ts = {.tv_sec = sec, .tv_nsec = nsec}; 	if (!timespec_valid(&ts))		return -EINVAL; 	/* Optimize for the zero timeout value here */	if (!sec && !nsec) {		to->tv_sec = to->tv_nsec = 0;	} else {		ktime_get_ts(to);		*to = timespec_add_safe(*to, ts);	}	return 0;} static int poll_select_copy_remaining(struct timespec *end_time, void __user *p,				      int timeval, int ret){	struct timespec rts;	struct timeval rtv; 	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_ts(&rts);	rts = timespec_sub(*end_time, rts);	if (rts.tv_sec < 0)		rts.tv_sec = rts.tv_nsec = 0; 	if (timeval) {		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; 	} else if (!copy_to_user(p, &rts, sizeof(rts)))		return ret; 	/*	 * 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;} #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 (POLLRDNORM | POLLRDBAND | POLLIN | POLLHUP | POLLERR)#define POLLOUT_SET (POLLWRBAND | POLLWRNORM | POLLOUT | POLLERR)#define POLLEX_SET (POLLPRI) static inline void wait_key_set(poll_table *wait, unsigned long in,				unsigned long out, unsigned long bit,				unsigned int ll_flag){	wait->_key = POLLEX_SET | ll_flag;	if (in & bit)		wait->_key |= POLLIN_SET;	if (out & bit)		wait->_key |= POLLOUT_SET;} int do_select(int n, fd_set_bits *fds, struct timespec *end_time){	ktime_t expire, *to = NULL;	struct poll_wqueues table;	poll_table *wait;	int retval, i, timed_out = 0;	unsigned long slack = 0;	unsigned int busy_flag = net_busy_loop_on() ? POLL_BUSY_LOOP : 0;	unsigned long busy_end = 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;	} 	if (end_time && !timed_out)		slack = select_estimate_accuracy(end_time); 	retval = 0;	for (;;) {		unsigned long *rinp, *routp, *rexp, *inp, *outp, *exp;		bool can_busy_loop = false; 		inp = fds->in; outp = fds->out; exp = fds->ex;		rinp = fds->res_in; routp = fds->res_out; rexp = fds->res_ex; 		for (i = 0; i < n; ++rinp, ++routp, ++rexp) {			unsigned long in, out, ex, all_bits, bit = 1, mask, j;			unsigned long res_in = 0, res_out = 0, res_ex = 0; 			in = *inp++; out = *outp++; ex = *exp++;			all_bits = in | out | ex;			if (all_bits == 0) {				i += BITS_PER_LONG;				continue;			} 			for (j = 0; j < BITS_PER_LONG; ++j, ++i, bit <<= 1) {				struct fd f;				if (i >= n)					break;				if (!(bit & all_bits))					continue;				f = fdget(i);				if (f.file) {					const struct file_operations *f_op;					f_op = f.file->f_op;					mask = DEFAULT_POLLMASK;					if (f_op->poll) {						wait_key_set(wait, in, out,							     bit, busy_flag);						mask = (*f_op->poll)(f.file, wait);					}					fdput(f);					if ((mask & POLLIN_SET) && (in & bit)) {						res_in |= bit;						retval++;						wait->_qproc = NULL;					}					if ((mask & POLLOUT_SET) && (out & bit)) {						res_out |= bit;						retval++;						wait->_qproc = NULL;					}					if ((mask & POLLEX_SET) && (ex & bit)) {						res_ex |= bit;						retval++;						wait->_qproc = NULL;					}					/* got something, stop busy polling */					if (retval) {						can_busy_loop = false;						busy_flag = 0; 					/*					 * only remember a returned					 * POLL_BUSY_LOOP if we asked for it					 */					} else if (busy_flag & mask)						can_busy_loop = true; 				}			}			if (res_in)				*rinp = res_in;			if (res_out)				*routp = res_out;			if (res_ex)				*rexp = res_ex;			cond_resched();		}		wait->_qproc = NULL;

Lines 1–500 of 1040.