From 31702521b10eb50e442e8b0ce48aba257acf8470 Mon Sep 17 00:00:00 2001 From: Julian Barathieu Date: Sun, 30 Dec 2018 22:21:19 +0100 Subject: [PATCH] Still more stuff --- src/kaleid/common/assert.h | 3 +- src/kaleid/common/common.h | 4 + src/kaleid/kernel/io/terminal.c | 128 ++++++++++++++++++-------------- src/kaleid/kernel/io/terminal.h | 51 +++++++------ src/kaleid/kernel/ke/lock.c | 13 ++++ src/kaleid/kernel/ke/lock.h | 96 ++++++++++++++++++++++++ src/kaleid/kernel/ke/panic.c | 18 +++-- src/kaleid/kernel/ke/panic.h | 7 +- 8 files changed, 226 insertions(+), 94 deletions(-) create mode 100644 src/kaleid/kernel/ke/lock.c create mode 100644 src/kaleid/kernel/ke/lock.h diff --git a/src/kaleid/common/assert.h b/src/kaleid/common/assert.h index 10b663d..f01060b 100644 --- a/src/kaleid/common/assert.h +++ b/src/kaleid/common/assert.h @@ -21,7 +21,8 @@ // uses panic() in kernel, abort() in system noreturn void ___assert_handler(const char *, const char *, int, const char *); -#define assert(x) do{if(unlikely(!(x)))___assert_handler(#x, __FILE__, __LINE__, __func__);}while(0); +#define DosAssert(x) do{if(unlikely(!(x)))___assert_handler(#x, __FILE__, __LINE__, __func__);}while(0); +#define assert DosAssert #else // not debugging diff --git a/src/kaleid/common/common.h b/src/kaleid/common/common.h index 5b4dc38..bc7a36f 100644 --- a/src/kaleid/common/common.h +++ b/src/kaleid/common/common.h @@ -41,6 +41,10 @@ # define unlikely(x) __builtin_expect((x), 0) #endif +#ifndef INITOK +# define INITOK 0xCAFEBABE +#endif + #ifdef _KALEID_KERNEL # include #endif diff --git a/src/kaleid/kernel/io/terminal.c b/src/kaleid/kernel/io/terminal.c index 79da9b4..b05ab48 100644 --- a/src/kaleid/kernel/io/terminal.c +++ b/src/kaleid/kernel/io/terminal.c @@ -7,6 +7,7 @@ // Desc: Early terminal functions // //----------------------------------------------------------------------------// +#define _UNLOCKED_IO #include // @@ -26,10 +27,8 @@ static terminal_t _vga_term = { .kt_curr_x = 0, .kt_curr_y = 0, .kt_color = ComputeColorCode(KTERM_COLOR_LGREY, KTERM_COLOR_BLACK), - .kt_lock = NULL, -#ifndef _NO_DEBUG + .kt_lock = INITLOCK(KLOCK_MUTEX), .kt_init = FALSE, -#endif }; // @@ -37,24 +36,20 @@ static terminal_t _vga_term = { // terminal_t *stdout; -#ifndef _NO_DEBUG // // Debugging terminal // terminal_t *stddbg; -#endif // // Initialize standard output // void DosInitTerms(void) { - assert(!stdout && !_vga_term.kt_init && "DosInitTerms() called twice"); + DosAssert(!stdout && _vga_term.kt_init != INITOK && "DosInitTerms() called twice"); -#ifndef _NO_DEBUG - _vga_term.kt_init = TRUE; + _vga_term.kt_init = INITOK; stddbg = &_vga_term; -#endif // to be switched to VESA stdout = &_vga_term; @@ -63,29 +58,16 @@ void DosInitTerms(void) // // Fills terminal with spaces -// XXX would '\0' work too? // status_t DosClearTerm(terminal_t *kt) { - size_t i; - if (kt == NULL) return BAD_ARG_NULL; - assert(kt->kt_init && "DosClearTerm called before initialization"); + DosAssert(kt->kt_init == INITOK); DosLockTerm(kt); - - const ushort filler = ComputeEntry(' ', kt->kt_color); - const size_t bufsize = kt->kt_width * kt->kt_height; - - for (i = 0; i < bufsize; i++) { - // XXX implement memsetw() - kt->kt_buffer[i] = filler; - } - - kt->kt_curr_x = kt->kt_curr_y = 0; - + DosClearTerm_Unlocked(kt); DosUnlockTerm(kt); return SUCCESS; @@ -102,20 +84,78 @@ status_t DosChTermColor(terminal_t *kt, uchar color) if (kt == NULL) return BAD_ARG_NULL; - DosLockTerm(kt); + DosLockTerm(kt); kt->kt_color = color; DosUnlockTerm(kt); return SUCCESS; } +// +// Writes a single character on the terminal +// +status_t DosPutOnTerm(terminal_t *kt, char ch) +{ + if (kt == NULL) + return BAD_ARG_NULL; + + DosAssert(kt->kt_init == INITOK); + + DosLockTerm(kt); + DosPutOnTerm_Unlocked(kt, ch); + DosUnlockTerm(kt); + + return SUCCESS; +} + +// +// Print string on terminal +// +status_t DosPrintOnTerm(terminal_t *kt, const char *str) +{ + if (kt == NULL) + return BAD_ARG_NULL; + + DosAssert(kt->kt_init == INITOK); + + DosLockTerm(kt); + while (*str) { + DosPutOnTerm_Unlocked(kt, *str++); + } + DosUnlockTerm(kt); + + return SUCCESS; +} + +//----------------------------------------------------------// +// UNLOCKED VERSIONS // +// // +// Direct use is highly deprecated // +// Useful in rare instances // +//----------------------------------------------------------// + +// +// Fills terminal with spaces +// XXX would '\0' work too? +// +void DosClearTerm_Unlocked(terminal_t *kt) +{ + size_t i; + + const ushort filler = ComputeEntry(' ', kt->kt_color); + const size_t bufsize = kt->kt_width * kt->kt_height; + + for (i = 0; i < bufsize; i++) { + // XXX implement memsetw() + kt->kt_buffer[i] = filler; + } + + kt->kt_curr_x = kt->kt_curr_y = 0; +} + // // Writes a single character on the terminal (UNLOCKED version) // -// DEPRECATED: -// - always use kterm_putch (LOCKED version) -// - doesn't check for NULL input -// void DosPutOnTerm_Unlocked(terminal_t *kt, char ch) { int i; @@ -158,37 +198,15 @@ void DosPutOnTerm_Unlocked(terminal_t *kt, char ch) } } -// -// Writes a single character on the terminal (LOCKED version) // -status_t DosPutOnTerm(terminal_t *kt, char ch) +// Print string on terminal (UNLOCKED version) +// +void DosPrintOnTerm_Unlocked(terminal_t *kt, const char *str) { - if (kt == NULL) - return BAD_ARG_NULL; - - DosLockTerm(kt); - DosPutOnTerm_Unlocked(kt, ch); - DosUnlockTerm(kt); - - return SUCCESS; -} - - -// -// Print string on terminal -// -status_t DosPrintOnTerm(terminal_t *kt, const char *str) -{ - if (kt == NULL) - return BAD_ARG_NULL; - - DosLockTerm(kt); while (*str) { DosPutOnTerm_Unlocked(kt, *str++); } - DosUnlockTerm(kt); - - return SUCCESS; } + diff --git a/src/kaleid/kernel/io/terminal.h b/src/kaleid/kernel/io/terminal.h index 63327fb..a209ead 100644 --- a/src/kaleid/kernel/io/terminal.h +++ b/src/kaleid/kernel/io/terminal.h @@ -10,12 +10,10 @@ #ifndef _KALKERN_IO_KTERM_H #define _KALKERN_IO_KTERM_H -#ifndef _KALCOMM_COMMON_H -#include -#endif +#include // all available colors -enum kterm_colors { +enum terminal_colors { KTERM_COLOR_BLACK, KTERM_COLOR_BLUE, KTERM_COLOR_GREEN, KTERM_COLOR_CYAN, KTERM_COLOR_RED, KTERM_COLOR_MAGENTA, @@ -26,43 +24,44 @@ enum kterm_colors { KTERM_COLOR_LBROWN, KTERM_COLOR_WHITE }; -typedef struct kterm { - void *kt_lock; - ushort *kt_buffer; - uchar kt_color; - size_t kt_width; - size_t kt_height; - off_t kt_curr_x; - off_t kt_curr_y; +typedef struct { + lock_t kt_lock; + ushort *kt_buffer; + uchar kt_color; + size_t kt_width; + size_t kt_height; + off_t kt_curr_x; + off_t kt_curr_y; + uint kt_init; // XXX flags -#ifndef _NO_DEBUG - bool kt_init; -#endif } terminal_t; // current "standard" terminal extern terminal_t *stdout; -void DosInitTerms(void); -status_t DosClearTerm(terminal_t *); -status_t DosPutOnTerm(terminal_t *, char); -status_t DosPrintOnTerm(terminal_t *, const char *); -status_t DosChTermColor(terminal_t *, uchar); +void DosInitTerms(void); +status_t DosClearTerm(terminal_t *); +status_t DosPutOnTerm(terminal_t *, char); +status_t DosPrintOnTerm(terminal_t *, const char *); +status_t DosChTermColor(terminal_t *, uchar); -#ifdef _UNLOCKED_IO -void DosPutOnTerm_Unlocked(terminal_t *, char); +#ifdef _UNLOCKED_IO +void DosClearTerm_Unlocked(terminal_t *); +void DosPutOnTerm_Unlocked(terminal_t *, char); +void DosPrintOnTerm_Unlocked(terminal_t *kt, const char *str); +#define DosChTermColor_Unlocked(kt, col) ((kt)->kt_color = col) #endif #ifndef _NO_DEBUG extern terminal_t *stddbg; -# define DebugLog(...) DosPutOnTerm(stddbg, __VA_ARGS__) +# define DebugLog(...) DosPutOnTerm(stddbg, __VA_ARGS__) #else # define DebugLog(...) #endif -#define DosLockTerm(kt) -#define DosTryLockTerm(kt) -#define DosUnlockTerm(kt) +#define DosLockTerm(kt) DosAquireLock(&kt->kt_lock) +#define DosUnlockTerm(kt) DosReleaseLock(&kt->kt_lock) +#define DosTryLockTerm(kt) DosAttemptLock(&kt->kt_lock) #endif diff --git a/src/kaleid/kernel/ke/lock.c b/src/kaleid/kernel/ke/lock.c new file mode 100644 index 0000000..544bf93 --- /dev/null +++ b/src/kaleid/kernel/ke/lock.c @@ -0,0 +1,13 @@ +//----------------------------------------------------------------------------// +// GNU GPL OS/K // +// // +// Authors: spectral` // +// NeoX // +// // +// Desc: Locks // +//----------------------------------------------------------------------------// + +#include + +// nothing to do here + diff --git a/src/kaleid/kernel/ke/lock.h b/src/kaleid/kernel/ke/lock.h new file mode 100644 index 0000000..79202d4 --- /dev/null +++ b/src/kaleid/kernel/ke/lock.h @@ -0,0 +1,96 @@ +//----------------------------------------------------------------------------// +// GNU GPL OS/K // +// // +// Authors: spectral` // +// NeoX // +// // +// Desc: Locks // +//----------------------------------------------------------------------------// + +#ifndef _KALKERN_KE_LOCK_H +#define _KALKERN_KE_LOCK_H + +#ifndef _KALCOMM_COMMON_H +#include +#endif + +enum lock_type { + // + // Mutex-type lock + // WARNING: DosLock() panics when used on a mutex while not running a process + // + KLOCK_MUTEX, + + // + // Spinlock-type lock + // Turns into a Mutex-type lock when MULTIPROCESSOR is off + // + KLOCK_SPINLOCK, + +}; + +typedef struct { + uchar lk_type; // lock type? + uint lk_lock; // is locked? + void *lk_owner; // unused + void *lk_waiting; // unused + uint lk_init; // unused if _NO_DEBUG +} lock_t; + +// +// Initialize a lock +// +#define DosInitLock(lk, type) \ + do { \ + (lk)->lk_type = (type); \ + (lk)->lk_lock = FALSE; \ + (lk)->lk_owner = NULL; \ + (lk)->lk_waiting = NULL; \ + (lk)->lk_init = INITOK; \ + } while (FALSE); + +// +// Alternative way to initalize a lock +// +#define INITLOCK(type) { (type), FALSE, NULL, NULL, INITOK } + +// +// Does nothing +// +#define DosDestroyLock(lk) + +// +// Aquires the lock +// Panics on double aquisition since that should never happen +// until we have at least a basic scheduler +// +#define DosAquireLock(lk) \ + do { \ + DosDisableInterrupts(); \ + DosAssert((lk)->lk_init == INITOK); \ + if ((lk)->lk_lock++) \ + DosPanic("DosAquireLock on an already locked object"); \ + DosEnableInterrupts(); \ + } while (FALSE); + +// +// Releases an already aquired lock +// Panics if the lock was never aquired (this will change) +// +#define DosReleaseLock(lk) \ + do { \ + DosDisableInterrupts(); \ + DosAssert((lk)->lk_init == INITOK); \ + if ((lk)->lk_lock++) \ + DosPanic("DosReleased on an unlocked object"); \ + DosEnableInterrupts(); \ + } while (FALSE); + +// +// Tries to aquire lock +// Doesn't work at all for obvious reasons +// +#define DosAttemptLock(lk) ((lk)->lk_lock++) + +#endif + diff --git a/src/kaleid/kernel/ke/panic.c b/src/kaleid/kernel/ke/panic.c index 028729c..e319fe6 100644 --- a/src/kaleid/kernel/ke/panic.c +++ b/src/kaleid/kernel/ke/panic.c @@ -9,12 +9,14 @@ #include #include + +#define _UNLOCKED_IO #include // // Panic message // -const char *panicstr = NULL; +const char *__panicmsg = NULL; // // Failed assert() handler @@ -39,22 +41,22 @@ void DosPanic(const char *str) DosSetKernState(KSTATE_PANIC); - DosClearTerm(stdout); + DosClearTerm_Unlocked(stdout); if (str == NULL) { str = "(no message given)"; } - if (panicstr) { - // shouldn't be possible - DosPrintOnTerm(stdout, "double panic!\n"); + if (DosGetPanicStr()) { + DosPrintOnTerm_Unlocked(stdout, "double panic!\n"); DosHaltCPU(); } - panicstr = str; + DosSetPanicStr(str); - DosPrintOnTerm(stdout, "panic! - "); - DosPrintOnTerm(stdout, str); + // we cannot lock anything when panicking + DosPrintOnTerm_Unlocked(stdout, "panic! - "); + DosPrintOnTerm_Unlocked(stdout, str); while (TRUE) { DosHaltCPU(); diff --git a/src/kaleid/kernel/ke/panic.h b/src/kaleid/kernel/ke/panic.h index 4b7883a..91cc78e 100644 --- a/src/kaleid/kernel/ke/panic.h +++ b/src/kaleid/kernel/ke/panic.h @@ -12,11 +12,10 @@ #include -extern const char *__panicstr; noreturn void DosPanic(const char *); -#define DosGetPanicStr() (__panicstr) - -#define panic DosPanic +extern const char *__panicmsg; +#define DosGetPanicStr() (__panicmsg) +#define DosSetPanicStr(str) (__panicmsg = (str)) #endif