Merge branch 'ohligs' into readwrite
Conflicts: drivers/char/null.c drivers/stderr/Makefile drivers/stderr/stderr.c drivers/stdin/Makefile drivers/stdin/stdin.c drivers/stdout/Makefile drivers/stdout/stdout.c fs/initrd.c include/metalsvm/fs_types.h include/metalsvm/tasks_types.h kernel/syscall.c kernel/tasks.c kernel/tests.c newlib/examples/hello.c newlib/examples/test tools/Makefile
This commit is contained in:
commit
0ac95a30b3
40 changed files with 900 additions and 157 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -7,6 +7,7 @@
|
|||
*.img
|
||||
*.a
|
||||
*.log
|
||||
*.swp
|
||||
*.DS_Store
|
||||
*.swp
|
||||
tags
|
||||
|
@ -14,6 +15,7 @@ include/metalsvm/config.h
|
|||
Makefile
|
||||
tools/make_initrd
|
||||
newlib/examples/hello
|
||||
newlib/examples/jacobi
|
||||
newlib/examples/echo
|
||||
newlib/examples/tests
|
||||
newlib/tmp/*
|
||||
|
|
63
arch/x86/include/asm/icc.h
Normal file
63
arch/x86/include/asm/icc.h
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright 2011 Stefan Lankes, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Function and prototypes for MetalSVM's inter core communication
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_ICC_H__
|
||||
#define __ARCH_ICC_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ROCKCREEK
|
||||
|
||||
typedef struct {
|
||||
uint32_t addr; // address of the initrd
|
||||
uint32_t size; // size of the initrd
|
||||
int32_t argc; // number of RCCE arguments
|
||||
char** argv; // RCCE arguments
|
||||
} bootinfo_t;
|
||||
|
||||
extern bootinfo_t* bootinfo;
|
||||
|
||||
typedef struct {
|
||||
uint8_t type;
|
||||
uint8_t tag;
|
||||
uint32_t length;
|
||||
} icc_header_t;
|
||||
|
||||
#define ICC_TYPE_IP (1 << 0)
|
||||
#define ICC_TYPE_SVM (1 << 1)
|
||||
#define ICC_TYPE_PINGREQUEST (1 << 2)
|
||||
#define ICC_TYPE_PINGRESPONSE (1 << 3)
|
||||
|
||||
int icc_init(void);
|
||||
int icc_ping();
|
||||
void icc_check(void);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -39,19 +39,6 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ROCKCREEK
|
||||
typedef struct {
|
||||
uint32_t addr; // address of the initrd
|
||||
uint32_t size; // size of the initrd
|
||||
int32_t argc; // number of RCCE arguments
|
||||
char** argv; // RCCE arguments
|
||||
} bootinfo_t;
|
||||
|
||||
extern bootinfo_t* bootinfo;
|
||||
|
||||
int scc_init(void);
|
||||
#endif
|
||||
|
||||
/** @brief Read out time stamp counter
|
||||
*
|
||||
* The rdtsc asm command puts a 64 bit time stamp value
|
||||
|
|
71
arch/x86/include/asm/tasks_types.h
Normal file
71
arch/x86/include/asm/tasks_types.h
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright 2011 Stefan Lankes, 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 __ARCH_TASKS_TYPES__
|
||||
#define __ARCH_TASKS_TYPES__
|
||||
|
||||
#include <metalsvm/stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
long cwd;
|
||||
long swd;
|
||||
long twd;
|
||||
long fip;
|
||||
long fcs;
|
||||
long foo;
|
||||
long fos;
|
||||
long st_space[20];
|
||||
long status;
|
||||
} i387_fsave_t;
|
||||
|
||||
typedef struct i387_fxsave_struct {
|
||||
unsigned short cwd;
|
||||
unsigned short swd;
|
||||
unsigned short twd;
|
||||
unsigned short fop;
|
||||
long fip;
|
||||
long fcs;
|
||||
long foo;
|
||||
long fos;
|
||||
long mxcsr;
|
||||
long reserved;
|
||||
long st_space[32];
|
||||
long xmm_space[32];
|
||||
long padding[56];
|
||||
} i387_fxsave_t __attribute__ ((aligned (16)));
|
||||
|
||||
union fpu_state {
|
||||
i387_fsave_t fsave;
|
||||
i387_fxsave_t fxsave;
|
||||
};
|
||||
|
||||
static inline void save_fpu_state(union fpu_state* state) {
|
||||
asm volatile ("fsave %0; fwait" : "=m"((*state).fsave));
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -64,16 +64,19 @@ ALIGN 4
|
|||
stublet:
|
||||
; initialize stack pointer.
|
||||
mov esp, default_stack_pointer
|
||||
; enable cache and turn on FPU exceptions
|
||||
mov eax, cr0
|
||||
; enable cache
|
||||
and eax, 0x9fffffff
|
||||
; ...and turn on FPU exceptions
|
||||
or eax, 0x20
|
||||
; enable caching, disable paging and fpu emulation
|
||||
and eax, 0x1ffffffb
|
||||
; ...and turn on FPU exceptions
|
||||
or eax, 0x22
|
||||
mov cr0, eax
|
||||
; clears the current pgd entry
|
||||
xor eax, eax
|
||||
mov cr3, eax
|
||||
; disable SSE support (TODO)
|
||||
mov eax, cr4
|
||||
and eax, 0xfffbf9ff
|
||||
mov cr4, eax
|
||||
; interpret multiboot information
|
||||
extern multiboot_init
|
||||
push ebx
|
||||
|
|
|
@ -74,6 +74,7 @@ extern void isr30(void);
|
|||
extern void isr31(void);
|
||||
|
||||
static void fault_handler(struct state *s);
|
||||
static void fpu_handler(struct state *s);
|
||||
|
||||
/*
|
||||
* This is a very repetitive function... it's not hard, it's
|
||||
|
@ -158,6 +159,26 @@ void isrs_install(void)
|
|||
// install the default handler
|
||||
for(i=0; i<32; i++)
|
||||
irq_install_handler(i, fault_handler);
|
||||
|
||||
// set hanlder for fpu exceptions
|
||||
irq_uninstall_handler(7);
|
||||
irq_install_handler(7, fpu_handler);
|
||||
}
|
||||
|
||||
static void fpu_handler(struct state *s)
|
||||
{
|
||||
task_t* task = per_core(current_task);
|
||||
|
||||
asm volatile ("clts"); // clear the TS flag of cr0
|
||||
if (!(task->flags & TASK_FPU_INIT)) {
|
||||
// use the FPU at the first time => Initialize FPU
|
||||
asm volatile ("finit");
|
||||
task->flags = task->flags|TASK_FPU_INIT|TASK_FPU_USED;
|
||||
} else {
|
||||
// restore the FPU context
|
||||
asm volatile ("frstor %0" :: "m"(task->fpu.fsave)); // restore fpu state
|
||||
task->flags |= TASK_FPU_USED;
|
||||
}
|
||||
}
|
||||
|
||||
/** @brief Exception messages
|
||||
|
@ -189,7 +210,7 @@ static void fault_handler(struct state *s)
|
|||
{
|
||||
if (s->int_no < 32) {
|
||||
kputs(exception_messages[s->int_no]);
|
||||
kputs(" Exception.\n");
|
||||
kprintf(" Exception. (%d)\n", s->int_no);
|
||||
|
||||
/* Now, we signalize that we have handled the interrupt */
|
||||
if (apic_is_enabled())
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <metalsvm/tasks.h>
|
||||
#include <metalsvm/time.h>
|
||||
#include <metalsvm/processor.h>
|
||||
#include <metalsvm/errno.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/irqflags.h>
|
||||
#include <asm/gdt.h>
|
||||
|
@ -39,6 +40,19 @@ uint64_t get_clock_tick(void)
|
|||
return timer_ticks;
|
||||
}
|
||||
|
||||
int sys_times(struct tms* buffer, clock_t* clock)
|
||||
{
|
||||
if (BUILTIN_EXPECT(!buffer, 0))
|
||||
return -EINVAL;
|
||||
if (BUILTIN_EXPECT(!clock, 0))
|
||||
return -EINVAL;
|
||||
|
||||
memset(buffer, 0x00, sizeof(struct tms));
|
||||
*clock = buffer->tms_utime = (clock_t) ((timer_ticks - per_core(current_task)->start_tick) * CLOCKS_PER_SEC / TIMER_FREQ);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handles the timer. In this case, it's very simple: We
|
||||
* increment the 'timer_ticks' variable every time the
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#ifdef CONFIG_ROCKCREEK
|
||||
#include <asm/RCCE_lib.h>
|
||||
#include <asm/SCC_API.h>
|
||||
#include <asm/icc.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -588,7 +589,28 @@ int print_paging_tree(size_t viraddr)
|
|||
|
||||
static void pagefault_handler(struct state *s)
|
||||
{
|
||||
kprintf("PAGE FAULT: Task %u got page fault at %p (irq %d)\n", per_core(current_task)->id, read_cr2(), s->int_no);
|
||||
task_t* task = per_core(current_task);
|
||||
size_t viraddr = read_cr2();
|
||||
size_t phyaddr;
|
||||
|
||||
if ((viraddr >= task->start_heap) && (viraddr <= task->end_heap) && (viraddr > KERNEL_SPACE)) {
|
||||
viraddr = viraddr & 0xFFFFF000;
|
||||
|
||||
phyaddr = get_page();
|
||||
if (BUILTIN_EXPECT(!phyaddr, 0))
|
||||
goto default_handler;
|
||||
|
||||
if (map_region(viraddr, phyaddr, 1, MAP_USER_SPACE) == viraddr) {
|
||||
memset((void*) viraddr, 0x00, PAGE_SIZE);
|
||||
return;
|
||||
}
|
||||
|
||||
kprintf("Could not map 0x%x at 0x%x\n", phyaddr, viraddr);
|
||||
put_page(phyaddr);
|
||||
}
|
||||
|
||||
default_handler:
|
||||
kprintf("PAGE FAULT: Task %u got page fault at %p (irq %d)\n", task->id, viraddr, s->int_no);
|
||||
kprintf("Register state: eax = 0x%x, ebx = 0x%x, ecx = 0x%x, edx = 0x%x, edi = 0x%x, esi = 0x%x, ebp = 0x%x, esp = 0x%x\n",
|
||||
s->eax, s->ebx, s->ecx, s->edx, s->edi, s->esi, s->ebp, s->esp);
|
||||
|
||||
|
@ -640,8 +662,8 @@ int arch_paging_init(void)
|
|||
* Set the page table and page directory entries for the kernel. We map the kernel's physical address
|
||||
* to the same virtual address.
|
||||
*/
|
||||
npages = ((size_t) &kernel_end - (size_t) &kernel_start) / PAGE_SIZE;
|
||||
if ((size_t)&kernel_end % PAGE_SIZE)
|
||||
npages = ((size_t) &kernel_end - (size_t) &kernel_start) >> PAGE_SHIFT;
|
||||
if ((size_t)&kernel_end & (PAGE_SIZE-1))
|
||||
npages++;
|
||||
map_region((size_t)&kernel_start, (size_t)&kernel_start, npages, MAP_KERNEL_SPACE);
|
||||
|
||||
|
@ -686,8 +708,8 @@ int arch_paging_init(void)
|
|||
|
||||
for(i=0; i<mb_info->mods_count; i++, mmodule++) {
|
||||
// map physical address to the same virtual address
|
||||
npages = (mmodule->mod_end - mmodule->mod_start) / PAGE_SIZE;
|
||||
if (mmodule->mod_end % PAGE_SIZE)
|
||||
npages = (mmodule->mod_end - mmodule->mod_start) >> PAGE_SHIFT;
|
||||
if (mmodule->mod_end & (PAGE_SIZE-1))
|
||||
npages++;
|
||||
map_region((size_t) (mmodule->mod_start), (size_t) (mmodule->mod_start), npages, MAP_KERNEL_SPACE);
|
||||
}
|
||||
|
@ -699,17 +721,17 @@ int arch_paging_init(void)
|
|||
map_region(SCC_BOOTINFO, SCC_BOOTINFO, 1, MAP_KERNEL_SPACE);
|
||||
|
||||
// map the initial ramdisk
|
||||
npages = bootinfo->size / PAGE_SIZE;
|
||||
if (bootinfo->size % PAGE_SIZE)
|
||||
npages = bootinfo->size >> PAGE_SHIFT;
|
||||
if (bootinfo->size & (PAGE_SIZE-1))
|
||||
npages++;
|
||||
map_region(bootinfo->addr, bootinfo->addr, npages, MAP_KERNEL_SPACE);
|
||||
|
||||
// map SCC's configuration registers
|
||||
viraddr = map_region(CRB_X0_Y0, CRB_X0_Y0, (CRB_OWN-CRB_X0_Y0+16*1024*1024)/PAGE_SIZE, MAP_KERNEL_SPACE|MAP_NO_CACHE);
|
||||
viraddr = map_region(CRB_X0_Y0, CRB_X0_Y0, (CRB_OWN-CRB_X0_Y0+16*1024*1024) >> PAGE_SHIFT, MAP_KERNEL_SPACE|MAP_NO_CACHE);
|
||||
kprintf("Map configuration registers at 0x%x\n", viraddr);
|
||||
|
||||
// map SCC's message passing buffers
|
||||
viraddr = map_region(MPB_X0_Y0, MPB_X0_Y0, (MPB_OWN-MPB_X0_Y0+16*1024*1024)/PAGE_SIZE, MAP_KERNEL_SPACE|MAP_MPE);
|
||||
viraddr = map_region(MPB_X0_Y0, MPB_X0_Y0, (MPB_OWN-MPB_X0_Y0+16*1024*1024) >> PAGE_SHIFT, MAP_KERNEL_SPACE|MAP_MPE);
|
||||
kprintf("Map message passing buffers at 0x%x\n", viraddr);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
C_source := scc_init.c SCC_API.c iRCCE_admin.c iRCCE_send.c iRCCE_isend.c iRCCE_irecv.c iRCCE_recv.c iRCCE_get.c iRCCE_put.c iRCCE_synch.c RCCE_malloc.c RCCE_shmalloc.c RCCE_debug.c RCCE_qsort.c RCCE_DCMflush.c RCCE_send.c RCCE_recv.c RCCE_flags.c RCCE_comm.c RCCE_put.c RCCE_get.c RCCE_synch.c RCCE_bcast.c RCCE_admin.c # RCCE_power_management.c
|
||||
C_source := icc.c SCC_API.c iRCCE_admin.c iRCCE_send.c iRCCE_isend.c iRCCE_irecv.c iRCCE_recv.c iRCCE_get.c iRCCE_put.c iRCCE_synch.c RCCE_malloc.c RCCE_shmalloc.c RCCE_debug.c RCCE_qsort.c RCCE_DCMflush.c RCCE_send.c RCCE_recv.c RCCE_flags.c RCCE_comm.c RCCE_put.c RCCE_get.c RCCE_synch.c RCCE_bcast.c RCCE_admin.c # RCCE_power_management.c
|
||||
ASM_source :=
|
||||
MODULE := arch_x86_scc
|
||||
|
||||
|
|
|
@ -17,17 +17,22 @@
|
|||
#include <metalsvm/processor.h>
|
||||
#include <metalsvm/errno.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/irqflags.h>
|
||||
#ifdef CONFIG_ROCKCREEK
|
||||
#include <asm/RCCE.h>
|
||||
#include <asm/iRCCE.h>
|
||||
#include <asm/SCC_API.h>
|
||||
|
||||
#ifdef CONFIG_ROCKCREEK
|
||||
#include <asm/icc.h>
|
||||
|
||||
bootinfo_t* bootinfo = (bootinfo_t*) SCC_BOOTINFO;
|
||||
static int num_ues, my_ue;
|
||||
|
||||
/* PSE bit for Pentium+ equals MPE (message buffer enable) flag in RCK! So, use it to create _PAGE_MPB symbol... */
|
||||
#define _CR4_MPE 0x00000800
|
||||
|
||||
/* maximal number of SCC's cores */
|
||||
#define MAX_SCC_CORES (NUM_ROWS*NUM_COLS*NUM_CORES)
|
||||
|
||||
/*
|
||||
* This is the modified MPB program, which is part of the RCCE distribution (src/mpb.c).
|
||||
*
|
||||
|
@ -67,10 +72,9 @@ static int scc_clear(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int scc_init(void)
|
||||
int icc_init(void)
|
||||
{
|
||||
int num_ranks;
|
||||
int i, my_rank;
|
||||
int i;
|
||||
uint64_t start, end, ticks, freq = 533;
|
||||
uint32_t cr4, msg = 0;
|
||||
|
||||
|
@ -109,9 +113,9 @@ int scc_init(void)
|
|||
// enable additional outputs
|
||||
RCCE_debug_set(RCCE_DEBUG_ALL);
|
||||
|
||||
my_rank = RCCE_ue();
|
||||
num_ranks = RCCE_num_ues();
|
||||
kprintf("Got rank %d of %d ranks\n", my_rank, num_ranks);
|
||||
my_ue = RCCE_ue();
|
||||
num_ues = RCCE_num_ues();
|
||||
kprintf("Got rank %d of %d ranks\n", my_ue, num_ues);
|
||||
|
||||
i = ReadConfigReg(CRB_OWN+GLCFG0);
|
||||
kprintf("glcfg0 0x%x\n", i);
|
||||
|
@ -119,7 +123,7 @@ int scc_init(void)
|
|||
RCCE_barrier(&RCCE_COMM_WORLD);
|
||||
|
||||
kputs("RCCE test...\t");
|
||||
if (my_rank == 0)
|
||||
if (my_ue == 0)
|
||||
msg = 0x4711;
|
||||
if (RCCE_bcast((char*) &msg, sizeof(msg), 0, RCCE_COMM_WORLD) == RCCE_SUCCESS)
|
||||
kprintf("successfull! (0x%x)\n", msg);
|
||||
|
@ -131,4 +135,102 @@ int scc_init(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int icc_ping(int ue)
|
||||
{
|
||||
icc_header_t ping_header = {ICC_TYPE_PINGREQUEST, 0, sizeof(uint64_t)};
|
||||
uint64_t tsc;
|
||||
uint32_t flags;
|
||||
iRCCE_SEND_REQUEST send_request;
|
||||
|
||||
if (BUILTIN_EXPECT(ue == my_ue, 0))
|
||||
return -EINVAL;
|
||||
if (BUILTIN_EXPECT((ue < 0) || (ue >= num_ues), 0))
|
||||
return -EINVAL;
|
||||
|
||||
tsc = rdtsc();
|
||||
|
||||
// iRCCE is not thread save => disable interrupts
|
||||
flags = irq_nested_disable();
|
||||
|
||||
iRCCE_isend((char*) &ping_header, sizeof(icc_header_t), ue, NULL);
|
||||
iRCCE_isend((char*) &tsc, sizeof(uint64_t), ue, &send_request);
|
||||
|
||||
// waiting for the completion
|
||||
while(iRCCE_isend_test(&send_request, NULL) != iRCCE_SUCCESS)
|
||||
icc_check(); // oh, we have time to check incoming requests
|
||||
|
||||
irq_nested_enable(flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void interpret_header(icc_header_t* header, int recv_ue)
|
||||
{
|
||||
//kprintf("Got ICC message %d from %d\n", header->type, recv_ue);
|
||||
|
||||
switch(header->type)
|
||||
{
|
||||
case ICC_TYPE_PINGREQUEST: {
|
||||
icc_header_t response = {ICC_TYPE_PINGRESPONSE, 0, sizeof(uint64_t)};
|
||||
iRCCE_RECV_REQUEST recv_req;
|
||||
uint64_t tsc;
|
||||
|
||||
iRCCE_isend((char*) &response, sizeof(icc_header_t), recv_ue, NULL);
|
||||
if (iRCCE_irecv((char*) &tsc, sizeof(uint64_t), recv_ue, &recv_req) != iRCCE_SUCCESS)
|
||||
iRCCE_irecv_wait(&recv_req);
|
||||
|
||||
iRCCE_isend((char*) &tsc, sizeof(uint64_t), recv_ue, NULL);
|
||||
iRCCE_isend_push();
|
||||
}
|
||||
break;
|
||||
case ICC_TYPE_PINGRESPONSE: {
|
||||
uint64_t start, end;
|
||||
iRCCE_RECV_REQUEST recv_req;
|
||||
|
||||
if (iRCCE_irecv((char*) &start, sizeof(uint64_t), recv_ue, &recv_req) != iRCCE_SUCCESS)
|
||||
iRCCE_irecv_wait(&recv_req);
|
||||
end = rdtsc();
|
||||
kprintf("Receive ping response. Ticks: %d\n", end-start);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
kprintf("Receive unknown ICC message (%d)\n", header->type);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* By entering this function, interrupts are already disables
|
||||
* => No race by using the static variables
|
||||
*/
|
||||
void icc_check(void)
|
||||
{
|
||||
static icc_header_t header[MAX_SCC_CORES];
|
||||
static iRCCE_RECV_REQUEST request[MAX_SCC_CORES];
|
||||
static int8_t pending[MAX_SCC_CORES] = {[0 ... MAX_SCC_CORES-1] = 0};
|
||||
int i, ret;
|
||||
|
||||
// pushes the progress of non-blocking communication requests
|
||||
iRCCE_isend_push();
|
||||
iRCCE_irecv_push();
|
||||
|
||||
for(i=0; i<num_ues; i++) {
|
||||
if (i == my_ue)
|
||||
continue;
|
||||
|
||||
if (!pending[i]) {
|
||||
ret = iRCCE_irecv((char*) (header+i), sizeof(icc_header_t), i, request+i);
|
||||
if (ret == iRCCE_SUCCESS)
|
||||
interpret_header(header+i, i);
|
||||
else
|
||||
pending[i] = 1;
|
||||
} else {
|
||||
ret = iRCCE_irecv_test(request+i, NULL);
|
||||
if (ret == iRCCE_SUCCESS) {
|
||||
interpret_header(header+i, i);
|
||||
pending[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -327,7 +327,7 @@ err_t rtl8139if_init(struct netif* netif)
|
|||
memset(rtl8139if, 0, sizeof(rtl1839if_t));
|
||||
|
||||
/* allocate the receive buffer */
|
||||
rtl8139if->rx_buffer = mem_allocation(8192+16, MAP_KERNEL_SPACE|MAP_HEAP|MAP_NO_CACHE);
|
||||
rtl8139if->rx_buffer = mem_allocation(8192+16, MAP_KERNEL_SPACE|MAP_NO_CACHE);
|
||||
if (!(rtl8139if->rx_buffer)) {
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("rtl8139if_init: out of memory\n"));
|
||||
kfree(rtl8139if, sizeof(rtl1839if_t));
|
||||
|
@ -336,7 +336,7 @@ err_t rtl8139if_init(struct netif* netif)
|
|||
memset(rtl8139if->rx_buffer, 0, 8192+16);
|
||||
|
||||
/* allocate the send buffers */
|
||||
rtl8139if->tx_buffer[0] = mem_allocation(4*4096, MAP_KERNEL_SPACE|MAP_HEAP|MAP_NO_CACHE);
|
||||
rtl8139if->tx_buffer[0] = mem_allocation(4*4096, MAP_KERNEL_SPACE|MAP_NO_CACHE);
|
||||
if (!(rtl8139if->tx_buffer[0])) {
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("rtl8139if_init: out of memory\n"));
|
||||
kfree(rtl8139if->rx_buffer, 8192+16);
|
||||
|
@ -482,7 +482,7 @@ err_t rtl8139if_init(struct netif* netif)
|
|||
/* maximum transfer unit */
|
||||
netif->mtu = 1500;
|
||||
/* broadcast capability */
|
||||
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
|
||||
netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
|
||||
/* hardware address length */
|
||||
netif->hwaddr_len = 6;
|
||||
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
* This code based mostly on the online manual http://www.lowlevel.eu/wiki/RTL8139
|
||||
*/
|
||||
|
||||
#ifndef __HAVE_RTL839_H__
|
||||
#define __HAVE_RL8139_H__
|
||||
#ifndef __HAVE_RTL8139_H__
|
||||
#define __HAVE_RTL8139_H__
|
||||
|
||||
#include <metalsvm/stddef.h>
|
||||
#include <metalsvm/mailbox.h>
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
C_source := stderr.c
|
||||
|
||||
MODULE := drivers_stderr
|
||||
|
||||
include $(TOPDIR)/Makefile.inc
|
||||
|
|
|
@ -33,7 +33,11 @@ static ssize_t stderr_read(vfs_node_t* node, uint8_t* buffer, size_t size, off_t
|
|||
|
||||
static ssize_t stderr_write(vfs_node_t* node, uint8_t* buffer, size_t size, off_t offset)
|
||||
{
|
||||
kprintf("\nFehler: %s", buffer);
|
||||
kprintf("\nFehler: ");
|
||||
int i;
|
||||
for (i = 0; i<size; i++, buffer++) {
|
||||
kputchar(*buffer);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
C_source := stdin.c
|
||||
|
||||
MODULE := drivers_stdin
|
||||
|
||||
include $(TOPDIR)/Makefile.inc
|
||||
|
|
|
@ -28,7 +28,9 @@
|
|||
|
||||
static ssize_t stdin_read(vfs_node_t* node, uint8_t* buffer, size_t size, off_t offset)
|
||||
{
|
||||
kprintf("Keine Eingabe implementiert");
|
||||
while(size) {
|
||||
size = kputs((char*)buffer);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
C_source := stdout.c
|
||||
|
||||
MODULE := drivers_stdout
|
||||
|
||||
include $(TOPDIR)/Makefile.inc
|
||||
|
|
|
@ -33,7 +33,10 @@ static ssize_t stdout_read(vfs_node_t* node, uint8_t* buffer, size_t size, off_t
|
|||
|
||||
static ssize_t stdout_write(vfs_node_t* node, uint8_t* buffer, size_t size, off_t offset)
|
||||
{
|
||||
kprintf("%s", buffer);
|
||||
int i;
|
||||
for (i = 0; i<size; i++, buffer++) {
|
||||
kputchar(*buffer);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
|
|
94
fs/initrd.c
94
fs/initrd.c
|
@ -25,6 +25,11 @@
|
|||
#include <asm/multiboot.h>
|
||||
#include <metalsvm/spinlock.h>
|
||||
#include <asm/processor.h>
|
||||
#include <metalsvm/spinlock.h>
|
||||
|
||||
#ifdef CONFIG_ROCKCREEK
|
||||
#include <asm/icc.h>
|
||||
#endif
|
||||
|
||||
static vfs_node_t initrd_root;
|
||||
|
||||
|
@ -93,13 +98,85 @@ static ssize_t initrd_read(vfs_node_t* node, uint8_t* buffer, size_t size, off_t
|
|||
|
||||
static ssize_t initrd_write(vfs_node_t* node, uint8_t* buffer, size_t size, off_t offset)
|
||||
{
|
||||
uint32_t i, writtenbytes = 0, writebytes = 0;
|
||||
char* data = NULL;
|
||||
block_list_t* blist = &node->block_list;
|
||||
char* data = (char*) blist->data[0];
|
||||
|
||||
//////////ACHTUNG keine Überprüfung der Blcoklängen etc.
|
||||
memcpy(data, buffer, size);
|
||||
do {
|
||||
data = (char*) blist->data[0];
|
||||
if ((size - writtenbytes) >= MAX_DATABLOCKS)
|
||||
writebytes = MAX_DATABLOCKS;
|
||||
else
|
||||
writebytes = size - writtenbytes;
|
||||
|
||||
memcpy(data, buffer, writebytes);
|
||||
writtenbytes += writebytes;
|
||||
//kprintf("geschrieben: %i", writtenbytes);
|
||||
|
||||
return size;
|
||||
if (!blist->next) {
|
||||
blist->next = (block_list_t*) kmalloc(sizeof(block_list_t));
|
||||
if (blist->next) {
|
||||
memset(blist->next, 0x00, sizeof(block_list_t));
|
||||
}
|
||||
}
|
||||
|
||||
blist = blist->next;
|
||||
} while(size > writtenbytes);
|
||||
|
||||
return writtenbytes;
|
||||
|
||||
/*
|
||||
uint32_t i, pos = 0, found = 0;
|
||||
char* data = NULL;
|
||||
block_list_t* blist = &node->block_list;
|
||||
|
||||
kprintf("tatsachen offset %i\n", offset);
|
||||
|
||||
// searching for the valid data block
|
||||
if (offset) {
|
||||
pos = offset / node->block_size;
|
||||
offset = offset % node->block_size;
|
||||
}
|
||||
kprintf("Pos: %i, Offset: %i, %i", pos, offset, node->block_size);
|
||||
|
||||
|
||||
|
||||
do {
|
||||
for(i=0; i<MAX_DATABLOCKS && !data; i++) {
|
||||
if (blist->data[i]) {
|
||||
found++;
|
||||
if (found > pos)
|
||||
data = (char*) blist->data[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if all blocks have already been used, we have to allocate a new one
|
||||
if (!blist->next) {
|
||||
blist->next = (block_list_t*) kmalloc(sizeof(block_list_t));
|
||||
if (blist->next) {
|
||||
kprintf("?");
|
||||
memset(blist->next, 0x00, sizeof(block_list_t));
|
||||
}
|
||||
}
|
||||
|
||||
blist = blist->next;
|
||||
} while(blist && !data);
|
||||
|
||||
if (BUILTIN_EXPECT(!data, 0))
|
||||
return 0;
|
||||
*/
|
||||
/*
|
||||
* If the data block is not large engough,
|
||||
* we copy only the rest of the current block.
|
||||
* The user has to restart the write operation
|
||||
* for the next block.
|
||||
*/
|
||||
/* if (offset+size >= node->block_size)
|
||||
size = node->block_size - offset;
|
||||
|
||||
memcpy(data + offset, buffer, size);
|
||||
|
||||
*/ //return size;
|
||||
}
|
||||
|
||||
|
||||
|
@ -268,9 +345,12 @@ int initrd_init(void)
|
|||
tmp = mkdir_fs(fs_root, "dev");
|
||||
/* create the character device "null" */
|
||||
null_init(tmp, "null");
|
||||
//stdin_init(tmp, "stdin");
|
||||
//stdout_init(tmp, "stdout");
|
||||
//stderr_init(tmp, "stderr");
|
||||
/* create the standart input device "stdin" */
|
||||
stdin_init(tmp, "stdin");
|
||||
/* create the standart output device "stdout" */
|
||||
stdout_init(tmp, "stdout");
|
||||
/* create the standart error-output device "stderr" */
|
||||
stderr_init(tmp, "stderr");
|
||||
|
||||
/* For every module.. */
|
||||
#ifdef CONFIG_MULTIBOOT
|
||||
|
|
|
@ -32,6 +32,7 @@ extern "C" {
|
|||
#define KERNEL_STACK_SIZE 8192
|
||||
#define KMSG_SIZE (128*1024)
|
||||
#define PAGE_SIZE 4096
|
||||
#define PAGE_SHIFT 12
|
||||
#define CACHE_LINE 64
|
||||
#define MAILBOX_SIZE 8
|
||||
#define TIMER_FREQ 100 /* in HZ */
|
||||
|
|
|
@ -196,6 +196,9 @@ vfs_node_t* findnode_fs(const char* name);
|
|||
/* @} */
|
||||
|
||||
int null_init(vfs_node_t* node, const char* name);
|
||||
int stdin_init(vfs_node_t* node, const char* name);
|
||||
int stdout_init(vfs_node_t* node, const char* name);
|
||||
int stderr_init(vfs_node_t* node, const char* name);
|
||||
int initrd_init(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
/*
|
||||
* Copyright 2011 Stefan Lankes, 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.
|
||||
+ * Copyright 2011 Stefan Lankes, 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 __FS_TYPES_H__
|
||||
|
|
|
@ -41,8 +41,8 @@ extern "C" {
|
|||
#define MAP_USER_SPACE (1 << 1)
|
||||
#define MAP_PAGE_TABLE (1 << 2)
|
||||
#define MAP_NO_CACHE (1 << 3)
|
||||
#define MAP_STACK (1 << 4)
|
||||
#define MAP_HEAP (1 << 5)
|
||||
//#define MAP_STACK (1 << 4)
|
||||
//#define MAP_HEAP (1 << 5)
|
||||
#define MAP_CODE (1 << 6)
|
||||
#define MAP_READONLY (1 << 7)
|
||||
#ifdef CONFIG_ROCKCREEK
|
||||
|
|
|
@ -49,6 +49,7 @@ extern "C" {
|
|||
#define __NR_fork 12
|
||||
#define __NR_wait 13
|
||||
#define __NR_execve 14
|
||||
#define __NR_times 15
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -32,6 +32,10 @@
|
|||
#include <metalsvm/stddef.h>
|
||||
#include <metalsvm/tasks_types.h>
|
||||
#include <asm/tasks.h>
|
||||
#include <asm/irqflags.h>
|
||||
#ifdef CONFIG_ROCKCREEK
|
||||
#include <asm/icc.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -134,6 +138,17 @@ int sys_fork(void);
|
|||
*/
|
||||
int sys_execve(const char* fname, char** argv, char** env);
|
||||
|
||||
static inline void check_workqueues(void)
|
||||
{
|
||||
uint32_t flags = irq_nested_disable();
|
||||
|
||||
#ifdef CONFIG_ROCKCREEK
|
||||
icc_check();
|
||||
#endif
|
||||
|
||||
irq_nested_enable(flags);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
#include <metalsvm/spinlock_types.h>
|
||||
#include <metalsvm/fs_types.h>
|
||||
#include <metalsvm/mailbox_types.h>
|
||||
#include <asm/tasks_types.h>
|
||||
#include <metalsvm/fs_types.h>
|
||||
#include <asm/atomic.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -47,6 +49,10 @@ extern "C" {
|
|||
#define TASK_FINISHED 4
|
||||
#define TASK_IDLE 5
|
||||
|
||||
#define TASK_DEFAULT_FLAGS 0
|
||||
#define TASK_FPU_INIT (1 << 0)
|
||||
#define TASK_FPU_USED (1 << 1)
|
||||
|
||||
typedef int (STDCALL *entry_point_t)(void*);
|
||||
struct page_dir;
|
||||
|
||||
|
@ -58,9 +64,9 @@ typedef struct task {
|
|||
uint32_t status;
|
||||
/// Usage in number of pages
|
||||
atomic_int32_t user_usage;
|
||||
/// Avoids concurrent access to the page directory
|
||||
/// Avoids concurrent access to the page directory
|
||||
spinlock_t pgd_lock;
|
||||
/// pointer to the page directory
|
||||
/// pointer to the page directory
|
||||
struct page_dir* pgd;
|
||||
/// Lock for the VMA_list
|
||||
spinlock_t vma_lock;
|
||||
|
@ -68,10 +74,20 @@ typedef struct task {
|
|||
vma_t* vma_list;
|
||||
/// Filedescriptor table
|
||||
fildes_t fildes_table[MAX_FILDES];
|
||||
/// Additional status flags. For instance, to signalize the using of the FPU
|
||||
uint32_t flags;
|
||||
/// starting time/tick of the task
|
||||
uint64_t start_tick;
|
||||
/// Start address of the heap
|
||||
uint32_t start_heap;
|
||||
/// End address of the heap
|
||||
uint32_t end_heap;
|
||||
/// Mail inbox
|
||||
mailbox_wait_msg_t inbox;
|
||||
/// Mail outbox array
|
||||
mailbox_wait_msg_t* outbox[MAX_TASKS];
|
||||
/// FPU state
|
||||
union fpu_state fpu;
|
||||
} __attribute__((packed)) task_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -30,6 +30,26 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef uint32_t clock_t;
|
||||
|
||||
struct tms {
|
||||
clock_t tms_utime;
|
||||
clock_t tms_stime;
|
||||
clock_t tms_cutime;
|
||||
clock_t tms_cstime;
|
||||
};
|
||||
|
||||
#ifndef CLOCKS_PER_SEC
|
||||
// newlib's default value
|
||||
#define CLOCKS_PER_SEC 1000
|
||||
#endif
|
||||
|
||||
/** @brief Determines the time in CLK_TCK's
|
||||
*
|
||||
* System call, which returns the value of time in CLK_TCK's
|
||||
*/
|
||||
int sys_times(struct tms*, clock_t* clock);
|
||||
|
||||
/** @brief Initialize Timer interrupts
|
||||
*
|
||||
* This procedure installs IRQ handlers for timer interrupts
|
||||
|
@ -49,7 +69,13 @@ void timer_wait(unsigned int ticks);
|
|||
*/
|
||||
uint64_t get_clock_tick(void);
|
||||
|
||||
static inline void sleep(unsigned int i) { timer_wait(i*TIMER_FREQ); }
|
||||
/** @brief sleep some seconds
|
||||
*
|
||||
* This function sleeps some seconds
|
||||
*
|
||||
* @paran sec Amount of seconds to wait
|
||||
*/
|
||||
static inline void sleep(unsigned int sec) { timer_wait(sec*TIMER_FREQ); }
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -30,6 +30,9 @@
|
|||
#include <asm/irq.h>
|
||||
#include <asm/irqflags.h>
|
||||
#include <asm/kb.h>
|
||||
#ifdef CONFIG_ROCKCREEK
|
||||
#include <asm/icc.h>
|
||||
#endif
|
||||
|
||||
extern int test_init(void);
|
||||
|
||||
|
@ -90,7 +93,7 @@ int main(void)
|
|||
multitasking_init();
|
||||
mmu_init();
|
||||
#ifdef CONFIG_ROCKCREEK
|
||||
scc_init();
|
||||
icc_init();
|
||||
#endif
|
||||
initrd_init();
|
||||
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#include <metalsvm/tasks.h>
|
||||
#include <metalsvm/string.h>
|
||||
#include <metalsvm/errno.h>
|
||||
#include <metalsvm/spinlock.h>
|
||||
#include <metalsvm/time.h>
|
||||
|
||||
static int sys_read(int fd, const char *buf, size_t len)
|
||||
{
|
||||
|
@ -32,20 +34,16 @@ static int sys_read(int fd, const char *buf, size_t len)
|
|||
(uint8_t*)buf, len,
|
||||
per_core(current_task)->fildes_table[fd].offset);
|
||||
per_core(current_task)->fildes_table[fd].offset += readbytes;
|
||||
/*kprintf("fd:%i, Dateilaenge:%i, Dateiinhalt: %s \n", fd, len, buf);*/
|
||||
//kprintf("fd:%i, Dateilaenge:%i, Dateiinhalt: %s \n", fd, len, buf);
|
||||
/* Beware: still reading above file limit! */
|
||||
return readbytes;
|
||||
}
|
||||
|
||||
|
||||
static int sys_write(int fd, const char *buf, size_t len)
|
||||
{
|
||||
unsigned int wrotebytes;
|
||||
/* per_core(current_task)->fildes_table[fd].node->write = 1; */
|
||||
wrotebytes = write_fs(
|
||||
per_core(current_task)->fildes_table[fd].node,
|
||||
(uint8_t*)buf, len, 0);
|
||||
/* per_core(current_task)->fildes_table[fd].offset); */
|
||||
/* kprintf("ins Dateis. geschr. -- fd:%i, Dateilaenge:%i, Dateiinhalt: %s \n", fd, len, buf); */
|
||||
wrotebytes = write_fs(per_core(current_task)->fildes_table[fd].node, (uint8_t*)buf, len, per_core(current_task)->fildes_table[fd].offset);
|
||||
//kprintf("ins Dateis. geschr. -- fd:%i, Dateilaenge:%i, Schreiblaenge: %i, Dateiinhalt: %s \n", fd, len, wrotebytes, buf);
|
||||
per_core(current_task)->fildes_table[fd].offset += wrotebytes;
|
||||
|
||||
return wrotebytes;
|
||||
|
@ -54,12 +52,12 @@ static int sys_write(int fd, const char *buf, size_t len)
|
|||
static int sys_open(const char* file, int flags, int mode)
|
||||
{
|
||||
int fd;
|
||||
for (fd = 0; fd < MAX_FILDES; fd++) {
|
||||
for (fd = 3; fd < MAX_FILDES; fd++) {
|
||||
if (per_core(current_task)->fildes_table[fd].node == NULL) {
|
||||
per_core(current_task)->fildes_table[fd].node = findnode_fs((char*) file);
|
||||
return fd;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fd >= MAX_FILDES) {
|
||||
kprintf("Unable to create filedescriptor");
|
||||
return -EINVAL;
|
||||
|
@ -73,6 +71,32 @@ static int sys_close(int fd)
|
|||
per_core(current_task)->fildes_table[fd].offset = 0;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static int sys_sbrk(int incr)
|
||||
{
|
||||
task_t* task = per_core(current_task);
|
||||
vma_t* tmp = NULL;
|
||||
int ret;
|
||||
|
||||
spinlock_lock(&task->vma_lock);
|
||||
|
||||
tmp = task->vma_list;
|
||||
while(tmp && !((task->end_heap >= tmp->start) && (task->end_heap <= tmp->end)))
|
||||
tmp = tmp->next;
|
||||
|
||||
ret = (int) task->end_heap;
|
||||
task->end_heap += incr;
|
||||
if (task->end_heap < task->start_heap)
|
||||
task->end_heap = task->start_heap;
|
||||
|
||||
// resize virtual memory area
|
||||
if (tmp && (tmp->end <= task->end_heap))
|
||||
tmp->end = task->end_heap;
|
||||
|
||||
spinlock_unlock(&task->vma_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int syscall_handler(uint32_t sys_nr, ...)
|
||||
|
@ -80,6 +104,8 @@ int syscall_handler(uint32_t sys_nr, ...)
|
|||
int ret = -EINVAL;
|
||||
va_list vl;
|
||||
|
||||
check_workqueues();
|
||||
|
||||
va_start(vl, sys_nr);
|
||||
|
||||
switch(sys_nr)
|
||||
|
@ -92,28 +118,32 @@ 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);
|
||||
kprintf("%s", buf);
|
||||
//ret = sys_read(fd, buf, len);
|
||||
ret = sys_read(fd, buf, len);
|
||||
break;
|
||||
}
|
||||
case __NR_write: {
|
||||
int fd = va_arg(vl, int);
|
||||
const char* buf = va_arg(vl, const char*);
|
||||
size_t len = va_arg(vl, size_t);
|
||||
kprintf("%s", buf);
|
||||
//ret = sys_write(fd, buf, len);
|
||||
ret = sys_write(fd, buf, len);
|
||||
break;
|
||||
}
|
||||
case __NR_open: {
|
||||
const char* file = va_arg(vl, const char*);
|
||||
int flags = va_arg(vl, int);
|
||||
int mode = va_arg(vl, int);
|
||||
//ret = sys_open(file, flags, mode);
|
||||
ret = sys_open(file, flags, mode);
|
||||
break;
|
||||
}
|
||||
case __NR_close: {
|
||||
int fd = va_arg(vl, int);
|
||||
//ret = sys_close(fd);
|
||||
ret = sys_close(fd);
|
||||
break;
|
||||
}
|
||||
case __NR_sbrk: {
|
||||
int incr = va_arg(vl, int);
|
||||
|
||||
ret = sys_sbrk(incr);
|
||||
break;
|
||||
}
|
||||
case __NR_getpid:
|
||||
|
@ -124,7 +154,7 @@ int syscall_handler(uint32_t sys_nr, ...)
|
|||
break;
|
||||
case __NR_wait: {
|
||||
int32_t* status = va_arg(vl, int32_t*);
|
||||
|
||||
|
||||
ret = wait(status);
|
||||
break;
|
||||
}
|
||||
|
@ -136,6 +166,13 @@ int syscall_handler(uint32_t sys_nr, ...)
|
|||
ret = sys_execve(name, argv, env);
|
||||
break;
|
||||
}
|
||||
case __NR_times: {
|
||||
struct tms* buffer = va_arg(vl, struct tms*);
|
||||
clock_t* clock = va_arg(vl, clock_t*);
|
||||
|
||||
ret = sys_times(buffer, clock);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
kputs("invalid system call\n");
|
||||
ret = -ENOSYS;
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include <metalsvm/mailbox.h>
|
||||
#include <metalsvm/syscall.h>
|
||||
#include <metalsvm/fs.h>
|
||||
#include <metalsvm/time.h>
|
||||
#include <asm/apic.h>
|
||||
#include <asm/elf.h>
|
||||
|
||||
|
@ -48,7 +49,7 @@ DEFINE_PER_CORE(task_t*, current_task, NULL);
|
|||
* A task's id will be its position in this array.
|
||||
*/
|
||||
static task_t task_table[MAX_TASKS] = {[0 ... MAX_TASKS-1] = {0, TASK_INVALID, ATOMIC_INIT(0), \
|
||||
SPINLOCK_INIT, NULL, SPINLOCK_INIT, NULL, FS_INIT}};
|
||||
SPINLOCK_INIT, NULL, SPINLOCK_INIT, NULL, FS_INIT, 0, 0, 0, 0}};
|
||||
static spinlock_irqsave_t table_lock = SPINLOCK_IRQSAVE_INIT;
|
||||
|
||||
/** @brief helper function for the assembly code to determine the current task
|
||||
|
@ -67,6 +68,7 @@ int multitasking_init(void) {
|
|||
memset(task_table[0].outbox, 0x00, sizeof(mailbox_wait_msg_t*)*MAX_TASKS);
|
||||
per_core(current_task) = task_table+0;
|
||||
per_core(current_task)->pgd = get_boot_pgd();
|
||||
task_table[0].flags = TASK_DEFAULT_FLAGS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -183,12 +185,20 @@ static int create_task(tid_t* id, entry_point_t ep, void* arg)
|
|||
mailbox_wait_msg_init(&task_table[i].inbox);
|
||||
memset(task_table[i].outbox, 0x00, sizeof(mailbox_wait_msg_t*)*MAX_TASKS);
|
||||
task_table[i].outbox[per_core(current_task)->id] = &per_core(current_task)->inbox;
|
||||
task_table[i].fildes_table[0].node = findnode_fs("/dev/stdin");
|
||||
task_table[i].fildes_table[1].node = findnode_fs("/dev/stdout");
|
||||
task_table[i].fildes_table[2].node = findnode_fs("/dev/stderr");
|
||||
|
||||
|
||||
if (id)
|
||||
*id = i;
|
||||
|
||||
ret = create_default_frame(task_table+i, ep, arg);
|
||||
|
||||
task_table[i].flags = TASK_DEFAULT_FLAGS;
|
||||
task_table[i].start_heap = 0;
|
||||
task_table[i].end_heap = 0;
|
||||
task_table[i].start_tick = get_clock_tick();
|
||||
task_table[i].status = TASK_READY;
|
||||
break;
|
||||
}
|
||||
|
@ -250,6 +260,11 @@ int sys_fork(void)
|
|||
mailbox_wait_msg_init(&task_table[i].inbox);
|
||||
memset(task_table[i].outbox, 0x00, sizeof(mailbox_wait_msg_t*)*MAX_TASKS);
|
||||
task_table[i].outbox[per_core(current_task)->id] = &per_core(current_task)->inbox;
|
||||
task_table[i].flags = per_core(current_task)->flags;
|
||||
memcpy(&(task_table[i].fpu), &(per_core(current_task)->fpu), sizeof(union fpu_state));
|
||||
task_table[i].start_tick = get_clock_tick();
|
||||
task_table[i].start_heap = 0;
|
||||
task_table[i].end_heap = 0;
|
||||
|
||||
ret = arch_fork(task_table+i);
|
||||
|
||||
|
@ -349,8 +364,8 @@ static int load_task(load_args_t* largs)
|
|||
if (!prog_header.virt_addr)
|
||||
continue;
|
||||
|
||||
npages = (prog_header.mem_size / PAGE_SIZE);
|
||||
if (prog_header.mem_size % PAGE_SIZE)
|
||||
npages = (prog_header.mem_size >> PAGE_SHIFT);
|
||||
if (prog_header.mem_size & (PAGE_SIZE-1))
|
||||
npages++;
|
||||
|
||||
addr = get_pages(npages);
|
||||
|
@ -366,6 +381,10 @@ static int load_task(load_args_t* largs)
|
|||
// clear pages
|
||||
memset((void*) prog_header.virt_addr, 0, npages*PAGE_SIZE);
|
||||
|
||||
// set starting point of the heap
|
||||
if (per_core(current_task)->start_heap < prog_header.virt_addr+prog_header.mem_size)
|
||||
per_core(current_task)->start_heap = per_core(current_task)->end_heap = prog_header.virt_addr+prog_header.mem_size;
|
||||
|
||||
// load program
|
||||
read_fs(node, (uint8_t*)prog_header.virt_addr, prog_header.file_size, prog_header.offset);
|
||||
|
||||
|
@ -384,8 +403,8 @@ static int load_task(load_args_t* largs)
|
|||
|
||||
case ELF_PT_GNU_STACK: // Indicates stack executability
|
||||
// create user-level stack
|
||||
npages = DEFAULT_STACK_SIZE / PAGE_SIZE;
|
||||
if (DEFAULT_STACK_SIZE % PAGE_SIZE)
|
||||
npages = DEFAULT_STACK_SIZE >> PAGE_SHIFT;
|
||||
if (DEFAULT_STACK_SIZE & (PAGE_SIZE-1))
|
||||
npages++;
|
||||
|
||||
addr = get_pages(npages);
|
||||
|
@ -472,6 +491,9 @@ static int load_task(load_args_t* largs)
|
|||
|
||||
kfree(largs, sizeof(load_args_t));
|
||||
|
||||
// clear fpu state
|
||||
per_core(current_task)->flags &= ~(TASK_FPU_USED|TASK_FPU_INIT);
|
||||
|
||||
jump_to_user_code(header.entry, stack+offset);
|
||||
|
||||
return 0;
|
||||
|
@ -692,6 +714,8 @@ void scheduler(void)
|
|||
unsigned int i;
|
||||
unsigned int new_id;
|
||||
|
||||
check_workqueues();
|
||||
|
||||
#if MAX_CORES > 1
|
||||
spinlock_irqsave_lock(&table_lock);
|
||||
#endif
|
||||
|
@ -700,6 +724,12 @@ void scheduler(void)
|
|||
if (per_core(current_task)->status == TASK_FINISHED)
|
||||
per_core(current_task)->status = TASK_INVALID;
|
||||
|
||||
/* if the task is using the FPU, we need to save the FPU context */
|
||||
if (per_core(current_task)->flags & TASK_FPU_USED) {
|
||||
save_fpu_state(&(per_core(current_task)->fpu));
|
||||
per_core(current_task)->flags &= ~TASK_FPU_USED;
|
||||
}
|
||||
|
||||
for(i=1, new_id=(per_core(current_task)->id + 1) % MAX_TASKS;
|
||||
i<MAX_TASKS; i++, new_id=(new_id+1) % MAX_TASKS)
|
||||
{
|
||||
|
@ -707,8 +737,8 @@ void scheduler(void)
|
|||
if (per_core(current_task)->status == TASK_RUNNING)
|
||||
per_core(current_task)->status = TASK_READY;
|
||||
task_table[new_id].status = TASK_RUNNING;
|
||||
|
||||
per_core(current_task) = task_table+new_id;
|
||||
|
||||
goto get_task_out;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,9 @@
|
|||
#include <metalsvm/semaphore.h>
|
||||
#include <metalsvm/mailbox.h>
|
||||
#include <metalsvm/syscall.h>
|
||||
#ifdef CONFIG_ROCKCREEK
|
||||
#include <asm/icc.h>
|
||||
#endif
|
||||
|
||||
static sem_t consuming, producing;
|
||||
static mailbox_int32_t mbox;
|
||||
|
@ -83,6 +86,20 @@ static int STDCALL foo(void* arg)
|
|||
return 42;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ROCKCREEK
|
||||
static int STDCALL ping(void* arg)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<20; i++) {
|
||||
icc_ping(1);
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int STDCALL join_test(void* arg)
|
||||
{
|
||||
tid_t id, ret;
|
||||
|
@ -102,7 +119,7 @@ static int STDCALL join_test(void* arg)
|
|||
|
||||
int test_init(void)
|
||||
{
|
||||
char* argv[] = {"/bin/tests", NULL};
|
||||
char* argv[] = {"/bin/hello", NULL};
|
||||
|
||||
//sem_init(&producing, 1);
|
||||
//sem_init(&consuming, 0);
|
||||
|
@ -112,8 +129,10 @@ int test_init(void)
|
|||
//create_kernel_task(NULL, join_test, NULL);
|
||||
//create_kernel_task(NULL, producer, NULL);
|
||||
//create_kernel_task(NULL, consumer, NULL);
|
||||
create_user_task(NULL, "/bin/hello", NULL);
|
||||
//create_user_task(NULL, "/bin/tests", argv);
|
||||
//create_kernel_task(NULL, ping, NULL);
|
||||
//create_user_task(NULL, "/bin/hello", argv);
|
||||
create_user_task(NULL, "/bin/hello", argv);
|
||||
//create_user_task(NULL, "/bin/jacobi", argv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
59
mm/memory.c
59
mm/memory.c
|
@ -29,6 +29,9 @@
|
|||
#ifdef CONFIG_MULTIBOOT
|
||||
#include <asm/multiboot.h>
|
||||
#endif
|
||||
#ifdef CONFIG_ROCKCREEK
|
||||
#include <asm/icc.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 0 => free
|
||||
|
@ -52,8 +55,8 @@ extern const void kernel_end;
|
|||
|
||||
inline static int page_marked(unsigned int i)
|
||||
{
|
||||
unsigned int index = i / 8;
|
||||
unsigned int mod = i % 8;
|
||||
unsigned int index = i >> 3;
|
||||
unsigned int mod = i & 0x7;
|
||||
|
||||
return (bitmap[index] & (1 << mod));
|
||||
}
|
||||
|
@ -65,8 +68,8 @@ inline static int page_unmarked(unsigned int i)
|
|||
|
||||
inline static void page_set_mark(unsigned int i)
|
||||
{
|
||||
unsigned int index = i / 8;
|
||||
unsigned int mod = i % 8;
|
||||
unsigned int index = i >> 3;
|
||||
unsigned int mod = i & 0x7;
|
||||
|
||||
//if (page_marked(i))
|
||||
// kprintf("page %u is alread marked\n", i);
|
||||
|
@ -104,7 +107,7 @@ int mmu_init(void)
|
|||
end_addr = addr + mmap->len;
|
||||
|
||||
while (addr < end_addr) {
|
||||
page_clear_mark(addr / PAGE_SIZE);
|
||||
page_clear_mark(addr >> PAGE_SHIFT);
|
||||
addr += PAGE_SIZE;
|
||||
atomic_int32_inc(&total_pages);
|
||||
atomic_int32_inc(&total_available_pages);
|
||||
|
@ -129,13 +132,13 @@ int mmu_init(void)
|
|||
/*
|
||||
* Mark the mb_info as used.
|
||||
*/
|
||||
page_set_mark((size_t)mb_info / PAGE_SIZE);
|
||||
page_set_mark((size_t)mb_info >> PAGE_SHIFT);
|
||||
atomic_int32_inc(&total_allocated_pages);
|
||||
atomic_int32_dec(&total_available_pages);
|
||||
|
||||
for(i=0; i<mb_info->mods_count; i++, mmodule++) {
|
||||
for(addr=mmodule->mod_start; addr<mmodule->mod_end; addr+=PAGE_SIZE) {
|
||||
page_set_mark(addr / PAGE_SIZE);
|
||||
page_set_mark(addr >> PAGE_SHIFT);
|
||||
atomic_int32_inc(&total_allocated_pages);
|
||||
atomic_int32_dec(&total_available_pages);
|
||||
}
|
||||
|
@ -143,7 +146,7 @@ int mmu_init(void)
|
|||
}
|
||||
#elif defined(CONFIG_ROCKCREEK)
|
||||
for(addr=PRIVATE_MEM1_START; addr<PRIVATE_MEM1_END; addr+=PAGE_SIZE) {
|
||||
page_clear_mark(addr / PAGE_SIZE);
|
||||
page_clear_mark(addr >> PAGE_SHIFT);
|
||||
if (addr > addr + PAGE_SIZE)
|
||||
break;
|
||||
atomic_int32_inc(&total_pages);
|
||||
|
@ -151,7 +154,7 @@ int mmu_init(void)
|
|||
}
|
||||
|
||||
for(addr=PRIVATE_MEM2_START; addr<PRIVATE_MEM2_END; addr+=PAGE_SIZE) {
|
||||
page_clear_mark(addr / PAGE_SIZE);
|
||||
page_clear_mark(addr >> PAGE_SHIFT);
|
||||
if (addr > addr + PAGE_SIZE)
|
||||
break;
|
||||
atomic_int32_inc(&total_pages);
|
||||
|
@ -161,7 +164,7 @@ int mmu_init(void)
|
|||
/*
|
||||
* Mark the bootinfo as used.
|
||||
*/
|
||||
page_set_mark((size_t)bootinfo / PAGE_SIZE);
|
||||
page_set_mark((size_t)bootinfo >> PAGE_SHIFT);
|
||||
atomic_int32_inc(&total_allocated_pages);
|
||||
atomic_int32_dec(&total_available_pages);
|
||||
|
||||
|
@ -170,7 +173,7 @@ int mmu_init(void)
|
|||
* Therefore, we set these pages as used.
|
||||
*/
|
||||
for(addr=bootinfo->addr; addr < bootinfo->addr+bootinfo->size; addr+=PAGE_SIZE) {
|
||||
page_set_mark(addr / PAGE_SIZE);
|
||||
page_set_mark(addr >> PAGE_SHIFT);
|
||||
atomic_int32_inc(&total_allocated_pages);
|
||||
atomic_int32_dec(&total_available_pages);
|
||||
}
|
||||
|
@ -179,19 +182,19 @@ int mmu_init(void)
|
|||
#endif
|
||||
|
||||
kernel_size = (size_t) &kernel_end - (size_t) &kernel_start;
|
||||
if (kernel_size % PAGE_SIZE)
|
||||
kernel_size += PAGE_SIZE - kernel_size % PAGE_SIZE;
|
||||
atomic_int32_add(&total_allocated_pages, kernel_size/PAGE_SIZE);
|
||||
atomic_int32_sub(&total_available_pages, kernel_size/PAGE_SIZE);
|
||||
if (kernel_size & (PAGE_SIZE-1))
|
||||
kernel_size += PAGE_SIZE - (kernel_size & (PAGE_SIZE-1));
|
||||
atomic_int32_add(&total_allocated_pages, kernel_size >> PAGE_SHIFT);
|
||||
atomic_int32_sub(&total_available_pages, kernel_size >> PAGE_SHIFT);
|
||||
|
||||
/* set kernel space as used */
|
||||
for(i=(size_t) &kernel_start / PAGE_SIZE; i < (size_t) &kernel_end / PAGE_SIZE; i++)
|
||||
for(i=(size_t) &kernel_start >> PAGE_SHIFT; i < (size_t) &kernel_end >> PAGE_SHIFT; i++)
|
||||
page_set_mark(i);
|
||||
if ((size_t) &kernel_end % PAGE_SIZE)
|
||||
if ((size_t) &kernel_end & (PAGE_SIZE-1))
|
||||
page_set_mark(i);
|
||||
|
||||
alloc_start = (size_t) &kernel_end / PAGE_SIZE;
|
||||
if ((size_t) &kernel_end % PAGE_SIZE)
|
||||
alloc_start = (size_t) &kernel_end >> PAGE_SHIFT;
|
||||
if ((size_t) &kernel_end & (PAGE_SIZE-1))
|
||||
alloc_start++;
|
||||
|
||||
return paging_init();
|
||||
|
@ -217,7 +220,7 @@ size_t get_pages(uint32_t npages)
|
|||
next_try:
|
||||
while((k < BITMAP_SIZE) && page_marked(i)) {
|
||||
k++;
|
||||
i = (i+1) % BITMAP_SIZE;
|
||||
i = (i+1) & (BITMAP_SIZE-1);
|
||||
}
|
||||
|
||||
if (k >= BITMAP_SIZE)
|
||||
|
@ -225,7 +228,7 @@ next_try:
|
|||
|
||||
for(j=1; (j<npages) && (i+j < BITMAP_SIZE) && (k < BITMAP_SIZE); j++, k++) {
|
||||
if (page_marked(i+j)) {
|
||||
i = (i+j) % BITMAP_SIZE;
|
||||
i = (i+j) & (BITMAP_SIZE-1);
|
||||
goto next_try;
|
||||
}
|
||||
}
|
||||
|
@ -259,7 +262,7 @@ oom:
|
|||
|
||||
int put_page(size_t phyaddr)
|
||||
{
|
||||
uint32_t index = phyaddr / PAGE_SIZE;
|
||||
uint32_t index = phyaddr >> PAGE_SHIFT;
|
||||
|
||||
if (BUILTIN_EXPECT(!phyaddr, 0))
|
||||
return -EINVAL;
|
||||
|
@ -277,9 +280,9 @@ int put_page(size_t phyaddr)
|
|||
void* mem_allocation(size_t sz, uint32_t flags)
|
||||
{
|
||||
size_t phyaddr, viraddr;
|
||||
uint32_t npages = sz / PAGE_SIZE;
|
||||
uint32_t npages = sz >> PAGE_SHIFT;
|
||||
|
||||
if (sz % PAGE_SIZE)
|
||||
if (sz & (PAGE_SIZE-1))
|
||||
npages++;
|
||||
|
||||
phyaddr = get_pages(npages);
|
||||
|
@ -293,7 +296,7 @@ void* mem_allocation(size_t sz, uint32_t flags)
|
|||
|
||||
void* kmalloc(size_t sz)
|
||||
{
|
||||
return mem_allocation(sz, MAP_KERNEL_SPACE|MAP_HEAP);
|
||||
return mem_allocation(sz, MAP_KERNEL_SPACE);
|
||||
}
|
||||
|
||||
void kfree(void* addr, size_t sz)
|
||||
|
@ -304,8 +307,8 @@ void kfree(void* addr, size_t sz)
|
|||
if (BUILTIN_EXPECT(!addr && !sz, 0))
|
||||
return;
|
||||
|
||||
npages = sz / PAGE_SIZE;
|
||||
if (sz % PAGE_SIZE)
|
||||
npages = sz >> PAGE_SHIFT;
|
||||
if (sz & (PAGE_SIZE-1))
|
||||
npages++;
|
||||
|
||||
spinlock_lock(&bitmap_lock);
|
||||
|
@ -316,7 +319,7 @@ void kfree(void* addr, size_t sz)
|
|||
if (!phyaddr)
|
||||
continue;
|
||||
|
||||
index = phyaddr / PAGE_SIZE;
|
||||
index = phyaddr >> PAGE_SHIFT;
|
||||
page_clear_mark(index);
|
||||
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ NEWLIB = ../x86/i586-metalsvm-elf32
|
|||
MAKE = make
|
||||
STRIP_DEBUG = --strip-debug
|
||||
KEEP_DEBUG = --only-keep-debug
|
||||
LDFLAGS =
|
||||
|
||||
# other implicit rules
|
||||
%.o : %.c
|
||||
|
@ -10,7 +11,13 @@ KEEP_DEBUG = --only-keep-debug
|
|||
|
||||
default: all
|
||||
|
||||
all: hello tests
|
||||
all: hello tests jacobi
|
||||
|
||||
jacobi: jacobi.o
|
||||
$(CC_FOR_TARGET) -T link.ld -o $@ $(LDFLAGS) $< -lm
|
||||
$(OBJCOPY_FOR_TARGET) $(KEEP_DEBUG) $@ $@.sym
|
||||
$(OBJCOPY_FOR_TARGET) $(STRIP_DEBUG) $@
|
||||
chmod a-x $@.sym
|
||||
|
||||
tests: tests.o
|
||||
$(CC_FOR_TARGET) -T link.ld -o $@ $(LDFLAGS) $<
|
||||
|
|
|
@ -28,8 +28,19 @@ extern int errno;
|
|||
int main(int argc, char** argv)
|
||||
{
|
||||
//int i;
|
||||
char* str = (char *)malloc(40 * sizeof(char));
|
||||
char* str = (char *)malloc(20 * sizeof(char));
|
||||
FILE* testfile;
|
||||
testfile = fopen("/bin/test", "w+r");
|
||||
setbuf(testfile, NULL);
|
||||
fflush(NULL);
|
||||
fwrite("wsblablaxxxyyyyzzzzzz", 1, 19, testfile);
|
||||
fclose(testfile);
|
||||
|
||||
testfile = fopen("/bin/test", "w+r");
|
||||
setbuf(testfile, NULL);
|
||||
fread(str, 1, 20, testfile);
|
||||
fflush(NULL);
|
||||
printf("Aus Datei gelesen (/bin/test):%s\n", str);
|
||||
|
||||
testfile = fopen("/bin/test", "w+r");
|
||||
setbuf(testfile, NULL);
|
||||
|
|
196
newlib/examples/jacobi.c
Normal file
196
newlib/examples/jacobi.c
Normal file
|
@ -0,0 +1,196 @@
|
|||
/*
|
||||
* Copyright 2010-2011 Stefan Lankes
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#undef errno
|
||||
extern int errno;
|
||||
|
||||
#define MATRIX_SIZE 128
|
||||
#define MAXVALUE 1337
|
||||
#define PAGE_SIZE 4096
|
||||
#define CACHE_SIZE (256*1024)
|
||||
#define ALIGN(x,a) (((x)+(a)-1)&~((a)-1))
|
||||
|
||||
static int generate_empty_matrix(double*** A , unsigned int N) {
|
||||
unsigned int iCnt;
|
||||
int i,j;
|
||||
|
||||
*A = (double**) malloc((N+1)*sizeof(double*));
|
||||
|
||||
if (*A == NULL)
|
||||
return -2; /* Error */
|
||||
|
||||
(*A)[0] = (double*) malloc((N+1)*N*sizeof(double));
|
||||
|
||||
if (**A == NULL)
|
||||
return -2; /* Error */
|
||||
|
||||
for(iCnt=1; iCnt<N; iCnt++) { /* Assign pointers in the first "real index"; Value from 1 to N (0 yet set, value N means N+1) */
|
||||
(*A)[iCnt] = &((*A)[0][iCnt*(N+1)]);
|
||||
}
|
||||
|
||||
memset(**A, 0, (N+1)*N*sizeof(double)); /* Fill matrix values with 0 */
|
||||
|
||||
srand( 42 /*(unsigned) time(NULL)*/ ) ; /* init random number generator */
|
||||
|
||||
/*
|
||||
* initialize the system of linear equations
|
||||
* the result vector is one
|
||||
*/
|
||||
for (i = 0; i < N; i++)
|
||||
{
|
||||
double sum = 0.0;
|
||||
|
||||
for (j = 0; j < N; j++)
|
||||
{
|
||||
if (i != j)
|
||||
{
|
||||
double c = ((double)rand()) / ((double)RAND_MAX) * MAXVALUE;
|
||||
|
||||
sum += fabs(c);
|
||||
(*A)[i][j] = c;
|
||||
(*A)[i][N] += c;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The Jacobi method will always converge if the matrix A is strictly or irreducibly diagonally dominant.
|
||||
* Strict row diagonal dominance means that for each row, the absolute value of the diagonal term is
|
||||
* greater than the sum of absolute values of other terms: |A[i][i]| > Sum |A[i][j]| with (i != j)
|
||||
*/
|
||||
|
||||
(*A)[i][i] = sum + 2.0;
|
||||
(*A)[i][N] += sum + 2.0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
double* temp;
|
||||
unsigned int i, j, iter_start, iter_end;
|
||||
unsigned int iterations = 0;
|
||||
double error, norm, max = 0.0;
|
||||
double** A=0;
|
||||
double* X;
|
||||
double* X_old, xi;
|
||||
clock_t start, end;
|
||||
|
||||
if (generate_empty_matrix(&A,MATRIX_SIZE) < 0)
|
||||
{
|
||||
printf("generate_empty_matrix() failed...\n");
|
||||
exit(-1);
|
||||
|
||||
}
|
||||
|
||||
printf("generate_empty_matrix() done...\n");
|
||||
|
||||
X = (double*) malloc(MATRIX_SIZE*sizeof(double));
|
||||
X_old = (double*) malloc(MATRIX_SIZE*sizeof(double));
|
||||
if(X == NULL || X_old == NULL)
|
||||
{
|
||||
printf("X or X_old is NULL...\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
for(i=0; i<MATRIX_SIZE; i++)
|
||||
{
|
||||
X[i] = ((double)rand()) / ((double)RAND_MAX) * 10.0;
|
||||
X_old[i] = 0.0;
|
||||
}
|
||||
|
||||
printf("start calculation...\n");
|
||||
|
||||
iter_start = 0;
|
||||
iter_end = MATRIX_SIZE;
|
||||
|
||||
start = clock();
|
||||
|
||||
while(1)
|
||||
{
|
||||
iterations++;
|
||||
|
||||
temp = X_old;
|
||||
X_old = X;
|
||||
X = temp;
|
||||
|
||||
for (i=iter_start; i<iter_end; i++)
|
||||
{
|
||||
for(j=0, xi=0.0; j<i; j++)
|
||||
xi += A[i][j] * X_old[j];
|
||||
|
||||
for(j=i+1; j<MATRIX_SIZE; j++)
|
||||
xi += A[i][j] * X_old[j];
|
||||
X[i] = (A[i][MATRIX_SIZE] - xi) / A[i][i];
|
||||
}
|
||||
|
||||
if (iterations % 5000 == 0 ) {/* calculate the Euclidean norm between X_old and X*/
|
||||
norm = 0.0;
|
||||
for (i=iter_start; i<iter_end; i++)
|
||||
norm += (X_old[i] - X[i]) * (X_old[i] - X[i]);
|
||||
|
||||
/* check the break condition */
|
||||
norm /= (double) MATRIX_SIZE;
|
||||
if (norm < 0.0000001)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
end = clock();
|
||||
|
||||
if (MATRIX_SIZE < 16) {
|
||||
printf("Print the solution...\n");
|
||||
/* print solution */
|
||||
for(i=0; i<MATRIX_SIZE; i++) {
|
||||
for(j=0; j<MATRIX_SIZE; j++)
|
||||
printf("%8.2f\t", A[i][j]);
|
||||
printf("*\t%8.2f\t=\t%8.2f\n", X[i], A[i][MATRIX_SIZE]);
|
||||
}
|
||||
}
|
||||
printf("Check the result...\n");
|
||||
|
||||
/*
|
||||
* check the result
|
||||
* X[i] have to be 1
|
||||
*/
|
||||
for(i=0; i<MATRIX_SIZE; i++) {
|
||||
error = fabs(X[i] - 1.0f);
|
||||
|
||||
if (max < error)
|
||||
max = error;
|
||||
if (error > 0.01f)
|
||||
printf("Result is on position %d wrong (%f != 1.0)\n", i, X[i]);
|
||||
}
|
||||
printf("maximal error is %f\n", max);
|
||||
|
||||
printf("\nmatrix size: %d x %d\n", MATRIX_SIZE, MATRIX_SIZE);
|
||||
printf("number of iterations: %d\n", iterations);
|
||||
printf("calculation time: %f s\n", (float) (end-start) / (float) CLOCKS_PER_SEC);
|
||||
|
||||
free((void*) X_old);
|
||||
free((void*) X);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1 +1 @@
|
|||
HalloXA!
|
||||
HalloXA!
|
||||
|
|
|
@ -22,23 +22,20 @@
|
|||
#include <errno.h>
|
||||
#undef errno
|
||||
extern int errno;
|
||||
#include "warning.h"
|
||||
#include "syscall.h"
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL ((void*) 0)
|
||||
#endif
|
||||
void*
|
||||
_DEFUN (sbrk, (incr),
|
||||
int incr)
|
||||
{
|
||||
int ret;
|
||||
|
||||
void *
|
||||
sbrk (incr)
|
||||
int incr;
|
||||
{
|
||||
extern char _end; // set by linker
|
||||
static char *heap_end = NULL;
|
||||
char *prev_heap_end;
|
||||
ret = SYSCALL1(__NR_sbrk, incr);
|
||||
if (ret < 0x1000) {
|
||||
errno = -ret;
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
if (!heap_end)
|
||||
heap_end = &_end;
|
||||
prev_heap_end = heap_end;
|
||||
heap_end += incr;
|
||||
|
||||
return (void *) prev_heap_end;
|
||||
return (void*) ret;
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ extern "C" {
|
|||
#define __NR_fork 12
|
||||
#define __NR_wait 13
|
||||
#define __NR_execve 14
|
||||
#define __NR_times 15
|
||||
|
||||
#define _STR(token) #token
|
||||
#define _SYSCALLSTR(x) "int $" _STR(x) " "
|
||||
|
|
|
@ -24,14 +24,20 @@
|
|||
#include <errno.h>
|
||||
#undef errno
|
||||
extern int errno;
|
||||
#include "warning.h"
|
||||
#include "syscall.h"
|
||||
|
||||
clock_t
|
||||
_DEFUN (_times, (buf),
|
||||
struct tms *buf)
|
||||
{
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
clock_t clock = 0;
|
||||
int ret;
|
||||
|
||||
stub_warning(_times)
|
||||
ret = SYSCALL2(__NR_times, buf, &clock);
|
||||
if (ret < 0) {
|
||||
errno = -ret;
|
||||
return (clock_t) -1;
|
||||
}
|
||||
|
||||
return clock;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ LDFLGAS =
|
|||
DEFINES=
|
||||
NASM = nasm
|
||||
NASMFLAGS = -fbin
|
||||
EXECFILES = $(shell find ../newlib/examples -perm -u+r+x -type f) ../newlib/examples/test
|
||||
EXECFILES = $(shell find ../newlib/examples -perm -u+r+x -type f) ../newlib/examples/test
|
||||
|
||||
# other implicit rules
|
||||
%.o : %.c
|
||||
|
|
Loading…
Add table
Reference in a new issue