diff --git a/drivers/log/log.c b/drivers/log/log.c index 45b5e620d..df267aec2 100644 --- a/drivers/log/log.c +++ b/drivers/log/log.c @@ -99,6 +99,9 @@ static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info)) logdevices[i].log_source = NONE; } + /* Register for diagnostics notifications. */ + sys_diagctl_register(); + return(OK); } diff --git a/drivers/tty/tty.c b/drivers/tty/tty.c index b0c910a6f..bdfdd142e 100644 --- a/drivers/tty/tty.c +++ b/drivers/tty/tty.c @@ -336,6 +336,9 @@ static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info)) /* Final one-time keyboard initialization. */ kb_init_once(); + /* Register for diagnostics notifications. */ + sys_diagctl_register(); + return(OK); } diff --git a/include/minix/com.h b/include/minix/com.h index 8534feb7d..3b659eeae 100644 --- a/include/minix/com.h +++ b/include/minix/com.h @@ -589,6 +589,8 @@ #define DIAGCTL_ARG2 m1_i2 #define DIAGCTL_CODE_DIAG 1 /* Print diagnostics. */ #define DIAGCTL_CODE_STACKTRACE 2 /* Print process stack. */ +#define DIAGCTL_CODE_REGISTER 3 /* Register for diagnostic signals */ +#define DIAGCTL_CODE_UNREGISTER 4 /* Unregister for diagnostic signals */ #define DIAG_BUFSIZE (80*25) /* Field names for SYS_VTIMER. */ diff --git a/include/minix/config.h b/include/minix/config.h index 2ccdec4a0..926c64df6 100644 --- a/include/minix/config.h +++ b/include/minix/config.h @@ -35,17 +35,6 @@ /* DMA_SECTORS may be increased to speed up DMA based drivers. */ #define DMA_SECTORS 1 /* DMA buffer size (must be >= 1) */ -/* Which processes should receive diagnostics from the kernel and system? - * Directly sending it to TTY only displays the output. Sending it to the - * log driver will cause the diagnostics to be buffered and displayed. - * Messages are sent by src/lib/sysutil/kputc.c to these processes, in - * the order of this array, which must be terminated by NONE. This is used - * by drivers and servers that printf(). - * The kernel does this for its own kprintf() in kernel/utility.c, also using - * this array, but a slightly different mechanism. - */ -#define OUTPUT_PROCS_ARRAY { TTY_PROC_NR, LOG_PROC_NR, NONE } - /* NR_CONS, NR_RS_LINES, and NR_PTYS determine the number of terminals the * system can handle. */ diff --git a/include/minix/syslib.h b/include/minix/syslib.h index dad156080..17b5812a1 100644 --- a/include/minix/syslib.h +++ b/include/minix/syslib.h @@ -69,8 +69,6 @@ int sys_vmctl_enable_paging(void * data); int sys_readbios(phys_bytes address, void *buf, size_t size); int sys_settime(int now, clockid_t clk_id, time_t sec, long nsec); int sys_stime(time_t boottime); -int sys_diagctl(int ctl, char *arg1, int arg2); -int sys_diagctl_stacktrace(endpoint_t who); int sys_vmctl_get_mapping(int index, phys_bytes *addr, phys_bytes *len, int *flags); int sys_vmctl_reply_mapping(int index, vir_bytes addr); @@ -159,6 +157,17 @@ int sys_umap_data_fb(endpoint_t proc_ep, vir_bytes vir_addr, vir_bytes int sys_umap_remote(endpoint_t proc_ep, endpoint_t grantee, int seg, vir_bytes vir_addr, vir_bytes bytes, phys_bytes *phys_addr); +/* Shorthands for sys_diagctl() system call. */ +#define sys_diagctl_diag(buf,len) \ + sys_diagctl(DIAGCTL_CODE_DIAG, buf, len) +#define sys_diagctl_stacktrace(ep) \ + sys_diagctl(DIAGCTL_CODE_STACKTRACE, NULL, ep) +#define sys_diagctl_register() \ + sys_diagctl(DIAGCTL_CODE_REGISTER, NULL, 0) +#define sys_diagctl_unregister() \ + sys_diagctl(DIAGCTL_CODE_UNREGISTER, NULL, 0) +int sys_diagctl(int ctl, char *arg1, int arg2); + /* Shorthands for sys_getinfo() system call. */ #define sys_getkinfo(dst) sys_getinfo(GET_KINFO, dst, 0,0,0) #define sys_getloadinfo(dst) sys_getinfo(GET_LOADINFO, dst, 0,0,0) diff --git a/kernel/arch/earm/pre_init.c b/kernel/arch/earm/pre_init.c index 4bb133c4d..73947905d 100644 --- a/kernel/arch/earm/pre_init.c +++ b/kernel/arch/earm/pre_init.c @@ -411,7 +411,7 @@ kinfo_t *pre_init(int argc, char **argv) * ensure this). The following methods are used in that context. Once we jump to kmain they are no * longer used and the "real" implementations are visible */ -int send_sig(endpoint_t proc_nr, int sig_nr) { return 0; } +void send_diag_sig(void) { } void minix_shutdown(minix_timer_t *t) { arch_shutdown(RBT_PANIC); } void busy_delay_ms(int x) { } int raise(int n) { panic("raise(%d)\n", n); } diff --git a/kernel/arch/i386/pre_init.c b/kernel/arch/i386/pre_init.c index 2a9967ac8..165e6d57b 100644 --- a/kernel/arch/i386/pre_init.c +++ b/kernel/arch/i386/pre_init.c @@ -245,7 +245,7 @@ kinfo_t *pre_init(u32_t magic, u32_t ebx) return &kinfo; } -int send_sig(endpoint_t proc_nr, int sig_nr) { return 0; } +void send_diag_sig(void) { } void minix_shutdown(minix_timer_t *t) { arch_shutdown(RBT_PANIC); } void busy_delay_ms(int x) { } int raise(int sig) { panic("raise(%d)\n", sig); } diff --git a/kernel/priv.h b/kernel/priv.h index 204dacd46..0bdd00949 100644 --- a/kernel/priv.h +++ b/kernel/priv.h @@ -45,6 +45,8 @@ struct priv { minix_timer_t s_alarm_timer; /* synchronous alarm timer */ reg_t *s_stack_guard; /* stack guard word for kernel tasks */ + char s_diag_sig; /* send a SIGKMESS when diagnostics arrive? */ + int s_nr_io_range; /* allowed I/O ports */ struct io_range s_io_tab[NR_IO_RANGE]; diff --git a/kernel/proto.h b/kernel/proto.h index ac2b55625..8de351bc2 100644 --- a/kernel/proto.h +++ b/kernel/proto.h @@ -91,6 +91,7 @@ void fill_sendto_mask(const struct proc *rc, sys_map_t *map); int send_sig(endpoint_t proc_nr, int sig_nr); void cause_sig(proc_nr_t proc_nr, int sig_nr); void sig_delay_done(struct proc *rp); +void send_diag_sig(void); void kernel_call(message *m_user, struct proc * caller); void system_init(void); void clear_endpoint(struct proc *rc); diff --git a/kernel/system.c b/kernel/system.c index 084d47760..a76d6af69 100644 --- a/kernel/system.c +++ b/kernel/system.c @@ -18,6 +18,7 @@ * send_sig: send a signal directly to a system process * cause_sig: take action to cause a signal to occur via a signal mgr * sig_delay_done: tell PM that a process is not sending + * send_diag_sig: send a diagnostics signal to interested processes * get_randomness: accumulate randomness in a buffer * clear_endpoint: remove a process' ability to send and receive messages * sched_proc: schedule a process @@ -464,6 +465,25 @@ void sig_delay_done(struct proc *rp) cause_sig(proc_nr(rp), SIGSNDELAY); } +/*===========================================================================* + * send_diag_sig * + *===========================================================================*/ +void send_diag_sig(void) +{ +/* Send a SIGKMESS signal to all processes in receiving updates about new + * diagnostics messages. + */ + struct priv *privp; + endpoint_t ep; + + for (privp = BEG_PRIV_ADDR; privp < END_PRIV_ADDR; privp++) { + if (privp->s_proc_nr != NONE && privp->s_diag_sig == TRUE) { + ep = proc_addr(privp->s_proc_nr)->p_endpoint; + send_sig(ep, SIGKMESS); + } + } +} + /*===========================================================================* * clear_ipc * *===========================================================================*/ diff --git a/kernel/system/do_diagctl.c b/kernel/system/do_diagctl.c index a75051b9d..788dddba3 100644 --- a/kernel/system/do_diagctl.c +++ b/kernel/system/do_diagctl.c @@ -42,6 +42,21 @@ int do_diagctl(struct proc * caller, message * m_ptr) return EINVAL; proc_stacktrace(proc_addr(proc_nr)); return OK; + case DIAGCTL_CODE_REGISTER: + if (!(priv(caller)->s_flags & SYS_PROC)) + return EPERM; + priv(caller)->s_diag_sig = TRUE; + /* If the message log is not empty, send a first notification + * immediately. After bootup the log is basically never empty. + */ + if (kmess.km_size > 0 && !kinfo.do_serial_debug) + send_sig(caller->p_endpoint, SIGKMESS); + return OK; + case DIAGCTL_CODE_UNREGISTER: + if (!(priv(caller)->s_flags & SYS_PROC)) + return EPERM; + priv(caller)->s_diag_sig = FALSE; + return OK; default: printf("do_diagctl: invalid request %d\n", m_ptr->DIAGCTL_CODE); return(EINVAL); diff --git a/kernel/system/do_privctl.c b/kernel/system/do_privctl.c index 2d3cb15b5..8b7dba019 100644 --- a/kernel/system/do_privctl.c +++ b/kernel/system/do_privctl.c @@ -116,6 +116,7 @@ int do_privctl(struct proc * caller, message * m_ptr) reset_kernel_timer(&priv(rp)->s_alarm_timer); /* - alarm */ priv(rp)->s_asyntab= -1; /* - asynsends */ priv(rp)->s_asynsize= 0; + priv(rp)->s_diag_sig = FALSE; /* no request for diag sigs */ /* Set defaults for privilege bitmaps. */ priv(rp)->s_flags= DSRV_F; /* privilege flags */ diff --git a/kernel/system/do_update.c b/kernel/system/do_update.c index 38341b32a..d0f7ceb90 100644 --- a/kernel/system/do_update.c +++ b/kernel/system/do_update.c @@ -161,6 +161,7 @@ static void adjust_priv_slot(struct priv *privp, struct priv *from_privp) privp->s_int_pending = from_privp->s_int_pending; privp->s_sig_pending = from_privp->s_sig_pending; privp->s_alarm_timer = from_privp->s_alarm_timer; + privp->s_diag_sig = from_privp->s_diag_sig; } /*===========================================================================* diff --git a/kernel/utility.c b/kernel/utility.c index f112ee07a..d5fdbdb02 100644 --- a/kernel/utility.c +++ b/kernel/utility.c @@ -55,7 +55,7 @@ void kputc(c) int c; /* character to append */ { /* Accumulate a single character for a kernel message. Send a notification - * to the output driver if an END_OF_KMESS is encountered. + * to the output drivers if an END_OF_KMESS is encountered. */ if (c != END_OF_KMESS) { int maxblpos = sizeof(kmess.kmess_buf) - 2; @@ -75,18 +75,9 @@ int c; /* character to append */ memmove(kmess.kmess_buf, kmess.kmess_buf+1, sizeof(kmess.kmess_buf)-1); } else kmess.blpos++; - } else { - int p; - endpoint_t outprocs[] = OUTPUT_PROCS_ARRAY; - if(!(kinfo.minix_panicing || kinfo.do_serial_debug)) { - for(p = 0; outprocs[p] != NONE; p++) { - if(isokprocn(outprocs[p])) { - send_sig(outprocs[p], SIGKMESS); - } - } - } + } else if (!(kinfo.minix_panicing || kinfo.do_serial_debug)) { + send_diag_sig(); } - return; } /*===========================================================================* diff --git a/lib/libsys/kputc.c b/lib/libsys/kputc.c index 5e3fbbf40..7a2106dcc 100644 --- a/lib/libsys/kputc.c +++ b/lib/libsys/kputc.c @@ -20,7 +20,7 @@ void kputc(int c) static int buf_count; /* # characters in the buffer */ if ((c == 0 && buf_count > 0) || buf_count == sizeof(print_buf)) { - sys_diagctl(DIAGCTL_CODE_DIAG, print_buf, buf_count); + sys_diagctl_diag(print_buf, buf_count); buf_count = 0; } if (c != 0) { diff --git a/lib/libsys/sys_diagctl.c b/lib/libsys/sys_diagctl.c index a74777c49..bf7ca5d8c 100644 --- a/lib/libsys/sys_diagctl.c +++ b/lib/libsys/sys_diagctl.c @@ -11,9 +11,3 @@ int sys_diagctl(int code, char *arg1, int arg2) return(_kernel_call(SYS_DIAGCTL, &m)); } - -int sys_diagctl_stacktrace(endpoint_t ep) -{ - return sys_diagctl(DIAGCTL_CODE_STACKTRACE, NULL, ep); -} -