1
0
mirror of https://gitlab.os-k.eu/os-k-team/os-k.git synced 2023-08-25 14:03:10 +02:00

Buffer stuff: functional printf

This commit is contained in:
Julian Barathieu 2019-03-25 17:33:51 +01:00
parent 5b70dfde0c
commit 93d8a579f8
25 changed files with 795 additions and 358 deletions

View File

@ -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/term.o $(KOBJDIR)/kernel/vga.o \
$(KOBJDIR)/kernel/panic.o $(KOBJDIR)/kernel/map.o \ $(KOBJDIR)/kernel/panic.o $(KOBJDIR)/kernel/map.o \
$(KOBJDIR)/kernel/heap.o $(KOBJDIR)/kernel/malloc.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 $(KOBJDIR)/kernel/cpuid.o: $(KERNELDIR)/kernel/cpu/cpuid.c $(KERNELDIR)/include/*/*.h
@$(KCC) $< -o $@ @$(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 $(KOBJDIR)/kernel/buf.o: $(KERNELDIR)/kernel/buf/buf.c $(KERNELDIR)/include/*/*.h
@$(KCC) $< -o $@ @$(KCC) $< -o $@
@echo ${CL2}[$@] ${CL}Compiled.${CL3} @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 ------------------------------------------------------------- # ## MISC MAKEFILE ------------------------------------------------------------- #
./ProjectTree: ./.stylehlp_sh ./ProjectTree: ./.stylehlp_sh

View File

@ -28,9 +28,9 @@
// Do not change errno // Do not change errno
#define _ATOI_IMPL(_Name, _Type, _Func) \ #define _ATOI_IMPL(_Name, _Type, _Func) \
_Type _Name(const char *str) { \ _Type _Name(const char *str) { \
__get_errno(old); \ error_t old; geterrno(old); \
_Type ret = (_Type)_Func(str, NULL, 0); \ _Type ret = (_Type)_Func(str, NULL, 0); \
__set_errno(old); \ seterrno(old); \
return ret; \ return ret; \
} }

View File

@ -72,7 +72,7 @@ char *ultoa(ulong i, char *str, int base)
// Only handle base 2 -> 36 // Only handle base 2 -> 36
if (base < 2 || base > 36) { if (base < 2 || base > 36) {
__set_errno(EINVAL); seterrno(EINVAL);
*orig = '\0'; *orig = '\0';
goto leave; goto leave;
} }

View File

@ -37,12 +37,18 @@ void *malloc(size_t n)
error_t rc; error_t rc;
rc = KalAllocMemory(&ptr, n, 0, 0); rc = KalAllocMemory(&ptr, n, 0, 0);
__set_errno(rc); if (rc > 0) seterrno(rc);
(void)rc;
return ptr; 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) void free(void *ptr)
{ {
error_t rc = KalFreeMemory(ptr); error_t rc = KalFreeMemory(ptr);
@ -132,7 +138,7 @@ void *memsetd(void *ptr, int val, size_t dwords)
{ {
(void)val; (void)val;
(void)dwords; (void)dwords;
__set_errno(ENOSYS); seterrno(ENOSYS);
return ptr; return ptr;
} }

View File

@ -28,7 +28,7 @@ long strtol(const char *str, char **endp, int base) {
(void)str; (void)str;
(void)endp; (void)endp;
(void)base; (void)base;
__set_errno(ENOSYS); seterrno(ENOSYS);
return 0; return 0;
} }
@ -36,7 +36,7 @@ ulong strtoul(const char *str, char **endp, int base) {
(void)str; (void)str;
(void)endp; (void)endp;
(void)base; (void)base;
__set_errno(ENOSYS); seterrno(ENOSYS);
return 0; return 0;
} }

View File

@ -33,7 +33,7 @@ extern "C" {
#ifndef __error_t_defined #ifndef __error_t_defined
#define __error_t_defined #define __error_t_defined
typedef int error_t; typedef unsigned int error_t;
#endif #endif
#ifndef __size_t_defined #ifndef __size_t_defined
@ -66,14 +66,14 @@ extern error_t __errno;
#define errno __errno #define errno __errno
#endif #endif
#define __get_errno(x) error_t x = errno #define geterrno(x) ((x) = errno)
#define __set_errno(x) (errno = (x)) #define seterrno(x) (errno = (x))
#else #else
#define errno #define errno
#define __get_errno(x) #define geterrno(x) ((void)x)
#define __set_errno(x) #define seterrno(x) ((void)x)
#endif #endif

View File

@ -119,7 +119,7 @@ typedef struct { long quot, rem; } ldiv_t;
#ifndef __error_t_defined #ifndef __error_t_defined
#define __error_t_defined #define __error_t_defined
typedef int error_t; typedef uint error_t;
#endif #endif
#ifndef __port_t_defined #ifndef __port_t_defined

View File

@ -22,10 +22,6 @@
// along with OS/K. If not, see <https://www.gnu.org/licenses/>. // // along with OS/K. If not, see <https://www.gnu.org/licenses/>. //
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
#ifdef _KALEID_KERNEL
#error "extra/list.h - Not ready for kernel compilation"
#endif
#ifndef _KALBASE_H #ifndef _KALBASE_H
#include <kalbase.h> #include <kalbase.h>
#endif #endif
@ -74,7 +70,7 @@ struct ListNode_t
static inline ListHead_t static inline ListHead_t
*ExCreateListHeadWithLock(Lock_t *lock) *ExCreateListHeadWithLock(Lock_t *lock)
{ {
ListHead_t *head = KalAllocMemory(sizeof(ListHead_t)); ListHead_t *head = malloc(sizeof(ListHead_t));
if (head == NULL) return NULL; if (head == NULL) return NULL;
@ -101,7 +97,7 @@ static inline ListHead_t
static inline ListNode_t static inline ListNode_t
*ExCreateNode(void *data) *ExCreateNode(void *data)
{ {
ListNode_t *node = KalAllocMemory(sizeof(ListNode_t)); ListNode_t *node = malloc(sizeof(ListNode_t));
if (node == NULL) return NULL; if (node == NULL) return NULL;
@ -118,7 +114,7 @@ static inline ListNode_t
static inline ListHead_t static inline ListHead_t
*ExPrependNode(ListHead_t *head, ListNode_t *node) *ExPrependNode(ListHead_t *head, ListNode_t *node)
{ {
KalAssert(head && node); assert(head && node);
node->head = head; node->head = head;
node->prev = NULL; node->prev = NULL;
@ -146,7 +142,7 @@ static inline ListHead_t
static inline ListHead_t static inline ListHead_t
*ExAppendNode(ListHead_t *head, ListNode_t *node) *ExAppendNode(ListHead_t *head, ListNode_t *node)
{ {
KalAssert(head && node); assert(head && node);
node->head = head; node->head = head;
node->next = NULL; node->next = NULL;
@ -174,7 +170,7 @@ static inline ListHead_t
static inline ListHead_t static inline ListHead_t
*ExAddNodeBefore(ListHead_t *head, ListNode_t *node1, ListNode_t *node2) *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) { if (head->first == node1) {
return ExPrependNode(head, node2); return ExPrependNode(head, node2);
@ -200,7 +196,7 @@ static inline ListHead_t
static inline ListHead_t static inline ListHead_t
*ExAddNodeAfter(ListHead_t *head, ListNode_t *node1, ListNode_t *node2) *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) { if (head->last == node1) {
return ExAppendNode(head, node2); return ExAppendNode(head, node2);
@ -224,7 +220,7 @@ static inline ListHead_t
static inline ListHead_t static inline ListHead_t
*ExRemoveNode(ListHead_t *head, ListNode_t *node) *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) { if (head->length == 1) {
head->first = head->last = NULL; head->first = head->last = NULL;
@ -259,8 +255,8 @@ leave:
static inline void static inline void
ExDestroyNode(ListNode_t *node) ExDestroyNode(ListNode_t *node)
{ {
KalAssert(node); assert(node);
KalFreeMemory(node); free(node);
} }
// //
@ -269,8 +265,8 @@ ExDestroyNode(ListNode_t *node)
static inline void static inline void
ExDestroyListHead(ListHead_t *head) ExDestroyListHead(ListHead_t *head)
{ {
KalAssert(head); assert(head);
KalFreeMemory(head); free(head);
} }
// //

View File

@ -32,6 +32,10 @@
#include <kernel/panic.h> #include <kernel/panic.h>
#endif #endif
#ifndef _KALKERN_SCHED_H
#include <kernel/sched.h>
#endif
#endif #endif
#ifndef _KALEXTRAS_LOCKS_H #ifndef _KALEXTRAS_LOCKS_H
@ -62,8 +66,8 @@ enum LockType_t
struct Lock_t struct Lock_t
{ {
unsigned int initDone; unsigned int initDone;
LockType_t type;
volatile int locked; volatile int locked;
LockType_t type;
/* #ifdef _KALEID_KERNEL /* #ifdef _KALEID_KERNEL
Thread_t *ownerThread; // unused Thread_t *ownerThread; // unused
@ -83,8 +87,8 @@ int KalYieldCPU(void),
static inline static inline
void ExInitLock(Lock_t *lock, LockType_t type) void ExInitLock(Lock_t *lock, LockType_t type)
{ {
lock->locked = 0;
lock->type = type; lock->type = type;
lock->locked = FALSE;
lock->initDone = INITOK; lock->initDone = INITOK;
/* #ifdef _KALEID_KERNEL /* #ifdef _KALEID_KERNEL
lock->ownerThread = NULL; lock->ownerThread = NULL;
@ -96,9 +100,9 @@ void ExInitLock(Lock_t *lock, LockType_t type)
// Alternative way to initalize a lock // Alternative way to initalize a lock
// //
#ifdef _KALEID_KERNEL #ifdef _KALEID_KERNEL
# define ExINITLOCK(type) { INITOK, FALSE, (type), /* NULL, NULL */ } # define ExINITLOCK(type) { INITOK, 0, (type), /* NULL, NULL */ }
#else #else
# define ExINITLOCK(type) { INITOK, FALSE, (type) } # define ExINITLOCK(type) { INITOK, 0, (type) }
#endif #endif
// //
@ -119,18 +123,29 @@ void ExDestroyLock(Lock_t *lock)
// until we have at least a basic scheduler // until we have at least a basic scheduler
// //
static inline 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) void ExAcquireLock(Lock_t *lock)
#endif
{ {
KalAssert(lock->initDone == INITOK); KalAssert(lock->initDone == INITOK);
while (!__sync_bool_compare_and_swap(&lock->locked, 0, 1)) { while (!__sync_bool_compare_and_swap(&lock->locked, 0, 1)) {
#ifdef _KALEID_KERNEL #if defined(_KALEID_KERNEL) && !defined(_NO_DEBUG)
KeStartPanic("AcquireLock on an already locked object"); KeStartPanic(
#else "In function '%s', from '%s' line %d\n"
if likely (lock->type == KLOCK_SPINLOCK) continue; "Double ExAcquireLock on object: '%s'",
else (void)KalYieldCPU(); func, file, line, obj);
#endif #endif
/*if likely (lock->type == KLOCK_SPINLOCK)*/
continue;
//else (void)KalYieldCPU();
} }
PsDisablePreemption();
__sync_synchronize(); __sync_synchronize();
} }
@ -146,7 +161,9 @@ void ExReleaseLock(Lock_t *lock)
#endif*/ #endif*/
__sync_synchronize(); __sync_synchronize();
lock->locked = 0; lock->locked = 0;
PsEnablePreemption();
} }
// //

View File

@ -56,13 +56,12 @@ typedef enum TermColor_t TermColor_t;
#endif #endif
// Current CPU number // Current CPU number
// Will return a CPU-local variable later #define _KeCurCPU 0
#define _KeGetCurCPU() 0
// Get Process_t structure of current CPU // Process_t structure of current CPU
#define KeGetCurCPU() (cpuTable[_KeGetCurCPU()]) #define KeCurCPU (cpuTable[_KeCurCPU])
//Get the BootInfo_t structure // Access the BootInfo_t structure
#define BtGetBootInfo(x) (bootTab.x) #define BtGetBootInfo(x) (bootTab.x)
//------------------------------------------// //------------------------------------------//

View File

@ -69,9 +69,9 @@ struct Buffer_t
size_t size; // Current size size_t size; // Current size
char *buf; // Beginning of buffer uchar *buf; // Beginning of buffer
char *rp; // Read pointer uchar *rp; // Read pointer
char *wp; // Write pointer uchar *wp; // Write pointer
BFlusher_t flusher; // Called for flushing BFlusher_t flusher; // Called for flushing
@ -107,7 +107,7 @@ bool BTrylockBuf(Buffer_t *buf);
error_t BFlushBuf(Buffer_t *buf); error_t BFlushBuf(Buffer_t *buf);
error_t BPutOnBuf(Buffer_t *buf, uchar ch); error_t BPutOnBuf(Buffer_t *buf, uchar ch);
error_t BPrintOnBuf(Buffer_t *buf, size_t n, const char *fmt, ...); error_t BPrintOnBuf(Buffer_t *buf, const char *fmt, ...);
error_t BPrintOnBufV(Buffer_t *buf, size_t n, const char *fmt, va_list ap); error_t BPrintOnBufV(Buffer_t *buf, const char *fmt, va_list ap);
#endif #endif

View File

@ -31,7 +31,7 @@
//------------------------------------------// //------------------------------------------//
#define _HEAP_START (4 * MB) #define _HEAP_START (8 * MB)
void MmInitHeap(void); void MmInitHeap(void);

View File

@ -44,7 +44,7 @@ struct MapEntry_t {
void *addr; void *addr;
size_t length; // in bytes size_t length; // in bytes
uint type; // reserved or not uint type; // reserved or not
} __attribute__((packed)); } __attribute__((__packed__));
// the map structure // the map structure
struct MemoryMap_t { struct MemoryMap_t {
@ -52,7 +52,7 @@ struct MemoryMap_t {
size_t freeRamSize; size_t freeRamSize;
size_t nonfreeRamSize; size_t nonfreeRamSize;
MapEntry_t entry[MAX_ENTRIES]; MapEntry_t entry[MAX_ENTRIES];
} __attribute__((packed)); } __attribute__((__packed__));
@ -64,7 +64,8 @@ struct MemoryMap_t {
error_t MmInitMemoryMap(void); 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); size_t MmGetAvailZoneSize(void *start);

View File

@ -96,7 +96,7 @@
typedef unsigned char uchar; typedef unsigned char uchar;
typedef unsigned short ushort; typedef unsigned short ushort;
typedef unsigned int uint; typedef unsigned int uint;
typedef unsigned long long ullong; typedef unsigned long ulong;
struct multiboot_header struct multiboot_header
{ {
@ -141,7 +141,8 @@ struct multiboot_elf_section_header_table
uint addr; uint addr;
uint shndx; 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 struct multiboot_info
{ {
@ -193,7 +194,7 @@ struct multiboot_info
ushort vbe_interface_off; ushort vbe_interface_off;
ushort vbe_interface_len; ushort vbe_interface_len;
ullong framebuffer_addr; ulong framebuffer_addr;
uint framebuffer_pitch; uint framebuffer_pitch;
uint framebuffer_width; uint framebuffer_width;
uint framebuffer_height; uint framebuffer_height;

View File

@ -77,8 +77,11 @@ struct Process_t
//------------------------------------------// //------------------------------------------//
DEC_PER_CPU(Ps, CurProc, process, Process_t *); #define PsCurProc (KeCurCPU.process)
DEC_PER_CPU(Ps, CurThread, thread, Thread_t *); #define PsCurThread (KeCurCPU.thread)
//DEC_PER_CPU(Ps, CurProc, process, Process_t *);
//DEC_PER_CPU(Ps, CurThread, thread, Thread_t *);
//------------------------------------------// //------------------------------------------//

View File

@ -39,7 +39,7 @@ enum { PREEMPT_ON = 0 };
// Time in ticks a process should be run // Time in ticks a process should be run
enum enum
{ {
DEF_PROC_TSLICE = 5, // 20 ticks DEF_PROC_TSLICE = 3, // 20 ticks
TCR_PROC_TSLICE = 20000 // 20000 ticks (time critical) 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 // Re-scheduling and preemption
// XXX atomic operations // XXX atomic operations
// //
#define PsSetReSchedFlag(x) _PsSetReSchedFlag(x) #define PsRequestReSched() (++KeCurCPU.needReSched)
#define PsDisablePreemption() _PsSetPreemptCount(GetPreemptCount()+1) #define PsDisablePreemption() (++KeCurCPU.preemptCount)
#define PsEnablePreemption() do { KalAssert(GetPreemptCount() > 0); \ #define PsEnablePreemption() do { assert(KeCurCPU.preemptCount > 0); \
_PsSetPreemptCount(GetPreemptCount()-1); } while(0) --KeCurCPU.preemptCount; } while(0)
//------------------------------------------// //------------------------------------------//

373
kaleid/kernel/buf/bprint.c Normal file
View File

@ -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 <https://www.gnu.org/licenses/>. //
//----------------------------------------------------------------------------//
#include <kernel/buf.h>
#include <kernel/term.h> //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;
}

141
kaleid/kernel/buf/bput.c Normal file
View File

@ -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 <https://www.gnu.org/licenses/>. //
//----------------------------------------------------------------------------//
#include <kernel/buf.h>
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;
}
}

View File

@ -47,9 +47,7 @@ void BFlushOnClose(Buffer_t *buf) { buf->flags |= BF_FONCLOSE; }
// //
error_t BCloseBuf(Buffer_t *buf) error_t BCloseBuf(Buffer_t *buf)
{ {
if (!buf) return EINVAL; assert(buf && buf->initDone == INITOK);
assert(buf->initDone == INITOK);
ExAcquireLock(&buf->lock); ExAcquireLock(&buf->lock);
if (buf->flags & BF_FONCLOSE) { if (buf->flags & BF_FONCLOSE) {
@ -109,9 +107,9 @@ Buffer_t *BOpenLineBuf(char *source, int mode,
buf->size = lineLen * nLines * (pbCount + 1); buf->size = lineLen * nLines * (pbCount + 1);
if (source == NULL) { if (source == NULL) {
buf->buf = malloc(buf->size); buf->buf = calloc(buf->size, 1);
} else { } else {
buf->buf = source; buf->buf = (uchar *)source;
} }
buf->wp = buf->rp = buf->buf; buf->wp = buf->rp = buf->buf;
@ -143,121 +141,4 @@ error_t BFlushBuf(Buffer_t *buf)
return rc; 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);

View File

@ -24,7 +24,10 @@
#include <kernel/multiboot.h> #include <kernel/multiboot.h>
#include <kernel/panic.h> #include <kernel/panic.h>
#include <kernel/sched.h>
#include <kernel/term.h> #include <kernel/term.h>
#include <kernel/heap.h>
#include <kernel/buf.h>
#include <kernel/mm.h> #include <kernel/mm.h>
// //
@ -33,8 +36,8 @@
// //
void BtInitBootInfo(multiboot_info_t *mbi) void BtInitBootInfo(multiboot_info_t *mbi)
{ {
extern ullong MB_header; extern ulong MB_header;
extern ullong kernelEnd; extern ulong kernelEnd;
// We need the multiboot structure // We need the multiboot structure
KalAlwaysAssert(mbi); KalAlwaysAssert(mbi);
@ -43,19 +46,19 @@ void BtInitBootInfo(multiboot_info_t *mbi)
BtGetBootInfo(btldr).grubFlags = mbi->flags; BtGetBootInfo(btldr).grubFlags = mbi->flags;
if (BtGetBootInfo(btldr).grubFlags & MULTIBOOT_INFO_BOOT_LOADER_NAME) { 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).kernelAddr = (void*)&MB_header;
BtGetBootInfo(btldr).kernelEndAddr = (void*)&kernelEnd; BtGetBootInfo(btldr).kernelEndAddr = (void*)&kernelEnd;
BtGetBootInfo(btldr).valid = 1; BtGetBootInfo(btldr).valid = 1;
} }
if (BtGetBootInfo(btldr).grubFlags & MULTIBOOT_INFO_MODS) { if (BtGetBootInfo(btldr).grubFlags & MULTIBOOT_INFO_MODS) {
BtGetBootInfo(btldr).modulesCount = mbi->mods_count; 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 //Retrieves the drives informations
if (BtGetBootInfo(btldr).grubFlags & MULTIBOOT_INFO_DRIVE_INFO) { if (BtGetBootInfo(btldr).grubFlags & MULTIBOOT_INFO_DRIVE_INFO) {
BtGetBootInfo(drives).bufferLength = mbi->drives_length; 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; BtGetBootInfo(drives).bufferValid = 1;
} }
if (BtGetBootInfo(btldr).grubFlags & MULTIBOOT_INFO_BOOTDEV) { if (BtGetBootInfo(btldr).grubFlags & MULTIBOOT_INFO_BOOTDEV) {
@ -70,15 +73,15 @@ void BtInitBootInfo(multiboot_info_t *mbi)
BtGetBootInfo(memory).memValid = 1; BtGetBootInfo(memory).memValid = 1;
} }
if (BtGetBootInfo(btldr).grubFlags & MULTIBOOT_INFO_MEM_MAP) { 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).mapLength = mbi->mmap_length;
BtGetBootInfo(memory).mapValid = 1; BtGetBootInfo(memory).mapValid = 1;
} }
// Retrieves video mode informations // Retrieves video mode informations
if (BtGetBootInfo(btldr).grubFlags & MULTIBOOT_INFO_VBE_INFO) { if (BtGetBootInfo(btldr).grubFlags & MULTIBOOT_INFO_VBE_INFO) {
BtGetBootInfo(video).vbeControl = (void*)(ullong)mbi->vbe_control_info; BtGetBootInfo(video).vbeControl = (void*)(ulong)mbi->vbe_control_info;
BtGetBootInfo(video).vbeModeInfo = (void*)(ullong)mbi->vbe_mode_info; BtGetBootInfo(video).vbeModeInfo = (void*)(ulong)mbi->vbe_mode_info;
BtGetBootInfo(video).vbeMode = mbi->vbe_mode; BtGetBootInfo(video).vbeMode = mbi->vbe_mode;
BtGetBootInfo(video).vbeInterfaceSeg = mbi->vbe_interface_seg; BtGetBootInfo(video).vbeInterfaceSeg = mbi->vbe_interface_seg;
BtGetBootInfo(video).vbeInterfaceOff = mbi->vbe_interface_off; BtGetBootInfo(video).vbeInterfaceOff = mbi->vbe_interface_off;
@ -86,7 +89,7 @@ void BtInitBootInfo(multiboot_info_t *mbi)
BtGetBootInfo(video).vbeValid = 1; BtGetBootInfo(video).vbeValid = 1;
} }
if (BtGetBootInfo(btldr).grubFlags & MULTIBOOT_INFO_FRAMEBUFFER_INFO) { 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).framebufferPitch = mbi->framebuffer_pitch;
BtGetBootInfo(video).framebufferWidth = mbi->framebuffer_width; BtGetBootInfo(video).framebufferWidth = mbi->framebuffer_width;
BtGetBootInfo(video).framebufferHeight= mbi->framebuffer_height; 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 // Entry point of the Kaleid kernel
@ -138,12 +142,27 @@ noreturn void BtStartKern(multiboot_info_t *mbInfo, int mbMagic)
mapBad mapBad
); );
KernLog("[Init] TEST First zone from %p : %p\n", (void*)0xB8010, MmGetFirstAvailZone((void*)0xB8010)); KernLog("[Init] TEST First zone from %p : %p\n", (void*)0xB8010,
KernLog("[Init] TEST Size of zone : %u Kio\n\n", MmGetAvailZoneSize(MmGetFirstAvailZone((void*)0xB8010)) / KB); 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 // We're out
KernLog("\n[Init] Evil never dies !\n"); PsFiniSched();
KeCrashSystem(); //yay KeCrashSystem(); //yay
} }

View File

@ -35,10 +35,8 @@ noreturn void __assert_handler(const char *msg,
{ {
KeDisableIRQs(); KeDisableIRQs();
(void)file; (void)line; (void)func; KeStartPanic("In function '%s', from '%s' line %d\nAssertion failed:\n"
"'%s'", func, file, line, msg);
KeStartPanic("In function '%s', from %s line %d - assertion failed: '%s'",
func, file, line, msg);
} }
// //
@ -51,7 +49,7 @@ noreturn void KeStartPanic(const char *fmt, ...)
KeDisableIRQs(); KeDisableIRQs();
if (PsGetCurProc()) _PsSetCurProc(NULL); PsCurProc = NULL;
if (StdOut == NULL) KeCrashSystem(); if (StdOut == NULL) KeCrashSystem();
if (fmt == NULL) { if (fmt == NULL) {

View File

@ -34,7 +34,6 @@ static size_t _heap_max;
// Lock NOT used internally, but used by KalAllocMemory() & co. // Lock NOT used internally, but used by KalAllocMemory() & co.
static Lock_t _heap_lock = ExINITLOCK(KLOCK_SPINLOCK); static Lock_t _heap_lock = ExINITLOCK(KLOCK_SPINLOCK);
// //
// Initializes heap managment // Initializes heap managment
// //
@ -100,7 +99,7 @@ error_t MmSetMaxHeapSize(size_t new)
// //
error_t MmGrowHeap(size_t req) 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) { if ((size_t)_heap_end + req > _HEAP_START + _heap_max) {
return ENOMEM; return ENOMEM;
@ -116,7 +115,7 @@ error_t MmGrowHeap(size_t req)
// //
error_t MmShrinkHeap(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) { if (req > (size_t)_heap_end - _HEAP_START) {
return EADDRINUSE; return EADDRINUSE;

View File

@ -57,6 +57,7 @@ error_t KalAllocMemory(void **ptr, size_t req, int flags, size_t align)
*ptr = (void *)brk; *ptr = (void *)brk;
assert(*ptr);
return rc; return rc;
} }

View File

@ -52,22 +52,22 @@ error_t MmInitMemoryMap(void)
currentEntry = (multiboot_memory_map_t*)BtGetBootInfo(memory).mapAddr; currentEntry = (multiboot_memory_map_t*)BtGetBootInfo(memory).mapAddr;
// End address of the map // End address of the map
mapEnd = (multiboot_memory_map_t*) mapEnd = (multiboot_memory_map_t*)
((ullong)currentEntry + (ullong)BtGetBootInfo(memory).mapLength); ((ulong)currentEntry + (ulong)BtGetBootInfo(memory).mapLength);
// fill the map // fill the map
while (currentEntry < mapEnd) { while (currentEntry < mapEnd) {
// memory zone address // memory zone address
memoryMap.entry[i].addr = (void*)( (ullong)currentEntry->addr_low + memoryMap.entry[i].addr = (void*)((ulong)currentEntry->addr_low +
(((ullong)currentEntry->addr_high) << 32 )); (((ulong)currentEntry->addr_high) << 32 ));
// memory zone size in bytes // memory zone size in bytes
memoryMap.entry[i].length = (ullong)currentEntry->len_low + memoryMap.entry[i].length = (ulong)currentEntry->len_low +
(((ullong)currentEntry->len_high) << 32); (((ulong)currentEntry->len_high) << 32);
// memory availability // memory availability
memoryMap.entry[i].type = (uint)currentEntry->type; memoryMap.entry[i].type = (uint)currentEntry->type;
// Adding the size to the size (yup) // Adding the size to the size (yup)
memoryMap.length++; memoryMap.length++;
// moving up ! // moving up !
currentEntry = (multiboot_memory_map_t*) ((ullong)currentEntry + currentEntry = (multiboot_memory_map_t*) ((ulong)currentEntry +
currentEntry->size + sizeof(currentEntry->size)); currentEntry->size + sizeof(currentEntry->size));
i++; i++;
} }
@ -108,11 +108,11 @@ size_t MmGetAvailZoneSize(void *start) {
// if the address is in an available zone, we can return the length // if the address is in an available zone, we can return the length
if ( if (
memoryMap.entry[i].type == AVAILABLE_ZONE && memoryMap.entry[i].type == AVAILABLE_ZONE &&
(ullong)start >= (ullong)memoryMap.entry[i].addr && (ulong)start >= (ulong)memoryMap.entry[i].addr &&
(ullong)start < ((ullong)memoryMap.entry[i].addr + (ulong)start < ((ulong)memoryMap.entry[i].addr +
(ullong)memoryMap.entry[i].length) (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; void *current = 0;
// Because the kernel is the kernel // 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); 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 the address is in an available zone, we can return the start address
if ( if (
memoryMap.entry[i].type == AVAILABLE_ZONE && memoryMap.entry[i].type == AVAILABLE_ZONE &&
(ullong)start >= (ullong)memoryMap.entry[i].addr && (ulong)start >= (ulong)memoryMap.entry[i].addr &&
(ullong)start < ((ullong)memoryMap.entry[i].addr + (ulong)start < ((ulong)memoryMap.entry[i].addr +
(ullong)memoryMap.entry[i].length) (ulong)memoryMap.entry[i].length)
) { ) {
current = start; current = start;
break; break;
@ -151,7 +151,7 @@ void *MmGetFirstAvailZone(void *start) {
// Return the first zone that is after start // Return the first zone that is after start
if ( if (
memoryMap.entry[i].type == AVAILABLE_ZONE && 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; current = memoryMap.entry[i].addr;
break; break;

View File

@ -25,10 +25,7 @@
#include <extras/list.h> #include <extras/list.h>
#include <kernel/proc.h> #include <kernel/proc.h>
#include <kernel/sched.h> #include <kernel/sched.h>
#include <kernel/term.h>
#ifndef _KALEID_KERNEL
#include <stdio.h>
// //
// For test purpose only // 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 }, { 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 // Set current process
// TODO Select thread, context switch
// //
static void SetCurProc(Process_t *proc) static void SetCurProc(Process_t *proc)
{ {
_SetCurProc(proc); PsCurProc = proc;
if (GetCurProc() != NULL) { if (PsCurProc) PsCurProc->procState = STATE_RUNNING;
GetCurProc()->procState = STATE_RUNNING;
}
} }
// //
@ -66,28 +70,24 @@ static void SetCurProc(Process_t *proc)
// //
static inline static inline
void SchedLock(void) { void PsLockSched(void) {
#ifdef _KALEID_KERNEL KeDisableIRQs();
DisableIRQs();
#endif
} }
static inline static inline
void SchedUnlock(void) { void PsUnlockSched(void) {
#ifdef _KALEID_KERNEL //KeEnableIRQs();
EnableIRQs();
#endif
} }
// //
// The four priority classes of OS/2 // 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(ServPrioProcs, ListHead_t *);
CREATE_PER_CPU(ReglPrioProcs, 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", "Time-critical class",
"Server priority class", "Server priority class",
"Regular priority class", "Regular priority class",
@ -100,10 +100,10 @@ const char *PrioClassesNames[] = {
static ListHead_t *GetPrioClassHead(int prioClass) static ListHead_t *GetPrioClassHead(int prioClass)
{ {
switch (prioClass) { switch (prioClass) {
case TIME_CRIT_PROC: return GetTimeCritProcs(); case TIME_CRIT_PROC: return TimeCritProcs;
case SERV_PRIO_PROC: return GetServPrioProcs(); case SERV_PRIO_PROC: return ServPrioProcs;
case REGL_PRIO_PROC: return GetReglPrioProcs(); case REGL_PRIO_PROC: return ReglPrioProcs;
case IDLE_PRIO_PROC: return GetIdlePrioProcs(); case IDLE_PRIO_PROC: return IdlePrioProcs;
default: KalAssert(FALSE && "Unknown priority class"); default: KalAssert(FALSE && "Unknown priority class");
} }
@ -134,23 +134,24 @@ static void SchedThisProcUnlocked(Process_t *proc)
{ {
KalAssert(proc && proc->procState == STATE_RUNNABLE && !proc->schedNode); KalAssert(proc && proc->procState == STATE_RUNNABLE && !proc->schedNode);
bool found = false; bool found = 0;
ListNode_t *iterNode = NULL; ListNode_t *iterNode = NULL;
ListNode_t *procNode = CreateNode(proc); ListNode_t *procNode = ExCreateNode(proc);
ListHead_t *head = GetPrioClassHead(proc->prioClass); ListHead_t *head = GetPrioClassHead(proc->prioClass);
KalAssert(procNode && head); KalAssert(head);
KalAssert(procNode);
proc->schedNode = procNode; proc->schedNode = procNode;
// Find a process with lesser priority // Find a process with lesser priority
for (iterNode = head->first; iterNode; iterNode = iterNode->next) { 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 // Detect double insertions
KalAssert(proc->pid != GetNodeData(iterNode, Process_t *)->pid); KalAssert(proc->pid != ExGetNodeData(iterNode, Process_t *)->pid);
// Add process to schedule // Add process to schedule
AddNodeBefore(head, iterNode, procNode); ExAddNodeBefore(head, iterNode, procNode);
found = true; found = true;
break; break;
} }
@ -158,20 +159,20 @@ static void SchedThisProcUnlocked(Process_t *proc)
// Didn't find any process with lesser priority // Didn't find any process with lesser priority
if (found == false) { if (found == false) {
AppendNode(head, procNode); ExAppendNode(head, procNode);
} }
} }
// //
// Add process to schedule lists // Add process to schedule lists
// //
void SchedThisProc(Process_t *proc) void PsSchedThisProc(Process_t *proc)
{ {
SchedLock(); PsLockSched();
SchedThisProcUnlocked(proc); SchedThisProcUnlocked(proc);
SchedUnlock(); PsUnlockSched();
} }
// //
@ -182,10 +183,17 @@ void SchedThisProc(Process_t *proc)
// //
static Process_t *SelectSchedNext(void) static Process_t *SelectSchedNext(void)
{ {
if (GetTimeCritProcs()->length > 0) return GetNodeData(GetTimeCritProcs()->first, Process_t *); if (TimeCritProcs->length > 0)
if (GetServPrioProcs()->length > 0) return GetNodeData(GetServPrioProcs()->first, Process_t *); return ExGetNodeData(TimeCritProcs->first, Process_t *);
if (GetReglPrioProcs()->length > 0) return GetNodeData(GetReglPrioProcs()->first, Process_t *);
if (GetIdlePrioProcs()->length > 0) return GetNodeData(GetIdlePrioProcs()->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; return NULL;
} }
@ -194,82 +202,82 @@ static Process_t *SelectSchedNext(void)
// Remove running process from schedule lists // Remove running process from schedule lists
// and schedule next runnable process // 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"); KalAssert(procNode && "Blocking non-scheduled process");
GetCurProc()->procState = STATE_BLOCKED; PsCurProc->procState = STATE_BLOCKED;
RemoveNode(procNode->head, procNode); ExRemoveNode(procNode->head, procNode);
GetCurProc()->schedNode = NULL; PsCurProc->schedNode = NULL;
SetCurProc(SelectSchedNext()); SetCurProc(SelectSchedNext());
} }
static void ReSchedCurProc(void) static void ReSchedCurProc(void)
{ {
KalAssert(GetCurProc() && GetCurProc()->procState == STATE_RUNNING); KalAssert(PsCurProc && PsCurProc->procState == STATE_RUNNING);
KalAssert(GetCurProc()->schedNode); KalAssert(PsCurProc->schedNode);
// Restore default attributes, cancelling boosts // Restore default attributes, cancelling boosts
GetCurProc()->prioClass = GetCurProc()->defPrioClass; PsCurProc->prioClass = PsCurProc->defPrioClass;
GetCurProc()->prioLevel = GetCurProc()->defPrioLevel; PsCurProc->prioLevel = PsCurProc->defPrioLevel;
GetCurProc()->timeSlice = GetCurProc()->defTimeSlice; PsCurProc->timeSlice = PsCurProc->defTimeSlice;
GetCurProc()->procState = STATE_RUNNABLE; PsCurProc->procState = STATE_RUNNABLE;
// Remove from list // Remove from list
RemoveNode(GetCurProc()->schedNode->head, GetCurProc()->schedNode); ExRemoveNode(PsCurProc->schedNode->head, PsCurProc->schedNode);
GetCurProc()->schedNode = NULL; PsCurProc->schedNode = NULL;
// Schedule again, with default attributes now // Schedule again, with default attributes now
SchedThisProcUnlocked(GetCurProc()); SchedThisProcUnlocked(PsCurProc);
} }
// //
// Should we schedule another process? // Should we schedule another process?
// Called at each tick // 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 // 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? // Have the current process spent its timeslice?
// (To be handled in CPU decisions function) // (To be handled in CPU decisions function)
if (GetCurProc() != NULL) { if (PsCurProc != NULL) {
if (GetCurProc()->timeSlice <= 1) { if (PsCurProc->timeSlice <= 1) {
// Re-schedule // Re-schedule
ReSchedCurProc(); ReSchedCurProc();
// See next 'if' statement // See next 'if' statement
_SetCurProc(NULL); PsCurProc = NULL;
} }
// Otherwise, make it lose a tick // Otherwise, make it lose a tick
else { else {
GetCurProc()->timeSlice--; PsCurProc->timeSlice--;
} }
} }
// Are we idle, or scheduling next process? // Are we idle, or scheduling next process?
if (GetCurProc() == NULL) { if (PsCurProc == NULL) {
SetCurProc(SelectSchedNext()); SetCurProc(SelectSchedNext());
goto leave; goto leave;
} }
// Is preemption on and a re-schedule is needed? // 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? // Is there a higher priority process that is runnable?
procNext = SelectSchedNext(); procNext = SelectSchedNext();
winner = CompareProcs(GetCurProc(), procNext); winner = CompareProcs(PsCurProc, procNext);
// Yes, procNext should preempt current process // Yes, procNext should preempt current process
if (winner == procNext) { if (winner == procNext) {
@ -283,9 +291,9 @@ void SchedOnTick(void)
// Current process won't be preempted and has time remaining // Current process won't be preempted and has time remaining
leave: leave:
SchedUnlock(); PsUnlockSched();
if (GetCurProc() != NULL && GetCurProc() != previous) { if (PsCurProc != NULL && PsCurProc != previous) {
// XXX context switch // XXX context switch
} }
} }
@ -293,55 +301,59 @@ leave:
// //
// Initialize scheduler // Initialize scheduler
// //
void InitSched(void) void PsInitSched(void)
{ {
int pid; int pid;
SchedLock(); PsLockSched();
_SetTimeCritProcs(CreateListHead()); TimeCritProcs = ExCreateListHead();
_SetServPrioProcs(CreateListHead()); ServPrioProcs = ExCreateListHead();
_SetReglPrioProcs(CreateListHead()); ReglPrioProcs = ExCreateListHead();
_SetIdlePrioProcs(CreateListHead()); IdlePrioProcs = ExCreateListHead();
KalAssert(IdlePrioProcs && ReglPrioProcs && ServPrioProcs && TimeCritProcs);
#ifndef _KALEID_KERNEL
for (pid = 0; pid < procslen; pid++) { for (pid = 0; pid < procslen; pid++) {
if (procs[pid].procState == STATE_RUNNABLE) { if (procs[pid].procState == STATE_RUNNABLE) {
SchedThisProcUnlocked(&procs[pid]); SchedThisProcUnlocked(&procs[pid]);
} }
} }
#endif
SchedUnlock(); PsUnlockSched();
} }
// //
// Shutdown scheduler // 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 (IdlePrioProcs->length > 0)
while (GetReglPrioProcs()->length > 0) RemoveNode(GetReglPrioProcs(), GetReglPrioProcs()->first); ExRemoveNode(IdlePrioProcs, IdlePrioProcs->first);
while (GetServPrioProcs()->length > 0) RemoveNode(GetServPrioProcs(), GetServPrioProcs()->first);
while (GetTimeCritProcs()->length > 0) RemoveNode(GetTimeCritProcs(), GetTimeCritProcs()->first);
DestroyListHead(GetIdlePrioProcs()); _SetIdlePrioProcs(NULL); while (ReglPrioProcs->length > 0)
DestroyListHead(GetReglPrioProcs()); _SetReglPrioProcs(NULL); ExRemoveNode(ReglPrioProcs, ReglPrioProcs->first);
DestroyListHead(GetServPrioProcs()); _SetServPrioProcs(NULL);
DestroyListHead(GetTimeCritProcs()); _SetTimeCritProcs(NULL);
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) KernLog("{ %d, '%s', %d , %lu}\n", (proc)->pid, \
PsPrioClassesNames[(proc)->prioClass], (proc)->prioLevel, (proc)->timeSlice);
#define PrintProc(proc) printf("{ %d, '%s', %d , %lu}\n", (proc)->pid, \
PrioClassesNames[(proc)->prioClass], (proc)->prioLevel, (proc)->timeSlice);
// //
// Print out process list // Print out process list
// //
@ -352,75 +364,65 @@ void PrintList(ListHead_t *head)
Process_t *proc; Process_t *proc;
ListNode_t *node = head->first; ListNode_t *node = head->first;
printf("len: %lu\n", head->length); KernLog("len: %lu\n", head->length);
while (node) { while (node) {
proc = GetNodeData(node, Process_t *); proc = ExGetNodeData(node, Process_t *);
PrintProc(proc); PrintProc(proc);
node = node->next; node = node->next;
} }
puts(""); KernLog("");
} }
int main(void) void pstest(void)
{ {
InitSched(); ClearTerm(StdOut);
puts("---------------"); KernLog("\nTime Critical: ");
PrintList(TimeCritProcs);
puts("Time Critical:"); KernLog("\nServer: ");
PrintList(GetTimeCritProcs()); PrintList(ServPrioProcs);
puts("Server:"); KernLog("\nRegular: ");
PrintList(GetServPrioProcs()); PrintList(ReglPrioProcs);
puts("Regular:"); KernLog("\nIdle:");
PrintList(GetReglPrioProcs()); PrintList(IdlePrioProcs);
puts("Idle:");
PrintList(GetIdlePrioProcs());
puts("---------------");
getchar();
int tick = 0; int tick = 0;
while (tick < 120) { while (tick < 24) {
if (tick%25==0)ClearTerm(StdOut);
if (tick > 0 && tick != 50 && tick % 10 == 0) { if (tick > 0 && tick != 50 && tick % 10 == 0) {
puts("Blocking current process"); KernLog("Blocking current process\n");
BlockCurProc(); PsBlockCurProc();
} }
if (tick == 50) { if (tick == 50) {
procs[0].procState = STATE_RUNNABLE; procs[0].procState = STATE_RUNNABLE;
SchedThisProc(&procs[0]); PsSchedThisProc(&procs[0]);
} }
printf("Tick %d - Running: ", tick); KernLog("Tick %d - Running: ", tick);
if (GetCurProc() == NULL) { if (PsCurProc == NULL) {
puts("IDLE"); KernLog("IDLE");
} }
else { else {
PrintProc(GetCurProc()); PrintProc(PsCurProc);
} }
SchedOnTick(); PsSchedOnTick();
if (tick == 50) // already done if (tick == 50) // already done
puts("Re-scheduling process 0"); KernLog("Re-scheduling process 0");
tick++; tick++;
} }
FiniSched();
return 0;
} }
#endif