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