6 * Author: Harti Brandt <harti@freebsd.org>
8 * Redistribution of this software and documentation and use in source and
9 * binary forms, with or without modification, are permitted provided that
10 * the following conditions are met:
12 * 1. Redistributions of source code or documentation must retain the above
13 * copyright notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE AUTHOR
19 * AND ITS CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
20 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
22 * THE AUTHOR OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
25 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
28 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 * $Begemot: libunimsg/netnatm/api/cc_sig.c,v 1.1 2004/07/08 08:21:54 brandt Exp $
32 * ATM API as defined per af-saa-0108
34 * Generic signal handling
36 #include <netnatm/unimsg.h>
37 #include <netnatm/msg/unistruct.h>
38 #include <netnatm/msg/unimsglib.h>
39 #include <netnatm/api/unisap.h>
40 #include <netnatm/sig/unidef.h>
41 #include <netnatm/api/atmapi.h>
42 #include <netnatm/api/ccatm.h>
43 #include <netnatm/api/ccpriv.h>
51 u_char type; /* type of target */
52 u_char has_msg; /* arg1 is a message */
53 void *target; /* target instance */
54 u_int sig; /* signal */
55 void *arg1; /* argument */
56 u_int arg2; /* argument */
57 TAILQ_ENTRY(ccsig) link;
60 #if defined(__GNUC__) && __GNUC__ < 3
61 #define cc_sig_log(CC, FMT, ARGS...) do { \
62 if ((CC)->log & CCLOG_SIGS) \
63 (CC)->funcs->log("%s: " FMT, __FUNCTION__ , ## ARGS); \
66 #define cc_sig_log(CC, FMT, ...) do { \
67 if ((CC)->log & CCLOG_SIGS) \
68 (CC)->funcs->log("%s: " FMT, __func__, __VA_ARGS__); \
73 const char *const cc_user_sigtab[] = {
74 #define DEF(N) [USER_SIG_##N] = #N,
79 const char *const cc_conn_sigtab[] = {
80 #define DEF(N) [CONN_SIG_##N] = #N,
87 * Allocate and populate a signal
89 static /* __inline */ struct ccsig *
90 sig_alloc(struct ccdata *cc, u_int type, void *target, u_int has_msg,
91 u_int sig, void *arg1, u_int arg2)
95 if ((s = TAILQ_FIRST(&cc->free_sigs)) == NULL) {
96 s = CCZALLOC(sizeof(struct ccsig));
98 cc_log(cc, "signal %u/%u lost - ENOMEM", type, sig);
102 TAILQ_REMOVE(&cc->free_sigs, s, link);
105 s->has_msg = has_msg;
115 * Queue a signal to this user
118 cc_user_sig(struct ccuser *user, enum user_sig sig, void *arg1, u_int arg2)
122 s = sig_alloc(user->cc, SIG_USER, user, 0, sig, arg1, arg2);
125 TAILQ_INSERT_TAIL(&user->cc->sigs, s, link);
126 cc_sig_log(user->cc, "queuing sig %s to user %p", cc_user_sigtab[sig],
131 /* Queue a signal with message to this user */
133 cc_user_sig_msg(struct ccuser *user, enum user_sig sig, struct uni_msg *msg)
137 s = sig_alloc(user->cc, SIG_USER, user, msg != NULL, sig, msg, 0);
140 TAILQ_INSERT_TAIL(&user->cc->sigs, s, link);
141 cc_sig_log(user->cc, "queuing sig %s to user %p", cc_user_sigtab[sig],
147 * Signal to connection
150 sig_conn(struct ccconn *conn, enum conn_sig sig, u_int has_msg, void *arg)
153 const struct ccreq *r = NULL;
155 s = sig_alloc(conn->cc, SIG_CONN, conn, has_msg, sig, arg, 0);
159 if (conn->port != NULL) {
161 TAILQ_FOREACH(r, &conn->port->cookies, link)
166 TAILQ_INSERT_TAIL(&conn->cc->sigs, s, link);
167 cc_sig_log(conn->cc, "queuing sig %s to conn %p",
168 cc_conn_sigtab[sig], conn);
170 TAILQ_INSERT_TAIL(&conn->cc->def_sigs, s, link);
171 cc_sig_log(conn->cc, "queuing defered sig %s to conn %p",
172 cc_conn_sigtab[sig], conn);
178 * Queue a signal to a connection.
181 cc_conn_sig(struct ccconn *conn, enum conn_sig sig, void *arg1)
184 return (sig_conn(conn, sig, 0, arg1));
188 * signal with message to connection
191 cc_conn_sig_msg(struct ccconn *conn, enum conn_sig sig, struct uni_msg *msg)
194 return (sig_conn(conn, sig, (msg != NULL), msg));
197 cc_conn_sig_msg_nodef(struct ccconn *conn, enum conn_sig sig,
202 s = sig_alloc(conn->cc, SIG_CONN, conn, (msg != NULL), sig, msg, 0);
206 TAILQ_INSERT_TAIL(&conn->cc->sigs, s, link);
207 cc_sig_log(conn->cc, "queuing sig %s to conn %p",
208 cc_conn_sigtab[sig], conn);
214 * Queue a response signal to a connection.
217 cc_conn_resp(struct ccconn *conn, enum conn_sig sig, u_int cookie __unused,
218 u_int reason, u_int state)
220 struct ccsig *s, *s1, *s2;
222 s = sig_alloc(conn->cc, SIG_CONN, conn, 0, sig, NULL,
223 ((reason & 0xffff) << 16) | (state & 0xffff));
227 TAILQ_INSERT_TAIL(&conn->cc->sigs, s, link);
229 cc_sig_log(conn->cc, "queuing response %s to conn %p",
230 cc_conn_sigtab[sig], conn);
232 s1 = TAILQ_FIRST(&conn->cc->def_sigs);
234 s2 = TAILQ_NEXT(s1, link);
235 if (s1->type == SIG_CONN && s1->target == conn) {
236 TAILQ_REMOVE(&conn->cc->def_sigs, s1, link);
237 TAILQ_INSERT_AFTER(&conn->cc->sigs, s, s1, link);
238 cc_sig_log(conn->cc, "undefering sig %s to conn %p",
239 cc_conn_sigtab[s1->sig], conn);
249 * Flush all signals to a given target from both queues
251 static /* __inline */ void
252 sig_flush(struct ccdata *cc, u_int type, void *target)
254 struct ccsig *s, *s1;
256 s = TAILQ_FIRST(&cc->sigs);
258 s1 = TAILQ_NEXT(s, link);
259 if (s->type == type && s->target == target) {
261 uni_msg_destroy((struct uni_msg *)s->arg1);
262 TAILQ_REMOVE(&cc->sigs, s, link);
263 TAILQ_INSERT_HEAD(&cc->free_sigs, s, link);
268 s = TAILQ_FIRST(&cc->def_sigs);
270 s1 = TAILQ_NEXT(s, link);
271 if (s->type == type && s->target == target) {
273 uni_msg_destroy((struct uni_msg *)s->arg1);
274 TAILQ_REMOVE(&cc->def_sigs, s, link);
275 TAILQ_INSERT_HEAD(&cc->free_sigs, s, link);
282 * Flush all signals to this user
285 cc_user_sig_flush(struct ccuser *user)
288 cc_sig_log(user->cc, "flushing signals to user %p", user);
289 sig_flush(user->cc, SIG_USER, user);
293 * Flush all signals to this connection
296 cc_conn_sig_flush(struct ccconn *conn)
299 cc_sig_log(conn->cc, "flushing signals to conn %p", conn);
300 sig_flush(conn->cc, SIG_CONN, conn);
307 cc_work(struct ccdata *cc)
311 cc_sig_log(cc, "start %s", "work");
312 while ((s = TAILQ_FIRST(&cc->sigs)) != NULL) {
313 TAILQ_REMOVE(&cc->sigs, s, link);
314 if (s->type == SIG_USER)
315 cc_user_sig_handle(s->target, s->sig, s->arg1, s->arg2);
317 cc_conn_sig_handle(s->target, s->sig, s->arg1, s->arg2);
319 uni_msg_destroy(s->arg1);
321 TAILQ_INSERT_HEAD(&cc->free_sigs, s, link);
323 cc_sig_log(cc, "end %s", "work");
330 cc_sig_flush_all(struct ccdata *cc)
334 while ((s = TAILQ_FIRST(&cc->sigs)) != NULL) {
336 uni_msg_destroy((struct uni_msg *)s->arg1);
337 TAILQ_REMOVE(&cc->sigs, s, link);
340 while ((s = TAILQ_FIRST(&cc->def_sigs)) != NULL) {
342 uni_msg_destroy((struct uni_msg *)s->arg1);
343 TAILQ_REMOVE(&cc->def_sigs, s, link);
346 while ((s = TAILQ_FIRST(&cc->free_sigs)) != NULL) {
347 TAILQ_REMOVE(&cc->free_sigs, s, link);