Date: Fri, 8 May 2009 18:24:01 +0100 From: Andrew Brampton <brampton+freebsd-hackers@gmail.com> To: freebsd-hackers@freebsd.org Subject: kthreads and sched_relinquish Message-ID: <d41814900905081024m2a67b037w91a4611aa633ab52@mail.gmail.com>
next in thread | raw e-mail | index | archive | help
Hi, I'm writing a FreeBSD kernel module and I think I really misunderstand something. My module spawns a thread, which should be running while the module is loaded. The thread does some work and then should yield for other threads. However, if there are no other threads waiting, then I would like to continue to do more work. The problem is that I am getting weird deadlocks so I wrote a simple test app to ask why this doesn't work: ------------------------ #include <sys/param.h> #include <sys/module.h> #include <sys/kernel.h> #include <sys/cdefs.h> #include <sys/proc.h> #include <sys/pcpu.h> #include <sys/kthread.h> #include <sys/sched.h> #include <sys/systm.h> static void test_thread(void *blah) { unsigned int i = 100000000; /* Limit the number of iterations */ printf("Test Thread Started\n"); while (i > 0) { sched_relinquish(curthread); i--; } printf("Test Thread Exited\n"); kthread_exit(0); } /* The function called at load/unload. */ static int event_handler(struct module *module, int event, void *arg) { int e = 0; /* Error, 0 for normal return status */ switch (event) { case MOD_LOAD: printf("Test Module Loaded\n"); kthread_create(test_thread, NULL, NULL, 0, 0, "test"); break; case MOD_UNLOAD: printf("Test Module Unloaded\n"); break; default: e = EOPNOTSUPP; /* Error, Operation Not Supported */ } return e; } /* The second argument of DECLARE_MODULE. */ static moduledata_t test_conf = { "test_mod", /* module name */ event_handler, /* event handler */ NULL /* extra data */ }; DECLARE_MODULE(test_mod, test_conf, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); ---------------------------- While my thread is running the rest of the system is unresponsive. The thread should sched_relinquish() every time round the loop, and from my understanding that should yield to allow other threads to run, for example the thread which executes my shell (bash). I suspect my thread is yielding and getting instantly rescheduled. I noticed that poll_idle() in sys/kern_poll.c does something similar to me, but they first lower their priority. This however has not worked for me, since my more complex module interacts with higher priority threads and ends up deadlocking. So I just want to ask, Why does this example code lock the system? Am I using sched_relinquish correctly? Or should I be doing something else? I did try using tsleep(...,1), but I don't want my thread sleeping if there are no other threads waiting. I would also be grateful if people could point me at other examples in the kernel where something like this is done. I have looked in quite a few places, but I can't see why my simple app is wrong. thanks Andrew
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?d41814900905081024m2a67b037w91a4611aa633ab52>