1df8bae1dSRodney W. Grimes /* 22b14f991SJulian Elischer * Copyright (c) 1995 Terrence R. Lambert 32b14f991SJulian Elischer * All rights reserved. 42b14f991SJulian Elischer * 5df8bae1dSRodney W. Grimes * Copyright (c) 1982, 1986, 1989, 1991, 1992, 1993 6df8bae1dSRodney W. Grimes * The Regents of the University of California. All rights reserved. 7df8bae1dSRodney W. Grimes * (c) UNIX System Laboratories, Inc. 8df8bae1dSRodney W. Grimes * All or some portions of this file are derived from material licensed 9df8bae1dSRodney W. Grimes * to the University of California by American Telephone and Telegraph 10df8bae1dSRodney W. Grimes * Co. or Unix System Laboratories, Inc. and are reproduced herein with 11df8bae1dSRodney W. Grimes * the permission of UNIX System Laboratories, Inc. 12df8bae1dSRodney W. Grimes * 13df8bae1dSRodney W. Grimes * Redistribution and use in source and binary forms, with or without 14df8bae1dSRodney W. Grimes * modification, are permitted provided that the following conditions 15df8bae1dSRodney W. Grimes * are met: 16df8bae1dSRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 17df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer. 18df8bae1dSRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 19df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 20df8bae1dSRodney W. Grimes * documentation and/or other materials provided with the distribution. 21df8bae1dSRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 22df8bae1dSRodney W. Grimes * must display the following acknowledgement: 23df8bae1dSRodney W. Grimes * This product includes software developed by the University of 24df8bae1dSRodney W. Grimes * California, Berkeley and its contributors. 25df8bae1dSRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 26df8bae1dSRodney W. Grimes * may be used to endorse or promote products derived from this software 27df8bae1dSRodney W. Grimes * without specific prior written permission. 28df8bae1dSRodney W. Grimes * 29df8bae1dSRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 30df8bae1dSRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 31df8bae1dSRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32df8bae1dSRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 33df8bae1dSRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 34df8bae1dSRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 35df8bae1dSRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36df8bae1dSRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37df8bae1dSRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 38df8bae1dSRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39df8bae1dSRodney W. Grimes * SUCH DAMAGE. 40df8bae1dSRodney W. Grimes * 41df8bae1dSRodney W. Grimes * @(#)init_main.c 8.9 (Berkeley) 1/21/94 42df8bae1dSRodney W. Grimes */ 43df8bae1dSRodney W. Grimes 44677b542eSDavid E. O'Brien #include <sys/cdefs.h> 45677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$"); 46677b542eSDavid E. O'Brien 4767481196SJohn Birrell #include "opt_init_path.h" 4840244964SRobert Watson #include "opt_mac.h" 494bd49128SPeter Wemm 50df8bae1dSRodney W. Grimes #include <sys/param.h> 519e209b12SAlfred Perlstein #include <sys/kernel.h> 52f36ba452SJake Burkholder #include <sys/exec.h> 53b3c5c18dSBruce Evans #include <sys/file.h> 54df8bae1dSRodney W. Grimes #include <sys/filedesc.h> 550384fff8SJason Evans #include <sys/ktr.h> 561005a129SJohn Baldwin #include <sys/lock.h> 5740244964SRobert Watson #include <sys/mac.h> 58ac0ad63fSBruce Evans #include <sys/mount.h> 5935e0e5b3SJohn Baldwin #include <sys/mutex.h> 608f19eb88SIan Dowse #include <sys/syscallsubr.h> 61946bb7a2SPoul-Henning Kamp #include <sys/sysctl.h> 62df8bae1dSRodney W. Grimes #include <sys/proc.h> 63df8bae1dSRodney W. Grimes #include <sys/resourcevar.h> 64df8bae1dSRodney W. Grimes #include <sys/systm.h> 6536240ea5SDoug Rabson #include <sys/signalvar.h> 66df8bae1dSRodney W. Grimes #include <sys/vnode.h> 67f3f0ca60SSøren Schmidt #include <sys/sysent.h> 68df8bae1dSRodney W. Grimes #include <sys/reboot.h> 69de028f5aSJeff Roberson #include <sys/sched.h> 701005a129SJohn Baldwin #include <sys/sx.h> 71ad7507e2SSteven Wallace #include <sys/sysproto.h> 72efeaf95aSDavid Greenman #include <sys/vmmeter.h> 7374b2192aSJohn Dyson #include <sys/unistd.h> 7494e9d7c1SPeter Wemm #include <sys/malloc.h> 75db901281SPoul-Henning Kamp #include <sys/conf.h> 76df8bae1dSRodney W. Grimes 77df8bae1dSRodney W. Grimes #include <machine/cpu.h> 78df8bae1dSRodney W. Grimes 79df8bae1dSRodney W. Grimes #include <vm/vm.h> 80efeaf95aSDavid Greenman #include <vm/vm_param.h> 81efeaf95aSDavid Greenman #include <vm/pmap.h> 82efeaf95aSDavid Greenman #include <vm/vm_map.h> 83efeaf95aSDavid Greenman #include <sys/user.h> 846faaa756SWolfram Schneider #include <sys/copyright.h> 85df8bae1dSRodney W. Grimes 8637b087a6SPeter Wemm void mi_startup(void); /* Should be elsewhere */ 87df8bae1dSRodney W. Grimes 88df8bae1dSRodney W. Grimes /* Components of the first process -- never freed. */ 89154c04e5SPoul-Henning Kamp static struct session session0; 90154c04e5SPoul-Henning Kamp static struct pgrp pgrp0; 91df8bae1dSRodney W. Grimes struct proc proc0; 92079b7badSJulian Elischer struct thread thread0; 934f0db5e0SJulian Elischer struct kse kse0; 944f0db5e0SJulian Elischer struct ksegrp ksegrp0; 95154c04e5SPoul-Henning Kamp static struct filedesc0 filedesc0; 9623734995SJake Burkholder struct vmspace vmspace0; 972b14f991SJulian Elischer struct proc *initproc; 98df8bae1dSRodney W. Grimes 992976b7f1SDavid Greenman struct vnode *rootvp; 100c463cf1cSBruce Evans int boothowto = 0; /* initialized so that it can be patched */ 1018d0bf3d6SJordan K. Hubbard SYSCTL_INT(_debug, OID_AUTO, boothowto, CTLFLAG_RD, &boothowto, 0, ""); 1027a08bae6SJohn Baldwin int bootverbose; 1037a08bae6SJohn Baldwin SYSCTL_INT(_debug, OID_AUTO, bootverbose, CTLFLAG_RW, &bootverbose, 0, ""); 104946bb7a2SPoul-Henning Kamp 1052b14f991SJulian Elischer /* 1062b14f991SJulian Elischer * This ensures that there is at least one entry so that the sysinit_set 1072b14f991SJulian Elischer * symbol is not undefined. A sybsystem ID of SI_SUB_DUMMY is never 1082b14f991SJulian Elischer * executed. 10926f9a767SRodney W. Grimes */ 1102b14f991SJulian Elischer SYSINIT(placeholder, SI_SUB_DUMMY, SI_ORDER_ANY, NULL, NULL) 1118a129caeSDavid Greenman 11294e9d7c1SPeter Wemm /* 11394e9d7c1SPeter Wemm * The sysinit table itself. Items are checked off as the are run. 11494e9d7c1SPeter Wemm * If we want to register new sysinit types, add them to newsysinit. 11594e9d7c1SPeter Wemm */ 116f41325dbSPeter Wemm SET_DECLARE(sysinit_set, struct sysinit); 117f41325dbSPeter Wemm struct sysinit **sysinit, **sysinit_end; 118f41325dbSPeter Wemm struct sysinit **newsysinit, **newsysinit_end; 11994e9d7c1SPeter Wemm 12094e9d7c1SPeter Wemm /* 12194e9d7c1SPeter Wemm * Merge a new sysinit set into the current set, reallocating it if 12294e9d7c1SPeter Wemm * necessary. This can only be called after malloc is running. 12394e9d7c1SPeter Wemm */ 12494e9d7c1SPeter Wemm void 125f41325dbSPeter Wemm sysinit_add(struct sysinit **set, struct sysinit **set_end) 12694e9d7c1SPeter Wemm { 12794e9d7c1SPeter Wemm struct sysinit **newset; 12894e9d7c1SPeter Wemm struct sysinit **sipp; 12994e9d7c1SPeter Wemm struct sysinit **xipp; 130f41325dbSPeter Wemm int count; 13194e9d7c1SPeter Wemm 132f41325dbSPeter Wemm count = set_end - set; 133ddd62546SPeter Wemm if (newsysinit) 134f41325dbSPeter Wemm count += newsysinit_end - newsysinit; 135ddd62546SPeter Wemm else 136f41325dbSPeter Wemm count += sysinit_end - sysinit; 13794e9d7c1SPeter Wemm newset = malloc(count * sizeof(*sipp), M_TEMP, M_NOWAIT); 13894e9d7c1SPeter Wemm if (newset == NULL) 13994e9d7c1SPeter Wemm panic("cannot malloc for sysinit"); 14094e9d7c1SPeter Wemm xipp = newset; 141ddd62546SPeter Wemm if (newsysinit) 142f41325dbSPeter Wemm for (sipp = newsysinit; sipp < newsysinit_end; sipp++) 143ddd62546SPeter Wemm *xipp++ = *sipp; 144ddd62546SPeter Wemm else 145f41325dbSPeter Wemm for (sipp = sysinit; sipp < sysinit_end; sipp++) 14694e9d7c1SPeter Wemm *xipp++ = *sipp; 147f41325dbSPeter Wemm for (sipp = set; sipp < set_end; sipp++) 14894e9d7c1SPeter Wemm *xipp++ = *sipp; 149ddd62546SPeter Wemm if (newsysinit) 150ddd62546SPeter Wemm free(newsysinit, M_TEMP); 15194e9d7c1SPeter Wemm newsysinit = newset; 152f41325dbSPeter Wemm newsysinit_end = newset + count; 15394e9d7c1SPeter Wemm } 15426f9a767SRodney W. Grimes 155df8bae1dSRodney W. Grimes /* 156df8bae1dSRodney W. Grimes * System startup; initialize the world, create process 0, mount root 157df8bae1dSRodney W. Grimes * filesystem, and fork to create init and pagedaemon. Most of the 158df8bae1dSRodney W. Grimes * hard work is done in the lower-level initialization routines including 159df8bae1dSRodney W. Grimes * startup(), which does memory initialization and autoconfiguration. 1602b14f991SJulian Elischer * 1612b14f991SJulian Elischer * This allows simple addition of new kernel subsystems that require 1622b14f991SJulian Elischer * boot time initialization. It also allows substitution of subsystem 1632b14f991SJulian Elischer * (for instance, a scheduler, kernel profiler, or VM system) by object 164c5b193bfSPoul-Henning Kamp * module. Finally, it allows for optional "kernel threads". 165df8bae1dSRodney W. Grimes */ 16626f9a767SRodney W. Grimes void 16737b087a6SPeter Wemm mi_startup(void) 168df8bae1dSRodney W. Grimes { 1692b14f991SJulian Elischer 1702b14f991SJulian Elischer register struct sysinit **sipp; /* system initialization*/ 1712b14f991SJulian Elischer register struct sysinit **xipp; /* interior loop of sort*/ 1722b14f991SJulian Elischer register struct sysinit *save; /* bubble*/ 1732b14f991SJulian Elischer 174f41325dbSPeter Wemm if (sysinit == NULL) { 175f41325dbSPeter Wemm sysinit = SET_BEGIN(sysinit_set); 176f41325dbSPeter Wemm sysinit_end = SET_LIMIT(sysinit_set); 177f41325dbSPeter Wemm } 178f41325dbSPeter Wemm 17994e9d7c1SPeter Wemm restart: 1802b14f991SJulian Elischer /* 1812b14f991SJulian Elischer * Perform a bubble sort of the system initialization objects by 1822b14f991SJulian Elischer * their subsystem (primary key) and order (secondary key). 1832b14f991SJulian Elischer */ 184f41325dbSPeter Wemm for (sipp = sysinit; sipp < sysinit_end; sipp++) { 185f41325dbSPeter Wemm for (xipp = sipp + 1; xipp < sysinit_end; xipp++) { 1862b14f991SJulian Elischer if ((*sipp)->subsystem < (*xipp)->subsystem || 1872b14f991SJulian Elischer ((*sipp)->subsystem == (*xipp)->subsystem && 188af4b2d2dSPeter Wemm (*sipp)->order <= (*xipp)->order)) 1892b14f991SJulian Elischer continue; /* skip*/ 1902b14f991SJulian Elischer save = *sipp; 1912b14f991SJulian Elischer *sipp = *xipp; 1922b14f991SJulian Elischer *xipp = save; 1932b14f991SJulian Elischer } 1942b14f991SJulian Elischer } 1952b14f991SJulian Elischer 1962b14f991SJulian Elischer /* 1972b14f991SJulian Elischer * Traverse the (now) ordered list of system initialization tasks. 1982b14f991SJulian Elischer * Perform each task, and continue on to the next task. 1992b14f991SJulian Elischer * 2002b14f991SJulian Elischer * The last item on the list is expected to be the scheduler, 2012b14f991SJulian Elischer * which will not return. 2022b14f991SJulian Elischer */ 203f41325dbSPeter Wemm for (sipp = sysinit; sipp < sysinit_end; sipp++) { 20474b2192aSJohn Dyson 2052b14f991SJulian Elischer if ((*sipp)->subsystem == SI_SUB_DUMMY) 2062b14f991SJulian Elischer continue; /* skip dummy task(s)*/ 2072b14f991SJulian Elischer 20894e9d7c1SPeter Wemm if ((*sipp)->subsystem == SI_SUB_DONE) 20994e9d7c1SPeter Wemm continue; 21094e9d7c1SPeter Wemm 2119c8b8baaSPeter Wemm /* Call function */ 2122b14f991SJulian Elischer (*((*sipp)->func))((*sipp)->udata); 21394e9d7c1SPeter Wemm 21494e9d7c1SPeter Wemm /* Check off the one we're just done */ 21594e9d7c1SPeter Wemm (*sipp)->subsystem = SI_SUB_DONE; 21694e9d7c1SPeter Wemm 21794e9d7c1SPeter Wemm /* Check if we've installed more sysinit items via KLD */ 21894e9d7c1SPeter Wemm if (newsysinit != NULL) { 219f41325dbSPeter Wemm if (sysinit != SET_BEGIN(sysinit_set)) 22094e9d7c1SPeter Wemm free(sysinit, M_TEMP); 22194e9d7c1SPeter Wemm sysinit = newsysinit; 222f41325dbSPeter Wemm sysinit_end = newsysinit_end; 22394e9d7c1SPeter Wemm newsysinit = NULL; 224f41325dbSPeter Wemm newsysinit_end = NULL; 22594e9d7c1SPeter Wemm goto restart; 22694e9d7c1SPeter Wemm } 2272b14f991SJulian Elischer } 2282b14f991SJulian Elischer 229477a642cSPeter Wemm panic("Shouldn't get here!"); 2302b14f991SJulian Elischer /* NOTREACHED*/ 2312b14f991SJulian Elischer } 2322b14f991SJulian Elischer 2332b14f991SJulian Elischer 2342b14f991SJulian Elischer /* 2352b14f991SJulian Elischer *************************************************************************** 2362b14f991SJulian Elischer **** 2372b14f991SJulian Elischer **** The following SYSINIT's belong elsewhere, but have not yet 2382b14f991SJulian Elischer **** been moved. 2392b14f991SJulian Elischer **** 2402b14f991SJulian Elischer *************************************************************************** 2412b14f991SJulian Elischer */ 2429ef6c28aSBruce Evans static void 24337b087a6SPeter Wemm print_caddr_t(void *data __unused) 2449ef6c28aSBruce Evans { 2459ef6c28aSBruce Evans printf("%s", (char *)data); 2469ef6c28aSBruce Evans } 247d841aaa7SBruce Evans SYSINIT(announce, SI_SUB_COPYRIGHT, SI_ORDER_FIRST, print_caddr_t, copyright) 2487a08bae6SJohn Baldwin SYSINIT(version, SI_SUB_COPYRIGHT, SI_ORDER_SECOND, print_caddr_t, version) 2497a08bae6SJohn Baldwin 2507a08bae6SJohn Baldwin static void 2517a08bae6SJohn Baldwin set_boot_verbose(void *data __unused) 2527a08bae6SJohn Baldwin { 2537a08bae6SJohn Baldwin 2547a08bae6SJohn Baldwin if (boothowto & RB_VERBOSE) 2557a08bae6SJohn Baldwin bootverbose++; 2567a08bae6SJohn Baldwin } 2577a08bae6SJohn Baldwin SYSINIT(boot_verbose, SI_SUB_TUNABLES, SI_ORDER_ANY, set_boot_verbose, NULL) 2582b14f991SJulian Elischer 259f36ba452SJake Burkholder struct sysentvec null_sysvec = { 260f36ba452SJake Burkholder 0, 261f36ba452SJake Burkholder NULL, 262f36ba452SJake Burkholder 0, 263f36ba452SJake Burkholder 0, 264f36ba452SJake Burkholder NULL, 265f36ba452SJake Burkholder 0, 266f36ba452SJake Burkholder NULL, 267f36ba452SJake Burkholder NULL, 268f36ba452SJake Burkholder NULL, 269f36ba452SJake Burkholder NULL, 270f36ba452SJake Burkholder NULL, 271f36ba452SJake Burkholder NULL, 272f36ba452SJake Burkholder NULL, 273f36ba452SJake Burkholder "null", 274f36ba452SJake Burkholder NULL, 275f36ba452SJake Burkholder NULL, 276f36ba452SJake Burkholder 0, 277f36ba452SJake Burkholder PAGE_SIZE, 278f36ba452SJake Burkholder VM_MIN_ADDRESS, 279f36ba452SJake Burkholder VM_MAXUSER_ADDRESS, 280f36ba452SJake Burkholder USRSTACK, 281f36ba452SJake Burkholder PS_STRINGS, 282f36ba452SJake Burkholder VM_PROT_ALL, 283f36ba452SJake Burkholder NULL, 284c460ac3aSPeter Wemm NULL, 285f36ba452SJake Burkholder NULL 286f36ba452SJake Burkholder }; 2873ebc1248SPeter Wemm 2882b14f991SJulian Elischer /* 2892b14f991SJulian Elischer *************************************************************************** 2902b14f991SJulian Elischer **** 2910c920c0dSGiorgos Keramidas **** The two following SYSINIT's are proc0 specific glue code. I am not 2922b14f991SJulian Elischer **** convinced that they can not be safely combined, but their order of 2932b14f991SJulian Elischer **** operation has been maintained as the same as the original init_main.c 2942b14f991SJulian Elischer **** for right now. 2952b14f991SJulian Elischer **** 2962b14f991SJulian Elischer **** These probably belong in init_proc.c or kern_proc.c, since they 2972b14f991SJulian Elischer **** deal with proc0 (the fork template process). 2982b14f991SJulian Elischer **** 2992b14f991SJulian Elischer *************************************************************************** 3002b14f991SJulian Elischer */ 3012b14f991SJulian Elischer /* ARGSUSED*/ 302154c04e5SPoul-Henning Kamp static void 30337b087a6SPeter Wemm proc0_init(void *dummy __unused) 3042b14f991SJulian Elischer { 305df8bae1dSRodney W. Grimes register struct proc *p; 306df8bae1dSRodney W. Grimes register struct filedesc0 *fdp; 30792579404SAlexander Langer register unsigned i; 308b40ce416SJulian Elischer struct thread *td; 309079b7badSJulian Elischer struct ksegrp *kg; 310079b7badSJulian Elischer struct kse *ke; 311df8bae1dSRodney W. Grimes 3120cddd8f0SMatthew Dillon GIANT_REQUIRED; 313df8bae1dSRodney W. Grimes p = &proc0; 314079b7badSJulian Elischer td = &thread0; 3154f0db5e0SJulian Elischer ke = &kse0; 3164f0db5e0SJulian Elischer kg = &ksegrp0; 317df8bae1dSRodney W. Grimes 318de028f5aSJeff Roberson ke->ke_sched = kse0_sched; 319de028f5aSJeff Roberson kg->kg_sched = ksegrp0_sched; 320de028f5aSJeff Roberson p->p_sched = proc0_sched; 321de028f5aSJeff Roberson td->td_sched = thread0_sched; 322de028f5aSJeff Roberson 323df8bae1dSRodney W. Grimes /* 3240384fff8SJason Evans * Initialize magic number. 3250384fff8SJason Evans */ 3260384fff8SJason Evans p->p_magic = P_MAGIC; 3270384fff8SJason Evans 3280384fff8SJason Evans /* 329079b7badSJulian Elischer * Initialize thread, process and pgrp structures. 330a3bfb996SJeffrey Hsu */ 331a3bfb996SJeffrey Hsu procinit(); 332e602ba25SJulian Elischer threadinit(); 333a3bfb996SJeffrey Hsu 334a3bfb996SJeffrey Hsu /* 335b1508c72SDavid Greenman * Initialize sleep queue hash table 336b1508c72SDavid Greenman */ 337b1508c72SDavid Greenman sleepinit(); 338b1508c72SDavid Greenman 339b1508c72SDavid Greenman /* 3403075778bSJohn Dyson * additional VM structures 3413075778bSJohn Dyson */ 3423075778bSJohn Dyson vm_init2(); 3433075778bSJohn Dyson 3443075778bSJohn Dyson /* 345df8bae1dSRodney W. Grimes * Create process 0 (the swapper). 346df8bae1dSRodney W. Grimes */ 347a3bfb996SJeffrey Hsu LIST_INSERT_HEAD(&allproc, p, p_list); 3487b531e60SJohn Baldwin LIST_INSERT_HEAD(PIDHASH(0), p, p_hash); 3496008862bSJohn Baldwin mtx_init(&pgrp0.pg_mtx, "process group", NULL, MTX_DEF | MTX_DUPOK); 350df8bae1dSRodney W. Grimes p->p_pgrp = &pgrp0; 351a3bfb996SJeffrey Hsu LIST_INSERT_HEAD(PGRPHASH(0), &pgrp0, pg_hash); 352a3bfb996SJeffrey Hsu LIST_INIT(&pgrp0.pg_members); 353a3bfb996SJeffrey Hsu LIST_INSERT_HEAD(&pgrp0.pg_members, p, p_pglist); 354a3bfb996SJeffrey Hsu 355df8bae1dSRodney W. Grimes pgrp0.pg_session = &session0; 3566008862bSJohn Baldwin mtx_init(&session0.s_mtx, "session", NULL, MTX_DEF); 357df8bae1dSRodney W. Grimes session0.s_count = 1; 358df8bae1dSRodney W. Grimes session0.s_leader = p; 359df8bae1dSRodney W. Grimes 3603ebc1248SPeter Wemm p->p_sysent = &null_sysvec; 361f3f0ca60SSøren Schmidt 362e602ba25SJulian Elischer /* 363e602ba25SJulian Elischer * proc_linkup was already done in init_i386() or alphainit() etc. 364e602ba25SJulian Elischer * because the earlier code needed to follow td->td_proc. Otherwise 365e602ba25SJulian Elischer * I would have done it here.. maybe this means this should be 366e602ba25SJulian Elischer * done earlier too. 367e602ba25SJulian Elischer */ 368f202965eSJohn Baldwin p->p_flag = P_SYSTEM; 369f202965eSJohn Baldwin p->p_sflag = PS_INMEM; 370e602ba25SJulian Elischer p->p_state = PRS_NORMAL; 371e602ba25SJulian Elischer td->td_state = TDS_RUNNING; 372e602ba25SJulian Elischer kg->kg_nice = NZERO; 3732c100766SJulian Elischer kg->kg_pri_class = PRI_TIMESHARE; 3742c100766SJulian Elischer kg->kg_user_pri = PUSER; 3752c100766SJulian Elischer td->td_priority = PVM; 3762c100766SJulian Elischer td->td_base_pri = PUSER; 377e602ba25SJulian Elischer td->td_kse = ke; /* XXXKSE */ 378060563ecSJulian Elischer td->td_oncpu = 0; 379c3b98db0SJulian Elischer ke->ke_state = KES_THREAD; 380e602ba25SJulian Elischer ke->ke_thread = td; 3812c1011f7SJohn Dyson p->p_peers = 0; 3822c1011f7SJohn Dyson p->p_leader = p; 383e602ba25SJulian Elischer 3842c1011f7SJohn Dyson 385df8bae1dSRodney W. Grimes bcopy("swapper", p->p_comm, sizeof ("swapper")); 386df8bae1dSRodney W. Grimes 387c06eb4e2SSam Leffler callout_init(&p->p_itcallout, CALLOUT_MPSAFE); 388c06eb4e2SSam Leffler callout_init(&td->td_slpcallout, CALLOUT_MPSAFE); 3894f559836SJake Burkholder 390df8bae1dSRodney W. Grimes /* Create credentials. */ 391df8bae1dSRodney W. Grimes p->p_ucred = crget(); 392df8bae1dSRodney W. Grimes p->p_ucred->cr_ngroups = 1; /* group 0 */ 393f535380cSDon Lewis p->p_ucred->cr_uidinfo = uifind(0); 394b1fc0ec1SRobert Watson p->p_ucred->cr_ruidinfo = uifind(0); 39591421ba2SRobert Watson p->p_ucred->cr_prison = NULL; /* Don't jail it. */ 39640244964SRobert Watson #ifdef MAC 39740244964SRobert Watson mac_create_proc0(p->p_ucred); 39840244964SRobert Watson #endif 3998e2e767bSJohn Baldwin td->td_ucred = crhold(p->p_ucred); 40075c13541SPoul-Henning Kamp 40190af4afaSJohn Baldwin /* Create sigacts. */ 40290af4afaSJohn Baldwin p->p_sigacts = sigacts_alloc(); 4036626c604SJulian Elischer 40437b087a6SPeter Wemm /* Initialize signal state for process 0. */ 40537b087a6SPeter Wemm siginit(&proc0); 40637b087a6SPeter Wemm 407df8bae1dSRodney W. Grimes /* Create the file descriptor table. */ 408a2fe44e8SDag-Erling Smørgrav /* XXX this duplicates part of fdinit() */ 409df8bae1dSRodney W. Grimes fdp = &filedesc0; 410df8bae1dSRodney W. Grimes p->p_fd = &fdp->fd_fd; 411ad05d580STor Egge p->p_fdtol = NULL; 4126008862bSJohn Baldwin mtx_init(&fdp->fd_fd.fd_mtx, FILEDESC_LOCK_DESC, NULL, MTX_DEF); 413df8bae1dSRodney W. Grimes fdp->fd_fd.fd_refcnt = 1; 414c142b0fcSRobert Watson fdp->fd_fd.fd_cmask = CMASK; 415df8bae1dSRodney W. Grimes fdp->fd_fd.fd_ofiles = fdp->fd_dfiles; 416df8bae1dSRodney W. Grimes fdp->fd_fd.fd_ofileflags = fdp->fd_dfileflags; 417df8bae1dSRodney W. Grimes fdp->fd_fd.fd_nfiles = NDFILE; 418a2fe44e8SDag-Erling Smørgrav fdp->fd_fd.fd_map = fdp->fd_dmap; 419df8bae1dSRodney W. Grimes 420df8bae1dSRodney W. Grimes /* Create the limits structures. */ 42191d5354aSJohn Baldwin p->p_limit = lim_alloc(); 42291d5354aSJohn Baldwin for (i = 0; i < RLIM_NLIMITS; i++) 42391d5354aSJohn Baldwin p->p_limit->pl_rlimit[i].rlim_cur = 42491d5354aSJohn Baldwin p->p_limit->pl_rlimit[i].rlim_max = RLIM_INFINITY; 42591d5354aSJohn Baldwin p->p_limit->pl_rlimit[RLIMIT_NOFILE].rlim_cur = 42691d5354aSJohn Baldwin p->p_limit->pl_rlimit[RLIMIT_NOFILE].rlim_max = maxfiles; 42791d5354aSJohn Baldwin p->p_limit->pl_rlimit[RLIMIT_NPROC].rlim_cur = 42891d5354aSJohn Baldwin p->p_limit->pl_rlimit[RLIMIT_NPROC].rlim_max = maxproc; 429df8bae1dSRodney W. Grimes i = ptoa(cnt.v_free_count); 43091d5354aSJohn Baldwin p->p_limit->pl_rlimit[RLIMIT_RSS].rlim_max = i; 43191d5354aSJohn Baldwin p->p_limit->pl_rlimit[RLIMIT_MEMLOCK].rlim_max = i; 43291d5354aSJohn Baldwin p->p_limit->pl_rlimit[RLIMIT_MEMLOCK].rlim_cur = i / 3; 4335715307fSJohn Baldwin p->p_cpulimit = RLIM_INFINITY; 434df8bae1dSRodney W. Grimes 435df8bae1dSRodney W. Grimes /* Allocate a prototype map so we have something to fork. */ 436b1028ad1SLuoqi Chen pmap_pinit0(vmspace_pmap(&vmspace0)); 437df8bae1dSRodney W. Grimes p->p_vmspace = &vmspace0; 438df8bae1dSRodney W. Grimes vmspace0.vm_refcnt = 1; 43905ba50f5SJake Burkholder vm_map_init(&vmspace0.vm_map, p->p_sysent->sv_minuser, 44005ba50f5SJake Burkholder p->p_sysent->sv_maxuser); 441b1028ad1SLuoqi Chen vmspace0.vm_map.pmap = vmspace_pmap(&vmspace0); 442df8bae1dSRodney W. Grimes 44339fb8e6bSJulian Elischer /* 44490af4afaSJohn Baldwin * We continue to place resource usage info 44590af4afaSJohn Baldwin * in the user struct so that it's pageable. 446df8bae1dSRodney W. Grimes */ 447b40ce416SJulian Elischer p->p_stats = &p->p_uarea->u_stats; 448df8bae1dSRodney W. Grimes 449df8bae1dSRodney W. Grimes /* 450a3bfb996SJeffrey Hsu * Charge root for one process. 451df8bae1dSRodney W. Grimes */ 452b1fc0ec1SRobert Watson (void)chgproccnt(p->p_ucred->cr_ruidinfo, 1, 0); 45326f9a767SRodney W. Grimes } 4542b14f991SJulian Elischer SYSINIT(p0init, SI_SUB_INTRINSIC, SI_ORDER_FIRST, proc0_init, NULL) 4552b14f991SJulian Elischer 4562b14f991SJulian Elischer /* ARGSUSED*/ 457154c04e5SPoul-Henning Kamp static void 45837b087a6SPeter Wemm proc0_post(void *dummy __unused) 4592b14f991SJulian Elischer { 46000af9731SPoul-Henning Kamp struct timespec ts; 46137b087a6SPeter Wemm struct proc *p; 462a6fc8288SPeter Wemm 4632b14f991SJulian Elischer /* 4641b0b259eSBruce Evans * Now we can look at the time, having had a chance to verify the 4651b0b259eSBruce Evans * time from the filesystem. Pretend that proc0 started now. 4662b14f991SJulian Elischer */ 4671005a129SJohn Baldwin sx_slock(&allproc_lock); 46837b087a6SPeter Wemm LIST_FOREACH(p, &allproc, p_list) { 46987ccef7bSDag-Erling Smørgrav microuptime(&p->p_stats->p_start); 4701cbb9c3bSPoul-Henning Kamp p->p_runtime.sec = 0; 4711cbb9c3bSPoul-Henning Kamp p->p_runtime.frac = 0; 47237b087a6SPeter Wemm } 4731005a129SJohn Baldwin sx_sunlock(&allproc_lock); 474e2256f43SPeter Wemm binuptime(PCPU_PTR(switchtime)); 4750384fff8SJason Evans PCPU_SET(switchticks, ticks); 4762b14f991SJulian Elischer 477a6fc8288SPeter Wemm /* 478a6fc8288SPeter Wemm * Give the ``random'' number generator a thump. 479a6fc8288SPeter Wemm */ 48000af9731SPoul-Henning Kamp nanotime(&ts); 48100af9731SPoul-Henning Kamp srandom(ts.tv_sec ^ ts.tv_nsec); 4822b14f991SJulian Elischer } 4832b14f991SJulian Elischer SYSINIT(p0post, SI_SUB_INTRINSIC_POST, SI_ORDER_FIRST, proc0_post, NULL) 4842b14f991SJulian Elischer 485df8bae1dSRodney W. Grimes /* 4862b14f991SJulian Elischer *************************************************************************** 4872b14f991SJulian Elischer **** 4882b14f991SJulian Elischer **** The following SYSINIT's and glue code should be moved to the 4892b14f991SJulian Elischer **** respective files on a per subsystem basis. 4902b14f991SJulian Elischer **** 4912b14f991SJulian Elischer *************************************************************************** 492df8bae1dSRodney W. Grimes */ 493df8bae1dSRodney W. Grimes 494df8bae1dSRodney W. Grimes 495df8bae1dSRodney W. Grimes /* 4962b14f991SJulian Elischer *************************************************************************** 4972b14f991SJulian Elischer **** 4982b14f991SJulian Elischer **** The following code probably belongs in another file, like 49937b087a6SPeter Wemm **** kern/init_init.c. 5002b14f991SJulian Elischer **** 5012b14f991SJulian Elischer *************************************************************************** 502df8bae1dSRodney W. Grimes */ 503df8bae1dSRodney W. Grimes 504df8bae1dSRodney W. Grimes /* 505df8bae1dSRodney W. Grimes * List of paths to try when searching for "init". 506df8bae1dSRodney W. Grimes */ 5075f967b24SDag-Erling Smørgrav static char init_path[MAXPATHLEN] = 50867481196SJohn Birrell #ifdef INIT_PATH 50967481196SJohn Birrell __XSTRING(INIT_PATH); 51067481196SJohn Birrell #else 511e4082284SJohn Birrell "/sbin/init:/sbin/oinit:/sbin/init.bak:/stand/sysinstall"; 51267481196SJohn Birrell #endif 513af1408e3SLuigi Rizzo SYSCTL_STRING(_kern, OID_AUTO, init_path, CTLFLAG_RD, init_path, 0, 514af1408e3SLuigi Rizzo "Path used to search the init process"); 515df8bae1dSRodney W. Grimes 516df8bae1dSRodney W. Grimes /* 5175f967b24SDag-Erling Smørgrav * Start the initial user process; try exec'ing each pathname in init_path. 518df8bae1dSRodney W. Grimes * The program is invoked with one argument containing the boot flags. 519df8bae1dSRodney W. Grimes */ 520df8bae1dSRodney W. Grimes static void 52137b087a6SPeter Wemm start_init(void *dummy) 522df8bae1dSRodney W. Grimes { 523df8bae1dSRodney W. Grimes vm_offset_t addr; 524df8bae1dSRodney W. Grimes struct execve_args args; 5255f967b24SDag-Erling Smørgrav int options, error; 5265f967b24SDag-Erling Smørgrav char *var, *path, *next, *s; 5275f967b24SDag-Erling Smørgrav char *ucp, **uap, *arg0, *arg1; 528b40ce416SJulian Elischer struct thread *td; 5299c8b8baaSPeter Wemm struct proc *p; 530b7116168SPeter Wemm int init_does_devfs = 0; 531df8bae1dSRodney W. Grimes 5329ed346baSBosko Milekic mtx_lock(&Giant); 5330384fff8SJason Evans 5340cddd8f0SMatthew Dillon GIANT_REQUIRED; 5350cddd8f0SMatthew Dillon 536b40ce416SJulian Elischer td = curthread; 537b40ce416SJulian Elischer p = td->td_proc; 538df8bae1dSRodney W. Grimes 539563af2ecSMaxime Henrion vfs_mountroot(); 540fb92273bSPoul-Henning Kamp 54137b087a6SPeter Wemm /* Get the vnode for '/'. Set p->p_fd->fd_cdir to reference it. */ 54237b087a6SPeter Wemm if (VFS_ROOT(TAILQ_FIRST(&mountlist), &rootvnode)) 54337b087a6SPeter Wemm panic("cannot find root vnode"); 544426da3bcSAlfred Perlstein FILEDESC_LOCK(p->p_fd); 54537b087a6SPeter Wemm p->p_fd->fd_cdir = rootvnode; 54637b087a6SPeter Wemm VREF(p->p_fd->fd_cdir); 54737b087a6SPeter Wemm p->p_fd->fd_rdir = rootvnode; 548a90ef2aeSIan Dowse VREF(p->p_fd->fd_rdir); 549426da3bcSAlfred Perlstein FILEDESC_UNLOCK(p->p_fd); 550b40ce416SJulian Elischer VOP_UNLOCK(rootvnode, 0, td); 551a87cdf83SRobert Watson #ifdef MAC 552a87cdf83SRobert Watson mac_create_root_mount(td->td_ucred, TAILQ_FIRST(&mountlist)); 553a87cdf83SRobert Watson #endif 55437b087a6SPeter Wemm 555b7116168SPeter Wemm /* 556b7116168SPeter Wemm * For disk based systems, we probably cannot do this yet 557b7116168SPeter Wemm * since the fs will be read-only. But a NFS root 558b7116168SPeter Wemm * might be ok. It is worth a shot. 559b7116168SPeter Wemm */ 5608f19eb88SIan Dowse error = kern_mkdir(td, "/dev", UIO_SYSSPACE, 0700); 561b7116168SPeter Wemm if (error == EEXIST) 562b7116168SPeter Wemm error = 0; 563b7116168SPeter Wemm if (error == 0) 5646dbde1feSMaxime Henrion error = kernel_vmount(0, "fstype", "devfs", 5656dbde1feSMaxime Henrion "fspath", "/dev", NULL); 566b7116168SPeter Wemm if (error != 0) 567b7116168SPeter Wemm init_does_devfs = 1; 568b7116168SPeter Wemm 569df8bae1dSRodney W. Grimes /* 570df8bae1dSRodney W. Grimes * Need just enough stack to hold the faked-up "execve()" arguments. 571df8bae1dSRodney W. Grimes */ 57205ba50f5SJake Burkholder addr = p->p_sysent->sv_usrstack - PAGE_SIZE; 5735f967b24SDag-Erling Smørgrav if (vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &addr, PAGE_SIZE, 5745f967b24SDag-Erling Smørgrav FALSE, VM_PROT_ALL, VM_PROT_ALL, 0) != 0) 575df8bae1dSRodney W. Grimes panic("init: couldn't allocate argument space"); 576df8bae1dSRodney W. Grimes p->p_vmspace->vm_maxsaddr = (caddr_t)addr; 57726f9a767SRodney W. Grimes p->p_vmspace->vm_ssize = 1; 578df8bae1dSRodney W. Grimes 5795f967b24SDag-Erling Smørgrav if ((var = getenv("init_path")) != NULL) { 580e80fb434SRobert Drehmel strlcpy(init_path, var, sizeof(init_path)); 581d786139cSMaxime Henrion freeenv(var); 5825f967b24SDag-Erling Smørgrav } 5835f967b24SDag-Erling Smørgrav 58467481196SJohn Birrell for (path = init_path; *path != '\0'; path = next) { 585e4082284SJohn Birrell while (*path == ':') 5865f967b24SDag-Erling Smørgrav path++; 58767481196SJohn Birrell if (*path == '\0') 5885f967b24SDag-Erling Smørgrav break; 589e4082284SJohn Birrell for (next = path; *next != '\0' && *next != ':'; next++) 5905f967b24SDag-Erling Smørgrav /* nothing */ ; 5915f967b24SDag-Erling Smørgrav if (bootverbose) 592ba41a07dSDmitrij Tejblum printf("start_init: trying %.*s\n", (int)(next - path), 593ba41a07dSDmitrij Tejblum path); 5945f967b24SDag-Erling Smørgrav 595df8bae1dSRodney W. Grimes /* 596df8bae1dSRodney W. Grimes * Move out the boot flag argument. 597df8bae1dSRodney W. Grimes */ 598df8bae1dSRodney W. Grimes options = 0; 59905ba50f5SJake Burkholder ucp = (char *)p->p_sysent->sv_usrstack; 600df8bae1dSRodney W. Grimes (void)subyte(--ucp, 0); /* trailing zero */ 601df8bae1dSRodney W. Grimes if (boothowto & RB_SINGLE) { 602df8bae1dSRodney W. Grimes (void)subyte(--ucp, 's'); 603df8bae1dSRodney W. Grimes options = 1; 604df8bae1dSRodney W. Grimes } 605df8bae1dSRodney W. Grimes #ifdef notyet 606df8bae1dSRodney W. Grimes if (boothowto & RB_FASTBOOT) { 607df8bae1dSRodney W. Grimes (void)subyte(--ucp, 'f'); 608df8bae1dSRodney W. Grimes options = 1; 609df8bae1dSRodney W. Grimes } 610df8bae1dSRodney W. Grimes #endif 61117755ac8SPoul-Henning Kamp 61217755ac8SPoul-Henning Kamp #ifdef BOOTCDROM 61317755ac8SPoul-Henning Kamp (void)subyte(--ucp, 'C'); 61417755ac8SPoul-Henning Kamp options = 1; 61517755ac8SPoul-Henning Kamp #endif 616b7116168SPeter Wemm if (init_does_devfs) { 6173f54a085SPoul-Henning Kamp (void)subyte(--ucp, 'd'); 6183f54a085SPoul-Henning Kamp options = 1; 619db901281SPoul-Henning Kamp } 620db901281SPoul-Henning Kamp 621df8bae1dSRodney W. Grimes if (options == 0) 622df8bae1dSRodney W. Grimes (void)subyte(--ucp, '-'); 623df8bae1dSRodney W. Grimes (void)subyte(--ucp, '-'); /* leading hyphen */ 624df8bae1dSRodney W. Grimes arg1 = ucp; 625df8bae1dSRodney W. Grimes 626df8bae1dSRodney W. Grimes /* 627df8bae1dSRodney W. Grimes * Move out the file name (also arg 0). 628df8bae1dSRodney W. Grimes */ 6295f967b24SDag-Erling Smørgrav (void)subyte(--ucp, 0); 6305f967b24SDag-Erling Smørgrav for (s = next - 1; s >= path; s--) 6315f967b24SDag-Erling Smørgrav (void)subyte(--ucp, *s); 632df8bae1dSRodney W. Grimes arg0 = ucp; 633df8bae1dSRodney W. Grimes 634df8bae1dSRodney W. Grimes /* 635df8bae1dSRodney W. Grimes * Move out the arg pointers. 636df8bae1dSRodney W. Grimes */ 637a20d7755SDoug Rabson uap = (char **)((intptr_t)ucp & ~(sizeof(intptr_t)-1)); 638c2da0fd9SBruce Evans (void)suword((caddr_t)--uap, (long)0); /* terminator */ 639c2da0fd9SBruce Evans (void)suword((caddr_t)--uap, (long)(intptr_t)arg1); 640c2da0fd9SBruce Evans (void)suword((caddr_t)--uap, (long)(intptr_t)arg0); 641df8bae1dSRodney W. Grimes 642df8bae1dSRodney W. Grimes /* 643df8bae1dSRodney W. Grimes * Point at the arguments. 644df8bae1dSRodney W. Grimes */ 645df8bae1dSRodney W. Grimes args.fname = arg0; 64626f9a767SRodney W. Grimes args.argv = uap; 64726f9a767SRodney W. Grimes args.envv = NULL; 648df8bae1dSRodney W. Grimes 649df8bae1dSRodney W. Grimes /* 650df8bae1dSRodney W. Grimes * Now try to exec the program. If can't for any reason 651df8bae1dSRodney W. Grimes * other than it doesn't exist, complain. 6522b14f991SJulian Elischer * 65337b087a6SPeter Wemm * Otherwise, return via fork_trampoline() all the way 6549c8b8baaSPeter Wemm * to user mode as init! 655df8bae1dSRodney W. Grimes */ 656b40ce416SJulian Elischer if ((error = execve(td, &args)) == 0) { 6579ed346baSBosko Milekic mtx_unlock(&Giant); 658df8bae1dSRodney W. Grimes return; 659db72809dSJohn Baldwin } 660df8bae1dSRodney W. Grimes if (error != ENOENT) 661ba41a07dSDmitrij Tejblum printf("exec %.*s: error %d\n", (int)(next - path), 662ba41a07dSDmitrij Tejblum path, error); 663df8bae1dSRodney W. Grimes } 664580e7e5aSGreg Lehey printf("init: not found in path %s\n", init_path); 665df8bae1dSRodney W. Grimes panic("no init"); 666df8bae1dSRodney W. Grimes } 66737b087a6SPeter Wemm 66837b087a6SPeter Wemm /* 66937b087a6SPeter Wemm * Like kthread_create(), but runs in it's own address space. 67037b087a6SPeter Wemm * We do this early to reserve pid 1. 67137b087a6SPeter Wemm * 67237b087a6SPeter Wemm * Note special case - do not make it runnable yet. Other work 67337b087a6SPeter Wemm * in progress will change this more. 67437b087a6SPeter Wemm */ 67537b087a6SPeter Wemm static void 67637b087a6SPeter Wemm create_init(const void *udata __unused) 67737b087a6SPeter Wemm { 6785a06cb0cSRobert Watson struct ucred *newcred, *oldcred; 67937b087a6SPeter Wemm int error; 68037b087a6SPeter Wemm 681316ec49aSScott Long error = fork1(&thread0, RFFDG | RFPROC | RFSTOPPED, 0, &initproc); 68237b087a6SPeter Wemm if (error) 68337b087a6SPeter Wemm panic("cannot fork init: %d\n", error); 684bafc8f25SRobert Watson KASSERT(initproc->p_pid == 1, ("create_init: initproc->p_pid != 1")); 6855a06cb0cSRobert Watson /* divorce init's credentials from the kernel's */ 6865a06cb0cSRobert Watson newcred = crget(); 687f202965eSJohn Baldwin PROC_LOCK(initproc); 688f202965eSJohn Baldwin initproc->p_flag |= P_SYSTEM; 6895a06cb0cSRobert Watson oldcred = initproc->p_ucred; 6905a06cb0cSRobert Watson crcopy(newcred, oldcred); 69140244964SRobert Watson #ifdef MAC 69240244964SRobert Watson mac_create_proc1(newcred); 69340244964SRobert Watson #endif 6945a06cb0cSRobert Watson initproc->p_ucred = newcred; 695f202965eSJohn Baldwin PROC_UNLOCK(initproc); 6965a06cb0cSRobert Watson crfree(oldcred); 6974d1a4bb7SRobert Watson cred_update_thread(FIRST_THREAD_IN_PROC(initproc)); 6989ed346baSBosko Milekic mtx_lock_spin(&sched_lock); 699f202965eSJohn Baldwin initproc->p_sflag |= PS_INMEM; 7009ed346baSBosko Milekic mtx_unlock_spin(&sched_lock); 701079b7badSJulian Elischer cpu_set_fork_handler(FIRST_THREAD_IN_PROC(initproc), start_init, NULL); 70237b087a6SPeter Wemm } 70337b087a6SPeter Wemm SYSINIT(init, SI_SUB_CREATE_INIT, SI_ORDER_FIRST, create_init, NULL) 70437b087a6SPeter Wemm 70537b087a6SPeter Wemm /* 70637b087a6SPeter Wemm * Make it runnable now. 70737b087a6SPeter Wemm */ 70837b087a6SPeter Wemm static void 70937b087a6SPeter Wemm kick_init(const void *udata __unused) 71037b087a6SPeter Wemm { 711079b7badSJulian Elischer struct thread *td; 712f202965eSJohn Baldwin 713079b7badSJulian Elischer td = FIRST_THREAD_IN_PROC(initproc); 7149ed346baSBosko Milekic mtx_lock_spin(&sched_lock); 71571fad9fdSJulian Elischer TD_SET_CAN_RUN(td); 716e602ba25SJulian Elischer setrunqueue(td); /* XXXKSE */ 7179ed346baSBosko Milekic mtx_unlock_spin(&sched_lock); 71837b087a6SPeter Wemm } 71937b087a6SPeter Wemm SYSINIT(kickinit, SI_SUB_KTHREAD_INIT, SI_ORDER_FIRST, kick_init, NULL) 720