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