This source file includes following definitions.
- free_wait
- check_in
- check_out
- check_ex
- do_select
- sys_select
1
2
3
4
5
6
7
8 #include <linux/types.h>
9 #include <linux/time.h>
10 #include <linux/fs.h>
11 #include <linux/kernel.h>
12 #include <linux/sched.h>
13 #include <linux/string.h>
14 #include <linux/stat.h>
15 #include <linux/signal.h>
16 #include <linux/errno.h>
17
18 #include <asm/segment.h>
19 #include <asm/system.h>
20
21
22
23
24
25
26
27
28
29
30
31
32
33 static void free_wait(select_table * p)
34 {
35 struct select_table_entry * entry = p->entry + p->nr;
36
37 while (p->nr > 0) {
38 p->nr--;
39 entry--;
40 remove_wait_queue(entry->wait_address,&entry->wait);
41 }
42 }
43
44
45
46
47
48 static int check_in(select_table * wait, struct inode * inode, struct file * file)
49 {
50 if (file->f_op && file->f_op->select)
51 return file->f_op->select(inode,file,SEL_IN,wait);
52 if (inode && S_ISREG(inode->i_mode))
53 return 1;
54 return 0;
55 }
56
57 static int check_out(select_table * wait, struct inode * inode, struct file * file)
58 {
59 if (file->f_op && file->f_op->select)
60 return file->f_op->select(inode,file,SEL_OUT,wait);
61 if (inode && S_ISREG(inode->i_mode))
62 return 1;
63 return 0;
64 }
65
66 static int check_ex(select_table * wait, struct inode * inode, struct file * file)
67 {
68 if (file->f_op && file->f_op->select)
69 return file->f_op->select(inode,file,SEL_EX,wait);
70 if (inode && S_ISREG(inode->i_mode))
71 return 1;
72 return 0;
73 }
74
75 int do_select(fd_set in, fd_set out, fd_set ex,
76 fd_set *inp, fd_set *outp, fd_set *exp)
77 {
78 int count;
79 select_table wait_table;
80 struct file * file;
81 int i;
82 fd_set mask;
83
84 mask = in | out | ex;
85 for (i = 0 ; i < NR_OPEN ; i++,mask >>= 1) {
86 if (!(mask & 1))
87 continue;
88 if (!current->filp[i])
89 return -EBADF;
90 if (!current->filp[i]->f_inode)
91 return -EBADF;
92 }
93 repeat:
94 wait_table.nr = 0;
95 *inp = *outp = *exp = 0;
96 count = 0;
97 current->state = TASK_INTERRUPTIBLE;
98 mask = 1;
99 for (i = 0 ; i < NR_OPEN ; i++, mask += mask) {
100 file = current->filp[i];
101 if (mask & in)
102 if (check_in(&wait_table,file->f_inode,file)) {
103 *inp |= mask;
104 count++;
105 }
106 if (mask & out)
107 if (check_out(&wait_table,file->f_inode,file)) {
108 *outp |= mask;
109 count++;
110 }
111 if (mask & ex)
112 if (check_ex(&wait_table,file->f_inode,file)) {
113 *exp |= mask;
114 count++;
115 }
116 }
117 if (!(current->signal & ~current->blocked) &&
118 current->timeout && !count) {
119 schedule();
120 free_wait(&wait_table);
121 goto repeat;
122 }
123 free_wait(&wait_table);
124 current->state = TASK_RUNNING;
125 return count;
126 }
127
128
129
130
131
132
133 int sys_select( unsigned long *buffer )
134 {
135
136 int i;
137 fd_set res_in, in = 0, *inp;
138 fd_set res_out, out = 0, *outp;
139 fd_set res_ex, ex = 0, *exp;
140 fd_set mask;
141 struct timeval *tvp;
142 unsigned long timeout;
143
144 mask = get_fs_long(buffer++);
145 if (mask >= 32)
146 mask = ~0;
147 else
148 mask = ~((~0) << mask);
149 inp = (fd_set *) get_fs_long(buffer++);
150 outp = (fd_set *) get_fs_long(buffer++);
151 exp = (fd_set *) get_fs_long(buffer++);
152 tvp = (struct timeval *) get_fs_long(buffer);
153
154 if (inp)
155 in = mask & get_fs_long(inp);
156 if (outp)
157 out = mask & get_fs_long(outp);
158 if (exp)
159 ex = mask & get_fs_long(exp);
160 timeout = 0xffffffff;
161 if (tvp) {
162 timeout = get_fs_long((unsigned long *)&tvp->tv_usec)/(1000000/HZ);
163 timeout += get_fs_long((unsigned long *)&tvp->tv_sec) * HZ;
164 timeout += jiffies;
165 }
166 current->timeout = timeout;
167 i = do_select(in, out, ex, &res_in, &res_out, &res_ex);
168 if (current->timeout > jiffies)
169 timeout = current->timeout - jiffies;
170 else
171 timeout = 0;
172 current->timeout = 0;
173 if (tvp) {
174 verify_area(tvp, sizeof(*tvp));
175 put_fs_long(timeout/HZ, (unsigned long *) &tvp->tv_sec);
176 timeout %= HZ;
177 timeout *= (1000000/HZ);
178 put_fs_long(timeout, (unsigned long *) &tvp->tv_usec);
179 }
180 if (i < 0)
181 return i;
182 if (!i && (current->signal & ~current->blocked))
183 return -EINTR;
184 if (inp) {
185 verify_area(inp, 4);
186 put_fs_long(res_in,inp);
187 }
188 if (outp) {
189 verify_area(outp,4);
190 put_fs_long(res_out,outp);
191 }
192 if (exp) {
193 verify_area(exp,4);
194 put_fs_long(res_ex,exp);
195 }
196 return i;
197 }