Changeset View
Changeset View
Standalone View
Standalone View
head/sys/kern/subr_gtaskqueue.c
Show All 35 Lines | |||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/kthread.h> | #include <sys/kthread.h> | ||||
#include <sys/libkern.h> | #include <sys/libkern.h> | ||||
#include <sys/limits.h> | #include <sys/limits.h> | ||||
#include <sys/lock.h> | #include <sys/lock.h> | ||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
#include <sys/mutex.h> | #include <sys/mutex.h> | ||||
#include <sys/proc.h> | #include <sys/proc.h> | ||||
#include <sys/epoch.h> | |||||
#include <sys/sched.h> | #include <sys/sched.h> | ||||
#include <sys/smp.h> | #include <sys/smp.h> | ||||
#include <sys/gtaskqueue.h> | #include <sys/gtaskqueue.h> | ||||
#include <sys/unistd.h> | #include <sys/unistd.h> | ||||
#include <machine/stdarg.h> | #include <machine/stdarg.h> | ||||
static MALLOC_DEFINE(M_GTASKQUEUE, "gtaskqueue", "Group Task Queues"); | static MALLOC_DEFINE(M_GTASKQUEUE, "gtaskqueue", "Group Task Queues"); | ||||
static void gtaskqueue_thread_enqueue(void *); | static void gtaskqueue_thread_enqueue(void *); | ||||
▲ Show 20 Lines • Show All 285 Lines • ▼ Show 20 Lines | gtaskqueue_unblock(struct gtaskqueue *queue) | ||||
if (!STAILQ_EMPTY(&queue->tq_queue)) | if (!STAILQ_EMPTY(&queue->tq_queue)) | ||||
queue->tq_enqueue(queue->tq_context); | queue->tq_enqueue(queue->tq_context); | ||||
TQ_UNLOCK(queue); | TQ_UNLOCK(queue); | ||||
} | } | ||||
static void | static void | ||||
gtaskqueue_run_locked(struct gtaskqueue *queue) | gtaskqueue_run_locked(struct gtaskqueue *queue) | ||||
{ | { | ||||
struct epoch_tracker et; | |||||
struct gtaskqueue_busy tb; | struct gtaskqueue_busy tb; | ||||
struct gtask *gtask; | struct gtask *gtask; | ||||
bool in_net_epoch; | |||||
KASSERT(queue != NULL, ("tq is NULL")); | KASSERT(queue != NULL, ("tq is NULL")); | ||||
TQ_ASSERT_LOCKED(queue); | TQ_ASSERT_LOCKED(queue); | ||||
tb.tb_running = NULL; | tb.tb_running = NULL; | ||||
LIST_INSERT_HEAD(&queue->tq_active, &tb, tb_link); | LIST_INSERT_HEAD(&queue->tq_active, &tb, tb_link); | ||||
in_net_epoch = false; | |||||
while ((gtask = STAILQ_FIRST(&queue->tq_queue)) != NULL) { | while ((gtask = STAILQ_FIRST(&queue->tq_queue)) != NULL) { | ||||
STAILQ_REMOVE_HEAD(&queue->tq_queue, ta_link); | STAILQ_REMOVE_HEAD(&queue->tq_queue, ta_link); | ||||
gtask->ta_flags &= ~TASK_ENQUEUED; | gtask->ta_flags &= ~TASK_ENQUEUED; | ||||
tb.tb_running = gtask; | tb.tb_running = gtask; | ||||
tb.tb_seq = ++queue->tq_seq; | tb.tb_seq = ++queue->tq_seq; | ||||
TQ_UNLOCK(queue); | TQ_UNLOCK(queue); | ||||
KASSERT(gtask->ta_func != NULL, ("task->ta_func is NULL")); | KASSERT(gtask->ta_func != NULL, ("task->ta_func is NULL")); | ||||
if (!in_net_epoch && TASK_IS_NET(gtask)) { | |||||
in_net_epoch = true; | |||||
NET_EPOCH_ENTER(et); | |||||
} else if (in_net_epoch && !TASK_IS_NET(gtask)) { | |||||
NET_EPOCH_EXIT(et); | |||||
in_net_epoch = false; | |||||
} | |||||
gtask->ta_func(gtask->ta_context); | gtask->ta_func(gtask->ta_context); | ||||
TQ_LOCK(queue); | TQ_LOCK(queue); | ||||
wakeup(gtask); | wakeup(gtask); | ||||
} | } | ||||
if (in_net_epoch) | |||||
NET_EPOCH_EXIT(et); | |||||
LIST_REMOVE(&tb, tb_link); | LIST_REMOVE(&tb, tb_link); | ||||
} | } | ||||
static int | static int | ||||
task_is_running(struct gtaskqueue *queue, struct gtask *gtask) | task_is_running(struct gtaskqueue *queue, struct gtask *gtask) | ||||
{ | { | ||||
struct gtaskqueue_busy *tb; | struct gtaskqueue_busy *tb; | ||||
▲ Show 20 Lines • Show All 662 Lines • Show Last 20 Lines |