Get rid of poll(2), use a blocking thread for network
Finally, network doesn't load CPU on 100%. Ping is below 0.5ms.
This commit is contained in:
parent
d0387f7d53
commit
5b0cf9febc
@ -37,6 +37,7 @@ vnet_reset_tap() {
|
|||||||
COVERAGE_OFF();
|
COVERAGE_OFF();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
static void
|
static void
|
||||||
dump_net_buff(net_buff_t *buf) {
|
dump_net_buff(net_buff_t *buf) {
|
||||||
for (size_t i = 0; i < buf->length; i++) {
|
for (size_t i = 0; i < buf->length; i++) {
|
||||||
@ -44,6 +45,7 @@ dump_net_buff(net_buff_t *buf) {
|
|||||||
}
|
}
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
static STDCALL int
|
static STDCALL int
|
||||||
vnet_transmit_tap(net_buff_t *buf) {
|
vnet_transmit_tap(net_buff_t *buf) {
|
||||||
@ -54,13 +56,14 @@ vnet_transmit_tap(net_buff_t *buf) {
|
|||||||
:
|
:
|
||||||
: "memory");
|
: "memory");
|
||||||
|
|
||||||
printf("vnet_transmit: %d bytes\n", buf->length);
|
// printf("vnet_transmit: %d bytes\n", buf->length);
|
||||||
dump_net_buff(buf);
|
// dump_net_buff(buf);
|
||||||
ssize_t written = write(net->fdout, buf->data, buf->length);
|
ssize_t written = write(net->fdout, buf->data, buf->length);
|
||||||
|
(void)written;
|
||||||
buf->length = 0;
|
buf->length = 0;
|
||||||
COVERAGE_OFF();
|
COVERAGE_OFF();
|
||||||
COVERAGE_ON();
|
COVERAGE_ON();
|
||||||
printf("vnet_transmit: %d bytes written\n", written);
|
// printf("vnet_transmit: %d bytes written\n", written);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +73,7 @@ vnet_init_tap() {
|
|||||||
.ifr_flags = IFF_TAP | IFF_NO_PI};
|
.ifr_flags = IFF_TAP | IFF_NO_PI};
|
||||||
int fd, err;
|
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 );
|
perror("Opening " TAP_DEV );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
16
makefile
16
makefile
@ -25,20 +25,20 @@ else
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
CFLAGS=$(WARNINGS) $(NOWARNINGS) -std=c11 -g -O0 -DNDEBUG -masm=intel \
|
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
|
CFLAGS_32=$(CFLAGS) -m32 -D_FILE_OFFSET_BITS=64 -D__USE_TIME_BITS64
|
||||||
LDFLAGS=-no-pie
|
LDFLAGS=-no-pie
|
||||||
LDFLAGS_32=$(LDFLAGS) -m32
|
LDFLAGS_32=$(LDFLAGS) -m32
|
||||||
|
|
||||||
#ifeq ($(HOST),linux)
|
ifeq ($(HOST),linux)
|
||||||
FASM_INCLUDE=$(KOLIBRIOS)/kernel/trunk;$(KOLIBRIOS)/programs/develop/libraries/libcrash/hash
|
FASM_INCLUDE=$(KOLIBRIOS)/kernel/trunk;$(KOLIBRIOS)/programs/develop/libraries/libcrash/hash
|
||||||
FASM=INCLUDE="$(FASM_INCLUDE)" $(FASM_EXE) $(FASM_FLAGS)
|
FASM=INCLUDE="$(FASM_INCLUDE)" $(FASM_EXE) $(FASM_FLAGS)
|
||||||
#else ifeq ($(HOST),windows)
|
else ifeq ($(HOST),windows)
|
||||||
# FASM_INCLUDE=$(KOLIBRIOS)\kernel\trunk;$(KOLIBRIOS)\programs\develop\libraries\libcrash\hash
|
FASM_INCLUDE=$(KOLIBRIOS)\kernel\trunk;$(KOLIBRIOS)\programs\develop\libraries\libcrash\hash
|
||||||
# FASM=set "INCLUDE=$(FASM_INCLUDE)" && $(FASM_EXE) $(FASM_FLAGS)
|
FASM=set "INCLUDE=$(FASM_INCLUDE)" && $(FASM_EXE) $(FASM_FLAGS)
|
||||||
#else
|
else
|
||||||
# $(error your OS is not supported)
|
$(error your OS is not supported)
|
||||||
#endif
|
endif
|
||||||
|
|
||||||
ifeq ($(HOST),linux)
|
ifeq ($(HOST),linux)
|
||||||
all: umka_shell umka_fuse umka_os umka_gen_devices_dat umka.sym umka.prp \
|
all: umka_shell umka_fuse umka_os umka_gen_devices_dat umka.sym umka.prp \
|
||||||
|
1
umka.h
1
umka.h
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
60
vnet.c
60
vnet.c
@ -12,7 +12,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#define _POSIX // to have SIGSYS on windows
|
#include <pthread.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdatomic.h>
|
#include <stdatomic.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -24,14 +24,10 @@
|
|||||||
#include "vnet/tap.h"
|
#include "vnet/tap.h"
|
||||||
#include "vnet/file.h"
|
#include "vnet/file.h"
|
||||||
|
|
||||||
// TODO: Cleanup
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <poll.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#else
|
#else
|
||||||
#include <winsock2.h>
|
#include <io.h>
|
||||||
#include <pthread.h>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define STACK_SIZE 0x10000
|
#define STACK_SIZE 0x10000
|
||||||
@ -39,48 +35,56 @@
|
|||||||
static int
|
static int
|
||||||
vnet_input(void *udata) {
|
vnet_input(void *udata) {
|
||||||
umka_sti();
|
umka_sti();
|
||||||
struct vnet *vnet = udata;
|
|
||||||
int fd = vnet->fdin;
|
|
||||||
int plen = 0;
|
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);
|
net_buff_t *buf = kos_net_buff_alloc(NET_BUFFER_SIZE);
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
fprintf(stderr, "[vnet] Can't allocate network buffer!\n");
|
fprintf(stderr, "[vnet] Can't allocate network buffer!\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
buf->device = &vnet->eth.net;
|
buf->device = &vnet->eth.net;
|
||||||
|
/*
|
||||||
plen = read(fd, buf->data, NET_BUFFER_SIZE - offsetof(net_buff_t, data));
|
plen = read(fd, buf->data, NET_BUFFER_SIZE - offsetof(net_buff_t, data));
|
||||||
if (plen == -1) {
|
if (plen == -1) {
|
||||||
plen = 0; // we have just allocated a buffer, so we have to submit it
|
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);
|
fprintf(stderr, "[vnet] read %i bytes\n", plen);
|
||||||
for (int i = 0; i < plen; i++) {
|
for (int i = 0; i < plen; i++) {
|
||||||
fprintf(stderr, " %2.2x", buf->data[i]);
|
fprintf(stderr, " %2.2x", buf->data[i]);
|
||||||
}
|
}
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
|
*/
|
||||||
buf->length = plen;
|
buf->length = plen;
|
||||||
buf->offset = offsetof(net_buff_t, data);
|
buf->offset = offsetof(net_buff_t, data);
|
||||||
kos_eth_input(buf);
|
kos_eth_input(buf);
|
||||||
vnet->input_processed = 1;
|
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
|
return 1; // acknowledge our interrupt
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void *
|
||||||
vnet_input_monitor(struct vnet *net) {
|
vnet_input_monitor(void *arg) {
|
||||||
umka_sti();
|
struct vnet *vnet = arg;
|
||||||
struct pollfd pfd = {net->fdin, POLLIN, 0};
|
|
||||||
while (1) {
|
while (1) {
|
||||||
if (net->input_processed && poll(&pfd, 1, 0)) {
|
ssize_t nread = read(vnet->fdin, vnet->bufin, VNET_BUFIN_CAP);
|
||||||
net->input_processed = 0;
|
vnet->input_processed = 0;
|
||||||
atomic_store_explicit(&umka_irq_number, UMKA_IRQ_NETWORK,
|
vnet->bufin_len = nread;
|
||||||
memory_order_release);
|
atomic_store_explicit(&umka_irq_number, UMKA_IRQ_NETWORK,
|
||||||
raise(UMKA_SIGNAL_IRQ);
|
memory_order_release);
|
||||||
umka_sti();
|
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 *
|
struct vnet *
|
||||||
@ -118,14 +122,14 @@ vnet_init(enum vnet_type type) {
|
|||||||
vnet->eth.net.packets_rx_drop = 0;
|
vnet->eth.net.packets_rx_drop = 0;
|
||||||
vnet->eth.net.packets_rx_ovr = 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);
|
kos_attach_int_handler(UMKA_IRQ_NETWORK, vnet_input, vnet);
|
||||||
fprintf(stderr, "[vnet] start input_monitor thread\n");
|
fprintf(stderr, "[vnet] start input_monitor thread\n");
|
||||||
uint8_t *stack = malloc(STACK_SIZE);
|
pthread_t thread_input_monitor;
|
||||||
size_t tid = umka_new_sys_threads(0, vnet_input_monitor, stack + STACK_SIZE);
|
pthread_create(&thread_input_monitor, NULL, vnet_input_monitor, vnet);
|
||||||
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
|
|
||||||
|
|
||||||
return vnet;
|
return vnet;
|
||||||
}
|
}
|
||||||
|
6
vnet.h
6
vnet.h
@ -13,7 +13,7 @@
|
|||||||
#include "umka.h"
|
#include "umka.h"
|
||||||
|
|
||||||
#define UMKA_VNET_NAME "umka%d"
|
#define UMKA_VNET_NAME "umka%d"
|
||||||
|
#define VNET_BUFIN_CAP (NET_BUFFER_SIZE - offsetof(net_buff_t, data))
|
||||||
extern uint32_t umka_irq_number;
|
extern uint32_t umka_irq_number;
|
||||||
|
|
||||||
enum vnet_type {
|
enum vnet_type {
|
||||||
@ -23,6 +23,10 @@ enum vnet_type {
|
|||||||
|
|
||||||
struct vnet {
|
struct vnet {
|
||||||
struct eth_device eth;
|
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 fdin;
|
||||||
int fdout;
|
int fdout;
|
||||||
int input_processed;
|
int input_processed;
|
||||||
|
@ -62,12 +62,12 @@ vnet_init_file() {
|
|||||||
int fdin;
|
int fdin;
|
||||||
int fdout;
|
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");
|
perror("[vnet_file] can't open input file");
|
||||||
return NULL;
|
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");
|
perror("[vnet_file] can't open output file");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user