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