Merge branch 'master' of git.lfbs.rwth-aachen.de:metalsvm

Conflicts:
	kernel/netio.c
This commit is contained in:
Stefan Lankes 2011-10-04 01:37:09 -07:00
commit 14785b5e23
23 changed files with 2265 additions and 1364 deletions

View file

@ -3,7 +3,7 @@ ARCH = x86
NAME = metalsvm
LWIPDIRS = lwip/src/arch lwip/src/api lwip/src/core lwip/src/core/ipv4 lwip/src/netif
DRIVERDIRS = drivers/net drivers/char
KERNDIRS = libkern kernel mm fs arch/$(ARCH)/kernel arch/$(ARCH)/mm arch/$(ARCH)/scc $(LWIPDIRS) $(DRIVERDIRS)
KERNDIRS = libkern kernel mm fs apps arch/$(ARCH)/kernel arch/$(ARCH)/mm arch/$(ARCH)/scc $(LWIPDIRS) $(DRIVERDIRS)
SUBDIRS = $(KERNDIRS)
CC_FOR_TARGET=gcc

4
apps/Makefile Normal file
View file

@ -0,0 +1,4 @@
C_source := tests.c echo.c netio.c
MODULE := apps
include $(TOPDIR)/Makefile.inc

View file

@ -24,8 +24,14 @@
#include <metalsvm/syscall.h>
#include <metalsvm/errno.h>
#ifdef CONFIG_ROCKCREEK
#include <asm/RCCE.h>
#include <asm/RCCE_lib.h>
#include <asm/SCC_API.h>
#endif
/*
* This implements a netio server.
* 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
@ -40,7 +46,6 @@
#ifdef CONFIG_LWIP
#include <lwip/sockets.h>
#include <lwip/stats.h>
typedef struct
{
@ -57,9 +62,12 @@ typedef struct
#define DEFAULTPORT 0x494F /* "IO" */
#define TMAXSIZE 65536
static int tSizes[] = {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;
static int send_data(int socket, void *buffer, size_t size, int flags)
{
@ -132,7 +140,7 @@ static int TCPServer(void* arg)
if ((cBuffer = InitBuffer(TMAXSIZE)) == NULL) {
kprintf("Netio: Not enough memory\n");
return -EINVAL;
return -1;
}
if ((server = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
@ -271,8 +279,6 @@ static int TCPServer(void* arg)
closesocket(client);
stats_display();
if (rc < 0)
break;
}
@ -283,10 +289,170 @@ static int TCPServer(void* arg)
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_cpu_frequency(); /* in MHz */
if ((cBuffer = InitBuffer(TMAXSIZE)) == NULL)
{
kprintf("Netio: Not enough memory\n");
return -1;
}
if ((server = socket(PF_INET, SOCK_STREAM, 0)) < 0)
{
kprintf("socket failed: %d\n", server);
kfree(cBuffer, TMAXSIZE);
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)
{
kprintf("connect failed: %d\n", err);
closesocket(server);
kfree(cBuffer, TMAXSIZE);
return -2;
}
kprintf("\nTCP connection established.\n");
for (i = 0; i < ntSizes; i++)
{
kprintf("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)
{
kprintf("send failed: %d\n", rc);
break;
}
if (rc > 0)
nByte += rc;
}
nData += tSizes[i];
end = rdtsc();
} while((end-start)/freq < 6000000ULL /* = 6s */);
kprintf("%llu KBytes/s\n", (nData/1024ULL)/((end-start)/(1000000ULL*freq)));
kprintf(" 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)
{
kprintf("recv failed: %d\n", rc);
break;
}
if (rc > 0)
nByte += rc;
}
nData += tSizes[i];
} while (cBuffer[0] == 0 && rc > 0);
end = rdtsc();
kprintf("%llu KBytes/s\n", (nData/1024ULL)/((end-start)/(1000000ULL*freq)));
kprintf(" Rx.\n");
}
ctl.cmd = htonl(CMD_QUIT);
ctl.data = 0;
send_data(server, (void *) &ctl, CTLSIZE, 0);
kprintf("Done.\n");
closesocket(server);
kfree(cBuffer, TMAXSIZE);
return 0;
}
int netio_init(void)
{
addr_local.s_addr = INADDR_ANY;
int err = 0;
return create_kernel_task(NULL, TCPServer, NULL, NORMAL_PRIO);
addr_local.s_addr = INADDR_ANY;
//addr_server.s_addr = inet_addr("192.168.28.254");
addr_server.s_addr = inet_addr("192.168.0.2");
#ifdef CONFIG_ROCKCREEK
if (RCCE_ue() == 1) {
err = create_kernel_task(NULL, TCPServer, NULL, NORMAL_PRIO);
} else if (RCCE_ue() == 0) {
sleep(3);
err = TCP_Bench();
}
#else
err = create_kernel_task(NULL, TCPServer, NULL, NORMAL_PRIO);
#endif
return err;
}
#endif

View file

@ -279,7 +279,7 @@ int test_init(void)
// char* argv[] = {"/bin/mshell", NULL};
char* argv[] = {"/bin/tests", NULL};
char* server_argv[] = {"/bin/server", "6789", NULL};
// char* client_argv[] = {"/bin/client", "127.0.0.1", "6789", NULL};
char* client_argv[] = {"/bin/client", "192.168.0.1", "6789", NULL};
sem_init(&producing, 1);
sem_init(&consuming, 0);
@ -297,9 +297,11 @@ int test_init(void)
//create_user_task(NULL, "/bin/jacobi", argv);
//create_user_task(NULL, "/bin/mshell", argv);
//create_user_task(NULL, "/bin/jacobi", argv);
//create_user_task(NULL, "/bin/server", server_argv);
//sleep(5);
//create_user_task(NULL, "/bin/client", client_argv);
/*create_user_task(NULL, "/bin/server", server_argv);
if (RCCE_ue() != 0) {
sleep(5);
create_user_task(NULL, "/bin/client", client_argv);
}*/
return 0;
}

View file

@ -53,7 +53,9 @@ typedef struct
extern kb_buffer_t kb_buffer;
void kb_flush();
void kb_init(size_t size, tid_t tid);
void kb_finish(void);
#endif

View file

@ -36,7 +36,7 @@ void kb_init(size_t size, tid_t tid) {
return;
}
void kb_finish() {
void kb_finish(void) {
kfree(kb_buffer.buffer, (kb_buffer.maxsize * sizeof(char)));
kb_buffer.buffer = NULL;
kb_buffer.size = 0;

View file

@ -26,7 +26,7 @@
#ifdef CONFIG_ROCKCREEK
#include "scc_memcpy.h"
#include <asm/scc_memcpy.h>
//--------------------------------------------------------------------------------------
// FUNCTION: RCCE_get

View file

@ -26,7 +26,7 @@
#ifdef CONFIG_ROCKCREEK
#include "scc_memcpy.h"
#include <asm/scc_memcpy.h>
//--------------------------------------------------------------------------------------
// FUNCTION: RCCE_put

View file

@ -28,7 +28,7 @@
#ifdef CONFIG_ROCKCREEK
#include <asm/RCCE_lib.h>
#include "scc_memcpy.h"
#include <asm/scc_memcpy.h>
//--------------------------------------------------------------------------------------
// FUNCTION: RCCE_recv_general

View file

@ -28,7 +28,7 @@
#ifdef CONFIG_ROCKCREEK
#include <asm/RCCE_lib.h>
#include "scc_memcpy.h"
#include <asm/scc_memcpy.h>
//--------------------------------------------------------------------------------------
// FUNCTION: RCCE_send_general

View file

@ -36,7 +36,7 @@
#include <asm/iRCCE_lib.h>
#if defined(COPPERRIDGE) || defined(SCC)
#include "scc_memcpy.h"
#include <asm/scc_memcpy.h>
#endif
void* iRCCE_memcpy_get(void *dest, const void *src, size_t count)

View file

@ -36,7 +36,7 @@
#include <asm/iRCCE_lib.h>
#if defined(COPPERRIDGE) || defined(SCC)
#include "scc_memcpy.h"
#include <asm/scc_memcpy.h>
#endif
void* iRCCE_memcpy_put(void *dest, const void *src, size_t count)

View file

@ -90,7 +90,7 @@ static void intr_handler(struct state *s)
int tmp, z;
#ifdef CONFIG_LWIP
//mmnif_irqhandler();
mmnif_irqhandler();
#endif
z = Z_PID(RC_COREID[my_ue]);

File diff suppressed because it is too large Load diff

View file

@ -1,51 +1,51 @@
/*
* Copyright 2011 Carl-Benedikt Krueger, Chair for Operating Systems,
* RWTH Aachen University
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of MetalSVM.
*/
#ifndef __MMNIF_H__
#define __MMNIF_H__
#ifdef WIN32
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef char int8_t;
typedef short int16_t;
typedef int int32_t;
#else
#define TRUE 1
#define FALSE 0
#endif
/*
* Initialize the network driver for mmn
*/
int mmnif_open(void);
int mmnif_close(void);
int mmnif_poll(void* e);
int mmnif_worker(void* e);
void mmnif_irqhandler(void);
#endif
/*
* Copyright 2011 Carl-Benedikt Krueger, Chair for Operating Systems,
* RWTH Aachen University
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of MetalSVM.
*/
#ifndef __MMNIF_H__
#define __MMNIF_H__
#include <metalsvm/stddef.h>
#ifdef CONFIG_LWIP
#include <lwip/err.h>
#include <lwip/netif.h> /* lwip netif */
#define AF_MMNIF_NET 0x1337
#define MMNIF_AUTOACTIVATE_FAST_SOCKETS 0
#if MMNIF_AUTOACTIVATE_FAST_SOCKETS
#define accept(a,b,c) mmnif_accept(a,b,c)
#define closesocket(s) mmnif_closesocket(s)
#define connect(a,b,c) mmnif_connect(a,b,c)
#define recv(a,b,c,d) mmnif_recv(a,b,c,d)
#define send(a,b,c,d) mmnif_send(a,b,c,d)
#define socket(a,b,c) mmnif_socket(a,b,c)
#define bind(a,b,c) mmnif_bind(a,b,c)
#define listen(a,b) mmnif_listen(a,b)
#endif
err_t mmnif_init(struct netif*);
err_t mmnif_shutdown(void);
int mmnif_worker(void *e);
void mmnif_irqhandler(void);
void mmnif_print_driver_status();
#endif
#endif

View file

@ -1,55 +1,52 @@
/*
* Copyright 2011 Carl-Benedikt Krueger, Chair for Operating Systems,
* RWTH Aachen University
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of MetalSVM.
*/
#include <metalsvm/stdio.h>
#include "util.h"
inline int isprint(unsigned char e)
{
if ((e < 0x30) || (e > 0x80))
return 0;
return 1;
}
// hex_dumb display network packets in a good way
void hex_dump(unsigned n, const unsigned char* buf)
{
int on_this_line = 0;
while (n-- > 0)
{
kprintf("%02X ", *buf++);
on_this_line += 1;
if (on_this_line == 16 || n == 0)
{
int i;
kputs(" ");
for (i = on_this_line; i < 16; i++)
kputs(" ");
for (i = on_this_line; i > 0; i--)
kputchar(isprint(buf[-i]) ? buf[-i] : '.');
kputs("\n");
on_this_line = 0;
}
}
}
/*
* Copyright 2011 Carl-Benedikt Krueger, Chair for Operating Systems,
* RWTH Aachen University
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of MetalSVM.
*/
#include <metalsvm/stdio.h>
#include "util.h"
inline int isprint(unsigned char e)
{
if ((e < 0x30) || (e > 0x80))
return 0;
return 1;
}
// hex_dumb display network packets in a good way
void hex_dump(unsigned n, const unsigned char *buf)
{
int on_this_line = 0;
while (n-- > 0)
{
kprintf("%02X ", *buf++);
on_this_line += 1;
if (on_this_line == 16 || n == 0)
{
int i;
kputs(" ");
for (i = on_this_line; i < 16; i++)
kputs(" ");
for (i = on_this_line; i > 0; i--)
kputchar(isprint(buf[-i]) ? buf[-i] : '.');
kputs("\n");
on_this_line = 0;
}
}
}

View file

@ -1,26 +1,26 @@
/*
* Copyright 2011 Carl-Benedikt Krueger, Chair for Operating Systems,
* RWTH Aachen University
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of MetalSVM.
*/
#ifndef __UTIL__
#define __UTIL__
// hex_dumb display network packets in a good way
void hex_dump(unsigned n, const unsigned char* buf);
#endif
/*
* Copyright 2011 Carl-Benedikt Krueger, Chair for Operating Systems,
* RWTH Aachen University
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of MetalSVM.
*/
#ifndef __UTIL__
#define __UTIL__
// hex_dumb display network packets in a good way
void hex_dump(unsigned n, const unsigned char *buf);
#endif

View file

@ -1,4 +1,4 @@
C_source := main.c tasks.c syscall.c tests.c echo.c netio.c init.c
C_source := main.c tasks.c syscall.c init.c
MODULE := kernel
include $(TOPDIR)/Makefile.inc

View file

@ -71,6 +71,9 @@ int lowlevel_init(void)
#if defined(CONFIG_LWIP) && (defined(CONFIG_PCI) || defined(CONFIG_ROCKCREEK))
static struct netif default_netif;
#ifdef CONFIG_ROCKCREEK
static struct netif mmnif_netif;
#endif
static int init_netifs(void)
{
@ -83,8 +86,9 @@ static int init_netifs(void)
// Set up the lwIP network interface
memset(&default_netif, 0x00, sizeof(struct netif));
#ifdef CONFIG_ROCKCREEK
memset(&mmnif_netif, 0x00, sizeof(struct netif));
/* Set network address variables */
IP4_ADDR(&gw, 192,168,28,254);
IP4_ADDR(&ipaddr, 192,168,28,RCCE_ue()+1);
@ -92,12 +96,38 @@ static int init_netifs(void)
/* Bring up the network interface */
if ((err = netifapi_netif_add(&default_netif, &ipaddr, &netmask, &gw, NULL, rckemacif_init, tcpip_input)) != ERR_OK) {
kprintf("Unable to add network interface: err = %d\n", err);
kprintf("Unable to add the network interface: err = %d\n", err);
return -ENODEV;
}
netifapi_netif_set_default(&default_netif);
netifapi_netif_set_up(&default_netif);
/* Bring up the intra network interface */
struct ip_addr intra_ipaddr;
struct ip_addr intra_netmask;
struct ip_addr intra_gw;
IP4_ADDR(&intra_gw, 0,0,0,0);
IP4_ADDR(&intra_ipaddr, 192,168,0,RCCE_ue()+1);
IP4_ADDR(&intra_netmask, 255,255,255,0);
/* register our Memory Mapped Virtual IP interface in the lwip stack
* and tell him how to use the interface:
* - mmnif_dev : the device data storage
* - ipaddr : the ip address wich should be used
* - gw : the gateway wicht should be used
* - mmnif_init : the initialization which has to be done in order to use our interface
* - ethernet_input : tells him that he should get ethernet input (inclusice ARP)
*/
if ((err = netifapi_netif_add(&mmnif_netif, &intra_ipaddr, &intra_netmask, &intra_gw, NULL, mmnif_init, tcpip_input)) != ERR_OK)
{
kprintf("Unable to add the intra network interface: err = %d\n", err);
return -ENODEV;
}
/* tell lwip all initialization is done and we want to set it ab */
netifapi_netif_set_up(&mmnif_netif);
#else
/* Clear network address because we use DHCP to get an ip address */
IP4_ADDR(&gw, 0,0,0,0);
@ -106,7 +136,7 @@ static int init_netifs(void)
/* Bring up the network interface */
if ((err = netifapi_netif_add(&default_netif, &ipaddr, &netmask, &gw, NULL, rtl8139if_init, tcpip_input)) != ERR_OK) {
kprintf("Unable to add network interface: err = %d\n", err);
kprintf("Unable to add the network interface: err = %d\n", err);
return -ENODEV;
}
@ -144,11 +174,10 @@ static void tcpip_init_done(void* arg)
static int network_shutdown(void)
{
#if defined(CONFIG_LWIP) && defined(CONFIG_ROCKCREEK)
mmnif_shutdown();
netifapi_netif_set_down(&default_netif);
memset(&default_netif, 0x00, sizeof(struct netif));
#elif defined(CONFIG_LWIP) && defined(CONFIG_PCI)
netifapi_dhcp_stop(&default_netif);
memset(&default_netif, 0x00, sizeof(struct netif));
#endif
return 0;
@ -209,6 +238,7 @@ int initd(void* arg)
{
#ifdef CONFIG_LWIP
sys_sem_t sem;
tid_t id;
char* argv[] = {"/bin/rlogind ", NULL};
// Initialize lwIP modules
@ -230,9 +260,10 @@ int initd(void* arg)
#endif
// start echo, netio and rlogind
echo_init();
netio_init();
create_user_task(NULL, "/bin/rlogind", argv);
//echo_init();
create_user_task(&id, "/bin/rlogind", argv);
kprintf("Create rlogind with id %u\n", id);
//netio_init();
#endif
list_root();

View file

@ -60,6 +60,8 @@ int smp_main(void)
int main(void)
{
tid_t id;
lowlevel_init();
pushbg(COL_BLUE);
@ -91,7 +93,8 @@ int main(void)
kprintf("Current available memory: %u MBytes\n", atomic_int32_read(&total_available_pages)/((1024*1024)/PAGE_SIZE));
sleep(5);
create_kernel_task(NULL, initd, NULL, NORMAL_PRIO);
create_kernel_task(&id, initd, NULL, NORMAL_PRIO);
kprintf("Create initd with id %u\n", id);
reschedule();
while(1) {

View file

@ -47,6 +47,11 @@ static int get_fildes(void)
task_t* curr_task = per_core(current_task);
int fd;
/*
* Seach the process specific file descriptor table for a free
* descriptor. The new descriptor returned by the call is the lowest
* numbered descriptor currently not in use by the process.
*/
for (fd = 0; fd < NR_OPEN; fd++) {
if (curr_task->fildes_table[fd] == NULL) {
/* Init Filedescriptor */
@ -60,32 +65,55 @@ static int get_fildes(void)
return -EMFILE;
}
static int sys_write(int fd, const char* buf, size_t len)
{
task_t* curr_task = per_core(current_task);
/* fd is negative or greater than the maximum allowable number */
if (BUILTIN_EXPECT((fd >= NR_OPEN) || (fd < 0), 0))
return -EBADF;
/* fd is not an active, valid file descriptor. */
if (curr_task->fildes_table[fd] == NULL)
return -EBADF;
return write_fs(curr_task->fildes_table[fd], (uint8_t*)buf, len);
}
static int sys_open(const char* name, int flags, int mode)
{
int fd, check;
fildes_t* file = NULL;
task_t* curr_task = per_core(current_task);
/* no name is given */
if (name == NULL)
return -EINVAL;
/* Get a free file descriptor */
fd = get_fildes();
/* validate the fd */
if (fd < 0)
return fd;
file = per_core(current_task)->fildes_table[fd];
file->mode = mode;
file->flags = flags;
file->count = 1;
check = open_fs(file, (char*) name);
/* fd is negative or greater than the maximum allowable number */
if (BUILTIN_EXPECT((fd >= NR_OPEN) || (fd < 0), 0))
return fd; /* in this case fd = errno */
/* init the whole file descriptor structure */
curr_task->fildes_table[fd]->mode = mode;
curr_task->fildes_table[fd]->flags = flags;
curr_task->fildes_table[fd]->count = 1;
check = open_fs(curr_task->fildes_table[fd], (char*) name);
/* file doesn't exist! */
if (check < 0) {
/* file doesn't exist! */
kfree(file, sizeof(fildes_t));
file = NULL;
/* tidy up the fildescriptor */
kfree(curr_task->fildes_table[fd], sizeof(fildes_t));
curr_task->fildes_table[fd] = NULL;
return check;
}
return fd;
}
static int sys_stat(const char* name, struct stat* st) {
static int sys_stat(const char* name, struct stat* st)
{
vfs_node_t* node;
node = findnode_fs(name);
@ -112,43 +140,102 @@ static int sys_stat(const char* name, struct stat* st) {
return 0;
}
static int sys_read(int fd, const char* buf, size_t len)
{
task_t* curr_task = per_core(current_task);
/* fd is negative or greater than the maximum allowable number */
if (BUILTIN_EXPECT((fd >= NR_OPEN) || (fd < 0), 0))
return -EBADF;
/* fd is not an active, valid file descriptor. */
if (curr_task->fildes_table[fd] == NULL)
return -EBADF;
return read_fs(curr_task->fildes_table[fd], (uint8_t*)buf, len);
}
#if defined(CONFIG_LWIP) && LWIP_SOCKET
static int sys_socket(int domain, int type, int protocol)
{
int fd;
fildes_t* file = NULL;
int fd, sock;
task_t* curr_task = per_core(current_task);
/* Get a free file descriptor */
fd = get_fildes();
/* validate the fd */
if (fd < 0)
return fd;
file = per_core(current_task)->fildes_table[fd];
file->offset = lwip_socket(domain, type, protocol);
file->node = findnode_fs("/dev/socket");
file->count = 1;
/* validate the file descriptor */
if (BUILTIN_EXPECT((fd >= NR_OPEN) || (fd < 0), 0))
return fd; /* in this case fd = errno */
/* Get a valid lwip descriptor */
sock = lwip_socket(domain, type, protocol);
/* validate the file descriptor */
if (BUILTIN_EXPECT(sock < 0, 0))
return sock; /* in this case sock = errno */
/*
* init the whole file descriptor structure.
* We use the offset to save the lwip descriptor
* TODO: find another solution or change the name 'offset'
*/
curr_task->fildes_table[fd]->offset = sock;
curr_task->fildes_table[fd]->count = 1;
curr_task->fildes_table[fd]->node = findnode_fs("/dev/socket");
/* file doesn't exist! */
if (curr_task->fildes_table[fd]->node == NULL) {
/* tidy up the fildescriptor */
kfree(curr_task->fildes_table[fd], sizeof(fildes_t));
curr_task->fildes_table[fd] = NULL;
return -ENOENT;
}
return fd;
}
static int sys_accept(int s, struct sockaddr* addr, socklen_t* addrlen)
{
int fd;
fildes_t* file = NULL;
int fd, sock2;
task_t* curr_task = per_core(current_task);
if (BUILTIN_EXPECT(s >= NR_OPEN, 0))
return -EINVAL;
/* validate the 'socket'-filedescriptor */
if (BUILTIN_EXPECT((s >= NR_OPEN) || (s < 0), 0))
return -EBADF;
/* validate the 'socket'-file descriptor object */
if (curr_task->fildes_table[s] == NULL)
return -EBADF;
/* Get a free file descriptor */
fd = get_fildes();
/* validate the fd */
if (fd < 0)
return fd;
file = per_core(current_task)->fildes_table[fd];
file->offset = lwip_accept(s, addr, addrlen);
file->node = findnode_fs("/dev/socket");
file->count = 1;
/* validate the file descriptor */
if (BUILTIN_EXPECT((fd >= NR_OPEN) || (fd < 0), 0))
return fd; /* in this case fd = errno */
/* Get a valid lwip descriptor */
sock2 = lwip_accept(s, addr, addrlen);
/* validate the file descriptor */
if (BUILTIN_EXPECT(sock2 < 0, 0))
return sock2; /* in this case sock = errno */
/*
* init the whole file descriptor structure.
* We use the offset to save the lwip descriptor
* TODO: find another solution or change the name 'offset'
*/
curr_task->fildes_table[fd]->offset = sock2;
curr_task->fildes_table[fd]->count = 1;
curr_task->fildes_table[fd]->node = findnode_fs("/dev/socket");
/* file doesn't exist! */
if (curr_task->fildes_table[fd]->node == NULL) {
/* tidy up the fildescriptor */
kfree(curr_task->fildes_table[fd], sizeof(fildes_t));
curr_task->fildes_table[fd] = NULL;
return -ENOENT;
}
return fd;
}
@ -157,13 +244,26 @@ static int sys_accept(int s, struct sockaddr* addr, socklen_t* addrlen)
static int sys_close(int fd)
{
int check;
task_t* curr_task = per_core(current_task);
if (BUILTIN_EXPECT(fd >= NR_OPEN, 0))
return -EINVAL;
/* fd is negative or greater than the maximum allowable number */
if (BUILTIN_EXPECT((fd >= NR_OPEN) || (fd < 0), 0))
return -EBADF;
/* fd is not an active, valid file descriptor. */
if (curr_task->fildes_table[fd] == NULL)
return -EBADF;
/*
* The close() call deletes a descriptor from the per-process object
* reference table. If this is the last reference to the underlying
* object, the object will be deactivated.
*/
if (curr_task->fildes_table[fd]->count == 1) {
close_fs(curr_task->fildes_table[fd]);
check = close_fs(curr_task->fildes_table[fd]);
/* close command failed -> return check = errno */
if (BUILTIN_EXPECT(check < 0, 0))
return check;
kfree(curr_task->fildes_table[fd], sizeof(fildes_t));
curr_task->fildes_table[fd] = NULL;
} else {
@ -178,30 +278,42 @@ static int sys_close(int fd)
static int sys_lseek(int fd, off_t pos, int origin)
{
int ret = -EINVAL;
fildes_t* file;
task_t* curr_task = per_core(current_task);
if (BUILTIN_EXPECT(fd >= NR_OPEN, 0))
return -EINVAL;
/* fd is negative or greater than the maximum allowable number */
if (BUILTIN_EXPECT((fd >= NR_OPEN) || (fd < 0), 0))
return -EBADF;
/* fd is not an active, valid file descriptor. */
if (curr_task->fildes_table[fd] == NULL)
return -EBADF;
file = per_core(current_task)->fildes_table[fd];
if (BUILTIN_EXPECT(!((file->node->type == FS_FILE)
|| (file->node->type == FS_CHARDEVICE)), 0))
return -EINVAL;
/* TODO: in case of Fildes is associated with a pipe, socket, or FIFO. return ESPIPE */
/* TODO: The seek location is too large to be stored in an object of type off_t. return EOVERFLOW*/
switch(origin)
{
{
case SEEK_SET: { /* set file offset to offset */
file->offset = pos;
ret = pos;
/* The seek location is negative. */
if (ret < 0)
return -EINVAL;
curr_task->fildes_table[fd]->offset = ret;
ret = 0;
break;
}
case SEEK_CUR: { /* set file offset to current plus offset */
ret = pos + file->offset;
ret = pos + curr_task->fildes_table[fd]->offset;
/* The seek location is negative. */
if (ret < 0)
return -EINVAL;
break;
}
case SEEK_END: { /* set file offset to EOF plus offset */
file->offset = pos + file->node->block_size;
ret = pos + curr_task->fildes_table[fd]->node->block_size;
/* The seek location is negative. */
if (ret < 0)
return -EINVAL;
curr_task->fildes_table[fd]->offset = ret;
ret = 0;
break;
}
@ -209,6 +321,7 @@ static int sys_lseek(int fd, off_t pos, int origin)
ret = -EINVAL;
break;
}
return ret;
}
@ -217,12 +330,19 @@ static int sys_dup(int fd)
task_t* curr_task = per_core(current_task);
int new_fd;
/* fd is negative or greater than the maximum allowable number */
if (BUILTIN_EXPECT((fd >= NR_OPEN) || (fd < 0), 0))
return -EBADF;
/* fd is not an active, valid file descriptor. */
if (curr_task->fildes_table[fd] == NULL)
return -EBADF;
/* Get a free file descriptor */
new_fd = get_fildes();
/* validate the file descriptor */
if (BUILTIN_EXPECT((new_fd >= NR_OPEN) || (fd < 0), 0))
return new_fd; /* in this case fd = errno */
curr_task->fildes_table[new_fd] = curr_task->fildes_table[fd];
curr_task->fildes_table[fd]->count++;
@ -233,18 +353,26 @@ static int sys_dup2(int fd, int fd2)
{
task_t* curr_task = per_core(current_task);
/* fd and fd2 is negative or greater than the maximum allowable number */
if (BUILTIN_EXPECT((fd >= NR_OPEN) || (fd < 0), 0))
return -EBADF;
if (BUILTIN_EXPECT((fd2 >= NR_OPEN) || (fd2 < 0), 0))
return -EBADF;
/* fd is not an active, valid file descriptor. */
if (curr_task->fildes_table[fd] == NULL)
return -EBADF;
if (fd == fd2)
/* If fd and fd2 are equal, then dup2() just returns fd2 */
if (fd == fd2)
return fd2;
/*
* if descriptor fd2 is already in use, it is first deallocated
* as if a close(2) call had been done first
*/
if (curr_task->fildes_table[fd2] != NULL)
sys_close(fd2);
curr_task->fildes_table[fd2] = curr_task->fildes_table[fd];
curr_task->fildes_table[fd]->count++;
@ -296,9 +424,7 @@ int syscall_handler(uint32_t sys_nr, ...)
int fd = va_arg(vl, int);
const char* buf = va_arg(vl, const char*);
size_t len = va_arg(vl, size_t);
if (fd >= 0)
ret = write_fs(per_core(current_task)->fildes_table[fd],
(uint8_t*)buf, len);
ret = sys_write(fd, buf, len);
break;
}
case __NR_open: {
@ -310,8 +436,7 @@ int syscall_handler(uint32_t sys_nr, ...)
}
case __NR_close: {
int fd = va_arg(vl, int);
if (fd >= 0)
ret = sys_close(fd);
ret = sys_close(fd);
break;
}
case __NR_dup: {
@ -328,7 +453,6 @@ int syscall_handler(uint32_t sys_nr, ...)
case __NR_stat: {
const char* name = va_arg(vl, const char*);
struct stat* st = va_arg(vl, struct stat*);
ret = sys_stat(name, st);
break;
}
@ -336,17 +460,14 @@ int syscall_handler(uint32_t sys_nr, ...)
int fd = va_arg(vl, int);
const char* buf = va_arg(vl, const char*);
size_t len = va_arg(vl, size_t);
if (fd >= 0)
ret = read_fs(per_core(current_task)->fildes_table[fd],
(uint8_t*)buf, len);
ret = sys_read(fd, buf, len);
break;
}
case __NR_lseek: {
int fd = va_arg(vl, int);
off_t pos = va_arg(vl, off_t);
int origin = va_arg(vl, int);
if (fd >= 0)
ret = sys_lseek(fd, pos, origin);
ret = sys_lseek(fd, pos, origin);
break;
}
case __NR_sbrk: {