tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: workqueues ....
> Date: Thu, 26 Jul 2018 22:57:57 -0700
> From: Phil Nelson <phil%NetBSD.org@localhost>
>
> I'm trying to work with workqueues and am having a locking problem
Is this a conceptual problem, or do you have a symptom that you're
actually hitting with specific code? If the latter, can you describe
the symptom and quote the code?
> Lets say I have a function f() as follows:
>
> int f() {
> mutex_enter(&some_mutex);
> ...... code .....
> mutex_exit(&some_mutex);
> }
>
> and now lets say that I start another function running via a workqueue, g()
> g() {
> ..... some code ....
> if (f()) {
> .... do something else ...
> } else {
> error
> }
> }
>
> So, my question is: if g() is running f() and holds the mutex and then the
> main code calls f() ... will this be detected as already holding the lock?
>
> If it will be detected as already holding the lock, how can I do locking
> between the code that does the enqueue and the code in the work item?
The workqueue function runs asynchronously in its own thread. You are
allowed to hold a lock when scheduling work with workqueue_enqueue
that the workqueue function itself will acquire too. Indeed, many
users will do exactly that.
Note that in your example, the caller of f must not hold some_mutex,
workqueues or not. If g _already_ holds the mutex when it calls f,
that's a bug.
Here's how you can use a workqueue to schedule work if it's not
already scheduled:
struct foo_softc {
...
struct workqueue *sc_wq;
kmutex_t sc_work_lock;
struct work sc_work;
bool sc_work_scheduled;
...
};
static void
do_work(struct work *wk, void *arg)
{
struct foo_softc *sc = container_of(wk, struct foo_softc, sc_work);
mutex_enter(&sc->sc_work_lock);
sc->sc_work_scheduled = false;
mutex_exit(&sc->sc_work_lock);
/* do stuff */
}
static void
foo_intr(...)
{
...
mutex_enter(&sc->sc_work_lock);
if (!sc->sc_work_scheduled) {
workqueue_enqueue(sc->sc_wq, &sc->sc_work, NULL);
sc->sc_work_scheduled = true;
}
mutex_exit(&sc->sc_work_lock);
...
}
Home |
Main Index |
Thread Index |
Old Index