]> Zhao Yanbai Git Server - minix.git/commitdiff
Allowed printing diagnostic messages (either from system processes or the
authorJorrit Herder <jnherder@minix3.org>
Thu, 21 Jul 2005 18:29:52 +0000 (18:29 +0000)
committerJorrit Herder <jnherder@minix3.org>
Thu, 21 Jul 2005 18:29:52 +0000 (18:29 +0000)
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.

drivers/libdriver/driver.c
drivers/log/Makefile
drivers/log/diag.c [new file with mode: 0644]
drivers/log/kputc.c [new file with mode: 0644]
drivers/log/log.c
drivers/log/log.h [new file with mode: 0644]

index bfd360e62d019bea910831b066989bbb33354428..78c4ebbaa5ffb3cb9452f106894164c470be96e1 100644 (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);
+       }
   }
 }
 
index d62267d9ce125a735271eac55925e518b78a93fe..bc6de0779ddc5fb1fe118236b6d87a7a0df51e18 100644 (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
 
 
diff --git a/drivers/log/diag.c b/drivers/log/diag.c
new file mode 100644 (file)
index 0000000..524a4e7
--- /dev/null
@@ -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 */
+{
+
+}
+
+
+
diff --git a/drivers/log/kputc.c b/drivers/log/kputc.c
new file mode 100644 (file)
index 0000000..5271181
--- /dev/null
@@ -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;
+  }
+}
+
index 54cf75c43d5221be3f2cd789e8d7643049fac7bb..fecf192128b99e434b52e5f54db5aa6a48d0e26e 100644 (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 "../../kernel/const.h"
-#include "../../kernel/type.h"
-
+#include "log.h"
 #include <sys/time.h>
 #include <sys/select.h>
+#include "../../kernel/const.h"
+#include "../../kernel/type.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;
 }
 
diff --git a/drivers/log/log.h b/drivers/log/log.h
new file mode 100644 (file)
index 0000000..91ab3ae
--- /dev/null
@@ -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)                                     );
+
+