summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/kern/subr_taskqueue.c
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2016-12-09 14:19:03 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2017-01-10 09:53:34 +0100
commit75b706fde4cbf82bcd41a1cec319778aa0f8eb2d (patch)
treeea39a351a1f6337b5a5dd6036314693adef5ffe6 /freebsd/sys/kern/subr_taskqueue.c
parentVMSTAT(8): Port to RTEMS (diff)
downloadrtems-libbsd-75b706fde4cbf82bcd41a1cec319778aa0f8eb2d.tar.bz2
Update to FreeBSD head 2016-12-10
Git mirror commit 80c55f08a05ab3b26a73b226ccb56adc3122a55c.
Diffstat (limited to 'freebsd/sys/kern/subr_taskqueue.c')
-rw-r--r--freebsd/sys/kern/subr_taskqueue.c28
1 files changed, 27 insertions, 1 deletions
diff --git a/freebsd/sys/kern/subr_taskqueue.c b/freebsd/sys/kern/subr_taskqueue.c
index 8580e8fc..5ef8683c 100644
--- a/freebsd/sys/kern/subr_taskqueue.c
+++ b/freebsd/sys/kern/subr_taskqueue.c
@@ -89,6 +89,7 @@ struct taskqueue {
#define TQ_FLAGS_UNLOCKED_ENQUEUE (1 << 2)
#define DT_CALLOUT_ARMED (1 << 0)
+#define DT_DRAIN_IN_PROGRESS (1 << 1)
#ifndef __rtems__
#define TQ_LOCK(tq) \
@@ -334,7 +335,11 @@ taskqueue_enqueue_timeout(struct taskqueue *queue,
#endif /* __rtems__ */
timeout_task->q = queue;
res = timeout_task->t.ta_pending;
- if (ticks == 0) {
+ if (timeout_task->f & DT_DRAIN_IN_PROGRESS) {
+ /* Do nothing */
+ TQ_UNLOCK(queue);
+ res = -1;
+ } else if (ticks == 0) {
taskqueue_enqueue_locked(queue, &timeout_task->t);
/* The lock is released inside. */
} else {
@@ -598,8 +603,24 @@ taskqueue_drain_timeout(struct taskqueue *queue,
struct timeout_task *timeout_task)
{
+ /*
+ * Set flag to prevent timer from re-starting during drain:
+ */
+ TQ_LOCK(queue);
+ KASSERT((timeout_task->f & DT_DRAIN_IN_PROGRESS) == 0,
+ ("Drain already in progress"));
+ timeout_task->f |= DT_DRAIN_IN_PROGRESS;
+ TQ_UNLOCK(queue);
+
callout_drain(&timeout_task->c);
taskqueue_drain(queue, &timeout_task->t);
+
+ /*
+ * Clear flag to allow timer to re-start:
+ */
+ TQ_LOCK(queue);
+ timeout_task->f &= ~DT_DRAIN_IN_PROGRESS;
+ TQ_UNLOCK(queue);
}
static void
@@ -666,6 +687,11 @@ _taskqueue_start_threads(struct taskqueue **tqp, int count, int pri,
} else
tq->tq_tcount++;
}
+ if (tq->tq_tcount == 0) {
+ free(tq->tq_threads, M_TASKQUEUE);
+ tq->tq_threads = NULL;
+ return (ENOMEM);
+ }
#ifndef __rtems__
for (i = 0; i < count; i++) {
if (tq->tq_threads[i] == NULL)