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