diff --git a/src/libraries/j6/channel.cpp b/src/libraries/j6/channel.cpp index 81e6300..3896eb7 100644 --- a/src/libraries/j6/channel.cpp +++ b/src/libraries/j6/channel.cpp @@ -125,8 +125,10 @@ channel::receive(void *buffer, size_t *size, bool block) { j6::scoped_lock lock {m_header->mutex}; while (!m_header->read_avail()) { - if (!block) + if (!block) { + *size = 0; return j6_status_would_block; + } lock.release(); m_header->read_waiting.wait(); diff --git a/src/libraries/j6/include/j6/ring_buffer.hh b/src/libraries/j6/include/j6/ring_buffer.hh new file mode 100644 index 0000000..69c01e0 --- /dev/null +++ b/src/libraries/j6/include/j6/ring_buffer.hh @@ -0,0 +1,55 @@ +#pragma once +/// \file j6/ring_buffer.hh +/// Helper class for managing ring buffers in doubly-mapped VMAs + +// The kernel depends on libj6 for some shared code, +// but should not include the user-specific code. +#ifndef __j6kernel +#include +#include +#include + +namespace j6 { + +API class ring_buffer +{ +public: + ring_buffer(size_t pages); + + inline bool valid() const { return m_data != nullptr; } + inline size_t size() const { return 1< free()) n = free(); + m_write += n; + } + + inline const char * consume(size_t &n) { + if (n > used()) n = used(); + size_t i = m_read; + m_read += n; + return get(i); + } + +private: + inline size_t mask() const { return (1< +#include +#include +#include +#include +#include +#include + +namespace j6 { + +API +ring_buffer::ring_buffer(size_t pages) : + m_bits {util::log2(pages) + arch::frame_bits}, + m_write {0}, + m_read {0}, + m_vma {j6_handle_invalid}, + m_data {nullptr} +{ + // Must be a power of 2 + if (!util::is_pow2(pages)) + return; + + uintptr_t buffer_addr = 0; + size_t size = 1<(buffer_addr); +} + +} // namespace j6 + +#endif // __j6kernel diff --git a/src/user/drv.uart/main.cpp b/src/user/drv.uart/main.cpp index 7db6263..b6987a5 100644 --- a/src/user/drv.uart/main.cpp +++ b/src/user/drv.uart/main.cpp @@ -2,12 +2,14 @@ #include #include +#include #include #include #include #include #include #include +#include #include #include #include @@ -64,8 +66,10 @@ main(int argc, const char **argv) serial_port com1 {COM1, in_buf_size, com1_in, out_buf_size, com1_out}; serial_port com2 {COM2, in_buf_size, com2_in, out_buf_size, com2_out}; - static constexpr size_t buffer_size = 512; - char buffer[buffer_size]; + static constexpr size_t buffer_pages = 1; + j6::ring_buffer buffer {buffer_pages}; + if (!buffer.valid()) + return 128; j6_handle_t slp = j6_find_init_handle(j6::proto::sl::id); if (slp == j6_handle_invalid) @@ -87,17 +91,13 @@ main(int argc, const char **argv) return 6; while (true) { - size_t size = buffer_size; - while (true) { - result = cout->receive(buffer, &size, 0); - if (result != j6_status_ok) - break; + size_t size = buffer.free(); + cout->receive(buffer.write_ptr(), &size, 0); + buffer.commit(size); + //j6::syslog(j6::logs::srv, j6::log_level::spam, "uart driver: got %d bytes from channel", size); - j6::syslog(j6::logs::srv, j6::log_level::spam, "uart driver: got %d bytes from channel", size); - com1.write(buffer, size); - } - if (result != j6_status_would_block) - j6::syslog(j6::logs::srv, j6::log_level::error, "uart driver: error %lx receiving from channel", result); + size = com1.write(buffer.read_ptr(), buffer.used()); + buffer.consume(size); uint64_t signals = 0; result = j6_event_wait(event, &signals, 500); @@ -110,7 +110,7 @@ main(int argc, const char **argv) j6::syslog(j6::logs::srv, j6::log_level::error, "uart driver: error %lx waiting for irq", result); continue; } else { - j6::syslog(j6::logs::srv, j6::log_level::verbose, "uart driver: irq signals: %lx", signals); + j6::syslog(j6::logs::srv, j6::log_level::spam, "uart driver: irq signals: %lx", signals); } if (signals & (1<<0)) @@ -121,5 +121,4 @@ main(int argc, const char **argv) j6::syslog(j6::logs::srv, j6::log_level::error, "uart driver somehow got to the end of main"); return 0; -} - +} \ No newline at end of file