Compare commits

..

No commits in common. "master" and "user_malloc" have entirely different histories.

61 changed files with 361 additions and 1794 deletions

2
.gitignore vendored
View File

@ -1,6 +1,6 @@
serialOut serialOut
disk.img disk.img
kernel kernel
kernel.debug kernel.sym
userspace/user userspace/user
docs/*.html docs/*.html

View File

@ -3,7 +3,7 @@ CPPFLAGS = -MMD
AS=nasm AS=nasm
ASFLAGS += -f elf32 ASFLAGS += -f elf32
LDFLAGS += -m elf_i386 LDFLAGS += -m elf_i386
CFLAGS += -m32 -pipe -Wall -Wextra -Werror -ffreestanding -fno-exceptions -fno-pie -fno-stack-protector -fno-tree-vectorize -D__KERNEL__ CFLAGS += -m32 -Wall -Wextra -Werror -ffreestanding -fno-exceptions -fno-pie -fno-stack-protector -fno-tree-vectorize -D__KERNEL__
#keep .i and .s #keep .i and .s
#CFLAGS += -save-temps #CFLAGS += -save-temps
#CFLAGS += -fanalyzer -Wno-analyzer-malloc-leak -Wno-analyzer-out-of-bounds #CFLAGS += -fanalyzer -Wno-analyzer-malloc-leak -Wno-analyzer-out-of-bounds
@ -88,16 +88,11 @@ test: clean kernel disk.img
run:kernel disk.img ## Run the OS on qemu run:kernel disk.img ## Run the OS on qemu
qemu-system-x86_64 -kernel $< -serial stdio $(QEMU_OPT) qemu-system-x86_64 -kernel $< -serial stdio $(QEMU_OPT)
debug: CFLAGS += $(DEBUG_FLAGS) ## Run the OS on qemu and attach a debugger to it (may need a clean before to have the debug symbols) debug: CFLAGS += $(DEBUG_FLAGS) ## Run the OS on qemu and attach a debugger to it (may need a clean befor to have the debug symbols)
debug: CXXFLAGS += $(DEBUG_FLAGS) debug: CXXFLAGS += $(DEBUG_FLAGS)
debug:kernel kernel.debug disk.img debug:kernel kernel.debug disk.img
gdb -q -x debug.gdb gdb -q -x debug.gdb
isodebug: CFLAGS += $(DEBUG_FLAGS) ## Same than previous but kernel is loaded by grub. So, for example, we can access the elf debug info
isodebug: CXXFLAGS += $(DEBUG_FLAGS)
isodebug:fd.iso disk.img
gdb -q -x debug.iso.gdb
debug_test: CFLAGS += $(DEBUG_FLAGS) -DRUN_TEST debug_test: CFLAGS += $(DEBUG_FLAGS) -DRUN_TEST
debug_test: debug debug_test: debug
@ -107,7 +102,6 @@ screenshot: ## Take a screenshot of the qemu window
clean: clean:
$(RM) kernel $(asmobj) $(gasmobj) $(cobj) $(deps) $(cinc) fd.iso kernel.debug kernel.map $(docobj) $(RM) kernel $(asmobj) $(gasmobj) $(cobj) $(deps) $(cinc) fd.iso kernel.debug kernel.map $(docobj)
$(RM) -r isodir $(RM) -r isodir
$(MAKE) -C userspace clean
.PHONY: .PHONY:
userspace screenshot userspace screenshot

View File

@ -45,53 +45,30 @@ int exceptionSetRoutine(int exception, exception_handler handler)
void print_handler(struct cpu_state *frame, ulong intr) void print_handler(struct cpu_state *frame, ulong intr)
{ {
VGAPrintf(RED, BLACK, 0, VGA_HEIGHT - 1, "EXCEPTION %lu", intr); int intNbInt = intr;
VGAPrintf(RED, BLACK, 0, VGA_HEIGHT - 1, "EXCEPTION %d", intNbInt);
printf("Exception %lu at 0x%p\n", intr, (void *)cpu_context_get_PC(frame)); printf("Exception %lu at 0x%p\n", intr, (void *)cpu_context_get_PC(frame));
asm("hlt"); asm("hlt");
} }
void pagefault_handler(struct cpu_state *frame, ulong intr) void pagefault_handler(struct cpu_state *frame, ulong intr)
{ {
// PAGE_FAULT is a interrupt with an error code (see exception_wrapper.S)
uint32_t error_code = cpu_context_get_EX_err(frame);
struct thread *current = getCurrentThread(); struct thread *current = getCurrentThread();
struct uAddrSpace *as = processGetAddrSpace(current->process);
vaddr_t faultAddr = cpu_context_get_EX_faulting_vaddr(frame);
if (cpu_context_is_in_user_mode(current->cpuState)) { if(!uAddrSpaceCheckNAlloc(as, faultAddr))
assert(frame == current->cpuState); // pagefault in kernel not supported ATM return;
struct uAddrSpace *as = processGetAddrSpace(current->process); printf("page fault while in thread [%s] at 0x%p when trying to access 0x%p err_code 0x%x\n", current->name,
vaddr_t faultAddr = cpu_context_get_EX_faulting_vaddr(frame); (void *)cpu_context_get_PC(frame), (void *)faultAddr, cpu_context_get_EX_err(frame));
int needMMUSetup = if (cpu_context_is_in_user_mode(frame)) {
(uAddrSpaceGetMMUContext(as) != getCurrentThread()->squattedContext);
if (needMMUSetup) {
threadChangeCurrentContext(uAddrSpaceGetMMUContext(as));
}
if (!uAddrSpaceHeapCheckNAlloc(as, faultAddr))
goto release_context;
int ret = uAddrSpaceSolvePageFault(as, faultAddr, error_code & 0x2);
if (!ret)
goto release_context;
printf(
"page fault while in thread [%s] at 0x%p when trying to access 0x%p err_code 0x%x ressource ret %d\n",
current->name, (void *)cpu_context_get_PC(frame), (void *)faultAddr, error_code,
ret);
printf("Killing User Thread\n"); printf("Killing User Thread\n");
threadExit(); threadExit();
release_context:
if (needMMUSetup)
threadChangeCurrentContext(NULL);
return;
} }
VGAPrintf(RED, BLACK, 0, VGA_HEIGHT - 1, "PAGE FAULT %d", intr); VGAPrintf(RED, BLACK, 0, VGA_HEIGHT - 1, "PAGE FAULT %d", intr);
(void)intr;
for (;;) for (;;)
continue; continue;
} }
@ -102,6 +79,5 @@ int exceptionSetup()
exceptionSetRoutine(i, print_handler); exceptionSetRoutine(i, print_handler);
} }
exceptionSetRoutine(EXCEPTION_PAGE_FAULT, pagefault_handler); exceptionSetRoutine(EXCEPTION_PAGE_FAULT, pagefault_handler);
return 0; return 0;
} }

View File

@ -165,7 +165,7 @@
iret iret
.endm .endm
/* List of exception w or w/o err code https://wiki.osdev.org/Exceptions */ /*List of exception w or w/o err codehttps://wiki.osdev.org/Exceptions*/
.irp exception_id, 8, 10, 11, 12, 13, 14, 17, 30 .irp exception_id, 8, 10, 11, 12, 13, 14, 17, 30
exception_mac_with_errcode exception_id exception_mac_with_errcode exception_id
.endr .endr

View File

@ -19,8 +19,6 @@
*/ */
#include "segment.h" #include "segment.h"
#include "gdt.h" #include "gdt.h"
#include "stddef.h"
#include "stdint.h"
/** /**
* The sructure of a segment descriptor. * The sructure of a segment descriptor.

View File

@ -1,6 +1,4 @@
#include "idt.h" #include "idt.h"
#include "stddef.h"
static struct idtEntry idt[IDT_NUM]; static struct idtEntry idt[IDT_NUM];
int idtSetup() int idtSetup()

View File

@ -1,5 +1,5 @@
#pragma once #pragma once
#include "stdint.h" #include "stdarg.h"
#define IDT_NUM 256 #define IDT_NUM 256

View File

@ -17,7 +17,6 @@
#define PAGING_MEM_USER (1U << 0) #define PAGING_MEM_USER (1U << 0)
#define PAGING_MEM_READ (1U << 1) #define PAGING_MEM_READ (1U << 1)
#define PAGING_MEM_WRITE (1U << 2) #define PAGING_MEM_WRITE (1U << 2)
#define PAGING_MEM_EXEC (1U << 3)
int pagingSetup(paddr_t lowerKernelAddr, paddr_t upperKernelAddr); int pagingSetup(paddr_t lowerKernelAddr, paddr_t upperKernelAddr);

View File

@ -1,19 +1,12 @@
#pragma once #pragma once
#include "paging.h" #include "paging.h"
#include "stddef.h" #include "stdarg.h"
#include "types.h"
/** Arbitrary size allocator **/
/* /*
* Initialize malloc system * Initialize malloc system
*/ */
int allocSetup(size_t sizeOfArea, vaddr_t *areaAddr, vaddr_t *descAddr, vaddr_t *entryAddr); int allocSetup(size_t sizeOfArea, vaddr_t *areaAddr, vaddr_t *descAddr, vaddr_t *entryAddr);
/*
* Add Slice for some simple/commun size
*/
int allocPopulate(); int allocPopulate();
/* /*
* Allow malloc to allocate elements of this precise size. * Allow malloc to allocate elements of this precise size.

View File

@ -7,14 +7,6 @@
#include "mem.h" #include "mem.h"
#include "stdarg.h" #include "stdarg.h"
struct memArea {
vaddr_t startAddr;
uint nbPages;
struct memArea *next;
struct memArea *prev;
};
static struct memArea *freeArea; static struct memArea *freeArea;
static struct memArea *usedArea; static struct memArea *usedArea;

View File

@ -1,7 +1,6 @@
#pragma once #pragma once
#include "paging.h" #include "paging.h"
#include "stdarg.h" #include "stdarg.h"
#include "stdint.h"
/* Pure Virtual Memory Allocation */ /* Pure Virtual Memory Allocation */
@ -9,29 +8,19 @@
#define AREA_PHY_MAP (1<<0) #define AREA_PHY_MAP (1<<0)
#define AREA_MEM_TOP PAGING_MIRROR_VADDR #define AREA_MEM_TOP PAGING_MIRROR_VADDR
/** struct memArea {
* Initialize the Area subsystem vaddr_t startAddr;
**/ uint nbPages;
struct memArea *next;
struct memArea *prev;
};
void areaInit(vaddr_t firstMemUsed, vaddr_t lastUsed, vaddr_t stack_bottom, vaddr_t stack_top); void areaInit(vaddr_t firstMemUsed, vaddr_t lastUsed, vaddr_t stack_bottom, vaddr_t stack_top);
/**
* Request a virtual memory area of @param nbPages
**/
vaddr_t areaAlloc(unsigned int nbPages, uint32_t flags); vaddr_t areaAlloc(unsigned int nbPages, uint32_t flags);
// Remove an area from the free ones but do not add it into used ones.
/** // This area should be latter added woth areaAdd.
* Free a virtual area // Used by malloc to avoid recursivity issue
**/
int areaFree(vaddr_t addr);
/**
* Remove an area from the "free" ones but do not add it into used ones.
* This area should be latter added with areaAdd.
* Used by malloc to avoid recursivity issue
**/
vaddr_t areaBook(unsigned int nbPages, uint32_t flags); vaddr_t areaBook(unsigned int nbPages, uint32_t flags);
int areaFree(vaddr_t addr);
/**
* Declare a virtual region to be managed by the subsytem
*/
int areaAdd(vaddr_t begin, vaddr_t end, int isFree); int areaAdd(vaddr_t begin, vaddr_t end, int isFree);

View File

@ -27,8 +27,7 @@
*/ */
#include "errno.h" #include "errno.h"
#include "stddef.h" #include "stdarg.h"
#include "stdint.h"
#include "types.h" #include "types.h"
/** /**

View File

@ -5,7 +5,6 @@
#include "paging.h" #include "paging.h"
#include "thread.h" #include "thread.h"
#include "types.h" #include "types.h"
#include "zero.h"
/** /**
* Make sure the program is in a valid ELF format, map it into memory, * Make sure the program is in a valid ELF format, map it into memory,
@ -14,11 +13,12 @@
* @return 0 when the program is not a valid ELF * @return 0 when the program is not a valid ELF
*/ */
uaddr_t loadElfProg(const char *prog, struct process *proc) uaddr_t loadElfProg(const char *prog, struct process * proc)
{ {
int i; int i;
uaddr_t lastUserAddr = 0; uaddr_t lastUserAddr = 0;
struct uAddrSpace *as = processGetAddrSpace(proc);
/* e_ident value */ /* e_ident value */
#define ELFMAG0 0x7f #define ELFMAG0 0x7f
@ -144,11 +144,6 @@ uaddr_t loadElfProg(const char *prog, struct process *proc)
if (lastUserAddr < uaddr) { if (lastUserAddr < uaddr) {
lastUserAddr = uaddr; lastUserAddr = uaddr;
} }
// Hack: Even if already allocated mark the adresse space as managed by a ressource
// So this address space is not used by another ressource.
uaddr = elf_phdrs[i].p_vaddr;
assert(zeroMmap(as, &uaddr, elf_phdrs[i].p_memsz, PAGING_MEM_USER | PAGING_MEM_WRITE | PAGING_MEM_READ, 0) == 0);
} }
processInitHeap(proc, lastUserAddr); processInitHeap(proc, lastUserAddr);

View File

@ -1,5 +1,5 @@
#pragma once #pragma once
#include "stdint.h" #include "stdarg.h"
// NIH http://wiki.osdev.org/Inline_Assembly/Examples#I.2FO_access // NIH http://wiki.osdev.org/Inline_Assembly/Examples#I.2FO_access
static inline void outb(uint16_t port, uint8_t val) static inline void outb(uint16_t port, uint8_t val)

View File

@ -425,8 +425,7 @@ int vsnprintf(char *str, size_t size, const char *format, va_list ap)
case 'x': { case 'x': {
char val[sizeof(long long int) * 2]; char val[sizeof(long long int) * 2];
unsigned int valIdx = 0; unsigned int valIdx = 0;
unsigned long long int d = long long int d = va_arg(ap, long long int);
va_arg(ap, unsigned long long int);
itoa(d, val, 16); itoa(d, val, 16);
if (str) { if (str) {
while (val[valIdx]) { while (val[valIdx]) {
@ -454,7 +453,7 @@ int vsnprintf(char *str, size_t size, const char *format, va_list ap)
case 'x': { case 'x': {
char val[sizeof(int) * 2]; char val[sizeof(int) * 2];
unsigned int valIdx = 0; unsigned int valIdx = 0;
unsigned long int d = va_arg(ap, unsigned long int); long int d = va_arg(ap, long int);
itoa(d, val, 16); itoa(d, val, 16);
if (str) { if (str) {
while (val[valIdx]) { while (val[valIdx]) {

View File

@ -1,7 +1,6 @@
#pragma once #pragma once
#include "assert.h" #include "assert.h"
#include "stdarg.h" #include "stdarg.h"
#include "stddef.h"
#include "minmax.h" #include "minmax.h"
#define islower(c) (('a' <= (c)) && ((c) <= 'z')) #define islower(c) (('a' <= (c)) && ((c) <= 'z'))
@ -37,8 +36,8 @@ int vprintf(const char *format, va_list ap) __attribute__ ((__format__ (printf,
int printf(const char *format, ...) __attribute__ ((__format__ (printf, 1, 2))); int printf(const char *format, ...) __attribute__ ((__format__ (printf, 1, 2)));
// Could be used after malloc is available // Could be used after malloc is available
int asprintf(char **strp, const char *fmt, ...) __attribute__ ((__format__ (printf, 2, 3))); int asprintf(char **strp, const char *fmt, ...);
int vasprintf(char **strp, const char *fmt, va_list ap) __attribute__ ((__format__ (printf, 2, 0))); int vasprintf(char **strp, const char *fmt, va_list ap);
/* /*
* Dummy printk for disabled debugging statements to use whilst maintaining * Dummy printk for disabled debugging statements to use whilst maintaining

View File

@ -28,7 +28,6 @@
#include "time.h" #include "time.h"
#include "types.h" #include "types.h"
#include "vga.h" #include "vga.h"
#include "zero.h"
#define CHECK_FLAG(flags, bit) ((flags) & (1 << (bit))) #define CHECK_FLAG(flags, bit) ((flags) & (1 << (bit)))
@ -36,7 +35,7 @@ void idleThread(void *arg)
{ {
(void)arg; (void)arg;
while (1) { while (1) {
VGAPrintf(GREEN, BLACK, 0, VGA_HEIGHT - 1, "%d allocated %d, mapped %d", (jiffies / HZ), getNbAllocatedPage(), getNbMappedPage()); VGAPrintf(GREEN, BLACK, 0, VGA_HEIGHT - 1, "%d", (jiffies / HZ));
threadYield(); threadYield();
} }
} }
@ -46,7 +45,7 @@ void idleThread(void *arg)
#define FILE_MAX_SIZE 64 // In nb of sectors #define FILE_MAX_SIZE 64 // In nb of sectors
void loadUserSpace() void loadUserSpace()
{ {
struct ata_partition *part = ATAGetPartitionByType(PART_TYPE_LINUX); struct ata_partition *part = ATAGetPartition(1);
if (part == NULL) { if (part == NULL) {
printf("No user partition found\n"); printf("No user partition found\n");
@ -84,28 +83,27 @@ void loadUserSpace()
return; return;
} }
{ struct process *proc = processCreate("UserSpace");
struct process *proc = processCreate("init");
struct uAddrSpace *as = processGetAddrSpace(proc);
threadChangeCurrentContext(processGetMMUContext(proc)); threadChangeCurrentContext(processGetMMUContext(proc));
uaddr_t prog = loadElfProg(buf + FILE_HEADER_SIZE, proc); uaddr_t prog = loadElfProg(buf + FILE_HEADER_SIZE, proc);
if (prog == (uaddr_t)NULL) { if (prog == (uaddr_t)NULL) {
free(buf); free(buf);
return; return;
}
// Alloc user stack
size_t stackSize = PAGE_SIZE * 2;
uaddr_t stack = PAGING_TOP_USER_ADDRESS - stackSize + 1;
zeroMmap(as, &stack, stackSize, PAGING_MEM_USER | PAGING_MEM_WRITE | PAGING_MEM_READ,
0);
threadCreateUser("init", proc, prog, 0, 0, stack + stackSize - 4);
processUnref(proc);
threadChangeCurrentContext(NULL);
} }
// Alloc user stack
uaddr_t stackTop = 0xfffffffc;
uaddr_t stackBottom = ALIGN_DOWN(stackTop, PAGE_SIZE);
paddr_t stackPhy = allocPhyPage(1);
assert(pageMap(stackBottom, stackPhy,
PAGING_MEM_USER | PAGING_MEM_WRITE | PAGING_MEM_READ) == 0);
unrefPhyPage(stackPhy);
threadCreateUser("UserProg", proc, prog, 0, 0, stackTop);
processUnref(proc);
threadChangeCurrentContext(NULL);
free(buf); free(buf);
} }

View File

@ -1,5 +1,5 @@
#pragma once #pragma once
#include "stdint.h" #include "stdarg.h"
#include "types.h" #include "types.h"
uint32_t log2(uint32_t x); uint32_t log2(uint32_t x);

View File

@ -1,9 +1,8 @@
#pragma once #pragma once
#include "stdint.h" #include "stdarg.h"
#include "types.h" #include "types.h"
/** /** Physical Page related function
* Physical Page management
*/ */
#define PAGE_SHIFT 12U #define PAGE_SHIFT 12U
@ -21,33 +20,10 @@ struct phyMemDesc {
struct phyMemDesc *next, *prev; struct phyMemDesc *next, *prev;
}; };
/**
* Initi Physical Page management subsystem
**/
int memSetup(paddr_t upperMem, paddr_t * firstUsed, paddr_t *lastUsed); int memSetup(paddr_t upperMem, paddr_t * firstUsed, paddr_t *lastUsed);
/**
* Declare a physical region to be managed by the physica page subsystem
**/
int memAddBank(paddr_t bottomMem, paddr_t topMem, int isFree); int memAddBank(paddr_t bottomMem, paddr_t topMem, int isFree);
/**
* Request @params nbPage free physical pages
**/
paddr_t allocPhyPage(uint nbPage); paddr_t allocPhyPage(uint nbPage);
/**
* Decrement the nb of user of a given physical page
**/
int unrefPhyPage(paddr_t addr); int unrefPhyPage(paddr_t addr);
/**
* Increment the nb of user of a given physical page
**/
int refPhyPage(paddr_t addr); int refPhyPage(paddr_t addr);
/**
* Return the number of physical allocated pages
**/
unsigned long getNbAllocatedPage(void); unsigned long getNbAllocatedPage(void);
void memGetStat(uint *free, uint *used); void memGetStat(uint *free, uint *used);

View File

@ -1,5 +1,5 @@
#pragma once #pragma once
#include "stddef.h" #include "stdarg.h"
struct mmu_context; struct mmu_context;

View File

@ -5,14 +5,12 @@
#include "list.h" #include "list.h"
#include "mmuContext.h" #include "mmuContext.h"
#include "types.h" #include "types.h"
#include "thread.h"
#include "uaddrspace.h" #include "uaddrspace.h"
struct process { struct process {
char name[PROCESS_NAME_MAX_LENGTH]; char name[PROCESS_NAME_MAX_LENGTH];
int ref; int ref;
pid_t pid; int pid;
pid_t nextTid;
struct uAddrSpace *addrSpace; struct uAddrSpace *addrSpace;
struct thread *thList; struct thread *thList;
@ -49,8 +47,7 @@ struct process *processCreate(char *name)
new->ref = 1; new->ref = 1;
disable_IRQs(flags); disable_IRQs(flags);
new->pid = nextPid++; new->pid = nextPid++;
new->nextTid = new->pid;
list_add_tail(processList, new); list_add_tail(processList, new);
restore_IRQs(flags); restore_IRQs(flags);
@ -69,7 +66,7 @@ void processListPrint()
struct thread *th; struct thread *th;
int nbTh; int nbTh;
printf("%lu %s %d %d\n", proc->pid, proc->name, processCountThread(proc), proc->ref); printf("%d %s %d %d\n", proc->pid, proc->name, processCountThread(proc), proc->ref);
list_foreach_named(proc->thList, th, nbTh, prevInProcess, nextInProcess) list_foreach_named(proc->thList, th, nbTh, prevInProcess, nextInProcess)
{ {
if (th == cur) { if (th == cur) {
@ -183,47 +180,3 @@ struct uAddrSpace *processGetAddrSpace(struct process *proc){
int processInitHeap(struct process *proc, uaddr_t lastUserAddr){ int processInitHeap(struct process *proc, uaddr_t lastUserAddr){
return uAddrSpaceSetHeap(proc->addrSpace, lastUserAddr, 0); return uAddrSpaceSetHeap(proc->addrSpace, lastUserAddr, 0);
} }
pid_t processGetId(struct process *proc){
return proc->pid;
}
pid_t processGetNextTid(struct process *proc){
return proc->nextTid++;
}
//Should be called with IRQ disabled
struct thread *processGetThread(struct process *proc, pid_t tid)
{
int count;
struct thread *th;
struct thread *thFound = NULL;
list_foreach_named(proc->thList, th, count, prevInProcess, nextInProcess)
{
if (th->tid == tid) {
thFound = th;
break;
}
}
return thFound;
}
int processJoinThread(struct process *proc, pid_t tid)
{
uint32_t flags;
struct thread *th;
int ret = -1;
disable_IRQs(flags);
th = processGetThread(proc, tid);
if (th && th->wqExit) {
wait(th->wqExit);
ret = 0;
}
restore_IRQs(flags);
return ret;
}

View File

@ -1,11 +1,9 @@
#pragma once #pragma once
#include "types.h" #include "thread.h"
#define PROCESS_NAME_MAX_LENGTH 32 #define PROCESS_NAME_MAX_LENGTH 32
typedef unsigned long int pid_t;
struct process; struct process;
struct thread;
int processSetup(); int processSetup();
struct process *processCreate(char *name); struct process *processCreate(char *name);
@ -20,6 +18,3 @@ int processRemoveThread(struct thread *th);
struct mmu_context *processGetMMUContext(struct process *th); struct mmu_context *processGetMMUContext(struct process *th);
struct uAddrSpace *processGetAddrSpace(struct process *proc); struct uAddrSpace *processGetAddrSpace(struct process *proc);
int processInitHeap(struct process *proc, uaddr_t lastUserAddr); int processInitHeap(struct process *proc, uaddr_t lastUserAddr);
pid_t processGetId(struct process *proc);
pid_t processGetNextTid(struct process *proc);
int processJoinThread(struct process *proc, pid_t tid);

View File

@ -1,5 +1,55 @@
#pragma once #pragma once
typedef __signed__ char __s8;
typedef unsigned char __u8;
typedef __signed__ short __s16;
typedef unsigned short __u16;
typedef __signed__ int __s32;
typedef unsigned int __u32;
#ifdef __GNUC__
__extension__ typedef __signed__ long long __s64;
__extension__ typedef unsigned long long __u64;
#else
typedef __signed__ long long __s64;
typedef unsigned long long __u64;
#endif
/* sysv */
typedef unsigned char unchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;
typedef __s8 int8_t;
typedef __s16 int16_t;
typedef __s32 int32_t;
typedef __u8 uint8_t;
typedef __u16 uint16_t;
typedef __u32 uint32_t;
typedef __u64 uint64_t;
typedef __u64 u_int64_t;
typedef __s64 int64_t;
typedef enum { FALSE = 0, TRUE } bool_t;
#define NULL ((void *)0)
#if __x86_64__
typedef unsigned long size_t;
typedef long ssize_t;
typedef unsigned long int uintptr_t;
typedef long int intptr_t;
#else
typedef unsigned int size_t;
typedef int ssize_t;
typedef unsigned int uintptr_t;
typedef int intptr_t;
#endif
//__builtin_va_list could be used instead //__builtin_va_list could be used instead
typedef char *va_list; typedef char *va_list;
#define va_start(v, l) ((v) = (va_list) & (l) + sizeof(l)) #define va_start(v, l) ((v) = (va_list) & (l) + sizeof(l))

View File

@ -1,29 +0,0 @@
#pragma once
typedef enum { FALSE = 0, TRUE } bool_t;
#define NULL ((void *)0)
#if __x86_64__
typedef unsigned long size_t;
typedef long ssize_t;
typedef unsigned long int uintptr_t;
typedef long int intptr_t;
#else
typedef unsigned int size_t;
typedef int ssize_t;
typedef unsigned int uintptr_t;
typedef int intptr_t;
#endif
#if __x86_64__
typedef unsigned long size_t;
typedef long ssize_t;
typedef unsigned long int uintptr_t;
typedef long int intptr_t;
#else
typedef unsigned int size_t;
typedef int ssize_t;
typedef unsigned int uintptr_t;
typedef int intptr_t;
#endif
typedef int wchar_t;

View File

@ -1,64 +0,0 @@
#pragma once
typedef __signed__ char __s8;
typedef unsigned char __u8;
typedef __signed__ short __s16;
typedef unsigned short __u16;
typedef __signed__ int __s32;
typedef unsigned int __u32;
#ifdef __GNUC__
__extension__ typedef __signed__ long long __s64;
__extension__ typedef unsigned long long __u64;
#else
typedef __signed__ long long __s64;
typedef unsigned long long __u64;
#endif
/* sysv */
typedef unsigned char unchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;
typedef __s8 int8_t;
typedef __s16 int16_t;
typedef __s32 int32_t;
typedef __u8 uint8_t;
typedef __u16 uint16_t;
typedef __u32 uint32_t;
typedef __u64 uint64_t;
typedef __u64 u_int64_t;
typedef __s64 int64_t;
#define USHRT_MAX ((u16)(~0U))
#define SHRT_MAX ((s16)(USHRT_MAX >> 1))
#define SHRT_MIN ((s16)(-SHRT_MAX - 1))
#define INT_MAX ((int)(~0U >> 1))
#define INT_MIN (-INT_MAX - 1)
#define UINT_MAX (~0U)
#define LONG_MAX ((long)(~0UL >> 1))
#define LONG_MIN (-LONG_MAX - 1)
#define ULONG_MAX (~0UL)
#define LLONG_MAX ((long long)(~0ULL >> 1))
#define LLONG_MIN (-LLONG_MAX - 1)
#define ULLONG_MAX (~0ULL)
#define SIZE_MAX (~(size_t)0)
#define PHYS_ADDR_MAX (~(phys_addr_t)0)
#define U8_MAX ((u8)~0U)
#define S8_MAX ((s8)(U8_MAX >> 1))
#define S8_MIN ((s8)(-S8_MAX - 1))
#define U16_MAX ((u16)~0U)
#define S16_MAX ((s16)(U16_MAX >> 1))
#define S16_MIN ((s16)(-S16_MAX - 1))
#define U32_MAX ((u32)~0U)
#define S32_MAX ((s32)(U32_MAX >> 1))
#define S32_MIN ((s32)(-S32_MAX - 1))
#define U64_MAX ((u64)~0ULL)
#define S64_MAX ((s64)(U64_MAX >> 1))
#define S64_MIN ((s64)(-S64_MAX - 1))

View File

@ -1,15 +1,11 @@
#include "syscall.h" #include "syscall.h"
#include "kernel.h"
#include "keyboard.h" #include "keyboard.h"
#include "klibc.h" #include "klibc.h"
#include "paging.h"
#include "process.h" #include "process.h"
#include "stdarg.h" #include "stdarg.h"
#include "thread.h" #include "thread.h"
#include "types.h" #include "types.h"
#include "uaccess.h"
#include "uaddrspace.h" #include "uaddrspace.h"
#include "zero.h"
int syscallExecute(int syscallId, const struct cpu_state *userCtx) int syscallExecute(int syscallId, const struct cpu_state *userCtx)
{ {
@ -44,150 +40,21 @@ int syscallExecute(int syscallId, const struct cpu_state *userCtx)
printf("Got 5args from userspace %d %d %d %d %d\n", arg1, arg2, arg3, arg4, arg5); printf("Got 5args from userspace %d %d %d %d %d\n", arg1, arg2, arg3, arg4, arg5);
break; break;
} }
case SYSCALL_ID_BRK: { case SYSCALL_ID_BRK:{
struct uAddrSpace *as; struct uAddrSpace *as;
uaddr_t newHeapTop; uaddr_t newHeapTop;
as = processGetAddrSpace(getCurrentThread()->process); as = processGetAddrSpace(getCurrentThread()->process);
ret = syscallGet1arg(userCtx, (unsigned int *)&newHeapTop); ret = syscallGet1arg(userCtx, (unsigned int *)&newHeapTop);
if (ret != 0) if (ret != 0)
break; break;
threadChangeCurrentContext(uAddrSpaceGetMMUContext(as)); threadChangeCurrentContext(uAddrSpaceGetMMUContext(as));
// TODO : what if *newHeapTop raise page fault? //TODO : what if *newHeapTop raise page fault?
ret = sysBrk(as, newHeapTop); ret = sysBrk(as, newHeapTop);
threadChangeCurrentContext(NULL); threadChangeCurrentContext(NULL);
break; break;
} }
case SYSCALL_ID_MMAP: {
struct uAddrSpace *as;
uaddr_t uaddr;
uaddr_t uaddr_ptr;
size_t size;
uint32_t rights;
uint32_t flags;
uaddr_t userPath;
char path[256];
as = processGetAddrSpace(getCurrentThread()->process);
ret = syscallGet5args(userCtx, (unsigned int *)&uaddr_ptr, (unsigned int *)&size,
(unsigned int *)&rights, (unsigned int *)&flags,
(unsigned int *)&userPath);
if (ret)
break;
if (memcpyFromUser((vaddr_t)&uaddr, uaddr_ptr, sizeof(uaddr)) != sizeof(uaddr)) {
ret = -EFAULT;
break;
}
strzcpyFromUser((vaddr_t *)path, (uaddr_t *)userPath, sizeof(path));
printf("Trying mmap for device %s at %lu\n", path, (vaddr_t)uaddr);
if (strcmp(path, "/dev/zero") == 0) {
ret = zeroMmap(as, &uaddr, size, rights, flags);
}
if (!ret) {
if (memcpyToUser(uaddr_ptr, (vaddr_t)&uaddr, sizeof(uaddr)) != sizeof(uaddr)) {
ret = -EFAULT;
break;
}
}
break;
}
case SYSCALL_ID_MUNMAP: {
struct uAddrSpace *as;
uaddr_t uaddr;
size_t size;
ret = syscallGet2args(userCtx, (unsigned int *)&uaddr, (unsigned int *)&size);
if (ret)
break;
as = processGetAddrSpace(getCurrentThread()->process);
ret = uAddrSpaceUnmap(as, uaddr, size);
break;
}
case SYSCALL_ID_NEW_THREAD: {
struct uAddrSpace *as;
thread_id_t threadIdPtr;
thread_id_t threadId;
uaddr_t funcAddr;
uint32_t arg1, arg2;
size_t stackSize;
ret = syscallGet5args(userCtx, (unsigned int *)&threadIdPtr,
(unsigned int *)&funcAddr, (unsigned int *)&arg1,
(unsigned int *)&arg2, (unsigned int *)&stackSize);
if (ret)
break;
if (stackSize <= 0) {
ret = -EINVAL;
break;
}
if (memcpyFromUser((vaddr_t)&threadId, threadIdPtr, sizeof(threadId)) !=
sizeof(threadId)) {
ret = -EFAULT;
break;
}
as = processGetAddrSpace(getCurrentThread()->process);
stackSize = ALIGN(stackSize, PAGE_SIZE);
uaddr_t stackAddr = 0;
ret = zeroMmap(as, &stackAddr, stackSize, PAGING_MEM_READ | PAGING_MEM_WRITE, 0);
if (ret)
break;
struct thread *th = threadCreateUser(NULL, getCurrentThread()->process, funcAddr,
arg1, arg2, stackAddr + stackSize);
if (th == NULL) {
ret = -ENOMEM;
uAddrSpaceUnmap(as, stackAddr, stackSize);
}
threadId = threadGetId(th);
if (memcpyToUser(threadIdPtr, (vaddr_t)&threadId, sizeof(threadId)) !=
sizeof(threadId)) {
ret = -EFAULT;
break;
}
break;
}
case SYSCALL_ID_USLEEP: {
unsigned int sleep;
ret = syscallGet1arg(userCtx, &sleep);
if (ret)
break;
ret = threadUsleep(sleep);
break;
}
case SYSCALL_ID_GETPID: {
ret = processGetId(getCurrentThread()->process);
break;
}
case SYSCALL_ID_GETTID: {
ret = threadGetId(getCurrentThread());
break;
}
case SYSCALL_ID_THREAD_JOIN: {
thread_id_t tid;
ret = syscallGet1arg(userCtx, (unsigned int *)&tid);
if (ret)
break;
ret = processJoinThread(getCurrentThread()->process, tid);
break;
}
default: default:
printf("Unknon syscall id %d\n", syscallId); printf("Unknon syscall id %d\n", syscallId);
ret = -ENOENT; ret = -ENOENT;

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#ifdef __KERNEL__ #ifdef __KERNEL__
#include "cpu_context.h" #include "cpu_context.h"
#endif #endif
#define SYSCALL_ID_EXIT 1 #define SYSCALL_ID_EXIT 1
@ -8,14 +8,7 @@
#define SYSCALL_ID_PUTC 3 #define SYSCALL_ID_PUTC 3
#define SYSCALL_ID_READ 4 #define SYSCALL_ID_READ 4
#define SYSCALL_ID_TEST 5 #define SYSCALL_ID_TEST 5
#define SYSCALL_ID_BRK 6 #define SYSCALL_ID_BRK 6
#define SYSCALL_ID_MMAP 7
#define SYSCALL_ID_MUNMAP 8
#define SYSCALL_ID_NEW_THREAD 9
#define SYSCALL_ID_USLEEP 10
#define SYSCALL_ID_GETPID 11
#define SYSCALL_ID_GETTID 12
#define SYSCALL_ID_THREAD_JOIN 13
#ifdef __KERNEL__ #ifdef __KERNEL__
int syscallExecute(int syscallId, const struct cpu_state *user_ctx); int syscallExecute(int syscallId, const struct cpu_state *user_ctx);

View File

@ -12,12 +12,6 @@
static struct thread *currentThread; static struct thread *currentThread;
static struct thread *threadWithTimeout; static struct thread *threadWithTimeout;
static thread_id_t nextTid; // This is the TID for kernel thread ONLY
pid_t threadGetId(struct thread *th)
{
return th->tid;
}
static void threadPrepareContext(struct thread *th); static void threadPrepareContext(struct thread *th);
@ -89,9 +83,7 @@ struct thread *threadCreate(const char *name, cpu_kstate_function_arg1_t func, v
(cpu_kstate_function_arg1_t *)threadExit, 0)) (cpu_kstate_function_arg1_t *)threadExit, 0))
goto free_mem; goto free_mem;
thread->state = READY; thread->state = READY;
thread->tid = nextTid++;
thread->wqExit = NULL;
uint32_t flags; uint32_t flags;
disable_IRQs(flags); disable_IRQs(flags);
list_add_tail(currentThread, thread); list_add_tail(currentThread, thread);
@ -118,14 +110,6 @@ struct thread *threadCreateUser(const char *name, struct process *proc, uaddr_t
} }
thread->stackSize = THREAD_DEFAULT_STACK_SIZE; thread->stackSize = THREAD_DEFAULT_STACK_SIZE;
thread->wqExit = (struct wait_queue * )malloc(sizeof(struct wait_queue));
if (!thread->wqExit) {
free((void *)thread->stackAddr);
free(thread);
return NULL;
}
waitQueueInit(thread->wqExit);
if (name) if (name)
strzcpy(thread->name, name, THREAD_NAME_MAX_LENGTH); strzcpy(thread->name, name, THREAD_NAME_MAX_LENGTH);
else else
@ -140,7 +124,6 @@ struct thread *threadCreateUser(const char *name, struct process *proc, uaddr_t
goto free_mem; goto free_mem;
thread->state = READY; thread->state = READY;
thread->tid = processGetNextTid(proc);
uint32_t flags; uint32_t flags;
disable_IRQs(flags); disable_IRQs(flags);
list_add_tail(currentThread, thread); list_add_tail(currentThread, thread);
@ -160,14 +143,9 @@ void threadDelete(struct thread *thread)
restore_IRQs(flags); restore_IRQs(flags);
assert(thread->state == EXITING); assert(thread->state == EXITING);
if (thread->wqExit) {
waitUp(thread->wqExit);
}
if (thread->squattedContext) { if (thread->squattedContext) {
mmuContextUnref(thread->squattedContext); threadChangeCurrentContext(NULL);
} }
if (thread->process) if (thread->process)
processRemoveThread(thread); processRemoveThread(thread);
@ -232,18 +210,17 @@ int threadOnJieffiesTick()
disable_IRQs(flags); disable_IRQs(flags);
list_foreach(currentThread, nextThread, idx) list_foreach(currentThread, nextThread, idx)
{ {
if (nextThread->state == SLEEPING) { if (nextThread->state == SLEEPING && nextThread->jiffiesSleeping) {
if (nextThread->jiffiesSleeping) nextThread->jiffiesSleeping--;
nextThread->jiffiesSleeping--; if (!nextThread->jiffiesSleeping) {
if (!nextThread->jiffiesSleeping)
nextThread->state = READY; nextThread->state = READY;
}
} }
} }
list_foreach_named(threadWithTimeout, nextThread, idx, timePrev, timeNext) list_foreach_named(threadWithTimeout, nextThread, idx, timePrev, timeNext)
{ {
if (nextThread->state == WAITING) { if (nextThread->state == WAITING && nextThread->jiffiesSleeping) {
if (nextThread->jiffiesSleeping) nextThread->jiffiesSleeping--;
nextThread->jiffiesSleeping--;
if (!nextThread->jiffiesSleeping) { if (!nextThread->jiffiesSleeping) {
nextThread->sleepHaveTimeouted = 1; nextThread->sleepHaveTimeouted = 1;
list_delete_named(threadWithTimeout, nextThread, timePrev, timeNext); list_delete_named(threadWithTimeout, nextThread, timePrev, timeNext);
@ -315,11 +292,6 @@ int threadYield()
} }
int threadMsleep(unsigned long msec) int threadMsleep(unsigned long msec)
{
return threadUsleep(msec*1000);
}
int threadUsleep(unsigned long usec)
{ {
uint32_t flags; uint32_t flags;
struct thread *next, *current; struct thread *next, *current;
@ -327,12 +299,12 @@ int threadUsleep(unsigned long usec)
disable_IRQs(flags); disable_IRQs(flags);
current = currentThread; current = currentThread;
assertmsg(current->state == RUNNING, "thread %s is in state %d for %lu us\n", current->name, assertmsg(current->state == RUNNING, "thread %s is in state %d for %lu\n", current->name,
current->state, usec); current->state, msec);
current->state = SLEEPING; current->state = SLEEPING;
current->sleepHaveTimeouted = 0; current->sleepHaveTimeouted = 0;
current->jiffiesSleeping = usecs_to_jiffies(usec); current->jiffiesSleeping = msecs_to_jiffies(msec);
next = threadSelectNext(); next = threadSelectNext();
assert(next != current); assert(next != current);

View File

@ -4,7 +4,6 @@ struct thread;
#include "cpu_context.h" #include "cpu_context.h"
#include "mem.h" #include "mem.h"
#include "process.h" #include "process.h"
#include "wait.h"
#define THREAD_NAME_MAX_LENGTH 32 #define THREAD_NAME_MAX_LENGTH 32
#define THREAD_DEFAULT_STACK_SIZE PAGE_SIZE #define THREAD_DEFAULT_STACK_SIZE PAGE_SIZE
@ -18,11 +17,8 @@ typedef enum {
EXITING EXITING
} thread_state; } thread_state;
typedef unsigned long int thread_id_t;
struct thread { struct thread {
char name[THREAD_NAME_MAX_LENGTH]; char name[THREAD_NAME_MAX_LENGTH];
thread_id_t tid;
struct cpu_state *cpuState; struct cpu_state *cpuState;
thread_state state; thread_state state;
vaddr_t stackAddr; vaddr_t stackAddr;
@ -36,7 +32,6 @@ struct thread {
// For User thread only // For User thread only
struct thread *nextInProcess, *prevInProcess; struct thread *nextInProcess, *prevInProcess;
struct process *process; struct process *process;
struct wait_queue *wqExit; // This will be signaled at thread exit (user only)
/** /**
* Address space currently "squatted" by the thread, or used to be * Address space currently "squatted" by the thread, or used to be
@ -88,10 +83,8 @@ int threadYield();
int threadWait(struct thread *current, struct thread *next, unsigned long msec); int threadWait(struct thread *current, struct thread *next, unsigned long msec);
int threadUnsched(struct thread *th); int threadUnsched(struct thread *th);
int threadMsleep(unsigned long msec); int threadMsleep(unsigned long msec);
int threadUsleep(unsigned long usec);
int threadOnJieffiesTick(); int threadOnJieffiesTick();
struct thread *getCurrentThread(); struct thread *getCurrentThread();
int threadAddThread(struct thread *th); int threadAddThread(struct thread *th);
int threadChangeCurrentContext(struct mmu_context *ctx); int threadChangeCurrentContext(struct mmu_context *ctx);
int threadCount(); int threadCount();
thread_id_t threadGetId(struct thread *th);

View File

@ -1,6 +1,4 @@
#include "time.h" #include "time.h"
#include "stddef.h"
#include <stdint.h>
unsigned long volatile jiffies = INITIAL_JIFFIES; unsigned long volatile jiffies = INITIAL_JIFFIES;

View File

@ -1,5 +1,5 @@
#pragma once #pragma once
#include "stdint.h" #include <stdint.h>
#define HZ 100 #define HZ 100
/* /*

View File

@ -1,5 +1,32 @@
#pragma once #pragma once
#define USHRT_MAX ((u16)(~0U))
#define SHRT_MAX ((s16)(USHRT_MAX >> 1))
#define SHRT_MIN ((s16)(-SHRT_MAX - 1))
#define INT_MAX ((int)(~0U >> 1))
#define INT_MIN (-INT_MAX - 1)
#define UINT_MAX (~0U)
#define LONG_MAX ((long)(~0UL >> 1))
#define LONG_MIN (-LONG_MAX - 1)
#define ULONG_MAX (~0UL)
#define LLONG_MAX ((long long)(~0ULL >> 1))
#define LLONG_MIN (-LLONG_MAX - 1)
#define ULLONG_MAX (~0ULL)
#define SIZE_MAX (~(size_t)0)
#define PHYS_ADDR_MAX (~(phys_addr_t)0)
#define U8_MAX ((u8)~0U)
#define S8_MAX ((s8)(U8_MAX >> 1))
#define S8_MIN ((s8)(-S8_MAX - 1))
#define U16_MAX ((u16)~0U)
#define S16_MAX ((s16)(U16_MAX >> 1))
#define S16_MIN ((s16)(-S16_MAX - 1))
#define U32_MAX ((u32)~0U)
#define S32_MAX ((s32)(U32_MAX >> 1))
#define S32_MIN ((s32)(-S32_MAX - 1))
#define U64_MAX ((u64)~0ULL)
#define S64_MAX ((s64)(U64_MAX >> 1))
#define S64_MIN ((s64)(-S64_MAX - 1))
// Virtual address // Virtual address
typedef unsigned long vaddr_t; typedef unsigned long vaddr_t;

View File

@ -1,12 +1,10 @@
#include "uaccess.h"
#include "assert.h" #include "assert.h"
#include "errno.h" #include "errno.h"
#include "minmax.h"
#include "mmuContext.h" #include "mmuContext.h"
#include "paging.h" #include "paging.h"
#include "process.h" #include "process.h"
#include "thread.h" #include "thread.h"
#include "types.h" #include "uaccess.h"
static int bindtoUserContext() static int bindtoUserContext()
{ {
@ -44,17 +42,6 @@ static int memcpyUserMemNoCheck(vaddr_t dest, vaddr_t src, size_t size)
return size; return size;
} }
int memcpyToUser(uaddr_t to, vaddr_t from, size_t size)
{
if ((uint)to < PAGING_BASE_USER_ADDRESS)
return -EPERM;
if ((uint)to > PAGING_TOP_USER_ADDRESS - size)
return -EPERM;
return memcpyUserMemNoCheck(to, from, size);
}
int memcpyFromUser(vaddr_t to, uaddr_t from, size_t size) int memcpyFromUser(vaddr_t to, uaddr_t from, size_t size)
{ {
@ -65,37 +52,3 @@ int memcpyFromUser(vaddr_t to, uaddr_t from, size_t size)
return memcpyUserMemNoCheck(to, from, size); return memcpyUserMemNoCheck(to, from, size);
} }
static int strzcpyFromUserNoCheck(char *to, char *from, size_t size)
{
int ret;
ret = bindtoUserContext();
if (ret != 0)
return ret;
for (unsigned int i = 0; i < size; i++) {
to[i] = from[i];
if (from[i] == '\0')
break;
}
if (size > 0)
to[size - 1] = '\0';
ret = unbindUserContext();
if (ret != 0)
return ret;
return size;
}
int strzcpyFromUser(vaddr_t *to, uaddr_t *from, size_t size)
{
if ((uint)from < PAGING_BASE_USER_ADDRESS)
return -EPERM;
if ((uint)from > PAGING_TOP_USER_ADDRESS - size)
return -EPERM;
return strzcpyFromUserNoCheck((char *)to, (char *)from, size);
}

View File

@ -1,8 +1,5 @@
#pragma once #pragma once
#include "types.h" #include "types.h"
#include "stddef.h"
#include "stdarg.h" #include "stdarg.h"
int memcpyFromUser(vaddr_t to, uaddr_t from, size_t size); int memcpyFromUser(vaddr_t to, uaddr_t from, size_t size);
int memcpyToUser(uaddr_t to, vaddr_t from, size_t size);
int strzcpyFromUser(vaddr_t *to, uaddr_t *from, size_t size);

View File

@ -1,6 +1,5 @@
#include "uaddrspace.h" #include "uaddrspace.h"
#include "alloc.h" #include "alloc.h"
#include "errno.h"
#include "kernel.h" #include "kernel.h"
#include "klibc.h" #include "klibc.h"
#include "list.h" #include "list.h"
@ -15,6 +14,18 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
struct uAddrVirtualReg {
uaddr_t addr;
size_t size;
int right; // PAGING_MEM_*
uint32_t offset; // in the mappedRessource
uint flags;
struct mappedRessource *res;
struct uAddrVirtualReg *nextInAddrSpace, *prevInAddrSpace;
struct uAddrVirtualReg *nextInMappedRes, *prevInMappedRes;
};
struct uAddrSpace { struct uAddrSpace {
struct process *process; // The process that is represented by this AS struct process *process; // The process that is represented by this AS
struct mmu_context *ctx; // The corresponding MMU configuration struct mmu_context *ctx; // The corresponding MMU configuration
@ -22,85 +33,22 @@ struct uAddrSpace {
struct uAddrVirtualReg *listVirtualReg; // List of Virtual Region used by this process struct uAddrVirtualReg *listVirtualReg; // List of Virtual Region used by this process
uaddr_t heapStart; // Start of the Head uaddr_t heapStart; // Start of the Head
size_t heapSize; // Heap size -> modified by brk() size_t heapSize; // Hep size -> modified by brk()
}; };
static int hasOverlap(uaddr_t addr1, size_t size1, uaddr_t addr2, size_t size2) struct mappedRessourceOps {
{ int (*open)(struct uAddrVirtualReg *vreg);
return max(addr1, addr2) < min(addr1 + size1, addr2 + size2); int (*close)(struct uAddrVirtualReg *vreg);
} int (*unmap)(struct uAddrVirtualReg *vregi, uaddr_t addr, size_t size);
int (*nopage)(struct uAddrVirtualReg *vregi, uaddr_t addr,
int right); // Called by the pageflt handler when the page is missing
};
static struct uAddrVirtualReg *findVirtualRegionFromAddr(struct uAddrSpace *as, uaddr_t uaddr, size_t size) struct mappedRessource {
{ int right; // PAGING_MEM_*
struct uAddrVirtualReg *reg; struct mappedRessourceOps *ops;
int idx; struct uAddrVirtualReg *listVirtualReg;
};
list_foreach_named(as->listVirtualReg, reg, idx, prevInAddrSpace, nextInAddrSpace)
{
if (hasOverlap(reg->addr, reg->size, uaddr, size))
return reg;
}
return NULL;
}
static struct uAddrVirtualReg *findVirtualRegionBeforeAddr(struct uAddrSpace *as,
uaddr_t uaddr)
{
struct uAddrVirtualReg *reg, *prev = NULL;
int idx;
list_foreach_named(as->listVirtualReg, reg, idx, prevInAddrSpace, nextInAddrSpace)
{
if (uaddr < reg->addr)
break;
prev = reg;
}
return prev;
}
/**
* Find a address not alreay used in the virtual region of the AS.
* This address will be equals to uaddr if possible and could take size
*/
static uaddr_t findFreeAddrInVirtualRegion(struct uAddrSpace *as, uaddr_t uaddr, size_t size)
{
struct uAddrVirtualReg *reg, *regNext, *regOver;
if (uaddr < PAGING_BASE_USER_ADDRESS)
uaddr = PAGING_BASE_USER_ADDRESS;
if(uaddr > PAGING_TOP_USER_ADDRESS - size)
uaddr = PAGING_TOP_USER_ADDRESS - size;
reg = findVirtualRegionFromAddr(as, uaddr, size);
if (!reg)
return uaddr;
int idx;
regOver = reg;
//Find last region that overlap
list_foreach_named(reg->nextInAddrSpace, regNext, idx, prevInAddrSpace, nextInAddrSpace){
if(!hasOverlap(uaddr, size, regNext->addr, regNext->size))
break;
regOver = regNext;
}
uaddr = regOver->addr + regOver->size;
list_foreach_named(regOver->nextInAddrSpace, regNext, idx, prevInAddrSpace,
nextInAddrSpace)
{
if (!hasOverlap(uaddr, size, regNext->addr, regNext->size) &&
uaddr <= (PAGING_TOP_USER_ADDRESS - size)) {
return uaddr;
}
if (reg == regNext) // Already checked region
break;
uaddr = regNext->addr + regNext->size;
}
return (uaddr_t)NULL;
}
struct uAddrSpace *uAddrSpaceCreate(struct process *proc) struct uAddrSpace *uAddrSpaceCreate(struct process *proc)
{ {
@ -128,120 +76,16 @@ int uAddrSpaceDelete(struct uAddrSpace *addr)
struct uAddrVirtualReg *reg; struct uAddrVirtualReg *reg;
list_collapse_named(addr->listVirtualReg, reg, nextInAddrSpace, prevInAddrSpace) { list_collapse_named(addr->listVirtualReg, reg, nextInAddrSpace, prevInAddrSpace) {
if (reg->res == NULL) { // TODO Implement me with real ressources
// This is memory allocated for the heap just unmap it to free it assertmsg(reg->res == NULL, "Unsupported mapper ressource");
pr_devel("Freeing heap 0x%lx for process %s\n", reg->addr, // This is memory allocated for the heap just unmap it to free it
processGetName(addr->process)); pr_devel("Freeing heap 0x%lx for process %s\n", reg->addr, processGetName(addr->process));
pageUnmap(reg->addr); pageUnmap(reg->addr);
free(reg); free(reg);
} else {
if(reg->res->ops){
if(reg->res->ops->unmap)
reg->res->ops->unmap(reg, reg->addr, reg->size);
if(reg->res->ops->close)
reg->res->ops->close(reg);
}
free(reg);
}
} }
return mmuContextUnref(addr->ctx); return mmuContextUnref(addr->ctx);
} }
/**
* Find the associated uAddrVirtualReg associated to the unmap space and free them;
*/
int uAddrSpaceUnmap(struct uAddrSpace *as, uaddr_t uaddr, size_t size)
{
if (uaddr < PAGING_BASE_USER_ADDRESS || uaddr > PAGING_TOP_USER_ADDRESS - size)
return -EINVAL;
if (!IS_ALIGNED(uaddr, PAGE_SIZE) || size <= 0)
return -EINVAL;
if(!as)
return -EINVAL;
size = ALIGN(size, PAGE_SIZE);
struct uAddrVirtualReg *reg = as->listVirtualReg;
struct uAddrVirtualReg *lastReg = reg ? reg->prevInAddrSpace : NULL;
while (reg != NULL) {
if (reg->addr > uaddr + size)
break;
struct uAddrVirtualReg *next = reg->nextInAddrSpace;
// The Virtual Region is completly inside the unmaped space
if (reg->addr >= uaddr && (reg->addr + reg->size <= uaddr + size)) {
list_delete_named(as->listVirtualReg, reg, prevInAddrSpace, nextInAddrSpace);
list_delete_named(reg->res->listVirtualReg, reg, prevInMappedRes, nextInMappedRes);
if (reg->res->ops && reg->res->ops->unmap)
reg->res->ops->unmap(reg, uaddr, size);
if (reg->res->ops && reg->res->ops->close)
reg->res->ops->close(reg);
if (reg == next)//singleton
next = NULL;
free(reg);
// Unmaped space is inside and smaller than the VR
// VR should be splitted
} else if (reg->addr > uaddr && (reg->addr + reg->size < uaddr + size)) {
struct uAddrVirtualReg *new =
(struct uAddrVirtualReg *)zalloc(sizeof(struct uAddrSpace));
if (!new)
return -ENOMEM;
new->addr = uaddr + size;
new->size = reg->addr + reg->size - (uaddr + size);
new->right = reg->right;
new->offset = uaddr + size - reg->addr;
reg->size = uaddr - reg->addr;
list_insert_after_named(as->listVirtualReg, reg, new, prevInAddrSpace,
nextInAddrSpace);
list_insert_after_named(reg->res->listVirtualReg, reg, new, prevInMappedRes,
nextInMappedRes);
if (reg->res->ops && reg->res->ops->unmap)
reg->res->ops->unmap(reg, uaddr, size);
if (new->res->ops && new->res->ops->open)
new->res->ops->open(new);
break;
// Only affect the beginning
} else if (uaddr <= reg->addr && uaddr + size > reg->addr) {
size_t offset = uaddr + size - reg->addr;
reg->size -= offset;
reg->offset += offset;
reg->addr += offset;
if (reg->res->ops && reg->res->ops->unmap)
reg->res->ops->unmap(reg, uaddr, size);
break;
// Only affect the end
} else if (uaddr > reg->addr && uaddr < reg->addr + size &&
uaddr + size > reg->addr + reg->size) {
size_t unmapSize = reg->addr + reg->size - uaddr;
reg->size = uaddr - reg->addr;
if (reg->res->ops && reg->res->ops->unmap)
reg->res->ops->unmap(reg, uaddr, unmapSize);
}
reg = next;
if (reg == lastReg)
break;
}
int needMMUSetup = as->ctx != getCurrentThread()->squattedContext;
if (needMMUSetup)
threadChangeCurrentContext(as->ctx);
for (vaddr_t addr = uaddr; addr < uaddr + size; addr += PAGE_SIZE) {
pageUnmap(addr);
}
if (needMMUSetup)
threadChangeCurrentContext(NULL);
return 0;
}
struct mmu_context *uAddrSpaceGetMMUContext(struct uAddrSpace *addr) struct mmu_context *uAddrSpaceGetMMUContext(struct uAddrSpace *addr)
{ {
return addr->ctx; return addr->ctx;
@ -270,6 +114,7 @@ uaddr_t sysBrk(struct uAddrSpace *as, uaddr_t newHeapTop)
incSize = ALIGN(newHeapTop - (as->heapStart + as->heapSize), PAGE_SIZE); incSize = ALIGN(newHeapTop - (as->heapStart + as->heapSize), PAGE_SIZE);
if (incSize < 0){ if (incSize < 0){
//TODO how to free allocated page by uAddrSpaceCheckNAlloc
return as->heapStart + as->heapSize; return as->heapStart + as->heapSize;
} }
@ -278,14 +123,12 @@ uaddr_t sysBrk(struct uAddrSpace *as, uaddr_t newHeapTop)
return as->heapStart + as->heapSize; return as->heapStart + as->heapSize;
} }
int uAddrSpaceHeapCheckNAlloc(struct uAddrSpace *as, vaddr_t addr) int uAddrSpaceCheckNAlloc(struct uAddrSpace *as, vaddr_t addr)
{ {
struct uAddrVirtualReg *newReg; struct uAddrVirtualReg *newReg;
int right = PAGING_MEM_USER | PAGING_MEM_WRITE | PAGING_MEM_READ; int right = PAGING_MEM_USER | PAGING_MEM_WRITE | PAGING_MEM_READ;
pr_devel("Heap check: 0x%lx inside 0x%lx and 0x%lx\n", addr, as->heapStart, pr_devel("Checking 0x%lx inside 0x%lx and 0x%lx\n", addr, as->heapStart, as->heapStart +as->heapSize);
as->heapStart + as->heapSize);
if (addr < as->heapStart || addr >= as->heapStart + as->heapSize) { if (addr < as->heapStart || addr >= as->heapStart + as->heapSize) {
return -1; return -1;
} }
@ -307,13 +150,7 @@ int uAddrSpaceHeapCheckNAlloc(struct uAddrSpace *as, vaddr_t addr)
newReg->size = PAGE_SIZE; newReg->size = PAGE_SIZE;
newReg->right = right; newReg->right = right;
// keep the AS list sorted list_add_tail_named(as->listVirtualReg, newReg, nextInAddrSpace, prevInAddrSpace);
struct uAddrVirtualReg *prev = findVirtualRegionBeforeAddr(as, addrAlign);
if (prev)
list_insert_after_named(as->listVirtualReg, prev, newReg, prevInAddrSpace,
nextInAddrSpace);
else
list_add_tail_named(as->listVirtualReg, newReg, nextInAddrSpace, prevInAddrSpace);
unrefPhyPage(ppage); unrefPhyPage(ppage);
@ -322,138 +159,3 @@ free_ppage:
unrefPhyPage(ppage); unrefPhyPage(ppage);
return -1; return -1;
} }
static struct uAddrVirtualReg *uAddrSpaceMergeVr(struct uAddrVirtualReg *prev,
struct uAddrVirtualReg *next)
{
if (prev && next && prev->addr + prev->size == next->addr && prev->right == next->right &&
prev->res == next->res && prev->flags == next->flags && prev->offset == next->offset) {
prev->size += next->size;
return next;
} else
return NULL;
}
int uAddrSpaceMmap(struct uAddrSpace *as, uaddr_t *uaddr, size_t size, uint32_t rights,
uint32_t flags, struct mappedRessource *res, uint32_t offset )
{
int ret = 0;
uaddr_t hint_uaddr = *uaddr;
if (res == NULL || res->ops == NULL || res->ops->nopage == NULL)
return -ENOENT;
if (!IS_ALIGNED(hint_uaddr, PAGE_SIZE) || size <= 0)
return -EINVAL;
if (flags & UA_MAP_SHARED) {
if (((rights & PAGING_MEM_READ) && !(res->allowedRight & PAGING_MEM_READ)) ||
((rights & PAGING_MEM_WRITE) && !(res->allowedRight & PAGING_MEM_WRITE)) ||
((rights & PAGING_MEM_EXEC) && !(res->allowedRight & PAGING_MEM_EXEC)))
return -EPERM;
}
size = ALIGN(size, PAGE_SIZE);
struct uAddrVirtualReg *reg =
(struct uAddrVirtualReg *)malloc(sizeof(struct uAddrVirtualReg));
if (!reg)
return -ENOMEM;
if (flags & UA_MAP_FIXED) {
if (hint_uaddr < PAGING_BASE_USER_ADDRESS ||
hint_uaddr > PAGING_TOP_USER_ADDRESS - size) {
ret = -EINVAL;
goto free_reg;
}
ret = uAddrSpaceUnmap(as, hint_uaddr, size);
if (ret)
goto free_reg;
} else {
hint_uaddr = findFreeAddrInVirtualRegion(as, hint_uaddr, size);
if (!hint_uaddr) {
ret = -ENOMEM;
goto free_reg;
}
}
reg->addr = hint_uaddr;
reg->size = size;
reg->right = rights;
reg->res = res;
reg->offset = offset;
// keep the AddrSpace list sorted
struct uAddrVirtualReg *prev = findVirtualRegionBeforeAddr(as, hint_uaddr);
bool_t regIsNew = TRUE;
if (prev) {
struct uAddrVirtualReg *toFree = uAddrSpaceMergeVr(prev, reg);
if (toFree) {
pr_devel("Merge VR with prev\n");
reg = prev;
regIsNew = FALSE;
free(toFree);
}
toFree = uAddrSpaceMergeVr(reg, prev->nextInAddrSpace);
if (toFree) {
pr_devel("Merge VR with next\n");
regIsNew = FALSE;
if (toFree->res && toFree->res->ops && toFree->res->ops->close)
toFree->res->ops->close(toFree);
list_delete_named(as->listVirtualReg, toFree, prevInAddrSpace, nextInAddrSpace);
list_delete_named(toFree->res->listVirtualReg, toFree, prevInMappedRes,
nextInMappedRes);
free(toFree);
}
if (regIsNew)
list_insert_after_named(as->listVirtualReg, prev, reg, prevInAddrSpace,
nextInAddrSpace);
} else
list_add_tail_named(as->listVirtualReg, reg, prevInAddrSpace, nextInAddrSpace);
if (regIsNew) {
list_add_tail_named(reg->res->listVirtualReg, reg, prevInMappedRes, nextInMappedRes);
if (res->onResMapped) {
int cbret = res->onResMapped(reg);
if (cbret) {
pr_devel("Call back failed on ressource mmaped\n");
ret = uAddrSpaceUnmap(as, reg->addr, reg->size);
}
}
if (res->ops->open)
res->ops->open(reg);
}
*uaddr = hint_uaddr;
return ret;
free_reg:
free(reg);
return ret;
}
/**
* Check if @param faultAddr could be managed by the uAddrVirtualReg from @param as
**/
int uAddrSpaceSolvePageFault(struct uAddrSpace *as, vaddr_t faultAddr, int isWriteAccess)
{
struct uAddrVirtualReg *reg;
int rights = PAGING_MEM_READ | PAGING_MEM_USER;
reg = findVirtualRegionFromAddr(as, faultAddr, 1);
if (reg == NULL)
return -EFAULT;
pr_devel("Virtual Region for pageflt found\n");
if (isWriteAccess && !(reg->right & PAGING_MEM_WRITE))
return -EACCES;
if (isWriteAccess || (reg->right & PAGING_MEM_WRITE))
rights |= PAGING_MEM_WRITE;
if (reg->res->ops->nopage(reg, faultAddr, rights))
return -EFAULT;
return 0;
}

View File

@ -1,54 +1,15 @@
#pragma once #pragma once
#include "mmuContext.h" #include "mmuContext.h"
#include "process.h" #include "process.h"
#include "stddef.h"
#include "stdint.h"
#include "types.h" #include "types.h"
#include <stddef.h>
struct uAddrSpace; struct uAddrSpace;
struct uAddrVirtualReg; struct uAddrVirtualReg;
#define UA_MAP_SHARED (1 << 0) struct uAddrSpace * uAddrSpaceCreate(struct process *proc);
#define UA_MAP_PRIVATE (1 << 1)
#define UA_MAP_FIXED (1 << 2)
// TODO : move this struct to .c and add accessors
struct uAddrVirtualReg {
uaddr_t addr;
size_t size;
int right; // PAGING_MEM_*
uint32_t offset; // in the mappedRessource
uint flags;
struct mappedRessource *res;
struct uAddrVirtualReg *nextInAddrSpace, *prevInAddrSpace;
struct uAddrVirtualReg *nextInMappedRes, *prevInMappedRes;
};
struct mappedRessourceOps {
int (*open)(struct uAddrVirtualReg *vreg);
int (*close)(struct uAddrVirtualReg *vreg);
int (*unmap)(struct uAddrVirtualReg *vreg, uaddr_t addr, size_t size);
int (*nopage)(struct uAddrVirtualReg *vreg, uaddr_t addr,
int right); // Called by the pageflt handler when the page is missing
};
struct mappedRessource {
int allowedRight; // PAGING_MEM_*
struct mappedRessourceOps *ops;
struct uAddrVirtualReg *listVirtualReg;
void *customData;
int (*onResMapped)(struct uAddrVirtualReg *reg); // Callabck for when the ressourced get mapped
};
struct uAddrSpace *uAddrSpaceCreate(struct process *proc);
int uAddrSpaceDelete(struct uAddrSpace *addr); int uAddrSpaceDelete(struct uAddrSpace *addr);
struct mmu_context *uAddrSpaceGetMMUContext(struct uAddrSpace *addr); struct mmu_context * uAddrSpaceGetMMUContext(struct uAddrSpace *addr);
int uAddrSpaceSetHeap(struct uAddrSpace *as, uaddr_t addr, size_t size); int uAddrSpaceSetHeap(struct uAddrSpace *as, uaddr_t addr, size_t size);
int uAddrSpaceHeapCheckNAlloc(struct uAddrSpace *as, vaddr_t addr); int uAddrSpaceCheckNAlloc(struct uAddrSpace *as, vaddr_t addr);
uaddr_t sysBrk(struct uAddrSpace *as, uaddr_t newHeapTop); uaddr_t sysBrk(struct uAddrSpace *as, uaddr_t newHeapTop);
int uAddrSpaceMmap(struct uAddrSpace *as, uaddr_t *uaddr, size_t size, uint32_t rights,
uint32_t flags, struct mappedRessource *res, uint32_t offset);
int uAddrSpaceUnmap(struct uAddrSpace *as, uaddr_t uaddr, size_t size);
int uAddrSpaceSolvePageFault(struct uAddrSpace *as, vaddr_t faultAddr, int isWriteAccess);

View File

@ -184,19 +184,18 @@ class ListDumpCmd(gdb.Command):
"list_dump", gdb.COMMAND_USER "list_dump", gdb.COMMAND_USER
) )
def _print_list(self, val, next_name): def _print_list(self, val):
"""Walk through the linked list. """Walk through the linked list.
We will simply follow the 'next' pointers until we encounter the HEAD again We will simply follow the 'next' pointers until we encounter the HEAD again
""" """
idx = 0 idx = 0
head = val head = val
thread_ptr = val thread_ptr = val
result = "" result = ""
while thread_ptr != 0 and (idx == 0 or thread_ptr != head): while thread_ptr != 0 and (idx == 0 or thread_ptr != head):
result += gdb.execute('p *({}){}'.format(str(thread_ptr.type), result += gdb.execute('p *({}){}'.format(str(thread_ptr.type),thread_ptr), to_string=True)
thread_ptr), to_string=True) thread_ptr = thread_ptr["next"]
thread_ptr = thread_ptr[next_name]
idx += 1 idx += 1
result = ("Found a Linked List with %d items:" % idx) + "\n" + result result = ("Found a Linked List with %d items:" % idx) + "\n" + result
return result return result
@ -210,21 +209,17 @@ class ListDumpCmd(gdb.Command):
# We can pass args here and use Python CLI utilities like argparse # We can pass args here and use Python CLI utilities like argparse
# to do argument parsing # to do argument parsing
print("Args Passed: %s" % args) print("Args Passed: %s" % args)
thread_name = "currentThread" if args:
next_name = "next" ptr_val = gdb.parse_and_eval(args)
if(args): else:
args_arr = args.split() ptr_val = gdb.parse_and_eval("currentThread")
thread_name = args_arr[0]
if(len(args_arr) >= 2):
next_name = args_arr[1]
ptr_val = gdb.parse_and_eval(thread_name)
try: try:
ptr_val[next_name] ptr_val["next"]
except: except:
print("Expected pointer argument with a %s field" % next_name) print("Expected pointer argument with a next field")
return return
print(self._print_list(ptr_val, next_name)) print(self._print_list(ptr_val))
register_pretty_printer(None, CustomPrettyPrinterLocator(), replace=True) register_pretty_printer(None, CustomPrettyPrinterLocator(), replace=True)

View File

@ -1,10 +0,0 @@
add-symbol-file userspace/user
# Thx to add-gnu-debuglink gdb should know that symbols are in kernel.debug.
# And by default, it should be looking at executable.debug
# But we still have to give him the executable he is suppose to debug (See https://sourceware.org/gdb/current/onlinedocs/gdb.html/Separate-Debug-Files.html)
#add-symbol-file kernel.debug
file kernel
source custom_gdb_extension.py
#For ASM sources
directory arch/x86/:core
target remote | qemu-system-i386 -S -gdb stdio -m 16M -serial file:serialOut -hda fd.iso -hdb disk.img

View File

@ -2,6 +2,7 @@ label: dos
label-id: 0x9ec19bcc label-id: 0x9ec19bcc
device: disk.img device: disk.img
unit: sectors unit: sectors
sector-size: 512
disk.img1 : start= 2048, size= 32768, type=6, bootable disk.img1 : start= 2048, size= 32768, type=6, bootable
disk.img2 : start= 34816, size= 30720, type=83 disk.img2 : start= 34816, size= 30720, type=83

View File

@ -521,19 +521,6 @@ struct ata_partition *ATAGetPartition(int id)
return NULL; return NULL;
} }
struct ata_partition *ATAGetPartitionByType(uint type)
{
struct ata_partition *part;
int count;
list_foreach(partitions, part, count)
{
if (part->type == type)
return part;
}
return NULL;
}
struct ata_partition *ATAPartitionCreate(uint type, uint size, uint32_t lba, struct ata_partition *ATAPartitionCreate(uint type, uint size, uint32_t lba,
struct ata_device *dev) struct ata_device *dev)
{ {

View File

@ -104,6 +104,5 @@ int ATAReadPartitionSector(struct ata_partition *part, int offset, uint nbSector
int ATAReadSector(struct ata_device *dev, int lba, uint nbSector, void *buf); int ATAReadSector(struct ata_device *dev, int lba, uint nbSector, void *buf);
int ATAWriteSector(struct ata_device *dev, int lba, uint nbSector, void *buf); int ATAWriteSector(struct ata_device *dev, int lba, uint nbSector, void *buf);
struct ata_device *ATAGetDevice(int ctlId, int devId); struct ata_device *ATAGetDevice(int ctlId, int devId);
struct ata_partition *ATAGetPartitionByType(uint type);
int ATAReadPartition(struct ata_device *dev); int ATAReadPartition(struct ata_device *dev);
struct ata_partition *ATAGetPartition(int id); struct ata_partition *ATAGetPartition(int id);

View File

@ -1,5 +1,5 @@
#pragma once #pragma once
#include "stdint.h" #include "stdarg.h"
#include "types.h" #include "types.h"
// https://wiki.osdev.org/Text_UI // https://wiki.osdev.org/Text_UI

View File

@ -1,124 +0,0 @@
#include "zero.h"
#include "alloc.h"
#include "errno.h"
#include "kernel.h"
#include "klibc.h"
#include "mem.h"
#include "list.h"
#include "paging.h"
#include "types.h"
struct zeroMappedPage {
uaddr_t mappedAddr;
paddr_t phyAddr;
struct zeroMappedPage *prev, *next;
};
struct zeroMappedEntry {
int refCnt;
struct zeroMappedPage *listMapped;
};
static int insertMappedPage(struct zeroMappedEntry *entry, uaddr_t vAddr, paddr_t pAddr){
struct zeroMappedPage *info = (struct zeroMappedPage *)zalloc(sizeof(struct zeroMappedPage));
if(!info)
return -ENOMEM;
info->mappedAddr = vAddr;
info->phyAddr = pAddr;
list_add_tail(entry->listMapped, info);
return 0;
}
static int zeroOpen(struct uAddrVirtualReg *vreg)
{
struct zeroMappedEntry *ent = (struct zeroMappedEntry *)vreg->res->customData;
ent->refCnt++;
return 0;
}
static int zeroClose(struct uAddrVirtualReg *vreg)
{
struct zeroMappedEntry *ent = (struct zeroMappedEntry *)vreg->res->customData;
ent->refCnt--;
if (ent->refCnt == 0) {
struct zeroMappedPage *pageInfo;
list_collapse(ent->listMapped, pageInfo){
pageUnmap(pageInfo->mappedAddr);
free(pageInfo);
}
free(vreg->res->customData);
free(vreg->res);
}
return 0;
}
static int zeroNoPage(struct uAddrVirtualReg *vreg, uaddr_t addr, int right)
{
int ret = 0;
paddr_t ppage = allocPhyPage(1);
uaddr_t mappedAddr = ALIGN_DOWN(addr, PAGE_SIZE);
ret = pageMap(mappedAddr, ppage, right | PAGING_MEM_USER);
struct zeroMappedEntry *ent = (struct zeroMappedEntry *)vreg->res->customData;
unrefPhyPage(ppage);
if (ret) {
return ret;
}
ret = insertMappedPage(ent, mappedAddr, ppage);
if (ret) {
pageUnmap(mappedAddr);
return ret;
}
memset((void *)mappedAddr, 0, PAGE_SIZE);
return ret;
}
static struct mappedRessourceOps zeroOps = {
.open = zeroOpen,
.close = zeroClose,
.unmap = NULL,
.nopage = zeroNoPage,
};
int zeroOnMapped(struct uAddrVirtualReg *vreg)
{
(void)vreg;
return 0;
}
int zeroMmap(struct uAddrSpace *as, uaddr_t *uaddr, size_t size, uint32_t rights,
uint32_t flags)
{
int ret = 0;
struct mappedRessource *res =
(struct mappedRessource *)zalloc(sizeof(struct mappedRessource));
struct zeroMappedEntry *cust =
(struct zeroMappedEntry *)zalloc(sizeof(struct zeroMappedEntry));
list_init(cust->listMapped);
res->allowedRight = PAGING_MEM_READ | PAGING_MEM_WRITE | PAGING_MEM_EXEC | PAGING_MEM_USER;
res->ops = &zeroOps;
res->customData = cust;
res->onResMapped = zeroOnMapped;
ret = uAddrSpaceMmap(as, uaddr, size, rights, flags, res, 0);
if (ret) {
free(res);
free(cust);
}
return ret;
}

View File

@ -1,11 +0,0 @@
#pragma once
#include "types.h"
#include "uaddrspace.h"
#include <stddef.h>
#include <stdint.h>
int zeroSetup();
int zeroMmap(struct uAddrSpace *as, uaddr_t *uaddr, size_t size, uint32_t rights, uint32_t flags);

View File

@ -306,8 +306,9 @@ void sleepThread(void *arg)
} }
unsigned long ellapsedTime = jiffies_to_msecs(jiffies - initialJiffies); unsigned long ellapsedTime = jiffies_to_msecs(jiffies - initialJiffies);
assertmsg(ellapsedTime >= 500 && ellapsedTime < 510, "ellapsedTime %lu\n", ellapsedTime); assertmsg(ellapsedTime >= 500 && ellapsedTime < 510, "ellapsedTime %lu\n", ellapsedTime);
threadMsleep(ULONG_MAX); threadMsleep(0);
assert(0); printf("I should never be showed\n");
assert(1);
} }
struct mutex mutexTest; struct mutex mutexTest;

View File

@ -1,37 +0,0 @@
#pragma once
extern int errno;
#define EPERM 1 /* Operation not permitted */
#define ENOENT 2 /* No such file or directory */
#define ESRCH 3 /* No such process */
#define EINTR 4 /* Interrupted system call */
#define EIO 5 /* I/O error */
#define ENXIO 6 /* No such device or address */
#define E2BIG 7 /* Argument list too long */
#define ENOEXEC 8 /* Exec format error */
#define EBADF 9 /* Bad file number */
#define ECHILD 10 /* No child processes */
#define EAGAIN 11 /* Try again */
#define ENOMEM 12 /* Out of memory */
#define EACCES 13 /* Permission denied */
#define EFAULT 14 /* Bad address */
#define ENOTBLK 15 /* Block device required */
#define EBUSY 16 /* Device or resource busy */
#define EEXIST 17 /* File exists */
#define EXDEV 18 /* Cross-device link */
#define ENODEV 19 /* No such device */
#define ENOTDIR 20 /* Not a directory */
#define EISDIR 21 /* Is a directory */
#define EINVAL 22 /* Invalid argument */
#define ENFILE 23 /* File table overflow */
#define EMFILE 24 /* Too many open files */
#define ENOTTY 25 /* Not a typewriter */
#define ETXTBSY 26 /* Text file busy */
#define EFBIG 27 /* File too large */
#define ENOSPC 28 /* No space left on device */
#define ESPIPE 29 /* Illegal seek */
#define EROFS 30 /* Read-only file system */
#define EMLINK 31 /* Too many links */
#define EPIPE 32 /* Broken pipe */
#define EDOM 33 /* Math argument out of domain of func */
#define ERANGE 34 /* Math result not representable */

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#ifdef __KERNEL__ #ifdef __KERNEL__
#include "cpu_context.h" #include "cpu_context.h"
#endif #endif
#define SYSCALL_ID_EXIT 1 #define SYSCALL_ID_EXIT 1
@ -8,14 +8,7 @@
#define SYSCALL_ID_PUTC 3 #define SYSCALL_ID_PUTC 3
#define SYSCALL_ID_READ 4 #define SYSCALL_ID_READ 4
#define SYSCALL_ID_TEST 5 #define SYSCALL_ID_TEST 5
#define SYSCALL_ID_BRK 6 #define SYSCALL_ID_BRK 6
#define SYSCALL_ID_MMAP 7
#define SYSCALL_ID_MUNMAP 8
#define SYSCALL_ID_NEW_THREAD 9
#define SYSCALL_ID_USLEEP 10
#define SYSCALL_ID_GETPID 11
#define SYSCALL_ID_GETTID 12
#define SYSCALL_ID_THREAD_JOIN 13
#ifdef __KERNEL__ #ifdef __KERNEL__
int syscallExecute(int syscallId, const struct cpu_state *user_ctx); int syscallExecute(int syscallId, const struct cpu_state *user_ctx);

View File

@ -1,14 +1,9 @@
#include "libc.h" #include "libc.h"
#include "errno.h"
#include "list.h" #include "list.h"
#include "minmax.h" #include "minmax.h"
#include "swintr.h" #include "swintr.h"
#include "sys/mman.h"
#include "syscall.h" #include "syscall.h"
#include "thread.h"
#include "unistd.h"
int errno = 0;
int memcmp(const void *aptr, const void *bptr, size_t size) int memcmp(const void *aptr, const void *bptr, size_t size)
{ {
const unsigned char *a = (const unsigned char *)aptr; const unsigned char *a = (const unsigned char *)aptr;
@ -85,16 +80,6 @@ void *memcpy(void *dst0, const void *src0, size_t len0)
#endif #endif
} }
void *memmove(void *dst, const void *src, size_t n)
{
char *dstChar = dst;
const char *srcChar = src;
for (size_t i = 0; i < n; i++) {
*(dstChar++) = *(srcChar++);
}
return dst;
}
void *memset(void *src, int c, size_t n) void *memset(void *src, int c, size_t n)
{ {
for (char *ptr = (char *)src; n > 0; n--, ptr++) { for (char *ptr = (char *)src; n > 0; n--, ptr++) {
@ -265,57 +250,8 @@ int puts(const char *str)
return ret; \ return ret; \
} }
#define PRINT_UINT(name, type) \
int print##name(type integer, char *str, size_t size) \
{ \
char num[sizeof(integer) * 3]; \
int i = 0; \
int c = 0; \
int ret = 0; \
\
do { \
int digit = integer % 10; \
num[i++] = (digit > 0) ? digit : -digit; \
integer = integer / 10; \
} while (integer != 0); \
\
for (i = i - 1; i >= 0; i--) { \
if (str) { \
if (size) { \
str[c++] = num[i] + '0'; \
size--; \
ret++; \
} else { \
return ret; \
} \
} else { \
ret++; \
} \
} \
return ret; \
}
PRINT_INT(Int, int); PRINT_INT(Int, int);
PRINT_INT(Lint, long int); PRINT_INT(Int64, long long int);
PRINT_INT(Llint, long long int);
PRINT_UINT(Uint, unsigned int);
PRINT_UINT(Luint, long unsigned int);
PRINT_UINT(Lluint, long long unsigned int);
#define PRINT_PART(func, type, str, size, c, ret) \
{ \
int s; \
type d = va_arg(ap, type); \
if (str) \
s = func(d, &str[c], size); \
else \
s = func(d, NULL, size); \
\
size -= s; \
c += s; \
ret += s; \
break; \
}
int vsnprintf(char *str, size_t size, const char *format, va_list ap) int vsnprintf(char *str, size_t size, const char *format, va_list ap)
{ {
@ -323,13 +259,24 @@ int vsnprintf(char *str, size_t size, const char *format, va_list ap)
int i = 0; int i = 0;
int c = 0; int c = 0;
while (format[i] != '\0' && (size|| !str)) { while (format[i] != '\0' && (size || !str)) {
switch (format[i]) { switch (format[i]) {
case '%': case '%':
switch (format[i + 1]) { switch (format[i + 1]) {
case 'i': case 'i':
case 'd': PRINT_PART(printInt, int, str, size, c, ret) case 'd': {
case 'u': PRINT_PART(printUint, uint, str, size, c, ret) int s;
int d = va_arg(ap, int);
if (str)
s = printInt(d, &str[c], size);
else
s = printInt(d, NULL, size);
size -= s;
c += s;
ret += s;
break;
}
case 'p': case 'p':
case 'x': { case 'x': {
char val[sizeof(int) * 2]; char val[sizeof(int) * 2];
@ -390,15 +337,24 @@ int vsnprintf(char *str, size_t size, const char *format, va_list ap)
switch (format[i + 2]) { switch (format[i + 2]) {
case 'l': case 'l':
switch (format[i + 3]) { switch (format[i + 3]) {
case 'i': case 'd': {
case 'd': PRINT_PART(printLlint, long long int, str, size, c, ret) int s;
case 'u': PRINT_PART(printLluint, long long unsigned int, str, size, c, ret) long long int d = va_arg(ap, long long int);
if (str)
s = printInt64(d, &str[c], size);
else
s = printInt64(d, NULL, size);
size -= s;
c += s;
ret += s;
break;
}
case 'p': case 'p':
case 'x': { case 'x': {
char val[sizeof(long long int) * 2]; char val[sizeof(long long int) * 2];
unsigned int valIdx = 0; unsigned int valIdx = 0;
unsigned long long int d = long long int d = va_arg(ap, long long int);
va_arg(ap, unsigned long long int);
itoa(d, val, 16); itoa(d, val, 16);
if (str) { if (str) {
while (val[valIdx]) { while (val[valIdx]) {
@ -419,28 +375,17 @@ int vsnprintf(char *str, size_t size, const char *format, va_list ap)
i++; i++;
break; break;
case 'i': case 'i':
case 'd': PRINT_PART(printLint, long int, str, size, c, ret) case 'd': {
case 'u': int s;
PRINT_PART(printLuint, long unsigned int, str, size, c, ret) long int d = va_arg(ap, long int);
case 'p': if (str)
case 'x': { s = printInt64(d, &str[c], size);
char val[sizeof(int) * 2]; else
unsigned int valIdx = 0; s = printInt64(d, NULL, size);
unsigned long int d = va_arg(ap, unsigned long int);
itoa(d, val, 16); size -= s;
if (str) { c += s;
while (val[valIdx]) { ret += s;
if (size) {
str[c++] = val[valIdx++];
size--;
ret++;
} else {
return ret;
}
}
} else {
ret += strlen(val);
}
break; break;
} }
} }
@ -657,25 +602,20 @@ struct heapBlock {
static struct heapBlock *heapBlkList = NULL; static struct heapBlock *heapBlkList = NULL;
static struct heapBlock *findFreeBlock(size_t size) struct heapBlock *findFreeBlock(size_t size){
{ struct heapBlock *cur = NULL;
struct heapBlock *cur = NULL;
struct heapBlock *found = NULL; struct heapBlock *found = NULL;
int idx; int idx;
list_foreach(heapBlkList, cur, idx){
list_foreach(heapBlkList, cur, idx) if(cur->size >= size && cur->free){
{
if (cur->size >= size && cur->free) {
found = cur; found = cur;
break; break;
} }
} }
return found; return found;
} }
static struct heapBlock *allocNewBlock(size_t size) struct heapBlock *allocNewBlock(size_t size) {
{
struct heapBlock *blk = sbrk(size + sizeof(struct heapBlock)); struct heapBlock *blk = sbrk(size + sizeof(struct heapBlock));
struct heapBlock *head = sbrk(0); struct heapBlock *head = sbrk(0);
size_t blkSize = (intptr_t)head - (intptr_t)blk - sizeof(struct heapBlock); size_t blkSize = (intptr_t)head - (intptr_t)blk - sizeof(struct heapBlock);
@ -685,11 +625,10 @@ static struct heapBlock *allocNewBlock(size_t size)
blk->size = blkSize; blk->size = blkSize;
blk->free = 1; blk->free = 1;
list_add_tail(heapBlkList, blk); list_add_tail(heapBlkList, blk);
return blk; return blk;
} }
static struct heapBlock *splitBlock(struct heapBlock *blk, size_t neededSize) struct heapBlock *splitBlock(struct heapBlock *blk, size_t neededSize)
{ {
if (blk->size < neededSize + sizeof(struct heapBlock) + 1) { if (blk->size < neededSize + sizeof(struct heapBlock) + 1) {
return NULL; return NULL;
@ -698,7 +637,6 @@ static struct heapBlock *splitBlock(struct heapBlock *blk, size_t neededSize)
newBlk->free = 1; newBlk->free = 1;
newBlk->size = blk->size - sizeof(struct heapBlock) - neededSize; newBlk->size = blk->size - sizeof(struct heapBlock) - neededSize;
blk->size = neededSize; blk->size = neededSize;
return newBlk; return newBlk;
} }
@ -717,18 +655,16 @@ void *malloc(size_t size)
list_add_head(heapBlkList, remainBlock); list_add_head(heapBlkList, remainBlock);
} }
blk->free = 0; blk->free = 0;
return blk + 1; // return the area after the blk description return blk + 1; // return the area after the blk description
} }
static struct heapBlock *getHeapBlock(void *ptr) struct heapBlock *getHeapBlock(void *ptr) {
{
return (struct heapBlock *)ptr - 1; return (struct heapBlock *)ptr - 1;
} }
void free(void *ptr)
{ void free(void *ptr){
if (!ptr) if(!ptr)
return; return;
struct heapBlock *blk = getHeapBlock(ptr); struct heapBlock *blk = getHeapBlock(ptr);
@ -737,90 +673,3 @@ void free(void *ptr)
blk->free = 1; blk->free = 1;
} }
void *calloc(size_t nmemb, size_t size)
{
size_t allocSize = nmemb * size;
void *ptr = malloc(allocSize);
if (ptr != NULL)
memset(ptr, 0, allocSize);
return ptr;
}
void *realloc(void *ptr, size_t size)
{
if (!ptr) {
return malloc(size);
}
struct heapBlock *blk = getHeapBlock(ptr);
if (blk->size >= size) {
return ptr;
}
void *new_ptr;
new_ptr = malloc(size);
if (!new_ptr) {
return NULL;
}
memmove(new_ptr, ptr, blk->size);
free(ptr);
return new_ptr;
}
void *mmap(void *addr, size_t len, int prot, int flags, char *path) {
int ret = syscall5(SYSCALL_ID_MMAP, (unsigned int)&addr, len, prot, flags, (unsigned int)path);
if(!ret)
return addr;
errno = ret;
return MAP_FAILED;
}
int munmap(void *addr, size_t len)
{
if (len == 0)
return -EINVAL;
return syscall2(SYSCALL_ID_MUNMAP, (unsigned int)addr, len);
}
/* As when a new thread is run, the params are passed by register (See cpu_ustate_init), use
* this function to simplify new thread usage*/
static void thread_runner()
{
register unsigned long int reg_arg1 asm("%eax");
register unsigned long int reg_arg2 asm("%ebx");
start_routine *func = (start_routine *)reg_arg1;
void *arg = (void *)reg_arg2;
func(arg);
_exit(0);
}
int thread_create(pthread_t *thread, start_routine *func, void *arg, size_t stackSize) {
return syscall5(SYSCALL_ID_NEW_THREAD, (unsigned int)thread, (unsigned int)thread_runner, (unsigned int)func,
(unsigned int)arg, stackSize);
}
int thread_join(pthread_t thread, void **retval){
(void)retval;
return syscall1(SYSCALL_ID_THREAD_JOIN, (unsigned int)thread);
}
int usleep(useconds_t usec) {
return syscall1(SYSCALL_ID_USLEEP, (unsigned int)usec);
}
pid_t gettid(void) {
return syscall0(SYSCALL_ID_GETTID);
}
pid_t getpid(void) {
return syscall0(SYSCALL_ID_GETPID);
}

View File

@ -1,10 +1,7 @@
#pragma once #pragma once
#include "assert.h" #include "assert.h"
#include "stdarg.h" #include "stdarg.h"
#include "stdint.h"
#include "stddef.h"
#include "minmax.h" #include "minmax.h"
#include "unistd.h"
#define islower(c) (('a' <= (c)) && ((c) <= 'z')) #define islower(c) (('a' <= (c)) && ((c) <= 'z'))
#define isupper(c) (('A' <= (c)) && ((c) <= 'Z')) #define isupper(c) (('A' <= (c)) && ((c) <= 'Z'))
@ -15,15 +12,8 @@
#define isprint(c) ((' ' <= (c)) && ((c) <= '~')) #define isprint(c) ((' ' <= (c)) && ((c) <= '~'))
#define EOF (-1) #define EOF (-1)
/** compares the first @param n bytes (each interpreted as
* unsigned char) of the memory areas @param s1 and @param s2.
*/
__attribute__ ((access (read_only, 1, 3), access (read_only, 2, 3))) int memcmp(const void *s1, const void *s2, size_t n);
/** __attribute__ ((access (read_only, 1, 3), access (read_only, 2, 3))) int memcmp(const void *s1, const void *s2, size_t n);
* copies n bytes from memory area src to memory area dest. The memory areas may overlap
*/
__attribute__ ((access (write_only, 1, 3), access (read_only, 2, 3))) void *memmove(void *dest, const void *src, size_t n);
__attribute__ ((access (write_only, 1, 3), access (read_only, 2, 3))) void *memcpy(void *dest, const void *src, size_t n); __attribute__ ((access (write_only, 1, 3), access (read_only, 2, 3))) void *memcpy(void *dest, const void *src, size_t n);
__attribute__ ((access (write_only, 1, 3))) void *memset(void *s, int c, size_t n); __attribute__ ((access (write_only, 1, 3))) void *memset(void *s, int c, size_t n);
char *itoa(long long int value, char *str, int base); char *itoa(long long int value, char *str, int base);
@ -37,8 +27,6 @@ int putc(const int c);
int vsnprintf(char *str, size_t size, const char *format, va_list ap) __attribute__ ((__format__ (printf, 3, 0))); int vsnprintf(char *str, size_t size, const char *format, va_list ap) __attribute__ ((__format__ (printf, 3, 0)));
int vprintf(const char *format, va_list ap) __attribute__ ((__format__ (printf, 1, 0))); int vprintf(const char *format, va_list ap) __attribute__ ((__format__ (printf, 1, 0)));
int printf(const char *format, ...) __attribute__ ((__format__ (printf, 1, 2))); int printf(const char *format, ...) __attribute__ ((__format__ (printf, 1, 2)));
void *mmap(void *addr, size_t len, int prot, int flags, char *path);
int munmap(void *addr, size_t len);
int asprintf(char **strp, const char *fmt, ...) __attribute__ ((__format__ (printf, 2, 3))); int asprintf(char **strp, const char *fmt, ...) __attribute__ ((__format__ (printf, 2, 3)));
int vasprintf(char **strp, const char *fmt, va_list ap) __attribute__ ((__format__ (printf, 2, 0))); int vasprintf(char **strp, const char *fmt, va_list ap) __attribute__ ((__format__ (printf, 2, 0)));
@ -61,9 +49,4 @@ int readline(char *buf, int size);
int brk(void *addr); int brk(void *addr);
void *sbrk(intptr_t increment); void *sbrk(intptr_t increment);
void *malloc(size_t size); void *malloc(size_t size);
void *calloc(size_t nmemb, size_t size);
void *realloc(void *ptr, size_t size);
void free(void *ptr); void free(void *ptr);
pid_t gettid(void);
pid_t getpid(void);

View File

@ -1,189 +0,0 @@
/* Copyright (C) 2001 David Decotigny
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
USA.
*/
#ifndef _SOS_LIST_H_
#define _SOS_LIST_H_
/**
* @file list.h
*
* Circular doubly-linked lists implementation entirely based on C
* macros
*/
/* *_named are used when next and prev links are not exactly next
and prev. For instance when we have next_in_team, prev_in_team,
prev_global and next_global */
#define list_init_named(list, prev, next) ((list) = NULL)
#define list_singleton_named(list, item, prev, next) \
({ \
(item)->next = (item)->prev = (item); \
(list) = (item); \
})
#define list_is_empty_named(list, prev, next) ((list) == NULL)
#define list_is_singleton_named(list, prev, next) \
(((list) != NULL) && ((list)->prev == (list)->next) && ((list) == (list)->next))
#define list_get_head_named(list, prev, next) (list)
#define list_get_tail_named(list, prev, next) ((list) ? ((list)->prev) : NULL)
/* Internal macro : insert before the head == insert at tail */
#define __list_insert_atleft_named(before_this, item, prev, next) \
({ \
(before_this)->prev->next = (item); \
(item)->prev = (before_this)->prev; \
(before_this)->prev = (item); \
(item)->next = (before_this); \
})
/* @note Before_this and item are expected to be valid ! */
#define list_insert_before_named(list, before_this, item, prev, next) \
({ \
__list_insert_atleft_named(before_this, item, prev, next); \
if ((list) == (before_this)) \
(list) = (item); \
})
/** @note After_this and item are expected to be valid ! */
#define list_insert_after_named(list, after_this, item, prev, next) \
({ \
(after_this)->next->prev = (item); \
(item)->next = (after_this)->next; \
(after_this)->next = (item); \
(item)->prev = (after_this); \
})
#define list_add_head_named(list, item, prev, next) \
({ \
if (list) \
__list_insert_atleft_named(list, item, prev, next); \
else \
list_singleton_named(list, item, prev, next); \
(list) = (item); \
})
#define list_add_tail_named(list, item, prev, next) \
({ \
if (list) \
__list_insert_atleft_named(list, item, prev, next); \
else \
list_singleton_named(list, item, prev, next); \
})
/** @note NO check whether item really is in list ! */
#define list_delete_named(list, item, prev, next) \
({ \
if (((item)->next == (item)) && ((item)->prev == (item))) \
(item)->next = (item)->prev = (list) = NULL; \
else { \
(item)->prev->next = (item)->next; \
(item)->next->prev = (item)->prev; \
if ((item) == (list)) \
(list) = (item)->next; \
(item)->prev = (item)->next = NULL; \
} \
})
#define list_pop_head_named(list, prev, next) \
({ \
typeof(list) __ret_elt = (list); \
list_delete_named(list, __ret_elt, prev, next); \
__ret_elt; \
})
/** Loop statement that iterates through all of its elements, from
head to tail */
#define list_foreach_forward_named(list, iterator, nb_elements, prev, next) \
for (nb_elements = 0, (iterator) = (list); \
(iterator) && (!nb_elements || ((iterator) != (list))); \
nb_elements++, (iterator) = (iterator)->next)
/** Loop statement that iterates through all of its elements, from
tail back to head */
#define list_foreach_backward_named(list, iterator, nb_elements, prev, next) \
for (nb_elements = 0, (iterator) = list_get_tail_named(list, prev, next); \
(iterator) && \
(!nb_elements || ((iterator) != list_get_tail_named(list, prev, next))); \
nb_elements++, (iterator) = (iterator)->prev)
#define list_foreach_named list_foreach_forward_named
/** True when we exitted early from the foreach loop (ie break) */
#define list_foreach_early_break(list, iterator, nb_elements) \
((list) && (((list) != (iterator)) || (((list) == (iterator)) && (nb_elements == 0))))
/** Loop statement that also removes the item at each iteration. The
body of the loop is allowed to delete the iterator element from
memory. */
#define list_collapse_named(list, iterator, prev, next) \
for (; ({ \
((iterator) = (list)); \
if (list) \
list_delete_named(list, iterator, prev, next); \
(iterator); \
});)
/*
* the same macros : assume that the prev and next fields are really
* named "prev" and "next"
*/
#define list_init(list) list_init_named(list, prev, next)
#define list_singleton(list, item) list_singleton_named(list, item, prev, next)
#define list_is_empty(list) list_is_empty_named(list, prev, next)
#define list_is_singleton(list) list_is_singleton_named(list, prev, next)
#define list_get_head(list) list_get_head_named(list, prev, next)
#define list_get_tail(list) list_get_tail_named(list, prev, next)
/* @note Before_this and item are expected to be valid ! */
#define list_insert_after(list, after_this, item) \
list_insert_after_named(list, after_this, item, prev, next)
/* @note After_this and item are expected to be valid ! */
#define list_insert_before(list, before_this, item) \
list_insert_before_named(list, before_this, item, prev, next)
#define list_add_head(list, item) list_add_head_named(list, item, prev, next)
#define list_add_tail(list, item) list_add_tail_named(list, item, prev, next)
/* @note NO check whether item really is in list ! */
#define list_delete(list, item) list_delete_named(list, item, prev, next)
#define list_pop_head(list) list_pop_head_named(list, prev, next)
#define list_foreach_forward(list, iterator, nb_elements) \
list_foreach_forward_named(list, iterator, nb_elements, prev, next)
#define list_foreach_backward(list, iterator, nb_elements) \
list_foreach_backward_named(list, iterator, nb_elements, prev, next)
#define list_foreach list_foreach_forward
#define list_collapse(list, iterator) list_collapse_named(list, iterator, prev, next)
#endif /* _SOS_LIST_H_ */

View File

@ -1,11 +1,6 @@
#include "errno.h"
#include "libc.h" #include "libc.h"
#include "stdarg.h" #include "stdarg.h"
#include "stddef.h"
#include "sys/mman.h"
#include "thread.h"
#include "tiny.h" #include "tiny.h"
#include "unistd.h"
int func_help() int func_help()
{ {
@ -15,9 +10,6 @@ int func_help()
printf(" syscall5: a syscall with parameters over the stack \n"); printf(" syscall5: a syscall with parameters over the stack \n");
printf(" alloc: test allocation\n"); printf(" alloc: test allocation\n");
printf(" tiny: a tiny C-like interpreter\n"); printf(" tiny: a tiny C-like interpreter\n");
printf(" mmap: test mmap \n");
printf(" munmap: test munmap \n");
printf(" thread: run a user thread\n");
return 0; return 0;
} }
@ -33,29 +25,29 @@ char *initialHeap = 0;
int func_alloc() int func_alloc()
{ {
if (initialHeap == 0) { if (initialHeap == 0) {
initialHeap = sbrk(0); initialHeap = sbrk(0);
} }
printf("Testing allocation\n"); printf("Testing allocation\n");
int allocSize = 4096 * 2; int allocSize = 4096 * 2;
char *currentHeap = sbrk(0); char *currentHeap = sbrk(0);
if (currentHeap - initialHeap < allocSize) { if (currentHeap - initialHeap < allocSize) {
brk(initialHeap + allocSize); brk(initialHeap + allocSize);
} }
int *allocatedData = (int *)initialHeap; int *allocatedData = (int *)initialHeap;
for (unsigned int i = 0; i < allocSize / sizeof(int); i++) { for (unsigned int i = 0; i < allocSize / sizeof(int); i++) {
allocatedData[i] = i; allocatedData[i] = i;
} }
printf("Success\nTesting malloc\n"); printf("Success\nTesting malloc\n");
uintptr_t heap = (uintptr_t)sbrk(0); uintptr_t heap = (uintptr_t)sbrk(0);
for (int i = 0; i < 12; i++) { for (int i = 0; i < 12; i++) {
void *ptr = malloc(1 << i); void *ptr = malloc(1 << i);
printf("malloc size %d: 0x%p\n", (1 << i), ptr); printf("malloc size %d: 0x%p\n", (1 << i), ptr);
if (ptr == NULL) { if (ptr == NULL) {
printf("Malloc failed\n"); printf("Malloc failed\n");
} }
memset(ptr, 0, 1 << i); memset(ptr, 0, 1 << i);
free(ptr); free(ptr);
} }
uintptr_t newHeap = (uintptr_t)sbrk(0); uintptr_t newHeap = (uintptr_t)sbrk(0);
printf("Malloc used %dB\n", newHeap - heap); printf("Malloc used %dB\n", newHeap - heap);
@ -63,86 +55,11 @@ int func_alloc()
return 0; return 0;
} }
struct mmapedArea { int main(int argc, char *argv[])
void *addr;
size_t size;
struct mmapedArea *next;
};
static struct mmapedArea *listMmap = NULL;
int func_mmap()
{ {
struct mmapedArea *area = (struct mmapedArea *)malloc(sizeof(struct mmapedArea));
if (area == NULL) {
printf("Fail to allocate area\n");
return -1;
}
char *path = "/dev/zero";
void *mapAddr = mmap((void *)0, 4096, PROT_READ | PROT_WRITE, 0, path);
if (mapAddr == MAP_FAILED) {
printf("mmap failed errno %d\n", errno);
return -1;
}
printf("Zero mmaped at %p\n", mapAddr);
int data = *(int *)mapAddr;
*(int *)mapAddr = data;
area->addr = mapAddr;
area->size = 4096;
area->next = listMmap;
listMmap = area;
return 0;
}
int func_munmap()
{
if (!listMmap) {
printf("Nothing to unmap... mmap first! \n");
return -1;
}
struct mmapedArea *area = listMmap;
int ret = munmap(area->addr, area->size);
if (ret) {
printf("Fail to unmap area at 0x%p (size %d) error %d\n", area->addr, area->size, ret);
return ret;
}
printf("unmap done\n");
listMmap = listMmap->next;
free(area);
return ret;
}
static void *print_hello(void *arg) {
(void)arg;
printf("Hello World from thread %lu\n", gettid());
usleep(100);
return NULL;
}
int func_thread() {
pthread_t id;
void *retval;
thread_create(&id, print_hello, NULL, 4096);
thread_join(id, &retval);
return 0;
}
int main(int argc, char *argv[]) {
(void)argc; (void)argc;
(void)argv; (void)argv;
char buf[64]; char buf[64];
assert(getpid() == gettid());
printf("Shell starting... type \"help\" for help\n"); printf("Shell starting... type \"help\" for help\n");
while (1) { while (1) {
printf(">"); printf(">");
@ -165,22 +82,7 @@ int main(int argc, char *argv[]) {
continue; continue;
} }
if (strcmp(buf, "tiny") == 0) { if (strcmp(buf, "tiny") == 0) {
pthread_t id; func_tiny();
void *retval;
thread_create(&id, func_tiny, NULL, 4096);
thread_join(id, &retval);
continue;
}
if (strcmp(buf, "mmap") == 0) {
func_mmap();
continue;
}
if (strcmp(buf, "munmap") == 0) {
func_munmap();
continue;
}
if (strcmp(buf, "thread") == 0) {
func_thread();
continue; continue;
} }
} }

View File

@ -1,5 +1,5 @@
#pragma once #pragma once
#include "stdint.h" #include "stdarg.h"
#include "types.h" #include "types.h"
uint32_t log2(uint32_t x); uint32_t log2(uint32_t x);

View File

@ -1,6 +1,55 @@
#pragma once #pragma once
//__builtin_va_list could be used instead typedef __signed__ char __s8;
typedef unsigned char __u8;
typedef __signed__ short __s16;
typedef unsigned short __u16;
typedef __signed__ int __s32;
typedef unsigned int __u32;
#ifdef __GNUC__
__extension__ typedef __signed__ long long __s64;
__extension__ typedef unsigned long long __u64;
#else
typedef __signed__ long long __s64;
typedef unsigned long long __u64;
#endif
/* sysv */
typedef unsigned char unchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;
typedef __s8 int8_t;
typedef __s16 int16_t;
typedef __s32 int32_t;
typedef __u8 uint8_t;
typedef __u16 uint16_t;
typedef __u32 uint32_t;
typedef __u64 uint64_t;
typedef __u64 u_int64_t;
typedef __s64 int64_t;
typedef enum { FALSE = 0, TRUE } bool_t;
#define NULL ((void *)0)
#if __x86_64__
typedef unsigned long size_t;
typedef long ssize_t;
typedef unsigned long int uintptr_t;
typedef long int intptr_t;
#else
typedef unsigned int size_t;
typedef int ssize_t;
typedef unsigned int uintptr_t;
typedef int intptr_t;
#endif
typedef char *va_list; typedef char *va_list;
#define va_start(v, l) ((v) = (va_list) & (l) + sizeof(l)) #define va_start(v, l) ((v) = (va_list) & (l) + sizeof(l))
#define va_end(v) ((v) = NULL) #define va_end(v) ((v) = NULL)

View File

@ -1,29 +0,0 @@
#pragma once
typedef enum { FALSE = 0, TRUE } bool_t;
#define NULL ((void *)0)
#if __x86_64__
typedef unsigned long size_t;
typedef long ssize_t;
typedef unsigned long int uintptr_t;
typedef long int intptr_t;
#else
typedef unsigned int size_t;
typedef int ssize_t;
typedef unsigned int uintptr_t;
typedef int intptr_t;
#endif
#if __x86_64__
typedef unsigned long size_t;
typedef long ssize_t;
typedef unsigned long int uintptr_t;
typedef long int intptr_t;
#else
typedef unsigned int size_t;
typedef int ssize_t;
typedef unsigned int uintptr_t;
typedef int intptr_t;
#endif
typedef int wchar_t;

View File

@ -1,64 +0,0 @@
#pragma once
typedef __signed__ char __s8;
typedef unsigned char __u8;
typedef __signed__ short __s16;
typedef unsigned short __u16;
typedef __signed__ int __s32;
typedef unsigned int __u32;
#ifdef __GNUC__
__extension__ typedef __signed__ long long __s64;
__extension__ typedef unsigned long long __u64;
#else
typedef __signed__ long long __s64;
typedef unsigned long long __u64;
#endif
/* sysv */
typedef unsigned char unchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;
typedef __s8 int8_t;
typedef __s16 int16_t;
typedef __s32 int32_t;
typedef __u8 uint8_t;
typedef __u16 uint16_t;
typedef __u32 uint32_t;
typedef __u64 uint64_t;
typedef __u64 u_int64_t;
typedef __s64 int64_t;
#define USHRT_MAX ((u16)(~0U))
#define SHRT_MAX ((s16)(USHRT_MAX >> 1))
#define SHRT_MIN ((s16)(-SHRT_MAX - 1))
#define INT_MAX ((int)(~0U >> 1))
#define INT_MIN (-INT_MAX - 1)
#define UINT_MAX (~0U)
#define LONG_MAX ((long)(~0UL >> 1))
#define LONG_MIN (-LONG_MAX - 1)
#define ULONG_MAX (~0UL)
#define LLONG_MAX ((long long)(~0ULL >> 1))
#define LLONG_MIN (-LLONG_MAX - 1)
#define ULLONG_MAX (~0ULL)
#define SIZE_MAX (~(size_t)0)
#define PHYS_ADDR_MAX (~(phys_addr_t)0)
#define U8_MAX ((u8)~0U)
#define S8_MAX ((s8)(U8_MAX >> 1))
#define S8_MIN ((s8)(-S8_MAX - 1))
#define U16_MAX ((u16)~0U)
#define S16_MAX ((s16)(U16_MAX >> 1))
#define S16_MIN ((s16)(-S16_MAX - 1))
#define U32_MAX ((u32)~0U)
#define S32_MAX ((s32)(U32_MAX >> 1))
#define S32_MIN ((s32)(-S32_MAX - 1))
#define U64_MAX ((u64)~0ULL)
#define S64_MAX ((s64)(U64_MAX >> 1))
#define S64_MIN ((s64)(-S64_MAX - 1))

View File

@ -1,13 +0,0 @@
#pragma once
/* To keep in sync with PAGING_MEM_* */
#define PROT_EXEC (1<<3)
#define PROT_READ (1<<1)
#define PROT_WRITE (1<<2)
#define MAP_SHARED (1 << 0)
#define MAP_PRIVATE (1 << 1)
#define MAP_FIXED (1 << 2)
#define MAP_FAILED (void *)-1

View File

@ -1,8 +0,0 @@
#pragma once
#include <stddef.h>
typedef unsigned long int pthread_t;
typedef void *(start_routine)(void *);
int thread_create(pthread_t *thread, start_routine *func, void *arg, size_t stackSize);
/* retval is ignored ATM */
int thread_join(pthread_t thread, void **retval);

View File

@ -282,9 +282,8 @@ void run()
/* Main program. */ /* Main program. */
void * func_tiny(void *args) int func_tiny()
{ {
(void)args;
printf("Enter your program then ESC\n\n"); printf("Enter your program then ESC\n\n");
printf("TinyC grammar\n"); printf("TinyC grammar\n");
printf("<program> ::= <statement>\n"); printf("<program> ::= <statement>\n");

View File

@ -1,4 +1,4 @@
#pragma once #pragma once
void * func_tiny(void *args); int func_tiny();

View File

@ -1,5 +1,32 @@
#pragma once #pragma once
#define USHRT_MAX ((u16)(~0U))
#define SHRT_MAX ((s16)(USHRT_MAX >> 1))
#define SHRT_MIN ((s16)(-SHRT_MAX - 1))
#define INT_MAX ((int)(~0U >> 1))
#define INT_MIN (-INT_MAX - 1)
#define UINT_MAX (~0U)
#define LONG_MAX ((long)(~0UL >> 1))
#define LONG_MIN (-LONG_MAX - 1)
#define ULONG_MAX (~0UL)
#define LLONG_MAX ((long long)(~0ULL >> 1))
#define LLONG_MIN (-LLONG_MAX - 1)
#define ULLONG_MAX (~0ULL)
#define SIZE_MAX (~(size_t)0)
#define PHYS_ADDR_MAX (~(phys_addr_t)0)
#define U8_MAX ((u8)~0U)
#define S8_MAX ((s8)(U8_MAX >> 1))
#define S8_MIN ((s8)(-S8_MAX - 1))
#define U16_MAX ((u16)~0U)
#define S16_MAX ((s16)(U16_MAX >> 1))
#define S16_MIN ((s16)(-S16_MAX - 1))
#define U32_MAX ((u32)~0U)
#define S32_MAX ((s32)(U32_MAX >> 1))
#define S32_MIN ((s32)(-S32_MAX - 1))
#define U64_MAX ((u64)~0ULL)
#define S64_MAX ((s64)(U64_MAX >> 1))
#define S64_MIN ((s64)(-S64_MAX - 1))
// Virtual address // Virtual address
typedef unsigned long vaddr_t; typedef unsigned long vaddr_t;

View File

@ -1,6 +0,0 @@
#pragma once
typedef unsigned int useconds_t;
int usleep(useconds_t usec);
typedef unsigned long int pid_t;