Index: i386/include/in_cksum.h =================================================================== RCS file: /home/ncvs/src/sys/i386/include/in_cksum.h,v retrieving revision 1.9 diff -u -u -r1.9 in_cksum.h --- i386/include/in_cksum.h 2000/05/06 18:18:32 1.9 +++ i386/include/in_cksum.h 2000/09/09 10:48:29 @@ -39,6 +39,10 @@ #ifndef _MACHINE_IN_CKSUM_H_ #define _MACHINE_IN_CKSUM_H_ 1 +/* + * MP safe (alfred) + */ + #include #define in_cksum(m, len) in_cksum_skip(m, len, 0) Index: kern/kern_prot.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_prot.c,v retrieving revision 1.63 diff -u -u -r1.63 kern_prot.c --- kern/kern_prot.c 2000/09/05 22:10:22 1.63 +++ kern/kern_prot.c 2000/09/10 02:35:00 @@ -1150,7 +1150,7 @@ crfree(cr) struct ucred *cr; { - if (--cr->cr_ref == 0) { + if (atomic_subtract_short(&cr->cr_ref, 1) == 0) { /* * Some callers of crget(), such as nfs_statfs(), * allocate a temporary credential, but don't Index: kern/kern_resource.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_resource.c,v retrieving revision 1.64 diff -u -u -r1.64 kern_resource.c --- kern/kern_resource.c 2000/09/18 17:03:03 1.64 +++ kern/kern_resource.c 2000/09/28 17:28:31 @@ -64,6 +64,7 @@ static MALLOC_DEFINE(M_UIDINFO, "uidinfo", "uidinfo structures"); #define UIHASH(uid) (&uihashtbl[(uid) & uihash]) +static struct mtx uidhash_mtx; static LIST_HEAD(uihashhead, uidinfo) *uihashtbl; static u_long uihash; /* size of hash table - 1 */ @@ -659,7 +660,9 @@ void uihashinit() { + uihashtbl = hashinit(maxproc / 16, M_UIDINFO, &uihash); + mtx_init(&uidhash_mtx, "uidinfo", MTX_DEF); } static struct uidinfo * @@ -669,6 +672,7 @@ struct uihashhead *uipp; struct uidinfo *uip; + mtx_assert(&uidhash_mtx, MA_OWNED); uipp = UIHASH(uid); LIST_FOREACH(uip, uipp, ui_hash) if (uip->ui_uid == uid) @@ -681,21 +685,10 @@ uicreate(uid) uid_t uid; { - struct uidinfo *uip, *norace; + struct uidinfo *uip; - MALLOC(uip, struct uidinfo *, sizeof(*uip), M_UIDINFO, M_NOWAIT); - if (uip == NULL) { - MALLOC(uip, struct uidinfo *, sizeof(*uip), M_UIDINFO, M_WAITOK); - /* - * if we M_WAITOK we must look afterwards or risk - * redundant entries - */ - norace = uilookup(uid); - if (norace != NULL) { - FREE(uip, M_UIDINFO); - return (norace); - } - } + mtx_assert(&uidhash_mtx, MA_OWNED); + MALLOC(uip, struct uidinfo *, sizeof(*uip), M_UIDINFO, M_WAITOK); LIST_INSERT_HEAD(UIHASH(uid), uip, ui_hash); uip->ui_uid = uid; uip->ui_proccnt = 0; @@ -710,10 +703,12 @@ { struct uidinfo *uip; + mtx_enter(&uidhash_mtx, MTX_DEF); uip = uilookup(uid); if (uip == NULL) uip = uicreate(uid); uip->ui_ref++; + mtx_exit(&uidhash_mtx, MTX_DEF); return (uip); } @@ -730,7 +725,9 @@ if (uip->ui_proccnt != 0) printf("freeing uidinfo: uid = %d, proccnt = %ld\n", uip->ui_uid, uip->ui_proccnt); + mtx_enter(&uidhash_mtx, MTX_DEF); LIST_REMOVE(uip, ui_hash); + mtx_exit(&uidhash_mtx, MTX_DEF); FREE(uip, M_UIDINFO); return (1); } @@ -769,11 +766,14 @@ rlim_t new; int s; + mtx_enter(&Giant, MTX_DEF); + s = splnet(); new = uip->ui_sbsize + to - *hiwat; /* don't allow them to exceed max, but allow subtraction */ if (to > *hiwat && new > max) { splx(s); + mtx_exit(&Giant, MTX_DEF); return (0); } uip->ui_sbsize = new; @@ -781,5 +781,6 @@ if (uip->ui_sbsize < 0) printf("negative sbsize for uid = %d\n", uip->ui_uid); splx(s); + mtx_exit(&Giant, MTX_DEF); return (1); } Index: kern/uipc_domain.c =================================================================== RCS file: /home/ncvs/src/sys/kern/uipc_domain.c,v retrieving revision 1.22 diff -u -u -r1.22 uipc_domain.c --- kern/uipc_domain.c 1999/08/28 00:46:21 1.22 +++ kern/uipc_domain.c 2000/09/28 07:03:53 @@ -64,6 +64,7 @@ static void pffasttimo __P((void *)); static void pfslowtimo __P((void *)); +mtx_t domain_mtx; struct domain *domains; /* @@ -109,30 +110,21 @@ dp = (struct domain *)data; s = splnet(); + mtx_enter(&domain_mtx, MTX_DEF); + net_init_domain(dp); dp->dom_next = domains; domains = dp; + mtx_exit(&domain_mtx, MTX_DEF); splx(s); - net_init_domain(dp); } /* ARGSUSED*/ static void domaininit(void *dummy) { - /* - * Before we do any setup, make sure to initialize the - * zone allocator we get struct sockets from. The obvious - * maximum number of sockets is `maxfiles', but it is possible - * to have a socket without an open file (e.g., a connection waiting - * to be accept(2)ed). Rather than think up and define a - * better value, we just use nmbclusters, since that's what people - * are told to increase first when the network runs out of memory. - * Perhaps we should have two pools, one of unlimited size - * for use during socreate(), and one ZONE_INTERRUPT pool for - * use in sonewconn(). - */ - socket_zone = zinit("socket", sizeof(struct socket), maxsockets, - ZONE_INTERRUPT, 0); + + mtx_init(&socket_alloc_lock, "socket_zone, so_gencnt", MTX_DEF); + mtx_init(&domain_mtx, "protect adding new domains", MTX_DEF); if (max_linkhdr < 16) /* XXX */ max_linkhdr = 16; Index: kern/uipc_socket.c =================================================================== RCS file: /home/ncvs/src/sys/kern/uipc_socket.c,v retrieving revision 1.83 diff -u -u -r1.83 uipc_socket.c --- kern/uipc_socket.c 2000/09/28 04:41:22 1.83 +++ kern/uipc_socket.c 2000/09/28 08:43:16 @@ -76,11 +76,16 @@ { 1, filt_sowattach, filt_sowdetach, filt_sowrite }, }; -struct vm_zone *socket_zone; +struct mtx socket_alloc_lock; /* protect socket_zone and so_gencnt */ +static long socket_alloc_via_malloc = 0; +static SLIST_HEAD(, socket) socket_freelst = + SLIST_HEAD_INITIALIZER(socket_freelst); + so_gen_t so_gencnt; /* generation count for sockets */ MALLOC_DEFINE(M_SONAME, "soname", "socket name"); MALLOC_DEFINE(M_PCB, "pcb", "protocol control block"); +MALLOC_DEFINE(M_SOCK, "socket", "socket data structure"); SYSCTL_DECL(_kern_ipc); @@ -109,15 +114,32 @@ { struct socket *so; - so = zalloci(socket_zone); - if (so) { - /* XXX race condition for reentrant kernel */ - bzero(so, sizeof *so); - so->so_gencnt = ++so_gencnt; - so->so_zone = socket_zone; - TAILQ_INIT(&so->so_aiojobq); + so = NULL; + mtx_enter(&socket_alloc_lock, MTX_DEF); + if (!SLIST_EMPTY(&socket_freelst)) { + so = SLIST_FIRST(&socket_freelst); + SLIST_REMOVE_HEAD(&socket_freelst, so_nextfree); + } else if (socket_alloc_via_malloc < maxsockets) { + MALLOC(so, struct socket *, sizeof(*so), M_SOCK, + waitok ? M_WAITOK : M_NOWAIT); + if (so != NULL) { + socket_alloc_via_malloc++; + bzero(so, sizeof(*so)); + SOCKBUF_LOCK_INIT(so->so_snd, "so->so_snd"); + SOCKBUF_LOCK_INIT(so->so_rcv, "so->so_rcv"); + TAILQ_INIT(&so->so_aiojobq); + TAILQ_INIT(&so->so_incomp); + TAILQ_INIT(&so->so_comp); + TAILQ_INIT(&so->so_aiojobq); + } } - return so; + if (so == NULL) + goto out; + + so->so_gencnt = ++so_gencnt; + + mtx_exit(&socket_alloc_lock, MTX_DEF); + return (so); } int @@ -153,8 +175,6 @@ if (so == 0) return (ENOBUFS); - TAILQ_INIT(&so->so_incomp); - TAILQ_INIT(&so->so_comp); so->so_type = type; so->so_cred = p->p_ucred; crhold(so->so_cred); @@ -188,7 +208,16 @@ struct socket *so; { - so->so_gencnt = ++so_gencnt; + KASSERT(!SOCK_OWNED(so), ("sodealloc: socket owned")); + +#define sodealloc_tailq_assert(tq) \ + KASSERT(TAILQ_FIRST(&tq) == NULL, ("sodealloc: " #tq)) + + sodealloc_tailq_assert(so->so_aiojobq); + sodealloc_tailq_assert(so->so_incomp); + sodealloc_tailq_assert(so->so_comp); + sodealloc_tailq_assert(so->so_aiojobq); + if (so->so_rcv.sb_hiwat) (void)chgsbsize(so->so_cred->cr_uidinfo, &so->so_rcv.sb_hiwat, 0, RLIM_INFINITY); @@ -205,7 +234,11 @@ FREE(so->so_accf, M_ACCF); } crfree(so->so_cred); - zfreei(so->so_zone, so); + + mtx_enter(&socket_alloc_lock, MTX_DEF); + so->so_gencnt = ++so_gencnt; + SLIST_INSERT_HEAD(&socket_freelst, so, so_nextfree); + mtx_exit(&socket_alloc_lock, MTX_DEF); } int @@ -222,11 +255,13 @@ splx(s); return (error); } + SOCKBUF_LOCK(&so->so_rcv, 0); if (TAILQ_EMPTY(&so->so_comp)) so->so_options |= SO_ACCEPTCONN; if (backlog < 0 || backlog > somaxconn) backlog = somaxconn; so->so_qlimit = backlog; + SOCKBUF_UNLOCK(&so->so_rcv, 0); splx(s); return (0); } @@ -275,7 +310,10 @@ int s = splnet(); /* conservative */ int error = 0; + mtx_enter(&Giant, MTX_DEF); funsetown(so->so_sigio); + mtx_exit(&Giant, MTX_DEF); + SOCK_LOCK(so, 0); if (so->so_options & SO_ACCEPTCONN) { struct socket *sp, *sonext; @@ -307,7 +345,7 @@ (so->so_state & SS_NBIO)) goto drop; while (so->so_state & SS_ISCONNECTED) { - error = tsleep((caddr_t)&so->so_timeo, + error = msleep((caddr_t)&so->so_timeo, SOCK_MTX(so), PSOCK | PCATCH, "soclos", so->so_linger * hz); if (error) break; @@ -321,16 +359,16 @@ error = error2; } discard: - if (so->so_state & SS_NOFDREF) - panic("soclose: NOFDREF"); + KASSERT((so->so_state & SS_NOFDREF) == 0, ("soclose: NOFDREF")); so->so_state |= SS_NOFDREF; + SOCK_UNLOCK(so); sofree(so); splx(s); return (error); } /* - * Must be called at splnet... + * Must be called with the socket locked */ int soabort(so) @@ -338,6 +376,7 @@ { int error; + KASSERT(SOCK_OWNED(so), ("soabort: socket not owned")); error = (*so->so_proto->pr_usrreqs->pru_abort)(so); if (error) { sofree(so); @@ -354,8 +393,8 @@ int s = splnet(); int error; - if ((so->so_state & SS_NOFDREF) == 0) - panic("soaccept: !NOFDREF"); + SOCK_LOCK(so); + KASSERT((so->so_state & SS_NOFDREF) != 0, ("soaccept: !NOFDREF")); so->so_state &= ~SS_NOFDREF; if ((so->so_state & SS_ISDISCONNECTED) == 0) error = (*so->so_proto->pr_usrreqs->pru_accept)(so, nam); @@ -365,6 +404,7 @@ error = 0; } splx(s); + SOCK_UNLOCK(so); return (error); } @@ -380,6 +420,7 @@ if (so->so_options & SO_ACCEPTCONN) return (EOPNOTSUPP); s = splnet(); + SOCK_LOCK(so); /* * If protocol is connection-based, can only connect once. * Otherwise, if connected, try to disconnect first. @@ -393,6 +434,7 @@ else error = (*so->so_proto->pr_usrreqs->pru_connect)(so, nam, p); splx(s); + SOCK_UNLOCK(so); return (error); } @@ -404,7 +446,9 @@ int s = splnet(); int error; + SOCK_LOCK(so); error = (*so1->so_proto->pr_usrreqs->pru_connect2)(so1, so2); + SOCK_UNLOCK(so); splx(s); return (error); } @@ -416,6 +460,7 @@ int s = splnet(); int error; + SOCK_LOCK(so); if ((so->so_state & SS_ISCONNECTED) == 0) { error = ENOTCONN; goto bad; @@ -426,6 +471,7 @@ } error = (*so->so_proto->pr_usrreqs->pru_disconnect)(so); bad: + SOCK_UNLOCK(so); splx(s); return (error); } @@ -490,8 +536,14 @@ p->p_stats->p_ru.ru_msgsnd++; if (control) clen = control->m_len; -#define snderr(errno) { error = errno; splx(s); goto release; } +#define snderr(errno) \ + do { \ + error = errno; \ + splx(s); \ + goto release; \ + } while(0) + SOCKBUF_LOCK(&so->so_snd, 0); restart: error = sblock(&so->so_snd, SBLOCKWAIT(flags)); if (error) @@ -540,6 +592,7 @@ goto restart; } splx(s); + SOCKBUF_UNLOCK(&so->so_snd, 0); mp = ⊤ space -= clen; do { @@ -551,10 +604,12 @@ if (flags & MSG_EOR) top->m_flags |= M_EOR; } else do { + SOCKBUF_UNLOCK(&so->so_snd, 0); if (top == 0) { MGETHDR(m, M_WAIT, MT_DATA); if (m == NULL) { error = ENOBUFS; + SOCKBUF_LOCK(&so->so_snd, 0); goto release; } mlen = MHLEN; @@ -564,6 +619,7 @@ MGET(m, M_WAIT, MT_DATA); if (m == NULL) { error = ENOBUFS; + SOCKBUF_LOCK(&so->so_snd, 0); goto release; } mlen = MLEN; @@ -590,8 +646,10 @@ m->m_len = len; *mp = m; top->m_pkthdr.len += len; - if (error) + if (error) { + SOCKBUF_LOCK(&so->so_snd, 0); goto release; + } mp = &m->m_next; if (resid <= 0) { if (flags & MSG_EOR) @@ -602,6 +660,7 @@ if (dontroute) so->so_options |= SO_DONTROUTE; s = splnet(); /* XXX */ + SOCKBUF_LOCK(&so->so_snd, 0); /* XXX */ /* * XXX all the SS_CANTSENDMORE checks previously * done could be out of date. We could have recieved @@ -640,6 +699,7 @@ release: sbunlock(&so->so_snd); out: + SOCKBUF_LOCK(&so->so_snd, 0); if (top) m_freem(top); if (control) @@ -711,9 +771,11 @@ (*pr->pr_usrreqs->pru_rcvd)(so, 0); restart: + SOCKBUF_LOCK(&so->so_rcv, 0); error = sblock(&so->so_rcv, SBLOCKWAIT(flags)); if (error) - return (error); + goto out; + s = splnet(); m = so->so_rcv.sb_mb; @@ -768,7 +830,7 @@ error = sbwait(&so->so_rcv); splx(s); if (error) - return (error); + goto release; goto restart; } dontblock: @@ -849,8 +911,10 @@ */ if (mp == 0) { splx(s); + SOCKBUF_UNLOCK(&so->so_rcv, 0); error = uiomove(mtod(m, caddr_t) + moff, (int)len, uio); s = splnet(); + SOCKBUF_LOCK(&so->so_rcv, 0); if (error) goto release; } else @@ -880,8 +944,21 @@ if (flags & MSG_PEEK) moff += len; else { - if (mp) + if (mp) { + /* + * XXX: can block so i need to drop + * my socket mutex + * solutions: + * pass a mutex to m_copym to msleep + * on + * try M_NOWAIT first, then M_WAIT + * ignore the problem and don't + * unlock + */ + SOCKBUF_UNLOCK(&so->so_rcv, 0); *mp = m_copym(m, 0, len, M_WAIT); + SOCKBUF_LOCK(&so->so_rcv, 0); + } m->m_data += len; m->m_len -= len; so->so_rcv.sb_cc -= len; @@ -915,9 +992,8 @@ break; error = sbwait(&so->so_rcv); if (error) { - sbunlock(&so->so_rcv); - splx(s); - return (0); + error = 0; + goto release; } m = so->so_rcv.sb_mb; if (m) @@ -939,7 +1015,7 @@ if (orig_resid == uio->uio_resid && orig_resid && (flags & MSG_EOR) == 0 && (so->so_state & SS_CANTRCVMORE) == 0) { sbunlock(&so->so_rcv); - splx(s); + SOCKBUF_UNLOCK(&so->so_rcv, 0); goto restart; } @@ -947,7 +1023,8 @@ *flagsp |= flags; release: sbunlock(&so->so_rcv); - splx(s); +out: + SOCKBUF_UNLOCK(&so->so_rcv, 0); return (error); } @@ -975,14 +1052,16 @@ register int s; struct sockbuf asb; + SOCKBUF_LOCK(&so->so_rcv, 0); sb->sb_flags |= SB_NOINTR; - (void) sblock(sb, M_WAITOK); + (void) sblock(so, sb, M_WAITOK); s = splimp(); socantrcvmore(so); sbunlock(sb); asb = *sb; bzero((caddr_t)sb, sizeof (*sb)); splx(s); + SOCKBUF_UNLOCK(&so->so_rcv, 0); if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose) (*pr->pr_domain->dom_dispose)(asb.sb_mb); sbrelease(&asb, so); @@ -1496,8 +1575,8 @@ sopoll(struct socket *so, int events, struct ucred *cred, struct proc *p) { int revents = 0; - int s = splnet(); + SOCK_LOCK(so); if (events & (POLLIN | POLLRDNORM)) if (soreadable(so)) revents |= events & (POLLIN | POLLRDNORM); @@ -1522,7 +1601,7 @@ } } - splx(s); + SOCK_UNLOCK(so); return (revents); } @@ -1530,13 +1609,13 @@ filt_sorattach(struct knote *kn) { struct socket *so = (struct socket *)kn->kn_fp->f_data; - int s = splnet(); + SOCK_LOCK(so); if (so->so_options & SO_ACCEPTCONN) kn->kn_fop = &solisten_filtops; SLIST_INSERT_HEAD(&so->so_rcv.sb_sel.si_note, kn, kn_selnext); so->so_rcv.sb_flags |= SB_KNOTE; - splx(s); + SOCK_UNLOCK(so); return (0); } @@ -1544,12 +1623,12 @@ filt_sordetach(struct knote *kn) { struct socket *so = (struct socket *)kn->kn_fp->f_data; - int s = splnet(); + SOCK_LOCK(so); SLIST_REMOVE(&so->so_rcv.sb_sel.si_note, kn, knote, kn_selnext); if (SLIST_EMPTY(&so->so_rcv.sb_sel.si_note)) so->so_rcv.sb_flags &= ~SB_KNOTE; - splx(s); + SOCK_UNLOCK(so); } /*ARGSUSED*/ @@ -1572,11 +1651,11 @@ filt_sowattach(struct knote *kn) { struct socket *so = (struct socket *)kn->kn_fp->f_data; - int s = splnet(); + SOCK_LOCK(so); SLIST_INSERT_HEAD(&so->so_snd.sb_sel.si_note, kn, kn_selnext); so->so_snd.sb_flags |= SB_KNOTE; - splx(s); + SOCK_UNLOCK(so); return (0); } @@ -1584,12 +1663,12 @@ filt_sowdetach(struct knote *kn) { struct socket *so = (struct socket *)kn->kn_fp->f_data; - int s = splnet(); + SOCK_LOCK(so); SLIST_REMOVE(&so->so_snd.sb_sel.si_note, kn, knote, kn_selnext); if (SLIST_EMPTY(&so->so_snd.sb_sel.si_note)) so->so_snd.sb_flags &= ~SB_KNOTE; - splx(s); + SOCK_UNLOCK(so); } /*ARGSUSED*/ Index: kern/uipc_socket2.c =================================================================== RCS file: /home/ncvs/src/sys/kern/uipc_socket2.c,v retrieving revision 1.65 diff -u -u -r1.65 uipc_socket2.c --- kern/uipc_socket2.c 2000/09/05 22:10:24 1.65 +++ kern/uipc_socket2.c 2000/09/17 18:18:47 @@ -295,12 +295,13 @@ * Wait for data to arrive at/drain from a socket buffer. */ int -sbwait(sb) +sbwait(so, sb) + struct socket *so; struct sockbuf *sb; { sb->sb_flags |= SB_WAIT; - return (tsleep((caddr_t)&sb->sb_cc, + return (msleep((caddr_t)&sb->sb_cc, SOCKBUF_MTX(sb), (sb->sb_flags & SB_NOINTR) ? PSOCK : PSOCK | PCATCH, "sbwait", sb->sb_timeo)); } @@ -311,13 +312,13 @@ */ int sb_lock(sb) - register struct sockbuf *sb; + struct sockbuf *sb; { int error; while (sb->sb_flags & SB_LOCK) { sb->sb_flags |= SB_WANT; - error = tsleep((caddr_t)&sb->sb_flags, + error = msleep((caddr_t)&sb->sb_flags, SOCKBUF_MTX(sb), (sb->sb_flags & SB_NOINTR) ? PSOCK : PSOCK|PCATCH, "sblock", 0); if (error) Index: libkern/inet_ntoa.c =================================================================== RCS file: /home/ncvs/src/sys/libkern/inet_ntoa.c,v retrieving revision 1.3 diff -u -u -r1.3 inet_ntoa.c --- libkern/inet_ntoa.c 2000/05/01 20:06:36 1.3 +++ libkern/inet_ntoa.c 2000/09/09 23:57:26 @@ -48,3 +48,17 @@ return buf; } +char * +inet_ntoa_r(struct in_addr ina, char *buf) +{ + unsigned char *ucp = (unsigned char *)&ina; + + sprintf(buf, "%d.%d.%d.%d", + ucp[0] & 0xff, + ucp[1] & 0xff, + ucp[2] & 0xff, + ucp[3] & 0xff); + return buf; +} + + Index: net/if_ethersubr.c =================================================================== RCS file: /home/ncvs/src/sys/net/if_ethersubr.c,v retrieving revision 1.83 diff -u -u -r1.83 if_ethersubr.c --- net/if_ethersubr.c 2000/09/30 14:33:53 1.83 +++ net/if_ethersubr.c 2000/10/07 21:03:43 @@ -267,11 +267,14 @@ schednetisr(NETISR_NS); inq = &nsintrq; s = splimp(); + IF_QLOCK(inq); if (IF_QFULL(inq)) { IF_DROP(inq); m_freem(m); - } else - IF_ENQUEUE(inq, m); + } else { + IF_ENQUEUE_NOUNLOCK(inq, m); + } + IF_QUNLOCK(ifq); splx(s); return (error); } @@ -383,12 +386,14 @@ #endif s = splimp(); + IF_QLOCK(ifp); /* * Queue message on interface, and start output if interface * not yet active. */ if (IF_QFULL(&ifp->if_snd)) { IF_DROP(&ifp->if_snd); + IF_QUNLOCK(ifp); splx(s); m_freem(m); return (ENOBUFS); @@ -436,7 +441,7 @@ return; } -#ifdef BRIDGE +#ifdef BRIDGE /* MPsafe? */ /* Check for bridging mode */ if (do_bridge) { struct ifnet *bif; @@ -642,11 +647,14 @@ } s = splimp(); + IF_QLOCK(inq); if (IF_QFULL(inq)) { IF_DROP(inq); m_freem(m); - } else - IF_ENQUEUE(inq, m); + } else { + IF_ENQUEUE_NOUNLOCK(inq, m); + } + IF_QUNLOCK(inq); splx(s); } Index: net/if_var.h =================================================================== RCS file: /home/ncvs/src/sys/net/if_var.h,v retrieving revision 1.26 diff -u -u -r1.26 if_var.h --- net/if_var.h 2000/08/15 00:48:38 1.26 +++ net/if_var.h 2000/09/28 10:43:02 @@ -89,6 +89,7 @@ int ifq_len; int ifq_maxlen; int ifq_drops; + struct mtx ifq_mtx; }; /* @@ -183,9 +184,16 @@ * (defined above). Entries are added to and deleted from these structures * by these macros, which should be called with ipl raised to splimp(). */ +#define IF_QLOCK_INIT(ifq, n) mtx_init(&(ifq)->ifq_mtx, n, M_DEF) +#define IF_QLOCK_UNINITED(ifq) ((ifq)->ifq_mtx.mtx_description == NULL) +#define IF_QLOCK(ifq) mtx_enter(&(ifq)->ifq_mtx, M_DEF) +#define IF_QUNLOCK(ifq) mtx_exit(&(ifq)->ifq_mtx, M_DEF) +#define IF_QLOCK_DESTROY(ifq) mtx_destroy(&(ifq)->ifq_mtx) + #define IF_QFULL(ifq) ((ifq)->ifq_len >= (ifq)->ifq_maxlen) #define IF_DROP(ifq) ((ifq)->ifq_drops++) -#define IF_ENQUEUE(ifq, m) { \ + +#define IF_ENQUEUE_NOUNLOCK(ifq, m) do { \ (m)->m_nextpkt = 0; \ if ((ifq)->ifq_tail == 0) \ (ifq)->ifq_head = m; \ @@ -193,15 +201,24 @@ (ifq)->ifq_tail->m_nextpkt = m; \ (ifq)->ifq_tail = m; \ (ifq)->ifq_len++; \ -} -#define IF_PREPEND(ifq, m) { \ +} while(0) + +#define IF_ENQUEUE(ifq, m) do { \ + IF_ENQUEUE_NOUNLOCK(ifq, m); \ + IF_QUNLOCK(ifq); \ +} while(0) + +#define IF_PREPEND(ifq, m) do { \ + IF_QLOCK(ifq); \ (m)->m_nextpkt = (ifq)->ifq_head; \ if ((ifq)->ifq_tail == 0) \ (ifq)->ifq_tail = (m); \ (ifq)->ifq_head = (m); \ (ifq)->ifq_len++; \ -} -#define IF_DEQUEUE(ifq, m) { \ + IF_QUNLOCK(ifq); \ +} while (0) + +#define IF_DEQUEUE_NOLOCK(ifq, m) do { \ (m) = (ifq)->ifq_head; \ if (m) { \ if (((ifq)->ifq_head = (m)->m_nextpkt) == 0) \ @@ -209,7 +226,14 @@ (m)->m_nextpkt = 0; \ (ifq)->ifq_len--; \ } \ -} +} while (0) + +#define IF_DEQUEUE(ifq, m) do { \ + IF_QLOCK(ifq); \ + IF_DEQUEUE_NOLOCK(ifq, m); \ + IF_QUNLOCK(ifq); \ +} while(0) + #ifdef _KERNEL #define IF_ENQ_DROP(ifq, m) if_enq_drop(ifq, m) Index: net/netisr.h =================================================================== RCS file: /home/ncvs/src/sys/net/netisr.h,v retrieving revision 1.21 diff -u -u -r1.21 netisr.h --- net/netisr.h 2000/02/13 03:31:56 1.21 +++ net/netisr.h 2000/09/12 09:09:45 @@ -68,7 +68,11 @@ #ifdef _KERNEL extern volatile unsigned int netisr; /* scheduling bits for network */ -#define schednetisr(anisr) { netisr |= 1 << (anisr); setsoftnet(); } +#define schednetisr(anisr) \ + do { \ + atomic_set_int(&netisr, 1 << (anisr)); \ + setsoftnet(); \ + } while(0) typedef void netisr_t __P((void)); Index: netinet/accf_http.c =================================================================== RCS file: /home/ncvs/src/sys/netinet/accf_http.c,v retrieving revision 1.2 diff -u -u -r1.2 accf_http.c --- netinet/accf_http.c 2000/09/06 18:49:11 1.2 +++ netinet/accf_http.c 2000/10/07 21:23:06 @@ -30,23 +30,11 @@ #define ACCEPT_FILTER_MOD #include -#include -#include #include #include -#include -#include -#include -#include -#include #include -#include #include -#include #include -#include -#include -#include /* check for GET/HEAD */ static void sohashttpget(struct socket *so, void *arg, int waitflag); Index: netinet/in.h =================================================================== RCS file: /home/ncvs/src/sys/netinet/in.h,v retrieving revision 1.50 diff -u -u -r1.50 in.h --- netinet/in.h 2000/07/04 16:35:05 1.50 +++ netinet/in.h 2000/09/09 23:57:24 @@ -483,6 +483,7 @@ int in_canforward __P((struct in_addr)); int in_localaddr __P((struct in_addr)); char *inet_ntoa __P((struct in_addr)); /* in libkern */ +char *inet_ntoa_r __P((struct in_addr, char *)); /* in libkern */ int prison_ip __P((struct proc *p, int flag, u_int32_t *ip)); void prison_remote_ip __P((struct proc *p, int flag, u_int32_t *ip)); Index: netinet/in_pcb.c =================================================================== RCS file: /home/ncvs/src/sys/netinet/in_pcb.c,v retrieving revision 1.68 diff -u -u -r1.68 in_pcb.c --- netinet/in_pcb.c 2000/09/17 13:35:42 1.68 +++ netinet/in_pcb.c 2000/09/17 16:12:25 @@ -145,6 +145,7 @@ { register struct inpcb *inp; + mxt_enter(&pcbinfo->ipi_mtx, MTX_DEF); inp = zalloci(pcbinfo->ipi_zone); if (inp == NULL) return (ENOBUFS); @@ -161,6 +162,7 @@ LIST_INSERT_HEAD(pcbinfo->listhead, inp, inp_list); pcbinfo->ipi_count++; so->so_pcb = (caddr_t)inp; + mxt_exit(&pcbinfo->ipi_mtx, MTX_DEF); return (0); } @@ -188,7 +190,7 @@ sin = (struct sockaddr_in *)nam; if (nam->sa_len != sizeof (*sin)) return (EINVAL); -#ifdef notdef +#ifdef 0 /* * We should check the family, but old programs * incorrectly fail to initialize it. @@ -562,7 +564,7 @@ */ if ((rt->rt_flags & RTF_DELCLONE) && (rt->rt_flags & RTF_WASCLONED)) { - if (--rt->rt_refcnt <= 0) { + if (atomic_subtract_long(rt->rt_refcnt, 1) <= 0) { rt->rt_flags &= ~RTF_UP; rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway, rt_mask(rt), @@ -573,7 +575,7 @@ * more than one reference, bump it up * again. */ - rt->rt_refcnt++; + atomic_add_long(rt->rt_refcnt, 1); } else rtfree(rt); @@ -975,6 +977,8 @@ pcbporthash = &pcbinfo->porthashbase[INP_PCBPORTHASH(inp->inp_lport, pcbinfo->porthashmask)]; + mxt_enter(&pcbinfo->ipi_mtx, MTX_DEF); + /* * Go through port list and look for a head for this lport. */ @@ -997,6 +1001,7 @@ inp->inp_phd = phd; LIST_INSERT_HEAD(&phd->phd_pcblist, inp, inp_portlist); LIST_INSERT_HEAD(pcbhash, inp, inp_hash); + mxt_exit(&pcbinfo->ipi_mtx, MTX_DEF); return (0); } @@ -1023,8 +1028,10 @@ head = &inp->inp_pcbinfo->hashbase[INP_PCBHASH(hashkey_faddr, inp->inp_lport, inp->inp_fport, inp->inp_pcbinfo->hashmask)]; + mxt_enter(&pcbinfo->ipi_mtx, MTX_DEF); LIST_REMOVE(inp, inp_hash); LIST_INSERT_HEAD(head, inp, inp_hash); + mxt_exit(&pcbinfo->ipi_mtx, MTX_DEF); } /* @@ -1034,6 +1041,8 @@ in_pcbremlists(inp) struct inpcb *inp; { + + mxt_enter(&pcbinfo->ipi_mtx, MTX_DEF); inp->inp_gencnt = ++inp->inp_pcbinfo->ipi_gencnt; if (inp->inp_lport) { struct inpcbport *phd = inp->inp_phd; @@ -1047,6 +1056,7 @@ } LIST_REMOVE(inp, inp_list); inp->inp_pcbinfo->ipi_count--; + mxt_exit(&pcbinfo->ipi_mtx, MTX_DEF); } int Index: netinet/in_pcb.h =================================================================== RCS file: /home/ncvs/src/sys/netinet/in_pcb.h,v retrieving revision 1.34 diff -u -u -r1.34 in_pcb.h --- netinet/in_pcb.h 2000/05/26 02:05:45 1.34 +++ netinet/in_pcb.h 2000/09/09 14:06:25 @@ -197,6 +197,7 @@ }; struct inpcbinfo { /* XXX documentation, prefixes */ + mtx_t ipi_mtx; struct inpcbhead *hashbase; u_long hashmask; struct inpcbporthead *porthashbase; Index: netinet/ip6.h =================================================================== RCS file: /home/ncvs/src/sys/netinet/ip6.h,v retrieving revision 1.4 diff -u -u -r1.4 ip6.h --- netinet/ip6.h 2000/07/12 16:39:13 1.4 +++ netinet/ip6.h 2000/09/09 11:08:25 @@ -213,31 +213,33 @@ * mbufs(never into two or more internal mbufs). Thus, the third case is * supposed to never be matched but is prepared just in case. */ - +/* + * MPsafe (alfred) + */ #define IP6_EXTHDR_CHECK(m, off, hlen, ret) \ do { \ if ((m)->m_next != NULL) { \ if (((m)->m_flags & M_LOOP) && \ ((m)->m_len < (off) + (hlen)) && \ (((m) = m_pullup((m), (off) + (hlen))) == NULL)) { \ - ip6stat.ip6s_exthdrtoolong++; \ + atomic_add_long(&ip6stat.ip6s_exthdrtoolong,1); \ return ret; \ } else if ((m)->m_flags & M_EXT) { \ if ((m)->m_len < (off) + (hlen)) { \ - ip6stat.ip6s_exthdrtoolong++; \ + atomic_add_long(&ip6stat.ip6s_exthdrtoolong, 1); \ m_freem(m); \ return ret; \ } \ } else { \ if ((m)->m_len < (off) + (hlen)) { \ - ip6stat.ip6s_exthdrtoolong++; \ + atomic_add_long(&ip6stat.ip6s_exthdrtoolong, 1); \ m_freem(m); \ return ret; \ } \ } \ } else { \ if ((m)->m_len < (off) + (hlen)) { \ - ip6stat.ip6s_tooshort++; \ + atomic_add_long(&ip6stat.ip6s_tooshort, 1); \ in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated); \ m_freem(m); \ return ret; \ Index: netinet/ip_input.c =================================================================== RCS file: /home/ncvs/src/sys/netinet/ip_input.c,v retrieving revision 1.141 diff -u -u -r1.141 ip_input.c --- netinet/ip_input.c 2000/09/14 21:06:48 1.141 +++ netinet/ip_input.c 2000/09/17 16:12:25 @@ -237,6 +237,7 @@ ip_id = time_second & 0xffff; ipintrq.ifq_maxlen = ipqmaxlen; + IF_QLOCK_INIT(ipintrq); register_netisr(NETISR_IP, ipintr); } @@ -1411,6 +1412,8 @@ * Second argument is buffer to which options * will be moved, and return value is their length. * XXX should be deleted; last arg currently ignored. + * + * MP safe (alfred) */ void ip_stripoptions(m, mopt) Index: netinet/tcp_input.c =================================================================== RCS file: /home/ncvs/src/sys/netinet/tcp_input.c,v retrieving revision 1.118 diff -u -u -r1.118 tcp_input.c --- netinet/tcp_input.c 2000/07/21 23:26:37 1.118 +++ netinet/tcp_input.c 2000/09/11 07:58:36 @@ -185,8 +185,8 @@ tp->t_flags |= TF_ACKNOW; \ (tp)->rcv_nxt += *(tlenp); \ flags = (th)->th_flags & TH_FIN; \ - tcpstat.tcps_rcvpack++;\ - tcpstat.tcps_rcvbyte += *(tlenp);\ + atomic_add_long(&tcpstat.tcps_rcvpack, 1);\ + atomic_add_long(&tcpstat.tcps_rcvbyte, *(tlenp));\ ND6_HINT(tp); \ sbappend(&(so)->so_rcv, (m)); \ sorwakeup(so); \ @@ -221,7 +221,7 @@ MALLOC(te, struct tseg_qent *, sizeof (struct tseg_qent), M_TSEGQ, M_NOWAIT); if (te == NULL) { - tcpstat.tcps_rcvmemdrop++; + atomic_add_long(&tcpstat.tcps_rcvmemdrop, 1); m_freem(m); return (0); } @@ -246,8 +246,8 @@ i = p->tqe_th->th_seq + p->tqe_len - th->th_seq; if (i > 0) { if (i >= *tlenp) { - tcpstat.tcps_rcvduppack++; - tcpstat.tcps_rcvdupbyte += *tlenp; + atomic_add_long(&tcpstat.tcps_rcvduppack, 1); + atomic_add_long(&tcpstat.tcps_rcvdupbyte, *tlenp); m_freem(m); FREE(te, M_TSEGQ); /* @@ -263,8 +263,8 @@ th->th_seq += i; } } - tcpstat.tcps_rcvoopack++; - tcpstat.tcps_rcvoobyte += *tlenp; + atomic_add_long(&tcpstat.tcps_rcvoopack, 1); + atomic_add_long(&tcpstat.tcps_rcvoobyte, *tlenp); /* * While we overlap succeeding segments trim them or, @@ -309,6 +309,8 @@ q = LIST_FIRST(&tp->t_segq); if (!q || q->tqe_th->th_seq != tp->rcv_nxt) return (0); + + mtx_enter(&so->so_mtx, MTX_DEF); do { tp->rcv_nxt += q->tqe_len; flags = q->tqe_th->th_flags & TH_FIN; @@ -323,6 +325,7 @@ } while (q && q->tqe_th->th_seq == tp->rcv_nxt); ND6_HINT(tp); sorwakeup(so); + mtx_exit(&so->so_mtx, MTX_DEF); return (flags); } @@ -398,7 +401,7 @@ #endif bzero((char *)&to, sizeof(to)); - tcpstat.tcps_rcvtotal++; + atomic_add_long(&tcpstat.tcps_rcvtotal, 1); #ifdef INET6 if (isipv6) { @@ -406,7 +409,7 @@ ip6 = mtod(m, struct ip6_hdr *); tlen = sizeof(*ip6) + ntohs(ip6->ip6_plen) - off0; if (in6_cksum(m, IPPROTO_TCP, off0, tlen)) { - tcpstat.tcps_rcvbadsum++; + atomic_add_long(&tcpstat.tcps_rcvbadsum, 1); goto drop; } th = (struct tcphdr *)((caddr_t)ip6 + off0); @@ -418,12 +421,12 @@ * Note: IP leaves IP header in first mbuf. */ if (off0 > sizeof (struct ip)) { - ip_stripoptions(m, (struct mbuf *)0); + ip_stripoptions(m, NULL); off0 = sizeof(struct ip); } if (m->m_len < sizeof (struct tcpiphdr)) { if ((m = m_pullup(m, sizeof (struct tcpiphdr))) == 0) { - tcpstat.tcps_rcvshort++; + atomic_add_long(&tcpstat.tcps_rcvshort, 1); return; } } @@ -451,7 +454,7 @@ th->th_sum = in_cksum(m, len); } if (th->th_sum) { - tcpstat.tcps_rcvbadsum++; + atomic_add_long(&tcpstat.tcps_rcvbadsum, 1); goto drop; } #ifdef INET6 @@ -466,7 +469,7 @@ */ off = th->th_off << 2; if (off < sizeof (struct tcphdr) || off > tlen) { - tcpstat.tcps_rcvbadoff++; + atomic_add_long(&tcpstat.tcps_rcvbadoff, 1); goto drop; } tlen -= off; /* tlen is used instead of ti->ti_len */ @@ -481,7 +484,7 @@ { if (m->m_len < sizeof(struct ip) + off) { if ((m = m_pullup(m, sizeof (struct ip) + off)) == 0) { - tcpstat.tcps_rcvshort++; + atomic_add_long(&tcpstat.tcps_rcvshort, 1); return; } ip = mtod(m, struct ip *); @@ -575,7 +578,7 @@ #ifdef INET6 if (isipv6) { if (inp != NULL && ipsec6_in_reject_so(m, inp->inp_socket)) { - ipsec6stat.in_polvio++; + atomic_add_long(&ipsec6stat.in_polvio, 1); goto drop; } } else @@ -607,8 +610,8 @@ } else #endif { - strcpy(dbuf, inet_ntoa(ip->ip_dst)); - strcpy(sbuf, inet_ntoa(ip->ip_src)); + (void) inet_ntoa_r(ip->ip_dst, dbuf); + (void) inet_ntoa_r(ip->ip_src, sbuf); } switch (log_in_vain) { case 1: @@ -704,7 +707,7 @@ * send a RST in response to a RST. */ if (thflags & TH_ACK) { - tcpstat.tcps_badsyn++; + atomic_add_long(&tcpstat.tcps_badsyn, 1); goto maybedropwithreset; } goto drop; @@ -712,7 +715,7 @@ #endif so2 = sonewconn(so, 0); if (so2 == 0) { - tcpstat.tcps_listendrop++; + atomic_add_long(&tcpstat.tcps_listendrop, 1); so2 = sodropablereq(so); if (so2) { if (tcp_lq_overflow) @@ -784,7 +787,7 @@ * send a RST in response to a RST. */ if (thflags & TH_ACK) { - tcpstat.tcps_badsyn++; + atomic_add_long(&tcpstat.tcps_badsyn, 1); goto maybedropwithreset; } goto drop; @@ -896,7 +899,7 @@ /* * this is a pure ack for outstanding data. */ - ++tcpstat.tcps_predack; + atomic_add_long(&tcpstat.tcps_predack, 1); /* * "bad retransmit" recovery */ @@ -915,8 +918,8 @@ SEQ_GT(th->th_ack, tp->t_rtseq)) tcp_xmit_timer(tp, ticks - tp->t_rtttime); acked = th->th_ack - tp->snd_una; - tcpstat.tcps_rcvackpack++; - tcpstat.tcps_rcvackbyte += acked; + atomic_add_long(&tcpstat.tcps_rcvackpack, 1); + atomic_add_long(&tcpstat.tcps_rcvackbyte, acked); sbdrop(&so->so_snd, acked); tp->snd_una = th->th_ack; m_freem(m); @@ -951,10 +954,10 @@ * with nothing on the reassembly queue and * we have enough buffer space to take it. */ - ++tcpstat.tcps_preddat; + atomic_add_long(&tcpstat.tcps_preddat, 1); tp->rcv_nxt += tlen; - tcpstat.tcps_rcvpack++; - tcpstat.tcps_rcvbyte += tlen; + atomic_add_long(&tcpstat.tcps_rcvpack, 1); + atomic_add_long(&tcpstat.tcps_rcvbyte, tlen); ND6_HINT(tp); /* some progress has been done */ /* * Add data to socket buffer. @@ -1170,12 +1173,12 @@ * become effective only later when our SYN is acked. */ tp->rcv_adv += min(tp->rcv_wnd, TCP_MAXWIN); - tcpstat.tcps_connects++; + atomic_add_long(&tcpstat.tcps_connects++, 1); soisconnected(so); callout_reset(tp->tt_keep, tcp_keepinit, tcp_timer_keep, tp); dropsocket = 0; /* committed to socket */ - tcpstat.tcps_accepts++; + atomic_add_long(&tcpstat.tcps_accepts, 1); goto trimthenstep6; } /* else do standard 3-way handshake */ @@ -1194,7 +1197,7 @@ tp->t_state = TCPS_SYN_RECEIVED; callout_reset(tp->tt_keep, tcp_keepinit, tcp_timer_keep, tp); dropsocket = 0; /* committed to socket */ - tcpstat.tcps_accepts++; + atomic_add_long(&tcpstat.tcps_accepts, 1); goto trimthenstep6; } @@ -1273,7 +1276,7 @@ } } else tp->t_flags &= ~TF_RCVD_CC; - tcpstat.tcps_connects++; + atomic_add_long(&tcpstat.tcps_connects, 1); soisconnected(so); /* Do window scaling on this connection? */ if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) == @@ -1366,8 +1369,8 @@ m_adj(m, -todrop); tlen = tp->rcv_wnd; thflags &= ~TH_FIN; - tcpstat.tcps_rcvpackafterwin++; - tcpstat.tcps_rcvbyteafterwin += todrop; + atomic_add_long(&tcpstat.tcps_rcvpackafterwin, 1); + atomic_add_long(&tcpstat.tcps_rcvbyteafterwin, todrop); } tp->snd_wl1 = th->th_seq - 1; tp->rcv_up = th->th_seq; @@ -1485,7 +1488,7 @@ so->so_error = ECONNRESET; close: tp->t_state = TCPS_CLOSED; - tcpstat.tcps_drops++; + atomic_add_long(&tcpstat.tcps_drops, 1); tp = tcp_close(tp); break; @@ -1523,9 +1526,9 @@ */ tp->ts_recent = 0; } else { - tcpstat.tcps_rcvduppack++; - tcpstat.tcps_rcvdupbyte += tlen; - tcpstat.tcps_pawsdrop++; + atomic_add_long(&tcpstat.tcps_rcvduppack, 1); + atomic_add_long(&tcpstat.tcps_rcvdupbyte, tlen); + atomic_add_long(&tcpstat.tcps_pawsdrop, 1); goto dropafterack; } } @@ -1579,11 +1582,11 @@ */ tp->t_flags |= TF_ACKNOW; todrop = tlen; - tcpstat.tcps_rcvduppack++; - tcpstat.tcps_rcvdupbyte += todrop; + atomic_add_long(&tcpstat.tcps_rcvduppack, 1); + atomic_add_long(&tcpstat.tcps_rcvdupbyte, todrop); } else { - tcpstat.tcps_rcvpartduppack++; - tcpstat.tcps_rcvpartdupbyte += todrop; + atomic_add_long(&tcpstat.tcps_rcvpartduppack, 1); + atomic_add_long(&tcpstat.tcps_rcvpartdupbyte, todrop); } drop_hdrlen += todrop; /* drop from the top afterwards */ th->th_seq += todrop; @@ -1603,7 +1606,7 @@ if ((so->so_state & SS_NOFDREF) && tp->t_state > TCPS_CLOSE_WAIT && tlen) { tp = tcp_close(tp); - tcpstat.tcps_rcvafterclose++; + atomic_add_long(&tcpstat.tcps_rcvafterclose, 1); goto dropwithreset; } @@ -1613,9 +1616,9 @@ */ todrop = (th->th_seq+tlen) - (tp->rcv_nxt+tp->rcv_wnd); if (todrop > 0) { - tcpstat.tcps_rcvpackafterwin++; + atomic_add_long(&tcpstat.tcps_rcvpackafterwin, 1); if (todrop >= tlen) { - tcpstat.tcps_rcvbyteafterwin += tlen; + atomic_add_long(&tcpstat.tcps_rcvbyteafterwin, tlen); /* * If a new connection request is received * while in TIME_WAIT, drop the old connection @@ -1638,11 +1641,11 @@ */ if (tp->rcv_wnd == 0 && th->th_seq == tp->rcv_nxt) { tp->t_flags |= TF_ACKNOW; - tcpstat.tcps_rcvwinprobe++; + atomic_add_long(&tcpstat.tcps_rcvwinprobe, 1); } else goto dropafterack; } else - tcpstat.tcps_rcvbyteafterwin += todrop; + atomic_add_long(&tcpstat.tcps_rcvbyteafterwin, todrop); m_adj(m, -todrop); tlen -= todrop; thflags &= ~(TH_PUSH|TH_FIN); @@ -1694,7 +1697,7 @@ */ case TCPS_SYN_RECEIVED: - tcpstat.tcps_connects++; + atomic_add_long(&tcpstat.tcps_connects, 1); soisconnected(so); /* Do window scaling? */ if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) == @@ -1753,7 +1756,7 @@ if (SEQ_LEQ(th->th_ack, tp->snd_una)) { if (tlen == 0 && tiwin == tp->snd_wnd) { - tcpstat.tcps_rcvdupack++; + atomic_add_long(&tcpstat.tcps_rcvdupack, 1); /* * If we have outstanding data (other than * a window probe), this is a completely @@ -1844,7 +1847,7 @@ tp->t_dupacks = 0; } if (SEQ_GT(th->th_ack, tp->snd_max)) { - tcpstat.tcps_rcvacktoomuch++; + atomic_add_long(&tcpstat.tcps_rcvacktoomuch, 1); goto dropafterack; } /* @@ -1871,8 +1874,8 @@ process_ACK: acked = th->th_ack - tp->snd_una; - tcpstat.tcps_rcvackpack++; - tcpstat.tcps_rcvackbyte += acked; + atomic_add_long(&tcpstat.tcps_rcvackpack, 1); + atomic_add_long(&tcpstat.tcps_rcvackbyte, acked); /* * If we just performed our first retransmit, and the ACK @@ -2038,7 +2041,7 @@ /* keep track of pure window updates */ if (tlen == 0 && tp->snd_wl2 == th->th_ack && tiwin > tp->snd_wnd) - tcpstat.tcps_rcvwinupd++; + atomic_add_long(&tcpstat.tcps_rcvwinupd, 1); tp->snd_wnd = tiwin; tp->snd_wl1 = th->th_seq; tp->snd_wl2 = th->th_ack; @@ -2479,7 +2482,7 @@ { register int delta; - tcpstat.tcps_rttupdated++; + atomic_add_long(&tcpstat.tcps_rttupdated, 1); tp->t_rttupdated++; if (tp->t_srtt != 0) { /* @@ -2657,11 +2660,11 @@ if (rt->rt_rmx.rmx_locks & RTV_RTT) tp->t_rttmin = rtt / (RTM_RTTUNIT / hz); tp->t_srtt = rtt / (RTM_RTTUNIT / (hz * TCP_RTT_SCALE)); - tcpstat.tcps_usedrtt++; + atomic_add_long(&tcpstat.tcps_usedrtt, 1); if (rt->rt_rmx.rmx_rttvar) { tp->t_rttvar = rt->rt_rmx.rmx_rttvar / (RTM_RTTUNIT / (hz * TCP_RTTVAR_SCALE)); - tcpstat.tcps_usedrttvar++; + atomic_add_long(&tcpstat.tcps_usedrttvar, 1); } else { /* default variation is +- 1 rtt */ tp->t_rttvar = @@ -2785,7 +2788,7 @@ * threshold to no less than 2*mss. */ tp->snd_ssthresh = max(2 * mss, rt->rt_rmx.rmx_ssthresh); - tcpstat.tcps_usedssthresh++; + atomic_add_long(&tcpstat.tcps_usedssthresh, 1); } } Index: netinet/tcp_output.c =================================================================== RCS file: /home/ncvs/src/sys/netinet/tcp_output.c,v retrieving revision 1.47 diff -u -u -r1.47 tcp_output.c --- netinet/tcp_output.c 2000/09/11 19:11:33 1.47 +++ netinet/tcp_output.c 2000/09/17 16:12:26 @@ -549,13 +549,13 @@ */ if (len) { if (tp->t_force && len == 1) - tcpstat.tcps_sndprobe++; + atomic_add_long(&tcpstat.tcps_sndprobe, 1); else if (SEQ_LT(tp->snd_nxt, tp->snd_max)) { - tcpstat.tcps_sndrexmitpack++; - tcpstat.tcps_sndrexmitbyte += len; + atomic_add_long(&tcpstat.tcps_sndrexmitpack, 1); + atomic_add_long(&tcpstat.tcps_sndrexmitbyte, len); } else { - tcpstat.tcps_sndpack++; - tcpstat.tcps_sndbyte += len; + atomic_add_long(&tcpstat.tcps_sndpack, 1); + atomic_add_long(&tcpstat.tcps_sndbyte, len); } #ifdef notyet if ((m = m_copypack(so->so_snd.sb_mb, off, @@ -609,13 +609,13 @@ flags |= TH_PUSH; } else { if (tp->t_flags & TF_ACKNOW) - tcpstat.tcps_sndacks++; + atomic_add_long(&tcpstat.tcps_sndacks, 1); else if (flags & (TH_SYN|TH_FIN|TH_RST)) - tcpstat.tcps_sndctrl++; + atomic_add_long(&tcpstat.tcps_sndctrl, 1); else if (SEQ_GT(tp->snd_up, tp->snd_una)) - tcpstat.tcps_sndurg++; + atomic_add_long(&tcpstat.tcps_sndurg, 1); else - tcpstat.tcps_sndwinup++; + atomic_add_long(&tcpstat.tcps_sndwinup, 1); MGETHDR(m, M_DONTWAIT, MT_HEADER); if (m == NULL) { @@ -765,7 +765,7 @@ if (tp->t_rtttime == 0) { tp->t_rtttime = ticks; tp->t_rtseq = startseq; - tcpstat.tcps_segstimed++; + atomic_add_long(&tcpstat.tcps_segstimed, 1); } } @@ -904,7 +904,7 @@ } return (error); } - tcpstat.tcps_sndtotal++; + atomic_add_long(&tcpstat.tcps_sndtotal, 1); /* * Data sent (as far as we can tell). Index: netinet/tcp_subr.c =================================================================== RCS file: /home/ncvs/src/sys/netinet/tcp_subr.c,v retrieving revision 1.81 diff -u -u -r1.81 tcp_subr.c --- netinet/tcp_subr.c 2000/09/29 01:37:19 1.81 +++ netinet/tcp_subr.c 2000/10/07 21:03:46 @@ -539,9 +539,10 @@ if (TCPS_HAVERCVDSYN(tp->t_state)) { tp->t_state = TCPS_CLOSED; (void) tcp_output(tp); - tcpstat.tcps_drops++; - } else - tcpstat.tcps_conndrops++; + atomic_add_long(&tcpstat.tcps_drops, 1); + } else { + atomic_add_long(&tcpstat.tcps_conndrops, 1); + } if (errno == ETIMEDOUT && tp->t_softerror) errno = tp->t_softerror; so->so_error = errno; @@ -621,7 +622,7 @@ (rt->rt_rmx.rmx_rtt + i) / 2; else rt->rt_rmx.rmx_rtt = i; - tcpstat.tcps_cachedrtt++; + atomic_add_long(&tcpstat.tcps_cachedrtt, 1); } if ((rt->rt_rmx.rmx_locks & RTV_RTTVAR) == 0) { i = tp->t_rttvar * @@ -631,7 +632,7 @@ (rt->rt_rmx.rmx_rttvar + i) / 2; else rt->rt_rmx.rmx_rttvar = i; - tcpstat.tcps_cachedrttvar++; + atomic_add_long(&tcpstat.tcps_cachedrttvar, 1); } /* * The old comment here said: @@ -677,7 +678,7 @@ (rt->rt_rmx.rmx_ssthresh + i) / 2; else rt->rt_rmx.rmx_ssthresh = i; - tcpstat.tcps_cachedssthresh++; + atomic_add_long(&tcpstat.tcps_cachedssthresh, 1); } } rt = inp->inp_route.ro_rt; @@ -709,7 +710,7 @@ else #endif /* INET6 */ in_pcbdetach(inp); - tcpstat.tcps_closed++; + atomic_add_long(&tcpstat.tcps_closed, 1); return ((struct tcpcb *)0); } @@ -1159,7 +1160,7 @@ tp->t_maxseg = mss; - tcpstat.tcps_mturesent++; + atomic_add_long(&tcpstat.tcps_mturesent, 1); tp->t_rtttime = 0; tp->snd_nxt = tp->snd_una; tcp_output(tp); Index: netinet/tcp_timer.c =================================================================== RCS file: /home/ncvs/src/sys/netinet/tcp_timer.c,v retrieving revision 1.39 diff -u -u -r1.39 tcp_timer.c --- netinet/tcp_timer.c 2000/10/02 15:00:13 1.39 +++ netinet/tcp_timer.c 2000/10/07 21:03:46 @@ -176,7 +176,7 @@ callout_deactivate(tp->tt_delack); tp->t_flags |= TF_ACKNOW; - tcpstat.tcps_delack++; + atomic_add_long(&tcpstat.tcps_delack, 1); (void) tcp_output(tp); splx(s); } @@ -240,7 +240,7 @@ * Keep-alive timer went off; send something * or drop connection if idle for too long. */ - tcpstat.tcps_keeptimeo++; + atomic_add_long(&tcpstat.tcps_keeptimeo, 1); if (tp->t_state < TCPS_ESTABLISHED) goto dropit; if ((always_keepalive || @@ -260,7 +260,7 @@ * by the protocol spec, this requires the * correspondent TCP to respond. */ - tcpstat.tcps_keepprobe++; + atomic_add_long(&tcpstat.tcps_keepprobe, 1); #ifdef TCP_COMPAT_42 /* * The keepalive packet must have nonzero length @@ -287,7 +287,7 @@ return; dropit: - tcpstat.tcps_keepdrops++; + atomic_add_long(&tcpstat.tcps_keepdrops, 1); tp = tcp_drop(tp, ETIMEDOUT); #ifdef TCPDEBUG @@ -319,7 +319,7 @@ * Persistance timer into zero window. * Force a byte to be output, if possible. */ - tcpstat.tcps_persisttimeo++; + atomic_add_long(&tcpstat.tcps_persisttimeo, 1); /* * Hack: if the peer is dead/unreachable, we do not * time out if the window is closed. After a full @@ -330,7 +330,7 @@ if (tp->t_rxtshift == TCP_MAXRXTSHIFT && ((ticks - tp->t_rcvtime) >= tcp_maxpersistidle || (ticks - tp->t_rcvtime) >= TCP_REXMTVAL(tp) * tcp_totbackoff)) { - tcpstat.tcps_persistdrop++; + atomic_add_long(&tcpstat.tcps_persistdrop, 1); tp = tcp_drop(tp, ETIMEDOUT); goto out; } @@ -373,7 +373,7 @@ */ if (++tp->t_rxtshift > TCP_MAXRXTSHIFT) { tp->t_rxtshift = TCP_MAXRXTSHIFT; - tcpstat.tcps_timeoutdrop++; + atomic_add_long(&tcpstat.tcps_timeoutdrop, 1); tp = tcp_drop(tp, tp->t_softerror ? tp->t_softerror : ETIMEDOUT); goto out; @@ -392,7 +392,7 @@ tp->snd_ssthresh_prev = tp->snd_ssthresh; tp->t_badrxtwin = ticks + (tp->t_srtt >> (TCP_RTT_SHIFT + 1)); } - tcpstat.tcps_rexmttimeo++; + atomic_add_long(&tcpstat.tcps_rexmttimeo, 1); rexmt = TCP_REXMTVAL(tp) * tcp_backoff[tp->t_rxtshift]; TCPT_RANGESET(tp->t_rxtcur, rexmt, tp->t_rttmin, TCPTV_REXMTMAX); Index: netinet/tcp_usrreq.c =================================================================== RCS file: /home/ncvs/src/sys/netinet/tcp_usrreq.c,v retrieving revision 1.52 diff -u -u -r1.52 tcp_usrreq.c --- netinet/tcp_usrreq.c 2000/04/01 22:35:45 1.52 +++ netinet/tcp_usrreq.c 2000/09/08 22:56:33 @@ -735,7 +735,7 @@ tp->request_r_scale++; soisconnecting(so); - tcpstat.tcps_connattempt++; + atomic_add_long(&tcpstat.tcps_connattempt, 1); tp->t_state = TCPS_SYN_SENT; callout_reset(tp->tt_keep, tcp_keepinit, tcp_timer_keep, tp); tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/2; @@ -827,7 +827,7 @@ tp->request_r_scale++; soisconnecting(so); - tcpstat.tcps_connattempt++; + atomic_add_long(&tcpstat.tcps_connattempt, 1); tp->t_state = TCPS_SYN_SENT; callout_reset(tp->tt_keep, tcp_keepinit, tcp_timer_keep, tp); tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/2; Index: netinet6/in6_cksum.c =================================================================== RCS file: /home/ncvs/src/sys/netinet6/in6_cksum.c,v retrieving revision 1.3 diff -u -u -r1.3 in6_cksum.c --- netinet6/in6_cksum.c 2000/09/09 15:56:46 1.3 +++ netinet6/in6_cksum.c 2000/09/11 00:29:36 @@ -89,7 +89,7 @@ * len is a total length of a transport segment. * (e.g. TCP header + TCP payload) */ - +/* MP safe (alfred) */ int in6_cksum(m, nxt, off, len) register struct mbuf *m; @@ -120,6 +120,15 @@ u_int16_t s[2]; u_int32_t l; } l_util; + union { + u_int16_t phs[4]; + struct { + u_int32_t ph_len; + u_int8_t ph_zero[3]; + u_int8_t ph_nxt; + } ph; + } uph; + /* sanity check */ if (m->m_pkthdr.len < off + len) { Index: netinet6/in6_var.h =================================================================== RCS file: /home/ncvs/src/sys/netinet6/in6_var.h,v retrieving revision 1.6 diff -u -u -r1.6 in6_var.h --- netinet6/in6_var.h 2000/07/04 16:35:09 1.6 +++ netinet6/in6_var.h 2000/09/09 11:08:01 @@ -436,6 +436,10 @@ extern struct icmp6stat icmp6stat; extern struct icmp6_ifstat **icmp6_ifstat; extern size_t icmp6_ifstatmax; +/* + * MPsafe assuming that there is only one executing context per interrupt + * (alfred) + */ #define in6_ifstat_inc(ifp, tag) \ do { \ if ((ifp) && (ifp)->if_index <= if_index \ Index: sys/socketvar.h =================================================================== RCS file: /home/ncvs/src/sys/sys/socketvar.h,v retrieving revision 1.52 diff -u -u -r1.52 socketvar.h --- sys/socketvar.h 2000/09/06 18:49:13 1.52 +++ sys/socketvar.h 2000/09/28 08:14:06 @@ -51,7 +51,7 @@ struct accept_filter; struct socket { - struct vm_zone *so_zone; /* zone we were allocated from */ + SLIST_ENTRY(socket) so_nextfree; /* next on the free list */ short so_type; /* generic type, see socket.h */ short so_options; /* from socket call, see socket.h */ short so_linger; /* time to linger while closing */ @@ -96,6 +96,7 @@ struct selinfo sb_sel; /* process selecting read/write */ short sb_flags; /* flags, see below */ short sb_timeo; /* timeout for read/write */ + struct mtx sb_mtx; } so_rcv, so_snd; #define SB_MAX (256*1024) /* default for max chars in sockbuf */ #define SB_LOCK 0x01 /* lock on data queue */ @@ -111,14 +112,14 @@ void (*so_upcall) __P((struct socket *, void *, int)); void *so_upcallarg; struct ucred *so_cred; /* user credentials */ - /* NB: generation count must not be first; easiest to make it last. */ - so_gen_t so_gencnt; /* generation count */ void *so_emuldata; /* private data for emulators */ 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; + /* NB: generation count must not be first; easiest to make it last. */ + so_gen_t so_gencnt; /* XXX: LEAVE THIS LAST! generation count */ }; /* @@ -176,6 +177,23 @@ * Macros for sockets and socket buffering. */ +#define SOCKBUF_MTX(sb) (&(sb)->sb_mtx) +#define SOCKBUF_OWNED(sb) mtx_owned(SOCKBUF_MTX(sb)) +/* #ifndef MT_DEBUG */ +#define SOCKBUF_LOCK_INIT(sb,t) mtx_init(SOCKBUF_MTX(sb), t, M_DEF) +#define SOCKBUF_LOCK(sb, r) mtx_enter(SOCKBUF_MTX(sb), M_DEF|(r)) +#define SOCKBUF_UNLOCK(sb, r) mtx_exit(SOCKBUF_MTX(sb), M_DEF|(r)) +#define SOCKBUF_LOCK_DESTROY(sb) mtx_destroy(SOCKBUF_MTX(sb)) +/* #else *//* MT_DEBUG */ +/* XXX: debug locks please */ +/*#endif *//* MT_DEBUG */ + +#define SOCK_MTX(so) SOCKBUF_MTX(&so->so_rcv) +#define SOCK_LOCK(so) SOCKBUF_LOCK(&so->so_rcv, 0) +#define SOCK_UNLOCK(so) SOCKBUF_UNLOCK(&so->so_rcv, 0) +#define SOCK_OWNED(so) SOCKBUF_OWNED(&so->so_rcv) + + /* * Do we need to notify the other side when I/O is possible? */ @@ -227,7 +245,8 @@ } /* - * Set lock on sockbuf sb; sleep if lock is already held. + * Must be called with socket's mutex owned + * Set lock on sockbuf sb; sleep if lock is already held and M_WAITOK is set. * Unless SB_NOINTR is set on sockbuf, sleep is interruptible. * Returns error without lock if sleep is interrupted. */ @@ -297,6 +316,7 @@ extern u_long sb_max; extern struct vm_zone *socket_zone; extern so_gen_t so_gencnt; +extern mtx_t socket_alloc_lock; struct file; struct filedesc; Index: sys/ucred.h =================================================================== RCS file: /home/ncvs/src/sys/sys/ucred.h,v retrieving revision 1.16 diff -u -u -r1.16 ucred.h --- sys/ucred.h 2000/09/16 23:59:37 1.16 +++ sys/ucred.h 2000/09/17 16:12:31 @@ -55,7 +55,7 @@ #define FSCRED ((struct ucred *)-1) /* filesystem credential */ #ifdef _KERNEL -#define crhold(cr) (cr)->cr_ref++ +#define crhold(cr) atomic_add_short(&((cr)->cr_ref), 1) struct proc;