]> git.saurik.com Git - apple/xnu.git/blame - bsd/kern/bsd_stubs.c
xnu-1699.32.7.tar.gz
[apple/xnu.git] / bsd / kern / bsd_stubs.c
CommitLineData
1c79356b 1/*
5d5c5d0d
A
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
2d21ac55
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
8f6c56a5 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
8f6c56a5 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
27 */
28#include <sys/time.h>
29#include <kern/task.h>
30#include <kern/thread.h>
31#include <mach/mach_types.h>
32#include <mach/vm_prot.h>
33#include <vm/vm_kern.h>
6d2010ae 34#include <sys/stat.h>
1c79356b
A
35#include <vm/vm_map.h>
36#include <sys/systm.h>
6d2010ae 37#include <kern/assert.h>
1c79356b 38#include <sys/conf.h>
91447636 39#include <sys/proc_internal.h>
1c79356b 40#include <sys/buf.h> /* for SET */
b0d623f7 41#include <sys/kernel.h>
0b4e3aa0 42#include <sys/user.h>
0c530ab8
A
43#include <sys/sysent.h>
44#include <sys/sysproto.h>
1c79356b 45
2d21ac55
A
46/* XXX these should be in a common header somwhere, but aren't */
47extern int chrtoblk_set(int, int);
b0d623f7 48extern vm_offset_t kmem_mb_alloc(vm_map_t, int, int);
2d21ac55
A
49
50/* XXX most of these just exist to export; there's no good header for them*/
51void pcb_synch(void);
2d21ac55
A
52void tbeproc(void *);
53
6d2010ae
A
54TAILQ_HEAD(,devsw_lock) devsw_locks;
55lck_mtx_t devsw_lock_list_mtx;
56lck_grp_t *devsw_lock_grp;
2d21ac55 57
1c79356b
A
58/* Just to satisfy pstat command */
59int dmmin, dmmax, dmtext;
60
91447636 61vm_offset_t
b0d623f7 62kmem_mb_alloc(vm_map_t mbmap, int size, int physContig)
1c79356b 63{
b0d623f7
A
64 vm_offset_t addr = 0;
65 kern_return_t kr = KERN_SUCCESS;
66
67 if(!physContig)
68 kr = kernel_memory_allocate(mbmap, &addr, size,
69 0, KMA_NOPAGEWAIT|KMA_KOBJECT|KMA_LOMEM);
1c79356b 70 else
b0d623f7
A
71 kr = kmem_alloc_contig(mbmap, &addr, size, PAGE_MASK,
72 0xfffff, 0, KMA_NOPAGEWAIT | KMA_KOBJECT | KMA_LOMEM);
73
74 if( kr != KERN_SUCCESS)
75 addr = 0;
76
77 return addr;
1c79356b
A
78}
79
91447636
A
80/*
81 * XXX this function only exists to be exported and do nothing.
82 */
83void
84pcb_synch(void)
85{
86}
1c79356b
A
87
88struct proc *
89current_proc(void)
90{
91 /* Never returns a NULL */
0b4e3aa0
A
92 struct uthread * ut;
93 struct proc *p;
2d21ac55 94 thread_t thread = current_thread();
0b4e3aa0 95
2d21ac55 96 ut = (struct uthread *)get_bsdthread_info(thread);
91447636 97 if (ut && (ut->uu_flag & UT_VFORK) && ut->uu_proc) {
0b4e3aa0 98 p = ut->uu_proc;
2d21ac55 99 if ((p->p_lflag & P_LINVFORK) == 0)
0b4e3aa0 100 panic("returning child proc not under vfork");
2d21ac55 101 if (p->p_vforkact != (void *)thread)
0b4e3aa0
A
102 panic("returning child proc which is not cur_act");
103 return(p);
104 }
105
106 p = (struct proc *)get_bsdtask_info(current_task());
107
1c79356b 108 if (p == NULL)
0b4e3aa0
A
109 return (kernproc);
110
1c79356b
A
111 return (p);
112}
113
114/* Device switch add delete routines */
115
1c79356b
A
116struct bdevsw nobdev = NO_BDEVICE;
117struct cdevsw nocdev = NO_CDEVICE;
118/*
119 * if index is -1, return a free slot if avaliable
120 * else see whether the index is free
121 * return the major number that is free else -1
122 *
123 */
124int
125bdevsw_isfree(int index)
126{
127 struct bdevsw *devsw;
128 if (index == -1) {
129 devsw = bdevsw;
130 for(index=0; index < nblkdev; index++, devsw++) {
131 if(memcmp((char *)devsw,
132 (char *)&nobdev,
133 sizeof(struct bdevsw)) == 0)
134 break;
135 }
55e303ae
A
136 } else {
137 /* NB: Not used below unless index is in range */
138 devsw = &bdevsw[index];
1c79356b
A
139 }
140
141 if ((index < 0) || (index >= nblkdev) ||
142 (memcmp((char *)devsw,
143 (char *)&nobdev,
144 sizeof(struct bdevsw)) != 0)) {
145 return(-1);
146 }
147 return(index);
148}
149
150/*
151 * if index is -1, find a free slot to add
152 * else see whether the slot is free
153 * return the major number that is used else -1
154 */
155int
156bdevsw_add(int index, struct bdevsw * bsw)
157{
158 struct bdevsw *devsw;
159
160 if (index == -1) {
55e303ae 161 devsw = &bdevsw[1]; /* Start at slot 1 - this is a hack to fix the index=1 hack */
9bccf70c
A
162 /* yes, start at 1 to avoid collision with volfs (Radar 2842228) */
163 for(index=1; index < nblkdev; index++, devsw++) {
1c79356b
A
164 if(memcmp((char *)devsw,
165 (char *)&nobdev,
166 sizeof(struct bdevsw)) == 0)
167 break;
168 }
169 }
170 devsw = &bdevsw[index];
171 if ((index < 0) || (index >= nblkdev) ||
172 (memcmp((char *)devsw,
173 (char *)&nobdev,
174 sizeof(struct bdevsw)) != 0)) {
175 return(-1);
176 }
177 bdevsw[index] = *bsw;
178 return(index);
179}
180/*
181 * if the slot has the same bsw, then remove
182 * else -1
183 */
184int
185bdevsw_remove(int index, struct bdevsw * bsw)
186{
187 struct bdevsw *devsw;
188
189 devsw = &bdevsw[index];
190 if ((index < 0) || (index >= nblkdev) ||
191 (memcmp((char *)devsw,
192 (char *)bsw,
193 sizeof(struct bdevsw)) != 0)) {
194 return(-1);
195 }
196 bdevsw[index] = nobdev;
197 return(index);
198}
199
200/*
201 * if index is -1, return a free slot if avaliable
202 * else see whether the index is free
203 * return the major number that is free else -1
204 */
205int
206cdevsw_isfree(int index)
207{
208 struct cdevsw *devsw;
209
210 if (index == -1) {
211 devsw = cdevsw;
212 for(index=0; index < nchrdev; index++, devsw++) {
213 if(memcmp((char *)devsw,
214 (char *)&nocdev,
215 sizeof(struct cdevsw)) == 0)
216 break;
217 }
218 }
219 devsw = &cdevsw[index];
220 if ((index < 0) || (index >= nchrdev) ||
221 (memcmp((char *)devsw,
222 (char *)&nocdev,
223 sizeof(struct cdevsw)) != 0)) {
224 return(-1);
225 }
226 return(index);
227}
228
229/*
230 * if index is -1, find a free slot to add
231 * else see whether the slot is free
232 * return the major number that is used else -1
2d21ac55
A
233 *
234 * NOTE: In practice, -1 is unusable, since there are kernel internal
235 * devices that call this function with absolute index values,
236 * which will stomp on free-slot based assignments that happen
237 * before them. Therefore, if index is negative, we start
238 * looking for a free slot at the absolute value of index,
239 * instead of starting at 0 (lets out slot 1, but that's one
240 * of the problem slots down low - the vndevice). -12 is
241 * currently a safe starting point.
1c79356b
A
242 */
243int
244cdevsw_add(int index, struct cdevsw * csw)
245{
246 struct cdevsw *devsw;
247
2d21ac55
A
248 if (index < 0) {
249 if (index == -1)
250 index = 0; /* historical behaviour; XXX broken */
251 else
252 index = -index; /* start at least this far up in the table */
253 devsw = &cdevsw[index];
254 for(; index < nchrdev; index++, devsw++) {
1c79356b
A
255 if(memcmp((char *)devsw,
256 (char *)&nocdev,
257 sizeof(struct cdevsw)) == 0)
258 break;
259 }
260 }
261 devsw = &cdevsw[index];
262 if ((index < 0) || (index >= nchrdev) ||
263 (memcmp((char *)devsw,
264 (char *)&nocdev,
265 sizeof(struct cdevsw)) != 0)) {
266 return(-1);
267 }
268 cdevsw[index] = *csw;
269 return(index);
270}
271/*
272 * if the index has the same bsw, then remove
273 * else -1
274 */
275int
276cdevsw_remove(int index, struct cdevsw * csw)
277{
278 struct cdevsw *devsw;
279
280 devsw = &cdevsw[index];
281 if ((index < 0) || (index >= nchrdev) ||
282 (memcmp((char *)devsw,
283 (char *)csw,
284 sizeof(struct cdevsw)) != 0)) {
285 return(-1);
286 }
287 cdevsw[index] = nocdev;
6d2010ae 288 cdevsw_flags[index] = 0;
1c79356b
A
289 return(index);
290}
291
9bccf70c
A
292static int
293cdev_set_bdev(int cdev, int bdev)
294{
9bccf70c
A
295 return (chrtoblk_set(cdev, bdev));
296}
297
298int
299cdevsw_add_with_bdev(int index, struct cdevsw * csw, int bdev)
300{
301 index = cdevsw_add(index, csw);
302 if (index < 0) {
303 return (index);
304 }
305 if (cdev_set_bdev(index, bdev) < 0) {
306 cdevsw_remove(index, csw);
307 return (-1);
308 }
309 return (index);
310}
311
6d2010ae
A
312int
313cdevsw_setkqueueok(int index, struct cdevsw *csw, int use_offset)
314{
315 struct cdevsw *devsw;
316 uint64_t flags = CDEVSW_SELECT_KQUEUE;
317
318 devsw = &cdevsw[index];
319 if ((index < 0) || (index >= nchrdev) ||
320 (memcmp((char *)devsw,
321 (char *)csw,
322 sizeof(struct cdevsw)) != 0)) {
323 return(-1);
324 }
325
326 if (use_offset) {
327 flags |= CDEVSW_USE_OFFSET;
328 }
329
330 cdevsw_flags[index] = flags;
331 return 0;
332}
333
2d21ac55
A
334#include <pexpert/pexpert.h> /* for PE_parse_boot_arg */
335
2d21ac55 336void
1c79356b
A
337tbeproc(void *procp)
338{
339 struct proc *p = procp;
340
341 if (p)
b0d623f7 342 OSBitOrAtomic(P_TBE, &p->p_flag);
1c79356b
A
343 return;
344}
345
b0d623f7
A
346/*
347 * Copy the "hostname" variable into a caller-provided buffer
348 * Returns: 0 for success, ENAMETOOLONG for insufficient buffer space.
349 * On success, "len" will be set to the number of characters preceding
350 * the NULL character in the hostname.
351 */
352int
353bsd_hostname(char *buf, int bufsize, int *len)
354{
355 /*
356 * "hostname" is null-terminated, and "hostnamelen" is equivalent to strlen(hostname).
357 */
358 if (hostnamelen < bufsize) {
359 strlcpy(buf, hostname, bufsize);
360 *len = hostnamelen;
361 return 0;
362 } else {
363 return ENAMETOOLONG;
364 }
365}
366
6d2010ae
A
367void
368devsw_lock(dev_t dev, int mode)
369{
370 devsw_lock_t newlock, tmplock;
371 int res;
372
373 assert(0 <= major(dev) && major(dev) < nchrdev);
374 assert(mode == S_IFCHR || mode == S_IFBLK);
375
376 MALLOC(newlock, devsw_lock_t, sizeof(struct devsw_lock), M_TEMP, M_WAITOK | M_ZERO);
377 newlock->dl_dev = dev;
378 newlock->dl_thread = current_thread();
379 newlock->dl_mode = mode;
380
381 lck_mtx_lock_spin(&devsw_lock_list_mtx);
382retry:
383 TAILQ_FOREACH(tmplock, &devsw_locks, dl_list) {
384 if (tmplock->dl_dev == dev && tmplock->dl_mode == mode) {
385 res = msleep(tmplock, &devsw_lock_list_mtx, PVFS, "devsw_lock", NULL);
386 assert(res == 0);
387 goto retry;
388 }
389 }
390
391 TAILQ_INSERT_TAIL(&devsw_locks, newlock, dl_list);
392 lck_mtx_unlock(&devsw_lock_list_mtx);
393
394}
395void
396devsw_unlock(dev_t dev, int mode)
397{
398 devsw_lock_t tmplock;
399
400 assert(0 <= major(dev) && major(dev) < nchrdev);
401
402 lck_mtx_lock_spin(&devsw_lock_list_mtx);
403
404 TAILQ_FOREACH(tmplock, &devsw_locks, dl_list) {
405 if (tmplock->dl_dev == dev && tmplock->dl_mode == mode) {
406 break;
407 }
408 }
409
410 if (tmplock == NULL) {
411 panic("Trying to unlock, and couldn't find lock.");
412 }
413
414 if (tmplock->dl_thread != current_thread()) {
415 panic("Trying to unlock, but I don't hold the lock.");
416 }
417
418 wakeup(tmplock);
419 TAILQ_REMOVE(&devsw_locks, tmplock, dl_list);
420
421 lck_mtx_unlock(&devsw_lock_list_mtx);
422
423 FREE(tmplock, M_TEMP);
424}
425
426void
427devsw_init()
428{
429 devsw_lock_grp = lck_grp_alloc_init("devsw", NULL);
430 assert(devsw_lock_grp != NULL);
431
432 lck_mtx_init(&devsw_lock_list_mtx, devsw_lock_grp, NULL);
433 TAILQ_INIT(&devsw_locks);
434}