mirror of
https://github.com/hermitcore/libhermit.git
synced 2025-03-09 00:00:03 +01:00
increase the interoperability between LwIP and newlib
- create own socket functions for newlib - exchange error numbers between newlib and LwIP - add LWIP_FD_BIT to mark a file descriptor as LwIP file descriptor - add netio example
This commit is contained in:
parent
e53c126bf3
commit
f9058f51e5
12 changed files with 666 additions and 88 deletions
|
@ -41,7 +41,7 @@ RM = rm -rf
|
|||
|
||||
CFLAGS_FOR_NEWLIB = -m64 -mtls-direct-seg-refs -mno-red-zone -O3 -mavx2 -mfma -mtune=intel $(STACKPROT)
|
||||
FFLAGS_FOR_NEWLIB = -m64 -mtls-direct-seg-refs -mno-red-zone -O3 -mavx2 -mfma -mtune=intel
|
||||
CXXFLAGS_FOR_NEWLIB = $(CFLAGS_FOR_NEWLIB)
|
||||
CXXFLAGS_FOR_NEWLIB =
|
||||
LDFLAGS_FOR_NEWLIB =
|
||||
NASMFLAGS_FOR_NEWLIB = -felf64
|
||||
CFLAGS_FOR_TOOLS = -O2 -Wall
|
||||
|
|
|
@ -59,7 +59,6 @@ static inline void enter_user_task(size_t ep, size_t stack)
|
|||
|
||||
static int thread_entry(void* arg, size_t ep)
|
||||
{
|
||||
task_t* curr_task = per_core(current_task);
|
||||
#if 0
|
||||
size_t addr, stack = 0;
|
||||
size_t flags;
|
||||
|
@ -95,21 +94,11 @@ static int thread_entry(void* arg, size_t ep)
|
|||
vma_add(stack, stack+npages*PAGE_SIZE-1, flags);
|
||||
#endif
|
||||
|
||||
if (init_tls())
|
||||
return -ENOMEM;
|
||||
|
||||
//vma_dump();
|
||||
|
||||
// do we have to create a TLS segement?
|
||||
if (curr_task->tls_addr && curr_task->tls_size) {
|
||||
char* tls_addr = NULL;
|
||||
|
||||
tls_addr = kmalloc(curr_task->tls_size);
|
||||
// copy default TLS segment to stack
|
||||
memcpy((void*) (tls_addr), (void*) curr_task->tls_addr, curr_task->tls_size);
|
||||
|
||||
// set fs register to the TLS segment
|
||||
writefs((size_t) tls_addr);
|
||||
kprintf("Task %d set fs to %p\n", curr_task->id, tls_addr);
|
||||
} else writefs(0); // no TLS => clear fs register
|
||||
|
||||
// set first argument
|
||||
//asm volatile ("mov %0, %%rdi" :: "r"(arg));
|
||||
//enter_user_task(ep, stack+offset);
|
||||
|
|
|
@ -137,10 +137,19 @@ int create_kernel_task_on_core(tid_t* id, entry_point_t ep, void* args, uint8_t
|
|||
*
|
||||
* @return
|
||||
* - 0 on success
|
||||
* - -EINVAL (-22) or -ENOMEM (-12)on failure
|
||||
* - -EINVAL (-22) or -ENOMEM (-12) on failure
|
||||
*/
|
||||
int create_user_task_on_core(tid_t* id, const char* fame, char** argv, uint8_t prio, uint32_t core_id);
|
||||
|
||||
|
||||
/** @brief Create a thread local storage for the current task
|
||||
*
|
||||
* @return
|
||||
* - 0 on success
|
||||
* - -EONMEM on failure
|
||||
*/
|
||||
int init_tls(void);
|
||||
|
||||
/** @brief Cleanup function for the task termination
|
||||
*
|
||||
* On termination, the task call this function to cleanup its address space.
|
||||
|
|
|
@ -54,12 +54,11 @@
|
|||
#include <netif/etharp.h>
|
||||
#include <net/mmnif.h>
|
||||
|
||||
#define HERMIT_PORT 0x494F
|
||||
#define HERMIT_PORT 0x494E
|
||||
#define HEMRIT_MAGIC 0x7E317
|
||||
|
||||
static struct netif mmnif_netif;
|
||||
static const int sobufsize = 131072;
|
||||
volatile int8_t shutdown = 0;
|
||||
|
||||
/*
|
||||
* Note that linker symbols are not variables, they have no memory allocated for
|
||||
|
@ -193,7 +192,7 @@ int network_shutdown(void)
|
|||
kputs("Shutdown LwIP\n");
|
||||
|
||||
if (libc_sd > 0)
|
||||
closesocket(libc_sd);
|
||||
lwip_close(libc_sd);
|
||||
|
||||
mmnif_shutdown();
|
||||
netifapi_netif_set_down(&mmnif_netif);
|
||||
|
@ -281,33 +280,13 @@ static int initd(void* arg)
|
|||
//create_kernel_task(NULL, foo, "foo1", NORMAL_PRIO);
|
||||
//create_kernel_task(NULL, foo, "foo2", NORMAL_PRIO);
|
||||
|
||||
// initialize network
|
||||
init_netifs();
|
||||
|
||||
// do we have a thread local storage?
|
||||
if (((size_t) &tls_end - (size_t) &tls_start) > 0) {
|
||||
char* tls_addr = NULL;
|
||||
|
||||
curr_task->tls_addr = (size_t) &tls_start;
|
||||
curr_task->tls_size = (size_t) &tls_end - (size_t) &tls_start;
|
||||
|
||||
// TODO: free TLS after termination
|
||||
tls_addr = kmalloc(curr_task->tls_size);
|
||||
if (BUILTIN_EXPECT(!tls_addr, 0)) {
|
||||
kprintf("load_task: heap is missing!\n");
|
||||
kfree(curr_task->heap);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memcpy((void*) tls_addr, (void*) curr_task->tls_addr, curr_task->tls_size);
|
||||
|
||||
// set fs register to the TLS segment
|
||||
set_tls((size_t) tls_addr);
|
||||
kprintf("Task %d set fs to 0x%zx\n", curr_task->id, tls_addr);
|
||||
} else set_tls(0); // no TLS => clear fs register
|
||||
|
||||
// initialize iRCCE
|
||||
//init_rcce();
|
||||
|
||||
s = socket(PF_INET , SOCK_STREAM , 0);
|
||||
s = lwip_socket(PF_INET , SOCK_STREAM , 0);
|
||||
if (s < 0) {
|
||||
kprintf("socket failed: %d\n", server);
|
||||
return -1;
|
||||
|
@ -319,17 +298,17 @@ static int initd(void* arg)
|
|||
server.sin_addr.s_addr = INADDR_ANY;
|
||||
server.sin_port = htons(HERMIT_PORT);
|
||||
|
||||
if ((err = bind(s, (struct sockaddr *) &server, sizeof(server))) < 0)
|
||||
if ((err = lwip_bind(s, (struct sockaddr *) &server, sizeof(server))) < 0)
|
||||
{
|
||||
kprintf("bind failed: %d\n", errno);
|
||||
closesocket(s);
|
||||
lwip_close(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((err = listen(s, 2)) < 0)
|
||||
if ((err = lwip_listen(s, 2)) < 0)
|
||||
{
|
||||
kprintf("listen failed: %d\n", errno);
|
||||
closesocket(s);
|
||||
lwip_close(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -337,28 +316,28 @@ static int initd(void* arg)
|
|||
|
||||
kputs("TCP server listening.\n");
|
||||
|
||||
if ((c = accept(s, (struct sockaddr *)&client, (socklen_t*)&len)) < 0)
|
||||
if ((c = lwip_accept(s, (struct sockaddr *)&client, (socklen_t*)&len)) < 0)
|
||||
{
|
||||
kprintf("accept faild: %d\n", errno);
|
||||
closesocket(s);
|
||||
lwip_close(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
kputs("Establish IP connection\n");
|
||||
|
||||
setsockopt(c, SOL_SOCKET, SO_RCVBUF, (char *) &sobufsize, sizeof(sobufsize));
|
||||
setsockopt(c, SOL_SOCKET, SO_SNDBUF, (char *) &sobufsize, sizeof(sobufsize));
|
||||
setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(flag));
|
||||
lwip_setsockopt(c, SOL_SOCKET, SO_RCVBUF, (char *) &sobufsize, sizeof(sobufsize));
|
||||
lwip_setsockopt(c, SOL_SOCKET, SO_SNDBUF, (char *) &sobufsize, sizeof(sobufsize));
|
||||
lwip_setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(flag));
|
||||
|
||||
read(c, &magic, sizeof(magic));
|
||||
lwip_read(c, &magic, sizeof(magic));
|
||||
if (magic != HEMRIT_MAGIC)
|
||||
{
|
||||
kprintf("Invalid magic number %d\n", magic);
|
||||
closesocket(c);
|
||||
lwip_close(c);
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = read(c, &argc, sizeof(argc));
|
||||
err = lwip_read(c, &argc, sizeof(argc));
|
||||
if (err != sizeof(argc))
|
||||
goto out;
|
||||
|
||||
|
@ -369,7 +348,7 @@ static int initd(void* arg)
|
|||
|
||||
for(i=0; i<argc; i++)
|
||||
{
|
||||
err = read(c, &len, sizeof(len));
|
||||
err = lwip_read(c, &len, sizeof(len));
|
||||
if (err != sizeof(len))
|
||||
goto out;
|
||||
|
||||
|
@ -379,7 +358,7 @@ static int initd(void* arg)
|
|||
|
||||
j = 0;
|
||||
while(j < len) {
|
||||
err = read(c, argv[i]+j, len-j);
|
||||
err = lwip_read(c, argv[i]+j, len-j);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
j += err;
|
||||
|
@ -387,7 +366,7 @@ static int initd(void* arg)
|
|||
|
||||
}
|
||||
|
||||
err = read(c, &envc, sizeof(envc));
|
||||
err = lwip_read(c, &envc, sizeof(envc));
|
||||
if (err != sizeof(envc))
|
||||
goto out;
|
||||
|
||||
|
@ -398,7 +377,7 @@ static int initd(void* arg)
|
|||
|
||||
for(i=0; i<envc; i++)
|
||||
{
|
||||
err = read(c, &len, sizeof(len));
|
||||
err = lwip_read(c, &len, sizeof(len));
|
||||
if (err != sizeof(len))
|
||||
goto out;
|
||||
|
||||
|
@ -408,7 +387,7 @@ static int initd(void* arg)
|
|||
|
||||
j = 0;
|
||||
while(j < len) {
|
||||
err = read(c, environ[i]+j, len-j);
|
||||
err = lwip_read(c, environ[i]+j, len-j);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
j += err;
|
||||
|
@ -440,11 +419,11 @@ out:
|
|||
}
|
||||
|
||||
if (c > 0)
|
||||
closesocket(c);
|
||||
lwip_close(c);
|
||||
libc_sd = -1;
|
||||
|
||||
if (s > 0)
|
||||
closesocket(s);
|
||||
lwip_close(s);
|
||||
|
||||
//network_shutdown();
|
||||
|
||||
|
|
|
@ -47,6 +47,15 @@ extern int32_t isle;
|
|||
extern int32_t possible_isles;
|
||||
extern int libc_sd;
|
||||
|
||||
|
||||
int* __getreent(void);
|
||||
|
||||
static inline int* libc_errno(void)
|
||||
{
|
||||
|
||||
return __getreent();
|
||||
}
|
||||
|
||||
tid_t sys_getpid(void)
|
||||
{
|
||||
task_t* task = per_core(current_task);
|
||||
|
@ -83,10 +92,10 @@ void NORETURN sys_exit(int arg)
|
|||
if (libc_sd >= 0)
|
||||
{
|
||||
spinlock_lock(&lwip_lock);
|
||||
write(libc_sd, &sysargs, sizeof(sysargs));
|
||||
lwip_write(libc_sd, &sysargs, sizeof(sysargs));
|
||||
spinlock_unlock(&lwip_lock);
|
||||
|
||||
closesocket(libc_sd);
|
||||
lwip_close(libc_sd);
|
||||
libc_sd = -1;
|
||||
}
|
||||
|
||||
|
@ -104,20 +113,32 @@ ssize_t sys_read(int fd, char* buf, size_t len)
|
|||
sys_read_t sysargs = {__NR_read, fd, len};
|
||||
ssize_t j, ret;
|
||||
|
||||
// do we have an LwIP file descriptor?
|
||||
if (fd & LWIP_FD_BIT) {
|
||||
ret = lwip_read(fd & ~LWIP_FD_BIT, buf, len);
|
||||
if (ret)
|
||||
{
|
||||
*libc_errno() = errno;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (libc_sd < 0)
|
||||
return -ENOSYS;
|
||||
|
||||
spinlock_lock(&lwip_lock);
|
||||
write(libc_sd, &sysargs, sizeof(sysargs));
|
||||
lwip_write(libc_sd, &sysargs, sizeof(sysargs));
|
||||
|
||||
read(libc_sd, &j, sizeof(j));
|
||||
lwip_read(libc_sd, &j, sizeof(j));
|
||||
if (j > 0)
|
||||
{
|
||||
ssize_t i = 0;
|
||||
|
||||
while(i < j)
|
||||
{
|
||||
ret = read(libc_sd, buf+i, j-i);
|
||||
ret = lwip_read(libc_sd, buf+i, j-i);
|
||||
if (ret < 0) {
|
||||
spinlock_unlock(&lwip_lock);
|
||||
return ret;
|
||||
|
@ -147,6 +168,18 @@ ssize_t sys_write(int fd, const char* buf, size_t len)
|
|||
if (BUILTIN_EXPECT(!buf, 0))
|
||||
return -1;
|
||||
|
||||
// do we have an LwIP file descriptor?
|
||||
if (fd & LWIP_FD_BIT) {
|
||||
ret = lwip_write(fd & ~LWIP_FD_BIT, buf, len);
|
||||
if (ret)
|
||||
{
|
||||
*libc_errno() = errno;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (libc_sd < 0)
|
||||
{
|
||||
for(i=0; i<len; i++)
|
||||
|
@ -158,14 +191,14 @@ ssize_t sys_write(int fd, const char* buf, size_t len)
|
|||
spinlock_lock(&lwip_lock);
|
||||
|
||||
flag = 0;
|
||||
setsockopt(libc_sd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(flag));
|
||||
lwip_setsockopt(libc_sd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(flag));
|
||||
|
||||
write(libc_sd, &sysargs, sizeof(sysargs));
|
||||
lwip_write(libc_sd, &sysargs, sizeof(sysargs));
|
||||
|
||||
i=0;
|
||||
while(i < len)
|
||||
{
|
||||
ret = write(libc_sd, (char*)buf+i, len-i);
|
||||
ret = lwip_write(libc_sd, (char*)buf+i, len-i);
|
||||
if (ret < 0) {
|
||||
spinlock_unlock(&lwip_lock);
|
||||
return ret;
|
||||
|
@ -175,10 +208,10 @@ ssize_t sys_write(int fd, const char* buf, size_t len)
|
|||
}
|
||||
|
||||
flag = 1;
|
||||
setsockopt(libc_sd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(flag));
|
||||
lwip_setsockopt(libc_sd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(flag));
|
||||
|
||||
if (fd > 2) {
|
||||
ret = read(libc_sd, &i, sizeof(i));
|
||||
ret = lwip_read(libc_sd, &i, sizeof(i));
|
||||
if (ret < 0)
|
||||
i = ret;
|
||||
} else i = len;
|
||||
|
@ -227,37 +260,37 @@ int sys_open(const char* name, int flags, int mode)
|
|||
spinlock_lock(&lwip_lock);
|
||||
|
||||
i = 0;
|
||||
setsockopt(libc_sd, IPPROTO_TCP, TCP_NODELAY, (char *) &i, sizeof(i));
|
||||
lwip_setsockopt(libc_sd, IPPROTO_TCP, TCP_NODELAY, (char *) &i, sizeof(i));
|
||||
|
||||
ret = write(libc_sd, &sysnr, sizeof(sysnr));
|
||||
ret = lwip_write(libc_sd, &sysnr, sizeof(sysnr));
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = write(libc_sd, &len, sizeof(len));
|
||||
ret = lwip_write(libc_sd, &len, sizeof(len));
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
i=0;
|
||||
while(i<len)
|
||||
{
|
||||
ret = write(libc_sd, name+i, len-i);
|
||||
ret = lwip_write(libc_sd, name+i, len-i);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
i += ret;
|
||||
}
|
||||
|
||||
ret = write(libc_sd, &flags, sizeof(flags));
|
||||
ret = lwip_write(libc_sd, &flags, sizeof(flags));
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = write(libc_sd, &mode, sizeof(mode));
|
||||
ret = lwip_write(libc_sd, &mode, sizeof(mode));
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
i = 1;
|
||||
setsockopt(libc_sd, IPPROTO_TCP, TCP_NODELAY, (char *) &i, sizeof(i));
|
||||
lwip_setsockopt(libc_sd, IPPROTO_TCP, TCP_NODELAY, (char *) &i, sizeof(i));
|
||||
|
||||
read(libc_sd, &ret, sizeof(ret));
|
||||
lwip_read(libc_sd, &ret, sizeof(ret));
|
||||
|
||||
out:
|
||||
spinlock_unlock(&lwip_lock);
|
||||
|
@ -275,15 +308,27 @@ int sys_close(int fd)
|
|||
int ret;
|
||||
sys_close_t sysargs = {__NR_close, fd};
|
||||
|
||||
// do we have an LwIP file descriptor?
|
||||
if (fd & LWIP_FD_BIT) {
|
||||
ret = lwip_close(fd & ~LWIP_FD_BIT);
|
||||
if (ret)
|
||||
{
|
||||
*libc_errno() = errno;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (libc_sd < 0)
|
||||
return 0;
|
||||
|
||||
spinlock_lock(&lwip_lock);
|
||||
|
||||
ret = write(libc_sd, &sysargs, sizeof(sysargs));
|
||||
ret = lwip_write(libc_sd, &sysargs, sizeof(sysargs));
|
||||
if (ret != sizeof(sysargs))
|
||||
goto out;
|
||||
read(libc_sd, &ret, sizeof(ret));
|
||||
lwip_read(libc_sd, &ret, sizeof(ret));
|
||||
|
||||
out:
|
||||
spinlock_unlock(&lwip_lock);
|
||||
|
@ -387,8 +432,8 @@ off_t sys_lseek(int fd, off_t offset, int whence)
|
|||
|
||||
spinlock_lock(&lwip_lock);
|
||||
|
||||
write(libc_sd, &sysargs, sizeof(sysargs));
|
||||
read(libc_sd, &off, sizeof(off));
|
||||
lwip_write(libc_sd, &sysargs, sizeof(sysargs));
|
||||
lwip_read(libc_sd, &off, sizeof(off));
|
||||
|
||||
spinlock_unlock(&lwip_lock);
|
||||
|
||||
|
|
|
@ -37,6 +37,13 @@
|
|||
#include <hermit/syscall.h>
|
||||
#include <hermit/memory.h>
|
||||
|
||||
/*
|
||||
* Note that linker symbols are not variables, they have no memory allocated for
|
||||
* maintaining a value, rather their address is their value.
|
||||
*/
|
||||
extern const void tls_start;
|
||||
extern const void tls_end;
|
||||
|
||||
/*
|
||||
* HermitCore is a single address space OS
|
||||
* => we need only a lock to protect the page tables & VMA
|
||||
|
@ -174,6 +181,33 @@ int set_idle_task(void)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int init_tls(void)
|
||||
{
|
||||
task_t* curr_task = per_core(current_task);
|
||||
|
||||
// do we have a thread local storage?
|
||||
if (((size_t) &tls_end - (size_t) &tls_start) > 0) {
|
||||
char* tls_addr = NULL;
|
||||
|
||||
curr_task->tls_addr = (size_t) &tls_start;
|
||||
curr_task->tls_size = (size_t) &tls_end - (size_t) &tls_start;
|
||||
|
||||
tls_addr = kmalloc(curr_task->tls_size);
|
||||
if (BUILTIN_EXPECT(!tls_addr, 0)) {
|
||||
kprintf("load_task: heap is missing!\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memcpy((void*) tls_addr, (void*) curr_task->tls_addr, curr_task->tls_size);
|
||||
|
||||
// set fs register to the TLS segment
|
||||
set_tls((size_t) tls_addr);
|
||||
kprintf("Task %d set fs to 0x%zx\n", curr_task->id, tls_addr);
|
||||
} else set_tls(0); // no TLS => clear fs register
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void finish_task_switch(void)
|
||||
{
|
||||
task_t* old;
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit cf00aee089047c3356b558423b368a85fc76caa7
|
||||
Subproject commit 9e76e0b89f21173c1a311be6789360c1054eb269
|
39
hermit/tools/netinet/in.h
Normal file
39
hermit/tools/netinet/in.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
#ifndef __NETINET_IN_H__
|
||||
#define __NETINET_IN_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
{
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
struct in_addr {
|
||||
uint32_t s_addr;
|
||||
};
|
||||
#endif
|
||||
|
||||
/** 255.255.255.255 */
|
||||
#define IPADDR_NONE ((uint32_t)0xffffffffUL)
|
||||
/** 127.0.0.1 */
|
||||
#define IPADDR_LOOPBACK ((uint32_t)0x7f000001UL)
|
||||
/** 0.0.0.0 */
|
||||
#define IPADDR_ANY ((uint32_t)0x00000000UL)
|
||||
/** 255.255.255.255 */
|
||||
#define IPADDR_BROADCAST ((uint32_t)0xffffffffUL)
|
||||
|
||||
/** 255.255.255.255 */
|
||||
#define INADDR_NONE IPADDR_NONE
|
||||
/** 127.0.0.1 */
|
||||
#define INADDR_LOOPBACK IPADDR_LOOPBACK
|
||||
/** 0.0.0.0 */
|
||||
#define INADDR_ANY IPADDR_ANY
|
||||
/** 255.255.255.255 */
|
||||
#define INADDR_BROADCAST IPADDR_BROADCAST
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __NETINET_IN_H__ */
|
|
@ -37,7 +37,7 @@
|
|||
#include <arpa/inet.h>
|
||||
#include <linux/tcp.h>
|
||||
|
||||
#define HERMIT_PORT 0x494F
|
||||
#define HERMIT_PORT 0x494E
|
||||
#define HERMIT_MAGIC 0x7E317
|
||||
#define MAX_PATH 255
|
||||
|
||||
|
|
|
@ -3,9 +3,11 @@ ARCH = x86
|
|||
TARGET=x86_64-hermit
|
||||
NJOBS=-j20
|
||||
|
||||
CROSSCOMPREFIX = x86_64-hermit
|
||||
NEWLIB = $(TOPDIR)/$(ARCH)/$(TARGET)
|
||||
RM = rm -rf
|
||||
CD = cd
|
||||
CP = cp
|
||||
MKDIR = mkdir
|
||||
TMP = $(TOPDIR)/tmp
|
||||
OPT = --disable-shared --disable-multilib --enable-newlib-io-c99-formats --enable-newlib-multithread #--enable-newlib-reent-small
|
||||
|
@ -43,7 +45,7 @@ $(TMP)/bootstrap:
|
|||
$Q$(MKDIR) $(TMP)/bootstrap
|
||||
$Q$(CD) $(TMP)/bootstrap; $(TOPDIR)/gcc/configure --target=$(TARGET) --prefix=$(TOPDIR)/$(ARCH) --without-headers --enable-languages=c --disable-nls --disable-shared --disable-libssp --disable-libgomp --enable-threads=posix --enable-tls && $(MAKE) $(NJOBS) all-gcc && $(MAKE) install-gcc
|
||||
|
||||
toolchain: $(TMP)/newlib libs $(TMP)/gcc demo
|
||||
toolchain: $(TMP)/newlib libs $(TMP)/gcc headers demo
|
||||
|
||||
$(TMP)/newlib:
|
||||
@echo Build newlib, libpthread and libgomp
|
||||
|
@ -58,6 +60,13 @@ libs:
|
|||
$Q$(MAKE) TARGET=$(TARGET) CC_FOR_TARGET=$(CC_FOR_TARGET) AR_FOR_TARGET=$(AR_FOR_TARGET) CFLAGS_FOR_TARGET+="-I. -Wall" -C ircce depend
|
||||
$Q$(MAKE) TARGET=$(TARGET) CC_FOR_TARGET=$(CC_FOR_TARGET) AR_FOR_TARGET=$(AR_FOR_TARGET) CFLAGS_FOR_TARGET+="-I. -Wall" -C ircce
|
||||
|
||||
headers:
|
||||
@echo [CP] Copy headers
|
||||
$Q$(CP) -R ../lwip/src/include/posix/* $(TOPDIR)/$(ARCH)/$(CROSSCOMPREFIX)/include/
|
||||
$Q$(CP) -R ../lwip/src/include/arch $(TOPDIR)/$(ARCH)/$(CROSSCOMPREFIX)/include/
|
||||
$Q$(CP) -R ../lwip/src/include/lwip* $(TOPDIR)/$(ARCH)/$(CROSSCOMPREFIX)/include/
|
||||
$Q$(CP) -R ../lwip/src/include/ipv4/lwip/* $(TOPDIR)/$(ARCH)/$(CROSSCOMPREFIX)/include/lwip/
|
||||
$Q$(CP) -R ../tools/neti* $(TOPDIR)/$(ARCH)/$(CROSSCOMPREFIX)/include/
|
||||
|
||||
$(TMP)/gcc:
|
||||
@echo Build final gcc
|
||||
|
@ -81,3 +90,5 @@ veryclean:
|
|||
$Q$(MAKE) -C benchmarks veryclean
|
||||
$Q$(RM) $(TOPDIR)/$(ARCH)
|
||||
$Q$(RM) $(TMP)
|
||||
|
||||
.PHONY: default all clean veryclean headers libs
|
||||
|
|
|
@ -48,7 +48,7 @@ endif
|
|||
|
||||
default: all
|
||||
|
||||
all: stream.bin hg.bin #RCCE_pingping RCCE_pingpong
|
||||
all: stream.bin hg.bin netio.bin #RCCE_pingping RCCE_pingpong
|
||||
|
||||
stream.o: stream.c
|
||||
@echo [CC] $@
|
||||
|
@ -75,6 +75,13 @@ RCCE_pingpong: RCCE_pingpong.o
|
|||
$Q$(OBJCOPY_FOR_TARGET) $(STRIP_DEBUG) $@
|
||||
$Qchmod a-x $@.sym
|
||||
|
||||
netio: netio.o
|
||||
@echo [LD] $@
|
||||
$Q$(CC_FOR_TARGET) $(LDFLAGS_FOR_TARGET) $(CFLAGS_FOR_TARGET) -o $@ $<
|
||||
$Q$(OBJCOPY_FOR_TARGET) $(KEEP_DEBUG) $@ $@.sym
|
||||
$Q$(OBJCOPY_FOR_TARGET) $(STRIP_DEBUG) $@
|
||||
$Qchmod a-x $@.sym
|
||||
|
||||
hg: hg.o hist.o rdtsc.o run.o init.o opt.o report.o setup.o
|
||||
@echo [LD] $@
|
||||
$Q$(CC_FOR_TARGET) $(LDFLAGS_FOR_TARGET) $(CFLAGS_FOR_TARGET) -o $@ $< hist.o rdtsc.o run.o init.o opt.o report.o setup.o
|
||||
|
@ -84,7 +91,7 @@ hg: hg.o hist.o rdtsc.o run.o init.o opt.o report.o setup.o
|
|||
|
||||
clean:
|
||||
@echo Cleaning benchmarks
|
||||
$Q$(RM) stream hg RCCE_pingping RCCE_pingpong *.sym *.o *~ *.bin
|
||||
$Q$(RM) stream hg netio RCCE_pingping RCCE_pingpong *.sym *.o *~ *.bin
|
||||
|
||||
veryclean:
|
||||
@echo Propper cleaning benchmarks
|
||||
|
|
465
hermit/usr/benchmarks/netio.c
Normal file
465
hermit/usr/benchmarks/netio.c
Normal file
|
@ -0,0 +1,465 @@
|
|||
/*
|
||||
* Copyright (c) 2011, Stefan Lankes, RWTH Aachen University
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR AN
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
|
||||
/*
|
||||
* This implements a netio server and client (only TCP version).
|
||||
* The client sends a command word (4 bytes) then a data length word (4 bytes).
|
||||
* If the command is "receive", the server is to consume "data length" bytes into
|
||||
* a circular buffer until the first byte is non-zero, then it is to consume
|
||||
* another command/data pair.
|
||||
* If the command is "send", the server is to send "data length" bytes from a circular
|
||||
* buffer with the first byte being zero, until "some time" (6 seconds in the
|
||||
* current netio131.zip download) has passed and then send one final buffer with
|
||||
* the first byte being non-zero. Then it is to consume another command/data pair.
|
||||
*/
|
||||
|
||||
/* See http://www.nwlab.net/art/netio/netio.html to get the netio tool */
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <netdb.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t cmd;
|
||||
uint32_t data;
|
||||
} CONTROL;
|
||||
|
||||
#define CMD_QUIT 0
|
||||
#define CMD_C2S 1
|
||||
#define CMD_S2C 2
|
||||
#define CMD_RES 3
|
||||
|
||||
#define CTLSIZE sizeof(CONTROL)
|
||||
#define DEFAULTPORT 0x494F
|
||||
#define TMAXSIZE 65536
|
||||
|
||||
static int tSizes[] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32767};
|
||||
static size_t ntSizes = sizeof(tSizes) / sizeof(int);
|
||||
static int nPort = DEFAULTPORT;
|
||||
static const int sobufsize = 131072;
|
||||
static struct in_addr addr_local;
|
||||
static struct in_addr addr_server;
|
||||
|
||||
extern unsigned int get_cpufreq(void);
|
||||
|
||||
inline static unsigned long long rdtsc(void)
|
||||
{
|
||||
unsigned long lo, hi;
|
||||
asm volatile ("rdtsc" : "=a"(lo), "=d"(hi) :: "memory");
|
||||
return ((unsigned long long) hi << 32ULL | (unsigned long long) lo);
|
||||
}
|
||||
|
||||
static int send_data(int socket, void *buffer, size_t size, int flags)
|
||||
{
|
||||
ssize_t rc = send(socket, buffer, size, flags);
|
||||
|
||||
if (rc < 0)
|
||||
{
|
||||
printf("send failed: %d\n", errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (rc != size)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int recv_data(int socket, void *buffer, size_t size, int flags)
|
||||
{
|
||||
ssize_t rc = recv(socket, buffer, size, flags);
|
||||
|
||||
if (rc < 0) {
|
||||
printf("recv failed: %d\n", errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (rc != size)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *InitBuffer(size_t nSize)
|
||||
{
|
||||
char *cBuffer = malloc(nSize);
|
||||
|
||||
memset(cBuffer, 0xFF, nSize);
|
||||
cBuffer[0] = 0;
|
||||
|
||||
return cBuffer;
|
||||
}
|
||||
|
||||
static char *PacketSize(int nSize)
|
||||
{
|
||||
static char szBuffer[64];
|
||||
|
||||
if ((nSize % 1024) == 0 || (nSize % 1024) == 1023)
|
||||
sprintf(szBuffer, "%2dk", (nSize + 512) / 1024);
|
||||
else
|
||||
sprintf(szBuffer, "%d", nSize);
|
||||
|
||||
return szBuffer;
|
||||
}
|
||||
|
||||
static int TCPServer(void)
|
||||
{
|
||||
char *cBuffer;
|
||||
CONTROL ctl;
|
||||
uint64_t nData;
|
||||
struct sockaddr_in sa_server, sa_client;
|
||||
int server, client;
|
||||
socklen_t length;
|
||||
struct timeval tv;
|
||||
fd_set fds;
|
||||
int rc;
|
||||
int nByte;
|
||||
int err;
|
||||
uint64_t start, end;
|
||||
uint32_t freq = get_cpufreq(); /* in MHz */
|
||||
|
||||
if ((cBuffer = InitBuffer(TMAXSIZE)) == NULL) {
|
||||
printf("Netio: Not enough memory\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((server = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
|
||||
printf("socket failed: %d\n", server);
|
||||
free(cBuffer);
|
||||
return -1;
|
||||
}
|
||||
|
||||
setsockopt(server, SOL_SOCKET, SO_RCVBUF, (char *) &sobufsize, sizeof(sobufsize));
|
||||
setsockopt(server, SOL_SOCKET, SO_SNDBUF, (char *) &sobufsize, sizeof(sobufsize));
|
||||
|
||||
memset((char *) &sa_server, 0x00, sizeof(sa_server));
|
||||
sa_server.sin_family = AF_INET;
|
||||
sa_server.sin_port = htons(nPort);
|
||||
sa_server.sin_addr = addr_local;
|
||||
|
||||
if ((err = bind(server, (struct sockaddr *) &sa_server, sizeof(sa_server))) < 0)
|
||||
{
|
||||
printf("bind failed: %d\n", errno);
|
||||
close(server);
|
||||
free(cBuffer);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((err = listen(server, 2)) != 0)
|
||||
{
|
||||
printf("listen failed: %d\n", errno);
|
||||
close(server);
|
||||
free(cBuffer);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
printf("TCP server listening.\n");
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(server, &fds);
|
||||
tv.tv_sec = 3600;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
if ((rc = select(FD_SETSIZE, &fds, 0, 0, &tv)) < 0)
|
||||
{
|
||||
printf("select failed: %d\n", errno);
|
||||
break;
|
||||
}
|
||||
|
||||
if (rc == 0 || FD_ISSET(server, &fds) == 0)
|
||||
continue;
|
||||
length = sizeof(sa_client);
|
||||
|
||||
if ((client = accept(server, (struct sockaddr *) &sa_client, &length)) < 0) {
|
||||
printf("accept faild: %d\n", errno);
|
||||
continue;
|
||||
}
|
||||
|
||||
setsockopt(client, SOL_SOCKET, SO_RCVBUF, (char *) &sobufsize, sizeof(sobufsize));
|
||||
setsockopt(client, SOL_SOCKET, SO_SNDBUF, (char *) &sobufsize, sizeof(sobufsize));
|
||||
|
||||
printf("TCP connection established ... ");
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (recv_data(client, (void *) &ctl, CTLSIZE, 0))
|
||||
break;
|
||||
|
||||
ctl.cmd = ntohl(ctl.cmd);
|
||||
ctl.data = ntohl(ctl.data);
|
||||
|
||||
if (ctl.cmd == CMD_C2S)
|
||||
{
|
||||
start = rdtsc();
|
||||
|
||||
printf("\nReceiving from client, packet size %s ... \n", PacketSize(ctl.data));
|
||||
cBuffer[0] = 0;
|
||||
nData = 0;
|
||||
|
||||
do {
|
||||
for (nByte = 0; nByte < ctl.data; )
|
||||
{
|
||||
rc = recv(client, cBuffer + nByte, ctl.data - nByte, 0);
|
||||
|
||||
if (rc < 0)
|
||||
{
|
||||
printf("recv failed: %d\n", errno);
|
||||
break;
|
||||
}
|
||||
|
||||
if (rc > 0)
|
||||
nByte += rc;
|
||||
}
|
||||
|
||||
nData += ctl.data;
|
||||
} while (cBuffer[0] == 0 && rc > 0);
|
||||
|
||||
end = rdtsc();
|
||||
printf("Time to receive %llu bytes: %llu nsec (ticks %llu)\n", nData, ((end-start)*1000ULL)/freq, end-start);
|
||||
} else if (ctl.cmd == CMD_S2C) {
|
||||
start = rdtsc();
|
||||
|
||||
printf("\nSending to client, packet size %s ... \n", PacketSize(ctl.data));
|
||||
cBuffer[0] = 0;
|
||||
nData = 0;
|
||||
|
||||
do
|
||||
{
|
||||
//GenerateRandomData(cBuffer, ctl.data);
|
||||
|
||||
for (nByte = 0; nByte < ctl.data; )
|
||||
{
|
||||
rc = send(client, cBuffer + nByte, ctl.data - nByte, 0);
|
||||
|
||||
if (rc < 0)
|
||||
{
|
||||
printf("send failed: %d\n", errno);
|
||||
break;
|
||||
}
|
||||
|
||||
if (rc > 0)
|
||||
nByte += rc;
|
||||
}
|
||||
|
||||
nData += ctl.data;
|
||||
end = rdtsc();
|
||||
} while((end-start)/freq < 6000000ULL /* = 6s */);
|
||||
|
||||
cBuffer[0] = 1;
|
||||
|
||||
if (send_data(client, cBuffer, ctl.data, 0))
|
||||
break;
|
||||
|
||||
end = rdtsc();
|
||||
printf("Time to send %llu bytes: %llu nsec (ticks %llu)\n", nData, ((end-start)*1000ULL)/freq, end-start);
|
||||
} else /* quit */
|
||||
break;
|
||||
}
|
||||
|
||||
printf("\nDone.\n");
|
||||
|
||||
close(client);
|
||||
|
||||
if (rc < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
close(server);
|
||||
free(cBuffer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int TCP_Bench(void)
|
||||
{
|
||||
char *cBuffer;
|
||||
CONTROL ctl;
|
||||
uint64_t nData;
|
||||
int i;
|
||||
struct sockaddr_in sa_server;
|
||||
int server;
|
||||
int rc, err;
|
||||
int nByte;
|
||||
uint64_t start, end;
|
||||
uint32_t freq = get_cpufreq(); /* in MHz */
|
||||
|
||||
if ((cBuffer = InitBuffer(TMAXSIZE)) == NULL)
|
||||
{
|
||||
printf("Netio: Not enough memory\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((server = socket(PF_INET, SOCK_STREAM, 0)) < 0)
|
||||
{
|
||||
printf("socket failed: %d\n", errno);
|
||||
free(cBuffer);
|
||||
return -2;
|
||||
}
|
||||
|
||||
setsockopt(server, SOL_SOCKET, SO_RCVBUF, (char *) &sobufsize, sizeof(sobufsize));
|
||||
setsockopt(server, SOL_SOCKET, SO_SNDBUF, (char *) &sobufsize, sizeof(sobufsize));
|
||||
|
||||
sa_server.sin_family = AF_INET;
|
||||
sa_server.sin_port = htons(nPort);
|
||||
sa_server.sin_addr = addr_server;
|
||||
|
||||
if ((err = connect(server, (struct sockaddr *) &sa_server, sizeof(sa_server))) < 0)
|
||||
{
|
||||
printf("connect failed: %d\n", errno);
|
||||
close(server);
|
||||
free(cBuffer);
|
||||
return -2;
|
||||
}
|
||||
|
||||
printf("\nTCP connection established.\n");
|
||||
|
||||
for (i = 0; i < ntSizes; i++)
|
||||
{
|
||||
printf("Packet size %s bytes: ", PacketSize(tSizes[i]));
|
||||
|
||||
/* tell the server we will send it data now */
|
||||
|
||||
ctl.cmd = htonl(CMD_C2S);
|
||||
ctl.data = htonl(tSizes[i]);
|
||||
|
||||
if (send_data(server, (void *) &ctl, CTLSIZE, 0))
|
||||
break;
|
||||
|
||||
/* 1 - Tx test */
|
||||
|
||||
start = rdtsc();
|
||||
nData = 0;
|
||||
cBuffer[0] = 0;
|
||||
|
||||
do
|
||||
{
|
||||
//GenerateRandomData(cBuffer, tSizes[i]);
|
||||
|
||||
for (nByte = 0; nByte < tSizes[i]; )
|
||||
{
|
||||
rc = send(server, cBuffer + nByte, tSizes[i] - nByte, 0);
|
||||
|
||||
if (rc < 0)
|
||||
{
|
||||
printf("send failed: %d\n", errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (rc > 0)
|
||||
nByte += rc;
|
||||
}
|
||||
|
||||
nData += tSizes[i];
|
||||
end = rdtsc();
|
||||
} while((end-start)/freq < 6000000ULL /* = 6s */);
|
||||
|
||||
printf("%llu/100 MBytes/s", ((100ULL*nData)/(1024ULL*1024ULL))/((end-start)/(1000000ULL*freq)));
|
||||
|
||||
printf(" Tx, ");
|
||||
|
||||
cBuffer[0] = 1;
|
||||
|
||||
if (send_data(server, cBuffer, tSizes[i], 0))
|
||||
break;
|
||||
|
||||
/* tell the server we expect him to send us data now */
|
||||
|
||||
ctl.cmd = htonl(CMD_S2C);
|
||||
ctl.data = htonl(tSizes[i]);
|
||||
|
||||
if (send_data(server, (void *) &ctl, CTLSIZE, 0))
|
||||
break;
|
||||
|
||||
/* 2 - Rx test */
|
||||
|
||||
start = rdtsc();
|
||||
nData = 0;
|
||||
cBuffer[0] = 0;
|
||||
rc = 0;
|
||||
|
||||
do
|
||||
{
|
||||
for (nByte = 0; nByte < tSizes[i]; )
|
||||
{
|
||||
rc = recv(server, cBuffer + nByte, tSizes[i] - nByte, 0);
|
||||
|
||||
if (rc < 0)
|
||||
{
|
||||
printf("recv failed: %d\n", errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (rc > 0)
|
||||
nByte += rc;
|
||||
}
|
||||
|
||||
nData += tSizes[i];
|
||||
} while (cBuffer[0] == 0 && rc > 0);
|
||||
|
||||
end = rdtsc();
|
||||
printf("%llu/100 MBytes/s", ((100ULL*nData)/(1024ULL*1024ULL))/((end-start)/(1000000ULL*freq)));
|
||||
|
||||
printf(" Rx.\n");
|
||||
}
|
||||
|
||||
ctl.cmd = htonl(CMD_QUIT);
|
||||
ctl.data = 0;
|
||||
|
||||
send_data(server, (void *) &ctl, CTLSIZE, 0);
|
||||
|
||||
printf("Done.\n");
|
||||
|
||||
close(server);
|
||||
free(cBuffer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
addr_local.s_addr = INADDR_ANY;
|
||||
//addr_server.s_addr = inet_addr("192.168.28.254");
|
||||
addr_server.s_addr = inet_addr("192.168.28.1");
|
||||
|
||||
err = TCPServer();
|
||||
|
||||
return err;
|
||||
}
|
Loading…
Add table
Reference in a new issue