mirror of
https://github.com/justinian/jsix.git
synced 2025-12-10 00:14:32 -08:00
[uart] Make UART driver single-threaded
The design of the UART driver was needlessly multi-threaded and a source of threading bugs. Just make it single-threaded.
This commit is contained in:
@@ -10,7 +10,6 @@
|
|||||||
#include <j6/protocols/service_locator.h>
|
#include <j6/protocols/service_locator.h>
|
||||||
#include <j6/syscalls.h>
|
#include <j6/syscalls.h>
|
||||||
#include <j6/sysconf.h>
|
#include <j6/sysconf.h>
|
||||||
#include <j6/thread.hh>
|
|
||||||
#include <j6/types.h>
|
#include <j6/types.h>
|
||||||
#include <util/hash.h>
|
#include <util/hash.h>
|
||||||
|
|
||||||
@@ -21,7 +20,6 @@ extern "C" {
|
|||||||
int main(int, const char **);
|
int main(int, const char **);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern j6_handle_t __handle_self;
|
|
||||||
j6_handle_t g_handle_sys = j6_handle_invalid;
|
j6_handle_t g_handle_sys = j6_handle_invalid;
|
||||||
|
|
||||||
constexpr size_t in_buf_size = 512;
|
constexpr size_t in_buf_size = 512;
|
||||||
@@ -35,9 +33,36 @@ uint8_t com2_out[out_buf_size];
|
|||||||
constexpr uintptr_t stack_top = 0xf80000000;
|
constexpr uintptr_t stack_top = 0xf80000000;
|
||||||
|
|
||||||
int
|
int
|
||||||
channel_pump_loop(serial_port *com1)
|
main(int argc, const char **argv)
|
||||||
{
|
{
|
||||||
j6_status_t result;
|
j6_log("uart driver starting");
|
||||||
|
|
||||||
|
j6_handle_t event = j6_handle_invalid;
|
||||||
|
j6_status_t result = j6_status_ok;
|
||||||
|
|
||||||
|
g_handle_sys = j6_find_first_handle(j6_object_type_system);
|
||||||
|
if (g_handle_sys == j6_handle_invalid)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
result = j6_system_request_iopl(g_handle_sys, 3);
|
||||||
|
if (result != j6_status_ok)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
result = j6_event_create(&event);
|
||||||
|
if (result != j6_status_ok)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
result = j6_system_bind_irq(g_handle_sys, event, 3, 0);
|
||||||
|
if (result != j6_status_ok)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
result = j6_system_bind_irq(g_handle_sys, event, 4, 1);
|
||||||
|
if (result != j6_status_ok)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
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;
|
static constexpr size_t buffer_size = 512;
|
||||||
char buffer[buffer_size];
|
char buffer[buffer_size];
|
||||||
|
|
||||||
@@ -71,57 +96,10 @@ channel_pump_loop(serial_port *com1)
|
|||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
size_t size = buffer_size;
|
size_t size = buffer_size;
|
||||||
j6_status_t s = j6_channel_receive(cout, buffer, &size, j6_channel_block);
|
result = j6_channel_receive(cout, buffer, &size, 0);
|
||||||
if (s == j6_status_ok)
|
if (result == j6_status_ok)
|
||||||
com1->write(buffer, size);
|
com1.write(buffer, size);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
pump_proc(void *com_ptr)
|
|
||||||
{
|
|
||||||
serial_port *com1 = reinterpret_cast<serial_port*>(com_ptr);
|
|
||||||
j6_process_exit(channel_pump_loop(com1));
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, const char **argv)
|
|
||||||
{
|
|
||||||
j6_log("uart driver starting");
|
|
||||||
|
|
||||||
j6_handle_t event = j6_handle_invalid;
|
|
||||||
j6_status_t result = j6_status_ok;
|
|
||||||
|
|
||||||
g_handle_sys = j6_find_first_handle(j6_object_type_system);
|
|
||||||
if (g_handle_sys == j6_handle_invalid)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
result = j6_system_request_iopl(g_handle_sys, 3);
|
|
||||||
if (result != j6_status_ok)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
result = j6_event_create(&event);
|
|
||||||
if (result != j6_status_ok)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
result = j6_system_bind_irq(g_handle_sys, event, 3, 0);
|
|
||||||
if (result != j6_status_ok)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
result = j6_system_bind_irq(g_handle_sys, event, 4, 1);
|
|
||||||
if (result != j6_status_ok)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
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};
|
|
||||||
|
|
||||||
j6::thread pump_thread {pump_proc, stack_top};
|
|
||||||
result = pump_thread.start(&com1);
|
|
||||||
if (result != j6_status_ok)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
size_t len = 0;
|
|
||||||
while (true) {
|
|
||||||
uint64_t signals = 0;
|
uint64_t signals = 0;
|
||||||
result = j6_event_wait(event, &signals, 100);
|
result = j6_event_wait(event, &signals, 100);
|
||||||
if (result == j6_err_timed_out) {
|
if (result == j6_err_timed_out) {
|
||||||
|
|||||||
@@ -91,9 +91,7 @@ serial_port::do_write()
|
|||||||
{
|
{
|
||||||
// If another thread is writing data, just give up and
|
// If another thread is writing data, just give up and
|
||||||
// try again later
|
// try again later
|
||||||
util::scoped_trylock lock {m_lock};
|
util::scoped_lock lock {m_lock};
|
||||||
if (!lock.locked())
|
|
||||||
return;
|
|
||||||
|
|
||||||
uint8_t *data = nullptr;
|
uint8_t *data = nullptr;
|
||||||
size_t n = m_out_buffer.get_block(reinterpret_cast<void**>(&data));
|
size_t n = m_out_buffer.get_block(reinterpret_cast<void**>(&data));
|
||||||
|
|||||||
Reference in New Issue
Block a user