]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/kern/kern_subr.c
Fix some unused variables.
[FreeBSD/FreeBSD.git] / sys / kern / kern_subr.c
1 /*
2  * Copyright (c) 1982, 1986, 1991, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  * (c) UNIX System Laboratories, Inc.
5  * All or some portions of this file are derived from material licensed
6  * to the University of California by American Telephone and Telegraph
7  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8  * the permission of UNIX System Laboratories, Inc.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *      This product includes software developed by the University of
21  *      California, Berkeley and its contributors.
22  * 4. Neither the name of the University nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  *
38  *      @(#)kern_subr.c 8.3 (Berkeley) 1/21/94
39  * $FreeBSD$
40  */
41
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/kernel.h>
45 #include <sys/ktr.h>
46 #include <sys/lock.h>
47 #include <sys/mutex.h>
48 #include <sys/proc.h>
49 #include <sys/malloc.h>
50 #include <sys/resourcevar.h>
51 #include <sys/sysctl.h>
52 #include <sys/vnode.h>
53
54 #include <vm/vm.h>
55 #include <vm/vm_page.h>
56 #include <vm/vm_map.h>
57
58 SYSCTL_INT(_kern, KERN_IOV_MAX, iov_max, CTLFLAG_RD, NULL, UIO_MAXIOV, 
59         "Maximum number of elements in an I/O vector; sysconf(_SC_IOV_MAX)");
60
61 int
62 uiomove(cp, n, uio)
63         register caddr_t cp;
64         register int n;
65         register struct uio *uio;
66 {
67         struct thread *td = curthread;
68         register struct iovec *iov;
69         u_int cnt;
70         int error = 0;
71         int save = 0;
72
73         KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE,
74             ("uiomove: mode"));
75         KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread,
76             ("uiomove proc"));
77
78         if (td) {
79                 mtx_lock_spin(&sched_lock);
80                 save = td->td_flags & TDF_DEADLKTREAT;
81                 td->td_flags |= TDF_DEADLKTREAT;
82                 mtx_unlock_spin(&sched_lock);
83         }
84
85         while (n > 0 && uio->uio_resid) {
86                 iov = uio->uio_iov;
87                 cnt = iov->iov_len;
88                 if (cnt == 0) {
89                         uio->uio_iov++;
90                         uio->uio_iovcnt--;
91                         continue;
92                 }
93                 if (cnt > n)
94                         cnt = n;
95
96                 switch (uio->uio_segflg) {
97
98                 case UIO_USERSPACE:
99                 case UIO_USERISPACE:
100                         if (ticks - PCPU_GET(switchticks) >= hogticks)
101                                 uio_yield();
102                         if (uio->uio_rw == UIO_READ)
103                                 error = copyout(cp, iov->iov_base, cnt);
104                         else
105                                 error = copyin(iov->iov_base, cp, cnt);
106                         if (error)
107                                 goto out;
108                         break;
109
110                 case UIO_SYSSPACE:
111                         if (uio->uio_rw == UIO_READ)
112                                 bcopy((caddr_t)cp, iov->iov_base, cnt);
113                         else
114                                 bcopy(iov->iov_base, (caddr_t)cp, cnt);
115                         break;
116                 case UIO_NOCOPY:
117                         break;
118                 }
119                 iov->iov_base += cnt;
120                 iov->iov_len -= cnt;
121                 uio->uio_resid -= cnt;
122                 uio->uio_offset += cnt;
123                 cp += cnt;
124                 n -= cnt;
125         }
126 out:
127         if (td != curthread) printf("uiomove: IT CHANGED!");
128         td = curthread; /* Might things have changed in copyin/copyout? */
129         if (td) {
130                 mtx_lock_spin(&sched_lock);
131                 td->td_flags = (td->td_flags & ~TDF_DEADLKTREAT) | save;
132                 mtx_unlock_spin(&sched_lock);
133         }
134         return (error);
135 }
136
137 int
138 uiomoveco(cp, n, uio, obj)
139         caddr_t cp;
140         int n;
141         struct uio *uio;
142         struct vm_object *obj;
143 {
144         struct iovec *iov;
145         u_int cnt;
146         int error;
147
148         KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE,
149             ("uiomoveco: mode"));
150         KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread,
151             ("uiomoveco proc"));
152
153         while (n > 0 && uio->uio_resid) {
154                 iov = uio->uio_iov;
155                 cnt = iov->iov_len;
156                 if (cnt == 0) {
157                         uio->uio_iov++;
158                         uio->uio_iovcnt--;
159                         continue;
160                 }
161                 if (cnt > n)
162                         cnt = n;
163
164                 switch (uio->uio_segflg) {
165
166                 case UIO_USERSPACE:
167                 case UIO_USERISPACE:
168                         if (ticks - PCPU_GET(switchticks) >= hogticks)
169                                 uio_yield();
170                         if (uio->uio_rw == UIO_READ) {
171 #ifdef ENABLE_VFS_IOOPT
172                                 if (vfs_ioopt && ((cnt & PAGE_MASK) == 0) &&
173                                         ((((intptr_t) iov->iov_base) & PAGE_MASK) == 0) &&
174                                         ((uio->uio_offset & PAGE_MASK) == 0) &&
175                                         ((((intptr_t) cp) & PAGE_MASK) == 0)) {
176                                                 error = vm_uiomove(&curproc->p_vmspace->vm_map, obj,
177                                                                 uio->uio_offset, cnt,
178                                                                 (vm_offset_t) iov->iov_base, NULL);
179                                 } else
180 #endif
181                                 {
182                                         error = copyout(cp, iov->iov_base, cnt);
183                                 }
184                         } else {
185                                 error = copyin(iov->iov_base, cp, cnt);
186                         }
187                         if (error)
188                                 return (error);
189                         break;
190
191                 case UIO_SYSSPACE:
192                         if (uio->uio_rw == UIO_READ)
193                                 bcopy((caddr_t)cp, iov->iov_base, cnt);
194                         else
195                                 bcopy(iov->iov_base, (caddr_t)cp, cnt);
196                         break;
197                 case UIO_NOCOPY:
198                         break;
199                 }
200                 iov->iov_base += cnt;
201                 iov->iov_len -= cnt;
202                 uio->uio_resid -= cnt;
203                 uio->uio_offset += cnt;
204                 cp += cnt;
205                 n -= cnt;
206         }
207         return (0);
208 }
209
210 #ifdef ENABLE_VFS_IOOPT
211
212 int
213 uioread(n, uio, obj, nread)
214         int n;
215         struct uio *uio;
216         struct vm_object *obj;
217         int *nread;
218 {
219         int npagesmoved;
220         struct iovec *iov;
221         u_int cnt, tcnt;
222         int error;
223
224         *nread = 0;
225         if (vfs_ioopt < 2)
226                 return 0;
227
228         error = 0;
229
230         while (n > 0 && uio->uio_resid) {
231                 iov = uio->uio_iov;
232                 cnt = iov->iov_len;
233                 if (cnt == 0) {
234                         uio->uio_iov++;
235                         uio->uio_iovcnt--;
236                         continue;
237                 }
238                 if (cnt > n)
239                         cnt = n;
240
241                 if ((uio->uio_segflg == UIO_USERSPACE) &&
242                         ((((intptr_t) iov->iov_base) & PAGE_MASK) == 0) &&
243                                  ((uio->uio_offset & PAGE_MASK) == 0) ) {
244
245                         if (cnt < PAGE_SIZE)
246                                 break;
247
248                         cnt &= ~PAGE_MASK;
249
250                         if (ticks - PCPU_GET(switchticks) >= hogticks)
251                                 uio_yield();
252                         error = vm_uiomove(&curproc->p_vmspace->vm_map, obj,
253                                                 uio->uio_offset, cnt,
254                                                 (vm_offset_t) iov->iov_base, &npagesmoved);
255
256                         if (npagesmoved == 0)
257                                 break;
258
259                         tcnt = npagesmoved * PAGE_SIZE;
260                         cnt = tcnt;
261
262                         if (error)
263                                 break;
264
265                         iov->iov_base += cnt;
266                         iov->iov_len -= cnt;
267                         uio->uio_resid -= cnt;
268                         uio->uio_offset += cnt;
269                         *nread += cnt;
270                         n -= cnt;
271                 } else {
272                         break;
273                 }
274         }
275         return error;
276 }
277
278 #endif
279
280 /*
281  * Give next character to user as result of read.
282  */
283 int
284 ureadc(c, uio)
285         register int c;
286         register struct uio *uio;
287 {
288         register struct iovec *iov;
289
290 again:
291         if (uio->uio_iovcnt == 0 || uio->uio_resid == 0)
292                 panic("ureadc");
293         iov = uio->uio_iov;
294         if (iov->iov_len == 0) {
295                 uio->uio_iovcnt--;
296                 uio->uio_iov++;
297                 goto again;
298         }
299         switch (uio->uio_segflg) {
300
301         case UIO_USERSPACE:
302                 if (subyte(iov->iov_base, c) < 0)
303                         return (EFAULT);
304                 break;
305
306         case UIO_SYSSPACE:
307                 *iov->iov_base = c;
308                 break;
309
310         case UIO_USERISPACE:
311                 if (suibyte(iov->iov_base, c) < 0)
312                         return (EFAULT);
313                 break;
314         case UIO_NOCOPY:
315                 break;
316         }
317         iov->iov_base++;
318         iov->iov_len--;
319         uio->uio_resid--;
320         uio->uio_offset++;
321         return (0);
322 }
323
324 /*
325  * General routine to allocate a hash table.
326  */
327 void *
328 hashinit(elements, type, hashmask)
329         int elements;
330         struct malloc_type *type;
331         u_long *hashmask;
332 {
333         long hashsize;
334         LIST_HEAD(generic, generic) *hashtbl;
335         int i;
336
337         if (elements <= 0)
338                 panic("hashinit: bad elements");
339         for (hashsize = 1; hashsize <= elements; hashsize <<= 1)
340                 continue;
341         hashsize >>= 1;
342         hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl), type, M_WAITOK);
343         for (i = 0; i < hashsize; i++)
344                 LIST_INIT(&hashtbl[i]);
345         *hashmask = hashsize - 1;
346         return (hashtbl);
347 }
348
349 static int primes[] = { 1, 13, 31, 61, 127, 251, 509, 761, 1021, 1531, 2039,
350                         2557, 3067, 3583, 4093, 4603, 5119, 5623, 6143, 6653,
351                         7159, 7673, 8191, 12281, 16381, 24571, 32749 };
352 #define NPRIMES (sizeof(primes) / sizeof(primes[0]))
353
354 /*
355  * General routine to allocate a prime number sized hash table.
356  */
357 void *
358 phashinit(elements, type, nentries)
359         int elements;
360         struct malloc_type *type;
361         u_long *nentries;
362 {
363         long hashsize;
364         LIST_HEAD(generic, generic) *hashtbl;
365         int i;
366
367         if (elements <= 0)
368                 panic("phashinit: bad elements");
369         for (i = 1, hashsize = primes[1]; hashsize <= elements;) {
370                 i++;
371                 if (i == NPRIMES)
372                         break;
373                 hashsize = primes[i];
374         }
375         hashsize = primes[i - 1];
376         hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl), type, M_WAITOK);
377         for (i = 0; i < hashsize; i++)
378                 LIST_INIT(&hashtbl[i]);
379         *nentries = hashsize;
380         return (hashtbl);
381 }
382
383 void
384 uio_yield()
385 {
386         struct thread *td;
387
388         td = curthread;
389         mtx_lock_spin(&sched_lock);
390         DROP_GIANT();
391         td->td_priority = td->td_ksegrp->kg_user_pri; /* XXXKSE */
392         setrunqueue(td);
393         td->td_proc->p_stats->p_ru.ru_nivcsw++;
394         mi_switch();
395         mtx_unlock_spin(&sched_lock);
396         PICKUP_GIANT();
397 }
398
399 int
400 copyinfrom(const void *src, void *dst, size_t len, int seg)
401 {
402         int error = 0;
403
404         switch (seg) {
405         case UIO_USERSPACE:
406                 error = copyin(src, dst, len);
407                 break;
408         case UIO_SYSSPACE:
409                 bcopy(src, dst, len);
410                 break;
411         default:
412                 panic("copyinfrom: bad seg %d\n", seg);
413         }
414         return (error);
415 }
416
417 int
418 copyinstrfrom(const void *src, void *dst, size_t len, size_t *copied, int seg)
419 {
420         int error = 0;
421
422         switch (seg) {
423         case UIO_USERSPACE:
424                 error = copyinstr(src, dst, len, copied);
425                 break;
426         case UIO_SYSSPACE:
427                 error = copystr(src, dst, len, copied);
428                 break;
429         default:
430                 panic("copyinstrfrom: bad seg %d\n", seg);
431         }
432         return (error);
433 }