Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/netmap/netmap_freebsd.c
Context not available. | |||||
/* ======================== FREEBSD-SPECIFIC ROUTINES ================== */ | /* ======================== FREEBSD-SPECIFIC ROUTINES ================== */ | ||||
static struct mtx nm_knlist_lock; | |||||
MTX_SYSINIT(nm_knlist_lock, &nm_knlist_lock, "knlist lock for netmap ports", | |||||
MTX_DEF); | |||||
void nm_os_selinfo_init(NM_SELINFO_T *si) { | void nm_os_selinfo_init(NM_SELINFO_T *si) { | ||||
struct mtx *m = &si->m; | knlist_init_mtx(&si->si_note, &nm_knlist_lock); | ||||
mtx_init(m, "nm_kn_lock", NULL, MTX_DEF); | |||||
knlist_init_mtx(&si->si.si_note, m); | |||||
} | } | ||||
void | void | ||||
nm_os_selinfo_uninit(NM_SELINFO_T *si) | nm_os_selinfo_uninit(NM_SELINFO_T *si) | ||||
{ | { | ||||
/* XXX kqueue(9) needed; these will mirror knlist_init. */ | /* XXX kqueue(9) needed; these will mirror knlist_init. */ | ||||
knlist_delete(&si->si.si_note, curthread, /*islocked=*/0); | knlist_delete(&si->si_note, curthread, /*islocked=*/0); | ||||
knlist_destroy(&si->si.si_note); | knlist_destroy(&si->si_note); | ||||
/* now we don't need the mutex anymore */ | |||||
mtx_destroy(&si->m); | |||||
} | } | ||||
void * | void * | ||||
Context not available. | |||||
* function that it is being called from 'nm_os_selwakeup'; this | * function that it is being called from 'nm_os_selwakeup'; this | ||||
* is necessary because when netmap_knrw() is called by the kevent | * is necessary because when netmap_knrw() is called by the kevent | ||||
* subsystem (i.e. kevent_scan()) we also need to call netmap_poll(). | * subsystem (i.e. kevent_scan()) we also need to call netmap_poll(). | ||||
* The knote uses a private mutex associated to the 'si' (see struct | |||||
* selinfo, struct nm_selinfo, and nm_os_selinfo_init). | |||||
* | * | ||||
* The netmap_kqfilter() function registers one or another f_event | * The netmap_kqfilter() function registers one or another f_event | ||||
* depending on read or write mode. A pointer to the struct | * depending on read or write mode. A pointer to the struct | ||||
Context not available. | |||||
void | void | ||||
nm_os_selwakeup(struct nm_selinfo *si) | nm_os_selwakeup(struct selinfo *si) | ||||
{ | { | ||||
if (netmap_verbose) | if (netmap_verbose) | ||||
nm_prinf("on knote %p", &si->si.si_note); | nm_prinf("on knote %p", &si->si_note); | ||||
selwakeuppri(&si->si, PI_NET); | selwakeuppri(si, PI_NET); | ||||
/* We use a non-zero hint to distinguish this notification call | /* We use a non-zero hint to distinguish this notification call | ||||
* from the call done in kqueue_scan(), which uses hint=0. | * from the call done in kqueue_scan(), which uses hint=0. | ||||
*/ | */ | ||||
KNOTE(&si->si.si_note, /*hint=*/0x100, | KNOTE(&si->si_note, /*hint=*/0x100, | ||||
mtx_owned(&si->m) ? KNF_LISTLOCKED : 0); | mtx_owned(&nm_knlist_lock) ? KNF_LISTLOCKED : 0); | ||||
} | } | ||||
void | void | ||||
nm_os_selrecord(struct thread *td, struct nm_selinfo *si) | nm_os_selrecord(struct thread *td, struct selinfo *si) | ||||
{ | { | ||||
selrecord(td, &si->si); | selrecord(td, si); | ||||
} | } | ||||
static void | static void | ||||
netmap_knrdetach(struct knote *kn) | netmap_knrdetach(struct knote *kn) | ||||
{ | { | ||||
struct netmap_priv_d *priv = (struct netmap_priv_d *)kn->kn_hook; | struct netmap_priv_d *priv = (struct netmap_priv_d *)kn->kn_hook; | ||||
struct selinfo *si = &priv->np_si[NR_RX]->si; | struct selinfo *si = priv->np_si[NR_RX]; | ||||
nm_prinf("remove selinfo %p", si); | nm_prinf("remove selinfo %p", si); | ||||
knlist_remove(&si->si_note, kn, /*islocked=*/0); | knlist_remove(&si->si_note, kn, /*islocked=*/0); | ||||
Context not available. | |||||
netmap_knwdetach(struct knote *kn) | netmap_knwdetach(struct knote *kn) | ||||
{ | { | ||||
struct netmap_priv_d *priv = (struct netmap_priv_d *)kn->kn_hook; | struct netmap_priv_d *priv = (struct netmap_priv_d *)kn->kn_hook; | ||||
struct selinfo *si = &priv->np_si[NR_TX]->si; | struct selinfo *si = priv->np_si[NR_TX]; | ||||
nm_prinf("remove selinfo %p", si); | nm_prinf("remove selinfo %p", si); | ||||
knlist_remove(&si->si_note, kn, /*islocked=*/0); | knlist_remove(&si->si_note, kn, /*islocked=*/0); | ||||
Context not available. | |||||
struct netmap_priv_d *priv; | struct netmap_priv_d *priv; | ||||
int error; | int error; | ||||
struct netmap_adapter *na; | struct netmap_adapter *na; | ||||
struct nm_selinfo *si; | struct selinfo *si; | ||||
int ev = kn->kn_filter; | int ev = kn->kn_filter; | ||||
if (ev != EVFILT_READ && ev != EVFILT_WRITE) { | if (ev != EVFILT_READ && ev != EVFILT_WRITE) { | ||||
Context not available. | |||||
kn->kn_fop = (ev == EVFILT_WRITE) ? | kn->kn_fop = (ev == EVFILT_WRITE) ? | ||||
&netmap_wfiltops : &netmap_rfiltops; | &netmap_wfiltops : &netmap_rfiltops; | ||||
kn->kn_hook = priv; | kn->kn_hook = priv; | ||||
knlist_add(&si->si.si_note, kn, /*islocked=*/0); | knlist_add(&si->si_note, kn, /*islocked=*/0); | ||||
return 0; | return 0; | ||||
} | } | ||||
Context not available. |