1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44:
45:
46: 47: 48: 49:
50:
51: #include <tk/tkernel.h>
52: #include "netmain/tkn_spl.h"
53:
54: #include <sys/param.h>
55: #include <sys/systm.h>
56: #include <sys/syslog.h>
57: #include <sys/tkn_intr.h>
58: #include <sys/intr.h>
59: #include <sys/lwp.h>
60: #include <sys/malloc.h>
61:
62: #include "tkn.h"
63: #include "netmain/tkn_taskutil.h"
64:
65:
66: struct tkn_intrhand {
67: ID task;
68: ID sem;
69: };
70:
71: struct tkn_spl_trampo {
72: struct tkn_intrhand ih;
73: int level;
74: int mpsafe;
75: void (*hand)(void*);
76: void* arg;
77: };
78:
79: static void spl_trampo(INT arg, VP vp)
80: {
81: ER er = 0;
82: lwp_t *lwp = curlwp;
83: struct tkn_spl_trampo *trampo = vp;
84: if (trampo == NULL)
85: goto err_bad_arg;
86:
87: ID sem = trampo->ih.sem;
88: void (*hand)(void*) = trampo->hand;
89: void* p_arg = trampo->arg;
90: int level = trampo->level;
91: int mpsafe = trampo->mpsafe;
92: int s;
93:
94: for (;;) {
95: 96: 97:
98: er = tk_wai_sem(sem, 1, TMO_FEVR);
99: if (er < 0) {
100: if (er == E_NOEXS || er == E_DLT)
101: goto err_exit;
102: goto err_sem;
103: }
104:
105: s = tkn_spl_lock(level);
106: if ( mpsafe ) {
107: KERNEL_LOCK(1, lwp);
108: hand(p_arg);
109: KERNEL_UNLOCK_ONE(lwp);
110: } else {
111: hand(p_arg);
112: }
113: tkn_spl_unlock(s);
114: }
115:
116: return;
117:
118: err_bad_arg:
119:
120: log(LOG_ERR, "%s:tid=%d bad args", __func__, tk_get_tid());
121: tk_exd_tsk();
122: return;
123: err_sem:
124: log(LOG_ERR, "%s: unexpected error %d(%d, %d)", __func__, er, MERCD(er), SERCD(er));
125: err_exit:
126:
127: free(trampo, M_SOFTINTR);
128: tk_exd_tsk();
129: }
130:
131:
132: 133: 134:
135: int
136: tkn_spl_submit_intr_di(int id)
137: {
138: return tk_sig_sem(id, 1);
139: }
140:
141: int
142: tkn_spl_submit_intr(int id)
143: {
144: ER er;
145:
146: er = tkn_spl_submit_intr_di(id);
147: if (er < 0)
148: goto err_signal;
149: return 0;
150:
151: err_signal:
152: log(LOG_ERR, "%s: unexpected error %d(%d, %d) ID=%d\n", __func__, er, MERCD(er), SERCD(er), id);
153: return er;
154: }
155:
156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167:
168: int
169: tkn_spl_make_handler(void (*hand)(), int flags, void* arg)
170: {
171: int level = flags & SOFTINT_LVLMASK;
172: int mpsafe = flags & SOFTINT_MPSAFE;
173: int ipl_level;
174:
175: switch(level) {
176: case SOFTINT_BIO:
177: ipl_level = IPL_BIO;
178: break;
179: case SOFTINT_CLOCK:
180: ipl_level = IPL_CLOCK;
181: break;
182: case SOFTINT_SERIAL:
183: ipl_level = IPL_SERIAL;
184: break;
185: case SOFTINT_NET:
186: ipl_level = IPL_NET;
187: break;
188: default:
189: ipl_level = level;
190: }
191:
192: 193: 194:
195: struct tkn_spl_trampo *trampo;
196: trampo = malloc(sizeof(struct tkn_spl_trampo), M_SOFTINTR, M_NOWAIT | M_ZERO);
197: if (trampo == NULL)
198: goto err_trampo;
199:
200: struct tkn_intrhand ih;
201:
202: ih.sem = tkn_cre_sem("Nsih");
203: if (ih.sem < 0)
204: goto err_sem;
205:
206: 207: 208:
209: PRI prio;
210: trampo->level = ipl_level;
211: trampo->mpsafe = mpsafe;
212: trampo->hand = hand;
213: trampo->arg = arg;
214: prio = tkn_spl_priority(ipl_level);
215: ih.task = tkn_cre_tsk(spl_trampo, prio, TKN_SPLTRAMPO_STKSZ, trampo);
216: if (ih.task < 0)
217: goto err_task;
218: trampo->ih = ih;
219:
220: 221: 222:
223: ER er;
224: er = tk_sta_tsk(ih.task, 0);
225: if (er < 0)
226: goto err_task_start;
227:
228: return ih.sem;
229:
230: err_task_start:
231: tk_del_tsk(ih.task);
232: err_task:
233: tk_del_sem(ih.sem);
234: err_sem:
235: free(trampo, M_RTABLE);
236: err_trampo:
237: log(LOG_ERR, "%s: unexpected error\n", __func__);
238: return -1;
239: }
240:
241: int tkn_spl_delete_handler(int id)
242: {
243: return tk_del_sem(id);
244: }
245:
246: void* softint_establish(unsigned int flags, void (*func)(void*), void* arg)
247: {
248: int ret = tkn_spl_make_handler(func, flags, arg);
249:
250: return (ret < 0 ? NULL : (void*)ret);
251: }
252:
253: void softint_disestablish(void* handle)
254: {
255: tk_del_sem((ID)handle);
256: }
257:
258: void softint_schedule(void* handle)
259: {
260: tkn_spl_submit_intr((ID)handle);
261: }