freebsd11_network: Properly implement CALLOUT_RETURNUNLOCKED.
Fixes a double-lock situation in the Atheros driver. We really should implement FreeBSD's MTX_SPIN instead of relying on cpu_status here...
This commit is contained in:
parent
3248de3de4
commit
09ddf9b9f3
@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010, Axel Dörfler, axeld@pinc-software.de.
|
* Copyright 2010, Axel Dörfler, axeld@pinc-software.de.
|
||||||
* Distributed under the terms of the MIT License.
|
* Copyright 2018, Haiku, Inc. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT license.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@ -66,7 +67,8 @@ callout_thread(void* /*data*/)
|
|||||||
|
|
||||||
c->c_func(c->c_arg);
|
c->c_func(c->c_arg);
|
||||||
|
|
||||||
if (mutex != NULL)
|
if (mutex != NULL
|
||||||
|
&& (c->c_flags & CALLOUT_RETURNUNLOCKED) == 0)
|
||||||
mtx_unlock(mutex);
|
mtx_unlock(mutex);
|
||||||
|
|
||||||
mutex_lock(&sLock);
|
mutex_lock(&sLock);
|
||||||
|
@ -293,11 +293,10 @@ taskqueue_drain_timeout(struct taskqueue *queue,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
static void
|
||||||
taskqueue_enqueue(struct taskqueue *taskQueue, struct task *task)
|
taskqueue_enqueue_locked(struct taskqueue *taskQueue, struct task *task,
|
||||||
|
cpu_status status)
|
||||||
{
|
{
|
||||||
cpu_status status;
|
|
||||||
tq_lock(taskQueue, &status);
|
|
||||||
/* we don't really support priorities */
|
/* we don't really support priorities */
|
||||||
if (task->ta_pending) {
|
if (task->ta_pending) {
|
||||||
task->ta_pending++;
|
task->ta_pending++;
|
||||||
@ -310,6 +309,18 @@ taskqueue_enqueue(struct taskqueue *taskQueue, struct task *task)
|
|||||||
taskQueue->tq_flags |= TQ_FLAGS_PENDING;
|
taskQueue->tq_flags |= TQ_FLAGS_PENDING;
|
||||||
}
|
}
|
||||||
tq_unlock(taskQueue, status);
|
tq_unlock(taskQueue, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
taskqueue_enqueue(struct taskqueue *taskQueue, struct task *task)
|
||||||
|
{
|
||||||
|
cpu_status status;
|
||||||
|
|
||||||
|
tq_lock(taskQueue, &status);
|
||||||
|
taskqueue_enqueue_locked(taskQueue, task, status);
|
||||||
|
/* The lock is released inside. */
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -319,13 +330,16 @@ taskqueue_timeout_func(void *arg)
|
|||||||
{
|
{
|
||||||
struct taskqueue *queue;
|
struct taskqueue *queue;
|
||||||
struct timeout_task *timeout_task;
|
struct timeout_task *timeout_task;
|
||||||
|
cpu_status status;
|
||||||
|
// dummy, as we should never get here on a spin taskqueue
|
||||||
|
|
||||||
timeout_task = arg;
|
timeout_task = arg;
|
||||||
queue = timeout_task->q;
|
queue = timeout_task->q;
|
||||||
KASSERT((timeout_task->f & DT_CALLOUT_ARMED) != 0, ("Stray timeout"));
|
KASSERT((timeout_task->f & DT_CALLOUT_ARMED) != 0, ("Stray timeout"));
|
||||||
timeout_task->f &= ~DT_CALLOUT_ARMED;
|
timeout_task->f &= ~DT_CALLOUT_ARMED;
|
||||||
queue->tq_callouts--;
|
queue->tq_callouts--;
|
||||||
taskqueue_enqueue(timeout_task->q, &timeout_task->t);
|
taskqueue_enqueue_locked(timeout_task->q, &timeout_task->t, status);
|
||||||
|
/* The lock is released inside. */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user