📄 debug.c
字号:
/* * This source code is a part of coLinux source package. * * Dan Aloni <da-x@colinux.org>, 2004 (c) * * The code is licensed under the GPL. See the COPYING file at * the root directory. */#include <colinux/os/alloc.h>#include <colinux/os/kernel/user.h>#include <colinux/common/libc.h>#include "manager.h"#include "debug.h"static void report_status(const char *event, co_manager_debug_t *debug){ co_debug_system("colinux-debug: %s: sections: %d, total: %ld, filled: %ld", event, debug->sections_count, debug->sections_total_size, debug->sections_total_filled);}static co_rc_t create_section(co_debug_section_t **section_out){ co_debug_section_t *section; co_rc_t rc; section = co_os_malloc(sizeof(co_debug_section_t)); if (!section) return CO_RC(OUT_OF_MEMORY); section->buffer = co_os_malloc(CO_DEBUG_SECTION_BUFFER_START_SIZE); if (!section->buffer) { co_os_free(section); return CO_RC(OUT_OF_MEMORY); } rc = co_os_mutex_create(§ion->mutex); if (!CO_OK(rc)) { co_os_free(section->buffer); co_os_free(section); return rc; } co_list_init(§ion->node); section->buffer_size = CO_DEBUG_SECTION_BUFFER_START_SIZE; section->filled = 0; section->refcount = 0; section->folded = PFALSE; section->peak_size = section->buffer_size; section->max_size = CO_DEBUG_SECTION_BUFFER_MAX_SIZE; *section_out = section; return CO_RC(OK);}static void resize_section(co_manager_debug_t *debug, co_debug_section_t *section){ long new_size = 0, old_size = 0; char *new_buffer, *old_buffer; if (section->filled >= section->buffer_size / 2) { /* * If the buffer is half full, increase it's size by a factor * of two. This reduces the chance of losing logs due to write * bursts but keeps the buffers short. */ new_size = section->buffer_size * 2; if (new_size > section->max_size) return; } else if (section->filled < CO_DEBUG_SECTION_BUFFER_START_SIZE) { /* * Reduce to half the size of the peak size if the buffer is * quite empty. */ new_size = section->peak_size / 2; } if (new_size == 0) return; old_size = section->buffer_size; if (old_size != new_size) return; new_buffer = co_os_malloc(new_size); if (!new_buffer) return; old_buffer = section->buffer; co_memcpy(new_buffer, old_buffer, section->filled); debug->sections_total_size += new_size - old_size; section->buffer_size = new_size; section->buffer = new_buffer; if (section->peak_size < new_size) section->peak_size = new_size; report_status("section resize", debug); co_os_free(old_buffer);}static void memcpy_vector(char *dest, co_debug_write_vector_t *vec, int vec_size){ while (vec_size--) { if (vec->vec_size) memcpy_vector(dest, vec->vec, vec->vec_size); else co_memcpy(dest, vec->ptr, vec->size); dest += vec->size; vec++; }}static co_rc_t append_to_buffer(co_manager_debug_t *debug, co_debug_section_t *section, co_debug_write_vector_t *vec, int vec_size){ co_rc_t rc = CO_RC(OK); long vec_length = 0; resize_section(debug, section); vec_length = co_debug_write_vector_size(vec, vec_size); /* Check if there's not enough space left in the buffer */ if (section->buffer_size - section->filled < vec_length) { rc = CO_RC(ERROR); } else { memcpy_vector(§ion->buffer[section->filled], vec, vec_size); section->filled += vec_length; debug->sections_total_filled += vec_length; } return rc;}static void get_section(struct co_debug_section *section){ section->refcount++; co_os_mutex_acquire(section->mutex);}static bool_t put_section(co_manager_debug_t *debug, struct co_debug_section *section){ section->refcount--; if (section->refcount == 0) { debug->sections_count--; debug->sections_total_size -= section->buffer_size; co_os_mutex_release(section->mutex); co_os_mutex_destroy(section->mutex); co_os_free(section->buffer); co_os_free(section); report_status("section release", debug); return PFALSE; } co_os_mutex_release(section->mutex); return PTRUE;}co_rc_t co_debug_writev(co_manager_debug_t *debug, struct co_debug_section **section_ptr, co_debug_write_vector_t *vec, int vec_size){ co_rc_t rc; co_debug_section_t *section; if (debug->sections_total_filled > CO_DEBUG_MAX_FILL) return CO_RC(OK); if (debug->freeing) return CO_RC(OK); section = *section_ptr; if (!section) { rc = create_section(§ion); if (!CO_OK(rc)) goto out; debug->sections_count++; debug->sections_total_size += section->buffer_size; co_os_mutex_acquire(debug->mutex); co_list_add_tail(§ion->node, &debug->sections); co_os_mutex_release(debug->mutex); report_status("section created", debug); get_section(section); *section_ptr = section; section->refcount++; } else { get_section(section); } rc = append_to_buffer(debug, section, vec, vec_size); if (!put_section(debug, section)) *section_ptr = NULL; if (CO_OK(rc)) { co_os_wait_wakeup(debug->read_wait); } out: return rc;}static int debug_driver_index;static co_debug_tlv_t debug_tlv_index = { .type = CO_DEBUG_TYPE_DRIVER_INDEX, .length = sizeof(debug_driver_index),};static co_debug_write_vector_t driver_local_vec[2] = { { .size = sizeof(debug_tlv_index), }, { .size = sizeof(debug_driver_index), }};co_rc_t co_debug_write_log(co_manager_debug_t *debug, struct co_debug_section **section_ptr, co_debug_write_vector_t *vec, int vec_size){ unsigned long size; co_debug_tlv_t tlv; co_debug_write_vector_t local_vec[3]; size = co_debug_write_vector_size(vec, vec_size); if (size > 0xf8) return CO_RC(OK); debug_driver_index++; tlv.type = CO_DEBUG_TYPE_TLV; tlv.length = size + sizeof(debug_tlv_index) + sizeof(debug_driver_index); local_vec[0].vec_size = 0; local_vec[0].size = sizeof(tlv); local_vec[0].ptr = (void *)&tlv; local_vec[1].vec_size = vec_size; local_vec[1].size = size; local_vec[1].vec = vec; local_vec[2].vec_size = 2; local_vec[2].size = sizeof(debug_tlv_index) + sizeof(debug_driver_index); local_vec[2].vec = driver_local_vec; driver_local_vec[0].ptr = (void *)&debug_tlv_index; driver_local_vec[1].ptr = (void *)&debug_driver_index; return co_debug_writev(debug, section_ptr, local_vec, 3);}co_rc_t co_debug_read(co_manager_debug_t *debug, char *buf, unsigned long size, unsigned long *read_size){ co_rc_t rc; co_debug_section_t *section, *section_new; long user_filled = 0; co_os_wait_sleep(debug->read_wait); co_os_mutex_acquire(debug->mutex); co_list_each_entry_safe(section, section_new, &debug->sections, node) { bool_t saved = PFALSE; get_section(section); if (!(size - user_filled < section->filled)) { rc = co_copy_to_user(&buf[user_filled], section->buffer, section->filled); if (CO_OK(rc)) { user_filled += section->filled; debug->sections_total_filled -= section->filled; section->filled = 0; saved = PTRUE; } } if (saved && section->folded) { co_list_del(§ion->node); section->refcount--; section->folded = PFALSE; } if (!section->folded) resize_section(debug, section); put_section(debug, section); } co_os_mutex_release(debug->mutex); *read_size = user_filled; return CO_RC(OK);}co_rc_t co_debug_fold(co_manager_debug_t *debug, co_debug_section_t *section){ char *shrunk_buffer; co_rc_t rc = CO_RC(OK); co_os_mutex_acquire(debug->mutex); get_section(section); shrunk_buffer = co_os_malloc(section->filled + 1); if (!shrunk_buffer) { rc = CO_RC(OUT_OF_MEMORY); } else { co_memcpy(shrunk_buffer, section->buffer, section->filled); co_os_free(section->buffer); debug->sections_total_size -= section->buffer_size; section->buffer = shrunk_buffer; section->buffer_size = section->filled; debug->sections_total_size += section->buffer_size; } section->folded = PTRUE; put_section(debug, section); co_os_mutex_release(debug->mutex); return rc;}co_rc_t co_debug_init(co_manager_debug_t *debug){ co_rc_t rc; debug->freeing = PFALSE; debug->section = NULL; debug->sections_total_filled = 0; debug->sections_total_size = 0; co_list_init(&debug->sections); rc = co_os_mutex_create(&debug->mutex); if (!CO_OK(rc)) goto out; rc = co_os_wait_create(&debug->read_wait); if (!CO_OK(rc)) { co_os_mutex_destroy(debug->mutex); goto out; } debug->ready = PTRUE;out: return rc;}co_rc_t co_debug_free(co_manager_debug_t *debug){ co_debug_section_t *section, *section_new; report_status("freeing all sections", debug); debug->ready = PFALSE; debug->freeing = PTRUE; co_list_each_entry_safe(section, section_new, &debug->sections, node) { get_section(section); co_list_del(§ion->node); section->refcount--; put_section(debug, section); } co_os_wait_destroy(debug->read_wait); co_os_mutex_destroy(debug->mutex); report_status("done freeing", debug); return CO_RC(OK);}void co_debug_buf(const char *buf, long size){ co_debug_write_vector_t vec; if (!co_global_manager) return; if (!co_global_manager->debug.ready) return; vec.vec_size = 0; vec.size = size; vec.ptr = buf; co_debug_write_log(&co_global_manager->debug, &co_global_manager->debug.section, &vec, 1);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -