Allowed printing diagnostic messages (either from system processes or the

kernel) to the log driver. The log driver forwards such output to the TTY.

Changed driver_task() not to send a reply if the return value is EDONTREPLY.
This commit is contained in:
Jorrit Herder 2005-07-21 18:29:52 +00:00
parent da9b8e45f9
commit 09830fc33e
6 changed files with 227 additions and 43 deletions

View file

@ -128,11 +128,13 @@ struct driver *dp; /* Device dependent entry points. */
(*dp->dr_cleanup)();
/* Finally, prepare and send the reply message. */
mess.m_type = TASK_REPLY;
mess.REP_PROC_NR = proc_nr;
mess.REP_STATUS = r; /* # of bytes transferred or error code */
send(device_caller, &mess); /* send reply to caller */
if (r != EDONTREPLY) {
mess.m_type = TASK_REPLY;
mess.REP_PROC_NR = proc_nr;
/* Status is # of bytes transferred or error code. */
mess.REP_STATUS = r;
send(device_caller, &mess);
}
}
}

View file

@ -15,7 +15,7 @@ CFLAGS = -I$i
LDFLAGS = -i
LIBS = -lsys -lsysutil
OBJ = log.o
OBJ = log.o diag.o kputc.o
LIBDRIVER = $d/libdriver/driver.o

122
drivers/log/diag.c Normal file
View file

@ -0,0 +1,122 @@
/* This file handle diagnostic output that is directly sent to the LOG driver.
* This output can either be a kernel message (announced through a SYS_EVENT
* with a SIGKMESS in the signal set) or output from another system process
* (announced through a DIAGNOSTICS message).
*
* Changes:
* 21 July 2005: Created (Jorrit N. Herder)
*/
#include <stdio.h>
#include <fcntl.h>
#include "log.h"
#include "../../kernel/const.h"
#include "../../kernel/config.h"
#include "../../kernel/type.h"
/*==========================================================================*
* do_new_kmess *
*==========================================================================*/
PUBLIC int do_new_kmess(m)
message *m; /* notification message */
{
/* Notification for a new kernel message. */
struct kmessages kmess; /* entire kmess structure */
char print_buf[KMESS_BUF_SIZE]; /* copy new message here */
static int prev_next = 0;
int size, next;
int bytes;
int i, r;
/* Try to get a fresh copy of the buffer with kernel messages. */
if ((r=sys_getkmessages(&kmess)) != OK) {
report("LOG","couldn't get copy of kmessages", r);
return EDONTREPLY;
}
/* Print only the new part. Determine how many new bytes there are with
* help of the current and previous 'next' index. Note that the kernel
* buffer is circular. This works fine if less then KMESS_BUF_SIZE bytes
* is new data; else we miss % KMESS_BUF_SIZE here.
* Check for size being positive, the buffer might as well be emptied!
*/
if (kmess.km_size > 0) {
bytes = ((kmess.km_next + KMESS_BUF_SIZE) - prev_next) % KMESS_BUF_SIZE;
r=prev_next; /* start at previous old */
i=0;
while (bytes > 0) {
print_buf[i] = kmess.km_buf[(r%KMESS_BUF_SIZE)];
log_putc( kmess.km_buf[(r%KMESS_BUF_SIZE)] );
bytes --;
r ++;
i ++;
}
/* Now terminate the new message and print it. */
print_buf[i] = 0;
printf(print_buf);
}
/* Almost done, store 'next' so that we can determine what part of the
* kernel messages buffer to print next time a notification arrives.
*/
prev_next = kmess.km_next;
return EDONTREPLY;
}
/*===========================================================================*
* do_diagnostics *
*===========================================================================*/
PUBLIC int do_diagnostics(message *m)
{
/* The LOG server handles all diagnostic messages from servers and device
* drivers. It forwards the message to the TTY driver to display it to the
* user. It also saves a copy in a local buffer so that messages can be
* reviewed at a later time.
*/
int result;
int proc_nr;
vir_bytes src;
int count;
char c;
int i = 0;
static char diagbuf[1024];
/* Forward the message to the TTY driver. Inform the TTY driver about the
* original sender, so that it knows where the buffer to be printed is.
* The message type, DIAGNOSTICS, remains the same.
*/
if ((proc_nr = m->DIAG_PROC_NR) == SELF)
m->DIAG_PROC_NR = proc_nr = m->m_source;
result = _sendrec(TTY, m);
/* Now also make a copy for the private buffer at the LOG server, so
* that the messages can be reviewed at a later time.
*/
src = (vir_bytes) m->DIAG_PRINT_BUF;
count = m->DIAG_BUF_COUNT;
while (count > 0) {
if (sys_datacopy(proc_nr, src, SELF, (vir_bytes) &c, 1) != OK)
break; /* stop copying on error */
log_putc(c); /* accumulate character */
src ++;
count --;
}
return result;
}
/*===========================================================================*
* log_putc *
*===========================================================================*/
PUBLIC void log_putc(c)
int c; /* char to be added to diag buffer */
{
}

36
drivers/log/kputc.c Normal file
View file

@ -0,0 +1,36 @@
/* A server must occasionally print some message. It uses a simple version of
* printf() found in the system library that calls putk() to output characters.
* The LOG driver cannot use the regular putk(). Hence, it uses a special
* version of putk() that directly sends to the TTY task.
*
* Changes:
* 21 July 2005: Created (Jorrit N. Herder)
*/
#include "log.h"
/*===========================================================================*
* kputc *
*===========================================================================*/
void kputc(c)
int c;
{
/* Accumulate another character. If 0 or buffer full, print it. */
static int buf_count; /* # characters in the buffer */
static char print_buf[80]; /* output is buffered here */
message m;
if ((c == 0 && buf_count > 0) || buf_count == sizeof(print_buf)) {
m.DIAG_BUF_COUNT = buf_count;
m.DIAG_PRINT_BUF = print_buf;
m.DIAG_PROC_NR = SELF;
m.m_type = DIAGNOSTICS; /* request TTY to output this buffer */
_sendrec(TTY, &m); /* if it fails, we cannot do better */
buf_count = 0; /* clear buffer for next batch */
}
if (c != 0) {
print_buf[buf_count++] = c;
}
}

View file

@ -2,45 +2,26 @@
* /dev/klog - system log device
*
* Changes:
* 7 july 2005 - Created (Ben Gras)
* 21 July 2005 - Support for diagnostic messages (Jorrit N. Herder)
* 7 July 2005 - Created (Ben Gras)
*/
#include "../drivers.h"
#include "../libdriver/driver.h"
#include "log.h"
#include <sys/time.h>
#include <sys/select.h>
#include "../../kernel/const.h"
#include "../../kernel/type.h"
#include <sys/time.h>
#include <sys/select.h>
#define NR_DEVS 1 /* number of minor devices */
#define KRANDOM_PERIOD 10 /* ticks between krandom calls */
#define LOG_DEBUG 0
#define LOG_DEBUG 0 /* enable/ disable debugging */
#define NR_DEVS 1 /* number of minor devices */
#define MINOR_KLOG 0 /* /dev/klog */
#define LOG_SIZE (5*1024)
#define LOGINC(n, i) do { (n) = (((n) + (i)) % LOG_SIZE); } while(0)
#define SUSPENDABLE 1
PRIVATE struct logdevice {
char log_buffer[LOG_SIZE];
int log_size, /* no. of bytes in log buffer */
log_read, /* read mark */
log_write; /* write mark */
#if SUSPENDABLE
int log_proc_nr,
log_source,
log_iosize; /* proc that is blocking on read */
vir_bytes log_user_vir;
#endif
int log_selected, log_select_proc;
} logdevices[NR_DEVS];
PRIVATE struct device log_geom[NR_DEVS]; /* base and size of each device */
PRIVATE int log_device = -1; /* current device */
PUBLIC struct logdevice logdevices[NR_DEVS];
PRIVATE struct device log_geom[NR_DEVS]; /* base and size of devices */
PRIVATE int log_device = -1; /* current device */
FORWARD _PROTOTYPE( char *log_name, (void) );
FORWARD _PROTOTYPE( struct device *log_prepare, (int device) );
@ -376,15 +357,22 @@ message *m_ptr;
* understand.
*/
switch(m_ptr->m_type) {
case DIAGNOSTICS:
r = subwrite(&logdevices[0], m_ptr->DIAG_BUF_COUNT,
m_ptr->m_source, (vir_bytes) m_ptr->DIAG_PRINT_BUF);
break;
default:
r = EINVAL;
break;
case DIAGNOSTICS: {
r = do_diagnostics(m_ptr);
break;
}
case SYS_EVENT: {
sigset_t sigset = m_ptr->NOTIFY_ARG;
if (sigismember(&sigset, SIGKMESS)) {
do_new_kmess(m_ptr);
}
r = EDONTREPLY;
break;
}
default:
r = EINVAL;
break;
}
return r;
}

36
drivers/log/log.h Normal file
View file

@ -0,0 +1,36 @@
/* Includes. */
#include "../drivers.h"
#include "../libdriver/driver.h"
#include <minix/type.h>
#include <minix/const.h>
#include <minix/com.h>
#include <sys/types.h>
#include <minix/ipc.h>
/* Constants and types. */
#define LOG_SIZE (5*1024)
#define SUSPENDABLE 1
struct logdevice {
char log_buffer[LOG_SIZE];
int log_size, /* no. of bytes in log buffer */
log_read, /* read mark */
log_write; /* write mark */
#if SUSPENDABLE
int log_proc_nr,
log_source,
log_iosize; /* proc that is blocking on read */
vir_bytes log_user_vir;
#endif
int log_selected, log_select_proc;
};
/* Function prototypes. */
_PROTOTYPE( void kputc, (int c) );
_PROTOTYPE( int do_new_kmess, (message *m) );
_PROTOTYPE( int do_diagnostics, (message *m) );
_PROTOTYPE( void log_putc, (int c) );