]> git.saurik.com Git - apple/xnu.git/blame - bsd/kern/bsd_stubs.c
xnu-6153.81.5.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@
3e170ce0 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.
3e170ce0 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.
3e170ce0 17 *
2d21ac55
A
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.
3e170ce0 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>
3e170ce0 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);
cc8bc92a 48extern vm_offset_t kmem_mb_alloc(vm_map_t, int, int, kern_return_t *);
2d21ac55
A
49
50/* XXX most of these just exist to export; there's no good header for them*/
3e170ce0 51void pcb_synch(void);
2d21ac55 52
3e170ce0 53TAILQ_HEAD(, devsw_lock) devsw_locks;
6d2010ae 54lck_mtx_t devsw_lock_list_mtx;
3e170ce0 55lck_grp_t * devsw_lock_grp;
2d21ac55 56
1c79356b 57/* Just to satisfy pstat command */
3e170ce0 58int dmmin, dmmax, dmtext;
1c79356b 59
91447636 60vm_offset_t
cc8bc92a 61kmem_mb_alloc(vm_map_t mbmap, int size, int physContig, kern_return_t *err)
1c79356b 62{
3e170ce0 63 vm_offset_t addr = 0;
b0d623f7
A
64 kern_return_t kr = KERN_SUCCESS;
65
0a7de745 66 if (!physContig) {
5c9f4661 67 kr = kernel_memory_allocate(mbmap, &addr, size, 0, KMA_KOBJECT | KMA_LOMEM, VM_KERN_MEMORY_MBUF);
0a7de745 68 } else {
5c9f4661 69 kr = kmem_alloc_contig(mbmap, &addr, size, PAGE_MASK, 0xfffff, 0, KMA_KOBJECT | KMA_LOMEM, VM_KERN_MEMORY_MBUF);
0a7de745 70 }
b0d623f7 71
0a7de745 72 if (kr != KERN_SUCCESS) {
b0d623f7 73 addr = 0;
0a7de745
A
74 }
75 if (err) {
cc8bc92a 76 *err = kr;
0a7de745 77 }
b0d623f7
A
78
79 return addr;
1c79356b
A
80}
81
91447636
A
82/*
83 * XXX this function only exists to be exported and do nothing.
84 */
85void
86pcb_synch(void)
87{
88}
1c79356b
A
89
90struct proc *
91current_proc(void)
92{
93 /* Never returns a NULL */
0b4e3aa0 94 struct uthread * ut;
3e170ce0 95 struct proc * p;
2d21ac55 96 thread_t thread = current_thread();
0b4e3aa0 97
3e170ce0
A
98 ut = (struct uthread *)get_bsdthread_info(thread);
99 if (ut && (ut->uu_flag & UT_VFORK) && ut->uu_proc) {
0b4e3aa0 100 p = ut->uu_proc;
0a7de745 101 if ((p->p_lflag & P_LINVFORK) == 0) {
0b4e3aa0 102 panic("returning child proc not under vfork");
0a7de745
A
103 }
104 if (p->p_vforkact != (void *)thread) {
0b4e3aa0 105 panic("returning child proc which is not cur_act");
0a7de745
A
106 }
107 return p;
0b4e3aa0
A
108 }
109
110 p = (struct proc *)get_bsdtask_info(current_task());
111
0a7de745
A
112 if (p == NULL) {
113 return kernproc;
114 }
0b4e3aa0 115
0a7de745 116 return p;
1c79356b
A
117}
118
119/* Device switch add delete routines */
120
1c79356b
A
121struct bdevsw nobdev = NO_BDEVICE;
122struct cdevsw nocdev = NO_CDEVICE;
3e170ce0 123/*
1c79356b
A
124 * if index is -1, return a free slot if avaliable
125 * else see whether the index is free
126 * return the major number that is free else -1
127 *
316670eb
A
128 * if index is negative, we start
129 * looking for a free slot at the absolute value of index,
130 * instead of starting at 0
1c79356b
A
131 */
132int
133bdevsw_isfree(int index)
134{
3e170ce0 135 struct bdevsw * devsw;
316670eb
A
136
137 if (index < 0) {
0a7de745 138 if (index == -1) {
3e170ce0 139 index = 1; /* start at 1 to avoid collision with volfs (Radar 2842228) */
0a7de745 140 } else {
3e170ce0 141 index = -index; /* start at least this far up in the table */
0a7de745 142 }
3e170ce0
A
143 devsw = &bdevsw[index];
144 for (; index < nblkdev; index++, devsw++) {
0a7de745 145 if (memcmp((char *)devsw, (char *)&nobdev, sizeof(struct bdevsw)) == 0) {
3e170ce0 146 break;
0a7de745 147 }
3e170ce0 148 }
1c79356b 149 }
3e170ce0 150
0a7de745
A
151 if (index < 0 || index >= nblkdev) {
152 return -1;
153 }
3e170ce0 154
316670eb 155 devsw = &bdevsw[index];
3e170ce0 156 if ((memcmp((char *)devsw, (char *)&nobdev, sizeof(struct bdevsw)) != 0)) {
0a7de745 157 return -1;
1c79356b 158 }
0a7de745 159 return index;
1c79356b
A
160}
161
3e170ce0 162/*
1c79356b
A
163 * if index is -1, find a free slot to add
164 * else see whether the slot is free
165 * return the major number that is used else -1
316670eb
A
166 *
167 * if index is negative, we start
168 * looking for a free slot at the absolute value of index,
169 * instead of starting at 0
1c79356b
A
170 */
171int
3e170ce0 172bdevsw_add(int index, struct bdevsw * bsw)
1c79356b 173{
39037602 174 lck_mtx_lock_spin(&devsw_lock_list_mtx);
316670eb
A
175 index = bdevsw_isfree(index);
176 if (index < 0) {
39037602
A
177 index = -1;
178 } else {
179 bdevsw[index] = *bsw;
1c79356b 180 }
39037602 181 lck_mtx_unlock(&devsw_lock_list_mtx);
0a7de745 182 return index;
1c79356b 183}
316670eb 184/*
1c79356b
A
185 * if the slot has the same bsw, then remove
186 * else -1
187 */
188int
3e170ce0 189bdevsw_remove(int index, struct bdevsw * bsw)
1c79356b 190{
3e170ce0
A
191 struct bdevsw * devsw;
192
0a7de745
A
193 if (index < 0 || index >= nblkdev) {
194 return -1;
195 }
1c79356b
A
196
197 devsw = &bdevsw[index];
39037602 198 lck_mtx_lock_spin(&devsw_lock_list_mtx);
3e170ce0 199 if ((memcmp((char *)devsw, (char *)bsw, sizeof(struct bdevsw)) != 0)) {
39037602
A
200 index = -1;
201 } else {
202 bdevsw[index] = nobdev;
1c79356b 203 }
39037602 204 lck_mtx_unlock(&devsw_lock_list_mtx);
0a7de745 205 return index;
1c79356b
A
206}
207
3e170ce0 208/*
1c79356b
A
209 * if index is -1, return a free slot if avaliable
210 * else see whether the index is free
211 * return the major number that is free else -1
316670eb
A
212 *
213 * if index is negative, we start
214 * looking for a free slot at the absolute value of index,
215 * instead of starting at 0
1c79356b
A
216 */
217int
218cdevsw_isfree(int index)
219{
3e170ce0 220 struct cdevsw * devsw;
1c79356b 221
316670eb 222 if (index < 0) {
0a7de745 223 if (index == -1) {
3e170ce0 224 index = 0;
0a7de745 225 } else {
3e170ce0 226 index = -index; /* start at least this far up in the table */
0a7de745 227 }
3e170ce0
A
228 devsw = &cdevsw[index];
229 for (; index < nchrdev; index++, devsw++) {
0a7de745 230 if (memcmp((char *)devsw, (char *)&nocdev, sizeof(struct cdevsw)) == 0) {
3e170ce0 231 break;
0a7de745 232 }
3e170ce0 233 }
1c79356b 234 }
3e170ce0 235
0a7de745
A
236 if (index < 0 || index >= nchrdev) {
237 return -1;
238 }
3e170ce0 239
1c79356b 240 devsw = &cdevsw[index];
3e170ce0 241 if ((memcmp((char *)devsw, (char *)&nocdev, sizeof(struct cdevsw)) != 0)) {
0a7de745 242 return -1;
1c79356b 243 }
0a7de745 244 return index;
1c79356b
A
245}
246
3e170ce0 247/*
1c79356b
A
248 * if index is -1, find a free slot to add
249 * else see whether the slot is free
250 * return the major number that is used else -1
2d21ac55 251 *
316670eb
A
252 * if index is negative, we start
253 * looking for a free slot at the absolute value of index,
254 * instead of starting at 0
255 *
2d21ac55
A
256 * NOTE: In practice, -1 is unusable, since there are kernel internal
257 * devices that call this function with absolute index values,
258 * which will stomp on free-slot based assignments that happen
316670eb 259 * before them. -24 is currently a safe starting point.
1c79356b
A
260 */
261int
3e170ce0 262cdevsw_add(int index, struct cdevsw * csw)
1c79356b 263{
39037602 264 lck_mtx_lock_spin(&devsw_lock_list_mtx);
316670eb 265 index = cdevsw_isfree(index);
2d21ac55 266 if (index < 0) {
39037602
A
267 index = -1;
268 } else {
269 cdevsw[index] = *csw;
1c79356b 270 }
39037602 271 lck_mtx_unlock(&devsw_lock_list_mtx);
0a7de745 272 return index;
1c79356b
A
273}
274/*
316670eb 275 * if the slot has the same csw, then remove
1c79356b
A
276 * else -1
277 */
278int
3e170ce0 279cdevsw_remove(int index, struct cdevsw * csw)
1c79356b 280{
3e170ce0
A
281 struct cdevsw * devsw;
282
0a7de745
A
283 if (index < 0 || index >= nchrdev) {
284 return -1;
285 }
1c79356b
A
286
287 devsw = &cdevsw[index];
39037602 288 lck_mtx_lock_spin(&devsw_lock_list_mtx);
3e170ce0 289 if ((memcmp((char *)devsw, (char *)csw, sizeof(struct cdevsw)) != 0)) {
39037602
A
290 index = -1;
291 } else {
292 cdevsw[index] = nocdev;
293 cdevsw_flags[index] = 0;
1c79356b 294 }
39037602 295 lck_mtx_unlock(&devsw_lock_list_mtx);
0a7de745 296 return index;
1c79356b
A
297}
298
9bccf70c
A
299static int
300cdev_set_bdev(int cdev, int bdev)
301{
0a7de745 302 return chrtoblk_set(cdev, bdev);
9bccf70c
A
303}
304
3e170ce0 305int
9bccf70c
A
306cdevsw_add_with_bdev(int index, struct cdevsw * csw, int bdev)
307{
308 index = cdevsw_add(index, csw);
309 if (index < 0) {
0a7de745 310 return index;
9bccf70c
A
311 }
312 if (cdev_set_bdev(index, bdev) < 0) {
313 cdevsw_remove(index, csw);
0a7de745 314 return -1;
9bccf70c 315 }
0a7de745 316 return index;
9bccf70c
A
317}
318
6d2010ae 319int
5ba3f43e 320cdevsw_setkqueueok(int maj, struct cdevsw * csw, int extra_flags)
6d2010ae 321{
3e170ce0 322 struct cdevsw * devsw;
6d2010ae
A
323 uint64_t flags = CDEVSW_SELECT_KQUEUE;
324
5ba3f43e
A
325 if (maj < 0 || maj >= nchrdev) {
326 return -1;
327 }
3e170ce0 328
5ba3f43e 329 devsw = &cdevsw[maj];
3e170ce0 330 if ((memcmp((char *)devsw, (char *)csw, sizeof(struct cdevsw)) != 0)) {
5ba3f43e 331 return -1;
6d2010ae
A
332 }
333
5ba3f43e 334 flags |= extra_flags;
6d2010ae 335
5ba3f43e 336 cdevsw_flags[maj] = flags;
6d2010ae
A
337 return 0;
338}
339
3e170ce0 340#include <pexpert/pexpert.h> /* for PE_parse_boot_arg */
2d21ac55 341
b0d623f7
A
342/*
343 * Copy the "hostname" variable into a caller-provided buffer
344 * Returns: 0 for success, ENAMETOOLONG for insufficient buffer space.
3e170ce0 345 * On success, "len" will be set to the number of characters preceding
b0d623f7
A
346 * the NULL character in the hostname.
347 */
348int
3e170ce0 349bsd_hostname(char * buf, int bufsize, int * len)
b0d623f7 350{
cb323159 351 int ret, hnlen;
b0d623f7 352 /*
cb323159 353 * "hostname" is null-terminated
b0d623f7 354 */
cb323159
A
355 lck_mtx_lock(&hostname_lock);
356 hnlen = strlen(hostname);
357 if (hnlen < bufsize) {
b0d623f7 358 strlcpy(buf, hostname, bufsize);
cb323159
A
359 *len = hnlen;
360 ret = 0;
b0d623f7 361 } else {
cb323159 362 ret = ENAMETOOLONG;
3e170ce0 363 }
cb323159
A
364 lck_mtx_unlock(&hostname_lock);
365 return ret;
b0d623f7
A
366}
367
6d2010ae
A
368void
369devsw_lock(dev_t dev, int mode)
370{
371 devsw_lock_t newlock, tmplock;
372 int res;
373
3e170ce0 374 assert(0 <= major(dev) && major(dev) < nchrdev);
6d2010ae
A
375 assert(mode == S_IFCHR || mode == S_IFBLK);
376
377 MALLOC(newlock, devsw_lock_t, sizeof(struct devsw_lock), M_TEMP, M_WAITOK | M_ZERO);
378 newlock->dl_dev = dev;
379 newlock->dl_thread = current_thread();
380 newlock->dl_mode = mode;
3e170ce0 381
6d2010ae
A
382 lck_mtx_lock_spin(&devsw_lock_list_mtx);
383retry:
3e170ce0
A
384 TAILQ_FOREACH(tmplock, &devsw_locks, dl_list)
385 {
6d2010ae 386 if (tmplock->dl_dev == dev && tmplock->dl_mode == mode) {
3e170ce0 387 res = msleep(tmplock, &devsw_lock_list_mtx, PVFS, "devsw_lock", NULL);
6d2010ae
A
388 assert(res == 0);
389 goto retry;
390 }
391 }
392
393 TAILQ_INSERT_TAIL(&devsw_locks, newlock, dl_list);
394 lck_mtx_unlock(&devsw_lock_list_mtx);
6d2010ae
A
395}
396void
397devsw_unlock(dev_t dev, int mode)
398{
399 devsw_lock_t tmplock;
400
3e170ce0 401 assert(0 <= major(dev) && major(dev) < nchrdev);
6d2010ae
A
402
403 lck_mtx_lock_spin(&devsw_lock_list_mtx);
404
3e170ce0
A
405 TAILQ_FOREACH(tmplock, &devsw_locks, dl_list)
406 {
407 if (tmplock->dl_dev == dev && tmplock->dl_mode == mode) {
6d2010ae
A
408 break;
409 }
410 }
411
412 if (tmplock == NULL) {
413 panic("Trying to unlock, and couldn't find lock.");
414 }
415
416 if (tmplock->dl_thread != current_thread()) {
417 panic("Trying to unlock, but I don't hold the lock.");
418 }
419
420 wakeup(tmplock);
421 TAILQ_REMOVE(&devsw_locks, tmplock, dl_list);
3e170ce0 422
6d2010ae 423 lck_mtx_unlock(&devsw_lock_list_mtx);
3e170ce0 424
6d2010ae
A
425 FREE(tmplock, M_TEMP);
426}
427
428void
429devsw_init()
430{
431 devsw_lock_grp = lck_grp_alloc_init("devsw", NULL);
432 assert(devsw_lock_grp != NULL);
433
434 lck_mtx_init(&devsw_lock_list_mtx, devsw_lock_grp, NULL);
435 TAILQ_INIT(&devsw_locks);
436}