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 9 * to the University of California by American Telephone and Telegraph 10 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 11 * the permission of UNIX System Laboratories, Inc. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 3. All advertising materials mentioning features or use of this software 22 * must display the following acknowledgement: 23 * This product includes software developed by the University of 24 * California, Berkeley and its contributors. 25 * 4. Neither the name of the University nor the names of its contributors 26 * may be used to endorse or promote products derived from this software 27 * without specific prior written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 * SUCH DAMAGE. 40 * 41 * @(#)init_main.c 8.9 (Berkeley) 1/21/94 42 */ 43 44 #include <sys/cdefs.h> 45 __FBSDID("$FreeBSD$"); 46 47 #include "opt_init_path.h" 48 #include "opt_mac.h" 49 50 #include <sys/param.h> 51 #include <sys/kernel.h> 52 #include <sys/exec.h> 53 #include <sys/file.h> 54 #include <sys/filedesc.h> 55 #include <sys/ktr.h> 56 #include <sys/lock.h> 57 #include <sys/mac.h> 58 #include <sys/mount.h> 59 #include <sys/mutex.h> 60 #include <sys/syscallsubr.h> 61 #include <sys/sysctl.h> 62 #include <sys/proc.h> 63 #include <sys/resourcevar.h> 64 #include <sys/systm.h> 65 #include <sys/signalvar.h> 66 #include <sys/vnode.h> 67 #include <sys/sysent.h> 68 #include <sys/reboot.h> 69 #include <sys/sched.h> 70 #include <sys/sx.h> 71 #include <sys/sysproto.h> 72 #include <sys/vmmeter.h> 73 #include <sys/unistd.h> 74 #include <sys/malloc.h> 75 #include <sys/conf.h> 76 77 #include <machine/cpu.h> 78 79 #include <vm/vm.h> 80 #include <vm/vm_param.h> 81 #include <vm/pmap.h> 82 #include <vm/vm_map.h> 83 #include <sys/copyright.h> 84 85 void mi_startup(void); /* Should be elsewhere */ 86 87 /* Components of the first process -- never freed. */ 88 static struct session session0; 89 static struct pgrp pgrp0; 90 struct proc proc0; 91 struct thread thread0; 92 struct ksegrp ksegrp0; 93 struct vmspace vmspace0; 94 struct proc *initproc; 95 96 int boothowto = 0; /* initialized so that it can be patched */ 97 SYSCTL_INT(_debug, OID_AUTO, boothowto, CTLFLAG_RD, &boothowto, 0, ""); 98 int bootverbose; 99 SYSCTL_INT(_debug, OID_AUTO, bootverbose, CTLFLAG_RW, &bootverbose, 0, ""); 100 101 /* 102 * This ensures that there is at least one entry so that the sysinit_set 103 * symbol is not undefined. A sybsystem ID of SI_SUB_DUMMY is never 104 * executed. 105 */ 106 SYSINIT(placeholder, SI_SUB_DUMMY, SI_ORDER_ANY, NULL, NULL) 107 108 /* 109 * The sysinit table itself. Items are checked off as the are run. 110 * If we want to register new sysinit types, add them to newsysinit. 111 */ 112 SET_DECLARE(sysinit_set, struct sysinit); 113 struct sysinit **sysinit, **sysinit_end; 114 struct sysinit **newsysinit, **newsysinit_end; 115 116 /* 117 * Merge a new sysinit set into the current set, reallocating it if 118 * necessary. This can only be called after malloc is running. 119 */ 120 void 121 sysinit_add(struct sysinit **set, struct sysinit **set_end) 122 { 123 struct sysinit **newset; 124 struct sysinit **sipp; 125 struct sysinit **xipp; 126 int count; 127 128 count = set_end - set; 129 if (newsysinit) 130 count += newsysinit_end - newsysinit; 131 else 132 count += sysinit_end - sysinit; 133 newset = malloc(count * sizeof(*sipp), M_TEMP, M_NOWAIT); 134 if (newset == NULL) 135 panic("cannot malloc for sysinit"); 136 xipp = newset; 137 if (newsysinit) 138 for (sipp = newsysinit; sipp < newsysinit_end; sipp++) 139 *xipp++ = *sipp; 140 else 141 for (sipp = sysinit; sipp < sysinit_end; sipp++) 142 *xipp++ = *sipp; 143 for (sipp = set; sipp < set_end; sipp++) 144 *xipp++ = *sipp; 145 if (newsysinit) 146 free(newsysinit, M_TEMP); 147 newsysinit = newset; 148 newsysinit_end = newset + count; 149 } 150 151 /* 152 * System startup; initialize the world, create process 0, mount root 153 * filesystem, and fork to create init and pagedaemon. Most of the 154 * hard work is done in the lower-level initialization routines including 155 * startup(), which does memory initialization and autoconfiguration. 156 * 157 * This allows simple addition of new kernel subsystems that require 158 * boot time initialization. It also allows substitution of subsystem 159 * (for instance, a scheduler, kernel profiler, or VM system) by object 160 * module. Finally, it allows for optional "kernel threads". 161 */ 162 void 163 mi_startup(void) 164 { 165 166 register struct sysinit **sipp; /* system initialization*/ 167 register struct sysinit **xipp; /* interior loop of sort*/ 168 register struct sysinit *save; /* bubble*/ 169 170 if (sysinit == NULL) { 171 sysinit = SET_BEGIN(sysinit_set); 172 sysinit_end = SET_LIMIT(sysinit_set); 173 } 174 175 restart: 176 /* 177 * Perform a bubble sort of the system initialization objects by 178 * their subsystem (primary key) and order (secondary key). 179 */ 180 for (sipp = sysinit; sipp < sysinit_end; sipp++) { 181 for (xipp = sipp + 1; xipp < sysinit_end; xipp++) { 182 if ((*sipp)->subsystem < (*xipp)->subsystem || 183 ((*sipp)->subsystem == (*xipp)->subsystem && 184 (*sipp)->order <= (*xipp)->order)) 185 continue; /* skip*/ 186 save = *sipp; 187 *sipp = *xipp; 188 *xipp = save; 189 } 190 } 191 192 /* 193 * Traverse the (now) ordered list of system initialization tasks. 194 * Perform each task, and continue on to the next task. 195 * 196 * The last item on the list is expected to be the scheduler, 197 * which will not return. 198 */ 199 for (sipp = sysinit; sipp < sysinit_end; sipp++) { 200 201 if ((*sipp)->subsystem == SI_SUB_DUMMY) 202 continue; /* skip dummy task(s)*/ 203 204 if ((*sipp)->subsystem == SI_SUB_DONE) 205 continue; 206 207 /* Call function */ 208 (*((*sipp)->func))((*sipp)->udata); 209 210 /* Check off the one we're just done */ 211 (*sipp)->subsystem = SI_SUB_DONE; 212 213 /* Check if we've installed more sysinit items via KLD */ 214 if (newsysinit != NULL) { 215 if (sysinit != SET_BEGIN(sysinit_set)) 216 free(sysinit, M_TEMP); 217 sysinit = newsysinit; 218 sysinit_end = newsysinit_end; 219 newsysinit = NULL; 220 newsysinit_end = NULL; 221 goto restart; 222 } 223 } 224 225 panic("Shouldn't get here!"); 226 /* NOTREACHED*/ 227 } 228 229 230 /* 231 *************************************************************************** 232 **** 233 **** The following SYSINIT's belong elsewhere, but have not yet 234 **** been moved. 235 **** 236 *************************************************************************** 237 */ 238 static void 239 print_caddr_t(void *data __unused) 240 { 241 printf("%s", (char *)data); 242 } 243 SYSINIT(announce, SI_SUB_COPYRIGHT, SI_ORDER_FIRST, print_caddr_t, copyright) 244 SYSINIT(version, SI_SUB_COPYRIGHT, SI_ORDER_SECOND, print_caddr_t, version) 245 246 #ifdef WITNESS 247 static char wit_warn[] = 248 "WARNING: WITNESS option enabled, expect reduced performance.\n"; 249 SYSINIT(witwarn, SI_SUB_COPYRIGHT, SI_ORDER_SECOND + 1, 250 print_caddr_t, wit_warn) 251 #endif 252 253 #ifdef DIAGNOSTIC 254 static char diag_warn[] = 255 "WARNING: DIAGNOSTIC option enabled, expect reduced performance.\n"; 256 SYSINIT(diagwarn, SI_SUB_COPYRIGHT, SI_ORDER_SECOND + 2, 257 print_caddr_t, diag_warn) 258 #endif 259 260 static void 261 set_boot_verbose(void *data __unused) 262 { 263 264 if (boothowto & RB_VERBOSE) 265 bootverbose++; 266 } 267 SYSINIT(boot_verbose, SI_SUB_TUNABLES, SI_ORDER_ANY, set_boot_verbose, NULL) 268 269 struct sysentvec null_sysvec = { 270 0, 271 NULL, 272 0, 273 0, 274 NULL, 275 0, 276 NULL, 277 NULL, 278 NULL, 279 NULL, 280 NULL, 281 NULL, 282 NULL, 283 "null", 284 NULL, 285 NULL, 286 0, 287 PAGE_SIZE, 288 VM_MIN_ADDRESS, 289 VM_MAXUSER_ADDRESS, 290 USRSTACK, 291 PS_STRINGS, 292 VM_PROT_ALL, 293 NULL, 294 NULL, 295 NULL 296 }; 297 298 /* 299 *************************************************************************** 300 **** 301 **** The two following SYSINIT's are proc0 specific glue code. I am not 302 **** convinced that they can not be safely combined, but their order of 303 **** operation has been maintained as the same as the original init_main.c 304 **** for right now. 305 **** 306 **** These probably belong in init_proc.c or kern_proc.c, since they 307 **** deal with proc0 (the fork template process). 308 **** 309 *************************************************************************** 310 */ 311 /* ARGSUSED*/ 312 static void 313 proc0_init(void *dummy __unused) 314 { 315 struct proc *p; 316 unsigned i; 317 struct thread *td; 318 struct ksegrp *kg; 319 320 GIANT_REQUIRED; 321 p = &proc0; 322 td = &thread0; 323 kg = &ksegrp0; 324 325 /* 326 * Initialize magic number. 327 */ 328 p->p_magic = P_MAGIC; 329 330 /* 331 * Initialize thread, process and ksegrp structures. 332 */ 333 procinit(); /* set up proc zone */ 334 threadinit(); /* set up thead, upcall and KSEGRP zones */ 335 336 /* 337 * Initialise scheduler resources. 338 * Add scheduler specific parts to proc, ksegrp, thread as needed. 339 */ 340 schedinit(); /* scheduler gets its house in order */ 341 /* 342 * Initialize sleep queue hash table 343 */ 344 sleepinit(); 345 346 /* 347 * additional VM structures 348 */ 349 vm_init2(); 350 351 /* 352 * Create process 0 (the swapper). 353 */ 354 LIST_INSERT_HEAD(&allproc, p, p_list); 355 LIST_INSERT_HEAD(PIDHASH(0), p, p_hash); 356 mtx_init(&pgrp0.pg_mtx, "process group", NULL, MTX_DEF | MTX_DUPOK); 357 p->p_pgrp = &pgrp0; 358 LIST_INSERT_HEAD(PGRPHASH(0), &pgrp0, pg_hash); 359 LIST_INIT(&pgrp0.pg_members); 360 LIST_INSERT_HEAD(&pgrp0.pg_members, p, p_pglist); 361 362 pgrp0.pg_session = &session0; 363 mtx_init(&session0.s_mtx, "session", NULL, MTX_DEF); 364 session0.s_count = 1; 365 session0.s_leader = p; 366 367 p->p_sysent = &null_sysvec; 368 p->p_flag = P_SYSTEM; 369 p->p_sflag = PS_INMEM; 370 p->p_state = PRS_NORMAL; 371 knlist_init(&p->p_klist, &p->p_mtx); 372 p->p_nice = NZERO; 373 td->td_state = TDS_RUNNING; 374 kg->kg_pri_class = PRI_TIMESHARE; 375 kg->kg_user_pri = PUSER; 376 td->td_priority = PVM; 377 td->td_base_pri = PUSER; 378 td->td_oncpu = 0; 379 p->p_peers = 0; 380 p->p_leader = p; 381 382 383 bcopy("swapper", p->p_comm, sizeof ("swapper")); 384 385 callout_init(&p->p_itcallout, CALLOUT_MPSAFE); 386 callout_init(&td->td_slpcallout, CALLOUT_MPSAFE); 387 388 /* Create credentials. */ 389 p->p_ucred = crget(); 390 p->p_ucred->cr_ngroups = 1; /* group 0 */ 391 p->p_ucred->cr_uidinfo = uifind(0); 392 p->p_ucred->cr_ruidinfo = uifind(0); 393 p->p_ucred->cr_prison = NULL; /* Don't jail it. */ 394 #ifdef MAC 395 mac_create_proc0(p->p_ucred); 396 #endif 397 td->td_ucred = crhold(p->p_ucred); 398 399 /* Create sigacts. */ 400 p->p_sigacts = sigacts_alloc(); 401 402 /* Initialize signal state for process 0. */ 403 siginit(&proc0); 404 405 /* Create the file descriptor table. */ 406 p->p_fd = fdinit(NULL); 407 p->p_fdtol = NULL; 408 409 /* Create the limits structures. */ 410 p->p_limit = lim_alloc(); 411 for (i = 0; i < RLIM_NLIMITS; i++) 412 p->p_limit->pl_rlimit[i].rlim_cur = 413 p->p_limit->pl_rlimit[i].rlim_max = RLIM_INFINITY; 414 p->p_limit->pl_rlimit[RLIMIT_NOFILE].rlim_cur = 415 p->p_limit->pl_rlimit[RLIMIT_NOFILE].rlim_max = maxfiles; 416 p->p_limit->pl_rlimit[RLIMIT_NPROC].rlim_cur = 417 p->p_limit->pl_rlimit[RLIMIT_NPROC].rlim_max = maxproc; 418 i = ptoa(cnt.v_free_count); 419 p->p_limit->pl_rlimit[RLIMIT_RSS].rlim_max = i; 420 p->p_limit->pl_rlimit[RLIMIT_MEMLOCK].rlim_max = i; 421 p->p_limit->pl_rlimit[RLIMIT_MEMLOCK].rlim_cur = i / 3; 422 p->p_cpulimit = RLIM_INFINITY; 423 424 p->p_stats = pstats_alloc(); 425 426 /* Allocate a prototype map so we have something to fork. */ 427 pmap_pinit0(vmspace_pmap(&vmspace0)); 428 p->p_vmspace = &vmspace0; 429 vmspace0.vm_refcnt = 1; 430 vm_map_init(&vmspace0.vm_map, p->p_sysent->sv_minuser, 431 p->p_sysent->sv_maxuser); 432 vmspace0.vm_map.pmap = vmspace_pmap(&vmspace0); 433 434 /* 435 * Charge root for one process. 436 */ 437 (void)chgproccnt(p->p_ucred->cr_ruidinfo, 1, 0); 438 } 439 SYSINIT(p0init, SI_SUB_INTRINSIC, SI_ORDER_FIRST, proc0_init, NULL) 440 441 /* ARGSUSED*/ 442 static void 443 proc0_post(void *dummy __unused) 444 { 445 struct timespec ts; 446 struct proc *p; 447 448 /* 449 * Now we can look at the time, having had a chance to verify the 450 * time from the filesystem. Pretend that proc0 started now. 451 */ 452 sx_slock(&allproc_lock); 453 LIST_FOREACH(p, &allproc, p_list) { 454 microuptime(&p->p_stats->p_start); 455 p->p_rux.rux_runtime.sec = 0; 456 p->p_rux.rux_runtime.frac = 0; 457 } 458 sx_sunlock(&allproc_lock); 459 binuptime(PCPU_PTR(switchtime)); 460 PCPU_SET(switchticks, ticks); 461 462 /* 463 * Give the ``random'' number generator a thump. 464 */ 465 nanotime(&ts); 466 srandom(ts.tv_sec ^ ts.tv_nsec); 467 } 468 SYSINIT(p0post, SI_SUB_INTRINSIC_POST, SI_ORDER_FIRST, proc0_post, NULL) 469 470 /* 471 *************************************************************************** 472 **** 473 **** The following SYSINIT's and glue code should be moved to the 474 **** respective files on a per subsystem basis. 475 **** 476 *************************************************************************** 477 */ 478 479 480 /* 481 *************************************************************************** 482 **** 483 **** The following code probably belongs in another file, like 484 **** kern/init_init.c. 485 **** 486 *************************************************************************** 487 */ 488 489 /* 490 * List of paths to try when searching for "init". 491 */ 492 static char init_path[MAXPATHLEN] = 493 #ifdef INIT_PATH 494 __XSTRING(INIT_PATH); 495 #else 496 "/sbin/init:/sbin/oinit:/sbin/init.bak:/stand/sysinstall"; 497 #endif 498 SYSCTL_STRING(_kern, OID_AUTO, init_path, CTLFLAG_RD, init_path, 0, 499 "Path used to search the init process"); 500 501 /* 502 * Start the initial user process; try exec'ing each pathname in init_path. 503 * The program is invoked with one argument containing the boot flags. 504 */ 505 static void 506 start_init(void *dummy) 507 { 508 vm_offset_t addr; 509 struct execve_args args; 510 int options, error; 511 char *var, *path, *next, *s; 512 char *ucp, **uap, *arg0, *arg1; 513 struct thread *td; 514 struct proc *p; 515 516 mtx_lock(&Giant); 517 518 GIANT_REQUIRED; 519 520 td = curthread; 521 p = td->td_proc; 522 523 vfs_mountroot(); 524 525 #ifdef MAC 526 mac_create_root_mount(td->td_ucred, TAILQ_FIRST(&mountlist)); 527 #endif 528 529 /* 530 * Need just enough stack to hold the faked-up "execve()" arguments. 531 */ 532 addr = p->p_sysent->sv_usrstack - PAGE_SIZE; 533 if (vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &addr, PAGE_SIZE, 534 FALSE, VM_PROT_ALL, VM_PROT_ALL, 0) != 0) 535 panic("init: couldn't allocate argument space"); 536 p->p_vmspace->vm_maxsaddr = (caddr_t)addr; 537 p->p_vmspace->vm_ssize = 1; 538 539 if ((var = getenv("init_path")) != NULL) { 540 strlcpy(init_path, var, sizeof(init_path)); 541 freeenv(var); 542 } 543 544 for (path = init_path; *path != '\0'; path = next) { 545 while (*path == ':') 546 path++; 547 if (*path == '\0') 548 break; 549 for (next = path; *next != '\0' && *next != ':'; next++) 550 /* nothing */ ; 551 if (bootverbose) 552 printf("start_init: trying %.*s\n", (int)(next - path), 553 path); 554 555 /* 556 * Move out the boot flag argument. 557 */ 558 options = 0; 559 ucp = (char *)p->p_sysent->sv_usrstack; 560 (void)subyte(--ucp, 0); /* trailing zero */ 561 if (boothowto & RB_SINGLE) { 562 (void)subyte(--ucp, 's'); 563 options = 1; 564 } 565 #ifdef notyet 566 if (boothowto & RB_FASTBOOT) { 567 (void)subyte(--ucp, 'f'); 568 options = 1; 569 } 570 #endif 571 572 #ifdef BOOTCDROM 573 (void)subyte(--ucp, 'C'); 574 options = 1; 575 #endif 576 577 if (options == 0) 578 (void)subyte(--ucp, '-'); 579 (void)subyte(--ucp, '-'); /* leading hyphen */ 580 arg1 = ucp; 581 582 /* 583 * Move out the file name (also arg 0). 584 */ 585 (void)subyte(--ucp, 0); 586 for (s = next - 1; s >= path; s--) 587 (void)subyte(--ucp, *s); 588 arg0 = ucp; 589 590 /* 591 * Move out the arg pointers. 592 */ 593 uap = (char **)((intptr_t)ucp & ~(sizeof(intptr_t)-1)); 594 (void)suword((caddr_t)--uap, (long)0); /* terminator */ 595 (void)suword((caddr_t)--uap, (long)(intptr_t)arg1); 596 (void)suword((caddr_t)--uap, (long)(intptr_t)arg0); 597 598 /* 599 * Point at the arguments. 600 */ 601 args.fname = arg0; 602 args.argv = uap; 603 args.envv = NULL; 604 605 /* 606 * Now try to exec the program. If can't for any reason 607 * other than it doesn't exist, complain. 608 * 609 * Otherwise, return via fork_trampoline() all the way 610 * to user mode as init! 611 */ 612 if ((error = execve(td, &args)) == 0) { 613 mtx_unlock(&Giant); 614 return; 615 } 616 if (error != ENOENT) 617 printf("exec %.*s: error %d\n", (int)(next - path), 618 path, error); 619 } 620 printf("init: not found in path %s\n", init_path); 621 panic("no init"); 622 } 623 624 /* 625 * Like kthread_create(), but runs in it's own address space. 626 * We do this early to reserve pid 1. 627 * 628 * Note special case - do not make it runnable yet. Other work 629 * in progress will change this more. 630 */ 631 static void 632 create_init(const void *udata __unused) 633 { 634 struct ucred *newcred, *oldcred; 635 int error; 636 637 error = fork1(&thread0, RFFDG | RFPROC | RFSTOPPED, 0, &initproc); 638 if (error) 639 panic("cannot fork init: %d\n", error); 640 KASSERT(initproc->p_pid == 1, ("create_init: initproc->p_pid != 1")); 641 /* divorce init's credentials from the kernel's */ 642 newcred = crget(); 643 PROC_LOCK(initproc); 644 initproc->p_flag |= P_SYSTEM; 645 oldcred = initproc->p_ucred; 646 crcopy(newcred, oldcred); 647 #ifdef MAC 648 mac_create_proc1(newcred); 649 #endif 650 initproc->p_ucred = newcred; 651 PROC_UNLOCK(initproc); 652 crfree(oldcred); 653 cred_update_thread(FIRST_THREAD_IN_PROC(initproc)); 654 mtx_lock_spin(&sched_lock); 655 initproc->p_sflag |= PS_INMEM; 656 mtx_unlock_spin(&sched_lock); 657 cpu_set_fork_handler(FIRST_THREAD_IN_PROC(initproc), start_init, NULL); 658 } 659 SYSINIT(init, SI_SUB_CREATE_INIT, SI_ORDER_FIRST, create_init, NULL) 660 661 /* 662 * Make it runnable now. 663 */ 664 static void 665 kick_init(const void *udata __unused) 666 { 667 struct thread *td; 668 669 td = FIRST_THREAD_IN_PROC(initproc); 670 mtx_lock_spin(&sched_lock); 671 TD_SET_CAN_RUN(td); 672 setrunqueue(td, SRQ_BORING); /* XXXKSE */ 673 mtx_unlock_spin(&sched_lock); 674 } 675 SYSINIT(kickinit, SI_SUB_KTHREAD_INIT, SI_ORDER_FIRST, kick_init, NULL) 676