⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 printk.c

📁 Kernel code of linux kernel
💻 C
📖 第 1 页 / 共 3 页
字号:
	return 0;}early_param("ignore_loglevel", ignore_loglevel_setup);/* * Write out chars from start to end - 1 inclusive */static void _call_console_drivers(unsigned start,				unsigned end, int msg_log_level){	if ((msg_log_level < console_loglevel || ignore_loglevel) &&			console_drivers && start != end) {		if ((start & LOG_BUF_MASK) > (end & LOG_BUF_MASK)) {			/* wrapped write */			__call_console_drivers(start & LOG_BUF_MASK,						log_buf_len);			__call_console_drivers(0, end & LOG_BUF_MASK);		} else {			__call_console_drivers(start, end);		}	}}/* * Call the console drivers, asking them to write out * log_buf[start] to log_buf[end - 1]. * The console_sem must be held. */static void call_console_drivers(unsigned start, unsigned end){	unsigned cur_index, start_print;	static int msg_level = -1;	BUG_ON(((int)(start - end)) > 0);	cur_index = start;	start_print = start;	while (cur_index != end) {		if (msg_level < 0 && ((end - cur_index) > 2) &&				LOG_BUF(cur_index + 0) == '<' &&				LOG_BUF(cur_index + 1) >= '0' &&				LOG_BUF(cur_index + 1) <= '7' &&				LOG_BUF(cur_index + 2) == '>') {			msg_level = LOG_BUF(cur_index + 1) - '0';			cur_index += 3;			start_print = cur_index;		}		while (cur_index != end) {			char c = LOG_BUF(cur_index);			cur_index++;			if (c == '\n') {				if (msg_level < 0) {					/*					 * printk() has already given us loglevel tags in					 * the buffer.  This code is here in case the					 * log buffer has wrapped right round and scribbled					 * on those tags					 */					msg_level = default_message_loglevel;				}				_call_console_drivers(start_print, cur_index, msg_level);				msg_level = -1;				start_print = cur_index;				break;			}		}	}	_call_console_drivers(start_print, end, msg_level);}static void emit_log_char(char c){	LOG_BUF(log_end) = c;	log_end++;	if (log_end - log_start > log_buf_len)		log_start = log_end - log_buf_len;	if (log_end - con_start > log_buf_len)		con_start = log_end - log_buf_len;	if (logged_chars < log_buf_len)		logged_chars++;}/* * Zap console related locks when oopsing. Only zap at most once * every 10 seconds, to leave time for slow consoles to print a * full oops. */static void zap_locks(void){	static unsigned long oops_timestamp;	if (time_after_eq(jiffies, oops_timestamp) &&			!time_after(jiffies, oops_timestamp + 30 * HZ))		return;	oops_timestamp = jiffies;	/* If a crash is occurring, make sure we can't deadlock */	spin_lock_init(&logbuf_lock);	/* And make sure that we print immediately */	init_MUTEX(&console_sem);}#if defined(CONFIG_PRINTK_TIME)static int printk_time = 1;#elsestatic int printk_time = 0;#endifmodule_param_named(time, printk_time, bool, S_IRUGO | S_IWUSR);/* Check if we have any console registered that can be called early in boot. */static int have_callable_console(void){	struct console *con;	for (con = console_drivers; con; con = con->next)		if (con->flags & CON_ANYTIME)			return 1;	return 0;}/** * printk - print a kernel message * @fmt: format string * * This is printk().  It can be called from any context.  We want it to work. * Be aware of the fact that if oops_in_progress is not set, we might try to * wake klogd up which could deadlock on runqueue lock if printk() is called * from scheduler code. * * We try to grab the console_sem.  If we succeed, it's easy - we log the output and * call the console drivers.  If we fail to get the semaphore we place the output * into the log buffer and return.  The current holder of the console_sem will * notice the new output in release_console_sem() and will send it to the * consoles before releasing the semaphore. * * One effect of this deferred printing is that code which calls printk() and * then changes console_loglevel may break. This is because console_loglevel * is inspected when the actual printing occurs. * * See also: * printf(3) */asmlinkage int printk(const char *fmt, ...){	va_list args;	int r;	va_start(args, fmt);	r = vprintk(fmt, args);	va_end(args);	return r;}/* cpu currently holding logbuf_lock */static volatile unsigned int printk_cpu = UINT_MAX;/* * Can we actually use the console at this time on this cpu? * * Console drivers may assume that per-cpu resources have * been allocated. So unless they're explicitly marked as * being able to cope (CON_ANYTIME) don't call them until * this CPU is officially up. */static inline int can_use_console(unsigned int cpu){	return cpu_online(cpu) || have_callable_console();}/* * Try to get console ownership to actually show the kernel * messages from a 'printk'. Return true (and with the * console_semaphore held, and 'console_locked' set) if it * is successful, false otherwise. * * This gets called with the 'logbuf_lock' spinlock held and * interrupts disabled. It should return with 'lockbuf_lock' * released but interrupts still disabled. */static int acquire_console_semaphore_for_printk(unsigned int cpu){	int retval = 0;	if (!try_acquire_console_sem()) {		retval = 1;		/*		 * If we can't use the console, we need to release		 * the console semaphore by hand to avoid flushing		 * the buffer. We need to hold the console semaphore		 * in order to do this test safely.		 */		if (!can_use_console(cpu)) {			console_locked = 0;			up(&console_sem);			retval = 0;		}	}	printk_cpu = UINT_MAX;	spin_unlock(&logbuf_lock);	return retval;}static const char recursion_bug_msg [] =		KERN_CRIT "BUG: recent printk recursion!\n";static int recursion_bug;	static int new_text_line = 1;static char printk_buf[1024];asmlinkage int vprintk(const char *fmt, va_list args){	int printed_len = 0;	int current_log_level = default_message_loglevel;	unsigned long flags;	int this_cpu;	char *p;	boot_delay_msec();	preempt_disable();	/* This stops the holder of console_sem just where we want him */	raw_local_irq_save(flags);	this_cpu = smp_processor_id();	/*	 * Ouch, printk recursed into itself!	 */	if (unlikely(printk_cpu == this_cpu)) {		/*		 * If a crash is occurring during printk() on this CPU,		 * then try to get the crash message out but make sure		 * we can't deadlock. Otherwise just return to avoid the		 * recursion and return - but flag the recursion so that		 * it can be printed at the next appropriate moment:		 */		if (!oops_in_progress) {			recursion_bug = 1;			goto out_restore_irqs;		}		zap_locks();	}	lockdep_off();	spin_lock(&logbuf_lock);	printk_cpu = this_cpu;	if (recursion_bug) {		recursion_bug = 0;		strcpy(printk_buf, recursion_bug_msg);		printed_len = sizeof(recursion_bug_msg);	}	/* Emit the output into the temporary buffer */	printed_len += vscnprintf(printk_buf + printed_len,				  sizeof(printk_buf) - printed_len, fmt, args);	/*	 * Copy the output into log_buf.  If the caller didn't provide	 * appropriate log level tags, we insert them here	 */	for (p = printk_buf; *p; p++) {		if (new_text_line) {			/* If a token, set current_log_level and skip over */			if (p[0] == '<' && p[1] >= '0' && p[1] <= '7' &&			    p[2] == '>') {				current_log_level = p[1] - '0';				p += 3;				printed_len -= 3;			}			/* Always output the token */			emit_log_char('<');			emit_log_char(current_log_level + '0');			emit_log_char('>');			printed_len += 3;			new_text_line = 0;			if (printk_time) {				/* Follow the token with the time */				char tbuf[50], *tp;				unsigned tlen;				unsigned long long t;				unsigned long nanosec_rem;				t = cpu_clock(printk_cpu);				nanosec_rem = do_div(t, 1000000000);				tlen = sprintf(tbuf, "[%5lu.%06lu] ",						(unsigned long) t,						nanosec_rem / 1000);				for (tp = tbuf; tp < tbuf + tlen; tp++)					emit_log_char(*tp);				printed_len += tlen;			}			if (!*p)				break;		}		emit_log_char(*p);		if (*p == '\n')			new_text_line = 1;	}	/*	 * Try to acquire and then immediately release the	 * console semaphore. The release will do all the	 * actual magic (print out buffers, wake up klogd,	 * etc). 	 *	 * The acquire_console_semaphore_for_printk() function	 * will release 'logbuf_lock' regardless of whether it	 * actually gets the semaphore or not.	 */	if (acquire_console_semaphore_for_printk(this_cpu))		release_console_sem();	lockdep_on();out_restore_irqs:	raw_local_irq_restore(flags);	preempt_enable();	return printed_len;}EXPORT_SYMBOL(printk);EXPORT_SYMBOL(vprintk);#elseasmlinkage long sys_syslog(int type, char __user *buf, int len){	return -ENOSYS;}static void call_console_drivers(unsigned start, unsigned end){}#endifstatic int __add_preferred_console(char *name, int idx, char *options,				   char *brl_options){	struct console_cmdline *c;	int i;	/*	 *	See if this tty is not yet registered, and	 *	if we have a slot free.	 */	for (i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++)		if (strcmp(console_cmdline[i].name, name) == 0 &&			  console_cmdline[i].index == idx) {				if (!brl_options)					selected_console = i;				return 0;		}	if (i == MAX_CMDLINECONSOLES)		return -E2BIG;	if (!brl_options)		selected_console = i;	c = &console_cmdline[i];	strlcpy(c->name, name, sizeof(c->name));	c->options = options;#ifdef CONFIG_A11Y_BRAILLE_CONSOLE	c->brl_options = brl_options;#endif	c->index = idx;	return 0;}/* * Set up a list of consoles.  Called from init/main.c */static int __init console_setup(char *str){	char buf[sizeof(console_cmdline[0].name) + 4]; /* 4 for index */	char *s, *options, *brl_options = NULL;	int idx;#ifdef CONFIG_A11Y_BRAILLE_CONSOLE	if (!memcmp(str, "brl,", 4)) {		brl_options = "";		str += 4;	} else if (!memcmp(str, "brl=", 4)) {		brl_options = str + 4;		str = strchr(brl_options, ',');		if (!str) {			printk(KERN_ERR "need port name after brl=\n");			return 1;		}		*(str++) = 0;	}#endif	/*	 * Decode str into name, index, options.	 */	if (str[0] >= '0' && str[0] <= '9') {		strcpy(buf, "ttyS");		strncpy(buf + 4, str, sizeof(buf) - 5);	} else {		strncpy(buf, str, sizeof(buf) - 1);	}	buf[sizeof(buf) - 1] = 0;	if ((options = strchr(str, ',')) != NULL)		*(options++) = 0;#ifdef __sparc__	if (!strcmp(str, "ttya"))		strcpy(buf, "ttyS0");	if (!strcmp(str, "ttyb"))		strcpy(buf, "ttyS1");#endif	for (s = buf; *s; s++)		if ((*s >= '0' && *s <= '9') || *s == ',')			break;	idx = simple_strtoul(s, NULL, 10);	*s = 0;	__add_preferred_console(buf, idx, options, brl_options);	console_set_on_cmdline = 1;	return 1;}__setup("console=", console_setup);/** * add_preferred_console - add a device to the list of preferred consoles. * @name: device name * @idx: device index * @options: options for this console * * The last preferred console added will be used for kernel messages * and stdin/out/err for init.  Normally this is used by console_setup * above to handle user-supplied console arguments; however it can also * be used by arch-specific code either to override the user or more * commonly to provide a default console (ie from PROM variables) when * the user has not supplied one. */int add_preferred_console(char *name, int idx, char *options){	return __add_preferred_console(name, idx, options, NULL);}int update_console_cmdline(char *name, int idx, char *name_new, int idx_new, char *options)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -