commit
e8b64a1fa2
13
Makefile
13
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/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,16 @@ $(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
|
||||||
|
|
13
ProjectTree
13
ProjectTree
|
@ -56,6 +56,8 @@
|
||||||
│ │ │ └── loader.o
|
│ │ │ └── loader.o
|
||||||
│ │ └── kaleid
|
│ │ └── kaleid
|
||||||
│ │ ├── kernel
|
│ │ ├── kernel
|
||||||
|
│ │ │ ├── bprint.o
|
||||||
|
│ │ │ ├── bput.o
|
||||||
│ │ │ ├── buf.o
|
│ │ │ ├── buf.o
|
||||||
│ │ │ ├── cpuid.o
|
│ │ │ ├── cpuid.o
|
||||||
│ │ │ ├── cursor.o
|
│ │ │ ├── cursor.o
|
||||||
|
@ -64,6 +66,7 @@
|
||||||
│ │ │ ├── malloc.o
|
│ │ │ ├── malloc.o
|
||||||
│ │ │ ├── map.o
|
│ │ │ ├── map.o
|
||||||
│ │ │ ├── panic.o
|
│ │ │ ├── panic.o
|
||||||
|
│ │ │ ├── sched.o
|
||||||
│ │ │ ├── table.o
|
│ │ │ ├── table.o
|
||||||
│ │ │ ├── term.o
|
│ │ │ ├── term.o
|
||||||
│ │ │ └── vga.o
|
│ │ │ └── vga.o
|
||||||
|
@ -131,9 +134,12 @@
|
||||||
│ │ └── kalext.h
|
│ │ └── kalext.h
|
||||||
│ └── kernel
|
│ └── kernel
|
||||||
│ ├── buf
|
│ ├── buf
|
||||||
|
│ │ ├── bprint.c
|
||||||
|
│ │ ├── bput.c
|
||||||
│ │ └── buf.c
|
│ │ └── buf.c
|
||||||
│ ├── cpu
|
│ ├── cpu
|
||||||
│ │ └── cpuid.c
|
│ │ ├── cpuid.c
|
||||||
|
│ │ └── idt.c
|
||||||
│ ├── init
|
│ ├── init
|
||||||
│ │ ├── init.c
|
│ │ ├── init.c
|
||||||
│ │ └── table.c
|
│ │ └── table.c
|
||||||
|
@ -147,7 +153,8 @@
|
||||||
│ ├── mm
|
│ ├── mm
|
||||||
│ │ ├── heap.c
|
│ │ ├── heap.c
|
||||||
│ │ ├── malloc.c
|
│ │ ├── malloc.c
|
||||||
│ │ └── map.c
|
│ │ ├── map.c
|
||||||
|
│ │ └── stack.c
|
||||||
│ └── proc
|
│ └── proc
|
||||||
│ ├── Makefile
|
│ ├── Makefile
|
||||||
│ └── sched.c
|
│ └── sched.c
|
||||||
|
@ -162,4 +169,4 @@
|
||||||
├── qemu.log
|
├── qemu.log
|
||||||
└── Readme.md
|
└── Readme.md
|
||||||
|
|
||||||
28 directories, 109 files
|
28 directories, 116 files
|
||||||
|
|
|
@ -44,7 +44,7 @@ MB_header:
|
||||||
dd MB_HEADER_MAGIC
|
dd MB_HEADER_MAGIC
|
||||||
dd MB_HEADER_FLAGS
|
dd MB_HEADER_FLAGS
|
||||||
dd CHECKSUM
|
dd CHECKSUM
|
||||||
times 5 dd 0x0
|
times 5 dd 0x0 ; The unused section (provided for a.out)
|
||||||
dd MB_VIDEO_MODE
|
dd MB_VIDEO_MODE
|
||||||
dd MB_VIDEO_WIDTH
|
dd MB_VIDEO_WIDTH
|
||||||
dd MB_VIDEO_HEIGHT
|
dd MB_VIDEO_HEIGHT
|
||||||
|
@ -52,7 +52,7 @@ MB_header:
|
||||||
|
|
||||||
[section .text]
|
[section .text]
|
||||||
|
|
||||||
;;MULTIBOOT POINT ENTRY FOR GRUB ------------------------------------------- ;;
|
;;MULTIBOOT POINT ENTRY FOR GRUB -------------------------------------------- ;;
|
||||||
MB_start:
|
MB_start:
|
||||||
mov esp, KERNEL_STACK ; Setup the stack
|
mov esp, KERNEL_STACK ; Setup the stack
|
||||||
push 0 ; Reset EFLAGS
|
push 0 ; Reset EFLAGS
|
||||||
|
@ -133,8 +133,9 @@ lbegin:
|
||||||
|
|
||||||
[BITS 64]
|
[BITS 64]
|
||||||
|
|
||||||
x64_K db "Now in x64 long mode", 0x0A, 0x0D, 0x0
|
x64_K db "64 bits long mode activated !", 0x0A, 0x0D, 0x0
|
||||||
GoKernel db "Launching Kernel...", 0
|
GoKernel db "Launching Kernel...", 0
|
||||||
|
GoStack db "Initializing the stack...", 0x0A, 0x0D, 0x0
|
||||||
nokernel db 219, 219, 219, " Error 05 : Kernel returns",0
|
nokernel db 219, 219, 219, " Error 05 : Kernel returns",0
|
||||||
|
|
||||||
_loader64:
|
_loader64:
|
||||||
|
@ -154,14 +155,21 @@ _loader64:
|
||||||
mov bl, 0x0A
|
mov bl, 0x0A
|
||||||
mov esi, x64_K
|
mov esi, x64_K
|
||||||
call write
|
call write
|
||||||
|
|
||||||
|
;; Initialize the stack
|
||||||
|
mov bl, 0x0F
|
||||||
|
mov esi, GoStack
|
||||||
|
call write
|
||||||
|
|
||||||
|
call tritemporize ; Let time to see
|
||||||
|
call InitStack
|
||||||
|
|
||||||
|
;; Launch the kernel !
|
||||||
mov bl, 0x0F
|
mov bl, 0x0F
|
||||||
mov esi, GoKernel
|
mov esi, GoKernel
|
||||||
call write
|
call write
|
||||||
|
|
||||||
;; Launch the kernel !
|
mov qword [newKernelEnd], KERNEL_STACK
|
||||||
;; XXX CHECK THE RAM BEFORE CALLING KERNEL !
|
|
||||||
call tritemporize ; Let time to see
|
|
||||||
|
|
||||||
mov rdi, [mbInfo]
|
mov rdi, [mbInfo]
|
||||||
mov rsi, [mbMagic]
|
mov rsi, [mbMagic]
|
||||||
call BtStartKern
|
call BtStartKern
|
||||||
|
|
|
@ -106,3 +106,36 @@ CheckA20:
|
||||||
.A20_err:
|
.A20_err:
|
||||||
mov ax, "04" ; ERROR 04 : A20 line failed
|
mov ax, "04" ; ERROR 04 : A20 line failed
|
||||||
jmp Error
|
jmp Error
|
||||||
|
|
||||||
|
[BITS 64]
|
||||||
|
; ---------------------------------------------------------------------------- ;
|
||||||
|
; Initilizes the stack ;
|
||||||
|
; ---------------------------------------------------------------------------- ;
|
||||||
|
InitStack:
|
||||||
|
xor rax, rax ; "Fill pattern"
|
||||||
|
push rcx
|
||||||
|
push rdi
|
||||||
|
|
||||||
|
;; Begin address to fill and length
|
||||||
|
mov rdi, kernelEnd
|
||||||
|
mov rcx, KERNEL_STACK - kernelEnd - 16
|
||||||
|
; stop before the return address
|
||||||
|
|
||||||
|
;; If bit 0 is on, fill one byte
|
||||||
|
sar rcx, 1 ; Shift bit 0 into CY
|
||||||
|
jnc $ + 3
|
||||||
|
stosb
|
||||||
|
;; We are word aligned and if bit 1 was on fill another word
|
||||||
|
sar rcx, 1 ; Shift bit 1 into CY
|
||||||
|
jnc $ + 4
|
||||||
|
stosw
|
||||||
|
;; We are dword aligned and if bit 2 was on fill another dword
|
||||||
|
sar rcx, 1 ; Shift bit 2 into CY
|
||||||
|
jnc $ + 3
|
||||||
|
stosd
|
||||||
|
;; RCX now equals the number of qwords to fill
|
||||||
|
repnz stosq ; Finish by writing RCX qwords.
|
||||||
|
|
||||||
|
pop rdi
|
||||||
|
pop rcx
|
||||||
|
ret
|
||||||
|
|
|
@ -24,6 +24,13 @@
|
||||||
;=----------------------------------------------------------------------------=;
|
;=----------------------------------------------------------------------------=;
|
||||||
|
|
||||||
[BITS 32]
|
[BITS 32]
|
||||||
|
extern kernelEnd
|
||||||
|
global newKernelEnd
|
||||||
|
|
||||||
|
[section .text]
|
||||||
|
KERNEL_STACK equ kernelEnd + 4096 * 2 * 1024 ; 8MB of stack
|
||||||
|
newKernelEnd dq 0x0
|
||||||
|
|
||||||
[section .rodata]
|
[section .rodata]
|
||||||
;; GDT WITH DOC
|
;; GDT WITH DOC
|
||||||
ALIGN 4096
|
ALIGN 4096
|
||||||
|
@ -43,6 +50,7 @@ GDT64:
|
||||||
dw $ - GDT64 - 1
|
dw $ - GDT64 - 1
|
||||||
dq GDT64
|
dq GDT64
|
||||||
|
|
||||||
|
|
||||||
;; EMPTY PAGE TABLES (identity of the first 1GiB)
|
;; EMPTY PAGE TABLES (identity of the first 1GiB)
|
||||||
[section .bss]
|
[section .bss]
|
||||||
ALIGN 4096
|
ALIGN 4096
|
||||||
|
@ -52,4 +60,3 @@ PDP_table:
|
||||||
resb 4096
|
resb 4096
|
||||||
PD_table:
|
PD_table:
|
||||||
resb 4096
|
resb 4096
|
||||||
|
|
||||||
|
|
|
@ -36,4 +36,3 @@ MB_HEADER_MAGIC equ 0x1badb002
|
||||||
MB_GRUB_MAGIC equ 0x2badb002
|
MB_GRUB_MAGIC equ 0x2badb002
|
||||||
MB_HEADER_FLAGS equ MB_AOUT_KLUDGE|MB_ALIGN|MB_MEMINFO|MB_VIDEOINFO
|
MB_HEADER_FLAGS equ MB_AOUT_KLUDGE|MB_ALIGN|MB_MEMINFO|MB_VIDEOINFO
|
||||||
CHECKSUM equ -(MB_HEADER_MAGIC + MB_HEADER_FLAGS)
|
CHECKSUM equ -(MB_HEADER_MAGIC + MB_HEADER_FLAGS)
|
||||||
KERNEL_STACK equ 0x00200000 ; Stack starts at the 2mb address & grows down
|
|
||||||
|
|
|
@ -61,10 +61,10 @@ SECTIONS {
|
||||||
*(.rodata) /* all rodata sections from all files */
|
*(.rodata) /* all rodata sections from all files */
|
||||||
}
|
}
|
||||||
|
|
||||||
kernelEnd = .;
|
|
||||||
|
|
||||||
/DISCARD/ :
|
/DISCARD/ :
|
||||||
{
|
{
|
||||||
*(.comment)
|
*(.comment)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kernelEnd = .;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
//------------------------------------------//
|
//------------------------------------------//
|
||||||
|
@ -75,6 +74,15 @@ struct Processor_t
|
||||||
// CPU number, index in CPU list
|
// CPU number, index in CPU list
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
|
// CPU APIC id
|
||||||
|
int apicId;
|
||||||
|
// CPU Vendor String (always 12 characters)
|
||||||
|
char vendorStr[12];
|
||||||
|
// CPU Model code (enum in cpu.h)
|
||||||
|
int modelCode;
|
||||||
|
// CPU Features flag
|
||||||
|
uint featureFlag;
|
||||||
|
|
||||||
// Number of ticks since boot time
|
// Number of ticks since boot time
|
||||||
ulong ticks;
|
ulong ticks;
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -29,14 +29,76 @@
|
||||||
#ifndef _KALKERN_CPU_H
|
#ifndef _KALKERN_CPU_H
|
||||||
#define _KALKERN_CPU_H
|
#define _KALKERN_CPU_H
|
||||||
|
|
||||||
//------------------------------------------//
|
// -------------------------------------------------------------------------- //
|
||||||
|
|
||||||
#define KeCPUID(in, a, b, c, d) asm("cpuid" \
|
#define KeCPUID(in, a, b, c, d) asm("cpuid" \
|
||||||
: "=a" (a), "=b" (b), "=c" (c), "=d" (d) \
|
: "=a" (a), "=b" (b), "=c" (c), "=d" (d) \
|
||||||
: "a" (in) \
|
: "a" (in) \
|
||||||
);
|
);
|
||||||
|
|
||||||
//------------------------------------------//
|
// -------------------------------------------------------------------------- //
|
||||||
|
|
||||||
|
// CPU features masks
|
||||||
|
enum {
|
||||||
|
FEAT_ECX_SSE3 = 1 << 0,
|
||||||
|
FEAT_ECX_PCLMUL = 1 << 1,
|
||||||
|
FEAT_ECX_DTES64 = 1 << 2,
|
||||||
|
FEAT_ECX_MONITOR = 1 << 3,
|
||||||
|
FEAT_ECX_DS_CPL = 1 << 4,
|
||||||
|
FEAT_ECX_VMX = 1 << 5,
|
||||||
|
FEAT_ECX_SMX = 1 << 6,
|
||||||
|
FEAT_ECX_EST = 1 << 7,
|
||||||
|
FEAT_ECX_TM2 = 1 << 8,
|
||||||
|
FEAT_ECX_SSSE3 = 1 << 9,
|
||||||
|
FEAT_ECX_CID = 1 << 10,
|
||||||
|
FEAT_ECX_FMA = 1 << 12,
|
||||||
|
FEAT_ECX_CX16 = 1 << 13,
|
||||||
|
FEAT_ECX_ETPRD = 1 << 14,
|
||||||
|
FEAT_ECX_PDCM = 1 << 15,
|
||||||
|
FEAT_ECX_PCIDE = 1 << 17,
|
||||||
|
FEAT_ECX_DCA = 1 << 18,
|
||||||
|
FEAT_ECX_SSE4_1 = 1 << 19,
|
||||||
|
FEAT_ECX_SSE4_2 = 1 << 20,
|
||||||
|
FEAT_ECX_x2APIC = 1 << 21,
|
||||||
|
FEAT_ECX_MOVBE = 1 << 22,
|
||||||
|
FEAT_ECX_POPCNT = 1 << 23,
|
||||||
|
FEAT_ECX_AES = 1 << 25,
|
||||||
|
FEAT_ECX_XSAVE = 1 << 26,
|
||||||
|
FEAT_ECX_OSXSAVE = 1 << 27,
|
||||||
|
FEAT_ECX_AVX = 1 << 28,
|
||||||
|
|
||||||
|
FEAT_EDX_FPU = 1 << 0,
|
||||||
|
FEAT_EDX_VME = 1 << 1,
|
||||||
|
FEAT_EDX_DE = 1 << 2,
|
||||||
|
FEAT_EDX_PSE = 1 << 3,
|
||||||
|
FEAT_EDX_TSC = 1 << 4,
|
||||||
|
FEAT_EDX_MSR = 1 << 5,
|
||||||
|
FEAT_EDX_PAE = 1 << 6,
|
||||||
|
FEAT_EDX_MCE = 1 << 7,
|
||||||
|
FEAT_EDX_CX8 = 1 << 8,
|
||||||
|
FEAT_EDX_APIC = 1 << 9,
|
||||||
|
FEAT_EDX_SEP = 1 << 11,
|
||||||
|
FEAT_EDX_MTRR = 1 << 12,
|
||||||
|
FEAT_EDX_PGE = 1 << 13,
|
||||||
|
FEAT_EDX_MCA = 1 << 14,
|
||||||
|
FEAT_EDX_CMOV = 1 << 15,
|
||||||
|
FEAT_EDX_PAT = 1 << 16,
|
||||||
|
FEAT_EDX_PSE36 = 1 << 17,
|
||||||
|
FEAT_EDX_PSN = 1 << 18,
|
||||||
|
FEAT_EDX_CLF = 1 << 19,
|
||||||
|
FEAT_EDX_DTES = 1 << 21,
|
||||||
|
FEAT_EDX_ACPI = 1 << 22,
|
||||||
|
FEAT_EDX_MMX = 1 << 23,
|
||||||
|
FEAT_EDX_FXSR = 1 << 24,
|
||||||
|
FEAT_EDX_SSE = 1 << 25,
|
||||||
|
FEAT_EDX_SSE2 = 1 << 26,
|
||||||
|
FEAT_EDX_SS = 1 << 27,
|
||||||
|
FEAT_EDX_HTT = 1 << 28,
|
||||||
|
FEAT_EDX_TM1 = 1 << 29,
|
||||||
|
FEAT_EDX_IA64 = 1 << 30,
|
||||||
|
FEAT_EDX_PBE = 1 << 31
|
||||||
|
};
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------- //
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,8 @@
|
||||||
|
|
||||||
//------------------------------------------//
|
//------------------------------------------//
|
||||||
|
|
||||||
#define _HEAP_START (4 * MB)
|
// Address of the heap
|
||||||
|
void *_heap_start;
|
||||||
|
|
||||||
void MmInitHeap(void);
|
void MmInitHeap(void);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 *);
|
||||||
|
|
||||||
//------------------------------------------//
|
//------------------------------------------//
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
//------------------------------------------//
|
//------------------------------------------//
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
@ -141,123 +139,4 @@ error_t BFlushBuf(Buffer_t *buf)
|
||||||
ExReleaseLock(&buf->lock);
|
ExReleaseLock(&buf->lock);
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
|
@ -22,4 +22,12 @@
|
||||||
// along with OS/K. If not, see <https://www.gnu.org/licenses/>. //
|
// along with OS/K. If not, see <https://www.gnu.org/licenses/>. //
|
||||||
//----------------------------------------------------------------------------//
|
//----------------------------------------------------------------------------//
|
||||||
|
|
||||||
int stub;
|
|
||||||
|
char *KeGetVendorString(void) {
|
||||||
|
return "Null";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
//----------------------------------------------------------------------------//
|
||||||
|
// GNU GPL OS/K //
|
||||||
|
// //
|
||||||
|
// Desc: Interrupt related functions //
|
||||||
|
// //
|
||||||
|
// //
|
||||||
|
// 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/>. //
|
||||||
|
//----------------------------------------------------------------------------//
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Registers the new idt in the idtr register.
|
||||||
|
//
|
||||||
|
static inline void lidt(void* idtAddr, ushort size)
|
||||||
|
{
|
||||||
|
struct {
|
||||||
|
ushort length;
|
||||||
|
void* base;
|
||||||
|
} __attribute__((packed)) IDTR = { size, idtAddr };
|
||||||
|
|
||||||
|
asm volatile( "lidt %0" : : "m"(IDTR) );
|
||||||
|
}
|
|
@ -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 newKernelEnd;
|
||||||
|
|
||||||
// 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*)newKernelEnd;
|
||||||
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,17 @@ 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));
|
MmInitHeap();
|
||||||
KernLog("[Init] TEST Size of zone : %u Kio\n\n", MmGetAvailZoneSize(MmGetFirstAvailZone((void*)0xB8010)) / KB);
|
PsInitSched();
|
||||||
|
|
||||||
|
Buffer_t *buf = BOpenLineBuf(NULL, BS_WRONLY, 80, 24, 1, NULL);
|
||||||
|
|
||||||
|
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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
#include <kernel/heap.h>
|
#include <kernel/heap.h>
|
||||||
#include <kernel/mm.h>
|
#include <kernel/mm.h>
|
||||||
|
#include <kernel/term.h>
|
||||||
|
|
||||||
// Least address out of the heap
|
// Least address out of the heap
|
||||||
static void *_heap_end;
|
static void *_heap_end;
|
||||||
|
@ -34,15 +35,23 @@ 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
|
||||||
//
|
//
|
||||||
void MmInitHeap(void)
|
void MmInitHeap(void)
|
||||||
{
|
{
|
||||||
assert(_heap_end == NULL);
|
assert(_heap_end == NULL);
|
||||||
_heap_end = (void *)_HEAP_START;
|
|
||||||
_heap_max = lmin(8 * MB, MmGetAvailZoneSize((void *)_HEAP_START));
|
// Get the first available zone address
|
||||||
|
_heap_start = MmGetFirstAvailZone((void*)0);
|
||||||
|
// Align it
|
||||||
|
while ((size_t)_heap_start % alignof(QWORD)) {
|
||||||
|
_heap_start++;
|
||||||
|
}
|
||||||
|
// Initialize the heap
|
||||||
|
_heap_end = _heap_start;
|
||||||
|
_heap_max = lmin(8 * MB, MmGetAvailZoneSize(_heap_end));
|
||||||
|
KernLog("[InitHeap] Start address : %p, Max length : %u Mio\n\n", _heap_start, _heap_max / MB);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -66,7 +75,7 @@ void MmUnlockHeap(void)
|
||||||
//
|
//
|
||||||
size_t MmGetHeapSize(void)
|
size_t MmGetHeapSize(void)
|
||||||
{
|
{
|
||||||
return (size_t)_heap_end - _HEAP_START;
|
return (size_t)_heap_end - (size_t)_heap_start;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -82,11 +91,11 @@ size_t MmGetMaxHeapSize(void)
|
||||||
//
|
//
|
||||||
error_t MmSetMaxHeapSize(size_t new)
|
error_t MmSetMaxHeapSize(size_t new)
|
||||||
{
|
{
|
||||||
if (new > MmGetAvailZoneSize((void *)_HEAP_START)) {
|
if (new > MmGetAvailZoneSize((void *)_heap_start)) {
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new < (size_t)_heap_end - _HEAP_START) {
|
if (new < (size_t)_heap_end - (size_t)_heap_start) {
|
||||||
return EADDRINUSE;
|
return EADDRINUSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,9 +109,9 @@ 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 > (size_t)_heap_start + _heap_max) {
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,9 +125,9 @@ 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 - (size_t)_heap_start) {
|
||||||
return EADDRINUSE;
|
return EADDRINUSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@ error_t KalAllocMemory(void **ptr, size_t req, int flags, size_t align)
|
||||||
{
|
{
|
||||||
error_t rc;
|
error_t rc;
|
||||||
size_t brk;
|
size_t brk;
|
||||||
|
extern void *_heap_start;
|
||||||
|
|
||||||
if (align == 0) align = M_DEFAULT_ALIGNMENT;
|
if (align == 0) align = M_DEFAULT_ALIGNMENT;
|
||||||
|
|
||||||
|
@ -38,7 +39,7 @@ error_t KalAllocMemory(void **ptr, size_t req, int flags, size_t align)
|
||||||
|
|
||||||
MmLockHeap();
|
MmLockHeap();
|
||||||
|
|
||||||
brk = _HEAP_START + MmGetHeapSize();
|
brk = (size_t)_heap_start + MmGetHeapSize();
|
||||||
req = _ALIGN_UP(req + brk, align) - brk;
|
req = _ALIGN_UP(req + brk, align) - brk;
|
||||||
|
|
||||||
rc = MmGrowHeap(req);
|
rc = MmGrowHeap(req);
|
||||||
|
@ -57,6 +58,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,23 +52,23 @@ 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;
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
//----------------------------------------------------------------------------//
|
||||||
|
// GNU GPL OS/K //
|
||||||
|
// //
|
||||||
|
// Desc: Mapping and checking memory related functions //
|
||||||
|
// //
|
||||||
|
// //
|
||||||
|
// 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/>. //
|
||||||
|
//----------------------------------------------------------------------------//
|
|
@ -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
|
|
||||||
|
|
Loading…
Reference in New Issue