From a455cd5af26bf8731e7c981a9421b16ab34dae6f Mon Sep 17 00:00:00 2001 From: Miguel Date: Mon, 1 Oct 2018 23:22:03 +0200 Subject: fukkin scheduler --- README.md | 2 +- asm/asm_x86.h | 2 ++ asm/asm_x86.s | 17 ++++++++++++++++ driver/keyboard.c | 1 - driver/mouse.c | 22 ++++++++++++-------- driver/timer.c | 6 +++--- kernel/apic.c | 2 +- kernel/kernel.c | 2 +- kernel/kernel.h | 2 +- kernel/ringbuffer.c | 14 +++++++++---- kernel/ringbuffer.h | 3 +++ kernel/scheduler.c | 57 +++++++++++++++++++++++++++++++++++++++++++++------- kernel/scheduler.h | 2 ++ kernel/smp.c | 2 +- kernel/syscalls.c | 18 +++++++++++++++++ kernel/syscalls.h | 3 +++ kernel/vmem.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++ kernel/vmem.h | 1 + lib/string/string.h | 1 + userspace/fsh.c | 1 + userspace/newcalls.h | 10 +++++++++ userspace/pain2.c | 13 ++++++++---- video/compositor.c | 3 ++- 23 files changed, 204 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index f45f7f0..434c133 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ Todos * PRIO: ringbuffers (spinlock on/off, interrupts on/off, read/write blocks of data); * PRIO: Writing to ext2 RAM-image!!!! -* PRIO: Fix scheduler. use all cpus! / accounting / queues? +* PRIO: Fix scheduler. use all cpus! / accounting/bookkeppiung x86: tsc /rdtscp? / load bareer / queues? * PRIO: semaphores/ mutexes * PRIO: return value / argv / env * PRIO: create/remove pages on demand (sbrk, stack, load prog) diff --git a/asm/asm_x86.h b/asm/asm_x86.h index ec9ebd0..0781fc7 100644 --- a/asm/asm_x86.h +++ b/asm/asm_x86.h @@ -100,4 +100,6 @@ static inline void x86_paging_enable() {x86_set_cr(0,x86_get_cr(0)| 0x8000000 /** Disable paging */ static inline void x86_paging_disable() {x86_set_cr(0,x86_get_cr(0)&~0x80000000);} +/** Read Time Stamp Counter */ +uint64_t x86_rdtscp(); #endif diff --git a/asm/asm_x86.s b/asm/asm_x86.s index 3481ec2..7f0f56b 100644 --- a/asm/asm_x86.s +++ b/asm/asm_x86.s @@ -24,6 +24,9 @@ .global x86_get_cr .global x86_set_cr +// timer +.global x86_rdtscp + x86_outb: mov 4(%esp), %edx mov 8(%esp), %eax @@ -132,3 +135,17 @@ x86_invlpg: mov 4(%esp), %eax // addr invlpg (%eax) ret + +#x86_rdtscp: +# rdtscp +# ret +# https://stackoverflow.com/questions/12631856/difference-between-rdtscp-rdtsc-memory-and-cpuid-rdtsc +x86_rdtscp: + lfence #intel + rdtsc + ret + +#x86_rdtscp: +# mfence #amd +# rdtsc +# ret diff --git a/driver/keyboard.c b/driver/keyboard.c index 757bbb8..cc060c7 100644 --- a/driver/keyboard.c +++ b/driver/keyboard.c @@ -30,7 +30,6 @@ int hex_to_dec(char c) extern struct netdev e1000_dev; static void put(uint8_t c) { - if(c=='p')net_packet(&e1000_dev); syscall_generic(SYSCALL_WRITE,kb_stream, (char *)&c , 1, 0); } diff --git a/driver/mouse.c b/driver/mouse.c index d0f1591..810cb83 100644 --- a/driver/mouse.c +++ b/driver/mouse.c @@ -19,12 +19,17 @@ static ringbuffer mouse_in; bool mouse_worker() { - bool wake=false; - while(ringbuffer_has(&mouse_in)){ - mouse_handler(ringbuffer_get(&mouse_in)); - wake=true; - } - return wake; + if(ringbuffer_full(&mouse_in)) + { + klog("mouse buffer full"); + } + + bool wake=false; + while(ringbuffer_has(&mouse_in)){ + mouse_handler(ringbuffer_get(&mouse_in)); + wake=true; + } + return wake; } @@ -121,7 +126,7 @@ void mouse_action() if(mouse_byte[0]&0x80||mouse_byte[0]&0x40) { - klog("mouse overflow, skipping packet"); + // klog("mouse overflow, skipping packet"); return; //skip packet on overflow } @@ -146,6 +151,7 @@ void mouse_action() if(mouse_x<0)mouse_x=0; if(mouse_y<0)mouse_y=0; + if(mouse_x>=1920)mouse_x=1920-1; if(mouse_y>=1080)mouse_y=1080-1; @@ -164,7 +170,7 @@ void mouse_handler(uint8_t byte)//struct regs *a_r) //struct regs *a_r (not used mouse_cycle++; if(!(mouse_byte[0]&0x8)) { - klog("mouse out of sync, try resync"); + //klog("mouse out of sync, try resync"); mouse_cycle--; // kpanic("mouse packets out of sync!?"); // this bit is always 1, otherwise panic! } diff --git a/driver/timer.c b/driver/timer.c index 6f0977c..1a97ad8 100644 --- a/driver/timer.c +++ b/driver/timer.c @@ -161,7 +161,7 @@ uint64_t timer_init() uint64_t epoch_time=get_rtc_time(); task_system_clock_start=epoch_time*100; // since pit ticks 100 times a second - asm_pit_rate_10ms(); //tick at 100hz + asm_pit_rate_50ms(); //tick at 100hz interrupt_register(INTERRUPT_PIT_TIMER,&timer_interrupt); @@ -170,10 +170,10 @@ uint64_t timer_init() uint64_t timer_get_ms() { - return (asm_pit_get_ticks()+task_system_clock_start)*10; + return (asm_pit_get_ticks()+task_system_clock_start)*50; } uint64_t timer_get_uptime_ms() { - return asm_pit_get_ticks()*10; + return asm_pit_get_ticks()*50; } diff --git a/kernel/apic.c b/kernel/apic.c index 4bc2bb3..75837f7 100644 --- a/kernel/apic.c +++ b/kernel/apic.c @@ -156,7 +156,7 @@ void ioapic_config() // ioapic_config_entry(2,0x90|0xa000,0x3<<24); // level trigger on low // CPU - ioapic_config_entry(2, INTERRUPT_PIT_TIMER, 0x0<<24); // pit +// ioapic_config_entry(2, INTERRUPT_PIT_TIMER, 0x0<<24); // pit ioapic_config_entry(1, INTERRUPT_KEYBOARD, 0x0<<24); // kb ioapic_config_entry(12, INTERRUPT_MOUSE, 0x0<<24); // mouse ioapic_config_entry(11, INTERRUPT_E1000|0x8000, 0x0<<24); // e1000 (level trigger on high) diff --git a/kernel/kernel.c b/kernel/kernel.c index f55b948..70b1913 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -155,7 +155,7 @@ void kernel_main(uint32_t eax,uint32_t ebx) if(e1000_addr) { klog("E1000 init ..."); - e1000_init(e1000_addr); + // e1000_init(e1000_addr); } klog("Symmetric Multi Processing (SMP) start ... "); diff --git a/kernel/kernel.h b/kernel/kernel.h index 1973d52..8ec8852 100644 --- a/kernel/kernel.h +++ b/kernel/kernel.h @@ -26,7 +26,7 @@ REFERENCES #define VESA_MAX_HEIGHT 1080 //#define FOOLOS_UNIT_TESTING // Run Unit Tests -//#define FOOLOS_LOG_OFF // Turn off logging (disables serial port alltogether) +#define FOOLOS_LOG_OFF // Turn off logging (disables serial port alltogether) //#define FOOLOS_COLORLESS // Turn off colors in log #define HIDE_FIXME diff --git a/kernel/ringbuffer.c b/kernel/ringbuffer.c index 6700931..43d0e33 100644 --- a/kernel/ringbuffer.c +++ b/kernel/ringbuffer.c @@ -18,10 +18,7 @@ void ringbuffer_free(ringbuffer *f) bool ringbuffer_put(ringbuffer* f,uint8_t c) { - if((f->back-1+f->size)%f->size==f->front) - { - return false; - } + if(ringbuffer_full(f))return false; f->data[f->back]=c; f->back--; @@ -30,6 +27,15 @@ bool ringbuffer_put(ringbuffer* f,uint8_t c) return true; } +bool ringbuffer_full(ringbuffer* f) +{ + if((f->back-1+f->size)%f->size==f->front) + { + return true; + } + return false; +} + bool ringbuffer_has(ringbuffer* f) { bool res=true; diff --git a/kernel/ringbuffer.h b/kernel/ringbuffer.h index 1ec88c8..6ad9537 100644 --- a/kernel/ringbuffer.h +++ b/kernel/ringbuffer.h @@ -53,4 +53,7 @@ uint8_t ringbuffer_get(ringbuffer*); /** Check if buffer is not empty */ bool ringbuffer_has(ringbuffer*); +/** Check if buffer is full */ +bool ringbuffer_full(ringbuffer* f); + #endif diff --git a/kernel/scheduler.c b/kernel/scheduler.c index fa32ebc..a4e3743 100644 --- a/kernel/scheduler.c +++ b/kernel/scheduler.c @@ -20,6 +20,7 @@ #include "mouse.h" #include "syscalls.h" #include "fs/ext2.h" +#include "lib/string/string.h" #define NO_TASK 0xffffffff @@ -59,6 +60,8 @@ static volatile struct task_list_struct volatile uint32_t edx; volatile bool thread; // is this a light thread? + + volatile char name[255]; }task_list[SMP_MAX_PROC][MAX_TASKS]; @@ -84,6 +87,7 @@ volatile void scheduler_init(uint32_t cpu, void *dir) task_list[cpu][0].vmem=dir; task_list[cpu][0].esp = VMEM_CPU_STACK_TOP-0x200-8; task_list[cpu][0].esp0 = 0; // esp0 not needed by kernel space tasks + strcpy(task_list[cpu][0].name,"kernel_worker"); fd_init_std_streams(task_list[cpu][0].pid,0); // this will go to userspace @@ -95,6 +99,7 @@ volatile void scheduler_init(uint32_t cpu, void *dir) task_list[cpu][1].vmem=dir; task_list[cpu][1].esp = kballoc(4)+4*4096-0x200-8; // 4 pages stack & prealign task_list[cpu][1].esp0 =kballoc(4)+4*4096; // esp0 not needed by kernel space tasks + strcpy(task_list[cpu][1].name,"init"); fd_init_std_streams(task_list[cpu][1].pid,0); @@ -107,6 +112,7 @@ volatile void scheduler_init(uint32_t cpu, void *dir) task_list[cpu][2].vmem=dir; task_list[cpu][2].esp = kballoc(4)+4*4096-0x200-8; // 4 pages stack & prealign task_list[cpu][2].esp0 =kballoc(4)+4*4096; // esp0 not needed by kernel space tasks + strcpy(task_list[cpu][2].name,"idle process"); fd_init_std_streams(task_list[cpu][2].pid,0); // stacks @@ -117,14 +123,21 @@ volatile void scheduler_init(uint32_t cpu, void *dir) static uint32_t scheduler_schedule(uint32_t idx) { + uint32_t cpu=smp_get(SMP_APIC_ID); + if(task_list[cpu][idx].active && !task_list[cpu][idx].syscall) { if(current_task[cpu]!=0)last_task[cpu]=current_task[cpu]; + if(current_task[cpu]==idx)return task_list[cpu][idx].esp; + current_task[cpu]=idx; - klog("%d",idx); - // klog("%d idx %d",last_task[cpu],current_task[cpu]); + //klog("idx %d",idx); + //klog("name: %s",task_list[cpu][idx].name); + + //klog("cpu %d / idx %d / pid %d / name: %5s",cpu,idx,task_list[cpu][idx].pid,task_list[cpu][idx].name); + //klog("%d idx %d",last_task[cpu],current_task[cpu]); install_tss(cpu,task_list[cpu][idx].esp0); x86_set_page_directory(task_list[cpu][idx].vmem); @@ -211,7 +224,10 @@ void scheduler_func() if(current_task[cpu]==2) while(1) { - while(1)asm("hlt"); // sleeper task + uint64_t t0=x86_rdtscp(); + asm("hlt"); // sleeper task + uint64_t t1=x86_rdtscp(); + klog("slept: l:%d h:%d",(t1-t0)); } if(current_task[cpu]==1) @@ -274,6 +290,8 @@ volatile int add_task(uint32_t parent_pid,uint32_t vmem, bool thread, char *name first=false; } + strcpy(task_list[cpu][i].name,name); + return task_list[cpu][i].pid; } } @@ -306,22 +324,27 @@ void scheduler_wake_all() */ void task_syscall_worker() { + static uint32_t c=0; /// TODO: cross check all cpus! uint32_t cpu=smp_get(SMP_APIC_ID); while(1) { bool wake=false; + bool wake_mouse=false; //TODO: would be enough only to lock during ringbuffer acces!? x86_cli(); // disable temporarily mouse/kb/timer interrupts. wake|=keyboard_worker(); - wake|=mouse_worker(); + wake_mouse|=mouse_worker(); x86_sti(); + if(wake_mouse)compositor_swap_buffers(); + if(wake)scheduler_wake_all(); - if(cpu==0)compositor_swap_buffers(); + + //if(cpu==0)compositor_swap_buffers(); for(int i=0;i [%d]", pid, ret); return ret; } +void task_set_name(uint32_t pid, char *name) +{ + uint32_t idx=task_runs(pid); + uint32_t cpu=smp_get(SMP_APIC_ID); + strcpy(task_list[cpu][idx].name,name); +} + volatile uint32_t task_clone(uint32_t pid) { uint32_t idx=task_runs(pid); uint32_t cpu=smp_get(SMP_APIC_ID); - int ret=add_task(pid,vmem_new_space_dir(task_list[cpu][idx].vmem,true),true); + char *name=task_list[cpu][idx].name; + int ret=add_task(pid,vmem_new_space_dir(task_list[cpu][idx].vmem,true),true,name); klog("[%d] cloned -> [%d]", pid, ret); return ret; } @@ -446,6 +478,17 @@ volatile uint32_t task_get_parent(uint32_t pid) return task_list[cpu][idx].parent; } +volatile int task_add_win(uint32_t pid) +{ + uint32_t cpu=smp_get(SMP_APIC_ID); + uint32_t idx=task_idx(pid); + + struct pdirectory *vmem=task_list[cpu][idx].vmem; + vmem_add_framebuffer(vmem); + compositor_add_window(vmem); + return 0; +} + volatile int task_reset(uint32_t pid, uint32_t entry, uint32_t stack,uint32_t brk) { uint32_t cpu=smp_get(SMP_APIC_ID); diff --git a/kernel/scheduler.h b/kernel/scheduler.h index 1911bc6..71d5646 100644 --- a/kernel/scheduler.h +++ b/kernel/scheduler.h @@ -19,3 +19,5 @@ volatile uint32_t task_syscall(uint32_t eax,uint32_t ebx, uint32_t ecx, uint32_t uint32_t task_runs(uint32_t pid); uint32_t task_idx(uint32_t pid); void task_exit(uint32_t pid); +void task_set_name(uint32_t pid, char *name); +volatile int task_add_win(uint32_t pid); diff --git a/kernel/smp.c b/kernel/smp.c index 0438db8..01230cf 100644 --- a/kernel/smp.c +++ b/kernel/smp.c @@ -58,7 +58,7 @@ void run_smp() apic_enable(); klog("Setup the LAPIC Timer on CPU with lapic_id=0x%x ...",apic_id()); - apic_init_timer(100);// freq x HZ + apic_init_timer(3);// freq x HZ klog("Enable Interrupts on CPU with lapic_id=0x%x ...",apic_id()); asm_smp_unlock(); diff --git a/kernel/syscalls.c b/kernel/syscalls.c index 5bdb76e..3b97917 100644 --- a/kernel/syscalls.c +++ b/kernel/syscalls.c @@ -22,6 +22,7 @@ #include "mem.h" #include "reent.h" #include "errno.h" +#include "compositor.h" #include "stdstreams.h" #define MAX_PID 200 @@ -237,6 +238,7 @@ int copy_args(char **in, char **out) int syscall_execve(const char *name, char *const argv[], char *const env[], int pid) { + fixme("not overwrite yourself?"); int arg_count=0; while(argv[arg_count]!=NULL)arg_count++; @@ -262,6 +264,8 @@ int syscall_execve(const char *name, char *const argv[], char *const env[], int *--stack=arg_count; *--stack=env1; task_reset(pid,entry_global,stack,alloc); + task_set_name(pid,name); + return 0; } @@ -398,6 +402,16 @@ uint32_t syscall_dup2(uint32_t oldfd,int newfd, int none2, uint32_t pid) fds[pid][newfd]=fd_dupl(&fds[pid][oldfd]); return newfd; } +uint32_t syscall_gui_rect(uint32_t p1, uint32_t p2, uint32_t p3, uint32_t pid) +{ + compositor_swap_buffers(); + return 1; +} +uint32_t syscall_gui_win(uint32_t p1, uint32_t p2, uint32_t p3, uint32_t pid) +{ + task_add_win(pid); + return 1; +} /** Generics */ uint32_t syscall_generic_test(uint32_t nr,uint32_t p1, uint32_t p2, uint32_t p3, uint32_t pid) @@ -469,6 +483,10 @@ uint32_t syscall_generic(uint32_t nr,uint32_t p1, uint32_t p2, uint32_t p3, uint return syscall_pipe(p1,p2,p3,pid); case SYSCALL_DUP2 : return syscall_dup2(p1,p2,p3,pid); + case SYSCALL_GUI_RECT : + return syscall_gui_rect(p1,p2,p3,pid); + case SYSCALL_GUI_WIN : + return syscall_gui_win(p1,p2,p3,pid); } kpanic("unknown syscall %d",nr); } diff --git a/kernel/syscalls.h b/kernel/syscalls.h index 5403c2c..f77aea5 100644 --- a/kernel/syscalls.h +++ b/kernel/syscalls.h @@ -42,6 +42,9 @@ #define SYSCALL_PIPE 84 #define SYSCALL_DUP2 86 +#define SYSCALL_GUI_RECT 87 +#define SYSCALL_GUI_WIN 88 + /** Todo move somewhere else and init per process , think how to make thread safe */ void fd_init_std_streams(uint32_t pid, bool use_framebuffer); diff --git a/kernel/vmem.c b/kernel/vmem.c index a1ee0e2..d99f6fd 100644 --- a/kernel/vmem.c +++ b/kernel/vmem.c @@ -212,6 +212,53 @@ static void vmem_clear_one(pdirectory* dir,uint32_t virt) } } + +// addresses need to be page aligned. (or will be forced down) +static void vmem_del_generic(pdirectory* dir, uint32_t virt,uint32_t pages, bool dealloc, bool user) +{ + //fixme("make sure the pages are marked as used in the physical mem manager, really?"); + + //force align + virt/=4096; + virt*=4096; + + while(pages>0) + { + pd_entry* entry = &dir->m_entries [PAGE_DIRECTORY_INDEX (virt) ]; + ptable* table; + + if(*entry==0){ + // no pagetable here yet. + kpanic("no pagetable found for vmem entry to delete!"); + } + else{ + // we use the existing one. + table= pd_entry_get_frame (entry); + } + + if(dealloc) + { + uint32_t page=table->m_entries [PAGE_TABLE_INDEX (virt) ]; + uint32_t phys=pt_entry_get_frame(page); + mem_free_block(phys); // free the space + } + + //zero page + pt_entry page=0; + + //set the page table + uint32_t old=table->m_entries [PAGE_TABLE_INDEX (virt) ]; + + if(old==0)kpanic("nothing to delete in vmem at 0x%08x",virt); + + table->m_entries [PAGE_TABLE_INDEX (virt) ] = page; + + virt+=4096; + + pages--; + } +} + // addresses need to be page aligned. (or will be forced down) static void vmem_add_generic(pdirectory* dir,uint32_t phys,uint32_t virt,uint32_t pages, bool alloc, bool user) { @@ -317,6 +364,12 @@ pdirectory* vmem_kernel_dir() return dir; } +void vmem_add_framebuffer(pdirectory *dir) +{ + vmem_del_generic(dir,VMEM_USER_FRAMEBUFFER,VMEM_USER_FRAMEBUFFER_PAGES,false, true); + vmem_add_alloc(dir, VMEM_USER_FRAMEBUFFER,VMEM_USER_FRAMEBUFFER_PAGES,true); /// each new process gets a 640x480x32 area +} + void vmem_free_space_dir(pdirectory *dir,bool stack_only) { diff --git a/kernel/vmem.h b/kernel/vmem.h index 211b5d3..73f9ce6 100644 --- a/kernel/vmem.h +++ b/kernel/vmem.h @@ -57,5 +57,6 @@ void vmem_init(multiboot_information *cfg_multiboot, acpi_information *cfg_acpi, void vmem_free_dir(struct pdirectory_struct *dir); struct pdirectory_struct* vmem_new_space_dir(struct pdirectory_struct *copy_dir,bool stack_only); void vmem_free_space_dir(struct pdirectory_struct *dir,bool stack_only); +void vmem_add_framebuffer(struct pdirectory_struct *dir); struct pdirectory_struct* vmem_kernel_dir(); diff --git a/lib/string/string.h b/lib/string/string.h index e5e4b94..acd03ab 100644 --- a/lib/string/string.h +++ b/lib/string/string.h @@ -5,5 +5,6 @@ void* memcpy(void* restrict dstptr, const void* restrict srcptr, int size); int strcmp(char *str1, char *str2); int strcmp_l(char *str1, char *str2, int length); int strlen(const char* string); +static char *strcpy (char* dst, const char *src ){return memcpy(dst,src,strlen(src));} #endif diff --git a/userspace/fsh.c b/userspace/fsh.c index d456d1b..62cd27e 100644 --- a/userspace/fsh.c +++ b/userspace/fsh.c @@ -88,6 +88,7 @@ int main(int argc, char **argv) while(1) { + _gui_rect(); char c=fgetc(stdin); if(c=='\b') diff --git a/userspace/newcalls.h b/userspace/newcalls.h index 20d8ffd..e22bc78 100644 --- a/userspace/newcalls.h +++ b/userspace/newcalls.h @@ -4,6 +4,8 @@ #define SYSCALL_CLONE 83 #define SYSCALL_PIPE 84 #define SYSCALL_DUP2 86 +#define SYSCALL_GUI_RECT 87 +#define SYSCALL_GUI_WIN 88 int _clone(void) { @@ -17,4 +19,12 @@ int _dup2(uint32_t oldfd,uint32_t newfd) { return syscall(SYSCALL_DUP2,oldfd,newfd,0); } +int _gui_rect() +{ + return syscall(SYSCALL_GUI_RECT,0,0,0); +} +int _gui_win() +{ + return syscall(SYSCALL_GUI_WIN,0,0,0); +} // diff --git a/userspace/pain2.c b/userspace/pain2.c index 840b6b6..69784ce 100644 --- a/userspace/pain2.c +++ b/userspace/pain2.c @@ -1,4 +1,5 @@ #include "put_pixel.h" +#include "newcalls.h" #include #include @@ -24,18 +25,22 @@ void doscolor(int color,int color2) int main(int argc,char **argv) { + _gui_win(); + for(int i=0;i0;i--) + for(int i=380;i>0;i-=80) { put_rect(0,0,640,480,0xff0000); - put_rect(100+i,100+i,100,100,0x0000ff); + put_rect(i,i,100,100,0x0000ff); + _gui_rect(); } } diff --git a/video/compositor.c b/video/compositor.c index 0997978..f6fcc6e 100644 --- a/video/compositor.c +++ b/video/compositor.c @@ -226,6 +226,8 @@ void compositor_swap_buffers() void compositor_mouse_handle(uint16_t x,uint16_t y, uint8_t key) { + + //klog("mouse: %d %d",x,y); static int last_mouse_x; static int last_mouse_y; @@ -276,7 +278,6 @@ void compositor_mouse_handle(uint16_t x,uint16_t y, uint8_t key) temp=windows[active]; windows[active]=windows[0]; windows[0]=temp; - } } -- cgit v1.2.3