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