1 /* $OpenBSD: softintr.c,v 1.8 2020/09/11 09:27:10 mpi Exp $ */
2 /* $NetBSD: softintr.c,v 1.1 2003/02/26 21:26:12 fvdl Exp $ */
3
4 /*-
5 * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Jason R. Thorpe.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 /*
34 * Generic soft interrupt implementation for NetBSD/x86.
35 */
36
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/malloc.h>
40
41 #include <machine/intr.h>
42
43 #include <uvm/uvm_extern.h>
44
45 struct i386_soft_intr i386_soft_intrs[I386_NSOFTINTR];
46
47 const int i386_soft_intr_to_ssir[I386_NSOFTINTR] = {
48 SIR_CLOCK,
49 SIR_NET,
50 SIR_TTY,
51 };
52
53 /*
54 * softintr_init:
55 *
56 * Initialize the software interrupt system.
57 */
58 void
59 softintr_init(void)
60 {
61 struct i386_soft_intr *si;
62 int i;
63
64 for (i = 0; i < I386_NSOFTINTR; i++) {
65 si = &i386_soft_intrs[i];
66 TAILQ_INIT(&si->softintr_q);
67 mtx_init(&si->softintr_lock, IPL_HIGH);
68 si->softintr_ssir = i386_soft_intr_to_ssir[i];
69 }
70 }
71
72 /*
73 * softintr_dispatch:
74 *
75 * Process pending software interrupts.
76 */
77 void
78 softintr_dispatch(int which)
79 {
80 struct i386_soft_intr *si = &i386_soft_intrs[which];
81 struct i386_soft_intrhand *sih;
82
83 KERNEL_LOCK();
84 for (;;) {
85 mtx_enter(&si->softintr_lock);
86 sih = TAILQ_FIRST(&si->softintr_q);
87 if (sih == NULL) {
88 mtx_leave(&si->softintr_lock);
89 break;
90 }
91 TAILQ_REMOVE(&si->softintr_q, sih, sih_q);
92 sih->sih_pending = 0;
93
94 uvmexp.softs++;
95
96 mtx_leave(&si->softintr_lock);
97
98 (*sih->sih_fn)(sih->sih_arg);
99 }
100 KERNEL_UNLOCK();
101 }
102
103 /*
104 * softintr_establish: [interface]
105 *
106 * Register a software interrupt handler.
107 */
108 void *
109 softintr_establish(int ipl, void (*func)(void *), void *arg)
110 {
111 struct i386_soft_intr *si;
112 struct i386_soft_intrhand *sih;
113 int which;
114
115 switch (ipl) {
116 case IPL_SOFTCLOCK:
117 which = I386_SOFTINTR_SOFTCLOCK;
118 break;
119
120 case IPL_SOFTNET:
121 which = I386_SOFTINTR_SOFTNET;
122 break;
123
124 case IPL_TTY:
125 case IPL_SOFTTTY:
126 which = I386_SOFTINTR_SOFTTTY;
127 break;
128
129 default:
130 panic("softintr_establish");
131 }
132
133 si = &i386_soft_intrs[which];
134
135 sih = malloc(sizeof(*sih), M_DEVBUF, M_NOWAIT);
136 if (__predict_true(sih != NULL)) {
137 sih->sih_intrhead = si;
138 sih->sih_fn = func;
139 sih->sih_arg = arg;
140 sih->sih_pending = 0;
141 }
142 return (sih);
143 }
144
145 /*
146 * softintr_disestablish: [interface]
147 *
148 * Unregister a software interrupt handler.
149 */
150 void
151 softintr_disestablish(void *arg)
152 {
153 struct i386_soft_intrhand *sih = arg;
154 struct i386_soft_intr *si = sih->sih_intrhead;
155
156 mtx_enter(&si->softintr_lock);
157 if (sih->sih_pending) {
158 TAILQ_REMOVE(&si->softintr_q, sih, sih_q);
159 sih->sih_pending = 0;
160 }
161 mtx_leave(&si->softintr_lock);
162
163 free(sih, M_DEVBUF, sizeof(*sih));
164 }
Cache object: 6e472c9851fe906aab3c205212f74f7d
|