init_main.c (af4b2d2d1cbe098025b9aa63c6682e069be82913) | init_main.c (37b087a645354d60200c774d51b305b268e41c83) |
---|---|
1/* 2 * Copyright (c) 1995 Terrence R. Lambert 3 * All rights reserved. 4 * 5 * Copyright (c) 1982, 1986, 1989, 1991, 1992, 1993 6 * The Regents of the University of California. All rights reserved. 7 * (c) UNIX System Laboratories, Inc. 8 * All or some portions of this file are derived from material licensed --- 60 unchanged lines hidden (view full) --- 69#include <sys/lock.h> 70#include <vm/pmap.h> 71#include <vm/vm_map.h> 72#include <sys/user.h> 73#include <sys/copyright.h> 74 75extern struct linker_set sysinit_set; /* XXX */ 76 | 1/* 2 * Copyright (c) 1995 Terrence R. Lambert 3 * All rights reserved. 4 * 5 * Copyright (c) 1982, 1986, 1989, 1991, 1992, 1993 6 * The Regents of the University of California. All rights reserved. 7 * (c) UNIX System Laboratories, Inc. 8 * All or some portions of this file are derived from material licensed --- 60 unchanged lines hidden (view full) --- 69#include <sys/lock.h> 70#include <vm/pmap.h> 71#include <vm/vm_map.h> 72#include <sys/user.h> 73#include <sys/copyright.h> 74 75extern struct linker_set sysinit_set; /* XXX */ 76 |
77extern void mi_startup __P((void *framep)); | 77void mi_startup(void); /* Should be elsewhere */ |
78 79/* Components of the first process -- never freed. */ 80static struct session session0; 81static struct pgrp pgrp0; 82struct proc proc0; 83static struct pcred cred0; 84static struct procsig procsig0; 85static struct filedesc0 filedesc0; --- 4 unchanged lines hidden (view full) --- 90int cmask = CMASK; 91extern struct user *proc0paddr; 92 93struct vnode *rootvp; 94int boothowto = 0; /* initialized so that it can be patched */ 95SYSCTL_INT(_debug, OID_AUTO, boothowto, CTLFLAG_RD, &boothowto, 0, ""); 96 97/* | 78 79/* Components of the first process -- never freed. */ 80static struct session session0; 81static struct pgrp pgrp0; 82struct proc proc0; 83static struct pcred cred0; 84static struct procsig procsig0; 85static struct filedesc0 filedesc0; --- 4 unchanged lines hidden (view full) --- 90int cmask = CMASK; 91extern struct user *proc0paddr; 92 93struct vnode *rootvp; 94int boothowto = 0; /* initialized so that it can be patched */ 95SYSCTL_INT(_debug, OID_AUTO, boothowto, CTLFLAG_RD, &boothowto, 0, ""); 96 97/* |
98 * Promiscuous argument pass for start_init() 99 * 100 * This is a kludge because we use a return from mi_startup() rather than a call 101 * to a new routine in locore.s to kick the kernel alive from locore.s. 102 */ 103static void *init_framep; 104 105/* | |
106 * This ensures that there is at least one entry so that the sysinit_set 107 * symbol is not undefined. A sybsystem ID of SI_SUB_DUMMY is never 108 * executed. 109 */ | 98 * This ensures that there is at least one entry so that the sysinit_set 99 * symbol is not undefined. A sybsystem ID of SI_SUB_DUMMY is never 100 * executed. 101 */ |
110SYSINIT(placeholder, SI_SUB_DUMMY,SI_ORDER_ANY, NULL, NULL) | 102SYSINIT(placeholder, SI_SUB_DUMMY, SI_ORDER_ANY, NULL, NULL) |
111 112/* 113 * The sysinit table itself. Items are checked off as the are run. 114 * If we want to register new sysinit types, add them to newsysinit. 115 */ 116struct sysinit **sysinit = (struct sysinit **)sysinit_set.ls_items; 117struct sysinit **newsysinit; 118 119/* 120 * Merge a new sysinit set into the current set, reallocating it if 121 * necessary. This can only be called after malloc is running. 122 */ 123void | 103 104/* 105 * The sysinit table itself. Items are checked off as the are run. 106 * If we want to register new sysinit types, add them to newsysinit. 107 */ 108struct sysinit **sysinit = (struct sysinit **)sysinit_set.ls_items; 109struct sysinit **newsysinit; 110 111/* 112 * Merge a new sysinit set into the current set, reallocating it if 113 * necessary. This can only be called after malloc is running. 114 */ 115void |
124sysinit_add(set) 125 struct sysinit **set; | 116sysinit_add(struct sysinit **set) |
126{ 127 struct sysinit **newset; 128 struct sysinit **sipp; 129 struct sysinit **xipp; 130 int count = 0; 131 132 if (newsysinit) 133 for (sipp = newsysinit; *sipp; sipp++) --- 29 unchanged lines hidden (view full) --- 163 * startup(), which does memory initialization and autoconfiguration. 164 * 165 * This allows simple addition of new kernel subsystems that require 166 * boot time initialization. It also allows substitution of subsystem 167 * (for instance, a scheduler, kernel profiler, or VM system) by object 168 * module. Finally, it allows for optional "kernel threads". 169 */ 170void | 117{ 118 struct sysinit **newset; 119 struct sysinit **sipp; 120 struct sysinit **xipp; 121 int count = 0; 122 123 if (newsysinit) 124 for (sipp = newsysinit; *sipp; sipp++) --- 29 unchanged lines hidden (view full) --- 154 * startup(), which does memory initialization and autoconfiguration. 155 * 156 * This allows simple addition of new kernel subsystems that require 157 * boot time initialization. It also allows substitution of subsystem 158 * (for instance, a scheduler, kernel profiler, or VM system) by object 159 * module. Finally, it allows for optional "kernel threads". 160 */ 161void |
171mi_startup(framep) 172 void *framep; | 162mi_startup(void) |
173{ 174 175 register struct sysinit **sipp; /* system initialization*/ 176 register struct sysinit **xipp; /* interior loop of sort*/ 177 register struct sysinit *save; /* bubble*/ 178 | 163{ 164 165 register struct sysinit **sipp; /* system initialization*/ 166 register struct sysinit **xipp; /* interior loop of sort*/ 167 register struct sysinit *save; /* bubble*/ 168 |
179 /* 180 * Copy the locore.s frame pointer for proc0, this is forked into 181 * all other processes. 182 */ 183 init_framep = framep; 184 | |
185restart: 186 /* 187 * Perform a bubble sort of the system initialization objects by 188 * their subsystem (primary key) and order (secondary key). 189 */ 190 for (sipp = sysinit; *sipp; sipp++) { 191 for (xipp = sipp + 1; *xipp; xipp++) { 192 if ((*sipp)->subsystem < (*xipp)->subsystem || --- 45 unchanged lines hidden (view full) --- 238/* 239 *************************************************************************** 240 **** 241 **** The following SYSINIT's belong elsewhere, but have not yet 242 **** been moved. 243 **** 244 *************************************************************************** 245 */ | 169restart: 170 /* 171 * Perform a bubble sort of the system initialization objects by 172 * their subsystem (primary key) and order (secondary key). 173 */ 174 for (sipp = sysinit; *sipp; sipp++) { 175 for (xipp = sipp + 1; *xipp; xipp++) { 176 if ((*sipp)->subsystem < (*xipp)->subsystem || --- 45 unchanged lines hidden (view full) --- 222/* 223 *************************************************************************** 224 **** 225 **** The following SYSINIT's belong elsewhere, but have not yet 226 **** been moved. 227 **** 228 *************************************************************************** 229 */ |
246static void print_caddr_t __P((void *data)); | |
247static void | 230static void |
248print_caddr_t(data) 249 void *data; | 231print_caddr_t(void *data __unused) |
250{ 251 printf("%s", (char *)data); 252} 253SYSINIT(announce, SI_SUB_COPYRIGHT, SI_ORDER_FIRST, print_caddr_t, copyright) 254 255 256/* 257 *************************************************************************** --- 4 unchanged lines hidden (view full) --- 262 **** for right now. 263 **** 264 **** These probably belong in init_proc.c or kern_proc.c, since they 265 **** deal with proc0 (the fork template process). 266 **** 267 *************************************************************************** 268 */ 269/* ARGSUSED*/ | 232{ 233 printf("%s", (char *)data); 234} 235SYSINIT(announce, SI_SUB_COPYRIGHT, SI_ORDER_FIRST, print_caddr_t, copyright) 236 237 238/* 239 *************************************************************************** --- 4 unchanged lines hidden (view full) --- 244 **** for right now. 245 **** 246 **** These probably belong in init_proc.c or kern_proc.c, since they 247 **** deal with proc0 (the fork template process). 248 **** 249 *************************************************************************** 250 */ 251/* ARGSUSED*/ |
270static void proc0_init __P((void *dummy)); | |
271static void | 252static void |
272proc0_init(dummy) 273 void *dummy; | 253proc0_init(void *dummy __unused) |
274{ 275 register struct proc *p; 276 register struct filedesc0 *fdp; 277 register unsigned i; 278 279 p = &proc0; 280 281 /* --- 27 unchanged lines hidden (view full) --- 309 p->p_sysent = &aout_sysvec; 310 311 p->p_flag = P_INMEM | P_SYSTEM; 312 p->p_stat = SRUN; 313 p->p_nice = NZERO; 314 p->p_rtprio.type = RTP_PRIO_NORMAL; 315 p->p_rtprio.prio = 0; 316 | 254{ 255 register struct proc *p; 256 register struct filedesc0 *fdp; 257 register unsigned i; 258 259 p = &proc0; 260 261 /* --- 27 unchanged lines hidden (view full) --- 289 p->p_sysent = &aout_sysvec; 290 291 p->p_flag = P_INMEM | P_SYSTEM; 292 p->p_stat = SRUN; 293 p->p_nice = NZERO; 294 p->p_rtprio.type = RTP_PRIO_NORMAL; 295 p->p_rtprio.prio = 0; 296 |
317/* 318 * Link for kernel based threads 319 */ | |
320 p->p_peers = 0; 321 p->p_leader = p; 322 323 bcopy("swapper", p->p_comm, sizeof ("swapper")); 324 325 /* Create credentials. */ 326 cred0.p_refcnt = 1; 327 p->p_cred = &cred0; 328 p->p_ucred = crget(); 329 p->p_ucred->cr_ngroups = 1; /* group 0 */ 330 331 /* Don't jail it */ 332 p->p_prison = 0; 333 334 /* Create procsig. */ 335 p->p_procsig = &procsig0; 336 p->p_procsig->ps_refcnt = 1; 337 | 297 p->p_peers = 0; 298 p->p_leader = p; 299 300 bcopy("swapper", p->p_comm, sizeof ("swapper")); 301 302 /* Create credentials. */ 303 cred0.p_refcnt = 1; 304 p->p_cred = &cred0; 305 p->p_ucred = crget(); 306 p->p_ucred->cr_ngroups = 1; /* group 0 */ 307 308 /* Don't jail it */ 309 p->p_prison = 0; 310 311 /* Create procsig. */ 312 p->p_procsig = &procsig0; 313 p->p_procsig->ps_refcnt = 1; 314 |
315 /* Initialize signal state for process 0. */ 316 siginit(&proc0); 317 |
|
338 /* Create the file descriptor table. */ 339 fdp = &filedesc0; 340 p->p_fd = &fdp->fd_fd; 341 fdp->fd_fd.fd_refcnt = 1; 342 fdp->fd_fd.fd_cmask = cmask; 343 fdp->fd_fd.fd_ofiles = fdp->fd_dfiles; 344 fdp->fd_fd.fd_ofileflags = fdp->fd_dfileflags; 345 fdp->fd_fd.fd_nfiles = NDFILE; --- 9 unchanged lines hidden (view full) --- 355 limit0.pl_rlimit[RLIMIT_NPROC].rlim_max = maxproc; 356 i = ptoa(cnt.v_free_count); 357 limit0.pl_rlimit[RLIMIT_RSS].rlim_max = i; 358 limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_max = i; 359 limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_cur = i / 3; 360 limit0.p_cpulimit = RLIM_INFINITY; 361 limit0.p_refcnt = 1; 362 | 318 /* Create the file descriptor table. */ 319 fdp = &filedesc0; 320 p->p_fd = &fdp->fd_fd; 321 fdp->fd_fd.fd_refcnt = 1; 322 fdp->fd_fd.fd_cmask = cmask; 323 fdp->fd_fd.fd_ofiles = fdp->fd_dfiles; 324 fdp->fd_fd.fd_ofileflags = fdp->fd_dfileflags; 325 fdp->fd_fd.fd_nfiles = NDFILE; --- 9 unchanged lines hidden (view full) --- 335 limit0.pl_rlimit[RLIMIT_NPROC].rlim_max = maxproc; 336 i = ptoa(cnt.v_free_count); 337 limit0.pl_rlimit[RLIMIT_RSS].rlim_max = i; 338 limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_max = i; 339 limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_cur = i / 3; 340 limit0.p_cpulimit = RLIM_INFINITY; 341 limit0.p_refcnt = 1; 342 |
363 | |
364 /* Allocate a prototype map so we have something to fork. */ 365 pmap_pinit0(vmspace_pmap(&vmspace0)); 366 p->p_vmspace = &vmspace0; 367 vmspace0.vm_refcnt = 1; 368 vm_map_init(&vmspace0.vm_map, round_page(VM_MIN_ADDRESS), 369 trunc_page(VM_MAXUSER_ADDRESS)); 370 vmspace0.vm_map.pmap = vmspace_pmap(&vmspace0); 371 p->p_addr = proc0paddr; /* XXX */ 372 | 343 /* Allocate a prototype map so we have something to fork. */ 344 pmap_pinit0(vmspace_pmap(&vmspace0)); 345 p->p_vmspace = &vmspace0; 346 vmspace0.vm_refcnt = 1; 347 vm_map_init(&vmspace0.vm_map, round_page(VM_MIN_ADDRESS), 348 trunc_page(VM_MAXUSER_ADDRESS)); 349 vmspace0.vm_map.pmap = vmspace_pmap(&vmspace0); 350 p->p_addr = proc0paddr; /* XXX */ 351 |
373#ifdef cpu_set_init_frame | |
374 /* | 352 /* |
375 * proc0 needs to have a coherent frame base in its stack. 376 */ 377 cpu_set_init_frame(p, init_framep); /* XXX! */ 378#endif 379 380 /* | |
381 * We continue to place resource usage info and signal 382 * actions in the user struct so they're pageable. 383 */ 384 p->p_stats = &p->p_addr->u_stats; 385 p->p_sigacts = &p->p_addr->u_sigacts; 386 387 /* 388 * Charge root for one process. --- 5 unchanged lines hidden (view full) --- 394 * any possible traps/probes to simplify trap processing. 395 */ 396 SET_CURPROC(p); 397 398} 399SYSINIT(p0init, SI_SUB_INTRINSIC, SI_ORDER_FIRST, proc0_init, NULL) 400 401/* ARGSUSED*/ | 353 * We continue to place resource usage info and signal 354 * actions in the user struct so they're pageable. 355 */ 356 p->p_stats = &p->p_addr->u_stats; 357 p->p_sigacts = &p->p_addr->u_sigacts; 358 359 /* 360 * Charge root for one process. --- 5 unchanged lines hidden (view full) --- 366 * any possible traps/probes to simplify trap processing. 367 */ 368 SET_CURPROC(p); 369 370} 371SYSINIT(p0init, SI_SUB_INTRINSIC, SI_ORDER_FIRST, proc0_init, NULL) 372 373/* ARGSUSED*/ |
402static void proc0_post __P((void *dummy)); | |
403static void | 374static void |
404proc0_post(dummy) 405 void *dummy; | 375proc0_post(void *dummy __unused) |
406{ 407 struct timespec ts; | 376{ 377 struct timespec ts; |
378 struct proc *p; |
|
408 409 /* 410 * Now we can look at the time, having had a chance to verify the 411 * time from the file system. Pretend that proc0 started now. 412 */ | 379 380 /* 381 * Now we can look at the time, having had a chance to verify the 382 * time from the file system. Pretend that proc0 started now. 383 */ |
413 microtime(&proc0.p_stats->p_start); 414 proc0.p_runtime = 0; | 384 LIST_FOREACH(p, &allproc, p_list) { 385 microtime(&p->p_stats->p_start); 386 p->p_runtime = 0; 387 } |
415 microuptime(&switchtime); 416 switchticks = ticks; 417 418 /* 419 * Give the ``random'' number generator a thump. 420 */ 421 nanotime(&ts); 422 srandom(ts.tv_sec ^ ts.tv_nsec); | 388 microuptime(&switchtime); 389 switchticks = ticks; 390 391 /* 392 * Give the ``random'' number generator a thump. 393 */ 394 nanotime(&ts); 395 srandom(ts.tv_sec ^ ts.tv_nsec); |
423 424 /* Initialize signal state for process 0. */ 425 siginit(&proc0); | |
426} 427SYSINIT(p0post, SI_SUB_INTRINSIC_POST, SI_ORDER_FIRST, proc0_post, NULL) 428 | 396} 397SYSINIT(p0post, SI_SUB_INTRINSIC_POST, SI_ORDER_FIRST, proc0_post, NULL) 398 |
429 430 431 | |
432/* 433 *************************************************************************** 434 **** 435 **** The following SYSINIT's and glue code should be moved to the 436 **** respective files on a per subsystem basis. 437 **** 438 *************************************************************************** 439 */ 440 | 399/* 400 *************************************************************************** 401 **** 402 **** The following SYSINIT's and glue code should be moved to the 403 **** respective files on a per subsystem basis. 404 **** 405 *************************************************************************** 406 */ 407 |
441/* ARGSUSED*/ 442static void xxx_vfs_root_fdtab __P((void *dummy)); 443static void 444xxx_vfs_root_fdtab(dummy) 445 void *dummy; 446{ 447 register struct filedesc0 *fdp = &filedesc0; | |
448 | 408 |
449 /* Get the vnode for '/'. Set fdp->fd_fd.fd_cdir to reference it. */ 450 if (VFS_ROOT(TAILQ_FIRST(&mountlist), &rootvnode)) 451 panic("cannot find root vnode"); 452 fdp->fd_fd.fd_cdir = rootvnode; 453 VREF(fdp->fd_fd.fd_cdir); 454 VOP_UNLOCK(rootvnode, 0, &proc0); 455 fdp->fd_fd.fd_rdir = rootvnode; 456} 457SYSINIT(retrofit, SI_SUB_ROOT_FDTAB, SI_ORDER_FIRST, xxx_vfs_root_fdtab, NULL) 458 459 | |
460/* 461 *************************************************************************** 462 **** 463 **** The following code probably belongs in another file, like | 409/* 410 *************************************************************************** 411 **** 412 **** The following code probably belongs in another file, like |
464 **** kern/init_init.c. It is here for two reasons only: | 413 **** kern/init_init.c. |
465 **** | 414 **** |
466 **** 1) This code returns to startup the system; this is 467 **** abnormal for a kernel thread. 468 **** 2) This code promiscuously uses init_frame 469 **** | |
470 *************************************************************************** 471 */ 472 | 415 *************************************************************************** 416 */ 417 |
473extern void prepare_usermode __P((void)); 474static void create_init __P((const void *dummy)); 475static void start_init __P((void *dummy)); 476SYSINIT(init,SI_SUB_KTHREAD_INIT, SI_ORDER_FIRST, create_init, NULL) | |
477 478/* | 418 419/* |
479 * Like kthread_create(), but runs in it's own address space. 480 */ 481static void 482create_init(udata) 483 const void *udata; 484{ 485 int error; 486 487 error = fork1(&proc0, RFFDG | RFPROC, &initproc); 488 if (error) 489 panic("cannot fork init: %d\n", error); 490 initproc->p_flag |= P_INMEM | P_SYSTEM; 491 cpu_set_fork_handler(initproc, start_init, NULL); 492} 493 494/* | |
495 * List of paths to try when searching for "init". 496 */ 497static char init_path[MAXPATHLEN] = 498#ifdef INIT_PATH 499 __XSTRING(INIT_PATH); 500#else 501 "/sbin/init:/sbin/oinit:/sbin/init.bak:/stand/sysinstall"; 502#endif 503SYSCTL_STRING(_kern, OID_AUTO, init_path, CTLFLAG_RD, init_path, 0, ""); 504 505/* 506 * Start the initial user process; try exec'ing each pathname in init_path. 507 * The program is invoked with one argument containing the boot flags. 508 */ 509static void | 420 * List of paths to try when searching for "init". 421 */ 422static char init_path[MAXPATHLEN] = 423#ifdef INIT_PATH 424 __XSTRING(INIT_PATH); 425#else 426 "/sbin/init:/sbin/oinit:/sbin/init.bak:/stand/sysinstall"; 427#endif 428SYSCTL_STRING(_kern, OID_AUTO, init_path, CTLFLAG_RD, init_path, 0, ""); 429 430/* 431 * Start the initial user process; try exec'ing each pathname in init_path. 432 * The program is invoked with one argument containing the boot flags. 433 */ 434static void |
510start_init(dummy) 511 void *dummy; | 435start_init(void *dummy) |
512{ 513 vm_offset_t addr; 514 struct execve_args args; 515 int options, error; 516 char *var, *path, *next, *s; 517 char *ucp, **uap, *arg0, *arg1; 518 struct proc *p; 519 520 p = curproc; 521 | 436{ 437 vm_offset_t addr; 438 struct execve_args args; 439 int options, error; 440 char *var, *path, *next, *s; 441 char *ucp, **uap, *arg0, *arg1; 442 struct proc *p; 443 444 p = curproc; 445 |
446 /* Get the vnode for '/'. Set p->p_fd->fd_cdir to reference it. */ 447 if (VFS_ROOT(TAILQ_FIRST(&mountlist), &rootvnode)) 448 panic("cannot find root vnode"); 449 p->p_fd->fd_cdir = rootvnode; 450 VREF(p->p_fd->fd_cdir); 451 p->p_fd->fd_rdir = rootvnode; 452 VOP_UNLOCK(rootvnode, 0, p); 453 |
|
522 /* 523 * Need just enough stack to hold the faked-up "execve()" arguments. 524 */ 525 addr = trunc_page(USRSTACK - PAGE_SIZE); 526 if (vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &addr, PAGE_SIZE, 527 FALSE, VM_PROT_ALL, VM_PROT_ALL, 0) != 0) 528 panic("init: couldn't allocate argument space"); 529 p->p_vmspace->vm_maxsaddr = (caddr_t)addr; --- 63 unchanged lines hidden (view full) --- 593 args.fname = arg0; 594 args.argv = uap; 595 args.envv = NULL; 596 597 /* 598 * Now try to exec the program. If can't for any reason 599 * other than it doesn't exist, complain. 600 * | 454 /* 455 * Need just enough stack to hold the faked-up "execve()" arguments. 456 */ 457 addr = trunc_page(USRSTACK - PAGE_SIZE); 458 if (vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &addr, PAGE_SIZE, 459 FALSE, VM_PROT_ALL, VM_PROT_ALL, 0) != 0) 460 panic("init: couldn't allocate argument space"); 461 p->p_vmspace->vm_maxsaddr = (caddr_t)addr; --- 63 unchanged lines hidden (view full) --- 525 args.fname = arg0; 526 args.argv = uap; 527 args.envv = NULL; 528 529 /* 530 * Now try to exec the program. If can't for any reason 531 * other than it doesn't exist, complain. 532 * |
601 * Otherwise, return via the fork trampoline all the way | 533 * Otherwise, return via fork_trampoline() all the way |
602 * to user mode as init! 603 */ | 534 * to user mode as init! 535 */ |
604 if ((error = execve(p, &args)) == 0) { 605 prepare_usermode(); | 536 if ((error = execve(p, &args)) == 0) |
606 return; | 537 return; |
607 } | |
608 if (error != ENOENT) 609 printf("exec %.*s: error %d\n", (int)(next - path), 610 path, error); 611 } 612 printf("init: not found in path %s\n", init_path); 613 panic("no init"); 614} | 538 if (error != ENOENT) 539 printf("exec %.*s: error %d\n", (int)(next - path), 540 path, error); 541 } 542 printf("init: not found in path %s\n", init_path); 543 panic("no init"); 544} |
545 546/* 547 * Like kthread_create(), but runs in it's own address space. 548 * We do this early to reserve pid 1. 549 * 550 * Note special case - do not make it runnable yet. Other work 551 * in progress will change this more. 552 */ 553static void 554create_init(const void *udata __unused) 555{ 556 int error; 557 int s; 558 559 s = splhigh(); 560 error = fork1(&proc0, RFFDG | RFPROC, &initproc); 561 if (error) 562 panic("cannot fork init: %d\n", error); 563 initproc->p_flag |= P_INMEM | P_SYSTEM; 564 cpu_set_fork_handler(initproc, start_init, NULL); 565 remrunqueue(initproc); 566 splx(s); 567} 568SYSINIT(init,SI_SUB_CREATE_INIT, SI_ORDER_FIRST, create_init, NULL) 569 570/* 571 * Make it runnable now. 572 */ 573static void 574kick_init(const void *udata __unused) 575{ 576 setrunqueue(initproc); 577} 578SYSINIT(kickinit,SI_SUB_KTHREAD_INIT, SI_ORDER_FIRST, kick_init, NULL) |
|