From: David van Moolenbroek Date: Tue, 24 Jun 2008 13:53:03 +0000 (+0000) Subject: Backport of fix from asynchvfs branch for PM-LOG-VFS-PM deadlock that resulted in... X-Git-Tag: v3.1.4~235 X-Git-Url: http://zhaoyanbai.com/repos/icons/static/man.3.ps?a=commitdiff_plain;h=f73b5419522533b3897a56d6dcc7c6b68fba50ea;p=minix.git Backport of fix from asynchvfs branch for PM-LOG-VFS-PM deadlock that resulted in VFS panics. --- diff --git a/servers/pm/Makefile b/servers/pm/Makefile index c6343e89a..8ae60194f 100644 --- a/servers/pm/Makefile +++ b/servers/pm/Makefile @@ -18,7 +18,7 @@ LDFLAGS = -i OBJ = main.o forkexit.o break.o exec.o time.o timers.o \ signal.o alloc.o utility.o table.o trace.o getset.o misc.o \ - profile.o + profile.o asynsend.o kputc.o # build local binary all build: $(SERVER) diff --git a/servers/pm/asynsend.c b/servers/pm/asynsend.c new file mode 100644 index 000000000..de7e5d106 --- /dev/null +++ b/servers/pm/asynsend.c @@ -0,0 +1,90 @@ + +#include "pm.h" + +#define ASYN_NR 100 +PRIVATE asynmsg_t msgtable[ASYN_NR]; +PRIVATE int first_slot= 0, next_slot= 0; + +PUBLIC int asynsend(dst, mp) +endpoint_t dst; +message *mp; +{ + int r, src_ind, dst_ind; + unsigned flags; + + /* Update first_slot */ + for (; first_slot < next_slot; first_slot++) + { + flags= msgtable[first_slot].flags; + if ((flags & (AMF_VALID|AMF_DONE)) == (AMF_VALID|AMF_DONE)) + { + if (msgtable[first_slot].result != OK) + { + printf( + "asynsend: found completed entry %d with error %d\n", + first_slot, + msgtable[first_slot].result); + } + continue; + } + if (flags != AMF_EMPTY) + break; + } + + if (first_slot >= next_slot) + { + /* Reset first_slot and next_slot */ + next_slot= first_slot= 0; + } + + if (next_slot >= ASYN_NR) + { + /* Tell the kernel to stop processing */ + r= senda(NULL, 0); + if (r != OK) + panic(__FILE__, "asynsend: senda failed", r); + + dst_ind= 0; + for (src_ind= first_slot; src_ind= ASYN_NR) + panic(__FILE__, "asynsend: msgtable full", NO_NUM); + } + + msgtable[next_slot].dst= dst; + msgtable[next_slot].msg= *mp; + msgtable[next_slot].flags= AMF_VALID; /* Has to be last. The kernel + * scans this table while we + * are sleeping. + */ + next_slot++; + + /* Tell the kernel to rescan the table */ + return senda(msgtable+first_slot, next_slot-first_slot); +} + diff --git a/servers/pm/kputc.c b/servers/pm/kputc.c new file mode 100644 index 000000000..b0c53b099 --- /dev/null +++ b/servers/pm/kputc.c @@ -0,0 +1,149 @@ +/* A server must occasionally print some message. It uses a simple version of + * printf() found in the system lib that calls kputc() to output characters. + * Printing is done with a call to the kernel, and not by going through FS. + * + * This routine can only be used by servers and device drivers. The kernel + * must define its own kputc(). Note that the log driver also defines its own + * kputc() to directly call the TTY instead of going through this library. + */ + +#include "pm.h" +#include +#include + +#define OVERFLOW_STR "[...]\n" + +#define PRINTPROCS (sizeof(procs)/sizeof(procs[0])) + +static char print_buf[80]; /* output is buffered here */ + +int kputc_use_private_grants= 0; + +static int buf_count = 0; /* # characters in the buffer */ +static int buf_offset = 0; /* Start of current line in buffer */ +static int procs[] = OUTPUT_PROCS_ARRAY; +static cp_grant_id_t printgrants[PRINTPROCS]; +static int procbusy[PRINTPROCS]; +static int do_flush = FALSE; +static int overflow = FALSE; + +/*===========================================================================* + * kputc * + *===========================================================================*/ +void kputc(c) +int c; +{ +/* Accumulate another character. If 0 or buffer full, print it. */ + int p; + message m; + + static int firstprint = 1; + + if (c == 0) + { + if (buf_count > buf_offset) + do_flush= TRUE; + } + else if (buf_count >= sizeof(print_buf)) + { + overflow= TRUE; + if (buf_count > buf_offset) + do_flush= TRUE; + } + else + print_buf[buf_count++] = c; + + if (!do_flush || buf_offset != 0) + return; + + buf_offset= buf_count; + if (kputc_use_private_grants) + { + for (p= 0; p buf_offset) + { + memmove(&print_buf[0], &print_buf[buf_offset], + buf_count-buf_offset); + } + buf_count -= buf_offset; + buf_offset= 0; + if (overflow) + { + if (buf_count + sizeof(OVERFLOW_STR) > sizeof(print_buf)) + buf_count= sizeof(print_buf)-sizeof(OVERFLOW_STR); + overflow= FALSE; + do_flush= FALSE; + printf("%s", OVERFLOW_STR); + } + kputc(0); +} diff --git a/servers/pm/main.c b/servers/pm/main.c index 1f6123d69..4a60bd1e7 100644 --- a/servers/pm/main.c +++ b/servers/pm/main.c @@ -124,6 +124,10 @@ PUBLIC int main() case GETPUID: result= do_getpuid(); break; + case DIAG_REPL : + diag_repl(); + result= SUSPEND; + break; default: /* Else, if the system call number is valid, perform the * call. diff --git a/servers/pm/proto.h b/servers/pm/proto.h index 392f8f6e3..ac8919efb 100644 --- a/servers/pm/proto.h +++ b/servers/pm/proto.h @@ -27,6 +27,9 @@ _PROTOTYPE( void swap_inqueue, (struct mproc *rmp) ); #endif /* !SWAP */ _PROTOTYPE(int mem_holes_copy, (struct hole *, size_t *, u32_t *) ); +/* asynsend.c */ +_PROTOTYPE( int asynsend, (endpoint_t dst, message *mp) ); + /* break.c */ _PROTOTYPE( int adjust, (struct mproc *rmp, vir_clicks data_clicks, vir_bytes sp) ); @@ -63,6 +66,9 @@ _PROTOTYPE( void real_cleanup, (struct mproc *rmp) ); /* getset.c */ _PROTOTYPE( int do_getset, (void) ); +/* kputc.c */ +_PROTOTYPE( void diag_repl, (void) ); + /* main.c */ _PROTOTYPE( int main, (void) );