diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/kern/kern_descrip.c | 2 | ||||
-rw-r--r-- | sys/kern/uipc_sockbuf.c | 82 | ||||
-rw-r--r-- | sys/kern/uipc_socket2.c | 82 | ||||
-rw-r--r-- | sys/net/rtsock.c | 4 | ||||
-rw-r--r-- | sys/netinet/accf_data.c | 5 | ||||
-rw-r--r-- | sys/netinet/accf_http.c | 12 | ||||
-rw-r--r-- | sys/netinet/tcp_input.c | 6 | ||||
-rw-r--r-- | sys/netinet/tcp_reass.c | 6 | ||||
-rw-r--r-- | sys/netkey/keysock.c | 4 | ||||
-rw-r--r-- | sys/sys/filedesc.h | 17 | ||||
-rw-r--r-- | sys/sys/socketvar.h | 53 |
11 files changed, 227 insertions, 46 deletions
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index 65f85d5..c645a56 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -113,6 +113,7 @@ struct filelist filehead; /* head of list of open files */ int nfiles; /* actual number of open files */ extern int cmask; struct sx filelist_lock; /* sx to protect filelist */ +struct sx sigio_lock; /* sx to protect pointers to sigio */ /* * System calls on descriptors. @@ -2186,4 +2187,5 @@ filelistinit(dummy) NULL, NULL, UMA_ALIGN_PTR, 0); sx_init(&filelist_lock, "filelist lock"); + sx_init(&sigio_lock, "sigio lock"); } diff --git a/sys/kern/uipc_sockbuf.c b/sys/kern/uipc_sockbuf.c index 1a8afd3..56fb012 100644 --- a/sys/kern/uipc_sockbuf.c +++ b/sys/kern/uipc_sockbuf.c @@ -107,11 +107,46 @@ soisconnecting(so) } void +soisconnected_locked(so) + struct socket *so; +{ + struct socket *head = so->so_head; + + SIGIO_ASSERT(SX_SLOCKED); /* XXX */ + so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING|SS_ISCONFIRMING); + so->so_state |= SS_ISCONNECTED; + if (head && (so->so_state & SS_INCOMP)) { + if ((so->so_options & SO_ACCEPTFILTER) != 0) { + so->so_upcall = head->so_accf->so_accept_filter->accf_callback; + so->so_upcallarg = head->so_accf->so_accept_filter_arg; + so->so_rcv.sb_flags |= SB_UPCALL; + so->so_options &= ~SO_ACCEPTFILTER; + SIGIO_SUNLOCK(); /* XXX */ + so->so_upcall(so, so->so_upcallarg, 0); + SIGIO_SLOCK(); + return; + } + TAILQ_REMOVE(&head->so_incomp, so, so_list); + head->so_incqlen--; + so->so_state &= ~SS_INCOMP; + TAILQ_INSERT_TAIL(&head->so_comp, so, so_list); + so->so_state |= SS_COMP; + sorwakeup_locked(head); + wakeup_one(&head->so_timeo); + } else { + wakeup(&so->so_timeo); + sorwakeup_locked(so); + sowwakeup_locked(so); + } +} + +void soisconnected(so) struct socket *so; { struct socket *head = so->so_head; + SIGIO_SLOCK(); so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING|SS_ISCONFIRMING); so->so_state |= SS_ISCONNECTED; if (head && (so->so_state & SS_INCOMP)) { @@ -120,6 +155,7 @@ soisconnected(so) so->so_upcallarg = head->so_accf->so_accept_filter_arg; so->so_rcv.sb_flags |= SB_UPCALL; so->so_options &= ~SO_ACCEPTFILTER; + SIGIO_SUNLOCK(); so->so_upcall(so, so->so_upcallarg, 0); return; } @@ -129,13 +165,14 @@ soisconnected(so) TAILQ_INSERT_TAIL(&head->so_comp, so, so_list); head->so_qlen++; so->so_state |= SS_COMP; - sorwakeup(head); + sorwakeup_locked(head); wakeup_one(&head->so_timeo); } else { wakeup(&so->so_timeo); - sorwakeup(so); - sowwakeup(so); + sorwakeup_locked(so); + sowwakeup_locked(so); } + SIGIO_SUNLOCK(); } void @@ -143,23 +180,36 @@ soisdisconnecting(so) register struct socket *so; { + SIGIO_SLOCK(); so->so_state &= ~SS_ISCONNECTING; so->so_state |= (SS_ISDISCONNECTING|SS_CANTRCVMORE|SS_CANTSENDMORE); wakeup((caddr_t)&so->so_timeo); - sowwakeup(so); - sorwakeup(so); + sowwakeup_locked(so); + sorwakeup_locked(so); + SIGIO_SUNLOCK(); } void -soisdisconnected(so) +soisdisconnected_locked(so) register struct socket *so; { + SIGIO_ASSERT(SX_LOCKED); so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING); so->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE|SS_ISDISCONNECTED); wakeup((caddr_t)&so->so_timeo); - sowwakeup(so); - sorwakeup(so); + sowwakeup_locked(so); + sorwakeup_locked(so); +} + +void +soisdisconnected(so) + register struct socket *so; +{ + + SIGIO_SLOCK(); + soisdisconnected_locked(so); + SIGIO_SUNLOCK(); } /* @@ -215,9 +265,9 @@ sonewconn(head, connstatus) head->so_incqlen++; } if (connstatus) { - sorwakeup(head); - wakeup((caddr_t)&head->so_timeo); - so->so_state |= connstatus; + SIGIO_SLOCK(); + sorwakeup_locked(head); + SIGIO_SUNLOCK(); } return (so); } @@ -237,8 +287,10 @@ socantsendmore(so) struct socket *so; { + SIGIO_SLOCK(); so->so_state |= SS_CANTSENDMORE; - sowwakeup(so); + sowwakeup_locked(so); + SIGIO_SUNLOCK(); } void @@ -246,8 +298,10 @@ socantrcvmore(so) struct socket *so; { + SIGIO_SLOCK(); so->so_state |= SS_CANTRCVMORE; - sorwakeup(so); + sorwakeup_locked(so); + SIGIO_SUNLOCK(); } /* @@ -296,6 +350,8 @@ sowakeup(so, sb) register struct socket *so; register struct sockbuf *sb; { + SIGIO_ASSERT(SX_LOCKED); + selwakeup(&sb->sb_sel); sb->sb_flags &= ~SB_SEL; if (sb->sb_flags & SB_WAIT) { diff --git a/sys/kern/uipc_socket2.c b/sys/kern/uipc_socket2.c index 1a8afd3..56fb012 100644 --- a/sys/kern/uipc_socket2.c +++ b/sys/kern/uipc_socket2.c @@ -107,11 +107,46 @@ soisconnecting(so) } void +soisconnected_locked(so) + struct socket *so; +{ + struct socket *head = so->so_head; + + SIGIO_ASSERT(SX_SLOCKED); /* XXX */ + so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING|SS_ISCONFIRMING); + so->so_state |= SS_ISCONNECTED; + if (head && (so->so_state & SS_INCOMP)) { + if ((so->so_options & SO_ACCEPTFILTER) != 0) { + so->so_upcall = head->so_accf->so_accept_filter->accf_callback; + so->so_upcallarg = head->so_accf->so_accept_filter_arg; + so->so_rcv.sb_flags |= SB_UPCALL; + so->so_options &= ~SO_ACCEPTFILTER; + SIGIO_SUNLOCK(); /* XXX */ + so->so_upcall(so, so->so_upcallarg, 0); + SIGIO_SLOCK(); + return; + } + TAILQ_REMOVE(&head->so_incomp, so, so_list); + head->so_incqlen--; + so->so_state &= ~SS_INCOMP; + TAILQ_INSERT_TAIL(&head->so_comp, so, so_list); + so->so_state |= SS_COMP; + sorwakeup_locked(head); + wakeup_one(&head->so_timeo); + } else { + wakeup(&so->so_timeo); + sorwakeup_locked(so); + sowwakeup_locked(so); + } +} + +void soisconnected(so) struct socket *so; { struct socket *head = so->so_head; + SIGIO_SLOCK(); so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING|SS_ISCONFIRMING); so->so_state |= SS_ISCONNECTED; if (head && (so->so_state & SS_INCOMP)) { @@ -120,6 +155,7 @@ soisconnected(so) so->so_upcallarg = head->so_accf->so_accept_filter_arg; so->so_rcv.sb_flags |= SB_UPCALL; so->so_options &= ~SO_ACCEPTFILTER; + SIGIO_SUNLOCK(); so->so_upcall(so, so->so_upcallarg, 0); return; } @@ -129,13 +165,14 @@ soisconnected(so) TAILQ_INSERT_TAIL(&head->so_comp, so, so_list); head->so_qlen++; so->so_state |= SS_COMP; - sorwakeup(head); + sorwakeup_locked(head); wakeup_one(&head->so_timeo); } else { wakeup(&so->so_timeo); - sorwakeup(so); - sowwakeup(so); + sorwakeup_locked(so); + sowwakeup_locked(so); } + SIGIO_SUNLOCK(); } void @@ -143,23 +180,36 @@ soisdisconnecting(so) register struct socket *so; { + SIGIO_SLOCK(); so->so_state &= ~SS_ISCONNECTING; so->so_state |= (SS_ISDISCONNECTING|SS_CANTRCVMORE|SS_CANTSENDMORE); wakeup((caddr_t)&so->so_timeo); - sowwakeup(so); - sorwakeup(so); + sowwakeup_locked(so); + sorwakeup_locked(so); + SIGIO_SUNLOCK(); } void -soisdisconnected(so) +soisdisconnected_locked(so) register struct socket *so; { + SIGIO_ASSERT(SX_LOCKED); so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING); so->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE|SS_ISDISCONNECTED); wakeup((caddr_t)&so->so_timeo); - sowwakeup(so); - sorwakeup(so); + sowwakeup_locked(so); + sorwakeup_locked(so); +} + +void +soisdisconnected(so) + register struct socket *so; +{ + + SIGIO_SLOCK(); + soisdisconnected_locked(so); + SIGIO_SUNLOCK(); } /* @@ -215,9 +265,9 @@ sonewconn(head, connstatus) head->so_incqlen++; } if (connstatus) { - sorwakeup(head); - wakeup((caddr_t)&head->so_timeo); - so->so_state |= connstatus; + SIGIO_SLOCK(); + sorwakeup_locked(head); + SIGIO_SUNLOCK(); } return (so); } @@ -237,8 +287,10 @@ socantsendmore(so) struct socket *so; { + SIGIO_SLOCK(); so->so_state |= SS_CANTSENDMORE; - sowwakeup(so); + sowwakeup_locked(so); + SIGIO_SUNLOCK(); } void @@ -246,8 +298,10 @@ socantrcvmore(so) struct socket *so; { + SIGIO_SLOCK(); so->so_state |= SS_CANTRCVMORE; - sorwakeup(so); + sorwakeup_locked(so); + SIGIO_SUNLOCK(); } /* @@ -296,6 +350,8 @@ sowakeup(so, sb) register struct socket *so; register struct sockbuf *sb; { + SIGIO_ASSERT(SX_LOCKED); + selwakeup(&sb->sb_sel); sb->sb_flags &= ~SB_SEL; if (sb->sb_flags & SB_WAIT) { diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c index ea9f4d3..f49f3df 100644 --- a/sys/net/rtsock.c +++ b/sys/net/rtsock.c @@ -146,8 +146,10 @@ rts_attach(struct socket *so, int proto, struct thread *td) } rp->rcb_faddr = &route_src; route_cb.any_count++; - soisconnected(so); + SIGIO_SLOCK(); + soisconnected_locked(so); so->so_options |= SO_USELOOPBACK; + SIGIO_SUNLOCK(); splx(s); return 0; } diff --git a/sys/netinet/accf_data.c b/sys/netinet/accf_data.c index b66e1c7..d38b165 100644 --- a/sys/netinet/accf_data.c +++ b/sys/netinet/accf_data.c @@ -56,12 +56,15 @@ static void sohasdata(struct socket *so, void *arg, int waitflag) { + SIGIO_SLOCK(); if (!soreadable(so)) { + SIGIO_SUNLOCK(); return; } so->so_upcall = NULL; so->so_rcv.sb_flags &= ~SB_UPCALL; - soisconnected(so); + soisconnected_locked(so); + SIGIO_SUNLOCK(); return; } diff --git a/sys/netinet/accf_http.c b/sys/netinet/accf_http.c index a9a8fb0..73c9af2 100644 --- a/sys/netinet/accf_http.c +++ b/sys/netinet/accf_http.c @@ -197,9 +197,11 @@ sohashttpget(struct socket *so, void *arg, int waitflag) fallout: DPRINT("fallout"); + SIGIO_SLOCK(); so->so_upcall = NULL; so->so_rcv.sb_flags &= ~SB_UPCALL; - soisconnected(so); + soisconnected_locked(so); + SIGIO_SUNLOCK(); return; } @@ -269,9 +271,11 @@ readmore: fallout: DPRINT("fallout"); + SIGIO_SLOCK(); so->so_upcall = NULL; so->so_rcv.sb_flags &= ~SB_UPCALL; - soisconnected(so); + soisconnected_locked(so); + SIGIO_SUNLOCK(); return; } @@ -339,8 +343,10 @@ readmore: return; gotit: + SIGIO_SLOCK(); so->so_upcall = NULL; so->so_rcv.sb_flags &= ~SB_UPCALL; - soisconnected(so); + soisconnected_locked(so); + SIGIO_SUNLOCK(); return; } diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index c7533e6..09be5d2 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -1842,10 +1842,14 @@ process_ACK: * specification, but if we don't get a FIN * we'll hang forever. */ + SIGIO_SLOCK(); if (so->so_state & SS_CANTRCVMORE) { - soisdisconnected(so); + soisdisconnected_locked(so); + SIGIO_SUNLOCK(); callout_reset(tp->tt_2msl, tcp_maxidle, tcp_timer_2msl, tp); + } else { + SIGIO_SUNLOCK(); } tp->t_state = TCPS_FIN_WAIT_2; } diff --git a/sys/netinet/tcp_reass.c b/sys/netinet/tcp_reass.c index c7533e6..09be5d2 100644 --- a/sys/netinet/tcp_reass.c +++ b/sys/netinet/tcp_reass.c @@ -1842,10 +1842,14 @@ process_ACK: * specification, but if we don't get a FIN * we'll hang forever. */ + SIGIO_SLOCK(); if (so->so_state & SS_CANTRCVMORE) { - soisdisconnected(so); + soisdisconnected_locked(so); + SIGIO_SUNLOCK(); callout_reset(tp->tt_2msl, tcp_maxidle, tcp_timer_2msl, tp); + } else { + SIGIO_SUNLOCK(); } tp->t_state = TCPS_FIN_WAIT_2; } diff --git a/sys/netkey/keysock.c b/sys/netkey/keysock.c index 6d00e48..5b733cd73 100644 --- a/sys/netkey/keysock.c +++ b/sys/netkey/keysock.c @@ -428,8 +428,10 @@ key_attach(struct socket *so, int proto, struct thread *td) key_cb.any_count++; kp->kp_raw.rcb_laddr = &key_src; kp->kp_raw.rcb_faddr = &key_dst; - soisconnected(so); + SIGIO_SLOCK(); + soisconnected_locked(so); so->so_options |= SO_USELOOPBACK; + SIGIO_SUNLOCK(); splx(s); return 0; diff --git a/sys/sys/filedesc.h b/sys/sys/filedesc.h index d2d108c..68611a3 100644 --- a/sys/sys/filedesc.h +++ b/sys/sys/filedesc.h @@ -37,8 +37,9 @@ #ifndef _SYS_FILEDESC_H_ #define _SYS_FILEDESC_H_ -#include <sys/_lock.h> -#include <sys/_mutex.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/sx.h> #include <sys/queue.h> /* @@ -134,12 +135,24 @@ SLIST_HEAD(sigiolst, sigio); #define FILEDESC_LOCK_DESC "filedesc structure" +extern struct sx sigio_lock; + /* Lock a file descriptor table. */ #define FILEDESC_LOCK(fd) mtx_lock(&(fd)->fd_mtx) #define FILEDESC_UNLOCK(fd) mtx_unlock(&(fd)->fd_mtx) #define FILEDESC_LOCKED(fd) mtx_owned(&(fd)->fd_mtx) #define FILEDESC_LOCK_ASSERT(fd, type) mtx_assert(&(fd)->fd_mtx, (type)) +/* + * Lock the pointers for a sigio object in the underlying objects of + * a file descriptor. + */ +#define SIGIO_SLOCK() sx_slock(&sigio_lock) +#define SIGIO_XLOCK() sx_xlock(&sigio_lock) +#define SIGIO_SUNLOCK() sx_sunlock(&sigio_lock) +#define SIGIO_XUNLOCK() sx_xunlock(&sigio_lock) +#define SIGIO_ASSERT(what) sx_assert(&sigio_lock, what) + int closef(struct file *fp, struct thread *p); int dupfdopen(struct thread *td, struct filedesc *fdp, int indx, int dfd, int mode, int error); diff --git a/sys/sys/socketvar.h b/sys/sys/socketvar.h index 3bfcde2..748ce7d 100644 --- a/sys/sys/socketvar.h +++ b/sys/sys/socketvar.h @@ -38,6 +38,10 @@ #define _SYS_SOCKETVAR_H_ #include <sys/queue.h> /* for TAILQ macros */ +#include <sys/filedesc.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/sx.h> #include <sys/selinfo.h> /* for struct selinfo */ #include <vm/uma.h> @@ -51,6 +55,19 @@ typedef u_quad_t so_gen_t; struct accept_filter; +/* + * List of locks: + * (c) const, inited in either socreate() or sonewconn() + * (m) sb_mtx mutex + * (mr) so_rcv.sb_mtx mutex + * (sg) sigio_lock sx + * (sh) sohead_lock sx + * + * Lock of so_rcv.sb_mtx can duplicate, provided that sohead_lock + * is exclusively locked. + * + * Brackets mean that this data is not protected yet. + */ struct socket { int so_count; /* reference count */ short so_type; /* generic type, see socket.h */ @@ -80,7 +97,7 @@ struct socket { short so_qlimit; /* max number queued connections */ short so_timeo; /* connection timeout */ u_short so_error; /* error affecting connection */ - struct sigio *so_sigio; /* information for async I/O or + struct sigio *so_sigio; /* [sg] information for async I/O or out of band data (SIGURG) */ u_long so_oobmark; /* chars to oob mark */ TAILQ_HEAD(, aiocblist) so_aiojobq; /* AIO ops waiting on socket */ @@ -267,15 +284,29 @@ struct xsocket { sofree(so); \ } while(0) -#define sorwakeup(so) do { \ - if (sb_notify(&(so)->so_rcv)) \ - sowakeup((so), &(so)->so_rcv); \ - } while (0) - -#define sowwakeup(so) do { \ - if (sb_notify(&(so)->so_snd)) \ - sowakeup((so), &(so)->so_snd); \ - } while (0) +#define sorwakeup_locked(so) do { \ + SIGIO_ASSERT(SX_SLOCKED); /* XXX */ \ + if (sb_notify(&(so)->so_rcv)) \ + sowakeup((so), &(so)->so_rcv); \ + } while (0) + +#define sorwakeup(so) do { \ + SIGIO_SLOCK(); \ + sorwakeup_locked(so); \ + SIGIO_SUNLOCK(); \ + } while (0) + +#define sowwakeup_locked(so) do { \ + SIGIO_ASSERT(SX_SLOCKED); /* XXX */ \ + if (sb_notify(&(so)->so_snd)) \ + sowakeup((so), &(so)->so_snd); \ + } while (0) + +#define sowwakeup(so) do { \ + SIGIO_SLOCK(); \ + sowwakeup_locked(so); \ + SIGIO_SUNLOCK(); \ + } while (0) #ifdef _KERNEL @@ -387,8 +418,10 @@ void sofree(struct socket *so); int sogetopt(struct socket *so, struct sockopt *sopt); void sohasoutofband(struct socket *so); void soisconnected(struct socket *so); +void soisconnected_locked(struct socket *so); void soisconnecting(struct socket *so); void soisdisconnected(struct socket *so); +void soisdisconnected_locked(struct socket *so); void soisdisconnecting(struct socket *so); int solisten(struct socket *so, int backlog, struct thread *td); struct socket * |