Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 26 Sep 2002 11:08:43 -0400 (EDT)
From:      John Baldwin <jhb@FreeBSD.org>
To:        Mark Murray <mark@grondar.za>
Cc:        arch@freebsd.org
Subject:   RE: [patch] module-with-thread exit routine.
Message-ID:  <XFMail.20020926110843.jhb@FreeBSD.org>
In-Reply-To: <200209260943.g8Q9hURP072845@grimreaper.grondar.org>

next in thread | previous in thread | raw e-mail | index | archive | help

On 26-Sep-2002 Mark Murray wrote:
> Hi
> 
> If an unloadable module has a thread (like random.ko has), then
> unloading the module is problematic because of the race between
> the module termination and the unload.
> 
> The thread must "die" in a part of the code that will not be
> unloaded.
> 
> The random device has its own code to do this, but I think this
> is better put with the kthread stuff.
> 
> Attached is a patch to the kthread code. I've been running this
> for at least three months.
> 
> Comments?

You don't need it.  Look at the crash module I have.  It has a thread
and I committed an extra wakeup() inside of exit1() for kthread's a
while ago to handle just this case.  Here's an excerpt from the crash
module code:

In the kthread's main loop (it usually gets events via a sysctl from
userland):

static void
crash_thread(void *arg)
{
        int ev;

        while (1) {
                mtx_lock(&event_mtx);
                while ((ev = event) == 0)
                        cv_wait(&event_cv, &event_mtx);
                event = 0;
                mtx_unlock(&event_mtx);
                ...
                switch (ev) {
                case -1:
                        mtx_lock(&Giant);
                        kthread_exit(0);
                        break;
                ...
                }
        }
}

Here's the unload() function that the module calls for MOD_UNLOAD:

static int
unload(void *arg)
{

        mtx_lock(&event_mtx);
        event = -1;
        cv_signal(&event_cv);
        msleep(kthread, &event_mtx, PWAIT, "crshun", 0);
        mtx_unlock(&event_mtx);
        mtx_destroy(&event_mtx);
        cv_destroy(&event_cv);
        ...
        return (0);
}

The actual wakeup in exit1 is from:

revision 1.129
date: 2001/06/27 06:15:44;  author: jhb;  state: Exp;  lines: +13 -16
...
- When a kthread exits, do a wakeup() on its proc pointers.  This can be
  used by kernel modules that have kthreads and want to ensure they have
  safely exited before completely the MOD_UNLOAD event.

and is at:

        /*
         * If this is a kthread, then wakeup anyone waiting for it to exit.
         */
        if (p->p_flag & P_KTHREAD)
                wakeup(p);
        PROC_UNLOCK(p);

The trick is to avoid missing the wakeup.  The way I do it above
is to make sure and sleep on the kthread address before and drop
event_mtx at the same time so that I am asleep before the kthread
gets to run.  Since the wakeup() is under the proc lock another
valid way that might be easier to accomplish for some kthreads would
be something like this:

static int
unload(void *arg)
{

        mtx_lock(&event_mtx);
        event = -1;
        cv_signal(&event_mtx);
        PROC_LOCK(kthread);
        mtx_unlock(&event_mtx);
        msleep(kthread, &kthread->p_mtx, PWAIT | PDROP, "crshun", 0);
        ...
}

Well, except that you need to use PDROP in that case since a kthread
might have already been harvested by init() and not have a proc mutex
around any longer to release when you get woken up.

-- 

John Baldwin <jhb@FreeBSD.org>  <><  http://www.FreeBSD.org/~jhb/
"Power Users Use the Power to Serve!"  -  http://www.FreeBSD.org/

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-arch" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?XFMail.20020926110843.jhb>