intr.c revision 1.3.6.2 1 1.3.6.2 haad /* $NetBSD: intr.c,v 1.3.6.2 2008/12/13 01:15:34 haad Exp $ */
2 1.2 ad
3 1.3.6.1 haad /*
4 1.3.6.1 haad * Copyright (c) 2008 Antti Kantee. All Rights Reserved.
5 1.2 ad *
6 1.2 ad * Redistribution and use in source and binary forms, with or without
7 1.2 ad * modification, are permitted provided that the following conditions
8 1.2 ad * are met:
9 1.2 ad * 1. Redistributions of source code must retain the above copyright
10 1.2 ad * notice, this list of conditions and the following disclaimer.
11 1.2 ad * 2. Redistributions in binary form must reproduce the above copyright
12 1.2 ad * notice, this list of conditions and the following disclaimer in the
13 1.2 ad * documentation and/or other materials provided with the distribution.
14 1.2 ad *
15 1.3.6.1 haad * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
16 1.3.6.1 haad * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 1.3.6.1 haad * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 1.3.6.1 haad * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 1.3.6.1 haad * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 1.3.6.1 haad * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 1.3.6.1 haad * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 1.3.6.1 haad * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 1.3.6.1 haad * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 1.3.6.1 haad * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 1.3.6.1 haad * SUCH DAMAGE.
26 1.2 ad */
27 1.2 ad
28 1.2 ad #include <sys/param.h>
29 1.2 ad #include <sys/cpu.h>
30 1.3.6.1 haad #include <sys/kthread.h>
31 1.3.6.1 haad #include <sys/intr.h>
32 1.2 ad
33 1.3.6.1 haad #include <rump/rumpuser.h>
34 1.3.6.1 haad
35 1.3.6.1 haad #include "rump_private.h"
36 1.3.6.1 haad
37 1.3.6.1 haad /*
38 1.3.6.1 haad * Interrupt simulator. It executes hardclock() and softintrs.
39 1.3.6.1 haad */
40 1.2 ad
41 1.3.6.1 haad time_t time_uptime = 1;
42 1.3.6.1 haad
43 1.3.6.1 haad struct softint {
44 1.3.6.1 haad void (*si_func)(void *);
45 1.3.6.1 haad void *si_arg;
46 1.3.6.1 haad bool si_onlist;
47 1.3.6.1 haad bool si_mpsafe;
48 1.3.6.1 haad
49 1.3.6.1 haad LIST_ENTRY(softint) si_entries;
50 1.2 ad };
51 1.3.6.1 haad static LIST_HEAD(, softint) si_pending = LIST_HEAD_INITIALIZER(si_pending);
52 1.3.6.1 haad static kmutex_t si_mtx;
53 1.3.6.1 haad static kcondvar_t si_cv;
54 1.2 ad
55 1.3.6.1 haad static void
56 1.3.6.1 haad intr_worker(void *arg)
57 1.2 ad {
58 1.3.6.1 haad struct softint *si;
59 1.3.6.1 haad void (*func)(void *) = NULL;
60 1.3.6.1 haad void *funarg = NULL; /* XXX gcc */
61 1.3.6.1 haad bool mpsafe = false; /* XXX gcc */
62 1.3.6.1 haad int ticks;
63 1.3.6.1 haad
64 1.3.6.1 haad for (ticks = 0;;ticks++) {
65 1.3.6.1 haad /*
66 1.3.6.1 haad * XXX: not exactly executed once per tick, but without
67 1.3.6.1 haad * a proper timer ticktocking we don't really care.
68 1.3.6.1 haad */
69 1.3.6.1 haad callout_hardclock();
70 1.3.6.1 haad
71 1.3.6.1 haad /* advance uptime with the same leisurely attitude */
72 1.3.6.1 haad if (ticks & 0x80) {
73 1.3.6.1 haad time_uptime++;
74 1.3.6.1 haad ticks = 0;
75 1.3.6.1 haad }
76 1.3.6.1 haad
77 1.3.6.1 haad mutex_enter(&si_mtx);
78 1.3.6.1 haad if (LIST_EMPTY(&si_pending)) {
79 1.3.6.1 haad cv_timedwait(&si_cv, &si_mtx, 1);
80 1.3.6.1 haad } else {
81 1.3.6.1 haad si = LIST_FIRST(&si_pending);
82 1.3.6.1 haad func = si->si_func;
83 1.3.6.1 haad funarg = si->si_arg;
84 1.3.6.1 haad mpsafe = si->si_mpsafe;
85 1.3.6.1 haad
86 1.3.6.1 haad si->si_onlist = false;
87 1.3.6.1 haad LIST_REMOVE(si, si_entries);
88 1.3.6.1 haad }
89 1.3.6.1 haad mutex_exit(&si_mtx);
90 1.3.6.1 haad
91 1.3.6.1 haad if (func) {
92 1.3.6.1 haad if (!mpsafe)
93 1.3.6.1 haad KERNEL_LOCK(1, curlwp);
94 1.3.6.1 haad func(funarg);
95 1.3.6.1 haad func = NULL;
96 1.3.6.1 haad if (!mpsafe)
97 1.3.6.1 haad KERNEL_UNLOCK_ONE(curlwp);
98 1.3.6.1 haad }
99 1.2 ad }
100 1.2 ad }
101 1.2 ad
102 1.2 ad void
103 1.3.6.1 haad softint_init(struct cpu_info *ci)
104 1.2 ad {
105 1.3.6.1 haad int rv;
106 1.2 ad
107 1.3.6.1 haad mutex_init(&si_mtx, MUTEX_DEFAULT, IPL_NONE);
108 1.3.6.1 haad cv_init(&si_cv, "intrw8");
109 1.3.6.1 haad
110 1.3.6.1 haad /* XXX: should have separate "wanttimer" control */
111 1.3.6.1 haad if (rump_threads) {
112 1.3.6.1 haad rv = kthread_create(PRI_NONE, 0, NULL, intr_worker, NULL, NULL,
113 1.3.6.1 haad "rumpmtr");
114 1.3.6.1 haad if (rv)
115 1.3.6.1 haad panic("timer thread creation failed %d", rv);
116 1.3.6.1 haad }
117 1.3.6.1 haad }
118 1.3.6.1 haad
119 1.3.6.1 haad /*
120 1.3.6.1 haad * Soft interrupts bring two choices. If we are running with thread
121 1.3.6.1 haad * support enabled, defer execution, otherwise execute in place.
122 1.3.6.1 haad * See softint_schedule().
123 1.3.6.1 haad *
124 1.3.6.1 haad * As there is currently no clear concept of when a thread finishes
125 1.3.6.1 haad * work (although rump_clear_curlwp() is close), simply execute all
126 1.3.6.1 haad * softints in the timer thread. This is probably not the most
127 1.3.6.1 haad * efficient method, but good enough for now.
128 1.3.6.1 haad */
129 1.3.6.1 haad void *
130 1.3.6.1 haad softint_establish(u_int flags, void (*func)(void *), void *arg)
131 1.3.6.1 haad {
132 1.3.6.1 haad struct softint *si;
133 1.3.6.1 haad
134 1.3.6.1 haad si = kmem_alloc(sizeof(*si), KM_SLEEP);
135 1.3.6.1 haad si->si_func = func;
136 1.3.6.1 haad si->si_arg = arg;
137 1.3.6.1 haad si->si_onlist = false;
138 1.3.6.1 haad si->si_mpsafe = flags & SOFTINT_MPSAFE;
139 1.3.6.1 haad
140 1.3.6.1 haad return si;
141 1.2 ad }
142 1.2 ad
143 1.2 ad void
144 1.2 ad softint_schedule(void *arg)
145 1.2 ad {
146 1.3.6.1 haad struct softint *si = arg;
147 1.2 ad
148 1.3.6.1 haad if (!rump_threads) {
149 1.3.6.1 haad si->si_func(si->si_arg);
150 1.3.6.1 haad } else {
151 1.3.6.1 haad mutex_enter(&si_mtx);
152 1.3.6.1 haad if (!si->si_onlist) {
153 1.3.6.1 haad LIST_INSERT_HEAD(&si_pending, si, si_entries);
154 1.3.6.1 haad si->si_onlist = true;
155 1.3.6.1 haad }
156 1.3.6.1 haad cv_signal(&si_cv);
157 1.3.6.1 haad mutex_exit(&si_mtx);
158 1.3.6.1 haad }
159 1.2 ad }
160 1.2 ad
161 1.2 ad bool
162 1.3.6.2 haad cpu_intr_p(void)
163 1.2 ad {
164 1.2 ad
165 1.2 ad return false;
166 1.2 ad }
167