]> git.saurik.com Git - apple/xnu.git/blob - bsd/kern/bsd_init.c
1b81ced7b7517c0bb4843960f3c45bbb2d85886c
[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 #include <mach/shared_memory_server.h>
118 #include <vm/vm_shared_memory_server.h>
119
120 extern shared_region_mapping_t system_shared_region;
121 extern int app_profile; /* on/off switch for pre-heat cache */
122
123 char copyright[] =
124 "Copyright (c) 1982, 1986, 1989, 1991, 1993\n\tThe Regents of the University of California. All rights reserved.\n\n";
125
126 extern void ux_handler();
127
128 /* Components of the first process -- never freed. */
129 struct proc proc0;
130 struct session session0;
131 struct pgrp pgrp0;
132 struct pcred cred0;
133 struct filedesc filedesc0;
134 struct plimit limit0;
135 struct pstats pstats0;
136 struct sigacts sigacts0;
137 struct proc *kernproc, *initproc;
138
139 long tk_cancc;
140 long tk_nin;
141 long tk_nout;
142 long tk_rawcc;
143
144 /* Global variables to make pstat happy. We do swapping differently */
145 int nswdev, nswap;
146 int nswapmap;
147 void *swapmap;
148 struct swdevt swdevt[1];
149
150 dev_t rootdev; /* device of the root */
151 dev_t dumpdev; /* device to take dumps on */
152 long dumplo; /* offset into dumpdev */
153 long hostid;
154 char hostname[MAXHOSTNAMELEN];
155 int hostnamelen;
156 char domainname[MAXDOMNAMELEN];
157 int domainnamelen;
158
159 char rootdevice[16]; /* hfs device names have at least 9 chars */
160 struct timeval boottime; /* GRODY! This has to go... */
161
162 #ifdef KMEMSTATS
163 struct kmemstats kmemstats[M_LAST];
164 #endif
165
166 int lbolt; /* awoken once a second */
167 struct vnode *rootvp;
168 int boothowto = RB_DEBUG;
169
170 #define BSD_PAGABLE_MAP_SIZE (4 * 512 * 1024)
171 vm_map_t bsd_pageable_map;
172 vm_map_t mb_map;
173 semaphore_t execve_semaphore;
174
175 int cmask = CMASK;
176
177 int parse_bsd_args(void);
178 extern int bsd_hardclockinit;
179 extern task_t bsd_init_task;
180 extern char init_task_failure_data[];
181 extern void time_zone_slock_init(void);
182
183 funnel_t * kernel_flock;
184 funnel_t * network_flock;
185 int disable_funnel = 0; /* disables split funnel */
186 int enable_funnel = 0; /* disables split funnel */
187
188 /*
189 * Initialization code.
190 * Called from cold start routine as
191 * soon as a stack and segmentation
192 * have been established.
193 * Functions:
194 * clear and free user core
195 * turn on clock
196 * hand craft 0th process
197 * call all initialization routines
198 * fork - process 0 to schedule
199 * - process 1 execute bootstrap
200 * - process 2 to page out
201 */
202
203 /*
204 * Sets the name for the given task.
205 */
206 void
207 proc_name(s, p)
208 char *s;
209 struct proc *p;
210 {
211 int length = strlen(s);
212
213 bcopy(s, p->p_comm,
214 length >= sizeof(p->p_comm) ? sizeof(p->p_comm) :
215 length + 1);
216 }
217
218 /* To allow these values to be patched, they're globals here */
219 #include <machine/vmparam.h>
220 struct rlimit vm_initial_limit_stack = { DFLSSIZ, MAXSSIZ };
221 struct rlimit vm_initial_limit_data = { DFLDSIZ, MAXDSIZ };
222 struct rlimit vm_initial_limit_core = { DFLCSIZ, MAXCSIZ };
223
224 extern thread_t first_thread;
225 extern thread_act_t cloneproc(struct proc *, int);
226 extern int (*mountroot) __P((void));
227 extern int netboot_mountroot(); /* netboot.c */
228 extern int netboot_setup(struct proc * p);
229
230 /* hook called after root is mounted XXX temporary hack */
231 void (*mountroot_post_hook)(void);
232
233 void
234 bsd_init()
235 {
236 register struct proc *p;
237 extern struct ucred *rootcred;
238 register int i;
239 int s;
240 thread_t th;
241 void lightning_bolt(void );
242 kern_return_t ret;
243 boolean_t funnel_state;
244 extern void uthread_zone_init();
245
246
247
248 #if 1
249 /* split funnel is enabled by default */
250 PE_parse_boot_arg("dfnl", &disable_funnel);
251 #else
252 /* split funnel is disabled befault */
253 disable_funnel = 1;
254 PE_parse_boot_arg("efnl", &enable_funnel);
255 if (enable_funnel) {
256 /* enable only if efnl is set in bootarg */
257 disable_funnel = 0;
258 }
259 #endif
260
261 kernel_flock = funnel_alloc(KERNEL_FUNNEL);
262 if (kernel_flock == (funnel_t *)0 ) {
263 panic("bsd_init: Failed to allocate kernel funnel");
264 }
265
266 funnel_state = thread_funnel_set(kernel_flock, TRUE);
267
268 if (!disable_funnel) {
269 network_flock = funnel_alloc(NETWORK_FUNNEL);
270 if (network_flock == (funnel_t *)0 ) {
271 panic("bsd_init: Failed to allocate network funnel");
272 }
273 } else {
274 network_flock = kernel_flock;
275 }
276
277 printf(copyright);
278
279 kmeminit();
280
281 parse_bsd_args();
282
283 bsd_bufferinit();
284
285 /* Initialize the uthread zone */
286 uthread_zone_init();
287
288 /*
289 * Initialize process and pgrp structures.
290 */
291 procinit();
292
293 kernproc = &proc0;
294
295 p = kernproc;
296
297 /* kernel_task->proc = kernproc; */
298 set_bsdtask_info(kernel_task,(void *)p);
299 p->p_pid = 0;
300
301 /* give kernproc a name */
302 proc_name("kernel_task", p);
303
304 if (current_task() != kernel_task)
305 printf("bsd_init: We have a problem, "
306 "current task is not kernel task\n");
307
308 /*
309 * Create process 0.
310 */
311 LIST_INSERT_HEAD(&allproc, p, p_list);
312 p->p_pgrp = &pgrp0;
313 LIST_INSERT_HEAD(PGRPHASH(0), &pgrp0, pg_hash);
314 LIST_INIT(&pgrp0.pg_members);
315 LIST_INSERT_HEAD(&pgrp0.pg_members, p, p_pglist);
316
317 pgrp0.pg_session = &session0;
318 session0.s_count = 1;
319 session0.s_leader = p;
320
321 p->task = kernel_task;
322
323 p->p_stat = SRUN;
324 p->p_flag = P_INMEM|P_SYSTEM;
325 p->p_nice = NZERO;
326 p->p_pptr = p;
327 lockinit(&p->signal_lock, PVM, "signal", 0, 0);
328 TAILQ_INIT(&p->p_uthlist);
329 p->sigwait = FALSE;
330 p->sigwait_thread = THREAD_NULL;
331 p->exit_thread = THREAD_NULL;
332
333 /* Create credentials. */
334 lockinit(&cred0.pc_lock, PLOCK, "proc0 cred", 0, 0);
335 cred0.p_refcnt = 1;
336 p->p_cred = &cred0;
337 p->p_ucred = crget();
338 p->p_ucred->cr_ngroups = 1; /* group 0 */
339
340 /* Create the file descriptor table. */
341 filedesc0.fd_refcnt = 1+1; /* +1 so shutdown will not _FREE_ZONE */
342 p->p_fd = &filedesc0;
343 filedesc0.fd_cmask = cmask;
344
345 /* Create the limits structures. */
346 p->p_limit = &limit0;
347 for (i = 0; i < sizeof(p->p_rlimit)/sizeof(p->p_rlimit[0]); i++)
348 limit0.pl_rlimit[i].rlim_cur =
349 limit0.pl_rlimit[i].rlim_max = RLIM_INFINITY;
350 limit0.pl_rlimit[RLIMIT_NOFILE].rlim_cur = NOFILE;
351 limit0.pl_rlimit[RLIMIT_NPROC].rlim_cur = MAXUPRC;
352 limit0.pl_rlimit[RLIMIT_STACK] = vm_initial_limit_stack;
353 limit0.pl_rlimit[RLIMIT_DATA] = vm_initial_limit_data;
354 limit0.pl_rlimit[RLIMIT_CORE] = vm_initial_limit_core;
355 limit0.p_refcnt = 1;
356
357 p->p_stats = &pstats0;
358 p->p_sigacts = &sigacts0;
359
360 /*
361 * Charge root for one process.
362 */
363 (void)chgproccnt(0, 1);
364
365 /*
366 * Allocate a kernel submap for pageable memory
367 * for temporary copying (execve()).
368 */
369 {
370 vm_offset_t min;
371
372 ret = kmem_suballoc(kernel_map,
373 &min,
374 (vm_size_t)BSD_PAGABLE_MAP_SIZE,
375 TRUE,
376 TRUE,
377 &bsd_pageable_map);
378 if (ret != KERN_SUCCESS)
379 panic("bsd_init: Failed to allocate bsd pageable map");
380 }
381
382 /* Initialize the execve() semaphore */
383 ret = semaphore_create(kernel_task, &execve_semaphore,
384 SYNC_POLICY_FIFO, (BSD_PAGABLE_MAP_SIZE / NCARGS));
385 if (ret != KERN_SUCCESS)
386 panic("bsd_init: Failed to create execve semaphore");
387
388 /*
389 * Initialize the calendar.
390 */
391 IOKitResetTime();
392
393 ubc_init();
394
395 /* Initialize the file systems. */
396 vfsinit();
397
398 /* Initialize mbuf's. */
399 mbinit();
400
401 /* Initialize syslog */
402 log_init();
403
404 /* POSIX Shm and Sem */
405 pshm_cache_init();
406 psem_cache_init();
407 time_zone_slock_init();
408
409 /*
410 * Initialize protocols. Block reception of incoming packets
411 * until everything is ready.
412 */
413 s = splimp();
414 sysctl_register_fixed();
415 dlil_init();
416 socketinit();
417 domaininit();
418 splx(s);
419
420 p->p_fd->fd_cdir = NULL;
421 p->p_fd->fd_rdir = NULL;
422
423 #ifdef GPROF
424 /* Initialize kernel profiling. */
425 kmstartup();
426 #endif
427
428 /* kick off timeout driven events by calling first time */
429 thread_wakeup(&lbolt);
430 timeout(lightning_bolt,0,hz);
431
432 bsd_autoconf();
433
434 /*
435 * We attach the loopback interface *way* down here to ensure
436 * it happens after autoconf(), otherwise it becomes the
437 * "primary" interface.
438 */
439 #include <loop.h>
440 #if NLOOP > 0
441 loopattach(); /* XXX */
442 #endif
443
444 /* Register the built-in dlil ethernet interface family */
445 ether_family_init();
446
447 vnode_pager_bootstrap();
448
449 /* Mount the root file system. */
450 while( TRUE) {
451 int err;
452
453 setconf();
454 /*
455 * read the time after clock_initialize_calendar()
456 * and before nfs mount
457 */
458 microtime(&time);
459
460 bsd_hardclockinit = -1; /* start ticking */
461
462 if (0 == (err = vfs_mountroot()))
463 break;
464 if (mountroot == netboot_mountroot) {
465 printf("cannot mount network root, errno = %d\n", err);
466 mountroot = NULL;
467 if (0 == (err = vfs_mountroot()))
468 break;
469 }
470 printf("cannot mount root, errno = %d\n", err);
471 boothowto |= RB_ASKNAME;
472 }
473
474 mountlist.cqh_first->mnt_flag |= MNT_ROOTFS;
475
476 /* Get the vnode for '/'. Set fdp->fd_fd.fd_cdir to reference it. */
477 if (VFS_ROOT(mountlist.cqh_first, &rootvnode))
478 panic("bsd_init: cannot find root vnode");
479 VREF(rootvnode);
480 filedesc0.fd_cdir = rootvnode;
481 VOP_UNLOCK(rootvnode, 0, p);
482
483 if (mountroot == netboot_mountroot) {
484 int err;
485 /* post mount setup */
486 if (err = netboot_setup(p)) {
487 panic("bsd_init: NetBoot could not find root, %d", err);
488 }
489 }
490
491
492 /*
493 * Now can look at time, having had a chance to verify the time
494 * from the file system. Reset p->p_rtime as it may have been
495 * munched in mi_switch() after the time got set.
496 */
497 p->p_stats->p_start = boottime = time;
498 p->p_rtime.tv_sec = p->p_rtime.tv_usec = 0;
499
500 #if DEVFS
501 {
502 extern void devfs_kernel_mount(char * str);
503
504 devfs_kernel_mount("/dev");
505 }
506 #endif DEVFS
507
508 /* Initialize signal state for process 0. */
509 siginit(p);
510
511 /* printf("Launching user process\n"); */
512
513 bsd_utaskbootstrap();
514
515 /* invoke post-root-mount hook */
516 if (mountroot_post_hook != NULL)
517 mountroot_post_hook();
518
519 (void) thread_funnel_set(kernel_flock, funnel_state);
520 }
521
522 /* Called with kernel funnel held */
523 void
524 bsdinit_task(void)
525 {
526 struct proc *p = current_proc();
527 struct uthread *ut;
528 kern_return_t kr;
529 thread_act_t th_act;
530
531 proc_name("init", p);
532
533 ux_handler_init();
534
535 th_act = current_act();
536 (void) host_set_exception_ports(host_priv_self(),
537 EXC_MASK_ALL & ~(EXC_MASK_SYSCALL |
538 EXC_MASK_MACH_SYSCALL |
539 EXC_MASK_RPC_ALERT),
540 ux_exception_port,
541 EXCEPTION_DEFAULT, 0);
542
543 (void) task_set_exception_ports(get_threadtask(th_act),
544 EXC_MASK_ALL & ~(EXC_MASK_SYSCALL |
545 EXC_MASK_MACH_SYSCALL |
546 EXC_MASK_RPC_ALERT),
547 ux_exception_port,
548 EXCEPTION_DEFAULT, 0);
549
550
551
552
553 ut = (uthread_t)get_bsdthread_info(th_act);
554 ut->uu_ar0 = (void *)get_user_regs(th_act);
555
556 bsd_hardclockinit = 1; /* Start bsd hardclock */
557 bsd_init_task = get_threadtask(th_act);
558 init_task_failure_data[0] = 0;
559 shared_region_mapping_ref(system_shared_region);
560 vm_set_shared_region(get_threadtask(th_act), system_shared_region);
561 load_init_program(p);
562 /* turn on app-profiling i.e. pre-heating */
563 app_profile = 1;
564 }
565
566 void
567 lightning_bolt()
568 {
569 boolean_t funnel_state;
570 extern void klogwakeup(void);
571
572 funnel_state = thread_funnel_set(kernel_flock, TRUE);
573
574 thread_wakeup(&lbolt);
575 timeout(lightning_bolt,0,hz);
576 klogwakeup();
577
578 (void) thread_funnel_set(kernel_flock, FALSE);
579 }
580
581 bsd_autoconf()
582 {
583 extern kern_return_t IOKitBSDInit( void );
584
585 kminit();
586
587 /*
588 * Early startup for bsd pseudodevices.
589 */
590 {
591 struct pseudo_init *pi;
592
593 for (pi = pseudo_inits; pi->ps_func; pi++)
594 (*pi->ps_func) (pi->ps_count);
595 }
596
597 return( IOKitBSDInit());
598 }
599
600
601 #include <sys/disklabel.h> // for MAXPARTITIONS
602
603 setconf()
604 {
605 extern kern_return_t IOFindBSDRoot( char * rootName,
606 dev_t * root, u_int32_t * flags );
607 u_int32_t flags;
608 kern_return_t err;
609
610 /*
611 * calls into IOKit can generate networking registrations
612 * which needs to be under network funnel. Right thing to do
613 * here is to drop the funnel alltogether and regrab it afterwards
614 */
615 thread_funnel_set(kernel_flock, FALSE);
616 err = IOFindBSDRoot( rootdevice, &rootdev, &flags );
617 thread_funnel_set(kernel_flock, TRUE);
618 if( err) {
619 printf("setconf: IOFindBSDRoot returned an error (%d);"
620 "setting rootdevice to 'sd0a'.\n", err); /* XXX DEBUG TEMP */
621 rootdev = makedev( 6, 0 );
622 strcpy( rootdevice, "sd0a" );
623 flags = 0;
624 }
625
626 if( flags & 1 ) {
627 /* network device */
628 mountroot = netboot_mountroot;
629 } else {
630 /* otherwise have vfs determine root filesystem */
631 mountroot = NULL;
632 }
633
634 }
635
636 bsd_utaskbootstrap()
637 {
638 thread_act_t th_act;
639 struct uthread *ut;
640
641 th_act = cloneproc(kernproc, 0);
642 initproc = pfind(1);
643 /* Set the launch time for init */
644 initproc->p_stats->p_start = time;
645
646 ut = (struct uthread *)get_bsdthread_info(th_act);
647 ut->uu_sigmask = 0;
648 thread_hold(th_act);
649 (void)thread_stop(getshuttle_thread(th_act));
650 act_set_astbsd(th_act);
651 thread_release(th_act);
652 thread_unstop(getshuttle_thread(th_act));
653 (void) thread_resume(th_act);
654 }
655
656 parse_bsd_args()
657 {
658 extern char init_args[];
659 char namep[16];
660 extern int boothowto;
661 extern int srv;
662 extern int ncl;
663
664 int len;
665
666 if (PE_parse_boot_arg("-s", namep)) {
667 boothowto |= RB_SINGLE;
668 len = strlen(init_args);
669 if(len != 0)
670 strcat(init_args," -s");
671 else
672 strcat(init_args,"-s");
673 }
674 if (PE_parse_boot_arg("-b", namep)) {
675 boothowto |= RB_NOBOOTRC;
676 len = strlen(init_args);
677 if(len != 0)
678 strcat(init_args," -b");
679 else
680 strcat(init_args,"-b");
681 }
682
683 if (PE_parse_boot_arg("-F", namep)) {
684 len = strlen(init_args);
685 if(len != 0)
686 strcat(init_args," -F");
687 else
688 strcat(init_args,"-F");
689 }
690
691 if (PE_parse_boot_arg("-v", namep)) {
692 len = strlen(init_args);
693 if(len != 0)
694 strcat(init_args," -v");
695 else
696 strcat(init_args,"-v");
697 }
698
699 if (PE_parse_boot_arg("-x", namep)) { /* safe boot */
700 len = strlen(init_args);
701 if(len != 0)
702 strcat(init_args," -x");
703 else
704 strcat(init_args,"-x");
705 }
706
707 PE_parse_boot_arg("srv", &srv);
708 PE_parse_boot_arg("ncl", &ncl);
709 PE_parse_boot_arg("nbuf", &nbuf);
710
711 return 0;
712 }
713
714 boolean_t
715 thread_funnel_switch(
716 int oldfnl,
717 int newfnl)
718 {
719 thread_t cur_thread;
720 boolean_t funnel_state_prev;
721 int curfnl;
722 funnel_t * curflock;
723 funnel_t * oldflock;
724 funnel_t * newflock;
725 funnel_t * exist_funnel;
726 extern int disable_funnel;
727
728
729 if (disable_funnel)
730 return(TRUE);
731
732 if(oldfnl == newfnl) {
733 panic("thread_funnel_switch: can't switch to same funnel");
734 }
735
736 if ((oldfnl != NETWORK_FUNNEL) && (oldfnl != KERNEL_FUNNEL)) {
737 panic("thread_funnel_switch: invalid oldfunnel");
738 }
739 if ((newfnl != NETWORK_FUNNEL) && (newfnl != KERNEL_FUNNEL)) {
740 panic("thread_funnel_switch: invalid newfunnel");
741 }
742
743 if((curflock = thread_funnel_get()) == THR_FUNNEL_NULL) {
744 panic("thread_funnel_switch: no funnel held");
745 }
746
747 cur_thread = current_thread();
748
749 if ((oldfnl == NETWORK_FUNNEL) && (curflock != network_flock))
750 panic("thread_funnel_switch: network funnel not held");
751
752 if ((oldfnl == KERNEL_FUNNEL) && (curflock != kernel_flock))
753 panic("thread_funnel_switch: kernel funnel not held");
754
755 if(oldfnl == NETWORK_FUNNEL) {
756 oldflock = network_flock;
757 newflock = kernel_flock;
758 } else {
759 oldflock = kernel_flock;
760 newflock = network_flock;
761 }
762 KERNEL_DEBUG(0x603242c | DBG_FUNC_NONE, oldflock, 1, 0, 0, 0);
763 thread_funnel_set(oldflock, FALSE);
764 KERNEL_DEBUG(0x6032428 | DBG_FUNC_NONE, newflock, 1, 0, 0, 0);
765 thread_funnel_set(newflock, TRUE);
766 KERNEL_DEBUG(0x6032434 | DBG_FUNC_NONE, newflock, 1, 0, 0, 0);
767
768 return(TRUE);
769 }