diff --git a/Makefile b/Makefile index ff578a4..2b68887 100644 --- a/Makefile +++ b/Makefile @@ -129,7 +129,8 @@ kal_kern_obj= $(KOBJDIR)/kernel/cpuid.o $(KOBJDIR)/kernel/init.o \ $(KOBJDIR)/kernel/term.o $(KOBJDIR)/kernel/vga.o \ $(KOBJDIR)/kernel/panic.o $(KOBJDIR)/kernel/map.o \ $(KOBJDIR)/kernel/heap.o $(KOBJDIR)/kernel/malloc.o \ - $(KOBJDIR)/kernel/buf.o + $(KOBJDIR)/kernel/buf.o $(KOBJDIR)/kernel/sched.o \ + $(KOBJDIR)/kernel/bput.o $(KOBJDIR)/kernel/bprint.o \ $(KOBJDIR)/kernel/cpuid.o: $(KERNELDIR)/kernel/cpu/cpuid.c $(KERNELDIR)/include/*/*.h @$(KCC) $< -o $@ @@ -164,6 +165,15 @@ $(KOBJDIR)/kernel/malloc.o: $(KERNELDIR)/kernel/mm/malloc.c $(KERNELDIR)/include $(KOBJDIR)/kernel/buf.o: $(KERNELDIR)/kernel/buf/buf.c $(KERNELDIR)/include/*/*.h @$(KCC) $< -o $@ @echo ${CL2}[$@] ${CL}Compiled.${CL3} +$(KOBJDIR)/kernel/bput.o: $(KERNELDIR)/kernel/buf/bput.c $(KERNELDIR)/include/*/*.h + @$(KCC) $< -o $@ + @echo ${CL2}[$@] ${CL}Compiled.${CL3} +$(KOBJDIR)/kernel/bprint.o: $(KERNELDIR)/kernel/buf/bprint.c $(KERNELDIR)/include/*/*.h + @$(KCC) $< -o $@ + @echo ${CL2}[$@] ${CL}Compiled.${CL3} +$(KOBJDIR)/kernel/sched.o: $(KERNELDIR)/kernel/proc/sched.c $(KERNELDIR)/include/*/*.h + @$(KCC) $< -o $@ + @echo ${CL2}[$@] ${CL}Compiled.${CL3} ## MISC MAKEFILE ------------------------------------------------------------- # ./ProjectTree: ./.stylehlp_sh diff --git a/kaleid/crtlib/atoi.c b/kaleid/crtlib/atoi.c index fba62ca..3b1b737 100644 --- a/kaleid/crtlib/atoi.c +++ b/kaleid/crtlib/atoi.c @@ -28,9 +28,9 @@ // Do not change errno #define _ATOI_IMPL(_Name, _Type, _Func) \ _Type _Name(const char *str) { \ - __get_errno(old); \ + error_t old; geterrno(old); \ _Type ret = (_Type)_Func(str, NULL, 0); \ - __set_errno(old); \ + seterrno(old); \ return ret; \ } diff --git a/kaleid/crtlib/itoa.c b/kaleid/crtlib/itoa.c index 95c1bd7..52d45a8 100644 --- a/kaleid/crtlib/itoa.c +++ b/kaleid/crtlib/itoa.c @@ -72,7 +72,7 @@ char *ultoa(ulong i, char *str, int base) // Only handle base 2 -> 36 if (base < 2 || base > 36) { - __set_errno(EINVAL); + seterrno(EINVAL); *orig = '\0'; goto leave; } diff --git a/kaleid/crtlib/mem.c b/kaleid/crtlib/mem.c index 208cffc..cd158e9 100644 --- a/kaleid/crtlib/mem.c +++ b/kaleid/crtlib/mem.c @@ -37,12 +37,18 @@ void *malloc(size_t n) error_t rc; rc = KalAllocMemory(&ptr, n, 0, 0); - __set_errno(rc); - (void)rc; + if (rc > 0) seterrno(rc); return ptr; } +void *calloc(size_t n, size_t m) +{ + char *mem = malloc(n * m); + memzero(mem, n * m); + return mem; +} + void free(void *ptr) { error_t rc = KalFreeMemory(ptr); @@ -132,7 +138,7 @@ void *memsetd(void *ptr, int val, size_t dwords) { (void)val; (void)dwords; - __set_errno(ENOSYS); + seterrno(ENOSYS); return ptr; } diff --git a/kaleid/crtlib/strtol.c b/kaleid/crtlib/strtol.c index dbde8ab..91c943d 100644 --- a/kaleid/crtlib/strtol.c +++ b/kaleid/crtlib/strtol.c @@ -28,7 +28,7 @@ long strtol(const char *str, char **endp, int base) { (void)str; (void)endp; (void)base; - __set_errno(ENOSYS); + seterrno(ENOSYS); return 0; } @@ -36,7 +36,7 @@ ulong strtoul(const char *str, char **endp, int base) { (void)str; (void)endp; (void)base; - __set_errno(ENOSYS); + seterrno(ENOSYS); return 0; } diff --git a/kaleid/include/base/crtlib.h b/kaleid/include/base/crtlib.h index a62aa39..8e7af7b 100644 --- a/kaleid/include/base/crtlib.h +++ b/kaleid/include/base/crtlib.h @@ -33,7 +33,7 @@ extern "C" { #ifndef __error_t_defined #define __error_t_defined -typedef int error_t; +typedef unsigned int error_t; #endif #ifndef __size_t_defined @@ -66,14 +66,14 @@ extern error_t __errno; #define errno __errno #endif -#define __get_errno(x) error_t x = errno -#define __set_errno(x) (errno = (x)) +#define geterrno(x) ((x) = errno) +#define seterrno(x) (errno = (x)) #else #define errno -#define __get_errno(x) -#define __set_errno(x) +#define geterrno(x) ((void)x) +#define seterrno(x) ((void)x) #endif diff --git a/kaleid/include/base/types.h b/kaleid/include/base/types.h index 0a1815a..ab3b547 100644 --- a/kaleid/include/base/types.h +++ b/kaleid/include/base/types.h @@ -119,7 +119,7 @@ typedef struct { long quot, rem; } ldiv_t; #ifndef __error_t_defined #define __error_t_defined -typedef int error_t; +typedef uint error_t; #endif #ifndef __port_t_defined diff --git a/kaleid/include/extras/list.h b/kaleid/include/extras/list.h index fea7f2a..7c51556 100644 --- a/kaleid/include/extras/list.h +++ b/kaleid/include/extras/list.h @@ -22,10 +22,6 @@ // along with OS/K. If not, see . // //----------------------------------------------------------------------------// -#ifdef _KALEID_KERNEL -#error "extra/list.h - Not ready for kernel compilation" -#endif - #ifndef _KALBASE_H #include #endif @@ -74,7 +70,7 @@ struct ListNode_t static inline ListHead_t *ExCreateListHeadWithLock(Lock_t *lock) { - ListHead_t *head = KalAllocMemory(sizeof(ListHead_t)); + ListHead_t *head = malloc(sizeof(ListHead_t)); if (head == NULL) return NULL; @@ -101,7 +97,7 @@ static inline ListHead_t static inline ListNode_t *ExCreateNode(void *data) { - ListNode_t *node = KalAllocMemory(sizeof(ListNode_t)); + ListNode_t *node = malloc(sizeof(ListNode_t)); if (node == NULL) return NULL; @@ -118,7 +114,7 @@ static inline ListNode_t static inline ListHead_t *ExPrependNode(ListHead_t *head, ListNode_t *node) { - KalAssert(head && node); + assert(head && node); node->head = head; node->prev = NULL; @@ -146,7 +142,7 @@ static inline ListHead_t static inline ListHead_t *ExAppendNode(ListHead_t *head, ListNode_t *node) { - KalAssert(head && node); + assert(head && node); node->head = head; node->next = NULL; @@ -174,7 +170,7 @@ static inline ListHead_t static inline ListHead_t *ExAddNodeBefore(ListHead_t *head, ListNode_t *node1, ListNode_t *node2) { - KalAssert(head && node1 && node2 && node1->head == head); + assert(head && node1 && node2 && node1->head == head); if (head->first == node1) { return ExPrependNode(head, node2); @@ -200,7 +196,7 @@ static inline ListHead_t static inline ListHead_t *ExAddNodeAfter(ListHead_t *head, ListNode_t *node1, ListNode_t *node2) { - KalAssert(head && node1 && node2 && node1->head == head); + assert(head && node1 && node2 && node1->head == head); if (head->last == node1) { return ExAppendNode(head, node2); @@ -224,7 +220,7 @@ static inline ListHead_t static inline ListHead_t *ExRemoveNode(ListHead_t *head, ListNode_t *node) { - KalAssert(head && node && head->length > 0 && node->head == head); + assert(head && node && head->length > 0 && node->head == head); if (head->length == 1) { head->first = head->last = NULL; @@ -259,8 +255,8 @@ leave: static inline void ExDestroyNode(ListNode_t *node) { - KalAssert(node); - KalFreeMemory(node); + assert(node); + free(node); } // @@ -269,8 +265,8 @@ ExDestroyNode(ListNode_t *node) static inline void ExDestroyListHead(ListHead_t *head) { - KalAssert(head); - KalFreeMemory(head); + assert(head); + free(head); } // diff --git a/kaleid/include/extras/locks.h b/kaleid/include/extras/locks.h index af41152..eba1e36 100644 --- a/kaleid/include/extras/locks.h +++ b/kaleid/include/extras/locks.h @@ -32,6 +32,10 @@ #include #endif +#ifndef _KALKERN_SCHED_H +#include +#endif + #endif #ifndef _KALEXTRAS_LOCKS_H @@ -62,8 +66,8 @@ enum LockType_t struct Lock_t { unsigned int initDone; - LockType_t type; volatile int locked; + LockType_t type; /* #ifdef _KALEID_KERNEL Thread_t *ownerThread; // unused @@ -83,8 +87,8 @@ int KalYieldCPU(void), static inline void ExInitLock(Lock_t *lock, LockType_t type) { + lock->locked = 0; lock->type = type; - lock->locked = FALSE; lock->initDone = INITOK; /* #ifdef _KALEID_KERNEL lock->ownerThread = NULL; @@ -96,9 +100,9 @@ void ExInitLock(Lock_t *lock, LockType_t type) // Alternative way to initalize a lock // #ifdef _KALEID_KERNEL -# define ExINITLOCK(type) { INITOK, FALSE, (type), /* NULL, NULL */ } +# define ExINITLOCK(type) { INITOK, 0, (type), /* NULL, NULL */ } #else -# define ExINITLOCK(type) { INITOK, FALSE, (type) } +# define ExINITLOCK(type) { INITOK, 0, (type) } #endif // @@ -119,18 +123,29 @@ void ExDestroyLock(Lock_t *lock) // until we have at least a basic scheduler // static inline +#if defined(_KALEID_KERNEL) && !defined(_NO_DEBUG) +#define ExAcquireLock(lock) \ + _ExAcquireLock(lock,__FILE__, __LINE__, __func__,#lock) +void _ExAcquireLock(Lock_t *lock, const char *file, int line, + const char *func, const char *obj) +#else void ExAcquireLock(Lock_t *lock) +#endif { KalAssert(lock->initDone == INITOK); while (!__sync_bool_compare_and_swap(&lock->locked, 0, 1)) { -#ifdef _KALEID_KERNEL - KeStartPanic("AcquireLock on an already locked object"); -#else - if likely (lock->type == KLOCK_SPINLOCK) continue; - else (void)KalYieldCPU(); +#if defined(_KALEID_KERNEL) && !defined(_NO_DEBUG) + KeStartPanic( + "In function '%s', from '%s' line %d\n" + "Double ExAcquireLock on object: '%s'", + func, file, line, obj); #endif + /*if likely (lock->type == KLOCK_SPINLOCK)*/ + continue; + //else (void)KalYieldCPU(); } + PsDisablePreemption(); __sync_synchronize(); } @@ -146,7 +161,9 @@ void ExReleaseLock(Lock_t *lock) #endif*/ __sync_synchronize(); + lock->locked = 0; + PsEnablePreemption(); } // diff --git a/kaleid/include/kernel/base.h b/kaleid/include/kernel/base.h index d15b63a..7ae02d7 100644 --- a/kaleid/include/kernel/base.h +++ b/kaleid/include/kernel/base.h @@ -56,13 +56,12 @@ typedef enum TermColor_t TermColor_t; #endif // Current CPU number -// Will return a CPU-local variable later -#define _KeGetCurCPU() 0 +#define _KeCurCPU 0 -// Get Process_t structure of current CPU -#define KeGetCurCPU() (cpuTable[_KeGetCurCPU()]) +// Process_t structure of current CPU +#define KeCurCPU (cpuTable[_KeCurCPU]) -//Get the BootInfo_t structure +// Access the BootInfo_t structure #define BtGetBootInfo(x) (bootTab.x) //------------------------------------------// diff --git a/kaleid/include/kernel/buf.h b/kaleid/include/kernel/buf.h index 13520d5..eb6cf48 100644 --- a/kaleid/include/kernel/buf.h +++ b/kaleid/include/kernel/buf.h @@ -69,9 +69,9 @@ struct Buffer_t size_t size; // Current size - char *buf; // Beginning of buffer - char *rp; // Read pointer - char *wp; // Write pointer + uchar *buf; // Beginning of buffer + uchar *rp; // Read pointer + uchar *wp; // Write pointer BFlusher_t flusher; // Called for flushing @@ -107,7 +107,7 @@ bool BTrylockBuf(Buffer_t *buf); error_t BFlushBuf(Buffer_t *buf); error_t BPutOnBuf(Buffer_t *buf, uchar ch); -error_t BPrintOnBuf(Buffer_t *buf, size_t n, const char *fmt, ...); -error_t BPrintOnBufV(Buffer_t *buf, size_t n, const char *fmt, va_list ap); +error_t BPrintOnBuf(Buffer_t *buf, const char *fmt, ...); +error_t BPrintOnBufV(Buffer_t *buf, const char *fmt, va_list ap); #endif diff --git a/kaleid/include/kernel/heap.h b/kaleid/include/kernel/heap.h index 9783c36..d8f4c78 100644 --- a/kaleid/include/kernel/heap.h +++ b/kaleid/include/kernel/heap.h @@ -31,7 +31,7 @@ //------------------------------------------// -#define _HEAP_START (4 * MB) +#define _HEAP_START (8 * MB) void MmInitHeap(void); diff --git a/kaleid/include/kernel/mm.h b/kaleid/include/kernel/mm.h index a70cdce..9fc07e1 100644 --- a/kaleid/include/kernel/mm.h +++ b/kaleid/include/kernel/mm.h @@ -44,7 +44,7 @@ struct MapEntry_t { void *addr; size_t length; // in bytes uint type; // reserved or not -} __attribute__((packed)); +} __attribute__((__packed__)); // the map structure struct MemoryMap_t { @@ -52,7 +52,7 @@ struct MemoryMap_t { size_t freeRamSize; size_t nonfreeRamSize; MapEntry_t entry[MAX_ENTRIES]; -} __attribute__((packed)); +} __attribute__((__packed__)); @@ -64,7 +64,8 @@ struct MemoryMap_t { error_t MmInitMemoryMap(void); // -// Returns the size of the first available memory zone from the start address pointer +// Returns the size of the first available memory zone +// from the start address pointer // size_t MmGetAvailZoneSize(void *start); diff --git a/kaleid/include/kernel/multiboot.h b/kaleid/include/kernel/multiboot.h index 896f23d..27da31f 100644 --- a/kaleid/include/kernel/multiboot.h +++ b/kaleid/include/kernel/multiboot.h @@ -96,7 +96,7 @@ typedef unsigned char uchar; typedef unsigned short ushort; typedef unsigned int uint; -typedef unsigned long long ullong; +typedef unsigned long ulong; struct multiboot_header { @@ -141,7 +141,8 @@ struct multiboot_elf_section_header_table uint addr; uint shndx; }; -typedef struct multiboot_elf_section_header_table multiboot_elf_section_header_table_t; +typedef struct multiboot_elf_section_header_table + multiboot_elf_section_header_table_t; struct multiboot_info { @@ -193,7 +194,7 @@ struct multiboot_info ushort vbe_interface_off; ushort vbe_interface_len; - ullong framebuffer_addr; + ulong framebuffer_addr; uint framebuffer_pitch; uint framebuffer_width; uint framebuffer_height; diff --git a/kaleid/include/kernel/proc.h b/kaleid/include/kernel/proc.h index 68b4770..2e4e962 100644 --- a/kaleid/include/kernel/proc.h +++ b/kaleid/include/kernel/proc.h @@ -77,8 +77,11 @@ struct Process_t //------------------------------------------// -DEC_PER_CPU(Ps, CurProc, process, Process_t *); -DEC_PER_CPU(Ps, CurThread, thread, Thread_t *); +#define PsCurProc (KeCurCPU.process) +#define PsCurThread (KeCurCPU.thread) + +//DEC_PER_CPU(Ps, CurProc, process, Process_t *); +//DEC_PER_CPU(Ps, CurThread, thread, Thread_t *); //------------------------------------------// diff --git a/kaleid/include/kernel/sched.h b/kaleid/include/kernel/sched.h index 694aaff..76bd799 100644 --- a/kaleid/include/kernel/sched.h +++ b/kaleid/include/kernel/sched.h @@ -39,7 +39,7 @@ enum { PREEMPT_ON = 0 }; // Time in ticks a process should be run enum { - DEF_PROC_TSLICE = 5, // 20 ticks + DEF_PROC_TSLICE = 3, // 20 ticks TCR_PROC_TSLICE = 20000 // 20000 ticks (time critical) }; @@ -57,24 +57,14 @@ extern const char *PsPrioClassesNames[]; //------------------------------------------// -DEC_PER_CPU(Ps, ReSchedFlag, needReSched, bool); -DEC_PER_CPU(Ps, PreemptCount, preemptCount, ulong); - -DEC_PER_CPU(Ps, IdlePrioProcs, idlePrioProcs, ListHead_t *); -DEC_PER_CPU(Ps, ReglPrioProcs, reglPrioProcs, ListHead_t *); -DEC_PER_CPU(Ps, ServPrioProcs, servPrioProcs, ListHead_t *); -DEC_PER_CPU(Ps, TimeCritProcs, timeCritProcs, ListHead_t *); - -//------------------------------------------// - // // Re-scheduling and preemption // XXX atomic operations // -#define PsSetReSchedFlag(x) _PsSetReSchedFlag(x) -#define PsDisablePreemption() _PsSetPreemptCount(GetPreemptCount()+1) -#define PsEnablePreemption() do { KalAssert(GetPreemptCount() > 0); \ - _PsSetPreemptCount(GetPreemptCount()-1); } while(0) +#define PsRequestReSched() (++KeCurCPU.needReSched) +#define PsDisablePreemption() (++KeCurCPU.preemptCount) +#define PsEnablePreemption() do { assert(KeCurCPU.preemptCount > 0); \ + --KeCurCPU.preemptCount; } while(0) //------------------------------------------// diff --git a/kaleid/kernel/buf/bprint.c b/kaleid/kernel/buf/bprint.c new file mode 100644 index 0000000..749100a --- /dev/null +++ b/kaleid/kernel/buf/bprint.c @@ -0,0 +1,373 @@ +//----------------------------------------------------------------------------// +// GNU GPL OS/K // +// // +// Desc: Buffer library // +// // +// // +// Copyright © 2018-2019 The OS/K Team // +// // +// This file is part of OS/K. // +// // +// OS/K 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 3 of the License, or // +// any later version. // +// // +// OS/K 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 OS/K. If not, see . // +//----------------------------------------------------------------------------// + +#include + +#include //XXX + +error_t bputc(Buffer_t *buf, uchar ch); + +// +// Prints formatted string on buf according to fmt +// +error_t BPrintOnBuf(Buffer_t *buf, const char *fmt, ...) +{ + error_t rc; + va_list ap; + + va_start(ap, fmt); + rc = BPrintOnBufV(buf, fmt, ap); + va_end(ap); + + return rc; +} +// +// Prints 0 for octal, 0x for hexadecimal, 0b for binary +// +static error_t bprinthash(Buffer_t *buf, int base, int cap) +{ + error_t rc; + + if (base != 2 && base != 8 && base != 16) { + return EOK; + } + + rc = bputc(buf, '0'); + + if (!rc && base != 8) { + rc = bputc(buf, (base==2 ? 'b' : (cap ? 'X' : 'x'))); + } + + return rc; +} + +static error_t bdopadding(Buffer_t *buf, size_t width, size_t len, + char filler) +{ + error_t rc = EOK; + + for (; !rc && width > len ; width--) { + rc = bputc(buf, filler); + } + + return rc; +} + + +// Increase fmt while parsing a modifier +#define fmtnext() do{fmt++;if(*fmt==0){rc=EINVAL;goto leave;}}while(0) + +// +// Actually does BPrintOnBuf's job +// Quite a long function +// +error_t BPrintOnBufV(Buffer_t *buf, const char *fmt, va_list ap) +{ + error_t rc = EOK; + int tmpwidth; + size_t width; + char type; + + uchar *s; + uchar uch; + + // Conversion buffer + uchar convbuf[100] = {0}; + size_t len; + + // Flags + int plus, minus, space, zero, hash; + + // Length modifiers + int l, h, hh; + + // Signed + bool sgn; + + // Capital digits + bool cap; + + // Base + int base; + + assert(buf && buf->initDone == INITOK); + + if (!buf) return EINVAL; + if (buf->state != BS_RDWR && buf->state != BS_WRONLY) { + return EBADF; + } + + ExAcquireLock(&buf->lock); + +//----------------------------------------------------------------------------// + + // We come back here after dealing with a modifier +loop: + + // Deal with all non-'%' characters + for (; !rc && *fmt && *fmt != '%' ; fmt++) { + rc = bputc(buf, *fmt); + continue; + } + + // Job's done / something bad happened + if (rc || !*fmt) goto leave; + +//----------------------------------------------------------------------------// + + // + // %[parameter][flags][width|*][.precision][length]type + // We aren't dealing with parameters and float stuff just yet + // + + // Skip the '%' + fmtnext(); + + // "%%" modifier + if (*fmt == '%') { + rc = bputc(buf, '%'); + + if (rc > 0) goto leave; + else { + fmt++; + goto loop; + } + } + + // Reset everything + width = 0; + cap = sgn = 0; + l = h = hh = 0; + plus = minus = space = zero = hash = 0; + +//----------------------------------------------------------------------------// + + // + // Flags field + // + while (1) { + if (*fmt == '#') hash++; + else if (*fmt == '0') zero++; + else if (*fmt == '+') plus++; + else if (*fmt == '-') minus++; + else if (*fmt == ' ') space++; + else break; + fmtnext(); + } + +//----------------------------------------------------------------------------// + + // + // Width field + // A width field of zero is ignored + // + + // '*' means we should extract it from the argument list + if (*fmt == '*') { + fmtnext(); + tmpwidth = va_arg(ap, int); + + // A width below 0 activates the "minus" flag + if (tmpwidth < 0) { + width = -tmpwidth; + minus++; + } else { + width = tmpwidth; + } + } else { + // Extract width field from fmt + while (isdigit(*fmt) && width < sizeof(convbuf)-10) { + width = 10 * width + (*fmt - '0'); + fmtnext(); + } + } + + if (width > sizeof(convbuf)) { + rc = EINVAL; + goto leave; + } + +//----------------------------------------------------------------------------// + + // + // Precision field + // Ignored until floats are implemented + // + +//----------------------------------------------------------------------------// + + // + // Length field + // + while (1) { + if (*fmt == 'l' || *fmt == 'z') l++; + else if (*fmt == 'h') h++; + else break; + fmtnext(); + } + + // Consistency check + assert(!(l > 0 && h > 0)); + assert(!(l > 2 || h > 2)); + +//----------------------------------------------------------------------------// + + // + // The type field, finally! + // + type = *fmt++; + + // Characters + if (type == 'c') { + uch = (uchar)va_arg(ap, int); + bputc(buf, uch); + + goto loop; + } + + // Strings + else if (type == 's') { + s = (uchar *)va_arg(ap, char *); + + for (; !rc && *s ; s++) { + rc = bputc(buf, *s); + } + + if (rc > 0) goto leave; + goto loop; + } + + // Decimal, unsigned decimal, hexadecimal, octal and binary numbers + else if (type == 'd' || type == 'i') { base = 10; sgn = 1; } + else if (type == 'X') { base = 16; cap = 1; } + else if (type == 'x') { base = 16; } + else if (type == 'u') { base = 10; } + else if (type == 'o') { base = 8; } + else if (type == 'b') { base = 2; } + + // Pointers: %p = %#012x + // (48-bit pointers have width 12 at least) + else if (type == 'p') { + type = 'x'; base = 16; zero++; hash++; + if (width < 12) width = 12; + } + + // Unknown/unsupported modifier + else { + rc = EINVAL; + goto leave; + } + +//----------------------------------------------------------------------------// + + // + // Numerical conversions + // + + // We re-use s to iterate convbuf + s = convbuf; + + // Deal with signed conversions + if (sgn) { + if (l) ltoa(va_arg(ap, long), (char *)s, base); + else if (h == 0) itoa(va_arg(ap, int), (char *)s, base); + else if (h == 1) itoa((short)va_arg(ap, int), (char *)s, base); + else /* h == 2 */ itoa((char)va_arg(ap, int), (char *)s, base); + } + + // Deal with unsigned conversions + else { + if (l) ultoa((ulong)va_arg(ap, long), (char *)s, base); + else if (h == 0) utoa((uint)va_arg(ap, int), (char *)s, base); + else if (h == 1) utoa((ushort)va_arg(ap, int), (char *)s, base); + else /* h == 2 */ utoa((uchar)va_arg(ap, int), (char *)s, base); + } + +//----------------------------------------------------------------------------// + + // + // Implement flags and %X + // + + // Capital letter digits + if (base > 10 && cap) { + for (; *s ; s++) + if (islower(*s)) *s = toupper(*s); + + // We use this "opportunity" to compute the length of s + len = s - convbuf; + + // Reset s + s = convbuf; + } + else len = strlen((char *)s); + + // Adjust width + if (sgn && (plus || space)) width--; + else if (hash) width -= (base==8 ? 1 : ((base==2||base==16) ? 2 : 0)); + + // When padding with spaces, we pad before +/-'s etc + if (!minus && !zero && width > len) + bdopadding(buf, width, len, ' '); + + // Deal with signs and the hash flag + if (*s == '-') { rc = bputc(buf, '-'); s++, len--; } + else if (sgn && plus) rc = bputc(buf, '+'); + else if (sgn && space) rc = bputc(buf, ' '); + else bprinthash(buf, base, cap); + + // Deal with padding by zeroes + // The 'minus' flag makes no sense with the 'zero' one + if (zero && width > len) + bdopadding(buf, width, len, '0'); + + // + // Output the actual number + // + for (; !rc && *s ; s++) { + rc = bputc(buf, *s); + } + + // 'minus' padding, only with spaces + if (minus && !zero && width > len) + bdopadding(buf, width, base, ' '); + + if (rc > 0) goto leave; + + +//----------------------------------------------------------------------------// + + // Make sure we leave convbuf filled with NULs + memzero(convbuf, sizeof(convbuf)); + + // Continue parsing fmt + goto loop; + +//----------------------------------------------------------------------------// + +leave: + ExReleaseLock(&buf->lock); + return rc; +} + diff --git a/kaleid/kernel/buf/bput.c b/kaleid/kernel/buf/bput.c new file mode 100644 index 0000000..46ce839 --- /dev/null +++ b/kaleid/kernel/buf/bput.c @@ -0,0 +1,141 @@ +//----------------------------------------------------------------------------// +// GNU GPL OS/K // +// // +// Desc: Buffer library // +// // +// // +// Copyright © 2018-2019 The OS/K Team // +// // +// This file is part of OS/K. // +// // +// OS/K 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 3 of the License, or // +// any later version. // +// // +// OS/K 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 OS/K. If not, see . // +//----------------------------------------------------------------------------// + +#include + +error_t bputc(Buffer_t *buf, uchar ch); + +// +// Writes a character on a buffer +// +error_t BPutOnBuf(Buffer_t *buf, uchar ch) +{ + error_t rc; + assert(buf && buf->initDone == INITOK); + + if (!buf) return EINVAL; + if (buf->state != BS_RDWR && buf->state != BS_WRONLY) { + return EBADF; + } + + ExAcquireLock(&buf->lock); + rc = bputc(buf, ch); + ExReleaseLock(&buf->lock); + return rc; +} + +// +// Internal, unlocked version of BPutOnBuf +// +error_t bputc(Buffer_t *buf, uchar ch) +{ + error_t rc; + size_t bufSize, pbCount; + + // Implements playback / scrolling up when line buffering + // Note that '\n', '\r' and '\t' can never occur in the buffer + // That should change; there should be a flag for it + if (buf->flags & BF_LINE) { + + // Deal with carriage returns + if (ch == '\r') { + buf->wp -= buf->lastLF; + buf->lastLF = 0; + assert(buf->wp >= buf->buf); + } + + // Deal with tabs... we need a tabSize field + // We assume tabs are 4 characters long for now + else if (ch == '\t') { + rc = bputc(buf, ' '); + if (rc > 0) return rc; + + while (buf->lastLF % 4 > 0) { + rc = bputc(buf, ' '); + if (rc > 0) return rc; + } + } + + // Deal with line feeds by filling the rest of the line with spaces + // We need a field for choosing a different filler, e.g. '\0' + else if (ch == '\n') { + assert(buf->lastLF < buf->lineLen); + while (buf->lastLF > 0) { + rc = bputc(buf, ' '); + if (rc > 0) return rc; + } + } + + // Just a regular character + else { + // Do we have to scroll up? + if (buf->wp == buf->buf + buf->size) { + // Yes, so we give up a whole playback buffer worth + // of lines so we don't have to do this too often + // (basically we make the current buffer a pb one) + bufSize = buf->nLines * buf->lineLen; + pbCount = (buf->size / bufSize) - 1; + + // Paranoia check + assert(buf->size >= (size_t)(buf->nLines * buf->lineLen)); + + // If we only have one playback buffer we just give up a line + if (pbCount == 0) { + // Use of memcpy() is safe because the source occur + // after the destination + memcpy(buf->buf, buf->buf + buf->lineLen, + buf->size - buf->lineLen); + buf->wp -= buf->lineLen; + } + + // We do have a playback buffer worth of lines to give up + else { + memcpy(buf->buf, buf->buf + bufSize, + buf->size - bufSize); + buf->wp -= buf->lineLen; + } + } + + // Write the damn thing + *buf->wp++ = ch; + + // Did we reach the end of line? + if (++buf->lastLF == buf->lineLen) { + buf->lastLF = 0; + } + } + + return EOK; + } + + // No scrolling up when not line-buffering + else { + if (buf->wp == buf->buf + buf->size) { + buf->state = BS_EOF; + } + + return ENOSYS; + } +} + diff --git a/kaleid/kernel/buf/buf.c b/kaleid/kernel/buf/buf.c index 3491ffd..0c42c10 100644 --- a/kaleid/kernel/buf/buf.c +++ b/kaleid/kernel/buf/buf.c @@ -47,9 +47,7 @@ void BFlushOnClose(Buffer_t *buf) { buf->flags |= BF_FONCLOSE; } // error_t BCloseBuf(Buffer_t *buf) { - if (!buf) return EINVAL; - - assert(buf->initDone == INITOK); + assert(buf && buf->initDone == INITOK); ExAcquireLock(&buf->lock); if (buf->flags & BF_FONCLOSE) { @@ -109,9 +107,9 @@ Buffer_t *BOpenLineBuf(char *source, int mode, buf->size = lineLen * nLines * (pbCount + 1); if (source == NULL) { - buf->buf = malloc(buf->size); + buf->buf = calloc(buf->size, 1); } else { - buf->buf = source; + buf->buf = (uchar *)source; } buf->wp = buf->rp = buf->buf; @@ -143,121 +141,4 @@ error_t BFlushBuf(Buffer_t *buf) return rc; } -static error_t bputc(Buffer_t *buf, uchar ch); - -// -// Writes a character on a buffer -// -error_t BPutOnBuf(Buffer_t *buf, uchar ch) -{ - error_t rc; - assert(buf && buf->initDone == INITOK); - - if (!buf) return EINVAL; - if (buf->state != BS_RDWR && buf->state != BS_WRONLY) { - return EBADF; - } - - ExAcquireLock(&buf->lock); - rc = bputc(buf, ch); - ExReleaseLock(&buf->lock); - return rc; -} - -// -// Internal, unlocked version of BPutOnBuf -// -static error_t bputc(Buffer_t *buf, uchar ch) -{ - error_t rc; - size_t bufSize, pbCount; - - // Implements playback / scrolling up when line buffering - // Note that '\n', '\r' and '\t' can never occur in the buffer - // That should change; there should be a flag for it - if (buf->flags & BF_LINE) { - - // Deal with carriage returns - if (ch == '\r') { - buf->wp -= buf->lastLF; - buf->lastLF = 0; - assert(buf->wp >= buf->buf); - } - - // Deal with tabs... we need a tabSize field - // We assume tabs are 4 characters long for now - else if (ch == '\t') { - rc = bputc(buf, ' '); - if (rc > 0) return rc; - - while (buf->lastLF % 4 > 0) { - rc = bputc(buf, ' '); - if (rc > 0) return rc; - } - } - - // Deal with line feeds by filling the rest of the line with spaces - // We need a field for choosing a different filler, e.g. '\0' - else if (ch == '\n') { - assert(buf->lastLF < buf->lineLen); - while (buf->lastLF > 0) { - rc = bputc(buf, ' '); - if (rc > 0) return rc; - } - } - - // Just a regular character - else { - // Do we have to scroll up? - if (buf->wp == buf->buf + buf->size) { - // Yes, so we give up a whole playback buffer worth - // of lines so we don't have to do this too often - // (basically we make the current buffer a pb one) - bufSize = buf->nLines * buf->lineLen; - pbCount = (buf->size / bufSize) - 1; - - // Paranoia check - assert(buf->size >= (size_t)(buf->nLines * buf->lineLen)); - - // If we only have one playback buffer we just give up a line - if (pbCount == 0) { - // Use of memcpy() is safe because the source occur - // after the destination - memcpy(buf->buf, buf->buf + buf->lineLen, - buf->size - buf->lineLen); - buf->wp -= buf->lineLen; - } - - // We do have a playback buffer worth of lines to give up - else { - memcpy(buf->buf, buf->buf + bufSize, - buf->size - bufSize); - buf->wp -= buf->lineLen; - } - } - - // Write the damn thing - *buf->wp++ = (char)ch; - - // Did we reach the end of line? - if (++buf->lastLF == buf->lineLen) { - buf->lastLF = 0; - } - } - - return EOK; - } - - // No scrolling up when not line-buffering - else { - if (buf->wp == buf->buf + buf->size) { - buf->state = BS_EOF; - } - - return ENOSYS; - } -} - -error_t BPrintOnBuf(Buffer_t *buf, size_t n, const char *fmt, ...); -error_t BPrintOnBufV(Buffer_t *buf, size_t n, const char *fmt, va_list ap); diff --git a/kaleid/kernel/init/init.c b/kaleid/kernel/init/init.c index bd07433..7ec185b 100644 --- a/kaleid/kernel/init/init.c +++ b/kaleid/kernel/init/init.c @@ -24,7 +24,10 @@ #include #include +#include #include +#include +#include #include // @@ -33,8 +36,8 @@ // void BtInitBootInfo(multiboot_info_t *mbi) { - extern ullong MB_header; - extern ullong kernelEnd; + extern ulong MB_header; + extern ulong kernelEnd; // We need the multiboot structure KalAlwaysAssert(mbi); @@ -43,19 +46,19 @@ void BtInitBootInfo(multiboot_info_t *mbi) BtGetBootInfo(btldr).grubFlags = mbi->flags; if (BtGetBootInfo(btldr).grubFlags & MULTIBOOT_INFO_BOOT_LOADER_NAME) { - BtGetBootInfo(btldr).grubName = (char*)(ullong)(mbi->boot_loader_name); + BtGetBootInfo(btldr).grubName = (char*)(ulong)(mbi->boot_loader_name); BtGetBootInfo(btldr).kernelAddr = (void*)&MB_header; BtGetBootInfo(btldr).kernelEndAddr = (void*)&kernelEnd; BtGetBootInfo(btldr).valid = 1; } if (BtGetBootInfo(btldr).grubFlags & MULTIBOOT_INFO_MODS) { BtGetBootInfo(btldr).modulesCount = mbi->mods_count; - BtGetBootInfo(btldr).modulesAddr = (void*)(ullong)mbi->mods_addr; + BtGetBootInfo(btldr).modulesAddr = (void*)(ulong)mbi->mods_addr; } //Retrieves the drives informations if (BtGetBootInfo(btldr).grubFlags & MULTIBOOT_INFO_DRIVE_INFO) { BtGetBootInfo(drives).bufferLength = mbi->drives_length; - BtGetBootInfo(drives).bufferAddr = (void*)(ullong)mbi->drives_addr; + BtGetBootInfo(drives).bufferAddr = (void*)(ulong)mbi->drives_addr; BtGetBootInfo(drives).bufferValid = 1; } if (BtGetBootInfo(btldr).grubFlags & MULTIBOOT_INFO_BOOTDEV) { @@ -70,15 +73,15 @@ void BtInitBootInfo(multiboot_info_t *mbi) BtGetBootInfo(memory).memValid = 1; } if (BtGetBootInfo(btldr).grubFlags & MULTIBOOT_INFO_MEM_MAP) { - BtGetBootInfo(memory).mapAddr = (void*)(ullong)mbi->mmap_addr; + BtGetBootInfo(memory).mapAddr = (void*)(ulong)mbi->mmap_addr; BtGetBootInfo(memory).mapLength = mbi->mmap_length; BtGetBootInfo(memory).mapValid = 1; } // Retrieves video mode informations if (BtGetBootInfo(btldr).grubFlags & MULTIBOOT_INFO_VBE_INFO) { - BtGetBootInfo(video).vbeControl = (void*)(ullong)mbi->vbe_control_info; - BtGetBootInfo(video).vbeModeInfo = (void*)(ullong)mbi->vbe_mode_info; + BtGetBootInfo(video).vbeControl = (void*)(ulong)mbi->vbe_control_info; + BtGetBootInfo(video).vbeModeInfo = (void*)(ulong)mbi->vbe_mode_info; BtGetBootInfo(video).vbeMode = mbi->vbe_mode; BtGetBootInfo(video).vbeInterfaceSeg = mbi->vbe_interface_seg; BtGetBootInfo(video).vbeInterfaceOff = mbi->vbe_interface_off; @@ -86,7 +89,7 @@ void BtInitBootInfo(multiboot_info_t *mbi) BtGetBootInfo(video).vbeValid = 1; } if (BtGetBootInfo(btldr).grubFlags & MULTIBOOT_INFO_FRAMEBUFFER_INFO) { - BtGetBootInfo(video).framebufferAddr = (void*)(ullong)mbi->framebuffer_addr; + BtGetBootInfo(video).framebufferAddr = (void*)mbi->framebuffer_addr; BtGetBootInfo(video).framebufferPitch = mbi->framebuffer_pitch; BtGetBootInfo(video).framebufferWidth = mbi->framebuffer_width; BtGetBootInfo(video).framebufferHeight= mbi->framebuffer_height; @@ -106,6 +109,7 @@ void BtInitBootInfo(multiboot_info_t *mbi) } } +extern void pstest(void); // // Entry point of the Kaleid kernel @@ -138,12 +142,27 @@ noreturn void BtStartKern(multiboot_info_t *mbInfo, int mbMagic) mapBad ); - KernLog("[Init] TEST First zone from %p : %p\n", (void*)0xB8010, MmGetFirstAvailZone((void*)0xB8010)); - KernLog("[Init] TEST Size of zone : %u Kio\n\n", MmGetAvailZoneSize(MmGetFirstAvailZone((void*)0xB8010)) / KB); + KernLog("[Init] TEST First zone from %p : %p\n", (void*)0xB8010, + MmGetFirstAvailZone((void*)0xB8010)); + KernLog("[Init] TEST Size of zone : %u Kio\n\n", + MmGetAvailZoneSize(MmGetFirstAvailZone((void*)0xB8010)) / KB); + MmInitHeap(); + PsInitSched(); + ClearTerm(StdOut); + + Buffer_t *buf = BOpenLineBuf(NULL, BS_WRONLY, 80, 24, 1, NULL); + + //BPrintOnBuf(buf, "xxx\nxxx\ry\tw\n%d %s\n%%%p", 1, "abcd", 0); + //int i; for(i=0;i<100;i++) BPrintOnBuf(buf,"%d\n",i); + + error_t rc = BPrintOnBuf(buf, "%+#05X", 0xcafeb00b); + if(rc)KernLog("error\n"); + + KernLog((char*)buf->buf); // We're out - KernLog("\n[Init] Evil never dies !\n"); + PsFiniSched(); KeCrashSystem(); //yay } diff --git a/kaleid/kernel/ke/panic.c b/kaleid/kernel/ke/panic.c index 9c9f56b..181ab5b 100644 --- a/kaleid/kernel/ke/panic.c +++ b/kaleid/kernel/ke/panic.c @@ -35,10 +35,8 @@ noreturn void __assert_handler(const char *msg, { KeDisableIRQs(); - (void)file; (void)line; (void)func; - - KeStartPanic("In function '%s', from %s line %d - assertion failed: '%s'", - func, file, line, msg); + KeStartPanic("In function '%s', from '%s' line %d\nAssertion failed:\n" + "'%s'", func, file, line, msg); } // @@ -51,7 +49,7 @@ noreturn void KeStartPanic(const char *fmt, ...) KeDisableIRQs(); - if (PsGetCurProc()) _PsSetCurProc(NULL); + PsCurProc = NULL; if (StdOut == NULL) KeCrashSystem(); if (fmt == NULL) { diff --git a/kaleid/kernel/mm/heap.c b/kaleid/kernel/mm/heap.c index 54c700b..16c8fe9 100644 --- a/kaleid/kernel/mm/heap.c +++ b/kaleid/kernel/mm/heap.c @@ -34,7 +34,6 @@ static size_t _heap_max; // Lock NOT used internally, but used by KalAllocMemory() & co. static Lock_t _heap_lock = ExINITLOCK(KLOCK_SPINLOCK); - // // Initializes heap managment // @@ -100,7 +99,7 @@ error_t MmSetMaxHeapSize(size_t new) // error_t MmGrowHeap(size_t req) { - assert(req % alignof(QWORD)); + assert(req % alignof(QWORD) == 0); if ((size_t)_heap_end + req > _HEAP_START + _heap_max) { return ENOMEM; @@ -116,7 +115,7 @@ error_t MmGrowHeap(size_t req) // error_t MmShrinkHeap(size_t req) { - assert(req % alignof(QWORD)); + assert(req % alignof(QWORD) == 0); if (req > (size_t)_heap_end - _HEAP_START) { return EADDRINUSE; diff --git a/kaleid/kernel/mm/malloc.c b/kaleid/kernel/mm/malloc.c index 1c699a2..6d7262a 100644 --- a/kaleid/kernel/mm/malloc.c +++ b/kaleid/kernel/mm/malloc.c @@ -57,6 +57,7 @@ error_t KalAllocMemory(void **ptr, size_t req, int flags, size_t align) *ptr = (void *)brk; + assert(*ptr); return rc; } diff --git a/kaleid/kernel/mm/map.c b/kaleid/kernel/mm/map.c index 320a9b3..80759d4 100644 --- a/kaleid/kernel/mm/map.c +++ b/kaleid/kernel/mm/map.c @@ -52,23 +52,23 @@ error_t MmInitMemoryMap(void) currentEntry = (multiboot_memory_map_t*)BtGetBootInfo(memory).mapAddr; // End address of the map mapEnd = (multiboot_memory_map_t*) - ((ullong)currentEntry + (ullong)BtGetBootInfo(memory).mapLength); + ((ulong)currentEntry + (ulong)BtGetBootInfo(memory).mapLength); // fill the map while (currentEntry < mapEnd) { // memory zone address - memoryMap.entry[i].addr = (void*)( (ullong)currentEntry->addr_low + - (((ullong)currentEntry->addr_high) << 32 )); + memoryMap.entry[i].addr = (void*)((ulong)currentEntry->addr_low + + (((ulong)currentEntry->addr_high) << 32 )); // memory zone size in bytes - memoryMap.entry[i].length = (ullong)currentEntry->len_low + - (((ullong)currentEntry->len_high) << 32); + memoryMap.entry[i].length = (ulong)currentEntry->len_low + + (((ulong)currentEntry->len_high) << 32); // memory availability memoryMap.entry[i].type = (uint)currentEntry->type; // Adding the size to the size (yup) memoryMap.length++; // moving up ! - currentEntry = (multiboot_memory_map_t*) ((ullong)currentEntry + - currentEntry->size + sizeof(currentEntry->size)); + currentEntry = (multiboot_memory_map_t*) ((ulong)currentEntry + + currentEntry->size + sizeof(currentEntry->size)); i++; } @@ -108,11 +108,11 @@ size_t MmGetAvailZoneSize(void *start) { // if the address is in an available zone, we can return the length if ( memoryMap.entry[i].type == AVAILABLE_ZONE && - (ullong)start >= (ullong)memoryMap.entry[i].addr && - (ullong)start < ((ullong)memoryMap.entry[i].addr + - (ullong)memoryMap.entry[i].length) + (ulong)start >= (ulong)memoryMap.entry[i].addr && + (ulong)start < ((ulong)memoryMap.entry[i].addr + + (ulong)memoryMap.entry[i].length) ) { - return (size_t)((ullong)memoryMap.entry[i].length - (ullong)start); + return (size_t)((ulong)memoryMap.entry[i].length - (ulong)start); } } @@ -125,7 +125,7 @@ void *MmGetFirstAvailZone(void *start) { void *current = 0; // Because the kernel is the kernel - if ((ullong)start < (ullong)BtGetBootInfo(btldr).kernelEndAddr) { + if ((ulong)start < (ulong)BtGetBootInfo(btldr).kernelEndAddr) { return MmGetFirstAvailZone(BtGetBootInfo(btldr).kernelEndAddr); } @@ -134,9 +134,9 @@ void *MmGetFirstAvailZone(void *start) { // if the address is in an available zone, we can return the start address if ( memoryMap.entry[i].type == AVAILABLE_ZONE && - (ullong)start >= (ullong)memoryMap.entry[i].addr && - (ullong)start < ((ullong)memoryMap.entry[i].addr + - (ullong)memoryMap.entry[i].length) + (ulong)start >= (ulong)memoryMap.entry[i].addr && + (ulong)start < ((ulong)memoryMap.entry[i].addr + + (ulong)memoryMap.entry[i].length) ) { current = start; break; @@ -151,7 +151,7 @@ void *MmGetFirstAvailZone(void *start) { // Return the first zone that is after start if ( memoryMap.entry[i].type == AVAILABLE_ZONE && - (ullong)start <= (ullong)memoryMap.entry[i].addr + (ulong)start <= (ulong)memoryMap.entry[i].addr ) { current = memoryMap.entry[i].addr; break; diff --git a/kaleid/kernel/proc/sched.c b/kaleid/kernel/proc/sched.c index d8ba70d..2b75f5d 100644 --- a/kaleid/kernel/proc/sched.c +++ b/kaleid/kernel/proc/sched.c @@ -25,10 +25,7 @@ #include #include #include - -#ifndef _KALEID_KERNEL - -#include +#include // // For test purpose only @@ -47,18 +44,25 @@ Process_t procs[] = { { 9, 2, 2, 21, 21, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE, NULL, NULL, NULL }, }; -#endif +//------------------------------------------// + +#define ReSchedFlag (KeCurCPU.needReSched) +#define PreemptCount (KeCurCPU.preemptCount) + +#define IdlePrioProcs (KeCurCPU.idlePrioProcs) +#define ReglPrioProcs (KeCurCPU.reglPrioProcs) +#define ServPrioProcs (KeCurCPU.servPrioProcs) +#define TimeCritProcs (KeCurCPU.timeCritProcs) + +//------------------------------------------// // // Set current process -// TODO Select thread, context switch // static void SetCurProc(Process_t *proc) { - _SetCurProc(proc); - if (GetCurProc() != NULL) { - GetCurProc()->procState = STATE_RUNNING; - } + PsCurProc = proc; + if (PsCurProc) PsCurProc->procState = STATE_RUNNING; } // @@ -66,28 +70,24 @@ static void SetCurProc(Process_t *proc) // static inline -void SchedLock(void) { -#ifdef _KALEID_KERNEL - DisableIRQs(); -#endif +void PsLockSched(void) { + KeDisableIRQs(); } static inline -void SchedUnlock(void) { -#ifdef _KALEID_KERNEL - EnableIRQs(); -#endif +void PsUnlockSched(void) { + //KeEnableIRQs(); } // // The four priority classes of OS/2 // -CREATE_PER_CPU(TimeCritProcs, ListHead_t *); +/*CREATE_PER_CPU(TimeCritProcs, ListHead_t *); CREATE_PER_CPU(ServPrioProcs, ListHead_t *); CREATE_PER_CPU(ReglPrioProcs, ListHead_t *); -CREATE_PER_CPU(IdlePrioProcs, ListHead_t *); +CREATE_PER_CPU(IdlePrioProcs, ListHead_t *);*/ -const char *PrioClassesNames[] = { +const char *PsPrioClassesNames[] = { "Time-critical class", "Server priority class", "Regular priority class", @@ -100,10 +100,10 @@ const char *PrioClassesNames[] = { static ListHead_t *GetPrioClassHead(int prioClass) { switch (prioClass) { - case TIME_CRIT_PROC: return GetTimeCritProcs(); - case SERV_PRIO_PROC: return GetServPrioProcs(); - case REGL_PRIO_PROC: return GetReglPrioProcs(); - case IDLE_PRIO_PROC: return GetIdlePrioProcs(); + case TIME_CRIT_PROC: return TimeCritProcs; + case SERV_PRIO_PROC: return ServPrioProcs; + case REGL_PRIO_PROC: return ReglPrioProcs; + case IDLE_PRIO_PROC: return IdlePrioProcs; default: KalAssert(FALSE && "Unknown priority class"); } @@ -134,23 +134,24 @@ static void SchedThisProcUnlocked(Process_t *proc) { KalAssert(proc && proc->procState == STATE_RUNNABLE && !proc->schedNode); - bool found = false; + bool found = 0; ListNode_t *iterNode = NULL; - ListNode_t *procNode = CreateNode(proc); + ListNode_t *procNode = ExCreateNode(proc); ListHead_t *head = GetPrioClassHead(proc->prioClass); - KalAssert(procNode && head); + KalAssert(head); + KalAssert(procNode); proc->schedNode = procNode; // Find a process with lesser priority for (iterNode = head->first; iterNode; iterNode = iterNode->next) { - if (proc->prioLevel > GetNodeData(iterNode, Process_t *)->prioLevel) { + if (proc->prioLevel > ExGetNodeData(iterNode, Process_t *)->prioLevel) { // Detect double insertions - KalAssert(proc->pid != GetNodeData(iterNode, Process_t *)->pid); + KalAssert(proc->pid != ExGetNodeData(iterNode, Process_t *)->pid); // Add process to schedule - AddNodeBefore(head, iterNode, procNode); + ExAddNodeBefore(head, iterNode, procNode); found = true; break; } @@ -158,20 +159,20 @@ static void SchedThisProcUnlocked(Process_t *proc) // Didn't find any process with lesser priority if (found == false) { - AppendNode(head, procNode); + ExAppendNode(head, procNode); } } // // Add process to schedule lists // -void SchedThisProc(Process_t *proc) +void PsSchedThisProc(Process_t *proc) { - SchedLock(); + PsLockSched(); SchedThisProcUnlocked(proc); - SchedUnlock(); + PsUnlockSched(); } // @@ -182,10 +183,17 @@ void SchedThisProc(Process_t *proc) // static Process_t *SelectSchedNext(void) { - if (GetTimeCritProcs()->length > 0) return GetNodeData(GetTimeCritProcs()->first, Process_t *); - if (GetServPrioProcs()->length > 0) return GetNodeData(GetServPrioProcs()->first, Process_t *); - if (GetReglPrioProcs()->length > 0) return GetNodeData(GetReglPrioProcs()->first, Process_t *); - if (GetIdlePrioProcs()->length > 0) return GetNodeData(GetIdlePrioProcs()->first, Process_t *); + if (TimeCritProcs->length > 0) + return ExGetNodeData(TimeCritProcs->first, Process_t *); + + if (ServPrioProcs->length > 0) + return ExGetNodeData(ServPrioProcs->first, Process_t *); + + if (ReglPrioProcs->length > 0) + return ExGetNodeData(ReglPrioProcs->first, Process_t *); + + if (IdlePrioProcs->length > 0) + return ExGetNodeData(IdlePrioProcs->first, Process_t *); return NULL; } @@ -194,82 +202,82 @@ static Process_t *SelectSchedNext(void) // Remove running process from schedule lists // and schedule next runnable process // -void BlockCurProc(void) +void PsBlockCurProc(void) { - KalAssert(GetCurProc() && GetCurProc()->procState == STATE_RUNNING); + KalAssert(PsCurProc && PsCurProc->procState == STATE_RUNNING); - ListNode_t *procNode = GetCurProc()->schedNode; + ListNode_t *procNode = PsCurProc->schedNode; KalAssert(procNode && "Blocking non-scheduled process"); - GetCurProc()->procState = STATE_BLOCKED; - RemoveNode(procNode->head, procNode); + PsCurProc->procState = STATE_BLOCKED; + ExRemoveNode(procNode->head, procNode); - GetCurProc()->schedNode = NULL; + PsCurProc->schedNode = NULL; SetCurProc(SelectSchedNext()); } static void ReSchedCurProc(void) { - KalAssert(GetCurProc() && GetCurProc()->procState == STATE_RUNNING); - KalAssert(GetCurProc()->schedNode); + KalAssert(PsCurProc && PsCurProc->procState == STATE_RUNNING); + KalAssert(PsCurProc->schedNode); // Restore default attributes, cancelling boosts - GetCurProc()->prioClass = GetCurProc()->defPrioClass; - GetCurProc()->prioLevel = GetCurProc()->defPrioLevel; - GetCurProc()->timeSlice = GetCurProc()->defTimeSlice; - GetCurProc()->procState = STATE_RUNNABLE; + PsCurProc->prioClass = PsCurProc->defPrioClass; + PsCurProc->prioLevel = PsCurProc->defPrioLevel; + PsCurProc->timeSlice = PsCurProc->defTimeSlice; + PsCurProc->procState = STATE_RUNNABLE; // Remove from list - RemoveNode(GetCurProc()->schedNode->head, GetCurProc()->schedNode); - GetCurProc()->schedNode = NULL; + ExRemoveNode(PsCurProc->schedNode->head, PsCurProc->schedNode); + PsCurProc->schedNode = NULL; // Schedule again, with default attributes now - SchedThisProcUnlocked(GetCurProc()); + SchedThisProcUnlocked(PsCurProc); } // // Should we schedule another process? // Called at each tick // -void SchedOnTick(void) +void PsSchedOnTick(void) { - SchedLock(); + PsLockSched(); - Process_t *procNext, *winner, *previous = GetCurProc(); + Process_t *procNext, *winner, *previous = PsCurProc; // We're either idle or running something - KalAssert(GetCurProc() == NULL || GetCurProc()->procState == STATE_RUNNING); + KalAssert(PsCurProc == NULL || PsCurProc->procState == STATE_RUNNING); // Have the current process spent its timeslice? // (To be handled in CPU decisions function) - if (GetCurProc() != NULL) { - if (GetCurProc()->timeSlice <= 1) { + if (PsCurProc != NULL) { + if (PsCurProc->timeSlice <= 1) { // Re-schedule ReSchedCurProc(); // See next 'if' statement - _SetCurProc(NULL); + PsCurProc = NULL; } // Otherwise, make it lose a tick else { - GetCurProc()->timeSlice--; + PsCurProc->timeSlice--; } } // Are we idle, or scheduling next process? - if (GetCurProc() == NULL) { + if (PsCurProc == NULL) { SetCurProc(SelectSchedNext()); goto leave; } // Is preemption on and a re-schedule is needed? - if (GetPreemptCount() == PREEMPT_ON && GetReSchedFlag()) { + if (PreemptCount == PREEMPT_ON && ReSchedFlag) { // Is there a higher priority process that is runnable? procNext = SelectSchedNext(); - winner = CompareProcs(GetCurProc(), procNext); + winner = CompareProcs(PsCurProc, procNext); // Yes, procNext should preempt current process if (winner == procNext) { @@ -283,9 +291,9 @@ void SchedOnTick(void) // Current process won't be preempted and has time remaining leave: - SchedUnlock(); + PsUnlockSched(); - if (GetCurProc() != NULL && GetCurProc() != previous) { + if (PsCurProc != NULL && PsCurProc != previous) { // XXX context switch } } @@ -293,55 +301,59 @@ leave: // // Initialize scheduler // -void InitSched(void) +void PsInitSched(void) { int pid; - SchedLock(); + PsLockSched(); - _SetTimeCritProcs(CreateListHead()); - _SetServPrioProcs(CreateListHead()); - _SetReglPrioProcs(CreateListHead()); - _SetIdlePrioProcs(CreateListHead()); + TimeCritProcs = ExCreateListHead(); + ServPrioProcs = ExCreateListHead(); + ReglPrioProcs = ExCreateListHead(); + IdlePrioProcs = ExCreateListHead(); + + KalAssert(IdlePrioProcs && ReglPrioProcs && ServPrioProcs && TimeCritProcs); -#ifndef _KALEID_KERNEL for (pid = 0; pid < procslen; pid++) { if (procs[pid].procState == STATE_RUNNABLE) { SchedThisProcUnlocked(&procs[pid]); } } -#endif - SchedUnlock(); + PsUnlockSched(); } // // Shutdown scheduler // -void FiniSched(void) +void PsFiniSched(void) { - KalAssert(GetIdlePrioProcs() && GetReglPrioProcs() && GetServPrioProcs() && GetTimeCritProcs()); + KalAssert(IdlePrioProcs && ReglPrioProcs && ServPrioProcs && TimeCritProcs); - SchedLock(); + PsLockSched(); - while (GetIdlePrioProcs()->length > 0) RemoveNode(GetIdlePrioProcs(), GetIdlePrioProcs()->first); - while (GetReglPrioProcs()->length > 0) RemoveNode(GetReglPrioProcs(), GetReglPrioProcs()->first); - while (GetServPrioProcs()->length > 0) RemoveNode(GetServPrioProcs(), GetServPrioProcs()->first); - while (GetTimeCritProcs()->length > 0) RemoveNode(GetTimeCritProcs(), GetTimeCritProcs()->first); + while (IdlePrioProcs->length > 0) + ExRemoveNode(IdlePrioProcs, IdlePrioProcs->first); - DestroyListHead(GetIdlePrioProcs()); _SetIdlePrioProcs(NULL); - DestroyListHead(GetReglPrioProcs()); _SetReglPrioProcs(NULL); - DestroyListHead(GetServPrioProcs()); _SetServPrioProcs(NULL); - DestroyListHead(GetTimeCritProcs()); _SetTimeCritProcs(NULL); + while (ReglPrioProcs->length > 0) + ExRemoveNode(ReglPrioProcs, ReglPrioProcs->first); - SchedUnlock(); + while (ServPrioProcs->length > 0) + ExRemoveNode(ServPrioProcs, ServPrioProcs->first); + + while (TimeCritProcs->length > 0) + ExRemoveNode(TimeCritProcs, TimeCritProcs->first); + + ExDestroyListHead(IdlePrioProcs); IdlePrioProcs = NULL; + ExDestroyListHead(ReglPrioProcs); ReglPrioProcs = NULL; + ExDestroyListHead(ServPrioProcs); ServPrioProcs = NULL; + ExDestroyListHead(TimeCritProcs); TimeCritProcs = NULL; + + PsUnlockSched(); } -#ifndef _KALEID_KERNEL - -#define PrintProc(proc) printf("{ %d, '%s', %d , %lu}\n", (proc)->pid, \ - PrioClassesNames[(proc)->prioClass], (proc)->prioLevel, (proc)->timeSlice); - +#define PrintProc(proc) KernLog("{ %d, '%s', %d , %lu}\n", (proc)->pid, \ + PsPrioClassesNames[(proc)->prioClass], (proc)->prioLevel, (proc)->timeSlice); // // Print out process list // @@ -352,75 +364,65 @@ void PrintList(ListHead_t *head) Process_t *proc; ListNode_t *node = head->first; - printf("len: %lu\n", head->length); + KernLog("len: %lu\n", head->length); while (node) { - proc = GetNodeData(node, Process_t *); + proc = ExGetNodeData(node, Process_t *); PrintProc(proc); node = node->next; } - puts(""); + KernLog(""); } -int main(void) +void pstest(void) { - InitSched(); + ClearTerm(StdOut); - puts("---------------"); + KernLog("\nTime Critical: "); + PrintList(TimeCritProcs); - puts("Time Critical:"); - PrintList(GetTimeCritProcs()); + KernLog("\nServer: "); + PrintList(ServPrioProcs); - puts("Server:"); - PrintList(GetServPrioProcs()); + KernLog("\nRegular: "); + PrintList(ReglPrioProcs); - puts("Regular:"); - PrintList(GetReglPrioProcs()); - - puts("Idle:"); - PrintList(GetIdlePrioProcs()); - - puts("---------------"); - - getchar(); + KernLog("\nIdle:"); + PrintList(IdlePrioProcs); int tick = 0; - while (tick < 120) { + while (tick < 24) { + if (tick%25==0)ClearTerm(StdOut); if (tick > 0 && tick != 50 && tick % 10 == 0) { - puts("Blocking current process"); - BlockCurProc(); + KernLog("Blocking current process\n"); + PsBlockCurProc(); } if (tick == 50) { procs[0].procState = STATE_RUNNABLE; - SchedThisProc(&procs[0]); + PsSchedThisProc(&procs[0]); } - printf("Tick %d - Running: ", tick); + KernLog("Tick %d - Running: ", tick); - if (GetCurProc() == NULL) { - puts("IDLE"); + if (PsCurProc == NULL) { + KernLog("IDLE"); } else { - PrintProc(GetCurProc()); + PrintProc(PsCurProc); } - SchedOnTick(); + PsSchedOnTick(); if (tick == 50) // already done - puts("Re-scheduling process 0"); + KernLog("Re-scheduling process 0"); tick++; } - - FiniSched(); - - return 0; } -#endif