Messages in this thread Patch in this message | | | Date | Mon, 12 Sep 2005 11:19:32 -0400 | From | Peter Staubach <> | Subject | Re: [UPDATE PATCH][Bug 5132] fix sys_poll() large timeout handling |
| |
Nishanth Aravamudan wrote:
> >I don't think the embedded folks are going to be ok with adding a 64-bit >div in the poll() common-path... But otherwise the patch looks pretty >sane, except I think you want s64, not int64_t? I can't ever remember >myself :) > >
Oops, I missed an include which is required. The updated patch is attached.
A 64 bit quantity divided by a 32 bit quantity seems to be a standard interface in the kernel and is used fairly widely, so I suspect that the embedded folks have already done the work.
I don't know which should be used, s64 or int64_t. I chose int64_t because then it would (more or less) match the interface of do_div().
>I agree the interface mght be mis-defined. And changing timeout_msecs() >to an integer is consistent with the size of millisecond-unit variables >used elsewhere in the kernel. >
Yes, it also makes the kernel definition for sys_poll() match the user level definition for poll(2) found in <poll.h>.
Thanx...
ps
Signed-off-by: Peter Staubach <staubach@redhat.com> --- linux-2.6.13/fs/select.c.org 2005-08-28 19:41:01.000000000 -0400 +++ linux-2.6.13/fs/select.c 2005-09-12 11:11:53.000000000 -0400 @@ -24,6 +24,7 @@ #include <linux/fs.h> #include <asm/uaccess.h> +#include <asm/div64.h> #define ROUND_UP(x,y) (((x)+(y)-1)/(y)) #define DEFAULT_POLLMASK (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM) @@ -457,25 +458,34 @@ static int do_poll(unsigned int nfds, s return count; } -asmlinkage long sys_poll(struct pollfd __user * ufds, unsigned int nfds, long timeout) +asmlinkage long sys_poll(struct pollfd __user * ufds, unsigned int nfds, int timeout_msecs) { struct poll_wqueues table; int fdcount, err; unsigned int i; struct poll_list *head; struct poll_list *walk; + long timeout; + int64_t lltimeout; /* Do a sanity check on nfds ... */ if (nfds > current->files->max_fdset && nfds > OPEN_MAX) return -EINVAL; - if (timeout) { - /* Careful about overflow in the intermediate values */ - if ((unsigned long) timeout < MAX_SCHEDULE_TIMEOUT / HZ) - timeout = (unsigned long)(timeout*HZ+999)/1000+1; - else /* Negative or overflow */ + if (timeout_msecs) { + if (timeout_msecs < 0) timeout = MAX_SCHEDULE_TIMEOUT; - } + else { + lltimeout = (int64_t)timeout_msecs * HZ + 999; + do_div(lltimeout, 1000); + lltimeout++; + if (lltimeout > MAX_SCHEDULE_TIMEOUT) + timeout = MAX_SCHEDULE_TIMEOUT; + else + timeout = (long)lltimeout; + } + } else + timeout = 0; poll_initwait(&table); --- linux-2.6.13/include/linux/syscalls.h.org 2005-08-28 19:41:01.000000000 -0400 +++ linux-2.6.13/include/linux/syscalls.h 2005-09-12 10:22:25.000000000 -0400 @@ -420,7 +420,7 @@ asmlinkage long sys_socketpair(int, int, asmlinkage long sys_socketcall(int call, unsigned long __user *args); asmlinkage long sys_listen(int, int); asmlinkage long sys_poll(struct pollfd __user *ufds, unsigned int nfds, - long timeout); + int timeout_msecs); asmlinkage long sys_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, struct timeval __user *tvp); asmlinkage long sys_epoll_create(int size); | |