Merge branch 'master' into ohligs

This commit is contained in:
Marian Ohligs 2011-08-01 22:35:04 +02:00
commit 429c2a99d7
17 changed files with 272 additions and 213 deletions

View file

@ -59,7 +59,7 @@ void switch_task(uint32_t id);
* - 0 on success
* - -EINVAL (-22) on failure
*/
int create_default_frame(task_t* task, entry_point_t ep, void* arg);
int create_default_frame(task_t* task, internal_entry_point_t ep, void* arg);
/** @brief Register a task's TSS at GDT
*

View file

@ -496,8 +496,8 @@ global apic_lint1
global apic_error
global apic_svr
global tss_switch
tss_switch:
global switch_task
switch_task:
mov eax, [esp+4]
add ax, WORD 5
mov bx, WORD 8

View file

@ -52,23 +52,6 @@ size_t get_stack(uint32_t id)
return (size_t) kstacks[id] + KERNEL_STACK_SIZE - sizeof(size_t);
}
void switch_task(uint32_t id)
{
#if MAX_CORES > 1
/*
* On SMP systems, the task switch on an other could be in progress...
* => we need to check, if the task is still busy
*/
volatile gdt_entry_t* newgdt = (volatile gdt_entry_t*) gdt+id-5;
while (newgdt->access & GDT_FLAG_TSS_BUSY) {
NOP1;
}
#endif
tss_switch(id);
}
int register_task(task_t* task) {
uint16_t sel;
uint32_t id = task->id;
@ -142,7 +125,7 @@ int arch_fork(task_t* task)
return 0;
}
int create_default_frame(task_t* task, entry_point_t ep, void* arg)
int create_default_frame(task_t* task, internal_entry_point_t ep, void* arg)
{
uint16_t cs = 0x08;
uint16_t ds = 0x10;

View file

@ -229,8 +229,8 @@ static void fault_handler(struct state *s)
{
if (s->int_no < 32) {
kputs(exception_messages[s->int_no]);
kprintf(" Exception (%d) at 0x%x:0x%x on core %d, error code 0x%x, eflags 0x%x\n",
s->int_no, s->cs, CORE_ID, s->eip, s->error, s->eflags);
kprintf(" Exception (%d) at 0x%x:0x%x on core %u, error code 0x%x, eflags 0x%x\n",
s->int_no, s->cs, s->eip, CORE_ID, s->error, s->eflags);
/* Now, we signalize that we have handled the interrupt */
if (apic_is_enabled())

View file

@ -258,6 +258,34 @@ again:
return ERR_OK;
}
static void rckemacif_input(struct netif* netif, struct pbuf* p)
{
struct eth_hdr *ethhdr;
/* points to packet payload, which starts with an Ethernet header */
ethhdr = p->payload;
switch (htons(ethhdr->type)) {
/* IP or ARP packet? */
case ETHTYPE_ARP:
case ETHTYPE_IP:
#if PPPOE_SUPPORT
/* PPPoE packet? */
case ETHTYPE_PPPOEDISC:
case ETHTYPE_PPPOE:
#endif /* PPPOE_SUPPORT */
/* full packet send to tcpip_thread to process */
if (mynetif->input(p, mynetif) != ERR_OK) {
LWIP_DEBUGF(NETIF_DEBUG, ("rtl8139if_input: IP input error\n"));
pbuf_free(p);
}
break;
default:
pbuf_free(p);
break;
}
}
static void rckemacif_rx_handler(struct netif* netif, unsigned int write_offset)
{
rckemacif_t* rckemacif = netif->state;
@ -372,7 +400,7 @@ out:
#if ETH_PAD_SIZE
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
#endif
mailbox_ptr_post(&rckemacif->mbox, (void*)p);
rckemacif_input(netif, p);
LINK_STATS_INC(link.recv);
} else {
LWIP_DEBUGF(NETIF_DEBUG, ("rckemacif_rx_inthandler: not enough memory!\n"));
@ -422,48 +450,6 @@ nexttry:
*((volatile unsigned*) (FPGA_BASE + IRQ_RESET + rckemacif->core * 2 * 4)) = (1 << rckemacif->num_emac);
}
err_t rckemacif_wait(struct netif* netif, uint32_t poll)
{
rckemacif_t* rckemacif = netif->state;
struct eth_hdr *ethhdr;
struct pbuf *p = NULL;
err_t err = ERR_OK;
if (poll) {
if (mailbox_ptr_tryfetch(&(rckemacif->mbox), (void**) &p))
return err;
} else {
mailbox_ptr_fetch(&(rckemacif->mbox), (void**) &p);
}
/* points to packet payload, which starts with an Ethernet header */
ethhdr = p->payload;
//LWIP_DEBUGF(NETIF_DEBUG, ("Got packet of type 0x%x!\n", htons(ethhdr->type)));
switch (htons(ethhdr->type)) {
/* IP or ARP packet? */
case ETHTYPE_ARP:
case ETHTYPE_IP:
#if PPPOE_SUPPORT
/* PPPoE packet? */
case ETHTYPE_PPPOEDISC:
case ETHTYPE_PPPOE:
#endif /* PPPOE_SUPPORT */
/* full packet send to tcpip_thread to process */
if ((err = mynetif->input(p, mynetif)) != ERR_OK) {
LWIP_DEBUGF(NETIF_DEBUG, ("rckemacif_poll: IP input error\n"));
pbuf_free(p);
}
break;
default:
pbuf_free(p);
break;
}
return err;
}
err_t rckemacif_init(struct netif* netif)
{
rckemacif_t* rckemacif;
@ -516,8 +502,6 @@ err_t rckemacif_init(struct netif* netif)
memset(rckemacif->tx_buffer, 0x00, 0x20);
memset(rckemacif->tx_buffer + 0x20, 0xDA, BUFFER_SIZE - 0x20);
rckemacif->tx_buffer_max = CLINE_PACKETS(BUFFER_SIZE) - 1;
mailbox_ptr_init(&rckemacif->mbox);
netif->state = rckemacif;
/* Depending on core location read own private data

View file

@ -21,7 +21,6 @@
#define __HAVE_RCKEMAC_H__
#include <metalsvm/stddef.h>
#include <metalsvm/mailbox.h>
#if defined(CONFIG_LWIP) && defined(CONFIG_ROCKCREEK)
@ -40,17 +39,8 @@ typedef struct rckemacif {
void* irq_address;
uint32_t core;
uint32_t num_emac;
mailbox_ptr_t mbox;
} rckemacif_t;
/*
* Wait for incoming messages.
*
* poll = 0 : wait blocks until a message is received
* poll != 0: non-blocking wait
*/
err_t rckemacif_wait(struct netif* netif, uint32_t poll);
/*
* Initialize the eMAC network driver
*/

View file

@ -110,8 +110,7 @@ static err_t rtl8139if_output(struct netif* netif, struct pbuf* p)
return ERR_OK;
}
#if 0
void rtl8139if_input(struct netif* netif, struct pbuf* p)
static void rtl8139if_input(struct netif* netif, struct pbuf* p)
{
struct eth_hdr *ethhdr;
@ -138,7 +137,6 @@ void rtl8139if_input(struct netif* netif, struct pbuf* p)
break;
}
}
#endif
static void rtl_rx_inthandler(struct netif* netif)
{
@ -175,8 +173,7 @@ static void rtl_rx_inthandler(struct netif* netif)
#if ETH_PAD_SIZE
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
#endif
mailbox_ptr_post(&rtl8139if->mbox, (void*)p);
//rtl8139if_input(netif, p);
rtl8139if_input(netif, p);
LINK_STATS_INC(link.recv);
} else {
LWIP_DEBUGF(NETIF_DEBUG, ("rtl8139if_rx_inthandler: not enough memory!\n"));
@ -268,46 +265,6 @@ static void rtl8139if_handler(struct state* s)
}
}
err_t rtl8139if_wait(struct netif* netif, uint32_t poll)
{
rtl1839if_t* rtl8139if = netif->state;
struct eth_hdr *ethhdr;
struct pbuf *p = NULL;
err_t err = ERR_OK;
if (poll) {
if (mailbox_ptr_tryfetch(&(rtl8139if->mbox), (void**) &p))
return err;
} else {
mailbox_ptr_fetch(&(rtl8139if->mbox), (void**) &p);
}
/* points to packet payload, which starts with an Ethernet header */
ethhdr = p->payload;
switch (htons(ethhdr->type)) {
/* IP or ARP packet? */
case ETHTYPE_ARP:
case ETHTYPE_IP:
#if PPPOE_SUPPORT
/* PPPoE packet? */
case ETHTYPE_PPPOEDISC:
case ETHTYPE_PPPOE:
#endif /* PPPOE_SUPPORT */
/* full packet send to tcpip_thread to process */
if ((err = mynetif->input(p, mynetif)) != ERR_OK) {
LWIP_DEBUGF(NETIF_DEBUG, ("rtl8139if_poll: IP input error\n"));
pbuf_free(p);
}
break;
default:
pbuf_free(p);
break;
}
return err;
}
err_t rtl8139if_init(struct netif* netif)
{
rtl1839if_t* rtl8139if;
@ -348,7 +305,6 @@ err_t rtl8139if_init(struct netif* netif)
rtl8139if->tx_buffer[2] = rtl8139if->tx_buffer[1] + 4096;
rtl8139if->tx_buffer[3] = rtl8139if->tx_buffer[2] + 4096;
mailbox_ptr_init(&rtl8139if->mbox);
netif->state = rtl8139if;
mynetif = netif;

View file

@ -23,7 +23,8 @@
#define __HAVE_RTL8139_H__
#include <metalsvm/stddef.h>
#include <metalsvm/mailbox.h>
#include <metalsvm/spinlock.h>
#if defined(CONFIG_LWIP) && defined(CONFIG_PCI)
// the registers are at the following places
@ -226,17 +227,8 @@ typedef struct rtl1839if {
uint32_t tx_complete;
uint16_t rx_pos;
uint8_t tx_inuse[4];
mailbox_ptr_t mbox;
} rtl1839if_t;
/*
* Wait for incoming messages.
*
* poll = 0 : wait blocks until a message is received
* poll != 0: non-blocking wait
*/
err_t rtl8139if_wait(struct netif* netif, uint32_t poll);
/*
* Initialize the network driver for the RealTek RTL8139 family
*/

View file

@ -36,6 +36,7 @@ typedef unsigned int tid_t;
#define per_core(name) name
#define DECLARE_PER_CORE(type, name) extern type name;
#define DEFINE_PER_CORE(type, name, def_value) type name = def_value;
#define DEFINE_PER_CORE_STATIC(type, name, def_value) static type name = def_value;
#define CORE_ID 0
#else
#define per_core(name) (*__get_percore_##name())
@ -51,6 +52,16 @@ typedef unsigned int tid_t;
}
#define DEFINE_PER_CORE(type, name, def_value) \
aligned_##name name[MAX_CORES] = {[0 ... MAX_CORES-1] = {def_value}};
#define DEFINE_PER_CORE_STATIC(type, name, def_value) \
typedef struct { type var __attribute__ ((aligned (CACHE_LINE))); } aligned_##name;\
static aligned_##name name[MAX_CORES] = {[0 ... MAX_CORES-1] = {def_value}}; \
inline static type* __get_percore_##name(void) {\
type* ret; \
uint32_t flags = irq_nested_disable(); \
ret = &(name[smp_id()].var); \
irq_nested_enable(flags);\
return ret; \
}
#define CORE_ID smp_id()
#endif

View file

@ -42,17 +42,19 @@ extern "C" {
#endif
#define TASK_INVALID 0
#define TASK_READY 1
#define TASK_READY 1
#define TASK_RUNNING 2
#define TASK_BLOCKED 3
#define TASK_FINISHED 4
#define TASK_IDLE 5
#define TASK_IDLE 5
#define TASK_DEFAULT_FLAGS 0
#define TASK_FPU_INIT (1 << 0)
#define TASK_FPU_USED (1 << 1)
#define TASK_DEFAULT_FLAGS 0
#define TASK_FPU_INIT (1 << 0)
#define TASK_FPU_USED (1 << 1)
#define TASK_SWITCH_IN_PROGESS (1 << 2)
typedef int (STDCALL *entry_point_t)(void*);
typedef int (*entry_point_t)(void*);
typedef int (STDCALL *internal_entry_point_t)(void*);
struct page_dir;
/* @brief The task_t structure */

View file

@ -48,8 +48,6 @@
void echo_init(void);
void ping_init(void);
static volatile int done = 0;
/*
* Note that linker symbols are not variables, they have no memory allocated for
* maintaining a value, rather their address is their value.
@ -70,17 +68,42 @@ int lowlevel_init(void)
}
#if defined(CONFIG_LWIP) && (defined(CONFIG_PCI) || defined(CONFIG_ROCKCREEK))
static tid_t netid;
static struct netif* default_netif = NULL;
static volatile uint32_t lwip_initialized = 0;
int STDCALL network_task(void* arg)
static void tcp_init_ok(void* e)
{
struct netif netif;
kputs("TCP/IP init COMPLETE!!\n");
lwip_initialized = 1;
}
#endif
int network_init(void)
{
#if defined(CONFIG_LWIP) && (defined(CONFIG_PCI) || defined(CONFIG_ROCKCREEK))
struct ip_addr ipaddr;
struct ip_addr netmask;
struct ip_addr gw;
kputs("Network task is started\n");
kputs("Initialize network...\n");
// Initialize lwIP modules
tcpip_init(tcp_init_ok, NULL);
while(!lwip_initialized) {
reschedule();
}
// Set up the lwIP network interface
// Allocate and configure netif
default_netif = (struct netif *) mem_malloc(sizeof(struct netif));
if(default_netif == NULL)
{
kprintf("ERROR: Out of memory for default netif\n");
return -ENOMEM;
}
memset(default_netif, 0x00, sizeof(struct netif));
#ifdef CONFIG_ROCKCREEK
/* Set network address variables */
IP4_ADDR(&gw, 192,168,4,254);
@ -88,7 +111,7 @@ int STDCALL network_task(void* arg)
IP4_ADDR(&netmask, 255,255,255,0);
/* Bring up the network interface */
if (!netif_add(&netif, &ipaddr, &netmask, &gw, NULL, rckemacif_init, ethernet_input)) {
if (!netif_add(default_netif, &ipaddr, &netmask, &gw, NULL, rckemacif_init, tcpip_input)) {
#else
/* Clear network address because we use DHCP to get an ip address */
IP4_ADDR(&gw, 0,0,0,0);
@ -96,82 +119,61 @@ int STDCALL network_task(void* arg)
IP4_ADDR(&netmask, 0,0,0,0);
/* Bring up the network interface */
if (!netif_add(&netif, &ipaddr, &netmask, &gw, NULL, rtl8139if_init, ethernet_input)) {
if (!netif_add(default_netif, &ipaddr, &netmask, &gw, NULL, rtl8139if_init, tcpip_input)) {
#endif
kputs("Unable to add network interface\n");
return -ENODEV;
}
netif_set_default(&netif);
netif_set_up(&netif);
netif_set_default(default_netif);
netif_set_up(default_netif);
/* test if interface is really up */
if (!netif_is_up(&netif)) {
if (!netif_is_up(default_netif)) {
kputs("network interface is not up\n");
return -ENODEV;
}
#ifndef CONFIG_ROCKCREEK
kprintf("Starting DHCPCD...\n");
dhcp_start(&netif);
dhcp_start(default_netif);
int mscnt = 0;
/* wait for ip address */
while(!netif.ip_addr.addr) {
rtl8139if_wait(&netif, 1);
reschedule();
while(!default_netif->ip_addr.addr) {
sys_msleep(DHCP_FINE_TIMER_MSECS);
dhcp_fine_tmr();
mscnt += DHCP_FINE_TIMER_MSECS;
if (mscnt >= DHCP_COARSE_TIMER_SECS*1000) {
dhcp_coarse_tmr();
mscnt = 0;
}
}
#else
mmnif_open();
//mmnif_open();
#endif
// start echo and ping server
echo_init();
ping_init();
while(!done) {
#ifdef CONFIG_PCI
rtl8139if_wait(&netif, 0);
#elif defined(CONFIG_ROCKCREEK)
rckemacif_wait(&netif, 0);
#endif
}
#ifndef CONFIG_ROCKCREEK
dhcp_release(&netif);
dhcp_stop(&netif);
#endif
return 0;
}
#endif
int network_shutdown(void)
{
#if defined(CONFIG_LWIP) && defined(CONFIG_ROCKCREEK)
mmnif_close();
//mmnif_close();
#elif defined(CONFIG_LWIP) && defined(CONFIG_PCI)
dhcp_release(default_netif);
dhcp_stop(default_netif);
#endif
done = 1;
mem_free(default_netif);
default_netif = NULL;
return 0;
}
static void tcp_init_ok(void* e)
{
kprintf("TCP/IP init COMPLETE!!");
}
int network_init(void)
{
int ret = 0;
#if defined(CONFIG_LWIP)
// Initialize lwIP modules
tcpip_init(tcp_init_ok, NULL);
#endif
#if defined(CONFIG_LWIP) && (defined(CONFIG_PCI) || defined(CONFIG_ROCKCREEK))
ret = create_kernel_task(&netid, network_task, NULL);
#endif
return ret;
}

View file

@ -212,11 +212,11 @@ ping_thread(void *arg)
lwip_setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
for(i=0; i<10; i++) {
for(i=0; i<5; i++) {
ping_target = PING_TARGET;
if (ping_send(s, &ping_target) == ERR_OK) {
LWIP_DEBUGF( PING_DEBUG, ("ping: send "));
LWIP_DEBUGF( PING_DEBUG, ("ping: send on core %d to " , CORE_ID));
ip_addr_debug_print(PING_DEBUG, &ping_target);
LWIP_DEBUGF( PING_DEBUG, ("\n"));

View file

@ -53,6 +53,7 @@ static task_t task_table[MAX_TASKS] = { \
static spinlock_irqsave_t table_lock = SPINLOCK_IRQSAVE_INIT;
DEFINE_PER_CORE(task_t*, current_task, task_table+0);
DEFINE_PER_CORE_STATIC(task_t*, old_task, NULL);
/** @brief helper function for the assembly code to determine the current task
* @return Pointer to the task_t structure of current task
@ -171,6 +172,24 @@ void NORETURN abort(void) {
do_exit(-1);
}
/*
* @brief: if the task switch is finished, we reset
* the TASK_SWITCH_IN_PROGRESS bit
*/
inline static void task_switch_finished(void)
{
uint32_t flags = irq_nested_disable();
// do we already reset the TASK_SWITCH_IN_PROGRESS bit?
task_t* old = per_core(old_task);
if (old) {
old->flags &= ~TASK_SWITCH_IN_PROGESS;
per_core(old_task) = NULL;
}
irq_nested_enable(flags);
}
/** @brief Create a task with a specific entry point
*
* @param id Pointer to a tid_t struct were the id shall be set
@ -180,7 +199,7 @@ void NORETURN abort(void) {
* - 0 on success
* - -ENOMEM (-12) or -EINVAL (-22) on failure
*/
static int create_task(tid_t* id, entry_point_t ep, void* arg)
static int create_task(tid_t* id, internal_entry_point_t ep, void* arg)
{
task_t* curr_task;
int ret = -ENOMEM;
@ -233,7 +252,6 @@ create_task_out:
return ret;
}
int sys_fork(void)
{
int ret = -ENOMEM;
@ -300,6 +318,10 @@ int sys_fork(void)
// Leave the function without releasing the locks
// because the locks are already released
// by the parent task!
// first switch to the new current task
// => signalizes a successful task switch
task_switch_finished();
return 0;
}
@ -318,15 +340,54 @@ create_task_out:
return ret;
}
int create_kernel_task(tid_t* id, entry_point_t ep, void* arg)
/** @brief Structure which keeps all
* relevant data for a new kernel task to start */
typedef struct {
/// entry point of the kernel task
entry_point_t func;
/// arguments
void* args;
} kernel_args_t;
/** @brief This call is used to adapt create_task calls
* which want to have a start function and argument list */
static int STDCALL kernel_entry(void* args)
{
return create_task(id, ep, arg);
int ret;
kernel_args_t* kernel_args = (kernel_args_t*) args;
// first switch to the new current task
// => signalizes a successful task switch
task_switch_finished();
if (BUILTIN_EXPECT(!kernel_args, 0))
return -EINVAL;
ret = kernel_args->func(kernel_args->args);
kfree(kernel_args, sizeof(kernel_args_t));
return ret;
}
int create_kernel_task(tid_t* id, entry_point_t ep, void* args)
{
kernel_args_t* kernel_args;
kernel_args = kmalloc(sizeof(kernel_args_t));
if (BUILTIN_EXPECT(!kernel_args, 0))
return -ENOMEM;
kernel_args->func = ep;
kernel_args->args = args;
return create_task(id, kernel_entry, kernel_args);
}
#define MAX_ARGS (PAGE_SIZE - 2*sizeof(int) - sizeof(vfs_node_t*))
/** @brief Structure which keeps all
* relevant data for a new task to start */
* relevant data for a new user task to start */
typedef struct {
/// Points to the node with the executable in the file system
vfs_node_t* node;
@ -543,7 +604,20 @@ invalid:
* which want to have a start function and argument list */
static int STDCALL user_entry(void* arg)
{
return load_task((load_args_t*) arg);
int ret;
// first switch to the new current task
// => signalizes a successful task switch
task_switch_finished();
if (BUILTIN_EXPECT(!arg, 0))
return -EINVAL;
ret = load_task((load_args_t*) arg);
kfree(arg, sizeof(load_args_t));
return ret;
}
/** @brief Luxus-edition of create_user_task functions. Just call with an exe name
@ -732,14 +806,14 @@ int block_task(tid_t id)
spinlock_irqsave_lock(&table_lock);
if ((task_table[id].status == TASK_RUNNING) || (task_table[id].status == TASK_READY)) {
if ((task_table[id].status == TASK_RUNNING) || (task_table[id].status == TASK_READY)) {
task_table[id].status = TASK_BLOCKED;
ret = 0;
} else kprintf("Unable to block task %d!\n", id);
spinlock_irqsave_unlock(&table_lock);
spinlock_irqsave_unlock(&table_lock);
return ret;
return ret;
}
/** @brief _The_ scheduler procedure
@ -753,13 +827,18 @@ void scheduler(void)
unsigned int i;
unsigned int new_id;
// let's play it save
// => check if we already signalizes that the previous switch
// is finished
task_switch_finished();
#if MAX_CORES > 1
spinlock_irqsave_lock(&table_lock);
#endif
orig_task = curr_task = per_core(current_task);
/* signalize that this task could be reused */
/* signalizes that this task could be reused */
if (curr_task->status == TASK_FINISHED)
curr_task->status = TASK_INVALID;
@ -772,16 +851,26 @@ void scheduler(void)
for(i=1, new_id=(curr_task->id + 1) % MAX_TASKS;
i<MAX_TASKS; i++, new_id=(new_id+1) % MAX_TASKS)
{
if (task_table[new_id].status == TASK_READY) {
if (curr_task->status == TASK_RUNNING)
if ((task_table[new_id].status == TASK_READY) && !(task_table[new_id].flags & TASK_SWITCH_IN_PROGESS)) {
if (curr_task->status == TASK_RUNNING) {
curr_task->status = TASK_READY;
curr_task->flags |= TASK_SWITCH_IN_PROGESS;
per_core(old_task) = curr_task;
} else per_core(old_task) = NULL;
task_table[new_id].status = TASK_RUNNING;
curr_task = per_core(current_task) = task_table+new_id;
goto get_task_out;
}
//if ((task_table[new_id].status == TASK_READY) && (task_table[new_id].flags & TASK_SWITCH_IN_PROGESS))
// kprintf("task switch %d is in progress\n", new_id);
}
// old task will never rescheduled
per_core(old_task) = NULL;
if ((curr_task->status == TASK_RUNNING) || (curr_task->status == TASK_IDLE))
goto get_task_out;
@ -798,8 +887,10 @@ get_task_out:
spinlock_irqsave_unlock(&table_lock);
#endif
if (curr_task != orig_task)
if (curr_task != orig_task) {
switch_task(new_id);
task_switch_finished();
}
}
void reschedule(void)

View file

@ -39,7 +39,7 @@ static sem_t consuming, producing;
static mailbox_int32_t mbox;
static int val = 0;
static int STDCALL consumer(void* arg)
static int consumer(void* arg)
{
int i, m = 0;
@ -58,7 +58,7 @@ static int STDCALL consumer(void* arg)
return 0;
}
static int STDCALL producer(void* arg)
static int producer(void* arg)
{
int i;
int mail[5] = {1, 2, 3, 4, 5};
@ -78,7 +78,7 @@ static int STDCALL producer(void* arg)
return 0;
}
static int STDCALL foo(void* arg)
static int foo(void* arg)
{
int i;
@ -94,7 +94,7 @@ static int STDCALL foo(void* arg)
}
#ifdef CONFIG_ROCKCREEK
int STDCALL mail_ping(void* arg) {
int mail_ping(void* arg) {
int i;
for(i=0; i<20; i++) {
@ -107,7 +107,7 @@ int STDCALL mail_ping(void* arg) {
}
#endif
static int STDCALL join_test(void* arg)
static int join_test(void* arg)
{
tid_t id, ret;
int result = -1234;
@ -125,7 +125,7 @@ static int STDCALL join_test(void* arg)
}
#if defined(CONFIG_LWIP) && defined(CONFIG_ROCKCREEK)
static int STDCALL server_task(void* e)
static int server_task(void* e)
{
int sockfd, newsockfd, portno, clilen;
char buffer[256];
@ -193,7 +193,7 @@ static int STDCALL server_task(void* e)
return 0;
}
static int STDCALL client_task(void* e)
static int client_task(void* e)
{
char dir[256];
int sd;

View file

@ -74,13 +74,16 @@ sys_msleep(u32_t ms)
}
}
/* sys_thread_new(): Spawns a new thread with given attributes as supportet
/* sys_thread_new(): Spawns a new thread with given attributes as supported
* Note: In MetalSVM this is realized as kernel tasks
*/
sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio)
{
tid_t tmp;
kprintf("Create LWIP task %s\n", name);
create_kernel_task(&tmp,thread,arg);
return tmp;
}
@ -252,4 +255,21 @@ err_t sys_mutex_new(sys_mutex_t * mutex)
return 0;
}
#if SYS_LIGHTWEIGHT_PROT
#if MAX_CORES > 1
static spinlock_irqsave_t lwprot_lock = SPINLOCK_IRQSAVE_INIT;
sys_prot_t sys_arch_protect(void)
{
spinlock_irqsave_lock(&lwprot_lock);
return 0;
}
void sys_arch_unprotect(sys_prot_t pval)
{
spinlock_irqsave_unlock(&lwprot_lock);
}
#endif
#endif
#endif /* !NO_SYS */

View file

@ -4,6 +4,7 @@
#include <asm/tasks.h>
#include <metalsvm/mailbox.h>
#include <metalsvm/errno.h>
#include <asm/irqflags.h>
#define EWOULDBLOCK EAGAIN /* Operation would block */
@ -22,4 +23,24 @@ typedef struct
typedef tid_t* sys_thread_t;
#if SYS_LIGHTWEIGHT_PROT
#if MAX_CORES > 1
typedef uint32_t sys_prot_t;
sys_prot_t sys_arch_protect(void);
void sys_arch_unprotect(sys_prot_t pval);
#else
typedef uint32_t sys_prot_t;
static inline sys_prot_t sys_arch_protect(void)
{
return irq_nested_disable();
}
static inline void sys_arch_unprotect(sys_prot_t pval)
{
irq_nested_enable(pval);
}
#endif
#endif
#endif /* __ARCH_SYS_ARCH_H__ */

View file

@ -3,6 +3,13 @@
#ifndef __LWIPOPTS_H__
#define __LWIPOPTS_H_
/**
* SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain
* critical regions during buffer allocation, deallocation and memory
* allocation and deallocation.
*/
#define SYS_LIGHTWEIGHT_PROT 1
/**
* NO_SYS==1: Provides VERY minimal functionality. Otherwise,
* use lwIP facilities.