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.
|
||||
* 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);
|
||||
|
||||
if (mutex != NULL)
|
||||
if (mutex != NULL
|
||||
&& (c->c_flags & CALLOUT_RETURNUNLOCKED) == 0)
|
||||
mtx_unlock(mutex);
|
||||
|
||||
mutex_lock(&sLock);
|
||||
|
@ -293,11 +293,10 @@ taskqueue_drain_timeout(struct taskqueue *queue,
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
taskqueue_enqueue(struct taskqueue *taskQueue, struct task *task)
|
||||
static void
|
||||
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 */
|
||||
if (task->ta_pending) {
|
||||
task->ta_pending++;
|
||||
@ -310,6 +309,18 @@ taskqueue_enqueue(struct taskqueue *taskQueue, struct task *task)
|
||||
taskQueue->tq_flags |= TQ_FLAGS_PENDING;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
@ -319,13 +330,16 @@ taskqueue_timeout_func(void *arg)
|
||||
{
|
||||
struct taskqueue *queue;
|
||||
struct timeout_task *timeout_task;
|
||||
cpu_status status;
|
||||
// dummy, as we should never get here on a spin taskqueue
|
||||
|
||||
timeout_task = arg;
|
||||
queue = timeout_task->q;
|
||||
KASSERT((timeout_task->f & DT_CALLOUT_ARMED) != 0, ("Stray timeout"));
|
||||
timeout_task->f &= ~DT_CALLOUT_ARMED;
|
||||
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