Hello,

        Currently I'm trying to make KLD which uses kernel threads
unloadable under recent -current. The prototype of functions looks like
this:

void
my_thread(void*arg)
{
        while(wearewanted) {
                do_something();
                tsleep();
        }
        exited = 1;
        kthread_exit(0);
}

void
my_unload()
{
        wearewanted = 0;
        while (!exited)
                tsleep(1sec);
}

        my_unload() function called from the module unload event which
issued from the kldunload() syscall.

        Unfortunately, kernel panics in the mtx_exit_hard() function.
After some examination I've found that two fields in the Giant mutex
structure set to unexpected values:
----
empty mtx_blocked for mutex Giant
mtx_contested not in any list for mutex Giant
----

        These messages printed by added diagnostics code. With this patch
(see attachment) it is possible to load and unload KLD without any
problems on UP machine except that the above messages printed. However,
I'm don't know if they are correct. (btw, 4.1 doesn't have this problem).

        Any ideas why this happened and how to fix it ?
--
Boris Popov
http://www.butya.kz/~bp/
Index: synch_machdep.c
===================================================================
RCS file: /home/ncvs/src/sys/i386/i386/synch_machdep.c,v
retrieving revision 1.5
diff -u -r1.5 synch_machdep.c
--- synch_machdep.c     2000/10/04 01:20:49     1.5
+++ synch_machdep.c     2000/10/05 10:23:33
@@ -355,10 +355,16 @@
                p = CURPROC;
                p1 = TAILQ_FIRST(&m->mtx_blocked);
                MPASS(p->p_magic == P_MAGIC);
-               MPASS(p1->p_magic == P_MAGIC);
-               TAILQ_REMOVE(&m->mtx_blocked, p1, p_procq);
+               if (p1) {
+                       MPASS(p1->p_magic == P_MAGIC);
+                       TAILQ_REMOVE(&m->mtx_blocked, p1, p_procq);
+               } else
+                       printf("empty mtx_blocked for mutex %s\n", 
+m->mtx_description);
                if (TAILQ_EMPTY(&m->mtx_blocked)) {
-                       LIST_REMOVE(m, mtx_contested);
+                       if (m->mtx_contested.le_prev != NULL)
+                               LIST_REMOVE(m, mtx_contested);
+                       else
+                               printf("mtx_contested not in any list for mutex %s\n", 
+m->mtx_description);
                        atomic_cmpset_int(&m->mtx_lock, m->mtx_lock,
                                          MTX_UNOWNED);
                        CTR1(KTR_LOCK, "mtx_exit: 0x%p not held", m);
@@ -373,12 +379,15 @@
                if (pri > p->p_nativepri)
                        pri = p->p_nativepri;
                SET_PRIO(p, pri);
-               CTR2(KTR_LOCK, "mtx_exit: 0x%p contested setrunqueue 0x%p",
-                   m, p1);
-               p1->p_blocked = NULL;
-               p1->p_stat = SRUN;
-               setrunqueue(p1);
-               if ((type & MTX_NOSWITCH) == 0 && p1->p_priority < pri) {
+               if (p1) {
+                       CTR2(KTR_LOCK, "mtx_exit: 0x%p contested setrunqueue 0x%p",
+                           m, p1);
+                       p1->p_blocked = NULL;
+                       p1->p_stat = SRUN;
+                       setrunqueue(p1);
+               }
+               if ((type & MTX_NOSWITCH) == 0 &&
+                   (p1 == NULL || p1->p_priority < pri)) {
 #ifdef notyet
                        if (p->p_flag & (P_ITHD | P_SITHD)) {
                                ithd_t *it = (ithd_t *)p;

Reply via email to