]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/subr_log.c
xnu-4570.20.62.tar.gz
[apple/xnu.git] / bsd / kern / subr_log.c
index 5a748b5b53e750b5515227e16e6b2b7ebe4159e5..cde2de0bedd85a73761a37b378d289721e431907 100644 (file)
 #include <kern/locks.h>
 
 /* XXX should be in a common header somewhere */
-extern void logwakeup(void);
+extern void logwakeup(struct msgbuf *);
 extern void oslogwakeup(void);
 extern void oslog_streamwakeup(void);
 static void oslog_streamwakeup_locked(void);
@@ -117,17 +117,21 @@ extern uint32_t oslog_s_error_count;
 #define LOG_ASYNC      0x04
 #define LOG_RDWAIT     0x08
 
-#define MAX_UNREAD_CHARS (CONFIG_MSG_BSIZE/2)
 /* All globals should be accessed under LOG_LOCK() */
 
+static char amsg_bufc[1024];
+static struct msgbuf aslbuf = {MSG_MAGIC, sizeof (amsg_bufc), 0, 0, amsg_bufc};
+struct msgbuf *aslbufp __attribute__((used)) = &aslbuf;
+
 /* logsoftc only valid while log_open=1 */
 struct logsoftc {
        int     sc_state;               /* see above for possibilities */
        struct  selinfo sc_selp;        /* thread waiting for select */
        int     sc_pgid;                /* process/group for async I/O */
+       struct msgbuf *sc_mbp;
 } logsoftc;
 
-int    log_open;                       /* also used in log() */
+static int log_open;
 char smsg_bufc[CONFIG_MSG_BSIZE]; /* static buffer */
 char oslog_stream_bufc[FIREHOSE_CHUNK_SIZE]; /* static buffer */
 struct firehose_chunk_s oslog_boot_buf = {
@@ -140,8 +144,8 @@ struct firehose_chunk_s oslog_boot_buf = {
        },
 }; /* static buffer */
 firehose_chunk_t firehose_boot_chunk = &oslog_boot_buf;
-struct msgbuf msgbuf = {MSG_MAGIC,sizeof(smsg_bufc),0,0,smsg_bufc};
-struct msgbuf oslog_stream_buf = {MSG_MAGIC,0,0,0,NULL};
+struct msgbuf msgbuf = {MSG_MAGIC, sizeof(smsg_bufc), 0, 0, smsg_bufc};
+struct msgbuf oslog_stream_buf = {MSG_MAGIC, 0, 0, 0, NULL};
 struct msgbuf *msgbufp __attribute__((used)) = &msgbuf;
 struct msgbuf *oslog_streambufp __attribute__((used)) = &oslog_stream_buf;
 
@@ -168,7 +172,7 @@ struct oslog_streamsoftc {
        int     sc_state;               /* see above for possibilities */
        struct  selinfo sc_selp;        /* thread waiting for select */
        int     sc_pgid;                /* process/group for async I/O */
-}oslog_streamsoftc;
+} oslog_streamsoftc;
 
 STAILQ_HEAD(, oslog_stream_buf_entry_s) oslog_stream_free_head =
                STAILQ_HEAD_INITIALIZER(oslog_stream_free_head);
@@ -233,9 +237,7 @@ static void oslog_streamwrite_append_bytes(const char *buffer, int buflen);
 #endif
 
 static int sysctl_kern_msgbuf(struct sysctl_oid *oidp,
-                               void *arg1,
-                               int arg2,
-                               struct sysctl_req *req);
+       void *arg1, int arg2, struct sysctl_req *req);
 
 /*ARGSUSED*/
 int
@@ -246,6 +248,16 @@ logopen(__unused dev_t dev, __unused int flags, __unused int mode, struct proc *
                LOG_UNLOCK();
                return (EBUSY);
        }
+       if (atm_get_diagnostic_config() & ATM_ENABLE_LEGACY_LOGGING) {
+               logsoftc.sc_mbp = msgbufp;
+       } else {
+               /*
+                * Support for messagetracer (kern_asl_msg())
+                * In this mode, /dev/klog exports only ASL-formatted messages
+                * written into aslbufp via vaddlog().
+                */
+               logsoftc.sc_mbp = aslbufp;
+       }
        logsoftc.sc_pgid = p->p_pid;            /* signal process only */
        log_open = 1;
 
@@ -408,9 +420,10 @@ logread(__unused dev_t dev, struct uio *uio, int flag)
 {
        int l;
        int error = 0;
+       struct msgbuf *mbp = logsoftc.sc_mbp;
 
        LOG_LOCK();
-       while (msgbufp->msg_bufr == msgbufp->msg_bufx) {
+       while (mbp->msg_bufr == mbp->msg_bufx) {
                if (flag & IO_NDELAY) {
                        error = EWOULDBLOCK;
                        goto out;
@@ -425,7 +438,7 @@ logread(__unused dev_t dev, struct uio *uio, int flag)
                 * If the wakeup is missed 
                 * then wait for 5 sec and reevaluate 
                 */
-               if ((error = tsleep((caddr_t)msgbufp, LOG_RDPRI | PCATCH,
+               if ((error = tsleep((caddr_t)mbp, LOG_RDPRI | PCATCH,
                                "klog", 5 * hz)) != 0) {
                        /* if it times out; ignore */
                        if (error != EWOULDBLOCK)
@@ -438,23 +451,22 @@ logread(__unused dev_t dev, struct uio *uio, int flag)
        while (uio_resid(uio) > 0) {
                int readpos;
 
-               l = msgbufp->msg_bufx - msgbufp->msg_bufr;
+               l = mbp->msg_bufx - mbp->msg_bufr;
                if (l < 0)
-                       l = msgbufp->msg_size - msgbufp->msg_bufr;
+                       l = mbp->msg_size - mbp->msg_bufr;
                l = min(l, uio_resid(uio));
                if (l == 0)
                        break;
 
-               readpos = msgbufp->msg_bufr;
+               readpos = mbp->msg_bufr;
                LOG_UNLOCK();
-               error = uiomove((caddr_t)&msgbufp->msg_bufc[readpos],
-                       l, uio);
+               error = uiomove((caddr_t)&mbp->msg_bufc[readpos], l, uio);
                LOG_LOCK();
                if (error)
                        break;
-               msgbufp->msg_bufr = readpos + l;
-               if (msgbufp->msg_bufr >= msgbufp->msg_size)
-                       msgbufp->msg_bufr = 0;
+               mbp->msg_bufr = readpos + l;
+               if (mbp->msg_bufr >= mbp->msg_size)
+                       mbp->msg_bufr = 0;
        }
 out:
        LOG_UNLOCK();
@@ -588,11 +600,13 @@ oslog_streamread(__unused dev_t dev, struct uio *uio, int flag)
 int
 logselect(__unused dev_t dev, int rw, void * wql, struct proc *p)
 {
+       const struct msgbuf *mbp = logsoftc.sc_mbp;
+
        switch (rw) {
 
        case FREAD:
                LOG_LOCK();     
-               if (msgbufp->msg_bufr != msgbufp->msg_bufx) {
+               if (mbp->msg_bufr != mbp->msg_bufx) {
                        LOG_UNLOCK();
                        return (1);
                }
@@ -643,10 +657,8 @@ oslog_streamselect(__unused dev_t dev, int rw, void * wql, struct proc *p)
 }
 
 void
-logwakeup(void)
+logwakeup(struct msgbuf *mbp)
 {
-       int pgid;
-
        /* cf. r24974766 & r25201228*/
        if (oslog_is_safe() == FALSE) {
                return;
@@ -657,9 +669,13 @@ logwakeup(void)
                LOG_UNLOCK();
                return;
        }
+       if (NULL == mbp)
+               mbp = logsoftc.sc_mbp;
+       if (mbp != logsoftc.sc_mbp)
+               goto out;
        selwakeup(&logsoftc.sc_selp);
        if (logsoftc.sc_state & LOG_ASYNC) {
-               pgid = logsoftc.sc_pgid;
+               int pgid = logsoftc.sc_pgid;
                LOG_UNLOCK();
                if (pgid < 0)
                        gsignal(-pgid, SIGIO); 
@@ -668,9 +684,10 @@ logwakeup(void)
                LOG_LOCK();
        }
        if (logsoftc.sc_state & LOG_RDWAIT) {
-               wakeup((caddr_t)msgbufp);
+               wakeup((caddr_t)mbp);
                logsoftc.sc_state &= ~LOG_RDWAIT;
        }
+out:
        LOG_UNLOCK();
 }
 
@@ -719,15 +736,16 @@ int
 logioctl(__unused dev_t dev, u_long com, caddr_t data, __unused int flag, __unused struct proc *p)
 {
        int l;
+       const struct msgbuf *mbp = logsoftc.sc_mbp;
 
        LOG_LOCK();
        switch (com) {
 
        /* return number of characters immediately available */
        case FIONREAD:
-               l = msgbufp->msg_bufx - msgbufp->msg_bufr;
+               l = mbp->msg_bufx - mbp->msg_bufr;
                if (l < 0)
-                       l += msgbufp->msg_size;
+                       l += mbp->msg_size;
                *(off_t *)data = l;
                break;
 
@@ -892,13 +910,10 @@ oslog_init(void)
  *             SMP reentrancy.
  */
 void
-log_putc_locked(char c)
+log_putc_locked(struct msgbuf *mbp, char c)
 {
-       struct msgbuf *mbp;
-
-       mbp = msgbufp; 
        mbp->msg_bufc[mbp->msg_bufx++] = c;
-       if (mbp->msg_bufx >= msgbufp->msg_size)
+       if (mbp->msg_bufx >= mbp->msg_size)
                mbp->msg_bufx = 0;
 }
 
@@ -953,7 +968,8 @@ oslog_streamwrite_metadata_locked(oslog_stream_buf_entry_t m_entry)
        return;
 }
 
-static void oslog_streamwrite_append_bytes(const char *buffer, int buflen)
+static void
+oslog_streamwrite_append_bytes(const char *buffer, int buflen)
 {
        struct msgbuf *mbp;
 
@@ -1080,7 +1096,7 @@ oslog_streamwrite_locked(firehose_tracepoint_id_u ftid,
  *
  * Returns:    (void)
  *
- * Notes:      This function is used for syingle byte output to the log.  It
+ * Notes:      This function is used for single byte output to the log.  It
  *             primarily exists to maintain binary backward compatibility.
  */
 void
@@ -1088,14 +1104,14 @@ log_putc(char c)
 {
        int unread_count = 0;
        LOG_LOCK();
-       log_putc_locked(c);
+       log_putc_locked(msgbufp, c);
        unread_count = msgbufp->msg_bufx - msgbufp->msg_bufr;
        LOG_UNLOCK();
 
        if (unread_count < 0)
                unread_count = 0 - unread_count;
-       if (c == '\n' || unread_count >= MAX_UNREAD_CHARS)
-               logwakeup();
+       if (c == '\n' || unread_count >= (msgbufp->msg_size / 2))
+               logwakeup(msgbufp);
 }
 
 
@@ -1109,7 +1125,8 @@ log_putc(char c)
  * memory is dynamically allocated. Memory management must already be up.
  */
 int
-log_setsize(int size) {
+log_setsize(int size)
+{
        char *new_logdata;
        int new_logsize, new_bufr, new_bufx;
        char *old_logdata;
@@ -1210,12 +1227,13 @@ void oslog_setsize(int size)
        printf("oslog_setsize: new buffer size = %d, new num entries= %d\n", oslog_stream_buf_size, oslog_stream_num_entries);
 }
 
-SYSCTL_PROC(_kern, OID_AUTO, msgbuf, CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED, 0, 0, sysctl_kern_msgbuf, "I", "");
+SYSCTL_PROC(_kern, OID_AUTO, msgbuf,
+       CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED, 0, 0,
+       sysctl_kern_msgbuf, "I", "");
 
-static int sysctl_kern_msgbuf(struct sysctl_oid *oidp __unused,
-                                                         void *arg1 __unused,
-                                                         int arg2 __unused,
-                                                         struct sysctl_req *req)
+static int
+sysctl_kern_msgbuf(struct sysctl_oid *oidp __unused,
+       void *arg1 __unused, int arg2 __unused, struct sysctl_req *req)
 {
        int old_bufsize, bufsize;
        int error;
@@ -1241,7 +1259,8 @@ static int sysctl_kern_msgbuf(struct sysctl_oid *oidp __unused,
  * It returns as much data still in the buffer as possible.
  */
 int
-log_dmesg(user_addr_t buffer, uint32_t buffersize, int32_t * retval) {
+log_dmesg(user_addr_t buffer, uint32_t buffersize, int32_t * retval)
+{
        uint32_t i;
        uint32_t localbuff_size;
        int error = 0, newl, skip;