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>