patch-2.1.26 linux/fs/select.c
Next file: linux/include/asm-alpha/checksum.h
Previous file: linux/fs/nfs/nfsroot.c
Back to the patch index
Back to the overall index
- Lines: 120
- Date:
Thu Feb 6 12:51:45 1997
- Orig file:
v2.1.25/linux/fs/select.c
- Orig date:
Tue Jan 28 18:50:22 1997
diff -u --recursive --new-file v2.1.25/linux/fs/select.c linux/fs/select.c
@@ -62,25 +62,31 @@
}
/*
- * Due to kernel stack usage, we use a _limited_ fd_set type here, and once
- * we really start supporting >256 file descriptors we'll probably have to
- * allocate the kernel fd_set copies dynamically.. (The kernel select routines
- * are careful to touch only the defined low bits of any fd_set pointer, this
- * is important for performance too).
+ * For the kernel fd_set we use a fixed set-size for allocation purposes.
+ * This set-size doesn't necessarily bear any relation to the size the user
+ * uses, but should preferably obviously be larger than any possible user
+ * size (NR_OPEN bits).
+ *
+ * We need 6 bitmaps (in/out/ex for both incoming and outgoing), and we
+ * allocate one page for all the bitmaps. Thus we have 8*PAGE_SIZE bits,
+ * to be divided by 6. And we'd better make sure we round to a full
+ * long-word (in fact, we'll round to 64 bytes).
*/
-typedef unsigned long limited_fd_set[NR_OPEN/(8*(sizeof(unsigned long)))];
+#define KFDS_64BLOCK ((PAGE_SIZE/(6*64))*64)
+#define KFDS_NR (KFDS_64BLOCK*8 > NR_OPEN ? NR_OPEN : KFDS_64BLOCK*8)
+typedef unsigned long kernel_fd_set[KFDS_NR/(8*sizeof(unsigned long))];
typedef struct {
- limited_fd_set in, out, ex;
- limited_fd_set res_in, res_out, res_ex;
+ kernel_fd_set in, out, ex;
+ kernel_fd_set res_in, res_out, res_ex;
} fd_set_buffer;
#define __IN(in) (in)
-#define __OUT(in) (in + sizeof(limited_fd_set)/sizeof(unsigned long))
-#define __EX(in) (in + 2*sizeof(limited_fd_set)/sizeof(unsigned long))
-#define __RES_IN(in) (in + 3*sizeof(limited_fd_set)/sizeof(unsigned long))
-#define __RES_OUT(in) (in + 4*sizeof(limited_fd_set)/sizeof(unsigned long))
-#define __RES_EX(in) (in + 5*sizeof(limited_fd_set)/sizeof(unsigned long))
+#define __OUT(in) (in + sizeof(kernel_fd_set)/sizeof(unsigned long))
+#define __EX(in) (in + 2*sizeof(kernel_fd_set)/sizeof(unsigned long))
+#define __RES_IN(in) (in + 3*sizeof(kernel_fd_set)/sizeof(unsigned long))
+#define __RES_OUT(in) (in + 4*sizeof(kernel_fd_set)/sizeof(unsigned long))
+#define __RES_EX(in) (in + 5*sizeof(kernel_fd_set)/sizeof(unsigned long))
#define BITS(in) (*__IN(in)|*__OUT(in)|*__EX(in))
@@ -277,17 +283,20 @@
asmlinkage int sys_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp)
{
int error = -EINVAL;
- fd_set_buffer fds;
+ fd_set_buffer *fds;
unsigned long timeout;
lock_kernel();
+ fds = (fd_set_buffer *) __get_free_page(GFP_KERNEL);
+ if (!fds)
+ goto out;
if (n < 0)
goto out;
- if (n > NR_OPEN)
- n = NR_OPEN;
- if ((error = get_fd_set(n, inp, &fds.in)) ||
- (error = get_fd_set(n, outp, &fds.out)) ||
- (error = get_fd_set(n, exp, &fds.ex))) goto out;
+ if (n > KFDS_NR)
+ n = KFDS_NR;
+ if ((error = get_fd_set(n, inp, &fds->in)) ||
+ (error = get_fd_set(n, outp, &fds->out)) ||
+ (error = get_fd_set(n, exp, &fds->ex))) goto out;
timeout = ~0UL;
if (tvp) {
error = verify_area(VERIFY_WRITE, tvp, sizeof(*tvp));
@@ -303,11 +312,11 @@
if (timeout)
timeout += jiffies + 1;
}
- zero_fd_set(n, &fds.res_in);
- zero_fd_set(n, &fds.res_out);
- zero_fd_set(n, &fds.res_ex);
+ zero_fd_set(n, &fds->res_in);
+ zero_fd_set(n, &fds->res_out);
+ zero_fd_set(n, &fds->res_ex);
current->timeout = timeout;
- error = do_select(n, &fds);
+ error = do_select(n, fds);
timeout = current->timeout - jiffies - 1;
current->timeout = 0;
if ((long) timeout < 0)
@@ -326,10 +335,11 @@
goto out;
error = 0;
}
- set_fd_set(n, inp, &fds.res_in);
- set_fd_set(n, outp, &fds.res_out);
- set_fd_set(n, exp, &fds.res_ex);
+ set_fd_set(n, inp, &fds->res_in);
+ set_fd_set(n, outp, &fds->res_out);
+ set_fd_set(n, exp, &fds->res_ex);
out:
+ free_page((unsigned long) fds);
unlock_kernel();
return error;
}
@@ -376,15 +386,12 @@
asmlinkage int sys_poll(struct pollfd * ufds, unsigned int nfds, int timeout)
{
- int i, count, fdcount, err = -EINVAL;
+ int i, count, fdcount, err;
struct pollfd * fds, *fds1;
poll_table wait_table;
struct poll_table_entry *entry;
lock_kernel();
- if (nfds > NR_OPEN)
- goto out;
-
err = -ENOMEM;
entry = (struct poll_table_entry *) __get_free_page(GFP_KERNEL);
if (!entry)
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov