From 9767c4db0ed9dd6fe96bc784db4e210875a96fd3 Mon Sep 17 00:00:00 2001 From: Sebastian Sumpf Date: Fri, 6 Dec 2019 14:12:04 +0100 Subject: [PATCH] vfs_lwip/lwip: Lwip::lock for concurrent access This is required in case the send and receive of IP packets is performed by multiple thread because lwip is not thread safe. issue #3568 --- repos/libports/include/lwip/genode_init.h | 6 ++++- repos/libports/include/lwip/nic_netif.h | 2 ++ .../src/lib/lwip/platform/sys_arch.cc | 13 ++++++++-- repos/libports/src/lib/vfs/lwip/vfs.cc | 25 ++++++++++--------- 4 files changed, 31 insertions(+), 15 deletions(-) diff --git a/repos/libports/include/lwip/genode_init.h b/repos/libports/include/lwip/genode_init.h index 531c6ac3e..e315e9f43 100644 --- a/repos/libports/include/lwip/genode_init.h +++ b/repos/libports/include/lwip/genode_init.h @@ -17,6 +17,10 @@ #include #include -namespace Lwip { void genode_init(Genode::Allocator &heap, Genode::Timeout_scheduler &timer); } +namespace Lwip { + void genode_init(Genode::Allocator &heap, Genode::Timeout_scheduler &timer); + + Genode::Lock &lock(); +} #endif diff --git a/repos/libports/include/lwip/nic_netif.h b/repos/libports/include/lwip/nic_netif.h index 2ee932bfc..b6579bbfd 100644 --- a/repos/libports/include/lwip/nic_netif.h +++ b/repos/libports/include/lwip/nic_netif.h @@ -26,6 +26,7 @@ #endif /* Genode includes */ +#include #include #include #include @@ -140,6 +141,7 @@ class Lwip::Nic_netif void handle_rx_packets() { + Genode::Lock::Guard g { Lwip::lock() }; auto &rx = *_nic.rx(); while (rx.packet_avail() && rx.ready_to_ack()) { diff --git a/repos/libports/src/lib/lwip/platform/sys_arch.cc b/repos/libports/src/lib/lwip/platform/sys_arch.cc index c3b7087f3..2963b1480 100644 --- a/repos/libports/src/lib/lwip/platform/sys_arch.cc +++ b/repos/libports/src/lib/lwip/platform/sys_arch.cc @@ -36,8 +36,11 @@ namespace Lwip { struct Sys_timer { - void check_timeouts(Genode::Duration) { - sys_check_timeouts(); } + void check_timeouts(Genode::Duration) + { + Genode::Lock::Guard g{ Lwip::lock() }; + sys_check_timeouts(); + } Genode::Timeout_scheduler &timer; @@ -62,6 +65,12 @@ namespace Lwip { lwip_init(); } + + Genode::Lock &lock() + { + static Genode::Lock _lwip_lock; + return _lwip_lock; + } } diff --git a/repos/libports/src/lib/vfs/lwip/vfs.cc b/repos/libports/src/lib/vfs/lwip/vfs.cc index 51df283c9..86ab57f01 100644 --- a/repos/libports/src/lib/vfs/lwip/vfs.cc +++ b/repos/libports/src/lib/vfs/lwip/vfs.cc @@ -898,6 +898,7 @@ class Lwip::Udp_socket_dir final : char *dst, file_size count, file_size &out_count) override { + Genode::Lock::Guard g { Lwip::lock() }; Read_result result = Read_result::READ_ERR_INVALID; switch(handle.kind) { @@ -983,6 +984,8 @@ class Lwip::Udp_socket_dir final : char const *src, file_size count, file_size &out_count) override { + Genode::Lock::Guard g { Lwip::lock() }; + switch(handle.kind) { case Lwip_file_handle::DATA: { @@ -1287,6 +1290,8 @@ class Lwip::Tcp_socket_dir final : char *dst, file_size count, file_size &out_count) override { + Genode::Lock::Guard g { Lwip::lock() }; + switch(handle.kind) { case Lwip_file_handle::DATA: @@ -1371,7 +1376,11 @@ class Lwip::Tcp_socket_dir final : handle.kind = Lwip_file_handle::LOCATION; /* read the location of the new socket directory */ - return handle.read(dst, count, out_count); + Lwip::lock().unlock(); + Read_result result = handle.read(dst, count, out_count); + Lwip::lock().lock(); + + return result; } return Read_result::READ_QUEUED; @@ -1433,6 +1442,7 @@ class Lwip::Tcp_socket_dir final : char const *src, file_size count, file_size &out_count) override { + Genode::Lock::Guard g { Lwip::lock() }; if (_pcb == NULL) { /* socket is closed */ return Write_result::WRITE_ERR_IO; @@ -1958,17 +1968,8 @@ class Lwip::File_system final : public Vfs::File_system, public Lwip::Directory if ((vfs_handle->status_flags() & OPEN_MODE_ACCMODE) == OPEN_MODE_RDONLY) return Write_result::WRITE_ERR_INVALID; if (Lwip_handle *handle = dynamic_cast(vfs_handle)) { - while (true) { - res = handle->write(src, count, out_count); - if (res != WRITE_ERR_WOULD_BLOCK || out_count) break; - - /* - * XXX: block for signals until the write completes - * or fails, this is not how it should be done, but - * it's how lxip does it - */ - _ep.wait_and_dispatch_one_io_signal(); - } + res = handle->write(src, count, out_count); + if (res == WRITE_ERR_WOULD_BLOCK) throw Insufficient_buffer(); } return res; }