From 5b0cf9febc9f21b758d9d89b47e5d39726e9fbda Mon Sep 17 00:00:00 2001 From: Ivan Baravy Date: Fri, 3 Feb 2023 02:35:26 +0000 Subject: [PATCH] Get rid of poll(2), use a blocking thread for network Finally, network doesn't load CPU on 100%. Ping is below 0.5ms. --- linux/vnet/tap.c | 11 +++++---- makefile | 16 ++++++------- umka.h | 1 + vnet.c | 60 ++++++++++++++++++++++++++---------------------- vnet.h | 6 ++++- vnet/file.c | 4 ++-- 6 files changed, 55 insertions(+), 43 deletions(-) diff --git a/linux/vnet/tap.c b/linux/vnet/tap.c index ee02d1e..a74a454 100644 --- a/linux/vnet/tap.c +++ b/linux/vnet/tap.c @@ -37,6 +37,7 @@ vnet_reset_tap() { COVERAGE_OFF(); } +/* static void dump_net_buff(net_buff_t *buf) { for (size_t i = 0; i < buf->length; i++) { @@ -44,6 +45,7 @@ dump_net_buff(net_buff_t *buf) { } putchar('\n'); } +*/ static STDCALL int vnet_transmit_tap(net_buff_t *buf) { @@ -54,13 +56,14 @@ vnet_transmit_tap(net_buff_t *buf) { : : "memory"); - printf("vnet_transmit: %d bytes\n", buf->length); - dump_net_buff(buf); +// printf("vnet_transmit: %d bytes\n", buf->length); +// dump_net_buff(buf); ssize_t written = write(net->fdout, buf->data, buf->length); + (void)written; buf->length = 0; COVERAGE_OFF(); COVERAGE_ON(); - printf("vnet_transmit: %d bytes written\n", written); +// printf("vnet_transmit: %d bytes written\n", written); return 0; } @@ -70,7 +73,7 @@ vnet_init_tap() { .ifr_flags = IFF_TAP | IFF_NO_PI}; int fd, err; - if( (fd = open(TAP_DEV, O_RDWR | O_NONBLOCK)) < 0 ) { + if( (fd = open(TAP_DEV, O_RDWR)) < 0 ) { perror("Opening " TAP_DEV ); return NULL; } diff --git a/makefile b/makefile index d1633e4..f4ea037 100644 --- a/makefile +++ b/makefile @@ -25,20 +25,20 @@ else endif CFLAGS=$(WARNINGS) $(NOWARNINGS) -std=c11 -g -O0 -DNDEBUG -masm=intel \ - -D_POSIX_C_SOURCE=200809L -I$(HOST) -I. -fno-pie + -D_POSIX_C_SOURCE=200809L -I$(HOST) -I. -fno-pie -D_POSIX CFLAGS_32=$(CFLAGS) -m32 -D_FILE_OFFSET_BITS=64 -D__USE_TIME_BITS64 LDFLAGS=-no-pie LDFLAGS_32=$(LDFLAGS) -m32 -#ifeq ($(HOST),linux) +ifeq ($(HOST),linux) FASM_INCLUDE=$(KOLIBRIOS)/kernel/trunk;$(KOLIBRIOS)/programs/develop/libraries/libcrash/hash FASM=INCLUDE="$(FASM_INCLUDE)" $(FASM_EXE) $(FASM_FLAGS) -#else ifeq ($(HOST),windows) -# FASM_INCLUDE=$(KOLIBRIOS)\kernel\trunk;$(KOLIBRIOS)\programs\develop\libraries\libcrash\hash -# FASM=set "INCLUDE=$(FASM_INCLUDE)" && $(FASM_EXE) $(FASM_FLAGS) -#else -# $(error your OS is not supported) -#endif +else ifeq ($(HOST),windows) + FASM_INCLUDE=$(KOLIBRIOS)\kernel\trunk;$(KOLIBRIOS)\programs\develop\libraries\libcrash\hash + FASM=set "INCLUDE=$(FASM_INCLUDE)" && $(FASM_EXE) $(FASM_FLAGS) +else + $(error your OS is not supported) +endif ifeq ($(HOST),linux) all: umka_shell umka_fuse umka_os umka_gen_devices_dat umka.sym umka.prp \ diff --git a/umka.h b/umka.h index 339b455..ecfa8ee 100644 --- a/umka.h +++ b/umka.h @@ -12,6 +12,7 @@ #include #include +#include #include #include #include diff --git a/vnet.c b/vnet.c index 5a341e3..9c99260 100644 --- a/vnet.c +++ b/vnet.c @@ -12,7 +12,7 @@ #include #include #include -#define _POSIX // to have SIGSYS on windows +#include #include #include #include @@ -24,14 +24,10 @@ #include "vnet/tap.h" #include "vnet/file.h" -// TODO: Cleanup #ifndef _WIN32 -#include -#include #include #else -#include -#include +#include #endif #define STACK_SIZE 0x10000 @@ -39,48 +35,56 @@ static int vnet_input(void *udata) { umka_sti(); - struct vnet *vnet = udata; - int fd = vnet->fdin; int plen = 0; - fprintf(stderr, "[vnet] input interrupt\n"); + struct vnet *vnet = udata; +// fprintf(stderr, "[vnet] input interrupt\n"); net_buff_t *buf = kos_net_buff_alloc(NET_BUFFER_SIZE); if (!buf) { fprintf(stderr, "[vnet] Can't allocate network buffer!\n"); return 1; } buf->device = &vnet->eth.net; +/* plen = read(fd, buf->data, NET_BUFFER_SIZE - offsetof(net_buff_t, data)); if (plen == -1) { plen = 0; // we have just allocated a buffer, so we have to submit it } - +*/ + plen = vnet->bufin_len; + memcpy(buf->data, vnet->bufin, vnet->bufin_len); +/* fprintf(stderr, "[vnet] read %i bytes\n", plen); for (int i = 0; i < plen; i++) { fprintf(stderr, " %2.2x", buf->data[i]); } fprintf(stderr, "\n"); - +*/ buf->length = plen; buf->offset = offsetof(net_buff_t, data); kos_eth_input(buf); vnet->input_processed = 1; +//fprintf(stderr, "[vnet_input] signal before\n"); +// pthread_cond_signal(&vnet->cond); +//fprintf(stderr, "[vnet_input] signal after\n"); return 1; // acknowledge our interrupt } -static void -vnet_input_monitor(struct vnet *net) { - umka_sti(); - struct pollfd pfd = {net->fdin, POLLIN, 0}; +static void * +vnet_input_monitor(void *arg) { + struct vnet *vnet = arg; while (1) { - if (net->input_processed && poll(&pfd, 1, 0)) { - net->input_processed = 0; - atomic_store_explicit(&umka_irq_number, UMKA_IRQ_NETWORK, - memory_order_release); - raise(UMKA_SIGNAL_IRQ); - umka_sti(); - } + ssize_t nread = read(vnet->fdin, vnet->bufin, VNET_BUFIN_CAP); + vnet->input_processed = 0; + vnet->bufin_len = nread; + atomic_store_explicit(&umka_irq_number, UMKA_IRQ_NETWORK, + memory_order_release); + raise(UMKA_SIGNAL_IRQ); // FIXME: not atomic with the above +//fprintf(stderr, "[vnet_input_monitor] wait for signal\n"); +// pthread_cond_wait(&vnet->cond, &vnet->mutex); // TODO: handle spurious +//fprintf(stderr, "[vnet_input_monitor] got signal\n"); } + return NULL; } struct vnet * @@ -118,14 +122,14 @@ vnet_init(enum vnet_type type) { vnet->eth.net.packets_rx_drop = 0; vnet->eth.net.packets_rx_ovr = 0; +// pthread_cond_init(&vnet->cond, NULL); +// pthread_mutex_init(&vnet->mutex, NULL); +// pthread_mutex_lock(&vnet->mutex); + kos_attach_int_handler(UMKA_IRQ_NETWORK, vnet_input, vnet); fprintf(stderr, "[vnet] start input_monitor thread\n"); - uint8_t *stack = malloc(STACK_SIZE); - size_t tid = umka_new_sys_threads(0, vnet_input_monitor, stack + STACK_SIZE); - appdata_t *t = kos_slot_base + tid; - *(void**)((uint8_t*)t->saved_esp0-12) = vnet; // param for monitor thread - // -12 here because in UMKa, unlike real hardware, we don't switch between - // kernel and userspace, i.e. stack structure is different + pthread_t thread_input_monitor; + pthread_create(&thread_input_monitor, NULL, vnet_input_monitor, vnet); return vnet; } diff --git a/vnet.h b/vnet.h index 774d72a..0162c3e 100644 --- a/vnet.h +++ b/vnet.h @@ -13,7 +13,7 @@ #include "umka.h" #define UMKA_VNET_NAME "umka%d" - +#define VNET_BUFIN_CAP (NET_BUFFER_SIZE - offsetof(net_buff_t, data)) extern uint32_t umka_irq_number; enum vnet_type { @@ -23,6 +23,10 @@ enum vnet_type { struct vnet { struct eth_device eth; + uint8_t bufin[VNET_BUFIN_CAP]; + size_t bufin_len; +// pthread_cond_t cond; +// pthread_mutex_t mutex; int fdin; int fdout; int input_processed; diff --git a/vnet/file.c b/vnet/file.c index 635df84..07818d3 100644 --- a/vnet/file.c +++ b/vnet/file.c @@ -62,12 +62,12 @@ vnet_init_file() { int fdin; int fdout; - if( (fdin = open("/path/to/fdin", O_RDONLY | O_NONBLOCK)) < 0 ) { + if( (fdin = open("/path/to/fdin", O_RDONLY)) < 0 ) { perror("[vnet_file] can't open input file"); return NULL; } - if( (fdout = open("/path/to/fdin", O_WRONLY | O_NONBLOCK)) < 0 ) { + if( (fdout = open("/path/to/fdin", O_WRONLY)) < 0 ) { perror("[vnet_file] can't open output file"); return NULL; }