xref: /titanic_51/usr/src/uts/common/os/softint.c (revision 8eea8e29cc4374d1ee24c25a07f45af132db3499)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <sys/types.h>
30 #include <sys/param.h>
31 #include <sys/t_lock.h>
32 #include <sys/systm.h>
33 #include <sys/spl.h>
34 #include <sys/cmn_err.h>
35 #include <sys/debug.h>
36 #include <sys/kdi_impl.h>
37 
38 /*
39  * Handle software interrupts through 'softcall' mechanism
40  */
41 
42 #define	NSOFTCALLS	200
43 
44 typedef struct softcall {
45 	void (*sc_func)(void *);	/* function to call */
46 	void *sc_arg;			/* arg to pass to func */
47 	struct softcall *sc_next;	/* next in list */
48 } softcall_t;
49 
50 static softcall_t softcalls[NSOFTCALLS], *softhead, *softtail, *softfree;
51 
52 static kmutex_t	softcall_lock;		/* protects softcall lists */
53 
54 static void (*kdi_softcall_func)(void);
55 
56 extern void siron(void);
57 
58 void
59 softcall_init(void)
60 {
61 	softcall_t *sc;
62 
63 	for (sc = softcalls; sc < &softcalls[NSOFTCALLS]; sc++) {
64 		sc->sc_next = softfree;
65 		softfree = sc;
66 	}
67 	mutex_init(&softcall_lock, NULL, MUTEX_SPIN, (void *)ipltospl(SPL8));
68 }
69 
70 /*
71  * Call function func with argument arg
72  * at some later time at software interrupt priority
73  */
74 void
75 softcall(void (*func)(void *), void *arg)
76 {
77 	softcall_t *sc;
78 
79 	/*
80 	 * protect against cross-calls
81 	 */
82 	mutex_enter(&softcall_lock);
83 	/* coalesce identical softcalls */
84 	for (sc = softhead; sc != 0; sc = sc->sc_next) {
85 		if (sc->sc_func == func && sc->sc_arg == arg) {
86 			mutex_exit(&softcall_lock);
87 			return;
88 		}
89 	}
90 
91 	if ((sc = softfree) == 0)
92 		panic("too many softcalls");
93 	softfree = sc->sc_next;
94 	sc->sc_func = func;
95 	sc->sc_arg = arg;
96 	sc->sc_next = 0;
97 
98 	if (softhead) {
99 		softtail->sc_next = sc;
100 		softtail = sc;
101 		mutex_exit(&softcall_lock);
102 	} else {
103 		softhead = softtail = sc;
104 		mutex_exit(&softcall_lock);
105 		siron();
106 	}
107 }
108 
109 void
110 kdi_softcall(void (*func)(void))
111 {
112 	kdi_softcall_func = func;
113 
114 	if (softhead == NULL)
115 		siron();
116 }
117 
118 /*
119  * Called to process software interrupts
120  * take one off queue, call it, repeat
121  * Note queue may change during call
122  */
123 void
124 softint(void)
125 {
126 	softcall_t *sc;
127 	void (*func)();
128 	caddr_t arg;
129 
130 	for (;;) {
131 		mutex_enter(&softcall_lock);
132 		if ((sc = softhead) != NULL) {
133 			func = sc->sc_func;
134 			arg = sc->sc_arg;
135 			softhead = sc->sc_next;
136 			sc->sc_next = softfree;
137 			softfree = sc;
138 		}
139 		mutex_exit(&softcall_lock);
140 		if (sc == NULL)
141 			break;
142 		func(arg);
143 	}
144 
145 	if ((func = kdi_softcall_func) != NULL) {
146 		kdi_softcall_func = NULL;
147 		func();
148 	}
149 }
150