scheduler.c revision 1.2 1 /* $NetBSD: scheduler.c,v 1.2 2009/10/15 16:39:22 pooka Exp $ */
2
3 /*
4 * Copyright (c) 2009 Antti Kantee. All Rights Reserved.
5 *
6 * Development of this software was supported by
7 * The Finnish Cultural Foundation.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
19 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31 #include <sys/cdefs.h>
32 __KERNEL_RCSID(0, "$NetBSD: scheduler.c,v 1.2 2009/10/15 16:39:22 pooka Exp $");
33
34 #include <sys/param.h>
35 #include <sys/cpu.h>
36 #include <sys/kmem.h>
37 #include <sys/mutex.h>
38 #include <sys/queue.h>
39 #include <sys/select.h>
40
41 #include <rump/rumpuser.h>
42
43 #include "rump_private.h"
44
45 /* should go for MAXCPUS at some point */
46 static struct cpu_info rump_cpus[1];
47 static struct rumpcpu {
48 struct cpu_info *rcpu_ci;
49 SLIST_ENTRY(rumpcpu) rcpu_entries;
50 } rcpu_storage[1];
51 struct cpu_info *rump_cpu = &rump_cpus[0];
52 int ncpu = 1;
53
54 static SLIST_HEAD(,rumpcpu) cpu_freelist = SLIST_HEAD_INITIALIZER(cpu_freelist);
55 static struct rumpuser_mtx *schedmtx;
56 static struct rumpuser_cv *schedcv;
57
58 struct cpu_info *
59 cpu_lookup(u_int index)
60 {
61
62 return &rump_cpus[index];
63 }
64
65 void
66 rump_scheduler_init()
67 {
68 struct rumpcpu *rcpu;
69 struct cpu_info *ci;
70 int i;
71
72 rumpuser_mutex_init(&schedmtx);
73 rumpuser_cv_init(&schedcv);
74 for (i = 0; i < ncpu; i++) {
75 rcpu = &rcpu_storage[i];
76 ci = &rump_cpus[i];
77 rump_cpu_bootstrap(ci);
78 rcpu->rcpu_ci = ci;
79 SLIST_INSERT_HEAD(&cpu_freelist, rcpu, rcpu_entries);
80 }
81 }
82
83 void
84 rump_schedule()
85 {
86 struct lwp *l = rumpuser_get_curlwp();
87
88 /*
89 * If there is no dedicated lwp, allocate a temp one and
90 * set it to be free'd upon unschedule().
91 */
92 if (l == NULL) {
93 l = rump_lwp_alloc(0, rump_nextlid());
94 rumpuser_set_curlwp(l);
95 rump_lwp_release(l);
96 }
97 rump_schedule_cpu(l);
98 }
99
100 void
101 rump_schedule_cpu(struct lwp *l)
102 {
103 struct rumpcpu *rcpu;
104
105 KASSERT(l->l_cpu == NULL);
106 rumpuser_mutex_enter_nowrap(schedmtx);
107 while ((rcpu = SLIST_FIRST(&cpu_freelist)) == NULL)
108 rumpuser_cv_wait_nowrap(schedcv, schedmtx);
109 SLIST_REMOVE_HEAD(&cpu_freelist, rcpu_entries);
110 rumpuser_mutex_exit(schedmtx);
111 l->l_cpu = rcpu->rcpu_ci;
112 }
113
114 void
115 rump_unschedule()
116 {
117 struct lwp *l;
118
119 l = rumpuser_get_curlwp();
120 rump_unschedule_cpu(l);
121 if (l->l_flag & LW_WEXIT) {
122 kmem_free(l, sizeof(*l));
123 rumpuser_set_curlwp(NULL);
124 }
125 }
126
127 void
128 rump_unschedule_cpu(struct lwp *l)
129 {
130 struct rumpcpu *rcpu;
131 struct cpu_info *ci;
132
133 ci = l->l_cpu;
134 l->l_cpu = NULL;
135 rcpu = &rcpu_storage[ci-&rump_cpus[0]];
136 KASSERT(rcpu->rcpu_ci == ci);
137
138 rumpuser_mutex_enter_nowrap(schedmtx);
139 SLIST_INSERT_HEAD(&cpu_freelist, rcpu, rcpu_entries);
140 rumpuser_cv_signal(schedcv);
141 rumpuser_mutex_exit(schedmtx);
142 }
143