File:  [DragonFly] / src / sys / net / netisr.c
Revision 1.9: download - view: text, annotated - select for diffs
Sat Mar 6 19:40:30 2004 UTC (10 years, 9 months ago) by dillon
Branches: MAIN
CVS tags: HEAD
Simplify LWKT message initialization semantics to reduce API confusion.

Cleanup netisr messaging to provide more uniform error handling and to use
lwkt_replymsg() unconditionally for both async/auto-free and sync messages
as the abstraction intended.  This also fixes a reply/free race.

    1: /*-
    2:  * Copyright (c) 2003 Jeffrey Hsu
    3:  * Copyright (c) 2003 Jonathan Lemon
    4:  * Copyright (c) 2003 Matthew Dillon
    5:  *
    6:  * $DragonFly: src/sys/net/netisr.c,v 1.9 2004/03/06 19:40:30 dillon Exp $
    7:  */
    8: 
    9: #include <sys/param.h>
   10: #include <sys/systm.h>
   11: #include <sys/kernel.h>
   12: #include <sys/malloc.h>
   13: #include <sys/msgport.h>
   14: #include <sys/proc.h>
   15: #include <sys/interrupt.h>
   16: #include <sys/socket.h>
   17: #include <sys/sysctl.h>
   18: #include <net/if.h>
   19: #include <net/if_var.h>
   20: #include <net/netisr.h>
   21: #include <machine/cpufunc.h>
   22: #include <machine/ipl.h>
   23: 
   24: #include <sys/thread2.h>
   25: #include <sys/msgport2.h>
   26: 
   27: static struct netisr netisrs[NETISR_MAX];
   28: 
   29: /* Per-CPU thread to handle any protocol.  */
   30: struct thread netisr_cpu[MAXCPU];
   31: lwkt_port netisr_afree_rport;
   32: 
   33: /*
   34:  * netisr_afree_rport replymsg function, only used to handle async
   35:  * messages which the sender has abandoned to their fate.
   36:  */
   37: static void
   38: netisr_autofree_reply(lwkt_port_t port, lwkt_msg_t msg)
   39: {
   40:     free(msg, M_LWKTMSG);
   41: }
   42: 
   43: static void
   44: netisr_init(void)
   45: {
   46:     int i;
   47: 
   48:     /* Create default per-cpu threads for generic protocol handling. */
   49:     for (i = 0; i < ncpus; ++i) {
   50: 	lwkt_create(netmsg_service_loop, NULL, NULL, &netisr_cpu[i], 0, i,
   51: 	    "netisr_cpu %d", i);
   52:     }
   53:     lwkt_initport(&netisr_afree_rport, NULL);
   54:     netisr_afree_rport.mp_replyport = netisr_autofree_reply;
   55: }
   56: 
   57: SYSINIT(netisr, SI_SUB_PROTO_BEGIN, SI_ORDER_FIRST, netisr_init, NULL);
   58: 
   59: void
   60: netmsg_service_loop(void *arg)
   61: {
   62:     struct netmsg *msg;
   63:     int error;
   64: 
   65:     while ((msg = lwkt_waitport(&curthread->td_msgport, NULL))) {
   66: 	error = msg->nm_handler(msg);
   67: 	lwkt_replymsg(&msg->nm_lmsg, error);
   68:     }
   69: }
   70: 
   71: /*
   72:  * Call the netisr directly.
   73:  * Queueing may be done in the msg port layer at its discretion.
   74:  */
   75: void
   76: netisr_dispatch(int num, struct mbuf *m)
   77: {
   78:     /* just queue it for now XXX JH */
   79:     netisr_queue(num, m);
   80: }
   81: 
   82: /*
   83:  * Same as netisr_dispatch(), but always queue.
   84:  * This is either used in places where we are not confident that
   85:  * direct dispatch is possible, or where queueing is required.
   86:  */
   87: int
   88: netisr_queue(int num, struct mbuf *m)
   89: {
   90:     struct netisr *ni;
   91:     struct netmsg_packet *pmsg;
   92:     lwkt_port_t port;
   93: 
   94:     KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
   95: 	("netisr_queue: bad isr %d", num));
   96: 
   97:     ni = &netisrs[num];
   98:     if (ni->ni_handler == NULL) {
   99: 	printf("netisr_queue: unregistered isr %d\n", num);
  100: 	return (EIO);
  101:     }
  102: 
  103:     if (!(port = ni->ni_mport(m)))
  104: 	return (EIO);
  105: 
  106:     /* use better message allocation system with limits later XXX JH */
  107:     if (!(pmsg = malloc(sizeof(struct netmsg_packet), M_LWKTMSG, M_NOWAIT)))
  108: 	return (ENOBUFS);
  109: 
  110:     lwkt_initmsg_rp(&pmsg->nm_lmsg, &netisr_afree_rport, CMD_NETMSG_NEWPKT);
  111:     pmsg->nm_packet = m;
  112:     pmsg->nm_handler = ni->ni_handler;
  113:     lwkt_sendmsg(port, &pmsg->nm_lmsg);
  114:     return (0);
  115: }
  116: 
  117: void
  118: netisr_register(int num, lwkt_portfn_t mportfn, netisr_fn_t handler)
  119: {
  120:     KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
  121: 	("netisr_register: bad isr %d", num));
  122: 
  123:     netisrs[num].ni_mport = mportfn;
  124:     netisrs[num].ni_handler = handler;
  125: }
  126: 
  127: int
  128: netisr_unregister(int num)
  129: {
  130:     KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
  131: 	("unregister_netisr: bad isr number: %d\n", num));
  132: 
  133:     /* XXX JH */
  134:     return (0);
  135: }
  136: 
  137: /*
  138:  * Return message port for default handler thread on CPU 0.
  139:  */
  140: lwkt_port_t
  141: cpu0_portfn(struct mbuf *m)
  142: {
  143:     return (&netisr_cpu[0].td_msgport);
  144: }
  145: 
  146: /* ARGSUSED */
  147: lwkt_port_t
  148: cpu0_soport(struct socket *so __unused, struct sockaddr *nam __unused)
  149: {
  150:     return (&netisr_cpu[0].td_msgport);
  151: }
  152: 
  153: /*
  154:  * This function is used to call the netisr handler from the appropriate
  155:  * netisr thread for polling and other purposes.
  156:  */
  157: void
  158: schednetisr(int num)
  159: {
  160:     struct netisr *ni = &netisrs[num];
  161:     struct netmsg *pmsg;
  162:     lwkt_port_t port = &netisr_cpu[0].td_msgport;
  163: 
  164:     KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
  165: 	("schednetisr: bad isr %d", num));
  166: 
  167:     if (!(pmsg = malloc(sizeof(struct netmsg), M_LWKTMSG, M_NOWAIT)))
  168: 	return;
  169: 
  170:     lwkt_initmsg_rp(&pmsg->nm_lmsg, &netisr_afree_rport, CMD_NETMSG_POLL);
  171:     pmsg->nm_handler = ni->ni_handler;
  172:     lwkt_sendmsg(port, &pmsg->nm_lmsg);
  173: }