The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/ngatm/netnatm/api/cc_sig.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2 * Copyright (c) 2004
    3 *       Hartmut Brandt
    4 *       All rights reserved.
    5 *
    6 * Author: Harti Brandt <harti@freebsd.org>
    7 *
    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:
   11 *
   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.
   17 *
   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.
   29 *
   30 * $Begemot: libunimsg/netnatm/api/cc_sig.c,v 1.1 2004/07/08 08:21:54 brandt Exp $
   31 *
   32 * ATM API as defined per af-saa-0108
   33 *
   34 * Generic signal handling
   35 */
   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>
   44 
   45 enum {
   46         SIG_USER,
   47         SIG_CONN,
   48 };
   49 
   50 struct ccsig {
   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;
   58 };
   59 
   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);   \
   64     } while (0)
   65 #else
   66 #define cc_sig_log(CC, FMT, ...) do {                                   \
   67         if ((CC)->log & CCLOG_SIGS)                                     \
   68                 (CC)->funcs->log("%s: " FMT, __func__, __VA_ARGS__);    \
   69     } while (0)
   70 #endif
   71 
   72 
   73 const char *const cc_user_sigtab[] = {
   74 #define DEF(N) [USER_SIG_##N] = #N,
   75 USER_SIGS
   76 #undef DEF
   77 };
   78 
   79 const char *const cc_conn_sigtab[] = {
   80 #define DEF(N) [CONN_SIG_##N] = #N,
   81 CONN_SIGS
   82 #undef DEF
   83 };
   84 
   85 
   86 /*
   87  * Allocate and populate a signal
   88  */
   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)
   92 {
   93         struct ccsig *s;
   94 
   95         if ((s = TAILQ_FIRST(&cc->free_sigs)) == NULL) {
   96                 s = CCZALLOC(sizeof(struct ccsig));
   97                 if (s == NULL) {
   98                         cc_log(cc, "signal %u/%u lost - ENOMEM", type, sig);
   99                         return (NULL);
  100                 }
  101         } else
  102                 TAILQ_REMOVE(&cc->free_sigs, s, link);
  103 
  104         s->type = type;
  105         s->has_msg = has_msg;
  106         s->target = target;
  107         s->sig = sig;
  108         s->arg1 = arg1;
  109         s->arg2 = arg2;
  110 
  111         return (s);
  112 }
  113 
  114 /*
  115  * Queue a signal to this user
  116  */
  117 int
  118 cc_user_sig(struct ccuser *user, enum user_sig sig, void *arg1, u_int arg2)
  119 {
  120         struct ccsig *s;
  121 
  122         s = sig_alloc(user->cc, SIG_USER, user, 0, sig, arg1, arg2);
  123         if (s == NULL)
  124                 return (ENOMEM);
  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],
  127             user);
  128         return (0);
  129 }
  130 
  131 /* Queue a signal with message to this user */
  132 int
  133 cc_user_sig_msg(struct ccuser *user, enum user_sig sig, struct uni_msg *msg)
  134 {
  135         struct ccsig *s;
  136 
  137         s = sig_alloc(user->cc, SIG_USER, user, msg != NULL, sig, msg, 0);
  138         if (s == NULL)
  139                 return (ENOMEM);
  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],
  142             user);
  143         return (0);
  144 }
  145 
  146 /*
  147  * Signal to connection
  148  */
  149 static int
  150 sig_conn(struct ccconn *conn, enum conn_sig sig, u_int has_msg, void *arg)
  151 {
  152         struct ccsig *s;
  153         const struct ccreq *r = NULL;
  154 
  155         s = sig_alloc(conn->cc, SIG_CONN, conn, has_msg, sig, arg, 0);
  156         if (s == NULL)
  157                 return (ENOMEM);
  158 
  159         if (conn->port != NULL) {
  160                 /* argh */
  161                 TAILQ_FOREACH(r, &conn->port->cookies, link)
  162                         if (r->conn == conn)
  163                                 break;
  164         }
  165         if (r == NULL) {
  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);
  169         } else {
  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);
  173         }
  174         return (0);
  175 }
  176 
  177 /*
  178  * Queue a signal to a connection.
  179  */
  180 int
  181 cc_conn_sig(struct ccconn *conn, enum conn_sig sig, void *arg1)
  182 {
  183 
  184         return (sig_conn(conn, sig, 0, arg1));
  185 }
  186 
  187 /*
  188  * signal with message to connection
  189  */
  190 int
  191 cc_conn_sig_msg(struct ccconn *conn, enum conn_sig sig, struct uni_msg *msg)
  192 {
  193 
  194         return (sig_conn(conn, sig, (msg != NULL), msg));
  195 }
  196 int
  197 cc_conn_sig_msg_nodef(struct ccconn *conn, enum conn_sig sig,
  198     struct uni_msg *msg)
  199 {
  200         struct ccsig *s;
  201 
  202         s = sig_alloc(conn->cc, SIG_CONN, conn, (msg != NULL), sig, msg, 0);
  203         if (s == NULL)
  204                 return (ENOMEM);
  205 
  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);
  209 
  210         return (0);
  211 }
  212 
  213 /*
  214  * Queue a response signal to a connection.
  215  */
  216 int
  217 cc_conn_resp(struct ccconn *conn, enum conn_sig sig, u_int cookie __unused,
  218     u_int reason, u_int state)
  219 {
  220         struct ccsig *s, *s1, *s2;
  221 
  222         s = sig_alloc(conn->cc, SIG_CONN, conn, 0, sig, NULL,
  223              ((reason & 0xffff) << 16) | (state & 0xffff));
  224         if (s == NULL)
  225                 return (ENOMEM);
  226 
  227         TAILQ_INSERT_TAIL(&conn->cc->sigs, s, link);
  228 
  229         cc_sig_log(conn->cc, "queuing response %s to conn %p",
  230             cc_conn_sigtab[sig], conn);
  231 
  232         s1 = TAILQ_FIRST(&conn->cc->def_sigs);
  233         while (s1 != NULL) {
  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);
  240                         s = s1;
  241                 }
  242                 s1 = s2;
  243         }
  244 
  245         return (0);
  246 }
  247 
  248 /*
  249  * Flush all signals to a given target from both queues
  250  */
  251 static /* __inline */ void
  252 sig_flush(struct ccdata *cc, u_int type, void *target)
  253 {
  254         struct ccsig *s, *s1;
  255 
  256         s = TAILQ_FIRST(&cc->sigs);
  257         while (s != NULL) {
  258                 s1 = TAILQ_NEXT(s, link);
  259                 if (s->type == type && s->target == target) {
  260                         if (s->has_msg)
  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);
  264                 }
  265                 s = s1;
  266         }
  267 
  268         s = TAILQ_FIRST(&cc->def_sigs);
  269         while (s != NULL) {
  270                 s1 = TAILQ_NEXT(s, link);
  271                 if (s->type == type && s->target == target) {
  272                         if (s->has_msg)
  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);
  276                 }
  277                 s = s1;
  278         }
  279 }
  280 
  281 /*
  282  * Flush all signals to this user
  283  */
  284 void
  285 cc_user_sig_flush(struct ccuser *user)
  286 {
  287 
  288         cc_sig_log(user->cc, "flushing signals to user %p", user);
  289         sig_flush(user->cc, SIG_USER, user);
  290 }
  291 
  292 /*
  293  * Flush all signals to this connection
  294  */
  295 void
  296 cc_conn_sig_flush(struct ccconn *conn)
  297 {
  298 
  299         cc_sig_log(conn->cc, "flushing signals to conn %p", conn);
  300         sig_flush(conn->cc, SIG_CONN, conn);
  301 }
  302 
  303 /*
  304  * Do the work
  305  */
  306 void
  307 cc_work(struct ccdata *cc)
  308 {
  309         struct ccsig *s;
  310 
  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);
  316                 else {
  317                         cc_conn_sig_handle(s->target, s->sig, s->arg1, s->arg2);
  318                         if (s->has_msg)
  319                                 uni_msg_destroy(s->arg1);
  320                 }
  321                 TAILQ_INSERT_HEAD(&cc->free_sigs, s, link);
  322         }
  323         cc_sig_log(cc, "end %s", "work");
  324 }
  325 
  326 /*
  327  * flush all signals
  328  */
  329 void
  330 cc_sig_flush_all(struct ccdata *cc)
  331 {
  332         struct ccsig *s;
  333 
  334         while ((s = TAILQ_FIRST(&cc->sigs)) != NULL) {
  335                 if (s->has_msg)
  336                         uni_msg_destroy((struct uni_msg *)s->arg1);
  337                 TAILQ_REMOVE(&cc->sigs, s, link);
  338                 CCFREE(s);
  339         }
  340         while ((s = TAILQ_FIRST(&cc->def_sigs)) != NULL) {
  341                 if (s->has_msg)
  342                         uni_msg_destroy((struct uni_msg *)s->arg1);
  343                 TAILQ_REMOVE(&cc->def_sigs, s, link);
  344                 CCFREE(s);
  345         }
  346         while ((s = TAILQ_FIRST(&cc->free_sigs)) != NULL) {
  347                 TAILQ_REMOVE(&cc->free_sigs, s, link);
  348                 CCFREE(s);
  349         }
  350 }

Cache object: a221e4152a58705e13de11298159d9d1


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.