logdevices[i].log_source = NONE;
}
+ /* Register for diagnostics notifications. */
+ sys_diagctl_register();
+
return(OK);
}
/* Final one-time keyboard initialization. */
kb_init_once();
+ /* Register for diagnostics notifications. */
+ sys_diagctl_register();
+
return(OK);
}
#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. */
/* 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.
*/
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);
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)
* 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); }
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); }
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];
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);
* 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
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 *
*===========================================================================*/
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);
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 */
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;
}
/*===========================================================================*
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;
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;
}
/*===========================================================================*
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) {
return(_kernel_call(SYS_DIAGCTL, &m));
}
-
-int sys_diagctl_stacktrace(endpoint_t ep)
-{
- return sys_diagctl(DIAGCTL_CODE_STACKTRACE, NULL, ep);
-}
-