static Menu* add_debug_menu() { Menu* menu = new(std::nothrow) Menu(STANDARD_MENU, "Debug Options"); MenuItem* item; #if DEBUG_SPINLOCK_LATENCIES item = new(std::nothrow) MenuItem("Disable latency checks"); if (item != NULL) { item->SetType(MENU_ITEM_MARKABLE); item->SetData(B_SAFEMODE_DISABLE_LATENCY_CHECK); item->SetHelpText("Disables latency check panics."); menu->AddItem(item); } #endif menu->AddItem(item = new(nothrow) MenuItem("Enable serial debug output")); item->SetData("serial_debug_output"); item->SetType(MENU_ITEM_MARKABLE); item->SetHelpText("Turns on forwarding the syslog output to the serial " "interface."); menu->AddItem(item = new(nothrow) MenuItem("Enable on screen debug output")); item->SetData("debug_screen"); item->SetType(MENU_ITEM_MARKABLE); item->SetHelpText("Displays debug output on screen while the system " "is booting, instead of the normal boot logo."); menu->AddItem(item = new(nothrow) MenuItem("Enable debug syslog")); item->SetType(MENU_ITEM_MARKABLE); item->SetMarked(gKernelArgs.keep_debug_output_buffer); item->SetTarget(&debug_menu_toggle_debug_syslog); item->SetHelpText("Enables a special in-memory syslog buffer for this " "session that the boot loader will be able to access after rebooting."); ring_buffer* syslogBuffer = (ring_buffer*)gKernelArgs.debug_output; if (syslogBuffer != NULL && ring_buffer_readable(syslogBuffer) > 0) { menu->AddSeparatorItem(); menu->AddItem(item = new(nothrow) MenuItem("Display syslog from previous session")); item->SetTarget(&debug_menu_display_syslog); item->SetType(MENU_ITEM_NO_CHOICE); item->SetHelpText( "Displays the syslog from the previous Haiku session."); menu->AddItem(item = new(nothrow) MenuItem( "Save syslog from previous session", add_save_debug_syslog_menu())); item->SetHelpText("Saves the syslog from the previous Haiku session to " "disk. Currently only FAT32 volumes are supported."); } menu->AddSeparatorItem(); menu->AddItem(item = new(nothrow) MenuItem("Return to main menu")); return menu; }
static status_t save_previous_syslog_to_volume(Directory* directory) { // find an unused name char name[16]; bool found = false; for (int i = 0; i < 99; i++) { snprintf(name, sizeof(name), "SYSLOG%02d.TXT", i); Node* node = directory->Lookup(name, false); if (node == NULL) { found = true; break; } node->Release(); } if (!found) { printf("Failed to find an unused name for the syslog file!\n"); return B_ERROR; } printf("Writing syslog to file \"%s\" ...\n", name); int fd = open_from(directory, name, O_RDWR | O_CREAT | O_EXCL, 0644); if (fd < 0) { printf("Failed to create syslog file!\n"); return fd; } ring_buffer* syslogBuffer = (ring_buffer*)gKernelArgs.debug_output.Pointer(); iovec vecs[2]; int32 vecCount = ring_buffer_get_vecs(syslogBuffer, vecs); if (vecCount > 0) { size_t toWrite = ring_buffer_readable(syslogBuffer); ssize_t written = writev(fd, vecs, vecCount); if (written < 0 || (size_t)written != toWrite) { printf("Failed to write to the syslog file \"%s\"!\n", name); close(fd); return errno; } } close(fd); printf("Successfully wrote syslog file.\n"); return B_OK; }
void read(void* data, size_t length) throw (ring_buffer_concurrency_error_exception, ring_buffer_underflow_exception, ring_buffer_invalid_address_exception) { if (0 != data) { lock_guard lock(this); if (ring_buffer_readable() >= length) { size_t left = length; do { size_t target = _read % capacity, size = std::min(left, capacity - target); memcpy(reinterpret_cast<char*>(data) + length - left, reinterpret_cast<const char*>(buffer) + target, size); left -= size; _read += size; } while (left > 0); if (write_callback.callback and (ring_buffer_writable() >= write_callback.threshold)) write_callback.callback(parent); } else throw ring_buffer_underflow_exception(); } else throw ring_buffer_invalid_address_exception(); }
inline size_t RingBuffer::Readable() const { return fBuffer != NULL ? ring_buffer_readable(fBuffer) : 0; }
virtual size_t BytesAvailable() const { return ring_buffer_readable(fBuffer); }
inline size_t ring_buffer_writable() { return capacity - ring_buffer_readable(); }
void get_available(size_t& read, size_t& write) throw (ring_buffer_concurrency_error_exception) { lock_guard lock(this); read = ring_buffer_readable(); write = ring_buffer_writable(); }
size_t RingBuffer::ReadableAmount() const { return ring_buffer_readable(fBuffer); }
static Menu* add_debug_menu() { Menu* menu = new(std::nothrow) Menu(STANDARD_MENU, "Debug Options"); MenuItem* item; #if DEBUG_SPINLOCK_LATENCIES item = new(std::nothrow) MenuItem("Disable latency checks"); if (item != NULL) { item->SetType(MENU_ITEM_MARKABLE); item->SetData(B_SAFEMODE_DISABLE_LATENCY_CHECK); item->SetHelpText("Disables latency check panics."); menu->AddItem(item); } #endif menu->AddItem(item = new(nothrow) MenuItem("Enable serial debug output")); item->SetData("serial_debug_output"); item->SetType(MENU_ITEM_MARKABLE); item->SetHelpText("Turns on forwarding the syslog output to the serial " "interface (default: 115200, 8N1)."); menu->AddItem(item = new(nothrow) MenuItem("Enable on screen debug output")); item->SetData("debug_screen"); item->SetType(MENU_ITEM_MARKABLE); item->SetHelpText("Displays debug output on screen while the system " "is booting, instead of the normal boot logo."); menu->AddItem(item = new(nothrow) MenuItem("Disable on screen paging")); item->SetData("disable_onscreen_paging"); item->SetType(MENU_ITEM_MARKABLE); item->SetHelpText("Disables paging when on screen debug output is " "enabled."); menu->AddItem(item = new(nothrow) MenuItem("Enable debug syslog")); item->SetType(MENU_ITEM_MARKABLE); item->SetMarked(gKernelArgs.keep_debug_output_buffer); item->SetTarget(&debug_menu_toggle_debug_syslog); item->SetHelpText("Enables a special in-memory syslog buffer for this " "session that the boot loader will be able to access after rebooting."); ring_buffer* syslogBuffer = (ring_buffer*)gKernelArgs.debug_output.Pointer(); bool hasPreviousSyslog = syslogBuffer != NULL && ring_buffer_readable(syslogBuffer) > 0; if (hasPreviousSyslog) { menu->AddItem(item = new(nothrow) MenuItem( "Save syslog from previous session during boot")); item->SetType(MENU_ITEM_MARKABLE); item->SetMarked(gKernelArgs.previous_debug_size); item->SetTarget(&debug_menu_toggle_previous_debug_syslog); item->SetHelpText("Saves the syslog from the previous Haiku session to " "/var/log/previous_syslog when booting."); } bool currentLogItemVisible = platform_debug_get_log_buffer(NULL) != NULL; if (currentLogItemVisible) { menu->AddSeparatorItem(); menu->AddItem(item = new(nothrow) MenuItem("Display current boot loader log")); item->SetTarget(&debug_menu_display_current_log); item->SetType(MENU_ITEM_NO_CHOICE); item->SetHelpText( "Displays the debug info the boot loader has logged."); } if (hasPreviousSyslog) { if (!currentLogItemVisible) menu->AddSeparatorItem(); menu->AddItem(item = new(nothrow) MenuItem("Display syslog from previous session")); item->SetTarget(&debug_menu_display_previous_syslog); item->SetType(MENU_ITEM_NO_CHOICE); item->SetHelpText( "Displays the syslog from the previous Haiku session."); menu->AddItem(item = new(nothrow) MenuItem( "Save syslog from previous session", add_save_debug_syslog_menu())); item->SetHelpText("Saves the syslog from the previous Haiku session to " "disk. Currently only FAT32 volumes are supported."); } menu->AddSeparatorItem(); menu->AddItem(item = new(nothrow) MenuItem( "Add advanced debug option")); item->SetType(MENU_ITEM_NO_CHOICE); item->SetTarget(&debug_menu_add_advanced_option); item->SetHelpText( "Allows advanced debugging options to be entered directly."); menu->AddSeparatorItem(); menu->AddItem(item = new(nothrow) MenuItem("Return to main menu")); return menu; }