]> git.saurik.com Git - apple/xnu.git/blob - bsd/kern/bsd_init.c
6a055af65f58b5bf5fa71d6fcc816647ba78f319
[apple/xnu.git] / bsd / kern / bsd_init.c
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22 /*
23 * Copyright (c) 1982, 1986, 1989, 1991, 1992, 1993
24 * The Regents of the University of California. All rights reserved.
25 * (c) UNIX System Laboratories, Inc.
26 * All or some portions of this file are derived from material licensed
27 * to the University of California by American Telephone and Telegraph
28 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
29 * the permission of UNIX System Laboratories, Inc.
30 *
31 * Redistribution and use in source and binary forms, with or without
32 * modification, are permitted provided that the following conditions
33 * are met:
34 * 1. Redistributions of source code must retain the above copyright
35 * notice, this list of conditions and the following disclaimer.
36 * 2. Redistributions in binary form must reproduce the above copyright
37 * notice, this list of conditions and the following disclaimer in the
38 * documentation and/or other materials provided with the distribution.
39 * 3. All advertising materials mentioning features or use of this software
40 * must display the following acknowledgement:
41 * This product includes software developed by the University of
42 * California, Berkeley and its contributors.
43 * 4. Neither the name of the University nor the names of its contributors
44 * may be used to endorse or promote products derived from this software
45 * without specific prior written permission.
46 *
47 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
48 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
51 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
53 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
56 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57 * SUCH DAMAGE.
58 *
59 * @(#)init_main.c 8.16 (Berkeley) 5/14/95
60 */
61
62 /*
63 *
64 * Mach Operating System
65 * Copyright (c) 1987 Carnegie-Mellon University
66 * All rights reserved. The CMU software License Agreement specifies
67 * the terms and conditions for use and redistribution.
68 */
69 /*
70 * HISTORY
71 * 16-Apr-98 A. Ramesh at Apple
72 * Created for Apple Core from DR2 init_main.c.
73 */
74
75 #include <quota.h>
76
77 #include <sys/param.h>
78 #include <sys/filedesc.h>
79 #include <sys/kernel.h>
80 #include <sys/mount.h>
81 #include <sys/proc.h>
82 #include <sys/systm.h>
83 #include <sys/vnode.h>
84 #include <sys/conf.h>
85 #include <sys/buf.h>
86 #include <sys/clist.h>
87 #include <sys/user.h>
88 #include <ufs/ufs/quota.h>
89
90 #include <sys/malloc.h>
91 #include <sys/dkstat.h>
92
93 #include <machine/spl.h>
94 #include <kern/thread.h>
95 #include <kern/task.h>
96 #include <kern/ast.h>
97
98 #include <mach/vm_param.h>
99
100 #include <vm/vm_map.h>
101 #include <vm/vm_kern.h>
102
103 #include <sys/ux_exception.h>
104
105 #include <sys/reboot.h>
106 #include <mach/exception_types.h>
107 #include <dev/busvar.h>
108 #include <sys/kdebug.h>
109
110 #include <mach/mach_types.h>
111 #include <mach/vm_prot.h>
112 #include <mach/semaphore.h>
113 #include <mach/sync_policy.h>
114 #include <kern/clock.h>
115 #include <mach/kern_return.h>
116
117 extern shared_region_mapping_t system_shared_region;
118
119 char copyright[] =
120 "Copyright (c) 1982, 1986, 1989, 1991, 1993\n\tThe Regents of the University of California. All rights reserved.\n\n";
121
122 extern void ux_handler();
123
124 /* Components of the first process -- never freed. */
125 struct proc proc0;
126 struct session session0;
127 struct pgrp pgrp0;
128 struct pcred cred0;
129 struct filedesc filedesc0;
130 struct plimit limit0;
131 struct pstats pstats0;
132 struct sigacts sigacts0;
133 struct proc *kernproc, *initproc;
134
135
136 long cp_time[CPUSTATES];
137 long dk_seek[DK_NDRIVE];
138 long dk_time[DK_NDRIVE];
139 long dk_wds[DK_NDRIVE];
140 long dk_wpms[DK_NDRIVE];
141 long dk_xfer[DK_NDRIVE];
142 long dk_bps[DK_NDRIVE];
143
144 int dk_busy;
145 int dk_ndrive;
146
147 long tk_cancc;
148 long tk_nin;
149 long tk_nout;
150 long tk_rawcc;
151
152 /* Global variables to make pstat happy. We do swapping differently */
153 int nswdev, nswap;
154 int nswapmap;
155 void *swapmap;
156 struct swdevt swdevt[1];
157
158 dev_t rootdev; /* device of the root */
159 dev_t dumpdev; /* device to take dumps on */
160 long dumplo; /* offset into dumpdev */
161 long hostid;
162 char hostname[MAXHOSTNAMELEN];
163 int hostnamelen;
164 char domainname[MAXDOMNAMELEN];
165 int domainnamelen;
166
167 char rootdevice[16]; /* hfs device names have at least 9 chars */
168 struct timeval boottime; /* GRODY! This has to go... */
169 #if FIXME /* [ */
170 struct timeval time;
171 #endif /* FIXME ] */
172
173 #ifdef KMEMSTATS
174 struct kmemstats kmemstats[M_LAST];
175 #endif
176
177 int lbolt; /* awoken once a second */
178 struct vnode *rootvp;
179 int boothowto = RB_DEBUG;
180
181 #define BSD_PAGABLE_MAP_SIZE (4 * 512 * 1024)
182 vm_map_t bsd_pageable_map;
183 vm_map_t mb_map;
184 semaphore_t execve_semaphore;
185
186 int cmask = CMASK;
187
188 int parse_bsd_args(void);
189 extern int bsd_hardclockinit;
190 extern vm_address_t bsd_init_task;
191 extern char init_task_failure_data[];
192
193 funnel_t * kernel_flock;
194 funnel_t * network_flock;
195 int disable_funnel = 0; /* disables split funnel */
196 int enable_funnel = 0; /* disables split funnel */
197
198 /*
199 * Initialization code.
200 * Called from cold start routine as
201 * soon as a stack and segmentation
202 * have been established.
203 * Functions:
204 * clear and free user core
205 * turn on clock
206 * hand craft 0th process
207 * call all initialization routines
208 * fork - process 0 to schedule
209 * - process 1 execute bootstrap
210 * - process 2 to page out
211 */
212
213 /*
214 * Sets the name for the given task.
215 */
216 void
217 proc_name(s, p)
218 char *s;
219 struct proc *p;
220 {
221 int length = strlen(s);
222
223 bcopy(s, p->p_comm,
224 length >= sizeof(p->p_comm) ? sizeof(p->p_comm) :
225 length + 1);
226 }
227
228
229 /* To allow these values to be patched, they're globals here */
230 #include <machine/vmparam.h>
231 struct rlimit vm_initial_limit_stack = { DFLSSIZ, MAXSSIZ };
232 struct rlimit vm_initial_limit_data = { DFLDSIZ, MAXDSIZ };
233 struct rlimit vm_initial_limit_core = { DFLCSIZ, MAXCSIZ };
234
235 extern thread_t first_thread;
236
237 #define SPL_DEBUG 0
238 #if SPL_DEBUG
239 #define dprintf(x) printf x
240 #else SPL_DEBUG
241 #define dprintf(x)
242 #endif /* SPL_DEBUG */
243
244 extern thread_t cloneproc(struct proc *, int);
245
246 void
247 bsd_init()
248 {
249 register struct proc *p;
250 extern struct ucred *rootcred;
251 register int i;
252 int s;
253 thread_t th;
254 extern void bsdinit_task();
255 void lightning_bolt(void );
256 kern_return_t ret;
257 boolean_t funnel_state;
258 extern void uthread_zone_init();
259
260 extern int (*mountroot) __P((void));
261
262
263 #if 1
264 /* split funnel is enabled by default */
265 PE_parse_boot_arg("dfnl", &disable_funnel);
266 #else
267 /* split funnel is disabled befault */
268 disable_funnel = 1;
269 PE_parse_boot_arg("efnl", &enable_funnel);
270 if (enable_funnel) {
271 /* enable only if efnl is set in bootarg */
272 disable_funnel = 0;
273 }
274 #endif
275
276 kernel_flock = funnel_alloc(KERNEL_FUNNEL);
277 if (kernel_flock == (funnel_t *)0 ) {
278 panic("bsd_init: Fail to allocate kernel mutex lock");
279 }
280
281
282 funnel_state = thread_funnel_set(kernel_flock, TRUE);
283
284 if (!disable_funnel) {
285 network_flock = funnel_alloc(NETWORK_FUNNEL);
286 if (network_flock == (funnel_t *)0 ) {
287 panic("bds_init: Fail to allocate network mutex lock");
288 }
289 } else {
290 network_flock = kernel_flock;
291 }
292
293
294 printf(copyright);
295
296 kmeminit();
297
298 parse_bsd_args();
299
300 bsd_bufferinit();
301
302 /* Initialize the uthread zone */
303 uthread_zone_init();
304
305 /*
306 * Initialize process and pgrp structures.
307 */
308 procinit();
309
310 kernproc = &proc0;
311
312 p = kernproc;
313
314 /* kernel_task->proc = kernproc; */
315 set_bsdtask_info(kernel_task,(void *)kernproc);
316 p->p_pid = 0;
317
318 /* give kernproc a name */
319 proc_name("kernel_task", p);
320
321 if (current_task() != kernel_task)
322 printf("We are in for problem, current task in not kernel task\n");
323
324 /*
325 * Create process 0.
326 */
327 LIST_INSERT_HEAD(&allproc, p, p_list);
328 p->p_pgrp = &pgrp0;
329 LIST_INSERT_HEAD(PGRPHASH(0), &pgrp0, pg_hash);
330 LIST_INIT(&pgrp0.pg_members);
331 LIST_INSERT_HEAD(&pgrp0.pg_members, p, p_pglist);
332
333 pgrp0.pg_session = &session0;
334 session0.s_count = 1;
335 session0.s_leader = p;
336
337 p->task = kernel_task;
338
339 p->p_stat = SRUN;
340 p->p_flag = P_INMEM|P_SYSTEM;
341 p->p_nice = NZERO;
342 p->p_pptr = p;
343 lockinit(&p->signal_lock, PVM, "signal", 0, 0);
344 p->sigwait = FALSE;
345 p->sigwait_thread = THREAD_NULL;
346 p->exit_thread = THREAD_NULL;
347
348 /* Create credentials. */
349 lockinit(&cred0.pc_lock, PLOCK, "proc0 cred", 0, 0);
350 cred0.p_refcnt = 1;
351 p->p_cred = &cred0;
352 p->p_ucred = crget();
353 p->p_ucred->cr_ngroups = 1; /* group 0 */
354
355 /* Create the file descriptor table. */
356 filedesc0.fd_refcnt = 1+1; /* +1 so shutdown will not _FREE_ZONE */
357 p->p_fd = &filedesc0;
358 filedesc0.fd_cmask = cmask;
359
360 /* Create the limits structures. */
361 p->p_limit = &limit0;
362 for (i = 0; i < sizeof(p->p_rlimit)/sizeof(p->p_rlimit[0]); i++)
363 limit0.pl_rlimit[i].rlim_cur =
364 limit0.pl_rlimit[i].rlim_max = RLIM_INFINITY;
365 limit0.pl_rlimit[RLIMIT_NOFILE].rlim_cur = NOFILE;
366 limit0.pl_rlimit[RLIMIT_NPROC].rlim_cur = MAXUPRC;
367 limit0.pl_rlimit[RLIMIT_STACK] = vm_initial_limit_stack;
368 limit0.pl_rlimit[RLIMIT_DATA] = vm_initial_limit_data;
369 limit0.pl_rlimit[RLIMIT_CORE] = vm_initial_limit_core;
370 limit0.p_refcnt = 1;
371
372 p->p_stats = &pstats0;
373 p->p_sigacts = &sigacts0;
374
375 /*
376 * Charge root for one process.
377 */
378 (void)chgproccnt(0, 1);
379
380
381 /*
382 * Allocate a kernel submap for pageable memory
383 * for temporary copying (execve()).
384 */
385 {
386 vm_offset_t min;
387
388 ret = kmem_suballoc(kernel_map,
389 &min,
390 (vm_size_t)BSD_PAGABLE_MAP_SIZE,
391 TRUE,
392 TRUE,
393 &bsd_pageable_map);
394 if (ret != KERN_SUCCESS)
395 panic("bsd_init: Failed to allocare bsd pageable map");
396 }
397
398 /* Initialize the execve() semaphore */
399 {
400 kern_return_t kret;
401 int value;
402
403 value = BSD_PAGABLE_MAP_SIZE / NCARGS;
404
405 kret = semaphore_create(kernel_task, &execve_semaphore,
406 SYNC_POLICY_FIFO, value);
407 if (kret != KERN_SUCCESS)
408 panic("bsd_init: Failed to create execve semaphore");
409 }
410
411 /*
412 * Initialize the calendar.
413 */
414 IOKitResetTime();
415
416 ubc_init();
417
418 /* Initialize the file systems. */
419 vfsinit();
420
421 /* Initialize mbuf's. */
422 mbinit();
423
424 /* Initialize syslog */
425 log_init();
426
427 /* Initialize SysV shm */
428 shminit();
429
430 /* POSIX Shm and Sem */
431 pshm_cache_init();
432 psem_cache_init();
433
434 /*
435 * Initialize protocols. Block reception of incoming packets
436 * until everything is ready.
437 */
438 s = splimp();
439 sysctl_register_fixed();
440 dlil_init();
441 socketinit();
442 domaininit();
443 splx(s);
444
445 /*
446 * Create kernel idle cpu processes. This must be done
447 * before a context switch can occur (and hence I/O can
448 * happen in the binit() call).
449 */
450 p->p_fd->fd_cdir = NULL;
451 p->p_fd->fd_rdir = NULL;
452
453
454 #ifdef GPROF
455 /* Initialize kernel profiling. */
456 kmstartup();
457 #endif
458
459 /* kick off timeout driven events by calling first time */
460 thread_wakeup(&lbolt);
461 timeout(lightning_bolt,0,hz);
462
463 bsd_autoconf();
464
465 /*
466 * We attach the loopback interface *way* down here to ensure
467 * it happens after autoconf(), otherwise it becomes the
468 * "primary" interface.
469 */
470 #include <loop.h>
471 #if NLOOP > 0
472 loopattach(); /* XXX */
473 #endif
474
475 vnode_pager_bootstrap();
476
477 /* Mount the root file system. */
478 while( TRUE) {
479 int err;
480
481 setconf();
482 /*
483 * read the time after clock_initialize_calendar()
484 * and before nfs mount
485 */
486 microtime(&time);
487
488 if (0 == (err = vfs_mountroot()))
489 break;
490 printf("cannot mount root, errno = %d\n", err);
491 boothowto |= RB_ASKNAME;
492 }
493
494 mountlist.cqh_first->mnt_flag |= MNT_ROOTFS;
495
496 /* Get the vnode for '/'. Set fdp->fd_fd.fd_cdir to reference it. */
497 if (VFS_ROOT(mountlist.cqh_first, &rootvnode))
498 panic("bsd_init: cannot find root vnode");
499 VREF(rootvnode);
500 filedesc0.fd_cdir = rootvnode;
501 VOP_UNLOCK(rootvnode, 0, p);
502
503
504 /*
505 * Now can look at time, having had a chance to verify the time
506 * from the file system. Reset p->p_rtime as it may have been
507 * munched in mi_switch() after the time got set.
508 */
509 p->p_stats->p_start = boottime = time;
510 p->p_rtime.tv_sec = p->p_rtime.tv_usec = 0;
511
512 #ifdef DEVFS
513 {
514 extern void devfs_kernel_mount(char * str);
515
516 devfs_kernel_mount("/dev");
517 }
518 #endif DEVFS
519
520 /* Initialize signal state for process 0. */
521 siginit(p);
522
523 /* printf("Launching user process\n"); */
524
525 bsd_utaskbootstrap();
526
527 (void) thread_funnel_set(kernel_flock, FALSE);
528 }
529
530 void
531 bsdinit_task()
532 {
533 struct proc *p = current_proc();
534 struct uthread *ut;
535 kern_return_t kr;
536 thread_act_t th_act;
537 boolean_t funnel_state;
538
539 funnel_state = thread_funnel_set(kernel_flock, TRUE);
540
541 #if FIXME /* [ */
542
543 ipc_port_t master_bootstrap_port;
544 task_t bootstrap_task;
545 thread_act_t bootstrap_thr_act;
546 ipc_port_t root_device_port;
547
548 master_bootstrap_port = ipc_port_alloc_kernel();
549 if (master_bootstrap_port == IP_NULL)
550 panic("can't allocate master bootstrap port");
551 printf("setting bootstrap port \n");
552 task_set_special_port(bootstrap_task,
553 TASK_BOOTSTRAP_PORT,
554 ipc_port_make_send(master_bootstrap_port));
555
556 printf("Setting exception port for the init task\n");
557 (void) task_set_exception_ports(get_threadtask(th),
558 EXC_MASK_ALL &
559 ~(EXC_MASK_SYSCALL |
560 EXC_MASK_MACH_SYSCALL | EXC_MASK_RPC_ALERT),
561 ux_exception_port,
562 EXCEPTION_DEFAULT, 0);
563
564 #endif /* FIXME ] */
565 proc_name("init", p);
566
567 ux_handler_init();
568 /* port_reference(ux_exception_port);*/
569
570 th_act = current_act();
571 (void) host_set_exception_ports(host_priv_self(),
572 EXC_MASK_ALL & ~(EXC_MASK_SYSCALL |
573 EXC_MASK_MACH_SYSCALL |
574 EXC_MASK_RPC_ALERT),
575 ux_exception_port,
576 EXCEPTION_DEFAULT, 0);
577
578 (void) task_set_exception_ports(get_threadtask(th_act),
579 EXC_MASK_ALL & ~(EXC_MASK_SYSCALL |
580 EXC_MASK_MACH_SYSCALL |
581 EXC_MASK_RPC_ALERT),
582 ux_exception_port,
583 EXCEPTION_DEFAULT, 0);
584
585
586
587
588 ut = (uthread_t)get_bsdthread_info(th_act);
589 ut->uu_ar0 = (void *)get_user_regs(th_act);
590
591 bsd_hardclockinit = 1; /* Start bsd hardclock */
592 bsd_init_task = get_threadtask(th_act);
593 init_task_failure_data[0] = 0;
594 vm_set_shared_region(get_threadtask(th_act), system_shared_region);
595 load_init_program(p);
596
597 (void) thread_funnel_set(kernel_flock, FALSE);
598
599 }
600
601 void
602 lightning_bolt()
603 {
604 boolean_t funnel_state;
605 extern void klogwakeup(void);
606
607 funnel_state = thread_funnel_set(kernel_flock, TRUE);
608
609 thread_wakeup(&lbolt);
610 timeout(lightning_bolt,0,hz);
611 klogwakeup();
612
613 (void) thread_funnel_set(kernel_flock, FALSE);
614 }
615
616 bsd_autoconf(){
617 extern kern_return_t IOKitBSDInit( void );
618
619 kminit();
620
621 /*
622 * Early startup for bsd pseudodevices.
623 */
624 {
625 struct pseudo_init *pi;
626
627 for (pi = pseudo_inits; pi->ps_func; pi++)
628 (*pi->ps_func) (pi->ps_count);
629 }
630
631 return( IOKitBSDInit());
632 }
633
634
635 #include <sys/disklabel.h> // for MAXPARTITIONS
636
637 setconf()
638 {
639 extern kern_return_t IOFindBSDRoot( char * rootName,
640 dev_t * root, u_int32_t * flags );
641
642 extern int (*mountroot) __P((void));
643 extern int nfs_mountroot(); /* nfs_vfsops.c */
644
645 u_int32_t flags;
646 kern_return_t err;
647
648 /*
649 * calls into IOKit can generate networking registrations
650 * which needs to be under network funnel. Right thing to do
651 * here is to drop the funnel alltogether and regrab it afterwards
652 */
653 thread_funnel_set(kernel_flock, FALSE);
654 err = IOFindBSDRoot( rootdevice, &rootdev, &flags );
655 thread_funnel_set(kernel_flock, TRUE);
656 if( err) {
657 printf("setconf: IOFindBSDRoot returned an error (%d);"
658 "setting rootdevice to 'sd0a'.\n", err); /* XXX DEBUG TEMP */
659 rootdev = makedev( 6, 0 );
660 strcpy( rootdevice, "sd0a" );
661 flags = 0;
662 }
663
664 /* if network device then force nfs root */
665 if( flags & 1 ) {
666 printf("mounting nfs root\n");
667 mountroot = nfs_mountroot;
668 } else {
669 /* otherwise have vfs determine root filesystem */
670 mountroot = NULL;
671 }
672
673 }
674
675 bsd_utaskbootstrap()
676 {
677 thread_act_t th_act;
678
679 th_act = (thread_act_t)cloneproc(kernproc, 0);
680 initproc = pfind(1);
681 thread_hold(th_act);
682 (void) thread_stop_wait(getshuttle_thread(th_act));
683 thread_ast_set(th_act,AST_BSD_INIT);
684 thread_release(th_act);
685 thread_unstop(getshuttle_thread(th_act));
686 (void) thread_resume(th_act);
687 }
688
689 parse_bsd_args()
690 {
691 extern char init_args[];
692 char namep[16];
693 extern int boothowto;
694 extern int srv;
695 extern int ncl;
696
697 int len;
698
699 if (PE_parse_boot_arg("-s", namep)) {
700 boothowto |= RB_SINGLE;
701 len = strlen(init_args);
702 if(len != 0)
703 strcat(init_args," -s");
704 else
705 strcat(init_args,"-s");
706 }
707 if (PE_parse_boot_arg("-b", namep)) {
708 boothowto |= RB_NOBOOTRC;
709 len = strlen(init_args);
710 if(len != 0)
711 strcat(init_args," -b");
712 else
713 strcat(init_args,"-b");
714 }
715
716 if (PE_parse_boot_arg("-F", namep)) {
717 len = strlen(init_args);
718 if(len != 0)
719 strcat(init_args," -F");
720 else
721 strcat(init_args,"-F");
722 }
723
724 if (PE_parse_boot_arg("-v", namep)) {
725 len = strlen(init_args);
726 if(len != 0)
727 strcat(init_args," -v");
728 else
729 strcat(init_args,"-v");
730 }
731
732 if (PE_parse_boot_arg("-x", namep)) { /* safe boot */
733 len = strlen(init_args);
734 if(len != 0)
735 strcat(init_args," -x");
736 else
737 strcat(init_args,"-x");
738 }
739
740 PE_parse_boot_arg("srv", &srv);
741 PE_parse_boot_arg("ncl", &ncl);
742 PE_parse_boot_arg("nbuf", &nbuf);
743
744 return 0;
745 }
746
747 boolean_t
748 thread_funnel_switch(
749 int oldfnl,
750 int newfnl)
751 {
752 thread_t cur_thread;
753 boolean_t funnel_state_prev;
754 int curfnl;
755 funnel_t * curflock;
756 funnel_t * oldflock;
757 funnel_t * newflock;
758 funnel_t * exist_funnel;
759 extern int disable_funnel;
760
761
762 if (disable_funnel)
763 return(TRUE);
764
765 if(oldfnl == newfnl) {
766 panic("thread_funnel_switch: can't switch to same funnel");
767 }
768
769 if ((oldfnl != NETWORK_FUNNEL) && (oldfnl != KERNEL_FUNNEL))
770 {
771 panic("thread_funnel_switch: invalid oldfunnel");
772 }
773 if ((newfnl != NETWORK_FUNNEL) && (newfnl != KERNEL_FUNNEL))
774 {
775 panic("thread_funnel_switch: invalid oldfunnel");
776 }
777
778 if((curflock = thread_funnel_get()) == THR_FUNNEL_NULL) {
779 panic("thread_funnel_switch: no funnel held");
780 }
781
782 cur_thread = current_thread();
783
784 if ((oldfnl == NETWORK_FUNNEL) && (curflock != network_flock))
785 panic("thread_funnel_switch: network funnel not held");
786
787 if ((oldfnl == KERNEL_FUNNEL) && (curflock != kernel_flock))
788 panic("thread_funnel_switch: network funnel not held");
789
790 if(oldfnl == NETWORK_FUNNEL) {
791 oldflock = network_flock;
792 newflock = kernel_flock;
793 } else {
794 oldflock = kernel_flock;
795 newflock = network_flock;
796 }
797 KERNEL_DEBUG(0x603242c | DBG_FUNC_NONE, oldflock, 1, 0, 0, 0);
798 thread_funnel_set(oldflock, FALSE);
799 KERNEL_DEBUG(0x6032428 | DBG_FUNC_NONE, newflock, 1, 0, 0, 0);
800 thread_funnel_set(newflock, TRUE);
801 KERNEL_DEBUG(0x6032434 | DBG_FUNC_NONE, newflock, 1, 0, 0, 0);
802
803 return(TRUE);
804 }