aboutsummaryrefslogtreecommitdiffstats
path: root/fs/select.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/select.c')
-rw-r--r--fs/select.c105
1 files changed, 77 insertions, 28 deletions
diff --git a/fs/select.c b/fs/select.c
index 87df51eadcf2..0fe0e1469df3 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -109,11 +109,11 @@ static void __pollwait(struct file *filp, wait_queue_head_t *wait_address,
109void poll_initwait(struct poll_wqueues *pwq) 109void poll_initwait(struct poll_wqueues *pwq)
110{ 110{
111 init_poll_funcptr(&pwq->pt, __pollwait); 111 init_poll_funcptr(&pwq->pt, __pollwait);
112 pwq->polling_task = current;
112 pwq->error = 0; 113 pwq->error = 0;
113 pwq->table = NULL; 114 pwq->table = NULL;
114 pwq->inline_index = 0; 115 pwq->inline_index = 0;
115} 116}
116
117EXPORT_SYMBOL(poll_initwait); 117EXPORT_SYMBOL(poll_initwait);
118 118
119static void free_poll_entry(struct poll_table_entry *entry) 119static void free_poll_entry(struct poll_table_entry *entry)
@@ -142,12 +142,10 @@ void poll_freewait(struct poll_wqueues *pwq)
142 free_page((unsigned long) old); 142 free_page((unsigned long) old);
143 } 143 }
144} 144}
145
146EXPORT_SYMBOL(poll_freewait); 145EXPORT_SYMBOL(poll_freewait);
147 146
148static struct poll_table_entry *poll_get_entry(poll_table *_p) 147static struct poll_table_entry *poll_get_entry(struct poll_wqueues *p)
149{ 148{
150 struct poll_wqueues *p = container_of(_p, struct poll_wqueues, pt);
151 struct poll_table_page *table = p->table; 149 struct poll_table_page *table = p->table;
152 150
153 if (p->inline_index < N_INLINE_POLL_ENTRIES) 151 if (p->inline_index < N_INLINE_POLL_ENTRIES)
@@ -159,7 +157,6 @@ static struct poll_table_entry *poll_get_entry(poll_table *_p)
159 new_table = (struct poll_table_page *) __get_free_page(GFP_KERNEL); 157 new_table = (struct poll_table_page *) __get_free_page(GFP_KERNEL);
160 if (!new_table) { 158 if (!new_table) {
161 p->error = -ENOMEM; 159 p->error = -ENOMEM;
162 __set_current_state(TASK_RUNNING);
163 return NULL; 160 return NULL;
164 } 161 }
165 new_table->entry = new_table->entries; 162 new_table->entry = new_table->entries;
@@ -171,20 +168,75 @@ static struct poll_table_entry *poll_get_entry(poll_table *_p)
171 return table->entry++; 168 return table->entry++;
172} 169}
173 170
171static int pollwake(wait_queue_t *wait, unsigned mode, int sync, void *key)
172{
173 struct poll_wqueues *pwq = wait->private;
174 DECLARE_WAITQUEUE(dummy_wait, pwq->polling_task);
175
176 /*
177 * Although this function is called under waitqueue lock, LOCK
178 * doesn't imply write barrier and the users expect write
179 * barrier semantics on wakeup functions. The following
180 * smp_wmb() is equivalent to smp_wmb() in try_to_wake_up()
181 * and is paired with set_mb() in poll_schedule_timeout.
182 */
183 smp_wmb();
184 pwq->triggered = 1;
185
186 /*
187 * Perform the default wake up operation using a dummy
188 * waitqueue.
189 *
190 * TODO: This is hacky but there currently is no interface to
191 * pass in @sync. @sync is scheduled to be removed and once
192 * that happens, wake_up_process() can be used directly.
193 */
194 return default_wake_function(&dummy_wait, mode, sync, key);
195}
196
174/* Add a new entry */ 197/* Add a new entry */
175static void __pollwait(struct file *filp, wait_queue_head_t *wait_address, 198static void __pollwait(struct file *filp, wait_queue_head_t *wait_address,
176 poll_table *p) 199 poll_table *p)
177{ 200{
178 struct poll_table_entry *entry = poll_get_entry(p); 201 struct poll_wqueues *pwq = container_of(p, struct poll_wqueues, pt);
202 struct poll_table_entry *entry = poll_get_entry(pwq);
179 if (!entry) 203 if (!entry)
180 return; 204 return;
181 get_file(filp); 205 get_file(filp);
182 entry->filp = filp; 206 entry->filp = filp;
183 entry->wait_address = wait_address; 207 entry->wait_address = wait_address;
184 init_waitqueue_entry(&entry->wait, current); 208 init_waitqueue_func_entry(&entry->wait, pollwake);
209 entry->wait.private = pwq;
185 add_wait_queue(wait_address, &entry->wait); 210 add_wait_queue(wait_address, &entry->wait);
186} 211}
187 212
213int poll_schedule_timeout(struct poll_wqueues *pwq, int state,
214 ktime_t *expires, unsigned long slack)
215{
216 int rc = -EINTR;
217
218 set_current_state(state);
219 if (!pwq->triggered)
220 rc = schedule_hrtimeout_range(expires, slack, HRTIMER_MODE_ABS);
221 __set_current_state(TASK_RUNNING);
222
223 /*
224 * Prepare for the next iteration.
225 *
226 * The following set_mb() serves two purposes. First, it's
227 * the counterpart rmb of the wmb in pollwake() such that data
228 * written before wake up is always visible after wake up.
229 * Second, the full barrier guarantees that triggered clearing
230 * doesn't pass event check of the next iteration. Note that
231 * this problem doesn't exist for the first iteration as
232 * add_wait_queue() has full barrier semantics.
233 */
234 set_mb(pwq->triggered, 0);
235
236 return rc;
237}
238EXPORT_SYMBOL(poll_schedule_timeout);
239
188/** 240/**
189 * poll_select_set_timeout - helper function to setup the timeout value 241 * poll_select_set_timeout - helper function to setup the timeout value
190 * @to: pointer to timespec variable for the final timeout 242 * @to: pointer to timespec variable for the final timeout
@@ -340,8 +392,6 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time)
340 for (;;) { 392 for (;;) {
341 unsigned long *rinp, *routp, *rexp, *inp, *outp, *exp; 393 unsigned long *rinp, *routp, *rexp, *inp, *outp, *exp;
342 394
343 set_current_state(TASK_INTERRUPTIBLE);
344
345 inp = fds->in; outp = fds->out; exp = fds->ex; 395 inp = fds->in; outp = fds->out; exp = fds->ex;
346 rinp = fds->res_in; routp = fds->res_out; rexp = fds->res_ex; 396 rinp = fds->res_in; routp = fds->res_out; rexp = fds->res_ex;
347 397
@@ -411,10 +461,10 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time)
411 to = &expire; 461 to = &expire;
412 } 462 }
413 463
414 if (!schedule_hrtimeout_range(to, slack, HRTIMER_MODE_ABS)) 464 if (!poll_schedule_timeout(&table, TASK_INTERRUPTIBLE,
465 to, slack))
415 timed_out = 1; 466 timed_out = 1;
416 } 467 }
417 __set_current_state(TASK_RUNNING);
418 468
419 poll_freewait(&table); 469 poll_freewait(&table);
420 470
@@ -507,8 +557,8 @@ out_nofds:
507 return ret; 557 return ret;
508} 558}
509 559
510asmlinkage long sys_select(int n, fd_set __user *inp, fd_set __user *outp, 560SYSCALL_DEFINE5(select, int, n, fd_set __user *, inp, fd_set __user *, outp,
511 fd_set __user *exp, struct timeval __user *tvp) 561 fd_set __user *, exp, struct timeval __user *, tvp)
512{ 562{
513 struct timespec end_time, *to = NULL; 563 struct timespec end_time, *to = NULL;
514 struct timeval tv; 564 struct timeval tv;
@@ -532,9 +582,9 @@ asmlinkage long sys_select(int n, fd_set __user *inp, fd_set __user *outp,
532} 582}
533 583
534#ifdef HAVE_SET_RESTORE_SIGMASK 584#ifdef HAVE_SET_RESTORE_SIGMASK
535asmlinkage long sys_pselect7(int n, fd_set __user *inp, fd_set __user *outp, 585static long do_pselect(int n, fd_set __user *inp, fd_set __user *outp,
536 fd_set __user *exp, struct timespec __user *tsp, 586 fd_set __user *exp, struct timespec __user *tsp,
537 const sigset_t __user *sigmask, size_t sigsetsize) 587 const sigset_t __user *sigmask, size_t sigsetsize)
538{ 588{
539 sigset_t ksigmask, sigsaved; 589 sigset_t ksigmask, sigsaved;
540 struct timespec ts, end_time, *to = NULL; 590 struct timespec ts, end_time, *to = NULL;
@@ -560,7 +610,7 @@ asmlinkage long sys_pselect7(int n, fd_set __user *inp, fd_set __user *outp,
560 sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved); 610 sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
561 } 611 }
562 612
563 ret = core_sys_select(n, inp, outp, exp, &end_time); 613 ret = core_sys_select(n, inp, outp, exp, to);
564 ret = poll_select_copy_remaining(&end_time, tsp, 0, ret); 614 ret = poll_select_copy_remaining(&end_time, tsp, 0, ret);
565 615
566 if (ret == -ERESTARTNOHAND) { 616 if (ret == -ERESTARTNOHAND) {
@@ -586,8 +636,9 @@ asmlinkage long sys_pselect7(int n, fd_set __user *inp, fd_set __user *outp,
586 * which has a pointer to the sigset_t itself followed by a size_t containing 636 * which has a pointer to the sigset_t itself followed by a size_t containing
587 * the sigset size. 637 * the sigset size.
588 */ 638 */
589asmlinkage long sys_pselect6(int n, fd_set __user *inp, fd_set __user *outp, 639SYSCALL_DEFINE6(pselect6, int, n, fd_set __user *, inp, fd_set __user *, outp,
590 fd_set __user *exp, struct timespec __user *tsp, void __user *sig) 640 fd_set __user *, exp, struct timespec __user *, tsp,
641 void __user *, sig)
591{ 642{
592 size_t sigsetsize = 0; 643 size_t sigsetsize = 0;
593 sigset_t __user *up = NULL; 644 sigset_t __user *up = NULL;
@@ -600,7 +651,7 @@ asmlinkage long sys_pselect6(int n, fd_set __user *inp, fd_set __user *outp,
600 return -EFAULT; 651 return -EFAULT;
601 } 652 }
602 653
603 return sys_pselect7(n, inp, outp, exp, tsp, up, sigsetsize); 654 return do_pselect(n, inp, outp, exp, tsp, up, sigsetsize);
604} 655}
605#endif /* HAVE_SET_RESTORE_SIGMASK */ 656#endif /* HAVE_SET_RESTORE_SIGMASK */
606 657
@@ -666,7 +717,6 @@ static int do_poll(unsigned int nfds, struct poll_list *list,
666 for (;;) { 717 for (;;) {
667 struct poll_list *walk; 718 struct poll_list *walk;
668 719
669 set_current_state(TASK_INTERRUPTIBLE);
670 for (walk = list; walk != NULL; walk = walk->next) { 720 for (walk = list; walk != NULL; walk = walk->next) {
671 struct pollfd * pfd, * pfd_end; 721 struct pollfd * pfd, * pfd_end;
672 722
@@ -709,10 +759,9 @@ static int do_poll(unsigned int nfds, struct poll_list *list,
709 to = &expire; 759 to = &expire;
710 } 760 }
711 761
712 if (!schedule_hrtimeout_range(to, slack, HRTIMER_MODE_ABS)) 762 if (!poll_schedule_timeout(wait, TASK_INTERRUPTIBLE, to, slack))
713 timed_out = 1; 763 timed_out = 1;
714 } 764 }
715 __set_current_state(TASK_RUNNING);
716 return count; 765 return count;
717} 766}
718 767
@@ -806,8 +855,8 @@ static long do_restart_poll(struct restart_block *restart_block)
806 return ret; 855 return ret;
807} 856}
808 857
809asmlinkage long sys_poll(struct pollfd __user *ufds, unsigned int nfds, 858SYSCALL_DEFINE3(poll, struct pollfd __user *, ufds, unsigned int, nfds,
810 long timeout_msecs) 859 long, timeout_msecs)
811{ 860{
812 struct timespec end_time, *to = NULL; 861 struct timespec end_time, *to = NULL;
813 int ret; 862 int ret;
@@ -841,9 +890,9 @@ asmlinkage long sys_poll(struct pollfd __user *ufds, unsigned int nfds,
841} 890}
842 891
843#ifdef HAVE_SET_RESTORE_SIGMASK 892#ifdef HAVE_SET_RESTORE_SIGMASK
844asmlinkage long sys_ppoll(struct pollfd __user *ufds, unsigned int nfds, 893SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds, unsigned int, nfds,
845 struct timespec __user *tsp, const sigset_t __user *sigmask, 894 struct timespec __user *, tsp, const sigset_t __user *, sigmask,
846 size_t sigsetsize) 895 size_t, sigsetsize)
847{ 896{
848 sigset_t ksigmask, sigsaved; 897 sigset_t ksigmask, sigsaved;
849 struct timespec ts, end_time, *to = NULL; 898 struct timespec ts, end_time, *to = NULL;