- minor changes to support APIC
(currently, we got page fault by entering apic_calibration) - first steps to realize a loader git-svn-id: http://svn.lfbs.rwth-aachen.de/svn/scc/trunk/MetalSVM@365 315a16e6-25f9-4109-90ae-ca3045a26c18
This commit is contained in:
parent
81d0b19726
commit
8646b56a63
9 changed files with 162 additions and 97 deletions
|
@ -105,4 +105,9 @@ int arch_paging_init(void);
|
|||
*/
|
||||
int get_kernel_pgd(task_t* task);
|
||||
|
||||
/*
|
||||
* Create a new page directory for a new user-level task
|
||||
*/
|
||||
page_dir_t* create_pgd(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -139,7 +139,7 @@ inline static int system_init(void)
|
|||
scc_init();
|
||||
#endif
|
||||
gdt_install();
|
||||
//apic_init();
|
||||
apic_init();
|
||||
#ifdef CONFIG_PCI
|
||||
pci_init();
|
||||
#endif
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include <metalsvm/stddef.h>
|
||||
#include <metalsvm/stdio.h>
|
||||
#include <metalsvm/stdlib.h>
|
||||
#include <metalsvm/string.h>
|
||||
#include <metalsvm/errno.h>
|
||||
#include <metalsvm/processor.h>
|
||||
|
@ -54,7 +55,7 @@ static volatile ioapic_t* ioapic = NULL;
|
|||
static uint32_t ncores = 1;
|
||||
static uint8_t irq_redirect[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF};
|
||||
#if MAX_CORES > 1
|
||||
static uint8_t boot_code[] = {0xE9, 0x1F, 0x00, 0x90, 0x17, 0x00, 0x0A, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x9A, 0xCF, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x92, 0xCF, 0x00, 0x0F, 0x01, 0x16, 0x04, 0x00, 0x0F, 0x20, 0xC0, 0x0C, 0x01, 0x0F, 0x22, 0xC0, 0x66, 0xEA, 0x37, 0x00, 0x01, 0x00, 0x08, 0x00, 0x31, 0xC0, 0x66, 0xB8, 0x10, 0x00, 0x8E, 0xD8, 0x8E, 0xC0, 0x8E, 0xE0, 0x8E, 0xE8, 0x8E, 0xD0, 0xB8, 0x02, 0xD0, 0xBA, 0x02, 0x31, 0xDB, 0xEA, 0x00, 0x10, 0x10, 0x00, 0x08, 0x00};
|
||||
static uint8_t boot_code[] = {0xE9, 0x1E, 0x00, 0x17, 0x00, 0x09, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x9A, 0xCF, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x92, 0xCF, 0x00, 0x0F, 0x01, 0x16, 0x03, 0x00, 0x0F, 0x20, 0xC0, 0x0C, 0x01, 0x0F, 0x22, 0xC0, 0x66, 0xEA, 0x36, 0x00, 0x01, 0x00, 0x08, 0x00, 0xFA, 0x31, 0xC0, 0x66, 0xB8, 0x10, 0x00, 0x8E, 0xD8, 0x8E, 0xC0, 0x8E, 0xE0, 0x8E, 0xE8, 0x8E, 0xD0, 0x0F, 0x20, 0xC0, 0x25, 0xFF, 0xFF, 0xFF, 0x9F, 0x0D, 0x20, 0x00, 0x00, 0x00, 0x0F, 0x22, 0xC0, 0x31, 0xC0, 0x0F, 0x22, 0xD8, 0xBC, 0xEF, 0xBE, 0xAD, 0xDE, 0x31, 0xC0, 0x31, 0xDB, 0xEA, 0xDE, 0xC0, 0xAD, 0xDE, 0x08, 0x00};
|
||||
#endif
|
||||
static uint8_t initialized = 0;
|
||||
static atomic_int32_t cpu_online = ATOMIC_INIT(1);
|
||||
|
@ -68,10 +69,10 @@ static inline uint32_t lapic_read(uint32_t addr)
|
|||
static inline void lapic_write(uint32_t addr, uint32_t value)
|
||||
{
|
||||
/*
|
||||
* to avoid ap entium bug, we have to read a apic register before
|
||||
* before we write value to this register
|
||||
* to avoid a pentium bug, we have to read a apic register
|
||||
* before we write a value to this register
|
||||
*/
|
||||
asm volatile ("movl (%%eax), %%edx; movl %%ebx, (%%eax)" :: "a"(addr+lapic), "b"(value) : "%edx");
|
||||
asm volatile ("movl (%%eax), %%edx; movl %%ebx, (%%eax)" :: "a"(lapic+addr), "b"(value) : "%edx");
|
||||
//*((volatile uint32_t*) (lapic+addr)) = value;
|
||||
}
|
||||
|
||||
|
@ -167,20 +168,16 @@ static int wakeup_all_aps(uint32_t start_eip)
|
|||
}
|
||||
#endif
|
||||
|
||||
int smp_main(void)
|
||||
{
|
||||
#if MAX_CORES > 1
|
||||
static void smp_main(void)
|
||||
{
|
||||
vga_puts("JJAJAJAJAJAJA\n");
|
||||
lowlevel_init();
|
||||
atomic_int32_inc(&cpu_online);
|
||||
kputs("JAJAJAJ\n");
|
||||
while(1)
|
||||
|
||||
;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
while(1) ;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_MULTIBOOT
|
||||
static unsigned int* search_apic(unsigned int base, unsigned int limit) {
|
||||
|
@ -201,6 +198,7 @@ static unsigned int* search_apic(unsigned int base, unsigned int limit) {
|
|||
int smp_init(void)
|
||||
{
|
||||
uint32_t i;
|
||||
size_t bootaddr;
|
||||
int err;
|
||||
|
||||
if (ncores <= 1)
|
||||
|
@ -210,12 +208,19 @@ int smp_init(void)
|
|||
* dirty hack: Copy 16bit startup code (see tools/smp_setup.asm)
|
||||
* to a 16bit address. Wakeup the other cores via IPI. They start
|
||||
* at this address in real mode, switch to protected and finally
|
||||
* they jump to 0x101000 (see smp_start in entry.asm)
|
||||
* they jump to smp_main.
|
||||
*/
|
||||
memcpy((void*)0x10000, boot_code, sizeof(boot_code));
|
||||
bootaddr = 0x10000;
|
||||
map_region(per_core(current_task), bootaddr, get_pages(1), 1, MAP_KERNEL_SPACE);
|
||||
for(i=0; i<sizeof(boot_code); i+=sizeof(size_t))
|
||||
{
|
||||
// replace 0xDEADC0DE with the address of the smp entry code
|
||||
if (*((size_t*) (bootaddr+i)) == 0xDEADC0DE)
|
||||
*((size_t*) (bootaddr+i)) = (size_t) smp_main;
|
||||
}
|
||||
|
||||
kprintf("size of the boot_code %d\n", sizeof(boot_code));
|
||||
err = wakeup_all_aps(0x10000);
|
||||
err = wakeup_all_aps(bootaddr);
|
||||
if (err)
|
||||
kprintf("Unable to wakeup application processors: %d\n", err);
|
||||
|
||||
|
@ -461,7 +466,7 @@ check_lapic:
|
|||
goto out;
|
||||
}
|
||||
|
||||
//return 0;
|
||||
return 0;
|
||||
|
||||
out:
|
||||
apic_mp = NULL;
|
||||
|
|
|
@ -95,7 +95,7 @@ size_t virt_to_phys(task_t* task, size_t viraddr)
|
|||
if (!(task->pgd->entries[index1] & 0xFFFFF000))
|
||||
goto out;
|
||||
|
||||
pgt = (page_table_t*) ((KERNEL_SPACE - 1024*PAGE_SIZE + index1*4) & 0xFFFFF000);
|
||||
pgt = (page_table_t*) ((KERNEL_SPACE - 1024*PAGE_SIZE + index1*PAGE_SIZE) & 0xFFFFF000);
|
||||
if (!pgt || !(pgt->entries[index2]))
|
||||
goto out;
|
||||
|
||||
|
@ -167,14 +167,14 @@ size_t map_region(task_t* task, size_t viraddr, size_t phyaddr, uint32_t npages,
|
|||
|
||||
// clear the page table
|
||||
if (paging_enabled)
|
||||
memset((void*) (KERNEL_SPACE - 1024*PAGE_SIZE + index*4), 0, PAGE_SIZE);
|
||||
memset((void*) ((KERNEL_SPACE - 1024*PAGE_SIZE + index*PAGE_SIZE) & 0xFFFFF000), 0, PAGE_SIZE);
|
||||
else
|
||||
memset(pgt, 0, PAGE_SIZE);
|
||||
} else pgt = (page_table_t*) (task->pgd->entries[index] & 0xFFFFF000);
|
||||
|
||||
/* convert physical address to virtual */
|
||||
if (paging_enabled)
|
||||
pgt = (page_table_t*) ((KERNEL_SPACE - 1024*PAGE_SIZE + index*4) & 0xFFFFF000);
|
||||
pgt = (page_table_t*) ((KERNEL_SPACE - 1024*PAGE_SIZE + index*PAGE_SIZE) & 0xFFFFF000);
|
||||
|
||||
index = (viraddr >> 12) & 0x3FF;
|
||||
if (BUILTIN_EXPECT(pgt->entries[index], 0)) {
|
||||
|
@ -225,7 +225,7 @@ size_t vm_alloc(task_t* task, uint32_t npages, uint32_t flags)
|
|||
index1 = i >> 22;
|
||||
index2 = (i >> 12) & 0x3FF;
|
||||
|
||||
pgt = (page_table_t*) ((KERNEL_SPACE - 1024*PAGE_SIZE + index1*4) & 0xFFFFF000);
|
||||
pgt = (page_table_t*) ((KERNEL_SPACE - 1024*PAGE_SIZE + index1*PAGE_SIZE) & 0xFFFFF000);
|
||||
if (!pgt || !(pgt->entries[index2])) {
|
||||
i+=PAGE_SIZE;
|
||||
j++;
|
||||
|
@ -257,7 +257,7 @@ int vm_free(task_t* task, size_t viraddr, uint32_t npages)
|
|||
index1 = viraddr >> 22;
|
||||
index2 = (viraddr >> 12) & 0x3FF;
|
||||
|
||||
pgt = (page_table_t*) ((KERNEL_SPACE - 1024*PAGE_SIZE + index1*4) & 0xFFFFF000);
|
||||
pgt = (page_table_t*) ((KERNEL_SPACE - 1024*PAGE_SIZE + index1*PAGE_SIZE) & 0xFFFFF000);
|
||||
if (!pgt)
|
||||
continue;
|
||||
pgt->entries[index2] = 0;
|
||||
|
@ -289,7 +289,7 @@ int print_paging_tree(size_t viraddr)
|
|||
|
||||
/* convert physical address to virtual */
|
||||
if (paging_enabled && pgt)
|
||||
pgt = (page_table_t*) (KERNEL_SPACE - 1024*PAGE_SIZE + index1*4);
|
||||
pgt = (page_table_t*) (KERNEL_SPACE - 1024*PAGE_SIZE + index1*PAGE_SIZE);
|
||||
|
||||
kprintf("\tPage table entry %u: ", index2);
|
||||
if (pgt)
|
||||
|
|
|
@ -29,59 +29,92 @@ extern "C" {
|
|||
|
||||
#define ELF_MAGIC 0x464C457F
|
||||
|
||||
#define ELF_ET_NONE 0x0000 // no type
|
||||
#define ELF_ET_REL 0x0001 // relocatable
|
||||
#define ELF_ET_EXEC 0x0002 // executeable
|
||||
#define ELF_ET_DYN 0x0003 // Shared-Object-File
|
||||
#define ELF_ET_CORE 0x0004 // Corefile
|
||||
#define ELF_ET_LOPROC 0xFF00 // Processor-specific
|
||||
#define ELF_ET_HIPROC 0x00FF // Processor-specific
|
||||
|
||||
#define ELF_EM_NONE 0x0000 // no type
|
||||
#define ELF_EM_M32 0x0001 // AT&T WE 32100
|
||||
#define ELF_EM_SPARC 0x0002 // SPARC
|
||||
#define ELF_EM_386 0x0003 // Intel 80386
|
||||
#define ELF_EM_68K 0x0004 // Motorola 68000
|
||||
#define ELF_EM_88K 0x0005 // Motorola 88000
|
||||
#define ELF_EM_860 0x0007 // Intel 80860
|
||||
#define ELF_EM_MIPS 0x0008 // MIPS RS3000
|
||||
|
||||
#define ELF_CLASS_NONE 0x0000
|
||||
#define ELF_CLASS_32 0x0001 // 32bit file
|
||||
#define ELF_CLASS_64 0x0002 // 64bit file
|
||||
|
||||
#define ELF_DATA_NONE 0x0000
|
||||
#define ELF_DATA_2LSB 0x0001
|
||||
#define ELF_DATA_2MSB 0x002
|
||||
|
||||
/* Legal values for p_type (segment type). */
|
||||
|
||||
#define PT_NULL 0 /* Program header table entry unused */
|
||||
#define PT_LOAD 1 /* Loadable program segment */
|
||||
#define PT_DYNAMIC 2 /* Dynamic linking information */
|
||||
#define PT_INTERP 3 /* Program interpreter */
|
||||
#define PT_NOTE 4 /* Auxiliary information */
|
||||
#define PT_SHLIB 5
|
||||
#define PT_PHDR 6 /* Entry for header table itself */
|
||||
#define PT_TLS 7 /* Thread-local storage segment */
|
||||
#define PT_NUM 8 /* Number of defined types */
|
||||
#define PT_LOOS 0x60000000 /* Start of OS-specific */
|
||||
#define PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */
|
||||
#define PT_GNU_STACK 0x6474e551 /* Indicates stack executability */
|
||||
#define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */
|
||||
#define PT_LOSUNW 0x6ffffffa
|
||||
#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */
|
||||
#define PT_SUNWSTACK 0x6ffffffb /* Stack segment */
|
||||
#define PT_HISUNW 0x6fffffff
|
||||
#define PT_HIOS 0x6fffffff /* End of OS-specific */
|
||||
#define PT_LOPROC 0x70000000 /* Start of processor-specific */
|
||||
#define PT_HIPROC 0x7fffffff /* End of processor-specific */
|
||||
#define ELF_PT_NULL 0 /* Program header table entry unused */
|
||||
#define ELF_PT_LOAD 1 /* Loadable program segment */
|
||||
#define ELF_PT_DYNAMIC 2 /* Dynamic linking information */
|
||||
#define ELF_PT_INTERP 3 /* Program interpreter */
|
||||
#define ELF_PT_NOTE 4 /* Auxiliary information */
|
||||
#define ELF_PT_SHLIB 5
|
||||
#define ELF_PT_PHDR 6 /* Entry for header table itself */
|
||||
#define ELF_PT_TLS 7 /* Thread-local storage segment */
|
||||
#define ELF_PT_NUM 8 /* Number of defined types */
|
||||
#define ELF_PT_LOOS 0x60000000 /* Start of OS-specific */
|
||||
#define ELF_PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */
|
||||
#define ELF_PT_GNU_STACK 0x6474e551 /* Indicates stack executability */
|
||||
#define ELF_PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */
|
||||
#define ELF_PT_LOSUNW 0x6ffffffa
|
||||
#define ELF_PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */
|
||||
#define ELF_PT_SUNWSTACK 0x6ffffffb /* Stack segment */
|
||||
#define ELF_PT_HISUNW 0x6fffffff
|
||||
#define ELF_PT_HIOS 0x6fffffff /* End of OS-specific */
|
||||
#define ELF_PT_LOPROC 0x70000000 /* Start of processor-specific */
|
||||
#define ELF_PT_HIPROC 0x7fffffff /* End of processor-specific */
|
||||
|
||||
typedef struct {
|
||||
uint32_t magic;
|
||||
uint32_t version;
|
||||
uint64_t reserved;
|
||||
uint64_t version2;
|
||||
uint32_t entry;
|
||||
uint32_t ph_offset;
|
||||
uint32_t sh_offset;
|
||||
uint32_t flags;
|
||||
uint16_t header_size;
|
||||
uint16_t ph_entry_size;
|
||||
uint16_t ph_entry_count;
|
||||
uint16_t sh_entry_size;
|
||||
uint16_t sh_entry_count;
|
||||
uint16_t sh_str_table_index;
|
||||
} __attribute__((packed)) elf_header_t;
|
||||
|
||||
uint32_t magic;
|
||||
uint8_t _class;
|
||||
uint8_t data;
|
||||
uint8_t version;
|
||||
uint8_t pad[8];
|
||||
uint8_t nident;
|
||||
} __attribute__ ((packed)) elf_ident_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t type;
|
||||
uint32_t offset;
|
||||
uint32_t virt_addr;
|
||||
uint32_t phys_addr;
|
||||
uint32_t file_size;
|
||||
uint32_t mem_size;
|
||||
uint32_t flags;
|
||||
uint32_t alignment;
|
||||
} __attribute__((packed)) elf_program_header_t;
|
||||
elf_ident_t ident;
|
||||
uint16_t type;
|
||||
uint16_t machine;
|
||||
uint32_t version;
|
||||
uint32_t entry;
|
||||
uint32_t ph_offset;
|
||||
uint32_t sh_offset;
|
||||
uint32_t flags;
|
||||
uint16_t header_size;
|
||||
uint16_t ph_entry_size;
|
||||
uint16_t ph_entry_count;
|
||||
uint16_t sh_entry_size;
|
||||
uint16_t sh_entry_count;
|
||||
uint16_t sh_str_table_index;
|
||||
} __attribute__ ((packed)) elf_header_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t type;
|
||||
uint32_t offset;
|
||||
uint32_t virt_addr;
|
||||
uint32_t phys_addr;
|
||||
uint32_t file_size;
|
||||
uint32_t mem_size;
|
||||
uint32_t flags;
|
||||
uint32_t alignment;
|
||||
} __attribute__ ((packed)) elf_program_header_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -38,7 +38,7 @@ int multitasking_init(void);
|
|||
int create_kernel_task(tid_t*, entry_point_t, void*);
|
||||
|
||||
/* create a user level task. if sz is zero, the task with the default stack size will be created */
|
||||
int create_user_task(tid_t* id, entry_point_t ep, void* arg, size_t sz);
|
||||
int create_user_task(tid_t* id, size_t sz, const char* filename, int argc, char** argv);
|
||||
|
||||
/* until the task id is runnint, the current task is block */
|
||||
int join_task(tid_t id, int* result);
|
||||
|
|
|
@ -97,7 +97,7 @@ int main(void)
|
|||
kprintf("Kernel starts at %p and ends at %p\n", &kernel_start, &kernel_end);
|
||||
|
||||
system_calibration();
|
||||
network_init();
|
||||
//network_init();
|
||||
|
||||
kprintf("Processor frequency: %u MHz\n", get_cpu_frequency());
|
||||
kprintf("Total memory: %u MBytes\n", atomic_int32_read(&total_pages)/((1024*1024)/PAGE_SIZE));
|
||||
|
@ -105,7 +105,7 @@ int main(void)
|
|||
kprintf("Current available memory: %u MBytes\n", atomic_int32_read(&total_available_pages)/((1024*1024)/PAGE_SIZE));
|
||||
|
||||
sleep(5);
|
||||
list_root();
|
||||
//list_root();
|
||||
test_init();
|
||||
|
||||
per_core(current_task)->status = TASK_IDLE;
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
#include <metalsvm/spinlock.h>
|
||||
#include <metalsvm/mailbox.h>
|
||||
#include <metalsvm/syscall.h>
|
||||
#include <metalsvm/fs.h>
|
||||
#include <metalsvm/elf.h>
|
||||
|
||||
DEFINE_PER_CORE(task_t*, current_task, NULL);
|
||||
static task_t task_table[MAX_TASKS] = {[0 ... MAX_TASKS-1] = {0, TASK_INVALID, NULL, 0, ATOMIC_INIT(0), NULL, NULL}};
|
||||
|
@ -173,10 +175,48 @@ int create_kernel_task(tid_t* id, entry_point_t ep, void* arg)
|
|||
return create_task(id, ep, arg, 0, 0);
|
||||
}
|
||||
|
||||
int create_user_task(tid_t* id, entry_point_t ep, void* arg, size_t stack_size)
|
||||
int create_user_task(tid_t* id, size_t sz, const char* filename, int argc, char** argv)
|
||||
{
|
||||
vfs_node_t* node;
|
||||
elf_header_t header;
|
||||
page_dir_t* pgd;
|
||||
|
||||
node = findnode_fs(filename);
|
||||
if (node && (node->type == FS_FILE)) {
|
||||
kprintf("Found application %s at node %p\n", filename, node);
|
||||
|
||||
read_fs(node, (uint8_t*)&header, sizeof(elf_header_t), 0);
|
||||
if (BUILTIN_EXPECT(header.ident.magic != ELF_MAGIC, 0))
|
||||
return -EINVAL;
|
||||
|
||||
if (BUILTIN_EXPECT(header.type != ELF_ET_EXEC, 0))
|
||||
return -EINVAL;
|
||||
|
||||
if (BUILTIN_EXPECT(header.machine != ELF_EM_386, 0))
|
||||
return -EINVAL;
|
||||
|
||||
if (BUILTIN_EXPECT(header.ident._class != ELF_CLASS_32, 0))
|
||||
return -EINVAL;
|
||||
|
||||
if (BUILTIN_EXPECT(header.ident.data != ELF_DATA_2LSB, 0))
|
||||
return -EINVAL;
|
||||
|
||||
kprintf("entry point at 0x%x\n", header.entry);
|
||||
|
||||
pgd = create_pgd();
|
||||
if (!pgd)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*int create_user_task(tid_t* id, entry_point_t ep, void* arg, size_t stack_size)
|
||||
{
|
||||
return create_task(id, ep, arg, stack_size, 1);
|
||||
}
|
||||
}*/
|
||||
|
||||
int join_task(tid_t id, int* result)
|
||||
{
|
||||
|
|
|
@ -83,25 +83,6 @@ static int STDCALL foo(void* arg)
|
|||
return 42;
|
||||
}
|
||||
|
||||
static int STDCALL userfoo(void* arg)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!arg)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
SYSCALL3(__NR_write, 0, (char*)arg, strlen((char*)arg));
|
||||
|
||||
// demo of a general protection fault
|
||||
//kprintf("test user\n");
|
||||
|
||||
/* task exit */
|
||||
SYSCALL1(__NR_exit, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int STDCALL join_test(void* arg)
|
||||
{
|
||||
tid_t id;
|
||||
|
@ -118,16 +99,17 @@ static int STDCALL join_test(void* arg)
|
|||
int test_init(void)
|
||||
{
|
||||
tid_t id1, id2, id3, id4, id5;
|
||||
char* argv[1] = {"/bin/hello"};
|
||||
|
||||
sem_init(&producing, 1);
|
||||
sem_init(&consuming, 0);
|
||||
mailbox_int32_init(&mbox);
|
||||
|
||||
create_kernel_task(&id1, foo, "Hello from foo1\n");
|
||||
//create_kernel_task(&id1, foo, "Hello from foo1\n");
|
||||
//create_kernel_task(&id2, join_test, NULL);
|
||||
create_kernel_task(&id3, producer, NULL);
|
||||
create_kernel_task(&id4, consumer, NULL);
|
||||
//create_user_task(&id5, userfoo, "Hello from user process foo\n", 0);
|
||||
//create_kernel_task(&id3, producer, NULL);
|
||||
//create_kernel_task(&id4, consumer, NULL);
|
||||
create_user_task(&id5, 8192, "/bin/hello", 1, argv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue