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