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