/* * Printf to the console. */ int kprintf(const char *fmt, ...) { int chars; va_list ap; bool dolock; dolock = kprintf_lock != NULL && curthread->t_in_interrupt == false && curthread->t_iplhigh_count == 0; if (dolock) { lock_acquire(kprintf_lock); } else { spinlock_acquire(&kprintf_spinlock); } putch_prepare(); va_start(ap, fmt); chars = __vprintf(console_send, NULL, fmt, ap); va_end(ap); putch_complete(); if (dolock) { lock_release(kprintf_lock); } else { spinlock_release(&kprintf_spinlock); } return chars; }
int sl_memlog_vprintf(const char* fmt, va_list args) { // If not initialized, report error if (memlog_pos == NULL) return EINVAL; if (*memlog_pos >= memlog_size) return 0; return __vprintf(fmt, args); }
/* * kprintf and tprintf helper function. */ static inline int __kprintf(const char *fmt, va_list ap) { int chars; bool dolock; dolock = kprintf_lock != NULL && curthread->t_in_interrupt == false && curthread->t_curspl == 0 && curcpu->c_spinlocks == 0; if (dolock) { lock_acquire(kprintf_lock); } else { spinlock_acquire(&kprintf_spinlock); } chars = __vprintf(console_send, NULL, fmt, ap); if (dolock) { lock_release(kprintf_lock); } else { spinlock_release(&kprintf_spinlock); } return chars; }
int bsp_vsprintf(char *str, const char *fmt, va_list ap) { str_ptr = str; __vprintf(str_putc, fmt, ap); *str_ptr = '\0'; return str_ptr - str; }
/* The standard vprintf() function, which is like printf() but uses a va_list. Writes its output to both vga display and serial port. */ int vprintf (const char *format, va_list args) { int char_cnt = 0; acquire_console (); __vprintf (format, args, vprintf_helper, &char_cnt); release_console (); return char_cnt; }
void bsp_dprintf(const char *fmt, ...) { va_list ap; va_start (ap, fmt); __vprintf(bsp_debug_putc, fmt, ap); va_end (ap); }
size_t printf(const char *format, ...) { va_list params; size_t retval; va_start(params, format); retval = __vprintf(format, params); va_end(params); return retval; }
/* Formats the printf() format specification FORMAT with arguments given in ARGS and writes the output to the given HANDLE. */ int vhprintf (int handle, const char *format, va_list args) { struct vhprintf_aux aux; aux.p = aux.buf; aux.char_cnt = 0; aux.handle = handle; __vprintf (format, args, add_char, &aux); flush (&aux); return aux.char_cnt; }
int sl_memlog_printf(const char* fmt, ...) { // If not initialized, report error if (memlog_pos == NULL) return EINVAL; if (*memlog_pos >= memlog_size) return 0; int len; va_list args; va_start(args, fmt); len = __vprintf(fmt, args); va_end(args); return len; }
void __panic(const char *fname, const char *format, ...) { va_list params; force_interrupts_off(); stack_trace(); printf("\n\n:: EVIL :: %s() :: ", fname); va_start(params, format); __vprintf(format, params); va_end(params); while(1) { force_interrupts_off(); __halt(); } }
/* Like vprintf(), except that output is stored into BUFFER, which must have space for BUF_SIZE characters. Writes at most BUF_SIZE - 1 characters to BUFFER, followed by a null terminator. BUFFER will always be null-terminated unless BUF_SIZE is zero. Returns the number of characters that would have been written to BUFFER, not including a null terminator, had there been enough room. */ int vsnprintf (char *buffer, size_t buf_size, const char *format, va_list args) { /* Set up aux data for vsnprintf_helper(). */ struct vsnprintf_aux aux; aux.p = buffer; aux.length = 0; aux.max_length = buf_size > 0 ? buf_size - 1 : 0; /* Do most of the work. */ __vprintf (format, args, vsnprintf_helper, &aux); /* Add null terminator. */ if (buf_size > 0) *aux.p = '\0'; return aux.length; }
void __panic(const char *fname, const char *format, ...) { va_list params; force_interrupts_off(); stack_trace(); printf("\n\n:: EVIL :: %s() :: ", fname); va_start(params, format); __vprintf(format, params); va_end(params); debug_flush(); lock_vmm(); }
/* * The va_list version of snprintf. */ int vsnprintf(char *buf, size_t len, const char *fmt, va_list ap) { int chars; SNP snp; /* * Fill in the context structure. * We set snp.buflen to the number of characters that can be * written (excluding the null terminator) so as not to have * to special-case the possibility that we got passed a length * of zero elsewhere. */ snp.buf = buf; if (len==0) { snp.buflen = 0; } else { snp.buflen = len-1; } snp.bufpos = 0; /* Call __vprintf to do the actual work. */ chars = __vprintf(__snprintf_send, &snp, fmt, ap); /* * Add a null terminator. If the length *we were passed* is greater * than zero, we reserved a space in the buffer for the terminator, * so this won't overflow. If the length we were passed is zero, * nothing will have been or should be written anyway, and buf * might even be NULL. (C99 explicitly endorses this possibility.) */ if (len > 0) { buf[snp.bufpos] = 0; } /* * Return the number of characters __vprintf processed. * According to C99, snprintf should return this number, not * the number of characters actually stored, and should not * return -1 on overflow but only on other errors. (All none * of them since we don't do multibyte characters...) */ return chars; }
/* * Common routine for all the *err* and *warn* functions. */ static void __printerr(int use_errno, const char *fmt, va_list ap) { const char *errmsg; const char *prog; /* * Get the error message for the current errno. * Do this early, before doing anything that might change the * value in errno. */ errmsg = strerror(errno); /* * Look up the program name. * Strictly speaking we should pull off the rightmost * path component of argv[0] and use that as the program * name (this is how BSD err* prints) but it doesn't make * much difference. */ if (__argv!=NULL && __argv[0]!=NULL) { prog = __argv[0]; } else { prog = "(program name hello unknown)"; } /* print the program name */ __senderrstr(prog); __senderrstr(": "); /* process the printf format and args */ __vprintf(__senderr, NULL, fmt, ap); /* if we're using errno, print the error string from above. */ if (use_errno) { __senderrstr(": "); __senderrstr(errmsg); } /* and always add a newline. */ __senderrstr("\n"); }
/* Printf to the console. */ int kprintf(const char *fmt, ...) { int chars; va_list ap; if (kprintf_lock != NULL && !in_interrupt && curspl==0) { lock_acquire(kprintf_lock); } va_start(ap, fmt); chars = __vprintf(console_send, NULL, fmt, ap); va_end(ap); if (kprintf_lock != NULL && !in_interrupt && curspl==0) { lock_release(kprintf_lock); } return chars; }
void bsp_dvprintf(const char *fmt, va_list ap) { __vprintf(bsp_debug_putc, fmt, ap); }
void bsp_vprintf(const char *fmt, va_list ap) { __vprintf(bsp_console_putc, fmt, ap); }
/* vprintf: call __vprintf to do the work. */ int vprintf(const char *fmt, va_list ap) { return __vprintf(__printf_send, NULL, fmt, ap); }
void panic(const char *fmt, ...) { va_list ap; /* * When we reach panic, the system is usually fairly screwed up. * It's not entirely uncommon for anything else we try to do * here to trigger more panics. * * This variable makes sure that if we try to do something here, * and it causes another panic, *that* panic doesn't try again; * trying again almost inevitably causes infinite recursion. * * This is not excessively paranoid - these things DO happen! */ static volatile int evil; if (evil == 0) { evil = 1; /* * Not only do we not want to be interrupted while * panicking, but we also want the console to be * printing in polling mode so as not to do context * switches. So turn interrupts off on this CPU. */ splhigh(); } if (evil == 1) { evil = 2; /* Kill off other threads and halt other CPUs. */ thread_panic(); } if (evil == 2) { evil = 3; /* Print the message. */ kprintf("panic: "); putch_prepare(); va_start(ap, fmt); __vprintf(console_send, NULL, fmt, ap); va_end(ap); putch_complete(); } if (evil == 3) { evil = 4; /* Try to sync the disks. */ vfs_sync(); } if (evil == 4) { evil = 5; /* Shut down or reboot the system. */ mainbus_panic(); } /* * Last resort, just in case. */ for (;;); }