2 * Copyright (c) 2003 Galen Sampson <galen_sampson@yahoo.com>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * $DragonFly: src/lib/libcaps/uthread.c,v 1.1 2003/12/04 22:06:19 dillon Exp $
30 * Each cpu in a system has its own self-contained light weight kernel
31 * thread scheduler, which means that generally speaking we only need
32 * to use a critical section to avoid problems. Foreign thread
33 * scheduling is queued via (async) IPIs.
35 * NOTE: on UP machines smp_active is defined to be 0. On SMP machines
36 * smp_active is 0 prior to SMP activation, then it is 1. The LWKT module
37 * uses smp_active to optimize UP builds and to avoid sending IPIs during
38 * early boot (primarily interrupt and network thread initialization).
43 void cpu_lwkt_switch(thread_t);
46 * system message port for the system call interface
51 lwkt_idleloop(void *dummy)
55 * if the idle thread and the main thread are the only remaining
56 * threads then switch to single threaded mode. Accomplish this
57 * by switching to the main thread. XXX
59 globaldata_t gd = mycpu;
60 if (gd->gd_num_threads == 0) { /* XXX not working yet */
61 lwkt_schedule(&main_td);
68 * Userland override of lwkt_init_thread. The only difference is
69 * the manipulation of gd->gd_num_threads;
72 lwkt_init_thread_remote(void *arg)
76 TAILQ_INSERT_TAIL(&td->td_gd->gd_tdallq, td, td_allq);
80 lwkt_init_thread(thread_t td, void *stack, int flags, struct globaldata *gd)
82 bzero(td, sizeof(struct thread));
83 td->td_kstack = stack;
84 td->td_flags |= flags;
86 td->td_pri = TDPRI_KERN_DAEMON + TDPRI_CRIT;
87 lwkt_initport(&td->td_msgport, td);
89 if (smp_active == 0 || gd == mycpu) {
91 TAILQ_INSERT_TAIL(&gd->gd_tdallq, td, td_allq);
92 gd->gd_num_threads++; /* Userland specific */
95 lwkt_send_ipiq(gd->gd_cpuid, lwkt_init_thread_remote, td);
100 * Userland override of lwkt_exit. The only difference is
101 * the manipulation of gd->gd_num_threads;
106 thread_t td = curthread;
108 if (td->td_flags & TDF_VERBOSE)
109 printf("kthread %p %s has exited\n", td, td->td_comm);
111 lwkt_deschedule_self();
112 ++mycpu->gd_tdfreecount;
113 --mycpu->gd_num_threads; /* Userland specific */
114 TAILQ_INSERT_TAIL(&mycpu->gd_tdfreeq, td, td_threadq);
119 * Userland override of lwkt_gdinit. Called from mi_gdinit().
122 lwkt_gdinit(struct globaldata *gd)
124 /* Kernel Version of lwkt_gdinit() */
127 for (i = 0; i < sizeof(gd->gd_tdrunq)/sizeof(gd->gd_tdrunq[0]); ++i)
128 TAILQ_INIT(&gd->gd_tdrunq[i]);
130 gd->gd_curthread = &gd->gd_idlethread;
131 TAILQ_INIT(&gd->gd_tdallq);
133 /* Set up this cpu's idle thread */
134 lwkt_init_thread(&gd->gd_idlethread, libcaps_alloc_stack(THREAD_STACK), 0, gd);
135 cpu_set_thread_handler(&gd->gd_idlethread, lwkt_exit, lwkt_idleloop, NULL);
138 * lwkt_init_thread added threads to gd->gd_tdallq and incrementented
139 * gd->gd_num_threads accordingly. Reset the count to zero here.
140 * The reason gd_num_threads exists is so a check can be performed
141 * to see if there are any non bookkeeping threads running on this
142 * virtual cpu. We have created some threads for bookkeeping here that
143 * shouldn't be counted. Resetting the count to 0 allows the test
144 * if(mycpu->gd_num_threads == 0) to correctly test if there are any
145 * non-bookeeping threads running on this virtual cpu.
147 gd->gd_num_threads = 0;
154 lwkt_start_threading(thread_t td)