1
0
Fork 0
mirror of https://github.com/hermitcore/libhermit.git synced 2025-03-09 00:00:03 +01:00

add support of proxy processes

This commit is contained in:
Stefan Lankes 2015-10-03 01:43:17 +02:00
parent dc4e376f94
commit e7cddc3e7e
8 changed files with 375 additions and 51 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, Stefan Lankes, RWTH Aachen University
* Copyright (c) 2010-2015, Stefan Lankes, RWTH Aachen University
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -38,6 +38,10 @@
#include <asm/elf.h>
#include <asm/page.h>
#include <lwip/sockets.h>
#include <lwip/err.h>
#include <lwip/stats.h>
#define START_ADDRESS 0x40200000
/*
@ -142,7 +146,7 @@ int create_default_frame(task_t* task, entry_point_t ep, void* arg, uint32_t cor
size_t state_size;
if (BUILTIN_EXPECT(!task, 0))
return -EINVAL;
return -EINVAL;
if (BUILTIN_EXPECT(!task->stack, 0))
return -EINVAL;
@ -162,7 +166,7 @@ int create_default_frame(task_t* task, entry_point_t ep, void* arg, uint32_t cor
* This procedure cleans the task after exit. */
*stack = (size_t) leave_kernel_task;
/* Next bunch on the stack is the initial register state.
/* Next bunch on the stack is the initial register state.
* The stack must look like the stack of a task which was
* scheduled away previously. */
state_size = sizeof(struct state);
@ -186,7 +190,7 @@ int create_default_frame(task_t* task, entry_point_t ep, void* arg, uint32_t cor
}
stptr->cs = 0x08;
stptr->ss = 0x10;
stptr->gs = core_id * ((size_t) &percore_end0 - (size_t) &percore_start);
stptr->gs = core_id * ((size_t) &percore_end0 - (size_t) &percore_start);
stptr->rflags = 0x1202;
stptr->userrsp = stptr->rsp;
@ -203,6 +207,10 @@ int create_default_frame(task_t* task, entry_point_t ep, void* arg, uint32_t cor
typedef struct {
/// Points to the node with the executable in the file system
vfs_node_t* node;
/// Points to a copy of the executable
char* executable;
/// Socket descriptor if have no file node
int sd;
/// Argument count
int argc;
/// Environment var count
@ -226,27 +234,29 @@ static int load_task(load_args_t* largs)
elf_header_t header;
elf_program_header_t prog_header;
//elf_section_header_t sec_header;
///!!! kfree is missing!
fildes_t *file = kmalloc(sizeof(fildes_t));
file->offset = 0;
file->flags = 0;
int ret = -EINVAL;
//TODO: init the hole fildes_t struct!
fildes_t file;
task_t* curr_task = per_core(current_task);
int ret = -EINVAL;
if (!largs)
return -EINVAL;
file->node = largs->node;
if (!file->node)
if (largs->node) {
file.node = largs->node;
file.offset = 0;
file.flags = 0;
} else if (!largs->executable || (largs->sd < 0))
return -EINVAL;
ret = read_fs(file, (uint8_t*)&header, sizeof(elf_header_t));
if (ret < 0) {
kprintf("read_fs failed: %d\n", ret);
goto Lerr;
}
curr_task->sd = largs->sd;
if (largs->node) {
ret = read_fs(&file, (uint8_t*)&header, sizeof(elf_header_t));
if (ret < 0) {
kprintf("read_fs failed: %d\n", ret);
goto Lerr;
}
} else memcpy(&header, largs->executable, sizeof(elf_header_t));
if (BUILTIN_EXPECT(header.ident.magic != ELF_MAGIC, 0))
goto Linvalid;
@ -268,11 +278,13 @@ static int load_task(load_args_t* largs)
// interpret program header table
for (i=0; i<header.ph_entry_count; i++) {
file->offset = header.ph_offset+i*header.ph_entry_size;
if (read_fs(file, (uint8_t*)&prog_header, sizeof(elf_program_header_t)) == 0) {
kprintf("Could not read programm header!\n");
continue;
}
if (largs->node) {
file.offset = header.ph_offset+i*header.ph_entry_size;
if (read_fs(&file, (uint8_t*)&prog_header, sizeof(elf_program_header_t)) == 0) {
kprintf("Could not read programm header!\n");
continue;
}
} else memcpy(&prog_header, largs->executable + header.ph_offset+i*header.ph_entry_size, sizeof(elf_program_header_t));
switch(prog_header.type)
{
@ -313,9 +325,12 @@ static int load_task(load_args_t* largs)
heap = prog_header.virt_addr + prog_header.mem_size;
// load program
file->offset = prog_header.offset;
//kprintf("read programm 0x%zx - 0x%zx\n", prog_header.virt_addr, prog_header.virt_addr + prog_header.file_size);
read_fs(file, (uint8_t*)prog_header.virt_addr, prog_header.file_size);
if (largs->node) {
file.offset = prog_header.offset;
read_fs(&file, (uint8_t*)prog_header.virt_addr, prog_header.file_size);
} else
memcpy((uint8_t*)prog_header.virt_addr, largs->executable + prog_header.offset, prog_header.file_size);
if (!(prog_header.flags & PF_W))
page_set_flags(prog_header.virt_addr, npages, flags);
@ -463,6 +478,8 @@ static int load_task(load_args_t* largs)
offset -= sizeof(ssize_t);
*((ssize_t*) (stack+offset)) = (ssize_t) largs->argc;
if (largs->executable)
kfree(largs->executable);
kfree(largs);
// clear fpu state => currently not supported
@ -492,6 +509,10 @@ Linvalid:
kprintf("program entry point 0x%lx\n", (size_t) header.entry);
Lerr:
if (largs->executable)
kfree(largs->executable);
kfree(largs);
return ret;
}
@ -499,6 +520,8 @@ Lerr:
* which want to have a start function and argument list */
static int user_entry(void* arg)
{
load_args_t* largs = (load_args_t*) arg;
int ret;
finish_task_switch();
@ -506,12 +529,10 @@ static int user_entry(void* arg)
if (BUILTIN_EXPECT(!arg, 0))
return -EINVAL;
ret = load_task((load_args_t*) arg);
ret = load_task(largs);
if (ret)
kprintf("Load task failed: %d\n", ret);
kfree(arg);
sys_exit(ret);
while(1) {
@ -558,6 +579,8 @@ int create_user_task_on_core(tid_t* id, const char* fname, char** argv, uint8_t
return -ENOMEM;
load_args->node = node;
load_args->argc = argc;
load_args->sd = -1;
load_args->executable = NULL;
load_args->envc = 0;
dest = load_args->buffer;
for (i=0; i<argc; i++) {
@ -568,3 +591,91 @@ int create_user_task_on_core(tid_t* id, const char* fname, char** argv, uint8_t
/* create new task */
return create_task(id, user_entry, load_args, prio, core_id);
}
int create_user_task_form_socket(tid_t* id, int sd, uint8_t prio)
{
int argc;
int ret, err = -EINVAL;
int len, total_len, i, j;
load_args_t* load_args = NULL;
char *dest;
uint32_t core_id = CORE_ID;
uint32_t counter = 0;
ret = read(sd, &argc, sizeof(int));
if ((ret != sizeof(int)) || (argc <= 0))
goto out;
load_args = kmalloc(sizeof(load_args_t));
if (BUILTIN_EXPECT(!load_args, 0)) {
err = -ENOMEM;
goto out;
}
load_args->node = NULL;
load_args->executable = NULL;
load_args->sd = sd;
load_args->argc = argc;
load_args->envc = 0;
dest = load_args->buffer;
for(i=0, total_len=0; i<argc; i++)
{
ret = read(sd, &len, sizeof(int));
if ((ret != sizeof(int)) || (len <= 0))
goto out;
total_len += len;
if (total_len >= MAX_ARGS)
goto out;
j=0;
while(j < len)
{
ret = read(sd, dest, len-j);
if (ret < 0)
goto out;
dest += ret;
j += ret;
}
}
// terminate array with a NULL pointer
*dest = 0;
ret = read(sd, &len, sizeof(int));
if ((ret != sizeof(int)) || (len <= 0))
goto out;
kprintf("length of the executable: %d\n", len);
load_args->executable = kmalloc(len);
if (!load_args->executable) {
err = -ENOMEM;
goto out;
}
j=0;
while(j < len)
{
ret = read(sd, load_args->executable+j, len-j);
if (ret < 0)
goto out;
j += ret;
}
/* create new task */
return create_task(id, user_entry, load_args, prio, core_id);
out:
kprintf("Unable to load task: %d\n", err);
if (load_args && load_args->executable)
kfree(load_args->executable);
if (load_args)
kfree(load_args);
closesocket(sd);
counter++;
return err;
}

View file

@ -132,6 +132,7 @@ int create_kernel_task_on_core(tid_t* id, entry_point_t ep, void* args, uint8_t
* @param id The value behind this pointer will be set to the new task's id
* @param fname Filename of the executable to start the task with
* @param argv Pointer to arguments array
* @param prio Desired priority of the new kernel task
*
* @return
* - 0 on success
@ -139,11 +140,24 @@ int create_kernel_task_on_core(tid_t* id, entry_point_t ep, void* args, uint8_t
*/
int create_user_task(tid_t* id, const char* fame, char** argv, uint8_t prio);
/** @brief Create a user level task on the current core.
*
* @param id The value behind this pointer will be set to the new task's id
* @param sd Socket descriptor to load and to start the executable
* @param prio Desired priority of the new kernel task
*
* @return
* - 0 on success
* - -EINVAL (-22) or -ENOMEM (-12)on failure
*/
int create_user_task_form_socket(tid_t* id, int sd, uint8_t prio);
/** @brief Create a user level task.
*
* @param id The value behind this pointer will be set to the new task's id
* @param fname Filename of the executable to start the task with
* @param sd Valid socket descriptor to a TCP/IP connection
* @param argv Pointer to arguments array
* @param prio Desired priority of the new kernel task
* @param core_id Start the new task on the core with this id
*
* @return

View file

@ -112,6 +112,8 @@ typedef struct task {
size_t tls_mem_size;
/// TLS file size
size_t tls_file_size;
/// Socket descriptor to the proxy
int sd;
/// LwIP error code
int lwip_err;
/// FPU state

View file

@ -48,11 +48,18 @@
#include <lwip/dhcp.h>
#include <lwip/netifapi.h>
#include <lwip/timers.h>
#include <lwip/sockets.h>
#include <lwip/err.h>
#include <lwip/stats.h>
#include <netif/etharp.h>
#include <net/mmnif.h>
static struct netif mmnif_netif;
#define HERMIT_PORT 0x494F
#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
* maintaining a value, rather their address is their value.
@ -76,6 +83,7 @@ extern atomic_int32_t possible_cpus;
extern int32_t isle;
extern int32_t possible_isles;
#if 0
static int foo(void* arg)
{
int i;
@ -87,6 +95,7 @@ static int foo(void* arg)
return 0;
}
#endif
static int hermit_init(void)
{
@ -173,6 +182,14 @@ static int init_netifs(void)
return 0;
}
static int network_shutdown(void)
{
mmnif_shutdown();
netifapi_netif_set_down(&mmnif_netif);
return 0;
}
#if MAX_CORES > 1
int smp_main(void)
{
@ -202,13 +219,15 @@ int smp_main(void)
// init task => creates all other tasks an initialize the LwIP
static int initd(void* arg)
{
int s, c, len, err;
int32_t magic;
struct sockaddr_in server, client;
//char* argv1[] = {"/bin/hello", NULL};
//char* argv2[] = {"/bin/jacobi", NULL};
//char* argv3[] = {"/bin/stream", NULL};
//char* argv4[] = {"/bin/thr_hello", NULL};
init_netifs();
//create_kernel_task(NULL, foo, "foo1", NORMAL_PRIO);
//create_kernel_task(NULL, foo, "foo2", NORMAL_PRIO);
//create_user_task(NULL, "/bin/hello", argv1, NORMAL_PRIO);
@ -217,6 +236,66 @@ static int initd(void* arg)
//create_user_task(NULL, "/bin/stream", argv3, NORMAL_PRIO);
//create_user_task(NULL, "/bin/thr_hello", argv4, NORMAL_PRIO);
init_netifs();
s = socket(PF_INET , SOCK_STREAM , 0);
if (s < 0) {
kprintf("socket failed: %d\n", server);
return -1;
}
// prepare the sockaddr_in structure
memset((char *) &server, 0x00, sizeof(server));
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(HERMIT_PORT);
if ((err = bind(s, (struct sockaddr *) &server, sizeof(server))) < 0)
{
kprintf("bind failed: %d\n", errno);
closesocket(s);
return -1;
}
if ((err = listen(s, 2)) < 0)
{
kprintf("listen failed: %d\n", errno);
closesocket(s);
return -1;
}
len = sizeof(struct sockaddr_in);
while(!shutdown)
{
kputs("TCP server listening.\n");
if ((c = accept(s, (struct sockaddr *)&client, (socklen_t*)&len)) < 0)
{
kprintf("accept faild: %d\n", errno);
closesocket(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));
read(c, &magic, sizeof(int32_t));
if (magic != HEMRIT_MAGIC)
{
kprintf("Invalid magic number %d\n", magic);
closesocket(c);
continue;
}
create_user_task_form_socket(NULL, c, NORMAL_PRIO);
}
closesocket(s);
network_shutdown();
return 0;
}

View file

@ -34,6 +34,12 @@
#include <hermit/semaphore.h>
#include <hermit/time.h>
#include <lwip/sockets.h>
#include <lwip/err.h>
#include <lwip/stats.h>
static spinlock_t lwip_lock = SPINLOCK_INIT;
static tid_t sys_getpid(void)
{
task_t* task = per_core(current_task);
@ -53,19 +59,74 @@ static void sys_yield(void)
reschedule();
}
void NORETURN do_exit(int arg);
/** @brief To be called by the systemcall to exit tasks */
void NORETURN sys_exit(int arg)
{
task_t* task = per_core(current_task);
int sysnr = __NR_exit;
if (task->sd >= 0)
{
spinlock_lock(&lwip_lock);
write(task->sd, &sysnr, sizeof(int));
write(task->sd, &arg, sizeof(int));
spinlock_unlock(&lwip_lock);
closesocket(task->sd);
task->sd = -1;
}
do_exit(arg);
}
static int sys_write(int fd, const char* buf, size_t len)
{
task_t* task = per_core(current_task);
int ret, sysnr = __NR_write;
size_t i;
//TODO: Currently, we ignore the file descriptor
if (BUILTIN_EXPECT(!buf, 0))
return -1;
for(i=0; i<len; i++)
kputchar(buf[i]);
if (task->sd < 0)
{
for(i=0; i<len; i++)
kputchar(buf[i]);
return len;
return len;
}
spinlock_lock(&lwip_lock);
ret = write(task->sd, &sysnr, sizeof(int));
if (ret < 0)
goto out;
ret = write(task->sd, &fd, sizeof(int));
if (ret < 0)
goto out;
ret = write(task->sd, &len, sizeof(size_t));
if (ret < 0)
goto out;
i=0;
while(i<len)
{
ret = write(task->sd, (char*)buf+i, len-i);
if (ret < 0)
goto out;
i += ret;
}
ret = len;
out:
spinlock_unlock(&lwip_lock);
return ret;
}
static ssize_t sys_sbrk(int incr)
@ -96,12 +157,72 @@ static ssize_t sys_sbrk(int incr)
static int sys_open(const char* name, int flags, int mode)
{
return 0;
task_t* task = per_core(current_task);
int i, ret, sysnr = __NR_open;
size_t len = strlen(name+1);
if (task->sd < 0)
return 0;
len = strlen(name+1);
spinlock_lock(&lwip_lock);
ret = write(task->sd, &sysnr, sizeof(int));
if (ret < 0)
goto out;
ret = write(task->sd, &len, sizeof(size_t));
if (ret < 0)
goto out;
i=0;
while(i<len)
{
ret = write(task->sd, name+i, len-i);
if (ret < 0)
goto out;
i += ret;
}
ret = write(task->sd, &flags, sizeof(int));
if (ret < 0)
goto out;
ret = write(task->sd, &mode, sizeof(int));
if (ret < 0)
goto out;
read(task->sd, &ret, sizeof(int));
out:
spinlock_unlock(&lwip_lock);
return ret;
}
static int sys_close(int fd)
{
return 0;
task_t* task = per_core(current_task);
int ret, sysnr = __NR_close;
if (task->sd < 0)
return 0;
spinlock_lock(&lwip_lock);
ret = write(task->sd, &sysnr, sizeof(int));
if (ret < 0)
goto out;
ret = write(task->sd, &fd, sizeof(int));
if (ret < 0)
goto out;
read(task->sd, &ret, sizeof(int));
out:
spinlock_unlock(&lwip_lock);
return ret;
}
static int sys_msleep(unsigned int msec)
@ -171,7 +292,7 @@ static int sys_sem_timedwait(sem_t *sem, unsigned int ms)
static int sys_clone(tid_t* id, void* ep, void* argv)
{
return clone_task(id, ep, argv, per_core(current_task)->prio);
return clone_task(id, ep, argv, per_core(current_task)->prio);
}
static int default_handler(void)

View file

@ -42,8 +42,8 @@
* A task's id will be its position in this array.
*/
static task_t task_table[MAX_TASKS] = { \
[0] = {0, TASK_IDLE, 0, NULL, NULL, TASK_DEFAULT_FLAGS, 0, 0, 0, SPINLOCK_IRQSAVE_INIT, SPINLOCK_INIT, NULL, 0, NULL, NULL, 0, NULL, NULL, 0, 0, 0, 0}, \
[1 ... MAX_TASKS-1] = {0, TASK_INVALID, 0, NULL, NULL, TASK_DEFAULT_FLAGS, 0, 0, 0, SPINLOCK_IRQSAVE_INIT, SPINLOCK_INIT, NULL, 0, NULL, NULL, 0, NULL, NULL, 0, 0, 0, 0}};
[0] = {0, TASK_IDLE, 0, NULL, NULL, TASK_DEFAULT_FLAGS, 0, 0, 0, SPINLOCK_IRQSAVE_INIT, SPINLOCK_INIT, NULL, 0, NULL, NULL, 0, NULL, NULL, 0, 0, 0, -1, 0}, \
[1 ... MAX_TASKS-1] = {0, TASK_INVALID, 0, NULL, NULL, TASK_DEFAULT_FLAGS, 0, 0, 0, SPINLOCK_IRQSAVE_INIT, SPINLOCK_INIT, NULL, 0, NULL, NULL, 0, NULL, NULL, 0, 0, 0, -1, 0}};
static spinlock_irqsave_t table_lock = SPINLOCK_IRQSAVE_INIT;
@ -215,7 +215,7 @@ void finish_task_switch(void)
/** @brief A procedure to be called by
* procedures which are called by exiting tasks. */
static void NORETURN do_exit(int arg)
void NORETURN do_exit(int arg)
{
task_t* curr_task = per_core(current_task);
const uint32_t core_id = CORE_ID;
@ -252,11 +252,6 @@ void NORETURN leave_kernel_task(void) {
do_exit(result);
}
/** @brief To be called by the systemcall to exit tasks */
void NORETURN sys_exit(int arg) {
do_exit(arg);
}
/** @brief Aborting a task is like exiting it with result -1 */
void NORETURN abort(void) {
do_exit(-1);
@ -319,6 +314,7 @@ int clone_task(tid_t* id, entry_point_t ep, void* arg, uint8_t prio)
task_table[i].tls_addr = curr_task->tls_addr;
task_table[i].tls_mem_size = curr_task->tls_mem_size;
task_table[i].tls_file_size = curr_task->tls_file_size;
task_table[i].sd = task_table[i].sd;
task_table[i].lwip_err = 0;
task_table[i].user_usage = curr_task->user_usage;
task_table[i].page_map = curr_task->page_map;
@ -350,7 +346,7 @@ int clone_task(tid_t* id, entry_point_t ep, void* arg, uint8_t prio)
}
spinlock_irqsave_unlock(&table_lock);
out:
out:
if (ret)
kfree(stack);
@ -403,6 +399,7 @@ int create_task(tid_t* id, entry_point_t ep, void* arg, uint8_t prio, uint32_t c
task_table[i].tls_addr = 0;
task_table[i].tls_mem_size = 0;
task_table[i].tls_file_size = 0;
task_table[i].sd = -1;
task_table[i].lwip_err = 0;
spinlock_irqsave_init(&task_table[i].page_lock);

@ -1 +1 @@
Subproject commit 6dbcf238e2e6abe4ae90a8c64521fbf8d75c3ce3
Subproject commit 9209bfad66bb4ca907bac43515be5b3905fd4f1f

View file

@ -5,7 +5,7 @@ CC = gcc
CFLAGS = -O2 -Wall
HEXDUMP = hexdump
LDFLGAS =
EXECFILES = $(shell find ../usr/examples -perm -u+r+x -type f)
EXECFILES = ../usr/examples/hello #$(shell find ../usr/examples -perm -u+r+x -type f)
# Prettify output
V = 0