Hello,
One of the most usual errors found by Hurd's developers is the "zalloc's
panic" one. I think that this panic could be (usually) related with the
extremly high number of threads that some translators (i.e. ext2fs)
spawn when there's a significant amount number of activity over it
(already discussed here
http://lists.gnu.org/archive/html/bug-hurd/2002-04/msg00003.html and
http://lists.gnu.org/archive/html/bug-hurd/2002-06/msg00263.html).
Antrik have also done a research about this issue
( http://hurd.gnufans.org/bin/view/Hurd/ZallocPanics ).
This is an experimental (just for testing) patch that (I hope) helps
with debuging this issue, and also seems to make the system a little
more robust.
It is extremly simple. Everytime a thread is going to serve a request,
it checks if nreqthreads == 0, and spawns a new thread if true. But
before spawning the new thread, it increments nreqthreads by 1 (to count
the new thread), so until this new thread receives a request
(nreqthreads is decremented at internal_demuxer), more threads can't be
created. What we do is, if a certain number of threads are already
spawned (THREAD_DELAY), we put the new thread to sleep for a time
(DELAY), so we're implicity delaying threads creation, giving time to
other threads to finish their requests.
On some machines (fast processor, slow I/O, or both), this isn't enough
to avoid a slowly but constant thread incrementation due to Mach's
pageouts, so a fixed limit is needed (THREAD_MAX) for self-paged
translators.
It's recommended to play with this values (THREAD_DELAY, THREAD_MAX,
DELAY) and enable debug (LP_DEBUG) to see how new threads are created.
Happy hacking!
--- manage-multithread.c.orig 2005-08-10 13:38:18.000000000 +0200
+++ manage-multithread.c 2005-08-10 13:34:30.000000000 +0200
@@ -23,6 +23,19 @@
#include <assert.h>
#include <cthreads.h>
#include <mach/message.h>
+#include <unistd.h> /* For sleep() */
+
+#define LP_DEBUG 0
+
+#if LP_DEBUG
+#include <stdio.h> /* For printf() */
+#endif
+
+#define THREAD_MAX 250 /* Maximum number of threads */
+#define THREAD_DELAY 64 /* Number of threads created as needed
+ without delay */
+#define DELAY 2 /* Time to sleep() each delayed thread
+ (in seconds) */
void
ports_manage_port_operations_multithread (struct port_bucket *bucket,
@@ -43,6 +56,7 @@
{
int spawn = 0;
int status;
+ int type = 0; /* 0 = standard, 1 = master, 2 = delayed */
struct port_info *pi;
struct rpc_info link;
register mig_reply_header_t *outp = (mig_reply_header_t *) outheadp;
@@ -59,8 +73,11 @@
spin_lock (&lock);
assert (nreqthreads);
nreqthreads--;
- if (nreqthreads == 0)
- spawn = 1;
+ if (nreqthreads == 0 && totalthreads <= THREAD_MAX) {
+ spawn = 1;
+ if (totalthreads >= THREAD_DELAY)
+ type = 2;
+ }
spin_unlock (&lock);
if (spawn)
@@ -69,7 +86,8 @@
totalthreads++;
nreqthreads++;
spin_unlock (&lock);
- cthread_detach (cthread_fork ((cthread_fn_t) thread_function, 0));
+ cthread_detach (cthread_fork ((cthread_fn_t) thread_function,
+ (any_t)(intptr_t) type));
}
/* Fill in default response. */
@@ -117,15 +135,31 @@
}
int
- thread_function (int master)
+ thread_function (int type)
{
int timeout;
error_t err;
-
+
+ if (type == 2) {
+#if LP_DEBUG
+ printf("libports: delayed thread number: %d || ", totalthreads);
+ fflush(stdout);
+#endif
+ sleep(DELAY); /* Take a little break */
+#if LP_DEBUG
+ printf("libports: delayed thread running (%d)\n", totalthreads);
+ fflush(stdout);
+#endif
+ }
+#if LP_DEBUG
+ else {
+ printf("libports: new thread without delay running\n");
+ }
+#endif
if (hook)
(*hook) ();
- if (master)
+ if (type == 1)
timeout = global_timeout;
else
timeout = thread_timeout;
@@ -138,7 +172,7 @@
timeout);
while (err != MACH_RCV_TIMED_OUT);
- if (master)
+ if (type == 1)
{
spin_lock (&lock);
if (totalthreads != 1)
_______________________________________________
Bug-hurd mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/bug-hurd