]> git.saurik.com Git - apple/xnu.git/blob - bsd/kern/bsd_stubs.c
xnu-6153.141.1.tar.gz
[apple/xnu.git] / bsd / kern / bsd_stubs.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
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
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
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>
34 #include <sys/stat.h>
35 #include <vm/vm_map.h>
36 #include <sys/systm.h>
37 #include <kern/assert.h>
38 #include <sys/conf.h>
39 #include <sys/proc_internal.h>
40 #include <sys/buf.h> /* for SET */
41 #include <sys/kernel.h>
42 #include <sys/user.h>
43 #include <sys/sysent.h>
44 #include <sys/sysproto.h>
45
46 /* XXX these should be in a common header somwhere, but aren't */
47 extern int chrtoblk_set(int, int);
48 extern vm_offset_t kmem_mb_alloc(vm_map_t, int, int, kern_return_t *);
49
50 /* XXX most of these just exist to export; there's no good header for them*/
51 void pcb_synch(void);
52
53 TAILQ_HEAD(, devsw_lock) devsw_locks;
54 lck_mtx_t devsw_lock_list_mtx;
55 lck_grp_t * devsw_lock_grp;
56
57 /* Just to satisfy pstat command */
58 int dmmin, dmmax, dmtext;
59
60 vm_offset_t
61 kmem_mb_alloc(vm_map_t mbmap, int size, int physContig, kern_return_t *err)
62 {
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, 0, KMA_KOBJECT | KMA_LOMEM, VM_KERN_MEMORY_MBUF);
68 } else {
69 kr = kmem_alloc_contig(mbmap, &addr, size, PAGE_MASK, 0xfffff, 0, KMA_KOBJECT | KMA_LOMEM, VM_KERN_MEMORY_MBUF);
70 }
71
72 if (kr != KERN_SUCCESS) {
73 addr = 0;
74 }
75 if (err) {
76 *err = kr;
77 }
78
79 return addr;
80 }
81
82 /*
83 * XXX this function only exists to be exported and do nothing.
84 */
85 void
86 pcb_synch(void)
87 {
88 }
89
90 struct proc *
91 current_proc(void)
92 {
93 /* Never returns a NULL */
94 struct uthread * ut;
95 struct proc * p;
96 thread_t thread = current_thread();
97
98 ut = (struct uthread *)get_bsdthread_info(thread);
99 if (ut && (ut->uu_flag & UT_VFORK) && ut->uu_proc) {
100 p = ut->uu_proc;
101 if ((p->p_lflag & P_LINVFORK) == 0) {
102 panic("returning child proc not under vfork");
103 }
104 if (p->p_vforkact != (void *)thread) {
105 panic("returning child proc which is not cur_act");
106 }
107 return p;
108 }
109
110 p = (struct proc *)get_bsdtask_info(current_task());
111
112 if (p == NULL) {
113 return kernproc;
114 }
115
116 return p;
117 }
118
119 /* Device switch add delete routines */
120
121 struct bdevsw nobdev = NO_BDEVICE;
122 struct cdevsw nocdev = NO_CDEVICE;
123 /*
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 *
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
131 */
132 int
133 bdevsw_isfree(int index)
134 {
135 struct bdevsw * devsw;
136
137 if (index < 0) {
138 if (index == -1) {
139 index = 1; /* start at 1 to avoid collision with volfs (Radar 2842228) */
140 } else {
141 index = -index; /* start at least this far up in the table */
142 }
143 devsw = &bdevsw[index];
144 for (; index < nblkdev; index++, devsw++) {
145 if (memcmp((char *)devsw, (char *)&nobdev, sizeof(struct bdevsw)) == 0) {
146 break;
147 }
148 }
149 }
150
151 if (index < 0 || index >= nblkdev) {
152 return -1;
153 }
154
155 devsw = &bdevsw[index];
156 if ((memcmp((char *)devsw, (char *)&nobdev, sizeof(struct bdevsw)) != 0)) {
157 return -1;
158 }
159 return index;
160 }
161
162 /*
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
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
170 */
171 int
172 bdevsw_add(int index, struct bdevsw * bsw)
173 {
174 lck_mtx_lock_spin(&devsw_lock_list_mtx);
175 index = bdevsw_isfree(index);
176 if (index < 0) {
177 index = -1;
178 } else {
179 bdevsw[index] = *bsw;
180 }
181 lck_mtx_unlock(&devsw_lock_list_mtx);
182 return index;
183 }
184 /*
185 * if the slot has the same bsw, then remove
186 * else -1
187 */
188 int
189 bdevsw_remove(int index, struct bdevsw * bsw)
190 {
191 struct bdevsw * devsw;
192
193 if (index < 0 || index >= nblkdev) {
194 return -1;
195 }
196
197 devsw = &bdevsw[index];
198 lck_mtx_lock_spin(&devsw_lock_list_mtx);
199 if ((memcmp((char *)devsw, (char *)bsw, sizeof(struct bdevsw)) != 0)) {
200 index = -1;
201 } else {
202 bdevsw[index] = nobdev;
203 }
204 lck_mtx_unlock(&devsw_lock_list_mtx);
205 return index;
206 }
207
208 /*
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
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
216 */
217 int
218 cdevsw_isfree(int index)
219 {
220 struct cdevsw * devsw;
221
222 if (index < 0) {
223 if (index == -1) {
224 index = 0;
225 } else {
226 index = -index; /* start at least this far up in the table */
227 }
228 devsw = &cdevsw[index];
229 for (; index < nchrdev; index++, devsw++) {
230 if (memcmp((char *)devsw, (char *)&nocdev, sizeof(struct cdevsw)) == 0) {
231 break;
232 }
233 }
234 }
235
236 if (index < 0 || index >= nchrdev) {
237 return -1;
238 }
239
240 devsw = &cdevsw[index];
241 if ((memcmp((char *)devsw, (char *)&nocdev, sizeof(struct cdevsw)) != 0)) {
242 return -1;
243 }
244 return index;
245 }
246
247 /*
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
251 *
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 *
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
259 * before them. -24 is currently a safe starting point.
260 */
261 int
262 cdevsw_add(int index, struct cdevsw * csw)
263 {
264 lck_mtx_lock_spin(&devsw_lock_list_mtx);
265 index = cdevsw_isfree(index);
266 if (index < 0) {
267 index = -1;
268 } else {
269 cdevsw[index] = *csw;
270 }
271 lck_mtx_unlock(&devsw_lock_list_mtx);
272 return index;
273 }
274 /*
275 * if the slot has the same csw, then remove
276 * else -1
277 */
278 int
279 cdevsw_remove(int index, struct cdevsw * csw)
280 {
281 struct cdevsw * devsw;
282
283 if (index < 0 || index >= nchrdev) {
284 return -1;
285 }
286
287 devsw = &cdevsw[index];
288 lck_mtx_lock_spin(&devsw_lock_list_mtx);
289 if ((memcmp((char *)devsw, (char *)csw, sizeof(struct cdevsw)) != 0)) {
290 index = -1;
291 } else {
292 cdevsw[index] = nocdev;
293 cdevsw_flags[index] = 0;
294 }
295 lck_mtx_unlock(&devsw_lock_list_mtx);
296 return index;
297 }
298
299 static int
300 cdev_set_bdev(int cdev, int bdev)
301 {
302 return chrtoblk_set(cdev, bdev);
303 }
304
305 int
306 cdevsw_add_with_bdev(int index, struct cdevsw * csw, int bdev)
307 {
308 index = cdevsw_add(index, csw);
309 if (index < 0) {
310 return index;
311 }
312 if (cdev_set_bdev(index, bdev) < 0) {
313 cdevsw_remove(index, csw);
314 return -1;
315 }
316 return index;
317 }
318
319 int
320 cdevsw_setkqueueok(int maj, struct cdevsw * csw, int extra_flags)
321 {
322 struct cdevsw * devsw;
323 uint64_t flags = CDEVSW_SELECT_KQUEUE;
324
325 if (maj < 0 || maj >= nchrdev) {
326 return -1;
327 }
328
329 devsw = &cdevsw[maj];
330 if ((memcmp((char *)devsw, (char *)csw, sizeof(struct cdevsw)) != 0)) {
331 return -1;
332 }
333
334 flags |= extra_flags;
335
336 cdevsw_flags[maj] = flags;
337 return 0;
338 }
339
340 #include <pexpert/pexpert.h> /* for PE_parse_boot_arg */
341
342 /*
343 * Copy the "hostname" variable into a caller-provided buffer
344 * Returns: 0 for success, ENAMETOOLONG for insufficient buffer space.
345 * On success, "len" will be set to the number of characters preceding
346 * the NULL character in the hostname.
347 */
348 int
349 bsd_hostname(char * buf, int bufsize, int * len)
350 {
351 int ret, hnlen;
352 /*
353 * "hostname" is null-terminated
354 */
355 lck_mtx_lock(&hostname_lock);
356 hnlen = strlen(hostname);
357 if (hnlen < bufsize) {
358 strlcpy(buf, hostname, bufsize);
359 *len = hnlen;
360 ret = 0;
361 } else {
362 ret = ENAMETOOLONG;
363 }
364 lck_mtx_unlock(&hostname_lock);
365 return ret;
366 }
367
368 void
369 devsw_lock(dev_t dev, int mode)
370 {
371 devsw_lock_t newlock, tmplock;
372 int res;
373
374 assert(0 <= major(dev) && major(dev) < nchrdev);
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;
381
382 lck_mtx_lock_spin(&devsw_lock_list_mtx);
383 retry:
384 TAILQ_FOREACH(tmplock, &devsw_locks, dl_list)
385 {
386 if (tmplock->dl_dev == dev && tmplock->dl_mode == mode) {
387 res = msleep(tmplock, &devsw_lock_list_mtx, PVFS, "devsw_lock", NULL);
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);
395 }
396 void
397 devsw_unlock(dev_t dev, int mode)
398 {
399 devsw_lock_t tmplock;
400
401 assert(0 <= major(dev) && major(dev) < nchrdev);
402
403 lck_mtx_lock_spin(&devsw_lock_list_mtx);
404
405 TAILQ_FOREACH(tmplock, &devsw_locks, dl_list)
406 {
407 if (tmplock->dl_dev == dev && tmplock->dl_mode == mode) {
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);
422
423 lck_mtx_unlock(&devsw_lock_list_mtx);
424
425 FREE(tmplock, M_TEMP);
426 }
427
428 void
429 devsw_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 }