Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet6/in6_mcast.c
Show First 20 Lines • Show All 514 Lines • ▼ Show 20 Lines | |||||
* dedicated thread to avoid deadlocks when draining in6m_release tasks. | * dedicated thread to avoid deadlocks when draining in6m_release tasks. | ||||
*/ | */ | ||||
TASKQUEUE_DEFINE_THREAD(in6m_free); | TASKQUEUE_DEFINE_THREAD(in6m_free); | ||||
static struct task in6m_free_task; | static struct task in6m_free_task; | ||||
static struct in6_multi_head in6m_free_list = SLIST_HEAD_INITIALIZER(); | static struct in6_multi_head in6m_free_list = SLIST_HEAD_INITIALIZER(); | ||||
static void in6m_release_task(void *arg __unused, int pending __unused); | static void in6m_release_task(void *arg __unused, int pending __unused); | ||||
static void | static void | ||||
in6m_init(void) | in6m_init(void *arg __unused) | ||||
kib: This is an unrelated fix, right ? | |||||
hselaskyAuthorUnsubmitted Done Inline ActionsYes, minor nit while at it. SYSINITs should take a pointer argument. hselasky: Yes, minor nit while at it. SYSINITs should take a pointer argument. | |||||
{ | { | ||||
TASK_INIT(&in6m_free_task, 0, in6m_release_task, NULL); | TASK_INIT(&in6m_free_task, 0, in6m_release_task, NULL); | ||||
} | } | ||||
SYSINIT(in6m_init, SI_SUB_TASKQ, SI_ORDER_ANY, in6m_init, NULL); | SYSINIT(in6m_init, SI_SUB_TASKQ, SI_ORDER_ANY, in6m_init, NULL); | ||||
void | void | ||||
in6m_release_list_deferred(struct in6_multi_head *inmh) | in6m_release_list_deferred(struct in6_multi_head *inmh) | ||||
{ | { | ||||
if (SLIST_EMPTY(inmh)) | if (SLIST_EMPTY(inmh)) | ||||
return; | return; | ||||
mtx_lock(&in6_multi_free_mtx); | mtx_lock(&in6_multi_free_mtx); | ||||
SLIST_CONCAT(&in6m_free_list, inmh, in6_multi, in6m_nrele); | SLIST_CONCAT(&in6m_free_list, inmh, in6_multi, in6m_nrele); | ||||
mtx_unlock(&in6_multi_free_mtx); | mtx_unlock(&in6_multi_free_mtx); | ||||
taskqueue_enqueue(taskqueue_in6m_free, &in6m_free_task); | taskqueue_enqueue(taskqueue_in6m_free, &in6m_free_task); | ||||
} | } | ||||
void | void | ||||
in6m_release_wait(void) | in6m_release_wait(void *arg __unused) | ||||
{ | { | ||||
/* | |||||
* Make sure all pending multicast addresses are freed before | |||||
* the VNET or network device is destroyed: | |||||
*/ | |||||
taskqueue_drain_all(taskqueue_in6m_free); | taskqueue_drain_all(taskqueue_in6m_free); | ||||
} | } | ||||
#ifdef VIMAGE | |||||
VNET_SYSUNINIT(in6m_release_wait, SI_SUB_PROTO_DOMAIN, SI_ORDER_FIRST, in6m_release_wait, NULL); | |||||
#endif | |||||
void | void | ||||
in6m_disconnect_locked(struct in6_multi_head *inmh, struct in6_multi *inm) | in6m_disconnect_locked(struct in6_multi_head *inmh, struct in6_multi *inm) | ||||
{ | { | ||||
struct ifnet *ifp; | struct ifnet *ifp; | ||||
struct ifaddr *ifa; | struct ifaddr *ifa; | ||||
struct in6_ifaddr *ifa6; | struct in6_ifaddr *ifa6; | ||||
struct in6_multi_mship *imm, *imm_tmp; | struct in6_multi_mship *imm, *imm_tmp; | ||||
▲ Show 20 Lines • Show All 2,354 Lines • Show Last 20 Lines |
This is an unrelated fix, right ?