int sblock(struct sockbuf *sb, int flags) { KASSERT((flags & SBL_VALID) == flags, ("sblock: flags invalid (0x%x)", flags)); if (flags & SBL_WAIT) { rw_rlock(&sb->sb_rwlock); return (0); } else { if (rw_try_rlock(&sb->sb_rwlock) == 0) return (EWOULDBLOCK); return (0); } }
/* * Caveat: Called from interrupt context */ static void ps_ether_input(struct ifnet *ifp, struct mbuf **mp) { struct pspcb *psp = NULL, *psp_next; struct ether_header *eh; struct sockaddr esa; struct socket *so = NULL; u_short etype; eh = mtod(*mp, struct ether_header *); etype = ntohs(eh->ether_type); if (PS_ETHER_TYPE != etype) return; /* * We currently place the mbuf to a bound socket's rcv. * * However,this is not the long term plan. Instead, in the * longer term we should fill in a page, place the page at * the local cache, and then wake up the network receiver. * through the bound socket. */ PS_PRINTF(PS_DEBUG_SOCKET, "m = %p\n", *mp); LIST_FOREACH_SAFE(psp, pspcbhead, psp_list, psp_next) { #if __FreeBSD_version >= 701000 if (!rw_try_rlock(&psp->psp_lock)) { PS_PRINTF(PS_DEBUG_SOCKET | PS_DEBUG_WARNING, "psp is w-locked, discard data\n"); /* Simply discard data if the psp happens to be w-locked */ continue; } #endif if (ifp == psp->psp_ifp) { so = psp->psp_socket; #if __FreeBSD_version >= 701000 rw_runlock(&psp->psp_lock); #endif break; } #if __FreeBSD_version >= 701000 rw_runlock(&psp->psp_lock); #endif } if (so) { /* * XXX: We don't understand why simple sbappend * doesn't work. But spappendaddr does. So be it. */ esa.sa_family = AF_LINK; esa.sa_len = 0; m_adj(*mp, sizeof(*eh)); /* Remove ethernet header */ if (!sbappendaddr(&so->so_rcv, &esa, *mp, NULL)) { PS_PRINTF(PS_DEBUG_SOCKET | PS_DEBUG_WARNING, "sbappendaddr() failed. " "Probably not enough buffer space. " "Packet lost.\n"); } sorwakeup(so); *mp = NULL; return; } #ifdef NOTYET /* We could free *mp here, but we don't. It gets discarded anyway */ m_freem(*mp); *mp = NULL; #endif return; }