Compare commits
1 Commits
master
...
test_gitea
Author | SHA1 | Date | |
---|---|---|---|
|
162750ed8d |
9
Makefile
9
Makefile
@ -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
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
# Introduction
|
# Introduction
|
||||||
|
#
|
||||||
|
|
||||||
Matos is a simple OS.
|
Matos is a simple OS.
|
||||||
|
|
||||||
|
@ -53,12 +53,10 @@ void print_handler(struct cpu_state *frame, ulong intr)
|
|||||||
|
|
||||||
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();
|
||||||
|
assert(frame == current->cpuState);
|
||||||
if (cpu_context_is_in_user_mode(current->cpuState)) {
|
if (cpu_context_is_in_user_mode(current->cpuState)) {
|
||||||
assert(frame == current->cpuState); // pagefault in kernel not supported ATM
|
|
||||||
|
|
||||||
struct uAddrSpace *as = processGetAddrSpace(current->process);
|
struct uAddrSpace *as = processGetAddrSpace(current->process);
|
||||||
vaddr_t faultAddr = cpu_context_get_EX_faulting_vaddr(frame);
|
vaddr_t faultAddr = cpu_context_get_EX_faulting_vaddr(frame);
|
||||||
@ -72,6 +70,8 @@ void pagefault_handler(struct cpu_state *frame, ulong intr)
|
|||||||
if (!uAddrSpaceHeapCheckNAlloc(as, faultAddr))
|
if (!uAddrSpaceHeapCheckNAlloc(as, faultAddr))
|
||||||
goto release_context;
|
goto release_context;
|
||||||
|
|
||||||
|
// PAGE_FAULT is a interrupt with an error code (see exception_wrapper.S)
|
||||||
|
uint32_t error_code = cpu_context_get_EX_err(frame);
|
||||||
int ret = uAddrSpaceSolvePageFault(as, faultAddr, error_code & 0x2);
|
int ret = uAddrSpaceSolvePageFault(as, faultAddr, error_code & 0x2);
|
||||||
|
|
||||||
if (!ret)
|
if (!ret)
|
||||||
|
@ -46,7 +46,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");
|
||||||
|
@ -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;
|
||||||
|
|
||||||
@ -50,7 +48,6 @@ struct process *processCreate(char *name)
|
|||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
@ -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);
|
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
#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"
|
||||||
@ -11,6 +9,7 @@
|
|||||||
#include "uaddrspace.h"
|
#include "uaddrspace.h"
|
||||||
#include "zero.h"
|
#include "zero.h"
|
||||||
|
|
||||||
|
|
||||||
int syscallExecute(int syscallId, const struct cpu_state *userCtx)
|
int syscallExecute(int syscallId, const struct cpu_state *userCtx)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -44,7 +43,7 @@ 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;
|
||||||
@ -54,7 +53,7 @@ int syscallExecute(int syscallId, const struct cpu_state *userCtx)
|
|||||||
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;
|
||||||
@ -111,83 +110,6 @@ int syscallExecute(int syscallId, const struct cpu_state *userCtx)
|
|||||||
ret = uAddrSpaceUnmap(as, uaddr, size);
|
ret = uAddrSpaceUnmap(as, uaddr, size);
|
||||||
break;
|
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;
|
||||||
|
@ -11,11 +11,6 @@
|
|||||||
#define SYSCALL_ID_BRK 6
|
#define SYSCALL_ID_BRK 6
|
||||||
#define SYSCALL_ID_MMAP 7
|
#define SYSCALL_ID_MMAP 7
|
||||||
#define SYSCALL_ID_MUNMAP 8
|
#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);
|
||||||
|
@ -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);
|
||||||
|
|
||||||
@ -90,8 +84,6 @@ struct thread *threadCreate(const char *name, cpu_kstate_function_arg1_t func, v
|
|||||||
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,17 +210,16 @@ 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;
|
||||||
@ -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);
|
||||||
|
@ -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);
|
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
#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;
|
||||||
|
@ -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
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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);
|
||||||
|
@ -1,41 +1,13 @@
|
|||||||
#include "zero.h"
|
#include "zero.h"
|
||||||
|
|
||||||
#include "alloc.h"
|
#include "alloc.h"
|
||||||
#include "errno.h"
|
|
||||||
#include "kernel.h"
|
#include "kernel.h"
|
||||||
#include "klibc.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 {
|
struct zeroMappedEntry {
|
||||||
int refCnt;
|
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)
|
static int zeroOpen(struct uAddrVirtualReg *vreg)
|
||||||
{
|
{
|
||||||
struct zeroMappedEntry *ent = (struct zeroMappedEntry *)vreg->res->customData;
|
struct zeroMappedEntry *ent = (struct zeroMappedEntry *)vreg->res->customData;
|
||||||
@ -48,11 +20,6 @@ static int zeroClose(struct uAddrVirtualReg *vreg)
|
|||||||
struct zeroMappedEntry *ent = (struct zeroMappedEntry *)vreg->res->customData;
|
struct zeroMappedEntry *ent = (struct zeroMappedEntry *)vreg->res->customData;
|
||||||
ent->refCnt--;
|
ent->refCnt--;
|
||||||
if (ent->refCnt == 0) {
|
if (ent->refCnt == 0) {
|
||||||
struct zeroMappedPage *pageInfo;
|
|
||||||
list_collapse(ent->listMapped, pageInfo){
|
|
||||||
pageUnmap(pageInfo->mappedAddr);
|
|
||||||
free(pageInfo);
|
|
||||||
}
|
|
||||||
free(vreg->res->customData);
|
free(vreg->res->customData);
|
||||||
free(vreg->res);
|
free(vreg->res);
|
||||||
}
|
}
|
||||||
@ -61,26 +28,17 @@ static int zeroClose(struct uAddrVirtualReg *vreg)
|
|||||||
|
|
||||||
static int zeroNoPage(struct uAddrVirtualReg *vreg, uaddr_t addr, int right)
|
static int zeroNoPage(struct uAddrVirtualReg *vreg, uaddr_t addr, int right)
|
||||||
{
|
{
|
||||||
|
(void)vreg;
|
||||||
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
paddr_t ppage = allocPhyPage(1);
|
paddr_t ppage = allocPhyPage(1);
|
||||||
uaddr_t mappedAddr = ALIGN_DOWN(addr, PAGE_SIZE);
|
ret = pageMap(ALIGN_DOWN(addr, PAGE_SIZE), ppage, right | PAGING_MEM_USER) ;
|
||||||
ret = pageMap(mappedAddr, ppage, right | PAGING_MEM_USER);
|
|
||||||
|
|
||||||
struct zeroMappedEntry *ent = (struct zeroMappedEntry *)vreg->res->customData;
|
|
||||||
|
|
||||||
unrefPhyPage(ppage);
|
unrefPhyPage(ppage);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
memset((void *)ALIGN_DOWN(addr, PAGE_SIZE), 0, PAGE_SIZE);
|
||||||
ret = insertMappedPage(ent, mappedAddr, ppage);
|
|
||||||
if (ret) {
|
|
||||||
pageUnmap(mappedAddr);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset((void *)mappedAddr, 0, PAGE_SIZE);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,8 +64,6 @@ int zeroMmap(struct uAddrSpace *as, uaddr_t *uaddr, size_t size, uint32_t rights
|
|||||||
struct zeroMappedEntry *cust =
|
struct zeroMappedEntry *cust =
|
||||||
(struct zeroMappedEntry *)zalloc(sizeof(struct zeroMappedEntry));
|
(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->allowedRight = PAGING_MEM_READ | PAGING_MEM_WRITE | PAGING_MEM_EXEC | PAGING_MEM_USER;
|
||||||
res->ops = &zeroOps;
|
res->ops = &zeroOps;
|
||||||
res->customData = cust;
|
res->customData = cust;
|
||||||
|
@ -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;
|
||||||
|
@ -11,11 +11,6 @@
|
|||||||
#define SYSCALL_ID_BRK 6
|
#define SYSCALL_ID_BRK 6
|
||||||
#define SYSCALL_ID_MMAP 7
|
#define SYSCALL_ID_MMAP 7
|
||||||
#define SYSCALL_ID_MUNMAP 8
|
#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);
|
||||||
|
159
userspace/libc.c
159
userspace/libc.c
@ -5,8 +5,6 @@
|
|||||||
#include "swintr.h"
|
#include "swintr.h"
|
||||||
#include "sys/mman.h"
|
#include "sys/mman.h"
|
||||||
#include "syscall.h"
|
#include "syscall.h"
|
||||||
#include "thread.h"
|
|
||||||
#include "unistd.h"
|
|
||||||
|
|
||||||
int errno = 0;
|
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)
|
||||||
@ -265,57 +263,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 +272,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 +350,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 +388,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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -787,40 +745,3 @@ int munmap(void *addr, size_t len)
|
|||||||
|
|
||||||
return syscall2(SYSCALL_ID_MUNMAP, (unsigned int)addr, len);
|
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);
|
|
||||||
}
|
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
#include "stdint.h"
|
#include "stdint.h"
|
||||||
#include "stddef.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'))
|
||||||
@ -64,6 +63,3 @@ void *malloc(size_t size);
|
|||||||
void *calloc(size_t nmemb, size_t size);
|
void *calloc(size_t nmemb, size_t size);
|
||||||
void *realloc(void *ptr, 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);
|
|
||||||
|
|
||||||
|
@ -3,9 +3,7 @@
|
|||||||
#include "stdarg.h"
|
#include "stdarg.h"
|
||||||
#include "stddef.h"
|
#include "stddef.h"
|
||||||
#include "sys/mman.h"
|
#include "sys/mman.h"
|
||||||
#include "thread.h"
|
|
||||||
#include "tiny.h"
|
#include "tiny.h"
|
||||||
#include "unistd.h"
|
|
||||||
|
|
||||||
int func_help()
|
int func_help()
|
||||||
{
|
{
|
||||||
@ -17,7 +15,6 @@ int func_help()
|
|||||||
printf(" tiny: a tiny C-like interpreter\n");
|
printf(" tiny: a tiny C-like interpreter\n");
|
||||||
printf(" mmap: test mmap \n");
|
printf(" mmap: test mmap \n");
|
||||||
printf(" munmap: test munmap \n");
|
printf(" munmap: test munmap \n");
|
||||||
printf(" thread: run a user thread\n");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,28 +118,11 @@ int func_munmap()
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *print_hello(void *arg) {
|
int main(int argc, char *argv[])
|
||||||
(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,10 +145,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;
|
continue;
|
||||||
}
|
}
|
||||||
if (strcmp(buf, "mmap") == 0) {
|
if (strcmp(buf, "mmap") == 0) {
|
||||||
@ -179,10 +156,6 @@ int main(int argc, char *argv[]) {
|
|||||||
func_munmap();
|
func_munmap();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (strcmp(buf, "thread") == 0) {
|
|
||||||
func_thread();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
|
@ -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");
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
void * func_tiny(void *args);
|
int func_tiny();
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
typedef unsigned int useconds_t;
|
|
||||||
int usleep(useconds_t usec);
|
|
||||||
|
|
||||||
typedef unsigned long int pid_t;
|
|
Loading…
Reference in New Issue
Block a user