socket: Speed up soclose by avoiding putting the user thread into sleep
[dragonfly.git] / sys / sys / socketvar.h
index 1bf8e02..ab494be 100644 (file)
 #ifndef _SYS_QUEUE_H_
 #include <sys/queue.h>                 /* for TAILQ macros */
 #endif
-#ifndef _SYS_SELINFO_H_
-#include <sys/selinfo.h>               /* for struct selinfo */
+#ifndef _SYS_EVENT_H_
+#include <sys/event.h>                 /* for struct kqinfo */
+#endif
+#ifndef _SYS_THREAD_H_
+#include <sys/thread.h>                        /* for struct lwkt_token */
 #endif
 #ifndef _SYS_SOCKBUF_H_
 #include <sys/sockbuf.h>
 
 #if defined(_KERNEL) || defined(_KERNEL_STRUCTURES)
 
+#ifndef _NET_NETMSG_H_
+#include <net/netmsg.h>
+#endif
+
 struct accept_filter;
 
 /*
  * Signaling socket buffers contain additional elements for locking
  * and signaling conditions.  These are used primarily by sockets.
+ *
+ * WARNING: See partial clearing of fields in kern/uipc_socket.c
+ *         sorflush() and sowflush().
  */
 struct signalsockbuf {
        struct sockbuf sb;
-       struct selinfo ssb_sel; /* process selecting read/write */
-       short   ssb_flags;      /* flags, see below */
-       short   ssb_timeo;      /* timeout for read/write */
+       struct kqinfo ssb_kq;   /* process selecting read/write */
+       uint32_t ssb_flags;     /* flags, see below (use atomic ops) */
+       u_int   ssb_timeo;      /* timeout for read/write */
        long    ssb_lowat;      /* low water mark */
        u_long  ssb_hiwat;      /* high water mark / max actual char count */
        u_long  ssb_mbmax;      /* max chars of mbufs to use */
+       struct lwkt_token ssb_token; /* frontend/backend serializer */
 };
 
 #define ssb_cc         sb.sb_cc        /* commonly used fields */
 #define ssb_mb         sb.sb_mb        /* commonly used fields */
 #define ssb_mbcnt      sb.sb_mbcnt     /* commonly used fields */
 
-#define        SSB_LOCK        0x01            /* lock on data queue */
-#define        SSB_WANT        0x02            /* someone is waiting to lock */
-#define        SSB_WAIT        0x04            /* someone is waiting for data/space */
-#define        SSB_ASYNC       0x10            /* ASYNC I/O, need signals */
-#define        SSB_UPCALL      0x20            /* someone wants an upcall */
-#define        SSB_NOINTR      0x40            /* operations not interruptible */
-#define SSB_AIO                0x80            /* AIO operations queued */
-#define SSB_KNOTE      0x100           /* kernel note attached */
-#define SSB_MEVENT     0x200           /* need message event notification */
-#define SSB_STOP       0x400           /* backpressure indicator */
-#define        SSB_AUTOSIZE    0x800           /* automatically size socket buffer */
+#define        SSB_LOCK        0x0001          /* lock on data queue */
+#define        SSB_WANT        0x0002          /* someone is waiting to lock */
+#define        SSB_WAIT        0x0004          /* someone is waiting for data/space */
+#define        SSB_ASYNC       0x0010          /* ASYNC I/O, need signals */
+#define        SSB_UPCALL      0x0020          /* someone wants an upcall */
+#define        SSB_NOINTR      0x0040          /* operations not interruptible */
+/*#define SSB_AIO      0x0080*/        /* AIO operations queued */
+#define SSB_KNOTE      0x0100          /* kernel note attached */
+#define SSB_MEVENT     0x0200          /* need message event notification */
+#define SSB_STOP       0x0400          /* backpressure indicator */
+#define        SSB_AUTOSIZE    0x0800          /* automatically size socket buffer */
 #define SSB_AUTOLOWAT  0x1000          /* automatically scale lowat */
+#define SSB_WAKEUP     0x2000          /* wakeup event race */
+
+#define SSB_CLEAR_MASK (SSB_ASYNC | SSB_UPCALL | SSB_STOP | \
+                        SSB_AUTOSIZE | SSB_AUTOLOWAT)
+
+#define SSB_NOTIFY_MASK        (SSB_WAIT | SSB_ASYNC | SSB_UPCALL | \
+                        SSB_KNOTE | SSB_MEVENT)
 
 /*
  * Per-socket kernel structure.  Contains universal send and receive queues,
@@ -128,17 +146,25 @@ struct socket {
        struct  ucred *so_cred;         /* user credentials */
        /* NB: generation count must not be first; easiest to make it last. */
        void    *so_emuldata;           /* private data for emulators */
+       int     so_refs;                /* shutdown refs */
        struct  so_accf { 
                struct  accept_filter *so_accept_filter;
                void    *so_accept_filter_arg;  /* saved filter args */
                char    *so_accept_filter_str;  /* saved user args */
        } *so_accf;
+
+       struct netmsg_base so_clomsg;
 };
 
 #endif
 
 /*
  * Socket state bits.
+ *
+ * NOTE: The following states are interlocked with so_refs:
+ *
+ *     SS_NOFDREF      so_refs while not set
+ *     (so_pcb)        so_refs while set
  */
 #define        SS_NOFDREF              0x0001  /* no file table ref any more */
 #define        SS_ISCONNECTED          0x0002  /* socket connected to a peer */
@@ -148,7 +174,7 @@ struct socket {
 #define        SS_CANTRCVMORE          0x0020  /* can't receive more data from peer */
 #define        SS_RCVATMARK            0x0040  /* at mark on input */
 
-#define        SS_ABORTING             0x0100  /* so_abort() in progress */
+#define        SS_ASSERTINPROG         0x0100  /* sonewconn race debugging */
 #define        SS_ASYNC                0x0200  /* async i/o notify */
 #define        SS_ISCONFIRMING         0x0400  /* deciding to accept connection req */
 
@@ -182,8 +208,8 @@ struct      xsocket {
                u_long  sb_mbcnt;
                u_long  sb_mbmax;
                long    sb_lowat;
+               u_int   sb_timeo;
                short   sb_flags;
-               short   sb_timeo;
        } so_rcv, so_snd;
        uid_t   so_uid;         /* XXX */
 };
@@ -211,11 +237,16 @@ struct    xsocket {
 
 /*
  * Do we need to notify the other side when I/O is possible?
+ *
+ * NOTE: Interlock for ssb_wait/wakeup.  The protocol side will set
+ *      SSB_WAKEUP asynchronously and this can race, so if it isn't
+ *      set we have to go through the full-on notification check.
+ *      If it is set but no waiting ever takes place it simply
+ *      remains set.
  */
-#define        ssb_notify(ssb)                                 \
-       (((ssb)->ssb_flags &                            \
-       (SSB_WAIT | SSB_ASYNC | SSB_UPCALL |            \
-       SSB_AIO | SSB_KNOTE | SSB_MEVENT)))
+#define ssb_notify(ssb)                                        \
+           (((ssb)->ssb_flags & SSB_NOTIFY_MASK) ||    \
+            ((ssb)->ssb_flags & SSB_WAKEUP) == 0)
 
 /* do we have to send all at once on a socket? */
 
@@ -262,25 +293,27 @@ ssb_space(struct signalsockbuf *ssb)
        ((ssb_space(ssb) <= 0) ? 0 : sbappendcontrol(&(ssb)->sb, m, control))
 
 #define ssb_insert_knote(ssb, kn) {                                    \
-        SLIST_INSERT_HEAD(&(ssb)->ssb_sel.si_note, kn, kn_selnext);    \
-       (ssb)->ssb_flags |= SSB_KNOTE;                                  \
+       knote_insert(&(ssb)->ssb_kq.ki_note, kn);                       \
+       atomic_set_int(&(ssb)->ssb_flags, SSB_KNOTE);                   \
 }
 
 #define ssb_remove_knote(ssb, kn) {                                    \
-        SLIST_REMOVE(&(ssb)->ssb_sel.si_note, kn, knote, kn_selnext);  \
-       if (SLIST_EMPTY(&(ssb)->ssb_sel.si_note))                       \
-               (ssb)->ssb_flags &= ~SSB_KNOTE;                         \
+       knote_remove(&(ssb)->ssb_kq.ki_note, kn);                       \
+       if (SLIST_EMPTY(&(ssb)->ssb_kq.ki_note))                        \
+               atomic_clear_int(&(ssb)->ssb_flags, SSB_KNOTE);         \
 }
 
-#define        sorwakeup(so)   do { \
-                         if (ssb_notify(&(so)->so_rcv)) \
-                           sowakeup((so), &(so)->so_rcv); \
-                       } while (0)
+#define        sorwakeup(so)                                           \
+       do {                                                    \
+               if (ssb_notify(&(so)->so_rcv))                  \
+                       sowakeup((so), &(so)->so_rcv);          \
+       } while (0)
 
-#define        sowwakeup(so)   do { \
-                         if (ssb_notify(&(so)->so_snd)) \
-                           sowakeup((so), &(so)->so_snd); \
-                       } while (0)
+#define        sowwakeup(so)                                           \
+       do {                                                    \
+               if (ssb_notify(&(so)->so_snd))                  \
+                       sowakeup((so), &(so)->so_snd);          \
+       } while (0)
 
 #ifdef _KERNEL
 
@@ -371,7 +404,6 @@ int soconnect (struct socket *so, struct sockaddr *nam, struct thread *td);
 int    soconnect2 (struct socket *so1, struct socket *so2);
 int    socreate (int dom, struct socket **aso, int type, int proto,
            struct thread *td);
-void   sodealloc (struct socket *so);
 int    sodisconnect (struct socket *so);
 void   sofree (struct socket *so);
 int    sogetopt (struct socket *so, struct sockopt *sopt);
@@ -411,6 +443,9 @@ int sosend (struct socket *so, struct sockaddr *addr, struct uio *uio,
 int    sosendudp (struct socket *so, struct sockaddr *addr, struct uio *uio,
                    struct mbuf *top, struct mbuf *control, int flags,
                    struct thread *td);
+int    sosendtcp (struct socket *so, struct sockaddr *addr, struct uio *uio,
+                   struct mbuf *top, struct mbuf *control, int flags,
+                   struct thread *td);
 int    sosetopt (struct socket *so, struct sockopt *sopt);
 int    soshutdown (struct socket *so, int how);
 void   sotoxsocket (struct socket *so, struct xsocket *xso);