__va_start(listp, fmt);
kvcprintf (fmt, db_putchar, NULL, db_radix, listp);
__va_end(listp);
+/* DELAY(100000);*/
}
void
db_vprintf(const char *fmt, __va_list va)
{
kvcprintf (fmt, db_putchar, NULL, db_radix, va);
+/* DELAY(100000);*/
}
int db_indent;
}
extern struct fileops socketops;
+
+/*
+ * NOTE: Callers of socket_wait() must already have a reference on the
+ * socket.
+ */
int
socket_wait(struct socket *so, struct timespec *ts, int *res)
{
#include <sys/ucred.h>
#include <sys/mplock2.h>
+#include <sys/socketvar2.h>
#include <net/if.h>
#include <net/route.h>
switch (cmd) {
case FIOASYNC:
if (*(int *)data) {
- so->so_state |= SS_ASYNC;
+ sosetstate(so, SS_ASYNC);
atomic_set_int(&so->so_rcv.ssb_flags, SSB_ASYNC);
atomic_set_int(&so->so_snd.ssb_flags, SSB_ASYNC);
} else {
- so->so_state &= ~SS_ASYNC;
+ soclrstate(so, SS_ASYNC);
atomic_clear_int(&so->so_rcv.ssb_flags, SSB_ASYNC);
atomic_clear_int(&so->so_snd.ssb_flags, SSB_ASYNC);
}
panic("mbufuntrack: mbuf %p was not tracked\n", m);
} else {
mbuf_rb_tree_RB_REMOVE(&mbuf_track_root, mbt);
+ spin_unlock(&mbuf_track_spin);
kfree(mbt, M_MTRACK);
}
- spin_unlock(&mbuf_track_spin);
}
void
/*
* Abort a socket and free it. Called from soabort() only.
- *
- * The SS_ABORTING flag must already be set.
*/
void
so_pru_abort(struct socket *so)
{
struct netmsg_pru_abort msg;
- KKASSERT(so->so_state & SS_ABORTING);
netmsg_init(&msg.nm_netmsg, so, &curthread->td_msgport,
0, netmsg_pru_abort);
msg.nm_prufn = so->so_proto->pr_usrreqs->pru_abort;
/*
* Abort a socket and free it, asynchronously. Called from
* soaborta() only.
- *
- * The SS_ABORTING flag must already be set.
*/
void
so_pru_aborta(struct socket *so)
{
struct netmsg_pru_abort *msg;
- KKASSERT(so->so_state & SS_ABORTING);
msg = kmalloc(sizeof(*msg), M_LWKTMSG, M_WAITOK | M_ZERO);
netmsg_init(&msg->nm_netmsg, so, &netisr_afree_rport,
0, netmsg_pru_abort);
/*
* Abort a socket and free it. Called from soabort_oncpu() only.
* Caller must make sure that the current CPU is inpcb's owner CPU.
- *
- * The SS_ABORTING flag must already be set.
*/
void
so_pru_abort_oncpu(struct socket *so)
/*
* Abort and destroy a socket.
+ *
+ * The originator referenced the socket so we must dereference it when
+ * done.
*/
void
netmsg_pru_abort(netmsg_t msg)
struct socket *so = msg->nm_so;
int error;
- KKASSERT(so->so_state & SS_ABORTING);
- so->so_state &= ~SS_ABORTING;
error = nm->nm_prufn(so);
- if (error)
- sofree(so);
+ sofree(so); /* from soabort*() */
lwkt_replymsg(&msg->nm_lmsg, error);
}
TAILQ_INIT(&so->so_aiojobq);
TAILQ_INIT(&so->so_rcv.ssb_kq.ki_mlist);
TAILQ_INIT(&so->so_snd.ssb_kq.ki_mlist);
+ lwkt_token_init(&so->so_rcv.ssb_token, 1, "rcvtok");
+ lwkt_token_init(&so->so_snd.ssb_token, 1, "rcvtok");
+ so->so_state = SS_NOFDREF;
+ so->so_refs = 1;
}
return so;
}
if (prp->pr_type != type)
return (EPROTOTYPE);
so = soalloc(p != 0);
- if (so == 0)
+ if (so == NULL)
return (ENOBUFS);
/*
+ * Callers of socreate() presumably will connect up a descriptor
+ * and call soclose() if they cannot. This represents our so_refs
+ * (which should be 1) from soalloc().
+ */
+ soclrstate(so, SS_NOFDREF);
+
+ /*
* Set a default port for protocol processing. No action will occur
* on the socket on this port until an inpcb is attached to it and
* is able to match incoming packets, or until the socket becomes
*/
error = so_pru_attach(so, proto, &ai);
if (error) {
- so->so_state |= SS_NOFDREF;
- sofree(so);
- return (error);
+ sosetstate(so, SS_NOFDREF);
+ sofree(so); /* from soalloc */
+ return error;
}
+ /*
+ * NOTE: Returns referenced socket.
+ */
*aso = so;
return (0);
}
{
int error;
- crit_enter();
error = so_pru_bind(so, nam, td);
- crit_exit();
return (error);
}
-void
+static void
sodealloc(struct socket *so)
{
if (so->so_rcv.ssb_hiwat)
short oldopt, oldqlimit;
#endif /* SCTP */
- crit_enter();
- if (so->so_state & (SS_ISCONNECTED | SS_ISCONNECTING)) {
- crit_exit();
+ if (so->so_state & (SS_ISCONNECTED | SS_ISCONNECTING))
return (EINVAL);
- }
#ifdef SCTP
oldopt = so->so_options;
oldqlimit = so->so_qlimit;
#endif /* SCTP */
+ lwkt_gettoken(&so->so_rcv.ssb_token);
if (TAILQ_EMPTY(&so->so_comp))
so->so_options |= SO_ACCEPTCONN;
+ lwkt_reltoken(&so->so_rcv.ssb_token);
if (backlog < 0 || backlog > somaxconn)
backlog = somaxconn;
so->so_qlimit = backlog;
so->so_options = oldopt;
so->so_qlimit = oldqlimit;
#endif /* SCTP */
- crit_exit();
return (error);
}
- crit_exit();
return (0);
}
*
* so_pcb - The protocol stack still has a reference
* SS_NOFDREF - There is no longer a file pointer reference
- * SS_ABORTING - An abort netmsg is in-flight
*/
void
sofree(struct socket *so)
{
struct socket *head = so->so_head;
- if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0)
- return;
- if (so->so_state & SS_ABORTING)
+ /*
+ * Arbitrage the last free.
+ */
+ KKASSERT(so->so_refs > 0);
+ if (atomic_fetchadd_int(&so->so_refs, -1) != 1)
return;
+
+ KKASSERT(so->so_pcb == NULL && (so->so_state & SS_NOFDREF));
+
+ /*
+ * We're done, clean up
+ */
if (head != NULL) {
+ lwkt_gettoken(&head->so_rcv.ssb_token);
if (so->so_state & SS_INCOMP) {
TAILQ_REMOVE(&head->so_incomp, so, so_list);
head->so_incqlen--;
* accept(2) may hang after select(2) indicated
* that the listening socket was ready.
*/
+ lwkt_reltoken(&head->so_rcv.ssb_token);
return;
} else {
panic("sofree: not queued");
}
- so->so_state &= ~SS_INCOMP;
+ soclrstate(so, SS_INCOMP);
so->so_head = NULL;
+ lwkt_reltoken(&head->so_rcv.ssb_token);
}
ssb_release(&so->so_snd, so);
sorflush(so);
{
int error = 0;
- crit_enter();
funsetown(so->so_sigio);
if (so->so_pcb == NULL)
goto discard;
(fflag & FNONBLOCK))
goto drop;
while (so->so_state & SS_ISCONNECTED) {
- error = tsleep((caddr_t)&so->so_timeo,
- PCATCH, "soclos", so->so_linger * hz);
+ error = tsleep(&so->so_timeo, PCATCH,
+ "soclos", so->so_linger * hz);
if (error)
break;
}
error = error2;
}
discard:
+ lwkt_gettoken(&so->so_rcv.ssb_token);
if (so->so_options & SO_ACCEPTCONN) {
struct socket *sp;
while ((sp = TAILQ_FIRST(&so->so_incomp)) != NULL) {
TAILQ_REMOVE(&so->so_incomp, sp, so_list);
- sp->so_state &= ~SS_INCOMP;
+ soclrstate(sp, SS_INCOMP);
sp->so_head = NULL;
so->so_incqlen--;
soaborta(sp);
}
while ((sp = TAILQ_FIRST(&so->so_comp)) != NULL) {
TAILQ_REMOVE(&so->so_comp, sp, so_list);
- sp->so_state &= ~SS_COMP;
+ soclrstate(sp, SS_COMP);
sp->so_head = NULL;
so->so_qlen--;
soaborta(sp);
}
}
+ lwkt_reltoken(&so->so_rcv.ssb_token);
if (so->so_state & SS_NOFDREF)
panic("soclose: NOFDREF");
- so->so_state |= SS_NOFDREF;
- sofree(so);
- crit_exit();
+ sosetstate(so, SS_NOFDREF); /* take ref */
+ sofree(so); /* dispose of ref */
return (error);
}
void
soabort(struct socket *so)
{
- if ((so->so_state & SS_ABORTING) == 0) {
- so->so_state |= SS_ABORTING;
- so_pru_abort(so);
- }
+ soreference(so);
+ so_pru_abort(so);
}
void
soaborta(struct socket *so)
{
- if ((so->so_state & SS_ABORTING) == 0) {
- so->so_state |= SS_ABORTING;
- so_pru_aborta(so);
- }
+ soreference(so);
+ so_pru_aborta(so);
}
void
soabort_oncpu(struct socket *so)
{
- if ((so->so_state & SS_ABORTING) == 0) {
- so->so_state |= SS_ABORTING;
- so_pru_abort_oncpu(so);
- }
+ soreference(so);
+ so_pru_abort_oncpu(so);
}
int
{
int error;
- crit_enter();
if ((so->so_state & SS_NOFDREF) == 0)
panic("soaccept: !NOFDREF");
- so->so_state &= ~SS_NOFDREF;
+ soreference(so); /* create ref */
+ soclrstate(so, SS_NOFDREF); /* owned by lack of SS_NOFDREF */
error = so_pru_accept(so, nam);
- crit_exit();
return (error);
}
if (so->so_options & SO_ACCEPTCONN)
return (EOPNOTSUPP);
- crit_enter();
/*
* If protocol is connection-based, can only connect once.
* Otherwise, if connected, try to disconnect first.
so->so_error = 0;
error = so_pru_connect(so, nam, td);
}
- crit_exit();
return (error);
}
{
int error;
- crit_enter();
error = so_pru_connect2(so1, so2);
- crit_exit();
return (error);
}
{
int error;
- crit_enter();
if ((so->so_state & SS_ISCONNECTED) == 0) {
error = ENOTCONN;
goto bad;
}
error = so_pru_disconnect(so);
bad:
- crit_exit();
return (error);
}
td->td_lwp->lwp_ru.ru_msgsnd++;
if (control)
clen = control->m_len;
-#define gotoerr(errcode) { error = errcode; crit_exit(); goto release; }
+#define gotoerr(errcode) { error = errcode; goto release; }
restart:
error = ssb_lock(&so->so_snd, SBLOCKWAIT(flags));
goto out;
do {
- crit_enter();
if (so->so_state & SS_CANTSENDMORE)
gotoerr(EPIPE);
if (so->so_error) {
error = so->so_error;
so->so_error = 0;
- crit_exit();
goto release;
}
if ((so->so_state & SS_ISCONNECTED) == 0) {
gotoerr(EWOULDBLOCK);
ssb_unlock(&so->so_snd);
error = ssb_wait(&so->so_snd);
- crit_exit();
if (error)
goto out;
goto restart;
}
- crit_exit();
mp = ⊤
space -= clen;
do {
} else {
pru_flags = 0;
}
- crit_enter();
/*
* XXX all the SS_CANTSENDMORE checks previously
* done could be out of date. We could have recieved
* also happens. We must rethink this.
*/
error = so_pru_send(so, pru_flags, top, addr, control, td);
- crit_exit();
if (dontroute)
so->so_options &= ~SO_DONTROUTE;
clen = 0;
if (error)
goto out;
- crit_enter();
if (so->so_state & SS_CANTSENDMORE)
gotoerr(EPIPE);
if (so->so_error) {
error = so->so_error;
so->so_error = 0;
- crit_exit();
goto release;
}
if (!(so->so_state & SS_ISCONNECTED) && addr == NULL)
gotoerr(EWOULDBLOCK);
ssb_unlock(&so->so_snd);
error = ssb_wait(&so->so_snd);
- crit_exit();
if (error)
goto out;
goto restart;
}
- crit_exit();
if (uio) {
top = m_uiomove(uio);
/*
* Implement receive operations on a socket.
+ *
* We depend on the way that records are added to the signalsockbuf
* by sbappend*. In particular, each record (mbufs linked through m_next)
* must begin with an address if the protocol so specifies,
* followed by an optional mbuf or mbufs containing ancillary data,
* and then zero or more mbufs of data.
- * In order to avoid blocking network interrupts for the entire time here,
- * we exit the critical section while doing the actual copy to user space.
- * Although the signalsockbuf is locked, new data may still be appended,
- * and thus we must maintain consistency of the signalsockbuf during that time.
+ *
+ * Although the signalsockbuf is locked, new data may still be appended.
+ * A token inside the ssb_lock deals with MP issues and still allows
+ * the network to access the socket if we block in a uio.
*
* The caller may receive the data as a single mbuf chain by supplying
* an mbuf **mp0 for use in returning the chain. The uio is then used
so_pru_rcvd(so, 0);
restart:
- crit_enter();
error = ssb_lock(&so->so_rcv, SBLOCKWAIT(flags));
if (error)
goto done;
error = ssb_wait(&so->so_rcv);
if (error)
goto done;
- crit_exit();
goto restart;
}
dontblock:
else
KASSERT(m->m_type == MT_DATA || m->m_type == MT_HEADER,
("receive 3"));
- so->so_state &= ~SS_RCVATMARK;
+ soclrstate(so, SS_RCVATMARK);
len = (resid > INT_MAX) ? INT_MAX : resid;
if (so->so_oobmark && len > so->so_oobmark - offset)
len = so->so_oobmark - offset;
* with the resid here either way.
*/
if (uio) {
- crit_exit();
uio->uio_resid = resid;
error = uiomove(mtod(m, caddr_t) + moff, len, uio);
resid = uio->uio_resid;
- crit_enter();
if (error)
goto release;
} else {
if ((flags & MSG_PEEK) == 0) {
so->so_oobmark -= len;
if (so->so_oobmark == 0) {
- so->so_state |= SS_RCVATMARK;
+ sosetstate(so, SS_RCVATMARK);
break;
}
} else {
if (orig_resid == resid && orig_resid &&
(flags & MSG_EOR) == 0 && (so->so_state & SS_CANTRCVMORE) == 0) {
ssb_unlock(&so->so_rcv);
- crit_exit();
goto restart;
}
release:
ssb_unlock(&so->so_rcv);
done:
- crit_exit();
if (free_chain)
m_freem(free_chain);
return (error);
if (kn->kn_sfflags & NOTE_LOWAT)
return (kn->kn_data >= kn->kn_sdata);
return ((kn->kn_data >= so->so_rcv.ssb_lowat) ||
- !TAILQ_EMPTY(&so->so_comp));
+ !TAILQ_EMPTY(&so->so_comp));
}
static void
#include <sys/thread2.h>
#include <sys/msgport2.h>
+#include <sys/socketvar2.h>
int maxsockets;
} else {
if (atomic_cmpset_int(&ssb->ssb_flags, flags,
flags | SSB_LOCK)) {
+ lwkt_gettoken(&ssb->ssb_token);
error = 0;
break;
}
void
soisconnecting(struct socket *so)
{
- so->so_state &= ~(SS_ISCONNECTED|SS_ISDISCONNECTING);
- so->so_state |= SS_ISCONNECTING;
+ soclrstate(so, SS_ISCONNECTED | SS_ISDISCONNECTING);
+ sosetstate(so, SS_ISCONNECTING);
}
void
{
struct socket *head = so->so_head;
- so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING|SS_ISCONFIRMING);
- so->so_state |= SS_ISCONNECTED;
+ soclrstate(so, SS_ISCONNECTING | SS_ISDISCONNECTING | SS_ISCONFIRMING);
+ sosetstate(so, 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_upcall(so, so->so_upcallarg, 0);
return;
}
+
+ /*
+ * Listen socket are not per-cpu.
+ */
+ lwkt_gettoken(&head->so_rcv.ssb_token);
TAILQ_REMOVE(&head->so_incomp, so, so_list);
head->so_incqlen--;
- so->so_state &= ~SS_INCOMP;
+ soclrstate(so, SS_INCOMP);
TAILQ_INSERT_TAIL(&head->so_comp, so, so_list);
head->so_qlen++;
- so->so_state |= SS_COMP;
+ sosetstate(so, SS_COMP);
+ lwkt_reltoken(&head->so_rcv.ssb_token);
+
sorwakeup(head);
wakeup_one(&head->so_timeo);
} else {
void
soisdisconnecting(struct socket *so)
{
- so->so_state &= ~SS_ISCONNECTING;
- so->so_state |= (SS_ISDISCONNECTING|SS_CANTRCVMORE|SS_CANTSENDMORE);
+ soclrstate(so, SS_ISCONNECTING);
+ sosetstate(so, SS_ISDISCONNECTING | SS_CANTRCVMORE | SS_CANTSENDMORE);
wakeup((caddr_t)&so->so_timeo);
sowwakeup(so);
sorwakeup(so);
void
soisdisconnected(struct socket *so)
{
- so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING);
- so->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE|SS_ISDISCONNECTED);
+ soclrstate(so, SS_ISCONNECTING | SS_ISCONNECTED | SS_ISDISCONNECTING);
+ sosetstate(so, SS_CANTRCVMORE | SS_CANTSENDMORE | SS_ISDISCONNECTED);
wakeup((caddr_t)&so->so_timeo);
sbdrop(&so->so_snd.sb, so->so_snd.ssb_cc);
sowwakeup(so);
void
soisreconnecting(struct socket *so)
{
- so->so_state &= ~(SS_ISDISCONNECTING|SS_ISDISCONNECTED|SS_CANTRCVMORE|
- SS_CANTSENDMORE);
- so->so_state |= SS_ISCONNECTING;
+ soclrstate(so, SS_ISDISCONNECTING | SS_ISDISCONNECTED |
+ SS_CANTRCVMORE | SS_CANTSENDMORE);
+ sosetstate(so, SS_ISCONNECTING);
}
void
soisreconnected(struct socket *so)
{
- so->so_state &= ~(SS_ISDISCONNECTED|SS_CANTRCVMORE|SS_CANTSENDMORE);
+ soclrstate(so, SS_ISDISCONNECTED | SS_CANTRCVMORE | SS_CANTSENDMORE);
soisconnected(so);
}
* then we allocate a new structure, propoerly linked into the
* data structure of the original socket, and return this.
* Connstatus may be 0, or SO_ISCONFIRMING, or SO_ISCONNECTED.
+ *
+ * The new socket is returned with one ref and so_pcb assigned.
+ * The reference is implied by so_pcb.
*/
struct socket *
sonewconn(struct socket *head, int connstatus)
so->so_type = head->so_type;
so->so_options = head->so_options &~ SO_ACCEPTCONN;
so->so_linger = head->so_linger;
+
+ /*
+ * NOTE: Clearing NOFDREF implies referencing the so with
+ * soreference().
+ */
so->so_state = head->so_state | SS_NOFDREF;
so->so_proto = head->so_proto;
so->so_cred = crhold(head->so_cred);
ai.sb_rlimit = NULL;
ai.p_ucred = NULL;
ai.fd_rdir = NULL; /* jail code cruft XXX JH */
- if (soreserve(so, head->so_snd.ssb_hiwat, head->so_rcv.ssb_hiwat, NULL) ||
- /* Directly call function since we're already at protocol level. */
+
+ /*
+ * Reserve space and call pru_attach. We can directl call the
+ * function since we're already in the protocol thread.
+ */
+ if (soreserve(so, head->so_snd.ssb_hiwat,
+ head->so_rcv.ssb_hiwat, NULL) ||
(*so->so_proto->pr_usrreqs->pru_attach)(so, 0, &ai)) {
- sodealloc(so);
+ so->so_head = NULL;
+ sofree(so); /* remove implied pcb ref */
return (NULL);
}
+ KKASSERT(so->so_refs == 2); /* attach + our base ref */
+ sofree(so);
KKASSERT(so->so_port != NULL);
so->so_rcv.ssb_lowat = head->so_rcv.ssb_lowat;
so->so_snd.ssb_lowat = head->so_snd.ssb_lowat;
(SSB_AUTOSIZE | SSB_AUTOLOWAT);
so->so_snd.ssb_flags |= head->so_snd.ssb_flags &
(SSB_AUTOSIZE | SSB_AUTOLOWAT);
+ lwkt_gettoken(&head->so_rcv.ssb_token);
if (connstatus) {
TAILQ_INSERT_TAIL(&head->so_comp, so, so_list);
- so->so_state |= SS_COMP;
+ sosetstate(so, SS_COMP);
head->so_qlen++;
} else {
if (head->so_incqlen > head->so_qlimit) {
sp = TAILQ_FIRST(&head->so_incomp);
TAILQ_REMOVE(&head->so_incomp, sp, so_list);
head->so_incqlen--;
- sp->so_state &= ~SS_INCOMP;
+ soclrstate(sp, SS_INCOMP);
sp->so_head = NULL;
soaborta(sp);
}
TAILQ_INSERT_TAIL(&head->so_incomp, so, so_list);
- so->so_state |= SS_INCOMP;
+ sosetstate(so, SS_INCOMP);
head->so_incqlen++;
}
+ lwkt_reltoken(&head->so_rcv.ssb_token);
if (connstatus) {
sorwakeup(head);
wakeup((caddr_t)&head->so_timeo);
- so->so_state |= connstatus;
+ sosetstate(so, connstatus);
}
return (so);
}
void
socantsendmore(struct socket *so)
{
- so->so_state |= SS_CANTSENDMORE;
+ sosetstate(so, SS_CANTSENDMORE);
sowwakeup(so);
}
void
socantrcvmore(struct socket *so)
{
- so->so_state |= SS_CANTRCVMORE;
+ sosetstate(so, SS_CANTRCVMORE);
sorwakeup(so);
}
msg->nm_netmsg.nm_lmsg.ms_error = head->so_error;
return (TRUE);
}
+ lwkt_gettoken(&head->so_rcv.ssb_token);
if (!TAILQ_EMPTY(&head->so_comp)) {
/* Abuse nm_so field as copy in/copy out parameter. XXX JH */
msg->nm_so = TAILQ_FIRST(&head->so_comp);
head->so_qlen--;
msg->nm_netmsg.nm_lmsg.ms_error = 0;
+ lwkt_reltoken(&head->so_rcv.ssb_token);
return (TRUE);
}
+ lwkt_reltoken(&head->so_rcv.ssb_token);
if (head->so_state & SS_CANTRCVMORE) {
msg->nm_netmsg.nm_lmsg.ms_error = ECONNABORTED;
return (TRUE);
/* connection has been removed from the listen queue */
KNOTE(&head->so_rcv.ssb_kq.ki_note, 0);
- so->so_state &= ~SS_COMP;
+ soclrstate(so, SS_COMP);
so->so_head = NULL;
if (head->so_sigio != NULL)
fsetown(fgetown(head->so_sigio), &so->so_sigio);
}
bad:
if (!interrupted)
- so->so_state &= ~SS_ISCONNECTING;
+ soclrstate(so, SS_ISCONNECTING);
if (error == ERESTART)
error = EINTR;
done:
*/
goto noconnection;
}
- so->so_state &= ~SS_COMP;
- so->so_state &= ~SS_NOFDREF;
+ soreference(so); /* reference needed */
+ soclrstate(so, SS_NOFDREF | SS_COMP); /* when clearing NOFDREF */
so->so_head = NULL;
if (head->so_sigio != NULL)
fsetown(fgetown(head->so_sigio), &so->so_sigio);
#include <sys/un.h>
#include <sys/unpcb.h>
#include <sys/vnode.h>
+
#include <sys/file2.h>
#include <sys/spinlock2.h>
-
+#include <sys/socketvar2.h>
static MALLOC_DEFINE(M_UNPCB, "unpcb", "unpcb struct");
static unp_gen_t unp_gencnt;
static struct unp_head unp_shead, unp_dhead;
+static struct lwkt_token unp_token = LWKT_TOKEN_MP_INITIALIZER(unp_token);
+
/*
* Unix communications domain.
*
static int unp_listen (struct unpcb *, struct thread *);
static void unp_fp_externalize(struct lwp *lp, struct file *fp, int fd);
+/*
+ * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort()
+ * will sofree() it when we return.
+ */
static int
uipc_abort(struct socket *so)
{
- struct unpcb *unp = so->so_pcb;
+ struct unpcb *unp;
+ int error;
- if (unp == NULL)
- return EINVAL;
- unp_drop(unp, ECONNABORTED);
- unp_detach(unp);
- sofree(so);
- return 0;
+ lwkt_gettoken(&unp_token);
+ unp = so->so_pcb;
+ if (unp) {
+ unp_drop(unp, ECONNABORTED);
+ unp_detach(unp);
+ error = 0;
+ } else {
+ error = EINVAL;
+ }
+ lwkt_reltoken(&unp_token);
+
+ return error;
}
static int
uipc_accept(struct socket *so, struct sockaddr **nam)
{
- struct unpcb *unp = so->so_pcb;
+ struct unpcb *unp;
- if (unp == NULL)
+ lwkt_gettoken(&unp_token);
+ unp = so->so_pcb;
+ if (unp == NULL) {
+ lwkt_reltoken(&unp_token);
return EINVAL;
+ }
/*
* Pass back name of connected socket,
} else {
*nam = dup_sockaddr((struct sockaddr *)&sun_noname);
}
+ lwkt_reltoken(&unp_token);
return 0;
}
static int
uipc_attach(struct socket *so, int proto, struct pru_attach_info *ai)
{
- struct unpcb *unp = so->so_pcb;
+ struct unpcb *unp;
+ int error;
+
+ lwkt_gettoken(&unp_token);
+ unp = so->so_pcb;
+ if (unp)
+ error = EISCONN;
+ else
+ error = unp_attach(so, ai);
+ lwkt_reltoken(&unp_token);
- if (unp != NULL)
- return EISCONN;
- return unp_attach(so, ai);
+ return error;
}
static int
uipc_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
{
- struct unpcb *unp = so->so_pcb;
+ struct unpcb *unp;
+ int error;
- if (unp == NULL)
- return EINVAL;
- return unp_bind(unp, nam, td);
+ lwkt_gettoken(&unp_token);
+ unp = so->so_pcb;
+ if (unp)
+ error = unp_bind(unp, nam, td);
+ else
+ error = EINVAL;
+ lwkt_reltoken(&unp_token);
+
+ return error;
}
static int
uipc_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
{
- struct unpcb *unp = so->so_pcb;
+ struct unpcb *unp;
+ int error;
- if (unp == NULL)
- return EINVAL;
- return unp_connect(so, nam, td);
+ lwkt_gettoken(&unp_token);
+ unp = so->so_pcb;
+ if (unp)
+ error = unp_connect(so, nam, td);
+ else
+ error = EINVAL;
+ lwkt_reltoken(&unp_token);
+
+ return error;
}
static int
uipc_connect2(struct socket *so1, struct socket *so2)
{
- struct unpcb *unp = so1->so_pcb;
+ struct unpcb *unp;
+ int error;
- if (unp == NULL)
- return EINVAL;
+ lwkt_gettoken(&unp_token);
+ unp = so1->so_pcb;
+ if (unp)
+ error = unp_connect2(so1, so2);
+ else
+ error = EINVAL;
+ lwkt_reltoken(&unp_token);
- return unp_connect2(so1, so2);
+ return error;
}
/* control is EOPNOTSUPP */
static int
uipc_detach(struct socket *so)
{
- struct unpcb *unp = so->so_pcb;
+ struct unpcb *unp;
+ int error;
- if (unp == NULL)
- return EINVAL;
+ lwkt_gettoken(&unp_token);
+ unp = so->so_pcb;
+ if (unp) {
+ unp_detach(unp);
+ error = 0;
+ } else {
+ error = EINVAL;
+ }
+ lwkt_reltoken(&unp_token);
- unp_detach(unp);
- return 0;
+ return error;
}
static int
uipc_disconnect(struct socket *so)
{
- struct unpcb *unp = so->so_pcb;
+ struct unpcb *unp;
+ int error;
- if (unp == NULL)
- return EINVAL;
- unp_disconnect(unp);
- return 0;
+ lwkt_gettoken(&unp_token);
+ unp = so->so_pcb;
+ if (unp) {
+ unp_disconnect(unp);
+ error = 0;
+ } else {
+ error = EINVAL;
+ }
+ lwkt_reltoken(&unp_token);
+
+ return error;
}
static int
uipc_listen(struct socket *so, struct thread *td)
{
- struct unpcb *unp = so->so_pcb;
+ struct unpcb *unp;
+ int error;
+ lwkt_gettoken(&unp_token);
+ unp = so->so_pcb;
if (unp == NULL || unp->unp_vnode == NULL)
- return EINVAL;
- return unp_listen(unp, td);
+ error = EINVAL;
+ else
+ error = unp_listen(unp, td);
+ lwkt_reltoken(&unp_token);
+
+ return error;
}
static int
uipc_peeraddr(struct socket *so, struct sockaddr **nam)
{
- struct unpcb *unp = so->so_pcb;
+ struct unpcb *unp;
+ int error;
- if (unp == NULL)
- return EINVAL;
- if (unp->unp_conn && unp->unp_conn->unp_addr)
+ lwkt_gettoken(&unp_token);
+ unp = so->so_pcb;
+ if (unp == NULL) {
+ error = EINVAL;
+ } else if (unp->unp_conn && unp->unp_conn->unp_addr) {
*nam = dup_sockaddr((struct sockaddr *)unp->unp_conn->unp_addr);
- else {
+ error = 0;
+ } else {
/*
* XXX: It seems that this test always fails even when
* connection is established. So, this else clause is
* added as workaround to return PF_LOCAL sockaddr.
*/
*nam = dup_sockaddr((struct sockaddr *)&sun_noname);
+ error = 0;
}
- return 0;
+ lwkt_reltoken(&unp_token);
+
+ return error;
}
static int
uipc_rcvd(struct socket *so, int flags)
{
- struct unpcb *unp = so->so_pcb;
+ struct unpcb *unp;
struct socket *so2;
- if (unp == NULL)
+ lwkt_gettoken(&unp_token);
+ unp = so->so_pcb;
+ if (unp == NULL) {
+ lwkt_reltoken(&unp_token);
return EINVAL;
+ }
+
switch (so->so_type) {
case SOCK_DGRAM:
panic("uipc_rcvd DGRAM?");
/*NOTREACHED*/
-
case SOCK_STREAM:
case SOCK_SEQPACKET:
if (unp->unp_conn == NULL)
sowwakeup(so2);
}
break;
-
default:
panic("uipc_rcvd unknown socktype");
+ /*NOTREACHED*/
}
+ lwkt_reltoken(&unp_token);
+
return 0;
}
uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
struct mbuf *control, struct thread *td)
{
- int error = 0;
- struct unpcb *unp = so->so_pcb;
+ struct unpcb *unp;
struct socket *so2;
+ int error = 0;
+ lwkt_gettoken(&unp_token);
+
+ unp = so->so_pcb;
if (unp == NULL) {
error = EINVAL;
goto release;
unp_dispose(control);
release:
+ lwkt_reltoken(&unp_token);
+
if (control)
m_freem(control);
if (m)
static int
uipc_sense(struct socket *so, struct stat *sb)
{
- struct unpcb *unp = so->so_pcb;
+ struct unpcb *unp;
- if (unp == NULL)
+ lwkt_gettoken(&unp_token);
+ unp = so->so_pcb;
+ if (unp == NULL) {
+ lwkt_reltoken(&unp_token);
return EINVAL;
+ }
sb->st_blksize = so->so_snd.ssb_hiwat;
sb->st_dev = NOUDEV;
if (unp->unp_ino == 0) { /* make up a non-zero inode number */
spin_unlock(&unp_ino_spin);
}
sb->st_ino = unp->unp_ino;
+ lwkt_reltoken(&unp_token);
+
return (0);
}
static int
uipc_shutdown(struct socket *so)
{
- struct unpcb *unp = so->so_pcb;
+ struct unpcb *unp;
+ int error;
- if (unp == NULL)
- return EINVAL;
- socantsendmore(so);
- unp_shutdown(unp);
- return 0;
+ lwkt_gettoken(&unp_token);
+ unp = so->so_pcb;
+ if (unp) {
+ socantsendmore(so);
+ unp_shutdown(unp);
+ error = 0;
+ } else {
+ error = EINVAL;
+ }
+ lwkt_reltoken(&unp_token);
+
+ return error;
}
static int
uipc_sockaddr(struct socket *so, struct sockaddr **nam)
{
- struct unpcb *unp = so->so_pcb;
+ struct unpcb *unp;
+ int error;
- if (unp == NULL)
- return EINVAL;
- if (unp->unp_addr)
- *nam = dup_sockaddr((struct sockaddr *)unp->unp_addr);
- return 0;
+ lwkt_gettoken(&unp_token);
+ unp = so->so_pcb;
+ if (unp) {
+ if (unp->unp_addr)
+ *nam = dup_sockaddr((struct sockaddr *)unp->unp_addr);
+ error = 0;
+ } else {
+ error = EINVAL;
+ }
+ lwkt_reltoken(&unp_token);
+
+ return error;
}
struct pr_usrreqs uipc_usrreqs = {
int
uipc_ctloutput(struct socket *so, struct sockopt *sopt)
{
- struct unpcb *unp = so->so_pcb;
+ struct unpcb *unp;
int error = 0;
+ lwkt_gettoken(&unp_token);
+ unp = so->so_pcb;
+
switch (sopt->sopt_dir) {
case SOPT_GET:
switch (sopt->sopt_name) {
error = EOPNOTSUPP;
break;
}
+ lwkt_reltoken(&unp_token);
+
return (error);
}
struct unpcb *unp;
int error;
+ lwkt_gettoken(&unp_token);
if (so->so_snd.ssb_hiwat == 0 || so->so_rcv.ssb_hiwat == 0) {
switch (so->so_type) {
panic("unp_attach");
}
if (error)
- return (error);
+ goto failed;
}
unp = kmalloc(sizeof(*unp), M_UNPCB, M_NOWAIT|M_ZERO);
- if (unp == NULL)
- return (ENOBUFS);
+ if (unp == NULL) {
+ error = ENOBUFS;
+ goto failed;
+ }
unp->unp_gencnt = ++unp_gencnt;
unp_count++;
LIST_INIT(&unp->unp_refs);
LIST_INSERT_HEAD(so->so_type == SOCK_DGRAM ? &unp_dhead
: &unp_shead, unp, unp_link);
so->so_pcb = (caddr_t)unp;
+ soreference(so);
so->so_port = sync_soport(so, NULL, NULL);
- return (0);
+ error = 0;
+failed:
+ lwkt_reltoken(&unp_token);
+ return error;
}
static void
unp_detach(struct unpcb *unp)
{
+ struct socket *so;
+
+ lwkt_gettoken(&unp_token);
+
LIST_REMOVE(unp, unp_link);
unp->unp_gencnt = ++unp_gencnt;
--unp_count;
while (!LIST_EMPTY(&unp->unp_refs))
unp_drop(LIST_FIRST(&unp->unp_refs), ECONNRESET);
soisdisconnected(unp->unp_socket);
- unp->unp_socket->so_pcb = NULL;
+ so = unp->unp_socket;
+ soreference(so); /* for delayed sorflush */
+ so->so_pcb = NULL;
+ unp->unp_socket = NULL;
+ sofree(so); /* remove pcb ref */
+
if (unp_rights) {
/*
* Normally the receive buffer is flushed later,
* of those descriptor references after the garbage collector
* gets them (resulting in a "panic: closef: count < 0").
*/
- sorflush(unp->unp_socket);
+ sorflush(so);
unp_gc();
}
+ sofree(so);
+ lwkt_reltoken(&unp_token);
+
if (unp->unp_addr)
kfree(unp->unp_addr, M_SONAME);
kfree(unp, M_UNPCB);
struct nlookupdata nd;
char buf[SOCK_MAXADDRLEN];
- if (unp->unp_vnode != NULL)
- return (EINVAL);
+ lwkt_gettoken(&unp_token);
+ if (unp->unp_vnode != NULL) {
+ error = EINVAL;
+ goto failed;
+ }
namelen = soun->sun_len - offsetof(struct sockaddr_un, sun_path);
- if (namelen <= 0)
- return (EINVAL);
+ if (namelen <= 0) {
+ error = EINVAL;
+ goto failed;
+ }
strncpy(buf, soun->sun_path, namelen);
buf[namelen] = 0; /* null-terminate the string */
error = nlookup_init(&nd, buf, UIO_SYSSPACE,
}
done:
nlookup_done(&nd);
+failed:
+ lwkt_reltoken(&unp_token);
return (error);
}
struct nlookupdata nd;
char buf[SOCK_MAXADDRLEN];
- KKASSERT(p);
+ lwkt_gettoken(&unp_token);
len = nam->sa_len - offsetof(struct sockaddr_un, sun_path);
- if (len <= 0)
- return EINVAL;
+ if (len <= 0) {
+ error = EINVAL;
+ goto failed;
+ }
strncpy(buf, soun->sun_path, len);
buf[len] = 0;
error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_EXCLUSIVE, &vp);
nlookup_done(&nd);
if (error)
- return (error);
+ goto failed;
if (vp->v_type != VSOCK) {
error = ENOTSOCK;
error = unp_connect2(so, so2);
bad:
vput(vp);
+failed:
+ lwkt_reltoken(&unp_token);
return (error);
}
int
unp_connect2(struct socket *so, struct socket *so2)
{
- struct unpcb *unp = so->so_pcb;
+ struct unpcb *unp;
struct unpcb *unp2;
- if (so2->so_type != so->so_type)
+ lwkt_gettoken(&unp_token);
+ unp = so->so_pcb;
+ if (so2->so_type != so->so_type) {
+ lwkt_reltoken(&unp_token);
return (EPROTOTYPE);
+ }
unp2 = so2->so_pcb;
unp->unp_conn = unp2;
- switch (so->so_type) {
+ switch (so->so_type) {
case SOCK_DGRAM:
LIST_INSERT_HEAD(&unp2->unp_refs, unp, unp_reflink);
soisconnected(so);
default:
panic("unp_connect2");
}
+ lwkt_reltoken(&unp_token);
return (0);
}
static void
unp_disconnect(struct unpcb *unp)
{
- struct unpcb *unp2 = unp->unp_conn;
+ struct unpcb *unp2;
- if (unp2 == NULL)
+ lwkt_gettoken(&unp_token);
+
+ unp2 = unp->unp_conn;
+ if (unp2 == NULL) {
+ lwkt_reltoken(&unp_token);
return;
+ }
unp->unp_conn = NULL;
switch (unp->unp_socket->so_type) {
case SOCK_DGRAM:
LIST_REMOVE(unp, unp_reflink);
- unp->unp_socket->so_state &= ~SS_ISCONNECTED;
+ soclrstate(unp->unp_socket, SS_ISCONNECTED);
break;
case SOCK_STREAM:
case SOCK_SEQPACKET:
soisdisconnected(unp2->unp_socket);
break;
}
+ lwkt_reltoken(&unp_token);
}
#ifdef notdef
void
unp_abort(struct unpcb *unp)
{
-
+ lwkt_gettoken(&unp_token);
unp_detach(unp);
+ lwkt_reltoken(&unp_token);
}
#endif
if (req->newptr != NULL)
return EPERM;
+ lwkt_gettoken(&unp_token);
+
/*
* OK, now we're committed to doing something.
*/
error = SYSCTL_OUT(req, &xu, sizeof xu);
}
}
+ lwkt_reltoken(&unp_token);
kfree(unp_list, M_TEMP);
+
return error;
}
void
unp_drain(void)
{
-
+ lwkt_gettoken(&unp_token);
+ lwkt_reltoken(&unp_token);
}
#endif
/ sizeof (struct file *);
int f;
+ lwkt_gettoken(&unp_token);
+
/*
* if the new FD's will not fit, then we free them all
*/
*rp++ = 0;
unp_discard(fp, NULL);
}
+ lwkt_reltoken(&unp_token);
return (EMSGSIZE);
}
*/
cm->cmsg_len = CMSG_LEN(newfds * sizeof(int));
rights->m_len = cm->cmsg_len;
+
+ lwkt_reltoken(&unp_token);
return (0);
}
struct file *fx;
int error;
+ lwkt_gettoken(&unp_token);
+
if (lp) {
KKASSERT(fd >= 0);
if (fp->f_flag & FREVOKED) {
unp_rights--;
spin_unlock(&unp_spin);
fdrop(fp);
+
+ lwkt_reltoken(&unp_token);
}
struct cmsgcred *cmcred;
int oldfds;
u_int newlen;
+ int error;
KKASSERT(p);
+ lwkt_gettoken(&unp_token);
+
fdescp = p->p_fd;
if ((cm->cmsg_type != SCM_RIGHTS && cm->cmsg_type != SCM_CREDS) ||
cm->cmsg_level != SOL_SOCKET ||
CMSG_ALIGN(cm->cmsg_len) != control->m_len) {
- return (EINVAL);
+ error = EINVAL;
+ goto done;
}
/*
CMGROUP_MAX);
for (i = 0; i < cmcred->cmcred_ngroups; i++)
cmcred->cmcred_groups[i] = p->p_ucred->cr_groups[i];
- return(0);
+ error = 0;
+ goto done;
}
/*
* cmsghdr may not be aligned, do not allow calculation(s) to
* go negative.
*/
- if (cm->cmsg_len < CMSG_LEN(0))
- return(EINVAL);
+ if (cm->cmsg_len < CMSG_LEN(0)) {
+ error = EINVAL;
+ goto done;
+ }
oldfds = (cm->cmsg_len - CMSG_LEN(0)) / sizeof (int);
for (i = 0; i < oldfds; i++) {
fd = *fdp++;
if ((unsigned)fd >= fdescp->fd_nfiles ||
- fdescp->fd_files[fd].fp == NULL)
- return (EBADF);
- if (fdescp->fd_files[fd].fp->f_type == DTYPE_KQUEUE)
- return (EOPNOTSUPP);
+ fdescp->fd_files[fd].fp == NULL) {
+ error = EBADF;
+ goto done;
+ }
+ if (fdescp->fd_files[fd].fp->f_type == DTYPE_KQUEUE) {
+ error = EOPNOTSUPP;
+ goto done;
+ }
}
/*
* Now replace the integer FDs with pointers to
* enough, return E2BIG.
*/
newlen = CMSG_LEN(oldfds * sizeof(struct file *));
- if (newlen > MCLBYTES)
- return (E2BIG);
+ if (newlen > MCLBYTES) {
+ error = E2BIG;
+ goto done;
+ }
if (newlen - control->m_len > M_TRAILINGSPACE(control)) {
- if (control->m_flags & M_EXT)
- return (E2BIG);
+ if (control->m_flags & M_EXT) {
+ error = E2BIG;
+ goto done;
+ }
MCLGET(control, MB_WAIT);
- if (!(control->m_flags & M_EXT))
- return (ENOBUFS);
+ if (!(control->m_flags & M_EXT)) {
+ error = ENOBUFS;
+ goto done;
+ }
/* copy the data to the cluster */
memcpy(mtod(control, char *), cm, cm->cmsg_len);
spin_unlock(&unp_spin);
}
}
- return (0);
+ error = 0;
+done:
+ lwkt_reltoken(&unp_token);
+ return error;
}
/*
unp_gcing = TRUE;
spin_unlock(&unp_spin);
+ lwkt_gettoken(&unp_token);
+
/*
* before going through all this, set all FDs to
* be NOT defered and NOT externally accessible
for (i = info.index, fpp = info.extra_ref; --i >= 0; ++fpp)
closef(*fpp, NULL);
} while (info.index == info.maxindex);
+
+ lwkt_reltoken(&unp_token);
+
kfree((caddr_t)info.extra_ref, M_FILE);
unp_gcing = FALSE;
}
struct unp_revoke_gc_info info;
int i;
+ lwkt_gettoken(&unp_token);
info.fx = fx;
do {
info.fcount = 0;
for (i = 0; i < info.fcount; ++i)
unp_fp_externalize(NULL, info.fary[i], -1);
} while (info.fcount == REVOKE_GC_MAXFILES);
+ lwkt_reltoken(&unp_token);
}
/*
void
unp_dispose(struct mbuf *m)
{
+ lwkt_gettoken(&unp_token);
if (m)
unp_scan(m, unp_discard, NULL);
+ lwkt_reltoken(&unp_token);
}
static int
struct proc *p = td->td_proc;
KKASSERT(p);
+ lwkt_gettoken(&unp_token);
cru2x(p->p_ucred, &unp->unp_peercred);
unp->unp_flags |= UNP_HAVEPCCACHED;
+ lwkt_reltoken(&unp_token);
return (0);
}
static u_char nexpire[MFCTBLSIZ];
+struct lwkt_token mroute_token = LWKT_TOKEN_MP_INITIALIZER(mroute_token);
+
+
static struct callout expire_upcalls_ch;
static struct callout tbf_reprocess_q_ch;
#define EXPIRE_TIMEOUT (hz / 4) /* 4x / second */
{
struct mfc *rt;
- crit_enter();
+ lwkt_gettoken(&mroute_token);
rt = mfc_find(req->src.s_addr, req->grp.s_addr);
- crit_exit();
if (rt == NULL) {
req->pktcnt = req->bytecnt = req->wrong_if = 0xffffffff;
+ lwkt_reltoken(&mroute_token);
return EADDRNOTAVAIL;
}
req->pktcnt = rt->mfc_pkt_cnt;
req->bytecnt = rt->mfc_byte_cnt;
req->wrong_if = rt->mfc_wrong_if;
+ lwkt_reltoken(&mroute_token);
return 0;
}
struct mfc *rt;
struct rtdetq *rte;
- crit_enter();
+ lwkt_gettoken(&mroute_token);
/*
* For each phyint in use, disable promiscuous reception of all IP
ip_mrouter = NULL;
- crit_exit();
+ lwkt_reltoken(&mroute_token);
if (mrtdebug)
log(LOG_DEBUG, "ip_mrouter_done\n");
return EOPNOTSUPP;
/* Enable promiscuous reception of all IP multicasts from the if */
- crit_enter();
+ lwkt_gettoken(&mroute_token);
error = if_allmulti(ifp, 1);
- crit_exit();
+ lwkt_reltoken(&mroute_token);
if (error)
return error;
}
- crit_enter();
+ lwkt_gettoken(&mroute_token);
/* define parameters for the tbf structure */
vifp->v_tbf = v_tbf;
GET_TIME(vifp->v_tbf->tbf_last_pkt_t);
vifp->v_pkt_out = 0;
vifp->v_bytes_in = 0;
vifp->v_bytes_out = 0;
- crit_exit();
/* Adjust numvifs up if the vifi is higher than numvifs */
if (numvifs <= vifcp->vifc_vifi) numvifs = vifcp->vifc_vifi + 1;
+ lwkt_reltoken(&mroute_token);
+
if (mrtdebug)
log(LOG_DEBUG, "add_vif #%d, lcladdr %lx, %s %lx, thresh %x, rate %d\n",
vifcp->vifc_vifi,
if (vifp->v_lcl_addr.s_addr == INADDR_ANY)
return EADDRNOTAVAIL;
- crit_enter();
+ lwkt_gettoken(&mroute_token);
if (!(vifp->v_flags & (VIFF_TUNNEL | VIFF_REGISTER)))
if_allmulti(vifp->v_ifp, 0);
break;
numvifs = vifi;
- crit_exit();
+ lwkt_reltoken(&mroute_token);
return 0;
}
(u_long)ntohl(mfccp->mfcc_mcastgrp.s_addr),
mfccp->mfcc_parent);
- crit_enter();
+ lwkt_gettoken(&mroute_token);
update_mfc_params(rt, mfccp);
- crit_exit();
+ lwkt_reltoken(&mroute_token);
return 0;
}
/*
* Find the entry for which the upcall was made and update
*/
- crit_enter();
+ lwkt_gettoken(&mroute_token);
hash = MFCHASH(mfccp->mfcc_origin.s_addr, mfccp->mfcc_mcastgrp.s_addr);
for (rt = mfctable[hash], nstl = 0; rt; rt = rt->mfc_next) {
if (rt == NULL) { /* no upcall, so make a new entry */
rt = kmalloc(sizeof(*rt), M_MRTABLE, M_INTWAIT | M_NULLOK);
if (rt == NULL) {
- crit_exit();
+ lwkt_reltoken(&mroute_token);
return ENOBUFS;
}
mfctable[hash] = rt;
}
}
- crit_exit();
+ lwkt_reltoken(&mroute_token);
return 0;
}
log(LOG_DEBUG,"del_mfc orig %lx mcastgrp %lx\n",
(u_long)ntohl(origin.s_addr), (u_long)ntohl(mcastgrp.s_addr));
- crit_enter();
+ lwkt_gettoken(&mroute_token);
hash = MFCHASH(origin.s_addr, mcastgrp.s_addr);
for (nptr = &mfctable[hash]; (rt = *nptr) != NULL; nptr = &rt->mfc_next)
rt->mfc_stall == NULL)
break;
if (rt == NULL) {
- crit_exit();
+ lwkt_reltoken(&mroute_token);
return EADDRNOTAVAIL;
}
*/
list = rt->mfc_bw_meter;
rt->mfc_bw_meter = NULL;
+ lwkt_reltoken(&mroute_token);
kfree(rt, M_MRTABLE);
-
- crit_exit();
-
free_bw_list(list);
return 0;
/*
* Determine forwarding vifs from the forwarding cache table
*/
- crit_enter();
+ lwkt_gettoken(&mroute_token);
++mrtstat.mrts_mfc_lookups;
rt = mfc_find(ip->ip_src.s_addr, ip->ip_dst.s_addr);
/* Entry exists, so forward if necessary */
if (rt != NULL) {
- crit_exit();
- return ip_mdq(m, ifp, rt, -1);
+ int ipres = ip_mdq(m, ifp, rt, -1);
+ lwkt_reltoken(&mroute_token);
+ return ipres;
} else {
/*
* If we don't have a route for packet's origin,
*/
rte = kmalloc((sizeof *rte), M_MRTABLE, M_INTWAIT | M_NULLOK);
if (rte == NULL) {
- crit_exit();
+ lwkt_reltoken(&mroute_token);
return ENOBUFS;
}
mb0 = m_pullup(mb0, hlen);
if (mb0 == NULL) {
kfree(rte, M_MRTABLE);
- crit_exit();
+ lwkt_reltoken(&mroute_token);
return ENOBUFS;
}
fail:
kfree(rte, M_MRTABLE);
m_freem(mb0);
- crit_exit();
+ lwkt_reltoken(&mroute_token);
return ENOBUFS;
}
non_fatal:
kfree(rte, M_MRTABLE);
m_freem(mb0);
- crit_exit();
+ lwkt_reltoken(&mroute_token);
return 0;
}
rte->ifp = ifp;
rte->next = NULL;
- crit_exit();
+ lwkt_reltoken(&mroute_token);
return 0;
}
}
struct mfc *mfc, **nptr;
int i;
- crit_enter();
+ lwkt_gettoken(&mroute_token);
for (i = 0; i < MFCTBLSIZ; i++) {
if (nexpire[i] == 0)
continue;
}
}
callout_reset(&expire_upcalls_ch, EXPIRE_TIMEOUT, expire_upcalls, NULL);
- crit_exit();
+ lwkt_reltoken(&mroute_token);
}
/*
{
struct tbf *t = vifp->v_tbf;
- crit_enter();
+ lwkt_gettoken(&mroute_token);
if (t->tbf_t == NULL) /* Queue was empty */
t->tbf_q = m;
t->tbf_q_len++;
- crit_exit();
+ lwkt_reltoken(&mroute_token);
}
/*
{
struct tbf *t = vifp->v_tbf;
- crit_enter();
+ lwkt_gettoken(&mroute_token);
/* loop through the queue at the interface and send as many packets
* as possible
m->m_nextpkt = NULL;
tbf_send_packet(vifp, m);
}
- crit_exit();
+ lwkt_reltoken(&mroute_token);
}
static void
struct mbuf **np;
struct tbf *t = vifp->v_tbf;
- crit_enter();
+ lwkt_gettoken(&mroute_token);
p = priority(vifp, ip);
/* It's impossible for the queue to be empty, but check anyways. */
if (--t->tbf_q_len == 0)
t->tbf_t = NULL;
- crit_exit();
mrtstat.mrts_drop_sel++;
+ lwkt_reltoken(&mroute_token);
return 1;
}
np = &m->m_nextpkt;
last = m;
}
- crit_exit();
+ lwkt_reltoken(&mroute_token);
return 0;
}
static void
tbf_send_packet(struct vif *vifp, struct mbuf *m)
{
- crit_enter();
+ lwkt_gettoken(&mroute_token);
if (vifp->v_flags & VIFF_TUNNEL) /* If tunnel options */
ip_output(m, NULL, &vifp->v_route, IP_FORWARDING, NULL, NULL);
log(LOG_DEBUG, "phyint_send on vif %d err %d\n",
(int)(vifp - viftable), error);
}
- crit_exit();
+ lwkt_reltoken(&mroute_token);
}
/* determine the current time and then
u_long tm;
struct tbf *t = vifp->v_tbf;
- crit_enter();
+ lwkt_gettoken(&mroute_token);
GET_TIME(tp);
if (t->tbf_n_tok > MAX_BKT_SIZE)
t->tbf_n_tok = MAX_BKT_SIZE;
- crit_exit();
+ lwkt_reltoken(&mroute_token);
}
static int
if (error)
return error;
- crit_enter();
+ lwkt_gettoken(&mroute_token);
if (vifi < 0 || vifi >= numvifs) { /* Error if vif is invalid */
- crit_exit();
+ lwkt_reltoken(&mroute_token);
return EADDRNOTAVAIL;
}
if (sopt->sopt_name == IP_RSVP_VIF_ON) {
/* Check if socket is available. */
if (viftable[vifi].v_rsvpd != NULL) {
- crit_exit();
+ lwkt_reltoken(&mroute_token);
return EADDRINUSE;
}
rsvp_on--;
}
}
- crit_exit();
+ lwkt_reltoken(&mroute_token);
return 0;
}
if (so->so_type != SOCK_RAW || so->so_proto->pr_protocol != IPPROTO_RSVP)
return;
- crit_enter();
+ lwkt_gettoken(&mroute_token);
/* The socket may be attached to more than one vif...this
* is perfectly legal.
}
}
- crit_exit();
+ lwkt_reltoken(&mroute_token);
}
static void
return;
}
- crit_enter();
+ lwkt_gettoken(&mroute_token);
if (rsvpdebug)
kprintf("rsvp_input: check vifs\n");
kprintf("rsvp_input: No socket defined for vif %d\n",vifi);
m_freem(m);
}
- crit_exit();
+ lwkt_reltoken(&mroute_token);
return;
}
rsvp_src.sin_addr = ip->ip_src;
}
#endif /* !ALTQ */
- crit_exit();
+ lwkt_reltoken(&mroute_token);
}
/*
/*
* Find if we have already same bw_meter entry
*/
- crit_enter();
+ lwkt_gettoken(&mroute_token);
mfc = mfc_find(req->bu_src.s_addr, req->bu_dst.s_addr);
if (mfc == NULL) {
- crit_exit();
+ lwkt_reltoken(&mroute_token);
return EADDRNOTAVAIL;
}
for (x = mfc->mfc_bw_meter; x != NULL; x = x->bm_mfc_next) {
(x->bm_threshold.b_packets == req->bu_threshold.b_packets) &&
(x->bm_threshold.b_bytes == req->bu_threshold.b_bytes) &&
(x->bm_flags & BW_METER_USER_FLAGS) == flags) {
- crit_exit();
+ lwkt_reltoken(&mroute_token);
return 0; /* XXX Already installed */
}
}
- crit_exit();
+ lwkt_reltoken(&mroute_token);
/* Allocate the new bw_meter entry */
x = kmalloc(sizeof(*x), M_BWMETER, M_INTWAIT);
x->bm_time_hash = BW_METER_BUCKETS;
/* Add the new bw_meter entry to the front of entries for this MFC */
- crit_enter();
+ lwkt_gettoken(&mroute_token);
x->bm_mfc = mfc;
x->bm_mfc_next = mfc->mfc_bw_meter;
mfc->mfc_bw_meter = x;
schedule_bw_meter(x, &now);
- crit_exit();
+ lwkt_reltoken(&mroute_token);
return 0;
}
if (!(mrt_api_config & MRT_MFC_BW_UPCALL))
return EOPNOTSUPP;
- crit_enter();
+ lwkt_gettoken(&mroute_token);
/* Find the corresponding MFC entry */
mfc = mfc_find(req->bu_src.s_addr, req->bu_dst.s_addr);
if (mfc == NULL) {
- crit_exit();
+ lwkt_reltoken(&mroute_token);
return EADDRNOTAVAIL;
} else if (req->bu_flags & BW_UPCALL_DELETE_ALL) {
/*
list = mfc->mfc_bw_meter;
mfc->mfc_bw_meter = NULL;
- crit_exit();
+ lwkt_reltoken(&mroute_token);
free_bw_list(list);
return 0;
} else { /* Delete a single bw_meter entry */
prev->bm_mfc_next = x->bm_mfc_next; /* remove from middle*/
else
x->bm_mfc->mfc_bw_meter = x->bm_mfc_next;/* new head of list */
- crit_exit();
-
unschedule_bw_meter(x);
+ lwkt_reltoken(&mroute_token);
/* Free the bw_meter entry */
kfree(x, M_BWMETER);
return 0;
} else {
- crit_exit();
+ lwkt_reltoken(&mroute_token);
return EINVAL;
}
}
{
struct timeval delta;
- crit_enter();
+ lwkt_gettoken(&mroute_token);
delta = *nowp;
BW_TIMEVALDECR(&delta, &x->bm_start_time);
x->bm_flags &= ~BW_METER_UPCALL_DELIVERED;
}
}
- crit_exit();
+ lwkt_reltoken(&mroute_token);
}
/*
struct timeval delta;
struct bw_upcall *u;
- crit_enter();
+ lwkt_gettoken(&mroute_token);
/*
* Compute the measured time interval
if (x->bm_flags & BW_METER_LEQ)
u->bu_flags |= BW_UPCALL_LEQ;
- crit_exit();
+ lwkt_reltoken(&mroute_token);
}
/*
/*
* Reset the bw_meter entry
*/
- crit_enter();
+ lwkt_gettoken(&mroute_token);
x->bm_start_time = *nowp;
x->bm_measured.b_packets = 0;
x->bm_measured.b_bytes = 0;
x->bm_flags &= ~BW_METER_UPCALL_DELIVERED;
- crit_exit();
/*
* Compute the timeout hash value and insert the entry
x->bm_time_next = bw_meter_timers[time_hash];
bw_meter_timers[time_hash] = x;
x->bm_time_hash = time_hash;
+
+ lwkt_reltoken(&mroute_token);
}
/*
if (last_tv_sec == now.tv_sec)
return; /* nothing to do */
- crit_enter();
+ lwkt_gettoken(&mroute_token);
loops = now.tv_sec - last_tv_sec;
last_tv_sec = now.tv_sec;
if (loops > BW_METER_BUCKETS)
schedule_bw_meter(x, &now);
}
}
- crit_exit();
-
/* Send all upcalls that are pending delivery */
bw_upcalls_send();
+ lwkt_reltoken(&mroute_token);
}
/*
{
switch (type) {
case MOD_LOAD:
- crit_enter();
+ lwkt_gettoken(&mroute_token);
/* XXX Protect against multiple loading */
ip_mcast_src = X_ip_mcast_src;
ip_mforward = X_ip_mforward;
legal_vif_num = X_legal_vif_num;
mrt_ioctl = X_mrt_ioctl;
rsvp_input_p = X_rsvp_input;
- crit_exit();
+ lwkt_reltoken(&mroute_token);
break;
case MOD_UNLOAD:
if (ip_mrouter)
return EINVAL;
- crit_enter();
+ lwkt_gettoken(&mroute_token);
ip_mcast_src = NULL;
ip_mforward = NULL;
ip_mrouter_done = NULL;
legal_vif_num = NULL;
mrt_ioctl = NULL;
rsvp_input_p = NULL;
- crit_exit();
+ lwkt_reltoken(&mroute_token);
break;
}
return 0;
/*
* Allocate a control block and a nominal amount
* of buffer space for the socket.
+ *
+ * The so->so_pcb has already been assigned by the caller, and the
+ * caller has also already bumped the socket refs.
*/
int
raw_attach(struct socket *so, int proto, struct rlimit *rl)
struct socket *so = rp->rcb_socket;
so->so_pcb = NULL;
- sofree(so);
+ sofree(so); /* remove pcb ref */
LIST_REMOVE(rp, list);
kfree(rp, M_PCB);
}
#include <sys/socket.h>
#include <sys/socketvar.h>
+#include <sys/socketvar2.h>
+
#include <net/raw_cb.h>
/*
/* INCOMPLETE */
}
+/*
+ * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort()
+ * will sofree() it when we return.
+ */
static int
raw_uabort(struct socket *so)
{
if (rp == NULL)
return EINVAL;
raw_disconnect(rp);
- sofree(so);
soisdisconnected(so);
return 0;
}
if (rp->rcb_faddr == NULL) {
return ENOTCONN;
}
+ soreference(so);
raw_disconnect(rp);
soisdisconnected(so);
+ sofree(so);
+
return 0;
}
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/domain.h>
+
#include <sys/thread2.h>
+#include <sys/socketvar2.h>
#include <net/if.h>
#include <net/route.h>
*/
crit_enter();
so->so_pcb = rp;
+ soreference(so); /* so_pcb assignment */
error = raw_attach(so, proto, ai->sb_rlimit);
rp = sotorawcb(so);
if (error) {
#include <net/if.h>
#include <net/if_var.h>
#include <sys/sysctl.h>
+
#include <sys/thread2.h>
+#include <sys/socketvar2.h>
#include <netbt/bluetooth.h>
#include <netbt/hci.h>
/*
* Implementation of usrreqs.
+ *
+ * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort()
+ * will sofree() it when we return.
*/
static int
hci_sabort (struct socket *so)
{
+ int error;
+
/* struct hci_pcb *pcb = (struct hci_pcb *)so->so_pcb; */
soisdisconnected(so);
- return hci_sdetach(so);
+ error = hci_sdetach(so);
+ return (error);
}
static int
hci_cmdwait_flush(so);
so->so_pcb = NULL;
+ sofree(so); /* remove pcb ref */
+
LIST_REMOVE(pcb, hp_next);
kfree(pcb, M_PCB);
* this socket (which is permitted) you get a broken pipe when you
* try to write any data.
*/
- so->so_state &= ~SS_ISCONNECTED;
+ soclrstate(so, SS_ISCONNECTED);
return 0;
}
if (pcb == NULL)
return ENOMEM;
+ soreference(so);
so->so_pcb = pcb;
pcb->hp_socket = so;
return l2cap_detach((struct l2cap_channel **)&so->so_pcb);
}
+/*
+ * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort()
+ * will sofree() it when we return.
+ */
static int
l2cap_sabort (struct socket *so)
{
struct l2cap_channel *pcb = so->so_pcb;
+ int error;
l2cap_disconnect(pcb, 0);
soisdisconnected(so);
- return l2cap_sdetach(so);
+ error = l2cap_sdetach(so);
+ return error;
}
static int
return rfcomm_detach((struct rfcomm_dlc **)&so->so_pcb);
}
+/*
+ * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort()
+ * will sofree() it when we return.
+ */
static int
rfcomm_sabort (struct socket *so)
{
struct rfcomm_dlc *pcb = (struct rfcomm_dlc *) so->so_pcb;
+ int error;
rfcomm_disconnect(pcb, 0);
soisdisconnected(so);
- return rfcomm_sdetach(so);
+ error = rfcomm_sdetach(so);
+ return error;
}
static int
return sco_detach((struct sco_pcb **)&so->so_pcb);
}
+/*
+ * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort()
+ * will sofree() it when we return.
+ */
static int
sco_sabort (struct socket *so)
{
struct sco_pcb *pcb = (struct sco_pcb *)so->so_pcb;
+ int error;
sco_disconnect(pcb, 0);
soisdisconnected(so);
+ error = sco_sdetach(so);
- return sco_sdetach(so);
+ return error;
}
static int
if ((so->so_state & SS_ISCONNECTING) != 0)
ERROUT(EALREADY);
if ((error = soconnect(so, sa, td)) != 0) {
- so->so_state &= ~SS_ISCONNECTING;
+ soclrstate(so, SS_ISCONNECTING);
ERROUT(error);
}
if ((so->so_state & SS_ISCONNECTING) != 0) {
if (priv->flags & KSF_CONNECTING) {
if ((error = so->so_error) != 0) {
so->so_error = 0;
- so->so_state &= ~SS_ISCONNECTING;
+ soclrstate(so, SS_ISCONNECTING);
}
if (!(so->so_state & SS_ISCONNECTING)) {
NG_MKMESSAGE(response, NGM_KSOCKET_COOKIE,
struct socket *const head = priv->so;
int error;
+ lwkt_gettoken(&head->so_rcv.ssb_token);
if ((error = head->so_error) != 0) {
head->so_error = 0;
+ lwkt_reltoken(&head->so_rcv.ssb_token);
return error;
}
if (TAILQ_EMPTY(&head->so_comp)) {
if (head->so_state & SS_CANTRCVMORE)
- return ECONNABORTED;
- return EWOULDBLOCK;
+ error = ECONNABORTED;
+ else
+ error = EWOULDBLOCK;
}
- return 0;
+ lwkt_reltoken(&head->so_rcv.ssb_token);
+ return error;
}
/*
priv_p priv2;
int len;
+ lwkt_gettoken(&head->so_rcv.ssb_token);
so = TAILQ_FIRST(&head->so_comp);
- if (so == NULL) /* Should never happen */
+ if (so == NULL) { /* Should never happen */
+ lwkt_reltoken(&head->so_rcv.ssb_token);
return;
+ }
TAILQ_REMOVE(&head->so_comp, so, so_list);
head->so_qlen--;
+ lwkt_reltoken(&head->so_rcv.ssb_token);
/* XXX KNOTE(&head->so_rcv.ssb_sel.si_note, 0); */
- so->so_state &= ~SS_COMP;
+ soclrstate(so, SS_COMP);
so->so_head = NULL;
soaccept(so, &sa);
pcbp->type = type;
/* Link the pcb and the socket */
+ soreference(so);
so->so_pcb = (caddr_t) pcbp;
pcbp->ng_socket = so;
ng_detach_common(struct ngpcb *pcbp, int which)
{
struct ngsock *sockdata;
+ struct socket *so;
if (pcbp->sockdata) {
sockdata = pcbp->sockdata;
if ((--sockdata->refs == 0) && (sockdata->node != NULL))
ng_rmnode(sockdata->node);
}
- pcbp->ng_socket->so_pcb = NULL;
+ so = pcbp->ng_socket;
+ so->so_pcb = NULL;
pcbp->ng_socket = NULL;
+ sofree(so); /* remove pcb ref */
+
LIST_REMOVE(pcbp, socks);
FREE(pcbp, M_PCB);
}
mtx_lock(&pcb->pcb_mtx);
+ so->so_pcb = NULL;
+
switch (pcb->state) {
case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT:
case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING:
FREE(pcb, M_NETGRAPH_BTSOCKET_RFCOMM);
soisdisconnected(so);
- so->so_pcb = NULL;
+ sofree(so); /* for so_pcb = NULL */
} /* ng_btsocket_rfcomm_detach */
/*
SOCKBUF_LOCK(&l2so->so_snd);
l2so->so_snd.sb_flags |= SB_UPCALL;
SOCKBUF_UNLOCK(&l2so->so_snd);
- l2so->so_state |= SS_NBIO;
+ sosetstate(l2so, SS_NBIO);
s->l2so = l2so;
mtx_lock(&s->session_mtx);
SOCKBUF_LOCK(&l2so->so_snd);
l2so->so_snd.sb_flags &= ~SB_UPCALL;
SOCKBUF_UNLOCK(&l2so->so_snd);
- l2so->so_state &= ~SS_NBIO;
+ soclrstate(l2so, SS_NBIO);
mtx_destroy(&s->session_mtx);
bzero(s, sizeof(*s));
l2so->so_head = NULL;
SOCK_LOCK(l2so);
soref(l2so);
- l2so->so_state |= SS_NBIO;
+ sosetstate(l2so, SS_NBIO);
SOCK_UNLOCK(l2so);
ACCEPT_UNLOCK();
priv->so->so_snd.sb_flags |= SB_UPCALL;
SOCKBUF_UNLOCK(&priv->so->so_snd);
SOCK_LOCK(priv->so);
- priv->so->so_state |= SS_NBIO;
+ sosetstate(priv->so, SS_NBIO);
SOCK_UNLOCK(priv->so);
/*
* --Original comment--
if ((so->so_state & SS_ISCONNECTING) != 0)
ERROUT(EALREADY);
if ((error = soconnect(so, sa, td)) != 0) {
- so->so_state &= ~SS_ISCONNECTING;
+ soclrstate(so, SS_ISCONNECTING);
ERROUT(error);
}
if ((so->so_state & SS_ISCONNECTING) != 0) {
if (priv->flags & KSF_CONNECTING) {
if ((error = so->so_error) != 0) {
so->so_error = 0;
- so->so_state &= ~SS_ISCONNECTING;
+ soclrstate(so, SS_ISCONNECTING);
}
if (!(so->so_state & SS_ISCONNECTING)) {
NG_MKMESSAGE(response, NGM_KSOCKET_COOKIE,
so->so_head = NULL;
SOCK_LOCK(so);
soref(so);
- so->so_state |= SS_NBIO;
+ sosetstate(so, SS_NBIO);
SOCK_UNLOCK(so);
ACCEPT_UNLOCK();
if ((priv->datasock) && (priv->datasock->ng_socket)) {
if (NG_NODE_NUMHOOKS(node) == 1)
- priv->datasock->ng_socket->so_state |= SS_ISCONNECTED;
+ sosetstate(priv->datasock->ng_socket, SS_ISCONNECTED);
else
- priv->datasock->ng_socket->so_state &= ~SS_ISCONNECTED;
+ soclrstate(priv->datasock->ng_socket, SS_ISCONNECTED);
}
return (0);
}
if ((priv->datasock) && (priv->datasock->ng_socket)) {
if (NG_NODE_NUMHOOKS(node) == 1)
- priv->datasock->ng_socket->so_state |= SS_ISCONNECTED;
+ sosetstate(priv->datasock->ng_socket, SS_ISCONNECTED);
else
- priv->datasock->ng_socket->so_state &= ~SS_ISCONNECTED;
+ soclrstate(priv->datasock->ng_socket, SS_ISCONNECTED);
}
if ((priv->flags & NGS_FLAG_NOLINGER) &&
#include <sys/jail.h>
#include <sys/kernel.h>
#include <sys/sysctl.h>
+
#include <sys/thread2.h>
+#include <sys/socketvar2.h>
#include <machine/limits.h>
if (ip6_auto_flowlabel)
inp->inp_flags |= IN6P_AUTOFLOWLABEL;
#endif
+ soreference(so);
so->so_pcb = inp;
LIST_INSERT_HEAD(&pcbinfo->pcblisthead, inp, inp_list);
pcbinfo->ipi_count++;
inp->inp_gencnt = ++ipi->ipi_gencnt;
in_pcbremlists(inp);
so->so_pcb = NULL;
- sofree(so);
+ sofree(so); /* remove pcb ref */
if (inp->inp_options)
m_free(inp->inp_options);
if (inp->inp_route.ro_rt)
static struct mbuf *ip_divert(struct mbuf *, int, int);
+static struct lwkt_token div_token = LWKT_TOKEN_MP_INITIALIZER(div_token);
+
/*
* Initialize divert connection block queue.
*/
* saving/testing the socket pointer is not MPSAFE. So we still
* need to hold BGL here.
*/
- get_mplock();
+ lwkt_gettoken(&div_token);
LIST_FOREACH(inp, &divcbinfo.pcblisthead, inp_list) {
if (inp->inp_flags & INP_PLACEMARKER)
continue;
sa = inp->inp_socket;
}
if (sa) {
- if (ssb_appendaddr(&sa->so_rcv, (struct sockaddr *)&divsrc, m,
- NULL) == 0)
+ lwkt_gettoken(&sa->so_rcv.ssb_token);
+ if (ssb_appendaddr(&sa->so_rcv, (struct sockaddr *)&divsrc, m, NULL) == 0)
m_freem(m);
else
sorwakeup(sa);
- rel_mplock();
+ lwkt_reltoken(&sa->so_rcv.ssb_token);
} else {
- rel_mplock();
m_freem(m);
ipstat.ips_noproto++;
ipstat.ips_delivered--;
}
+ lwkt_reltoken(&div_token);
}
#ifdef SMP
error = soreserve(so, div_sendspace, div_recvspace, ai->sb_rlimit);
if (error)
return error;
+ lwkt_gettoken(&div_token);
error = in_pcballoc(so, &divcbinfo);
- if (error)
+ if (error) {
+ lwkt_reltoken(&div_token);
return error;
+ }
inp = (struct inpcb *)so->so_pcb;
inp->inp_ip_p = proto;
inp->inp_vflag |= INP_IPV4;
* we always know "where" to send the packet.
*/
so->so_port = cpu0_soport(so, NULL, NULL);
- so->so_state |= SS_ISCONNECTED;
+ sosetstate(so, SS_ISCONNECTED);
+ lwkt_reltoken(&div_token);
return 0;
}
return 0;
}
+/*
+ * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort()
+ * will sofree() it when we return.
+ */
static int
div_abort(struct socket *so)
{
+ int error;
+
soisdisconnected(so);
- return div_detach(so);
+ error = div_detach(so);
+
+ return error;
}
static int
div_disconnect(struct socket *so)
{
+ int error;
+
if (!(so->so_state & SS_ISCONNECTED))
return ENOTCONN;
- return div_abort(so);
+ soreference(so);
+ error = div_abort(so);
+ sofree(so);
+
+ return error;
}
static int
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/sysctl.h>
+
#include <sys/thread2.h>
+#include <sys/socketvar2.h>
#include <machine/stdarg.h>
ip_fw_ctl_t *ip_fw_ctl_ptr;
ip_dn_ctl_t *ip_dn_ctl_ptr;
+static struct lwkt_token raw_token = LWKT_TOKEN_MP_INITIALIZER(raw_token);
+
+
/*
* hooks for multicast routing. They all default to NULL,
* so leave them not initialized and rely on BSS being set to 0.
__va_end(ap);
ripsrc.sin_addr = ip->ip_src;
+ lwkt_gettoken(&raw_token);
LIST_FOREACH(inp, &ripcbinfo.pcblisthead, inp_list) {
if (inp->inp_flags & INP_PLACEMARKER)
continue;
} else
#endif /*FAST_IPSEC*/
if (n) {
+ lwkt_gettoken(&last->inp_socket->so_rcv.ssb_token);
if (last->inp_flags & INP_CONTROLOPTS ||
last->inp_socket->so_options & SO_TIMESTAMP)
ip_savecontrol(last, &opts, ip, n);
if (ssb_appendaddr(&last->inp_socket->so_rcv,
- (struct sockaddr *)&ripsrc, n,
- opts) == 0) {
+ (struct sockaddr *)&ripsrc, n,
+ opts) == 0) {
/* should notify about lost packet */
m_freem(n);
if (opts)
m_freem(opts);
- } else
+ } else {
sorwakeup(last->inp_socket);
+ }
+ lwkt_reltoken(&last->inp_socket->so_rcv.ssb_token);
opts = 0;
}
}
if (last->inp_flags & INP_CONTROLOPTS ||
last->inp_socket->so_options & SO_TIMESTAMP)
ip_savecontrol(last, &opts, ip, m);
+ lwkt_gettoken(&last->inp_socket->so_rcv.ssb_token);
if (ssb_appendaddr(&last->inp_socket->so_rcv,
(struct sockaddr *)&ripsrc, m, opts) == 0) {
m_freem(m);
if (opts)
m_freem(opts);
- } else
+ } else {
sorwakeup(last->inp_socket);
+ }
+ lwkt_reltoken(&last->inp_socket->so_rcv.ssb_token);
} else {
m_freem(m);
ipstat.ips_noproto++;
ipstat.ips_delivered--;
}
+ lwkt_reltoken(&raw_token);
}
/*
error = soreserve(so, rip_sendspace, rip_recvspace, ai->sb_rlimit);
if (error)
return error;
- crit_enter();
+ lwkt_gettoken(&raw_token);
error = in_pcballoc(so, &ripcbinfo);
- crit_exit();
- if (error)
- return error;
- inp = (struct inpcb *)so->so_pcb;
- inp->inp_vflag |= INP_IPV4;
- inp->inp_ip_p = proto;
- inp->inp_ip_ttl = ip_defttl;
+ if (error == 0) {
+ inp = (struct inpcb *)so->so_pcb;
+ inp->inp_vflag |= INP_IPV4;
+ inp->inp_ip_p = proto;
+ inp->inp_ip_ttl = ip_defttl;
+ }
+ lwkt_reltoken(&raw_token);
return 0;
}
return 0;
}
+/*
+ * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort()
+ * will sofree() it when we return.
+ */
static int
rip_abort(struct socket *so)
{
+ int error;
+
soisdisconnected(so);
- if (so->so_state & SS_NOFDREF)
- return rip_detach(so);
- return 0;
+ if (so->so_state & SS_NOFDREF) /* XXX not sure why this test */
+ error = rip_detach(so);
+ else
+ error = 0;
+
+ return error;
}
static int
rip_disconnect(struct socket *so)
{
+ int error;
+
if ((so->so_state & SS_ISCONNECTED) == 0)
return ENOTCONN;
- return rip_abort(so);
+ soreference(so);
+ error = rip_abort(so);
+ sofree(so);
+
+ return error;
}
static int
}
goto skip;
}
+ lwkt_gettoken(&stcb->sctp_socket->so_rcv.ssb_token);
if (!sctp_sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv,
to, chk->data, control, stcb->asoc.my_vtag,
stcb->sctp_ep)) {
}
free_it = 1;
}
+ lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
} else {
/* append to a already started message. */
+ lwkt_gettoken(&stcb->sctp_socket->so_rcv.ssb_token);
if (sctp_sbspace(&stcb->sctp_socket->so_rcv) >=
(long)chk->send_size) {
ssb_append(&stcb->sctp_socket->so_rcv, chk->data);
free_it = 1;
}
+ lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
}
skip:
if (hold_locks == 0)
SCTP_INP_WUNLOCK(stcb->sctp_ep);
return;
}
+ lwkt_gettoken(&stcb->sctp_socket->so_rcv.ssb_token);
if (!sctp_sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv,
to, chk->data, control, stcb->asoc.my_vtag,
stcb->sctp_ep)) {
stcb->sctp_socket);
if (hold_locks == 0)
SCTP_INP_WUNLOCK(stcb->sctp_ep);
+ lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
return;
}
+ lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) {
if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
stcb->asoc.my_rwnd_control_len +=
} else {
if (sctp_sbspace(&stcb->sctp_socket->so_rcv) >=
(long)chk->send_size) {
+ lwkt_gettoken(&stcb->sctp_socket->so_rcv.ssb_token);
ssb_append(&stcb->sctp_socket->so_rcv, chk->data);
+ lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
cntDel++;
} else {
/* out of space in the sb */
SCTP_TCB_UNLOCK(stcb);
SCTP_INP_WLOCK(stcb->sctp_ep);
SCTP_TCB_LOCK(stcb);
+ lwkt_gettoken(&stcb->sctp_socket->so_rcv.ssb_token);
if (!sctp_sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv, to, dmbuf,
control, stcb->asoc.my_vtag, stcb->sctp_ep)) {
if (control) {
CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
}
sctp_m_freem(dmbuf);
+ lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
goto failed_express_del;
}
+ lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) {
if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
#if defined(__FreeBSD__) && __FreeBSD_version >= 502115
stcb->sctp_ep->sctp_socket->so_rcv.sb_state |= SBS_CANTSENDMORE;
#else
- stcb->sctp_ep->sctp_socket->so_state |= SS_CANTSENDMORE;
+ sosetstate(stcb->sctp_ep->sctp_socket, SS_CANTSENDMORE);
#endif
}
/* reset time */
#endif
int cnt;
- crit_enter();
SCTP_ASOC_CREATE_LOCK(inp);
SCTP_INP_WLOCK(inp);
if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) {
/* been here before */
- crit_exit();
kprintf("Endpoint was all gone (dup free)?\n");
SCTP_INP_WUNLOCK(inp);
SCTP_ASOC_CREATE_UNLOCK(inp);
/* now is there some left in our SHUTDOWN state? */
if (cnt_in_sd) {
inp->sctp_flags |= SCTP_PCB_FLAGS_SOCKET_GONE;
- crit_exit();
SCTP_INP_WUNLOCK(inp);
SCTP_ASOC_CREATE_UNLOCK(inp);
return;
#ifdef IPSEC
#ifdef __OpenBSD__
/* XXX IPsec cleanup here */
- crit_enter();
if (ip_pcb->inp_tdb_in)
TAILQ_REMOVE(&ip_pcb->inp_tdb_in->tdb_inp_in,
ip_pcb, inp_tdb_in_next);
ipsp_reffree(ip_pcb->inp_ipsec_localauth);
if (ip_pcb->inp_ipsec_remoteauth)
ipsp_reffree(ip_pcb->inp_ipsec_remoteauth);
- crit_exit();
#else
ipsec4_delete_pcbpolicy(ip_pcb);
#endif
ACCEPT_LOCK();
SOCK_LOCK(so);
#endif
- so->so_pcb = 0;
-#if defined(__FreeBSD__) && __FreeBSD_version > 500000
- sotryfree(so);
-#else
+ so->so_pcb = NULL;
sofree(so);
-#endif
}
if (ip_pcb->inp_options) {
sctppcbinfo.ipi_count_ep--;
SCTP_INP_INFO_WUNLOCK();
- crit_exit();
}
struct sctp_socket_q_list *sq;
/* first, lets purge the entry from the hash table. */
- crit_enter();
if (stcb->asoc.state == 0) {
kprintf("Freeing already free association:%p - huh??\n",
stcb);
- crit_exit();
return;
}
asoc = &stcb->asoc;
if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
sctp_inpcb_free(inp, 0);
}
- crit_exit();
}
sctp_insert_laddr(struct sctpladdr *list, struct ifaddr *ifa) {
struct sctp_laddr *laddr;
- crit_enter();
laddr = (struct sctp_laddr *)SCTP_ZONE_GET(sctppcbinfo.ipi_zone_laddr);
if (laddr == NULL) {
/* out of memory? */
- crit_exit();
return (EINVAL);
}
sctppcbinfo.ipi_count_laddr++;
/* insert it */
LIST_INSERT_HEAD(list, laddr, sctp_nxt_addr);
- crit_exit();
return (0);
}
void
sctp_remove_laddr(struct sctp_laddr *laddr)
{
- crit_enter();
/* remove from the list */
LIST_REMOVE(laddr, sctp_nxt_addr);
SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_laddr, laddr);
sctppcbinfo.ipi_count_laddr--;
sctppcbinfo.ipi_gencnt_laddr++;
- crit_exit();
}
/*
SCTP_INP_INFO_WLOCK();
LIST_INSERT_HEAD(&sctppcbinfo.iteratorhead, it, sctp_nxt_itr);
SCTP_INP_INFO_WUNLOCK();
- crit_enter();
sctp_iterator_timer(it);
- crit_exit();
return (0);
}
void
callout_reset(struct callout *c, int to_ticks, void (*ftn)(void *), void *arg)
{
- crit_enter();
if (c->c_flags & CALLOUT_PENDING)
callout_stop(c);
c->c_time = ticks + to_ticks;
TAILQ_INSERT_TAIL(&sctppcbinfo.callqueue, c, tqe);
#endif
- crit_exit();
}
int
callout_stop(struct callout *c)
{
- crit_enter();
/*
* Don't attempt to delete a callout that's not on the queue.
*/
if (!(c->c_flags & CALLOUT_PENDING)) {
c->c_flags &= ~CALLOUT_ACTIVE;
- crit_exit();
return (0);
}
c->c_flags &= ~(CALLOUT_ACTIVE | CALLOUT_PENDING| CALLOUT_FIRED);
TAILQ_REMOVE(&sctppcbinfo.callqueue, c, tqe);
c->c_func = NULL;
#endif
- crit_exit();
return (1);
}
struct calloutlist locallist;
int inited = 0;
- crit_enter();
/* run through and subtract and mark all callouts */
c = TAILQ_FIRST(&sctppcbinfo.callqueue);
while (c) {
/* now validate that it did not get canceled */
if (c->c_flags & CALLOUT_FIRED) {
c->c_flags &= ~CALLOUT_PENDING;
- crit_exit();
(*c->c_func)(c->c_arg);
- crit_enter();
}
c = TAILQ_FIRST(&locallist);
}
}
- crit_exit();
}
#endif
#endif /* _SCTP_NEEDS_CALLOUT_ */
SCTP_PCB_FLAGS_IN_TCPPOOL | /* Turn on Blocking IO */
(SCTP_PCB_COPY_FLAGS & inp->sctp_flags));
n_inp->sctp_socket = newso;
- newso->so_state |= SS_ISCONNECTED;
+ sosetstate(newso, SS_ISCONNECTED);
/* We remove it right away */
#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__DragonFly__)
SOCK_LOCK(head);
+ lwkt_gettoken(&head->so_rcv.ssb_token);
TAILQ_REMOVE(&head->so_comp, newso, so_list);
head->so_qlen--;
+ lwkt_reltoken(&head->so_rcv.ssb_token);
SOCK_UNLOCK(head);
#else
#endif /* SCTP_DEBUG */
#endif
+/*
+ * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort()
+ * will sofree() it when we return.
+ */
static int
sctp_abort(struct socket *so)
{
struct sctp_inpcb *inp;
+ int error;
inp = (struct sctp_inpcb *)so->so_pcb;
- if (inp == 0)
- return EINVAL; /* ??? possible? panic instead? */
-
- crit_enter();
- sctp_inpcb_free(inp, 1);
- crit_exit();
- return 0;
+ if (inp) {
+ sctp_inpcb_free(inp, 1);
+ error = 0;
+ } else {
+ error = EINVAL;
+ }
+ return error;
}
static int
#if defined(__FreeBSD__) && __FreeBSD_version >= 502115
so->so_rcv.sb_state &= ~SBS_CANTRCVMORE;
#else
- so->so_state &= ~SS_CANTRCVMORE;
+ soclrstate(so, SS_CANTRCVMORE);
#endif
/* This proc will wakeup for read and do nothing (I hope) */
crit_exit();
SCTP_TCB_UNLOCK(stcb);
SCTP_INP_WLOCK(stcb->sctp_ep);
SCTP_TCB_LOCK(stcb);
+ lwkt_gettoken(&stcb->sctp_socket->so_rcv.ssb_token);
if (!sctp_sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv,
to, m_notify, NULL, stcb->asoc.my_vtag, stcb->sctp_ep)) {
/* not enough room */
sctp_m_freem(m_notify);
SCTP_INP_WUNLOCK(stcb->sctp_ep);
+ lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
return;
}
+ lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)){
if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
SCTP_TCB_UNLOCK(stcb);
SCTP_INP_WLOCK(stcb->sctp_ep);
SCTP_TCB_LOCK(stcb);
+ lwkt_gettoken(&stcb->sctp_socket->so_rcv.ssb_token);
if (!sctp_sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv, to,
m_notify, NULL, stcb->asoc.my_vtag, stcb->sctp_ep)) {
/* not enough room */
sctp_m_freem(m_notify);
SCTP_INP_WUNLOCK(stcb->sctp_ep);
+ lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
return;
}
+ lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)){
if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
SCTP_TCB_UNLOCK(stcb);
SCTP_INP_WLOCK(stcb->sctp_ep);
SCTP_TCB_LOCK(stcb);
+ lwkt_gettoken(&stcb->sctp_socket->so_rcv.ssb_token);
if (!sctp_sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv, to,
m_notify, NULL, stcb->asoc.my_vtag, stcb->sctp_ep)) {
/* not enough room */
sctp_m_freem(m_notify);
+ lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
SCTP_INP_WUNLOCK(stcb->sctp_ep);
return;
}
+ lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)){
if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
SCTP_TCB_UNLOCK(stcb);
SCTP_INP_WLOCK(stcb->sctp_ep);
SCTP_TCB_LOCK(stcb);
+ lwkt_gettoken(&stcb->sctp_socket->so_rcv.ssb_token);
if (!sctp_sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv, to,
m_notify, NULL, stcb->asoc.my_vtag, stcb->sctp_ep)) {
/* not enough room */
sctp_m_freem(m_notify);
+ lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
SCTP_INP_WUNLOCK(stcb->sctp_ep);
return;
}
+ lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)){
if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
SCTP_TCB_UNLOCK(stcb);
SCTP_INP_WLOCK(stcb->sctp_ep);
SCTP_TCB_LOCK(stcb);
+ lwkt_gettoken(&stcb->sctp_socket->so_rcv.ssb_token);
if (!sctp_sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv, to,
m_notify, NULL, stcb->asoc.my_vtag, stcb->sctp_ep)) {
/* not enough room */
sctp_m_freem(m_notify);
+ lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
SCTP_INP_WUNLOCK(stcb->sctp_ep);
return;
}
+ lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)){
if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
SCTP_TCB_UNLOCK(stcb);
SCTP_INP_WLOCK(stcb->sctp_ep);
SCTP_TCB_LOCK(stcb);
+ lwkt_gettoken(&stcb->sctp_socket->so_rcv.ssb_token);
if (!sctp_sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv, to,
m_notify, NULL, stcb->asoc.my_vtag, stcb->sctp_ep)) {
/* not enough room */
sctp_m_freem(m_notify);
+ lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
SCTP_INP_WUNLOCK(stcb->sctp_ep);
return;
}
+ lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)){
if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
SCTP_TCB_UNLOCK(stcb);
SCTP_INP_WLOCK(stcb->sctp_ep);
SCTP_TCB_LOCK(stcb);
+ lwkt_gettoken(&stcb->sctp_socket->so_rcv.ssb_token);
if (!sctp_sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv, to,
m_notify, NULL, stcb->asoc.my_vtag, stcb->sctp_ep)) {
/* not enough room */
sctp_m_freem(m_notify);
+ lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
SCTP_INP_WUNLOCK(stcb->sctp_ep);
return;
}
+ lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)){
if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
u_int32_t retval;
retval = 0;
+ lwkt_gettoken(&so->so_rcv.ssb_token);
if (so->so_rcv.ssb_mb) {
/* grubbing time */
this = so->so_rcv.ssb_mb;
}
}
+ lwkt_reltoken(&so->so_rcv.ssb_token);
return (retval);
}
}
SOCKBUF_LOCK(old_sb);
SOCKBUF_LOCK(new_sb);
+ lwkt_gettoken(&old_sb->ssb_token);
+ lwkt_gettoken(&new_sb->ssb_token);
if (inp->sctp_vtag_first == asoc->my_vtag) {
/* First one must be moved */
*/
inp->sctp_vtag_first = sctp_get_first_vtag_from_sb(old);
}
+ lwkt_reltoken(&new_sb->ssb_token);
+ lwkt_reltoken(&old_sb->ssb_token);
SOCKBUF_UNLOCK(old_sb);
SOCKBUF_UNLOCK(new_sb);
}
#include <sys/syslog.h>
#include <sys/in_cksum.h>
+#include <sys/socketvar2.h>
+
#include <machine/cpu.h> /* before tcp_seq.h, for tcp_random18() */
#include <machine/stdarg.h>
KASSERT(LIST_EMPTY(&tp->t_segq) ||
LIST_FIRST(&tp->t_segq)->tqe_th->th_seq != tp->rcv_nxt,
("segment not coalesced"));
- if (so->so_state & SS_CANTRCVMORE)
+ if (so->so_state & SS_CANTRCVMORE) {
m_freem(q->tqe_m);
- else
+ } else {
+ lwkt_gettoken(&so->so_rcv.ssb_token);
ssb_appendstream(&so->so_rcv, q->tqe_m);
+ lwkt_reltoken(&so->so_rcv.ssb_token);
+ }
kfree(q, M_TSEGQ);
atomic_add_int(&tcp_reass_qsize, -1);
ND6_HINT(tp);
* being avoided (which is the default),
* so force an ack.
*/
+ lwkt_gettoken(&so->so_rcv.ssb_token);
if (newsize) {
tp->t_flags |= TF_RXRESIZED;
if (!ssb_reserve(&so->so_rcv, newsize,
}
m_adj(m, drop_hdrlen); /* delayed header drop */
ssb_appendstream(&so->so_rcv, m);
+ lwkt_reltoken(&so->so_rcv.ssb_token);
}
sorwakeup(so);
/*
so->so_oobmark = so->so_rcv.ssb_cc +
(tp->rcv_up - tp->rcv_nxt) - 1;
if (so->so_oobmark == 0)
- so->so_state |= SS_RCVATMARK;
+ sosetstate(so, SS_RCVATMARK);
sohasoutofband(so);
tp->t_oobflags &= ~(TCPOOB_HAVEDATA | TCPOOB_HADDATA);
}
tcpstat.tcps_rcvpack++;
tcpstat.tcps_rcvbyte += tlen;
ND6_HINT(tp);
- if (so->so_state & SS_CANTRCVMORE)
+ if (so->so_state & SS_CANTRCVMORE) {
m_freem(m);
- else
+ } else {
+ lwkt_gettoken(&so->so_rcv.ssb_token);
ssb_appendstream(&so->so_rcv, m);
+ lwkt_reltoken(&so->so_rcv.ssb_token);
+ }
sorwakeup(so);
} else {
if (!(tp->t_flags & TF_DUPSEG)) {
bufsize = roundup(bufsize, mss);
if (bufsize > sb_max)
bufsize = sb_max;
- if (bufsize > so->so_rcv.ssb_hiwat)
+ if (bufsize > so->so_rcv.ssb_hiwat) {
+ lwkt_gettoken(&so->so_rcv.ssb_token);
ssb_reserve(&so->so_rcv, bufsize, so, NULL);
+ lwkt_reltoken(&so->so_rcv.ssb_token);
+ }
}
/*
inp->inp_ppcb = NULL;
soisdisconnected(so);
+ /* note: pcb detached later on */
tcp_destroy_timermsg(tp);
if (tp->t_flags & TF_SYNCACHE)
#include <sys/thread2.h>
#include <sys/msgport2.h>
+#include <sys/socketvar2.h>
#include <net/if.h>
#include <net/netisr.h>
struct tcpcb *tp = 0;
TCPDEBUG0;
- crit_enter();
+ soreference(so);
inp = so->so_pcb;
TCPDEBUG1();
if (inp) {
so->so_linger = TCP_LINGERTIME;
tp = sototcpcb(so);
out:
+ sofree(so); /* from ref above */
TCPDEBUG2(PRU_ATTACH);
- crit_exit();
return error;
}
struct tcpcb *tp;
TCPDEBUG0;
- crit_enter();
inp = so->so_pcb;
/*
* If the inp is already detached it may have been due to an async
* close. Just return as if no error occured.
*/
- if (inp == NULL) {
- crit_exit();
+ if (inp == NULL)
return 0;
- }
/*
* It's possible for the tcpcb (tp) to disconnect from the inp due
tp = tcp_disconnect(tp);
TCPDEBUG2(PRU_DETACH);
}
- crit_exit();
return error;
}
#define COMMON_START(so, inp, ignore_error) \
TCPDEBUG0; \
\
- crit_enter(); \
inp = so->so_pcb; \
do { \
if (inp == NULL) { \
- crit_exit(); \
return (ignore_error ? 0 : EINVAL); \
} \
tp = intotcpcb(inp); \
TCPDEBUG1(); \
} while(0)
-#define COMMON_END(req) out: TCPDEBUG2(req); crit_exit(); return error; goto out
-
+#define COMMON_END(req) out: TCPDEBUG2(req); return error; goto out
/*
* Give the socket an address.
struct tcpcb *tp = NULL;
TCPDEBUG0;
- crit_enter();
inp = so->so_pcb;
if (so->so_state & SS_ISDISCONNECTED) {
error = ECONNABORTED;
goto out;
}
- if (inp == 0) {
- crit_exit();
+ if (inp == 0)
return (EINVAL);
- }
+
tp = intotcpcb(inp);
TCPDEBUG1();
in_setpeeraddr(so, nam);
struct tcpcb *tp = NULL;
TCPDEBUG0;
- crit_enter();
inp = so->so_pcb;
if (so->so_state & SS_ISDISCONNECTED) {
error = ECONNABORTED;
goto out;
}
- if (inp == 0) {
- crit_exit();
+ if (inp == 0)
return (EINVAL);
- }
tp = intotcpcb(inp);
TCPDEBUG1();
in6_mapped_peeraddr(so, nam);
#endif
TCPDEBUG0;
- crit_enter();
inp = so->so_pcb;
if (inp == NULL) {
}
/*
- * Abort the TCP.
+ * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort()
+ * will sofree() it when we return.
*/
static int
tcp_usr_abort(struct socket *so)
struct tcpcb *tp;
error = 0;
- crit_enter(); /* XXX */
inp = so->so_pcb;
- if (inp == NULL) {
- crit_exit();
+ if (inp == NULL)
return (ECONNRESET);
- }
+
if (sopt->sopt_level != IPPROTO_TCP) {
#ifdef INET6
if (INP_CHECK_SOCKAF(so, AF_INET6))
else
#endif /* INET6 */
error = ip_ctloutput(so, sopt);
- crit_exit();
return (error);
}
tp = intotcpcb(inp);
soopt_from_kbuf(sopt, &optval, sizeof optval);
break;
}
- crit_exit();
return (error);
}
#endif
if (so->so_snd.ssb_hiwat == 0 || so->so_rcv.ssb_hiwat == 0) {
+ lwkt_gettoken(&so->so_rcv.ssb_token);
error = soreserve(so, tcp_sendspace, tcp_recvspace,
ai->sb_rlimit);
+ lwkt_reltoken(&so->so_rcv.ssb_token);
if (error)
return (error);
}
#endif
inp->inp_vflag |= INP_IPV4;
tp = tcp_newtcpcb(inp);
- if (tp == 0) {
- int nofd = so->so_state & SS_NOFDREF; /* XXX */
-
- so->so_state &= ~SS_NOFDREF; /* don't free the socket yet */
+ if (tp == NULL) {
+ /*
+ * Make sure the socket is destroyed by the pcbdetach.
+ */
+ soreference(so);
#ifdef INET6
if (isipv6)
in6_pcbdetach(inp);
else
#endif
in_pcbdetach(inp);
- so->so_state |= nofd;
+ sofree(so); /* from ref above */
return (ENOBUFS);
}
tp->t_state = TCPS_CLOSED;
{
struct socket *so = tp->t_inpcb->inp_socket;
- if (tp->t_state < TCPS_ESTABLISHED)
+ if (tp->t_state < TCPS_ESTABLISHED) {
tp = tcp_close(tp);
- else if ((so->so_options & SO_LINGER) && so->so_linger == 0)
+ } else if ((so->so_options & SO_LINGER) && so->so_linger == 0) {
tp = tcp_drop(tp, 0);
- else {
+ } else {
+ lwkt_gettoken(&so->so_rcv.ssb_token);
soisdisconnecting(so);
sbflush(&so->so_rcv.sb);
tp = tcp_usrclosed(tp);
if (tp)
tcp_output(tp);
+ lwkt_reltoken(&so->so_rcv.ssb_token);
}
return (tp);
}
#include <sys/socketvar.h>
#include <sys/sysctl.h>
#include <sys/syslog.h>
-#include <sys/thread2.h>
#include <sys/in_cksum.h>
+#include <sys/thread2.h>
+#include <sys/socketvar2.h>
+
#include <machine/stdarg.h>
#include <net/if.h>
else if ((unsigned)cmd >= PRC_NCMDS || inetctlerrmap[cmd] == 0)
return;
if (ip) {
- crit_enter();
uh = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2));
inp = in_pcblookup_hash(&udbinfo, faddr, uh->uh_dport,
ip->ip_src, uh->uh_sport, 0, NULL);
if (inp != NULL && inp->inp_socket != NULL)
(*notify)(inp, inetctlerrmap[cmd]);
- crit_exit();
} else if (PRC_IS_REDIRECT(cmd)) {
struct netmsg_udp_notify nmsg;
error = SYSCTL_IN(req, addrs, sizeof addrs);
if (error)
return (error);
- crit_enter();
inp = in_pcblookup_hash(&udbinfo, addrs[1].sin_addr, addrs[1].sin_port,
addrs[0].sin_addr, addrs[0].sin_port, 1, NULL);
if (inp == NULL || inp->inp_socket == NULL) {
}
error = SYSCTL_OUT(req, inp->inp_socket->so_cred, sizeof(struct ucred));
out:
- crit_exit();
return (error);
}
SYSCTL_INT(_net_inet_udp, UDPCTL_RECVSPACE, recvspace, CTLFLAG_RW,
&udp_recvspace, 0, "Maximum incoming UDP datagram size");
+/*
+ * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort()
+ * will sofree() it when we return.
+ */
static int
udp_abort(struct socket *so)
{
struct inpcb *inp;
+ int error;
inp = so->so_pcb;
- if (inp == NULL)
- return EINVAL; /* ??? possible? panic instead? */
- soisdisconnected(so);
- crit_enter();
- in_pcbdetach(inp);
- crit_exit();
- return 0;
+ if (inp) {
+ soisdisconnected(so);
+ in_pcbdetach(inp);
+ error = 0;
+ } else {
+ error = EINVAL;
+ }
+ return error;
}
static int
error = soreserve(so, udp_sendspace, udp_recvspace, ai->sb_rlimit);
if (error)
return error;
- crit_enter();
error = in_pcballoc(so, &udbinfo);
- crit_exit();
if (error)
return error;
so->so_port = udp_soport_attach(so);
inp = so->so_pcb;
if (inp == NULL)
return EINVAL;
- crit_enter();
error = in_pcbbind(inp, nam, td);
- crit_exit();
if (error == 0) {
if (sin->sin_addr.s_addr != INADDR_ANY)
inp->inp_flags |= INP_WASBOUND_NOTANY;
inp = so->so_pcb;
if (inp == NULL)
return EINVAL;
- crit_enter();
in_pcbdetach(inp);
- crit_exit();
return 0;
}
if (inp->inp_faddr.s_addr == INADDR_ANY)
return ENOTCONN;
- crit_enter();
+ soreference(so);
in_pcbdisconnect(inp);
- crit_exit();
- so->so_state &= ~SS_ISCONNECTED; /* XXX */
+ soclrstate(so, SS_ISCONNECTED); /* XXX */
+ sofree(so);
ro = &inp->inp_route;
if (ro->ro_rt != NULL)
inp->inp_gencnt = ++ipi->ipi_gencnt;
in_pcbremlists(inp);
so->so_pcb = NULL;
- sofree(so);
+ sofree(so); /* remove pcb ref */
if (inp->in6p_options)
m_freem(inp->in6p_options);
if (currsp == NULL)
panic("ipsec4_getpolicybysock: currsp is NULL.");
+ lwkt_gettoken(&key_token);
+
/* when privilieged socket */
if (pcbsp->priv) {
switch (currsp->policy) {
case IPSEC_POLICY_BYPASS:
currsp->refcnt++;
*error = 0;
+ lwkt_reltoken(&key_token);
return currsp;
case IPSEC_POLICY_ENTRUST:
kprintf("DP ipsec4_getpolicybysock called "
"to allocate SP:%p\n", kernsp));
*error = 0;
+ lwkt_reltoken(&key_token);
return kernsp;
}
}
ip4_def_policy.refcnt++;
*error = 0;
+ lwkt_reltoken(&key_token);
return &ip4_def_policy;
case IPSEC_POLICY_IPSEC:
currsp->refcnt++;
*error = 0;
+ lwkt_reltoken(&key_token);
return currsp;
default:
ipseclog((LOG_ERR, "ipsec4_getpolicybysock: "
"Invalid policy for PCB %d\n", currsp->policy));
*error = EINVAL;
+ lwkt_reltoken(&key_token);
return NULL;
}
/* NOTREACHED */
kprintf("DP ipsec4_getpolicybysock called "
"to allocate SP:%p\n", kernsp));
*error = 0;
+ lwkt_reltoken(&key_token);
return kernsp;
}
"Illegal policy for non-priviliged defined %d\n",
currsp->policy));
*error = EINVAL;
+ lwkt_reltoken(&key_token);
return NULL;
case IPSEC_POLICY_ENTRUST:
}
ip4_def_policy.refcnt++;
*error = 0;
+ lwkt_reltoken(&key_token);
return &ip4_def_policy;
case IPSEC_POLICY_IPSEC:
currsp->refcnt++;
*error = 0;
+ lwkt_reltoken(&key_token);
return currsp;
default:
ipseclog((LOG_ERR, "ipsec4_getpolicybysock: "
"Invalid policy for PCB %d\n", currsp->policy));
*error = EINVAL;
+ lwkt_reltoken(&key_token);
return NULL;
}
/* NOTREACHED */
#include <sys/socketvar.h>
#include <sys/errno.h>
#include <sys/systm.h>
+
#include <sys/thread2.h>
+#include <sys/socketvar2.h>
#include <net/if.h>
#include <net/route.h>
return 0;
}
+/*
+ * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort()
+ * will sofree() it when we return.
+ */
static int
rip6_abort(struct socket *so)
{
+ int error;
+
soisdisconnected(so);
- return rip6_detach(so);
+ error = rip6_detach(so);
+
+ return error;
}
static int
rip6_disconnect(struct socket *so)
{
struct inpcb *inp = so->so_pcb;
+ int error;
if (!(so->so_state & SS_ISCONNECTED))
return ENOTCONN;
inp->in6p_faddr = kin6addr_any;
- return rip6_abort(so);
+ soreference(so);
+ error = rip6_abort(so);
+ sofree(so);
+
+ return error;
}
static int
#endif
-/* This is the same as the sctp_abort() could be made common */
+/*
+ * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort()
+ * will sofree() it when we return.
+ */
static int
sctp6_abort(struct socket *so)
{
struct sctp_inpcb *inp;
+ int error;
inp = (struct sctp_inpcb *)so->so_pcb;
- if (inp == NULL)
- return EINVAL; /* ??? possible? panic instead? */
- soisdisconnected(so);
- crit_enter();
- sctp_inpcb_free(inp, 1);
- crit_exit();
- return 0;
+ if (inp) {
+ soisdisconnected(so);
+ sctp_inpcb_free(inp, 1);
+ error = 0;
+ } else {
+ error = EINVAL;
+ }
+
+ return error;
}
static int
#include <sys/syslog.h>
#include <sys/proc.h>
#include <sys/priv.h>
+
#include <sys/thread2.h>
+#include <sys/socketvar2.h>
#include <net/if.h>
#include <net/route.h>
0, 0,
udp6_getcred, "S,ucred", "Get the ucred of a UDP6 connection");
+/*
+ * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort()
+ * will sofree() it when we return.
+ */
static int
udp6_abort(struct socket *so)
{
struct inpcb *inp;
+ int error;
inp = so->so_pcb;
- if (inp == NULL)
- return EINVAL; /* ??? possible? panic instead? */
- soisdisconnected(so);
- crit_enter();
- in6_pcbdetach(inp);
- crit_exit();
- return 0;
+ if (inp) {
+ soisdisconnected(so);
+ in6_pcbdetach(inp);
+ error = 0;
+ } else {
+ error = EINVAL;
+ }
+
+ return error;
}
static int
crit_enter();
in6_pcbdisconnect(inp);
crit_exit();
- so->so_state &= ~SS_ISCONNECTED; /* XXX */
+ soclrstate(so, SS_ISCONNECTED); /* XXX */
return 0;
}
return( EINVAL);
}
- crit_enter();
error = at_pcballoc( so );
- crit_exit();
if (error) {
return (error);
}
if ( ddp == NULL ) {
return( EINVAL);
}
- crit_enter();
at_pcbdetach( so, ddp );
- crit_exit();
return(0);
}
if ( ddp == NULL ) {
return( EINVAL);
}
- crit_enter();
error = at_pcbsetaddr(ddp, nam, td);
- crit_exit();
return (error);
}
return(EISCONN);
}
- crit_enter();
error = at_pcbconnect( ddp, nam, td );
- crit_exit();
if ( error == 0 )
soisconnected( so );
return(error);
return(ENOTCONN);
}
- crit_enter();
+ soreference(so);
at_pcbdisconnect( ddp );
ddp->ddp_fsat.sat_addr.s_node = ATADDR_ANYNODE;
- crit_exit();
soisdisconnected( so );
+ sofree(sp); /* soref above */
return(0);
}
return(EISCONN);
}
- crit_enter();
error = at_pcbconnect(ddp, addr, td);
- crit_exit();
if ( error ) {
return(error);
}
}
}
- crit_enter();
error = ddp_output( m, so );
if ( addr ) {
at_pcbdisconnect( ddp );
}
- crit_exit();
return(error);
}
+/*
+ * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort()
+ * will sofree() it when we return.
+ */
static int
ddp_abort(struct socket *so)
{
- struct ddpcb *ddp;
+ struct ddpcb *ddp;
+ int error;
- ddp = sotoddpcb( so );
- if ( ddp == NULL ) {
- return(EINVAL);
+ ddp = sotoddpcb(so);
+ if (ddb) {
+ soisdisconnected( so );
+ at_pcbdetach( so, ddp );
+ error = 0;
+ } else {
+ error = EINVAL;
}
- soisdisconnected( so );
- crit_enter();
- at_pcbdetach( so, ddp );
- crit_exit();
- return(0);
+ return error;
}
static void
at_pcbdetach( struct socket *so, struct ddpcb *ddp)
{
- soisdisconnected( so );
- so->so_pcb = 0;
- sofree( so );
+ soisdisconnected(so);
+ so->so_pcb = NULL;
+ sofree(so);
/* remove ddp from ddp_ports list */
if ( ddp->ddp_lsat.sat_port != ATADDR_ANYPORT &&
* 0 request processed
* error error processing request - reason indicated
*
+ * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort()
+ * will sofree() it when we return.
*/
static int
atm_aal5_abort(struct socket *so)
so->so_error = ECONNABORTED;
err = atm_sock_detach(so);
-
ATM_OUTRO();
}
* Break links and free control blocks
*/
so->so_pcb = NULL;
- sofree(so);
+ sofree(so); /* remove pcb ref */
atm_free((caddr_t)atp);
key_abort(struct socket *so)
{
int error;
- crit_enter();
+
error = raw_usrreqs.pru_abort(so);
- crit_exit();
+
return error;
}
{
struct socket *so = ipxp->ipxp_socket;
- so->so_pcb = 0;
+ so->so_pcb = NULL;
sofree(so);
+
if (ipxp->ipxp_route.ro_rt != NULL)
rtfree(ipxp->ipxp_route.ro_rt);
remque(ipxp);
{
struct socket *so = ipxp->ipxp_socket;
+ soreference(so);
ipx_pcbdisconnect(ipxp);
soisdisconnected(so);
+ sofree(so);
}
/*
tcp_output(tp);
}*/
so->so_error = errno;
+ soreference(so);
ipx_pcbdisconnect(ipxp);
soisdisconnected(so);
+ sofree(so);
}
static int
return (error);
}
+/*
+ * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort()
+ * will sofree() it when we return.
+ */
static int
ipx_usr_abort(struct socket *so)
{
struct ipxpcb *ipxp = sotoipxpcb(so);
- crit_enter();
ipx_pcbdetach(ipxp);
- crit_exit();
- sofree(so);
soisdisconnected(so);
+
return (0);
}
if (ipxp != NULL)
return (EINVAL);
- crit_enter();
error = ipx_pcballoc(so, &ipxpcb);
- crit_exit();
if (error == 0)
error = soreserve(so, ipxsendspace, ipxrecvspace,
ai->sb_rlimit);
if (!ipx_nullhost(ipxp->ipxp_faddr))
return (EISCONN);
- crit_enter();
error = ipx_pcbconnect(ipxp, nam, td);
- crit_exit();
if (error == 0)
soisconnected(so);
return (error);
if (ipxp == NULL)
return (ENOTCONN);
- crit_enter();
ipx_pcbdetach(ipxp);
- crit_exit();
return (0);
}
if (ipx_nullhost(ipxp->ipxp_faddr))
return (ENOTCONN);
- crit_enter();
+ soreference(so);
ipx_pcbdisconnect(ipxp);
- crit_exit();
soisdisconnected(so);
+ sofree(so);
+
return (0);
}
struct ipxpcb *ipxp = sotoipxpcb(so);
struct ipx_addr laddr;
- crit_enter();
if (nam != NULL) {
laddr = ipxp->ipxp_laddr;
if (!ipx_nullhost(ipxp->ipxp_faddr)) {
ipxp->ipxp_laddr = laddr;
}
send_release:
- crit_exit();
if (m != NULL)
m_freem(m);
return (error);
if ((error = priv_check_cred(ai->p_ucred, PRIV_ROOT, NULL_CRED_OKAY)) != 0)
return (error);
- crit_enter();
error = ipx_pcballoc(so, &ipxrawpcb);
- crit_exit();
if (error)
return (error);
error = soreserve(so, ipxsendspace, ipxrecvspace, ai->sb_rlimit);
if (so->so_rcv.ssb_cc)
so->so_oobmark = so->so_rcv.ssb_cc;
else
- so->so_state |= SS_RCVATMARK;
+ sosetstate(so, SS_RCVATMARK);
}
nq = q;
q = q->si_prev;
m_chtype(m, MT_OOBDATA);
spx_newchecks[1]++;
so->so_oobmark = 0;
- so->so_state &= ~SS_RCVATMARK;
+ soclrstate(so, SS_RCVATMARK);
}
if (packetp == 0) {
m->m_data += SPINC;
return (error);
}
+/*
+ * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort()
+ * will sofree() it when we return.
+ */
static int
spx_usr_abort(struct socket *so)
{
ipxp = sotoipxpcb(so);
cb = ipxtospxpcb(ipxp);
- crit_enter();
spx_drop(cb, ECONNABORTED);
- crit_exit();
+
return (0);
}
#endif
static LIST_HEAD(_spacqtree, secspacq) spacqtree; /* SP acquiring list */
+struct lwkt_token key_token = LWKT_TOKEN_MP_INITIALIZER(key_token);
+
struct key_cb key_cb;
/* search order for SAs */
}
/* get a SP entry */
- crit_enter();
+ lwkt_gettoken(&key_token);
KEYDEBUG(KEYDEBUG_IPSEC_DATA,
kprintf("*** objects\n");
kdebug_secpolicyindex(spidx));
goto found;
}
- crit_exit();
+ lwkt_reltoken(&key_token);
return NULL;
found:
microtime(&tv);
sp->lastused = tv.tv_sec;
sp->refcnt++;
- crit_exit();
+ lwkt_reltoken(&key_token);
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
kprintf("DP key_allocsp cause refcnt++:%d SP:%p\n",
sp->refcnt, sp));
return NULL;
}
- crit_enter();
+ lwkt_gettoken(&key_token);
LIST_FOREACH(sp, &sptree[dir], chain) {
if (sp->state == IPSEC_SPSTATE_DEAD)
continue;
goto found;
}
}
- crit_exit();
+ lwkt_reltoken(&key_token);
return NULL;
found:
microtime(&tv);
sp->lastused = tv.tv_sec;
sp->refcnt++;
- crit_exit();
+ lwkt_reltoken(&key_token);
return sp;
}
panic("key_checkrequest: Invalid policy defined.\n");
}
+ lwkt_gettoken(&key_token);
+
/* get current level */
level = ipsec_get_reqlevel(isr);
isr->sav = key_allocsa_policy(saidx);
/* When there is SA. */
- if (isr->sav != NULL)
+ if (isr->sav != NULL) {
+ lwkt_reltoken(&key_token);
return 0;
+ }
/* there is no SA */
if ((error = key_acquire(saidx, isr->sp)) != 0) {
/* XXX What should I do ? */
ipseclog((LOG_DEBUG, "key_checkrequest: error %d returned "
"from key_acquire.\n", error));
+ lwkt_reltoken(&key_token);
return error;
}
+ lwkt_reltoken(&key_token);
return level == IPSEC_LEVEL_REQUIRE ? ENOENT : 0;
}
* IPsec tunnel packet is received. But ESP tunnel mode is
* encrypted so we can't check internal IP header.
*/
- crit_enter();
+ lwkt_gettoken(&key_token);
LIST_FOREACH(sah, &sahtree, chain) {
/*
* search a valid state list for inbound packet.
}
/* not found */
- crit_exit();
+ lwkt_reltoken(&key_token);
return NULL;
found:
sav->refcnt++;
- crit_exit();
+ lwkt_reltoken(&key_token);
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
kprintf("DP allocsa cause refcnt++:%d SA:%p\n",
sav->refcnt, sav));
if (sp == NULL)
panic("key_freesp: NULL pointer is passed.\n");
+ lwkt_gettoken(&key_token);
sp->refcnt--;
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
kprintf("DP freesp cause refcnt--:%d SP:%p\n",
if (sp->refcnt == 0)
key_delsp(sp);
-
- return;
+ lwkt_reltoken(&key_token);
}
/*
if (so == NULL)
panic("key_freeso: NULL pointer is passed.\n");
+ lwkt_gettoken(&key_token);
switch (so->so_proto->pr_domain->dom_family) {
#ifdef INET
case PF_INET:
/* Does it have a PCB ? */
if (pcb == NULL)
- return;
+ break;
key_freesp_so(&pcb->inp_sp->sp_in);
key_freesp_so(&pcb->inp_sp->sp_out);
}
/* Does it have a PCB ? */
if (pcb == NULL)
- return;
+ break;
key_freesp_so(&pcb->inp_sp->sp_in);
key_freesp_so(&pcb->inp_sp->sp_out);
#else
/* Does it have a PCB ? */
if (pcb == NULL)
- return;
+ break;
key_freesp_so(&pcb->in6p_sp->sp_in);
key_freesp_so(&pcb->in6p_sp->sp_out);
#endif
default:
ipseclog((LOG_DEBUG, "key_freeso: unknown address family=%d.\n",
so->so_proto->pr_domain->dom_family));
- return;
+ break;
}
-
- return;
+ lwkt_reltoken(&key_token);
}
static void
if (sav == NULL)
panic("key_freesav: NULL pointer is passed.\n");
+ lwkt_gettoken(&key_token);
sav->refcnt--;
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
kprintf("DP freesav cause refcnt--:%d SA:%p SPI %u\n",
if (sav->refcnt == 0)
key_delsav(sav);
- return;
+ lwkt_reltoken(&key_token);
}
/* %%% SPD management */
if (sp->refcnt > 0)
return; /* can't free */
- crit_enter();
/* remove from SP index */
if (__LIST_CHAINED(sp))
LIST_REMOVE(sp, chain);
}
keydb_delsecpolicy(sp);
-
- crit_exit();
-
- return;
}
/*
{
struct secpolicy *newsp = NULL;
+ lwkt_gettoken(&key_token);
newsp = keydb_newsecpolicy();
- if (!newsp)
- return newsp;
-
- newsp->refcnt = 1;
- newsp->req = NULL;
+ if (newsp) {
+ newsp->refcnt = 1;
+ newsp->req = NULL;
+ }
+ lwkt_reltoken(&key_token);
return newsp;
}
return NULL;
}
+ lwkt_gettoken(&key_token);
if ((newsp = key_newsp()) == NULL) {
+ lwkt_reltoken(&key_token);
*error = ENOBUFS;
return NULL;
}
ipseclog((LOG_DEBUG,
"key_msg2sp: Invalid msg length.\n"));
key_freesp(newsp);
+ lwkt_reltoken(&key_token);
*error = EINVAL;
return NULL;
}
ipseclog((LOG_DEBUG, "key_msg2sp: "
"invalid ipsecrequest length.\n"));
key_freesp(newsp);
+ lwkt_reltoken(&key_token);
*error = EINVAL;
return NULL;
}
ipseclog((LOG_DEBUG,
"key_msg2sp: No more memory.\n"));
key_freesp(newsp);
+ lwkt_reltoken(&key_token);
*error = ENOBUFS;
return NULL;
}
"key_msg2sp: invalid proto type=%u\n",
xisr->sadb_x_ipsecrequest_proto));
key_freesp(newsp);
+ lwkt_reltoken(&key_token);
*error = EPROTONOSUPPORT;
return NULL;
}
"key_msg2sp: invalid mode=%u\n",
xisr->sadb_x_ipsecrequest_mode));
key_freesp(newsp);
+ lwkt_reltoken(&key_token);
*error = EINVAL;
return NULL;
}
u_int32_t reqid;
if ((reqid = key_newreqid()) == 0) {
key_freesp(newsp);
+ lwkt_reltoken(&key_token);
*error = ENOBUFS;
return NULL;
}
ipseclog((LOG_DEBUG, "key_msg2sp: invalid level=%u\n",
xisr->sadb_x_ipsecrequest_level));
key_freesp(newsp);
+ lwkt_reltoken(&key_token);
*error = EINVAL;
return NULL;
}
ipseclog((LOG_DEBUG, "key_msg2sp: invalid request "
"address length.\n"));
key_freesp(newsp);
+ lwkt_reltoken(&key_token);
*error = EINVAL;
return NULL;
}
ipseclog((LOG_DEBUG, "key_msg2sp: invalid request "
"address length.\n"));
key_freesp(newsp);
+ lwkt_reltoken(&key_token);
*error = EINVAL;
return NULL;
}
if (tlen < 0) {
ipseclog((LOG_DEBUG, "key_msg2sp: becoming tlen < 0.\n"));
key_freesp(newsp);
+ lwkt_reltoken(&key_token);
*error = EINVAL;
return NULL;
}
default:
ipseclog((LOG_DEBUG, "key_msg2sp: invalid policy type.\n"));
key_freesp(newsp);
+ lwkt_reltoken(&key_token);
*error = EINVAL;
return NULL;
}
-
+ lwkt_reltoken(&key_token);
*error = 0;
return newsp;
}
if (sp == NULL)
panic("key_sp2msg: NULL pointer was passed.\n");
+ lwkt_gettoken(&key_token);
tlen = key_getspreqmsglen(sp);
m = key_alloc_mbuf(tlen);
if (!m || m->m_next) { /*XXX*/
if (m)
m_freem(m);
+ lwkt_reltoken(&key_token);
return NULL;
}
+ isr->saidx.dst.ss_len);
}
}
-
+ lwkt_reltoken(&key_token);
return m;
}
if (sp->policy != IPSEC_POLICY_IPSEC)
panic("key_spdacquire: policy mismatched. IPsec is expected.\n");
+ lwkt_gettoken(&key_token);
/* get a entry to check whether sent message or not. */
if ((newspacq = key_getspacq(&sp->spidx)) != NULL) {
if (key_blockacq_count < newspacq->count) {
} else {
/* increment counter and do nothing. */
newspacq->count++;
+ lwkt_reltoken(&key_token);
return 0;
}
} else {
/* make new entry for blocking to send SADB_ACQUIRE. */
- if ((newspacq = key_newspacq(&sp->spidx)) == NULL)
+ if ((newspacq = key_newspacq(&sp->spidx)) == NULL) {
+ lwkt_reltoken(&key_token);
return ENOBUFS;
+ }
/* add to acqtree */
LIST_INSERT_HEAD(&spacqtree, newspacq, chain);
mtod(result, struct sadb_msg *)->sadb_msg_len =
PFKEY_UNIT64(result->m_pkthdr.len);
- return key_sendup_mbuf(NULL, m, KEY_SENDUP_REGISTERED);
+ error = key_sendup_mbuf(NULL, m, KEY_SENDUP_REGISTERED);
+ lwkt_reltoken(&key_token);
+ return error;
fail:
+ lwkt_reltoken(&key_token);
if (result)
m_freem(result);
return error;
struct sadb_lifetime *lt;
/* XXX: Why do we lock ? */
- crit_enter();
/* sanity check */
if (sp == NULL)
fail:
if (result)
m_freem(result);
- crit_exit();
return error;
}
if (sah == NULL)
panic("key_delsah: NULL pointer is passed.\n");
- crit_enter();
-
/* searching all SA registerd in the secindex. */
for (stateidx = 0;
stateidx < _ARRAYLEN(saorder_state_any);
}
/* don't delete sah only if there are savs. */
- if (zombie) {
- crit_exit();
+ if (zombie)
return;
- }
if (sah->sa_route.ro_rt) {
RTFREE(sah->sa_route.ro_rt);
KFREE(sah);
- crit_exit();
return;
}
struct sockaddr_in *sin;
struct in_ifaddr_container *iac;
#endif
+ int res;
/* sanity check */
if (sa == NULL)
panic("key_ismyaddr: NULL pointer is passed.\n");
+ lwkt_gettoken(&key_token);
switch (sa->sa_family) {
#ifdef INET
case AF_INET:
sin->sin_len == ia->ia_addr.sin_len &&
sin->sin_addr.s_addr == ia->ia_addr.sin_addr.s_addr)
{
+ lwkt_reltoken(&key_token);
return 1;
}
}
+ res = 0;
break;
#endif
#ifdef INET6
case AF_INET6:
- return key_ismyaddr6((struct sockaddr_in6 *)sa);
+ res = key_ismyaddr6((struct sockaddr_in6 *)sa);
+ break;
#endif
+ default:
+ res = 0;
+ break;
}
-
- return 0;
+ lwkt_reltoken(&key_token);
+ return res;
}
#ifdef INET6
microtime(&tv);
- crit_enter();
+ lwkt_gettoken(&key_token);
/* SPD */
{
callout_reset(&key_timehandler_ch, hz, key_timehandler, NULL);
#endif /* IPSEC_DEBUG2 */
- crit_exit();
+ lwkt_reltoken(&key_token);
return;
}
* check all type of SA, because there is a potential that
* one socket is registered to multiple type of SA.
*/
+ lwkt_gettoken(&key_token);
for (i = 0; i <= SADB_SATYPE_MAX; i++) {
LIST_FOREACH(reg, ®tree[i], chain) {
if (reg->so == so
}
}
}
-
- return;
+ lwkt_reltoken(&key_token);
}
/*
int error = -1;
struct sadb_lifetime *lt;
- /* XXX: Why do we lock ? */
- crit_enter();
-
/* sanity check */
if (sav == NULL)
panic("key_expire: NULL pointer is passed.\n");
mtod(result, struct sadb_msg *)->sadb_msg_len =
PFKEY_UNIT64(result->m_pkthdr.len);
- crit_exit();
return key_sendup_mbuf(NULL, result, KEY_SENDUP_REGISTERED);
fail:
if (result)
m_freem(result);
- crit_exit();
return error;
}
goto senderror;
}
- return (*key_typesw[msg->sadb_msg_type])(so, m, &mh);
+ lwkt_gettoken(&key_token);
+ error = (*key_typesw[msg->sadb_msg_type])(so, m, &mh);
+ lwkt_reltoken(&key_token);
+ return error;
senderror:
msg->sadb_msg_errno = error;
- return key_sendup_mbuf(so, m, target);
+ lwkt_gettoken(&key_token);
+ error = key_sendup_mbuf(so, m, target);
+ lwkt_reltoken(&key_token);
+ return error;
}
static int
struct secashead *sah;
struct route *ro;
+ lwkt_gettoken(&key_token);
LIST_FOREACH(sah, &sahtree, chain) {
ro = &sah->sa_route;
if (ro->ro_rt && dst->sa_len == ro->ro_dst.sa_len
ro->ro_rt = NULL;
}
}
-
- return;
+ lwkt_reltoken(&key_token);
}
static void
void
key_sa_stir_iv(struct secasvar *sav)
{
-
if (!sav->iv)
panic("key_sa_stir_iv called with sav == NULL");
key_randomfill(sav->iv, sav->ivlen);
#ifdef _KERNEL
extern struct key_cb key_cb;
+extern struct lwkt_token key_token;
struct secpolicy;
struct secpolicyindex;
#include <net/pfkeyv2.h>
#include "keydb.h"
+#include "key.h"
#include <netinet6/ipsec.h>
#include <net/net_osdep.h>
void
keydb_refsecasvar(struct secasvar *p)
{
- crit_enter();
+ lwkt_gettoken(&key_token);
p->refcnt++;
- crit_exit();
+ lwkt_reltoken(&key_token);
}
void
keydb_freesecasvar(struct secasvar *p)
{
- crit_enter();
+ lwkt_gettoken(&key_token);
p->refcnt--;
/* negative refcnt will cause panic intentionally */
if (p->refcnt <= 0)
keydb_delsecasvar(p);
- crit_exit();
+ lwkt_reltoken(&key_token);
}
static void
}
/*XXX giant lock*/
- crit_enter();
+ lwkt_gettoken(&key_token);
error = key_parse(m, so);
m = NULL;
- crit_exit();
+ lwkt_reltoken(&key_token);
end:
if (m)
m_freem(m);
pfkeystat.in_msgtype[pmsg->sadb_msg_type]++;
}
- if (!ssb_appendaddr(&rp->rcb_socket->so_rcv, (struct sockaddr *)&key_src,
- m, NULL)) {
+ lwkt_gettoken(&key_token);
+ if (!ssb_appendaddr(&rp->rcb_socket->so_rcv,
+ (struct sockaddr *)&key_src, m, NULL)) {
pfkeystat.in_nomem++;
m_freem(m);
error = ENOBUFS;
- } else
+ } else {
error = 0;
+ }
+ lwkt_reltoken(&key_token);
sorwakeup(rp->rcb_socket);
return error;
}
pfkeystat.in_msgtype[msg->sadb_msg_type]++;
}
+ lwkt_gettoken(&key_token);
+
LIST_FOREACH(rp, &rawcb_list, list)
{
if (rp->rcb_proto.sp_family != PF_KEY)
if ((n = m_copy(m, 0, (int)M_COPYALL)) == NULL) {
m_freem(m);
pfkeystat.in_nomem++;
+ lwkt_reltoken(&key_token);
return ENOBUFS;
}
if ((error = key_sendup0(rp, n, 0)) != 0) {
+ lwkt_reltoken(&key_token);
m_freem(m);
return error;
}
n = NULL;
}
+ lwkt_reltoken(&key_token);
if (so) {
error = key_sendup0(sotorawcb(so), m, 0);
{
int error;
- crit_enter();
+ lwkt_gettoken(&key_token);
error = raw_usrreqs.pru_abort(so);
- crit_exit();
+ lwkt_reltoken(&key_token);
+
return error;
}
* Probably we should try to do more of this work beforehand and
* eliminate the critical section.
*/
- crit_enter();
+ lwkt_gettoken(&key_token);
so->so_pcb = (caddr_t)kp;
error = raw_usrreqs.pru_attach(so, proto, ai);
kp = (struct keycb *)sotorawcb(so);
if (error) {
kfree(kp, M_PCB);
so->so_pcb = (caddr_t) 0;
- crit_exit();
+ lwkt_reltoken(&key_token);
return error;
}
soisconnected(so);
so->so_options |= SO_USELOOPBACK;
- crit_exit();
+ lwkt_reltoken(&key_token);
return 0;
}
{
int error;
- crit_enter();
+ lwkt_gettoken(&key_token);
error = raw_usrreqs.pru_bind(so, nam, td); /* xxx just EINVAL */
- crit_exit();
+ lwkt_reltoken(&key_token);
return error;
}
{
int error;
- crit_enter();
+ lwkt_gettoken(&key_token);
error = raw_usrreqs.pru_connect(so, nam, td); /* XXX just EINVAL */
- crit_exit();
+ lwkt_reltoken(&key_token);
return error;
}
struct keycb *kp = (struct keycb *)sotorawcb(so);
int error;
- crit_enter();
+ lwkt_gettoken(&key_token);
if (kp != 0) {
if (kp->kp_raw.rcb_proto.sp_protocol
== PF_KEY) /* XXX: AF_KEY */
key_freereg(so);
}
error = raw_usrreqs.pru_detach(so);
- crit_exit();
+ lwkt_reltoken(&key_token);
return error;
}
{
int error;
- crit_enter();
+ lwkt_gettoken(&key_token);
error = raw_usrreqs.pru_disconnect(so);
- crit_exit();
+ lwkt_reltoken(&key_token);
return error;
}
{
int error;
- crit_enter();
+ lwkt_gettoken(&key_token);
error = raw_usrreqs.pru_peeraddr(so, nam);
- crit_exit();
+ lwkt_reltoken(&key_token);
return error;
}
{
int error;
- crit_enter();
+ lwkt_gettoken(&key_token);
error = raw_usrreqs.pru_send(so, flags, m, nam, control, td);
- crit_exit();
+ lwkt_reltoken(&key_token);
return error;
}
{
int error;
- crit_enter();
+ lwkt_gettoken(&key_token);
error = raw_usrreqs.pru_shutdown(so);
- crit_exit();
+ lwkt_reltoken(&key_token);
return error;
}
{
int error;
- crit_enter();
+ lwkt_gettoken(&key_token);
error = raw_usrreqs.pru_sockaddr(so, nam);
- crit_exit();
+ lwkt_reltoken(&key_token);
return error;
}
/*
* we turn on 'drain' *before* we sofree.
*/
- npcb_free(npcb, NPCB_DESTROY); /* drain */
so->so_pcb = NULL;
- sofree(so);
+ npcb_free(npcb, NPCB_DESTROY); /* drain */
+ sofree(so); /* remove pcb ref */
out:
crit_exit();
return (error);
return (error);
}
+/*
+ * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort()
+ * will sofree() it when we return.
+ */
static int
natm_usr_abort(struct socket *so)
{
- return natm_usr_shutdown(so);
+ int error;
+
+ error = natm_usr_shutdown(so);
+
+ return error;
}
static int
* we turn on 'drain' *before* we sofree.
*/
- npcb_free(npcb, NPCB_DESTROY); /* drain */
so->so_pcb = NULL;
- sofree(so);
+ npcb_free(npcb, NPCB_DESTROY); /* drain */
+ sofree(so); /* remove pcb ref */
break;
tsleep((caddr_t)&so->so_timeo, 0, "ncpcon", 2 * hz);
if ((so->so_state & SS_ISCONNECTING) &&
so->so_error == 0 /*&& rep &&*/) {
- so->so_state &= ~SS_ISCONNECTING;
+ soclrstate(so, SS_ISCONNECTING);
crit_exit();
goto bad;
}
{
struct socket *so = nsp->nsp_socket;
+ soreference(so);
ns_pcbdisconnect(nsp);
soisdisconnected(so);
+ sofree(so);
}
+
/*
* Drop connection, reporting
* the specified error.
tcp_output(tp);
}*/
so->so_error = errno;
+ soreference(so);
ns_pcbdisconnect(nsp);
soisdisconnected(so);
+ sofree(so);
}
int noIdpRoute;
* IDP_USRREQ PROCEDURES
*/
+/*
+ * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort()
+ * will sofree() it when we return.
+ */
static int
idp_usr_abort(struct socket *so)
{
if (nsp) {
ns_pcbdetach(nsp);
- sofree(so);
soisdisconnected(so);
error = 0;
} else {
error = EINVAL;
}
+
return(error);
}
error = ENOTCONN;
} else {
error = 0;
+ soreference(so);
ns_pcbdisconnect(nsp);
soisdisconnected(so);
+ sofree(so);
}
} else {
error = EINVAL;
{
struct socket *so = nsp->nsp_socket;
- so->so_pcb = 0;
+ so->so_pcb = NULL;
sofree(so);
if (nsp->nsp_route.ro_rt)
rtfree(nsp->nsp_route.ro_rt);
if (so->so_rcv.ssb_cc)
so->so_oobmark = so->so_rcv.ssb_cc;
else
- so->so_state |= SS_RCVATMARK;
+ sosetstate(so, SS_RCVATMARK);
}
nq = q;
q = q->si_prev;
m_chtype(m, MT_OOBDATA);
spp_newchecks[1]++;
so->so_oobmark = 0;
- so->so_state &= ~SS_RCVATMARK;
+ soclrstate(so, SS_RCVATMARK);
}
if (packetp == 0) {
m->m_data += SPINC;
* SPP_USRREQ PROCEDURES
*/
+/*
+ * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort()
+ * will sofree() it when we return.
+ */
static int
spp_usr_abort(struct socket *so)
{
} else {
error = EINVAL;
}
+
return(error);
}
}
kfree(cb->s_idp, M_IDP);
kfree(cb, M_SPPCB);
- nsp->nsp_pcb = 0;
+ nsp->nsp_pcb = NULL;
soisdisconnected(so);
ns_pcbdetach(nsp);
sppstat.spps_closed++;
tsleep(&so->so_timeo, 0, "nbcon", 2 * hz);
if ((so->so_state & SS_ISCONNECTING) && so->so_error == 0 &&
(error = nb_intr(nbp, td)) != 0) {
- so->so_state &= ~SS_ISCONNECTING;
+ soclrstate(so, SS_ISCONNECTING);
crit_exit();
goto bad;
}
#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>
#endif
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 */
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 */
/*
* 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 */
#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_UNUSED0100 0x0100
#define SS_ASYNC 0x0200 /* async i/o notify */
#define SS_ISCONFIRMING 0x0400 /* deciding to accept connection req */
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);
* Acquire a lock on a signalsockbuf, sleep if the lock is already held.
* The sleep is interruptable unless SSB_NOINTR is set in the ssb.
*
+ * We also acquire the token on success. This token is used to interlock
+ * frontend/backend operations until the sockbuf itself can be made mpsafe.
+ *
* Returns 0 on success, non-zero if the lock could not be acquired.
*/
static __inline int
return _ssb_lock(ssb);
return EWOULDBLOCK;
}
- if (atomic_cmpset_int(&ssb->ssb_flags, flags, flags | SSB_LOCK))
+ if (atomic_cmpset_int(&ssb->ssb_flags, flags, flags|SSB_LOCK)) {
+ lwkt_gettoken(&ssb->ssb_token);
return(0);
+ }
}
}
uint32_t flags;
KKASSERT(ssb->ssb_flags & SSB_LOCK);
+ lwkt_reltoken(&ssb->ssb_token);
for (;;) {
flags = ssb->ssb_flags;
cpu_ccfence();
}
}
+static __inline void
+sosetstate(struct socket *so, short state)
+{
+ atomic_set_short(&so->so_state, state);
+}
+
+static __inline void
+soclrstate(struct socket *so, short state)
+{
+ atomic_clear_short(&so->so_state, state);
+}
+
+static __inline void
+soreference(struct socket *so)
+{
+ atomic_add_int(&so->so_refs, 1);
+}
+
#endif
#include <sys/un.h>
#include <sys/thread2.h>
+#include <sys/socketvar2.h>
#include "fifo.h"
}
fip->fi_readers = fip->fi_writers = 0;
wso->so_snd.ssb_lowat = PIPE_BUF;
- rso->so_state |= SS_CANTRCVMORE;
+ sosetstate(rso, SS_CANTRCVMORE);
}
if (ap->a_mode & FREAD) {
fip->fi_readers++;
#include <sys/signal2.h>
#include <sys/mutex2.h>
+#include <sys/socketvar2.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
if ((so->so_state & SS_ISCONNECTING) &&
so->so_error == 0 && rep &&
(error = nfs_sigintr(nmp, rep, rep->r_td)) != 0){
- so->so_state &= ~SS_ISCONNECTING;
+ soclrstate(so, SS_ISCONNECTING);
crit_exit();
goto bad;
}