Espresso 0.0.2c
This commit is contained in:
58
lib/espresso/kstring.c
Normal file
58
lib/espresso/kstring.c
Normal file
@ -0,0 +1,58 @@
|
||||
#include <stdlib.h>
|
||||
#include <types.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/*
|
||||
A custom standard for strings for use in the Espresso kernel.
|
||||
*/
|
||||
|
||||
struct kstring {
|
||||
size_t s_len;
|
||||
char* data; /* NOT null-terminated */
|
||||
};
|
||||
|
||||
/*
|
||||
if the length of initial_data is more than initial_len, only initial_len bytes will be copied.
|
||||
if the length of initial_data is less then initial_len, the rest of the bytes are zeroed.
|
||||
if initial_data is null, no data is copied and the string in set to zero.
|
||||
*/
|
||||
struct kstring* make_kstring(size_t initial_len, const char* initial_data)
|
||||
{
|
||||
struct kstring* str = malloc(sizeof(struct kstring));
|
||||
|
||||
if (!str)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
str->s_len = initial_len;
|
||||
str->data = malloc(initial_len);
|
||||
|
||||
if (!str->data)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(str->data, 0, initial_len);
|
||||
|
||||
if (initial_data)
|
||||
{
|
||||
size_t slen = strlen(initial_data);
|
||||
|
||||
if (slen < initial_len)
|
||||
{
|
||||
strncpy(str->data, initial_data, slen);
|
||||
}
|
||||
else if (slen > initial_len)
|
||||
{
|
||||
strncpy(str->data, initial_data, initial_len);
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(str->data, initial_data);
|
||||
}
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
79
lib/math/random.c
Normal file
79
lib/math/random.c
Normal file
@ -0,0 +1,79 @@
|
||||
#include <types.h>
|
||||
|
||||
#include <math/random.h>
|
||||
|
||||
|
||||
/*
|
||||
This code uses Xorshift (high speed, small) and PCG (Permuted Congruential Generator).
|
||||
PCG may or may not be slightly slower than Xorshift.
|
||||
*/
|
||||
|
||||
static uint32_t xorshift_state = 2463534242;
|
||||
|
||||
static void srand_xorshift(uint32_t seed)
|
||||
{
|
||||
xorshift_state = seed;
|
||||
}
|
||||
|
||||
static inline uint32_t rand_xorshift(void)
|
||||
{
|
||||
uint32_t x = xorshift_state;
|
||||
x ^= x << 13;
|
||||
x ^= x >> 17;
|
||||
x ^= x << 5;
|
||||
|
||||
return xorshift_state = x;
|
||||
}
|
||||
|
||||
static uint64_t state = 0x853c49e6748fea9bULL;
|
||||
static uint64_t inc = 0xda3e39cb94b95bdbULL;
|
||||
|
||||
static inline uint32_t rand_pcg32(void)
|
||||
{
|
||||
uint64_t oldstate = state;
|
||||
state = oldstate * 6364136223846793005ULL + (inc | 1);
|
||||
uint32_t xorshifted = ((oldstate >> 18u) ^ oldstate) >> 27u;
|
||||
uint32_t rot = oldstate >> 59u;
|
||||
|
||||
return (xorshifted >> rot) | (xorshifted << ((-rot) & 31));
|
||||
}
|
||||
|
||||
void seed_rand(uint32_t seed)
|
||||
{
|
||||
srand_xorshift(seed);
|
||||
state = seed * 6364136223846793005ULL + (seed | 1);
|
||||
}
|
||||
|
||||
uint32_t uirand(void)
|
||||
{
|
||||
return rand_pcg32() ^ rand_xorshift();
|
||||
}
|
||||
|
||||
/* get a number between 0 and max-1 */
|
||||
uint32_t uirand_range(uint32_t max)
|
||||
{
|
||||
if (max == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return uirand() % max;
|
||||
}
|
||||
|
||||
uint64_t ulrand(void)
|
||||
{
|
||||
uint64_t hi = uirand();
|
||||
uint64_t lo = uirand();
|
||||
return (hi << 32) | lo;
|
||||
}
|
||||
|
||||
/* get a number between 0 and max-1 */
|
||||
uint64_t ulrand_range(uint64_t max)
|
||||
{
|
||||
if (max == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ulrand() % max;
|
||||
}
|
||||
@ -111,7 +111,12 @@ void free(void* ptr)
|
||||
block_t* curr = free_list;
|
||||
while (curr && curr->next)
|
||||
{
|
||||
if (curr->free && curr->next->free)
|
||||
/*if (curr->free && curr->next->free)
|
||||
{
|
||||
curr->size += BLOCK_SIZE + curr->next->size;
|
||||
curr->next = curr->next->next;
|
||||
}*/
|
||||
if (curr->free && curr->next->free && (uint8_t*)curr + BLOCK_SIZE + curr->size == (uint8_t*)curr->next)
|
||||
{
|
||||
curr->size += BLOCK_SIZE + curr->next->size;
|
||||
curr->next = curr->next->next;
|
||||
|
||||
24
lib/mm/pmm.c
24
lib/mm/pmm.c
@ -12,6 +12,10 @@ static size_t total_pages;
|
||||
#define BITMAP_CLEAR(i) (bitmap[(i) / 8] &= ~(1 << ((i) % 8)))
|
||||
#define BITMAP_TEST(i) (bitmap[(i) / 8] & (1 << ((i) % 8)))
|
||||
|
||||
|
||||
extern uint32_t __kernel_start;
|
||||
extern uint32_t __kernel_end;
|
||||
|
||||
void pmm_init(multiboot_info_t* mb)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
@ -45,6 +49,18 @@ void pmm_init(multiboot_info_t* mb)
|
||||
}
|
||||
}
|
||||
total_pages = MAX_PAGES;
|
||||
|
||||
uintptr_t start = (uintptr_t)&__kernel_start;
|
||||
uintptr_t end = (uintptr_t)&__kernel_end;
|
||||
|
||||
start &= ~0xFFF;
|
||||
end = (end + 0xFFF) & ~0xFFF;
|
||||
|
||||
for (uintptr_t addr = start; addr < end; addr += 0x1000)
|
||||
{
|
||||
size_t idx = addr / 0x1000;
|
||||
BITMAP_SET(idx); // Mark kernel pages as USED
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
printf("[ PMM ] Physical memory manager initialized\n");
|
||||
@ -55,6 +71,14 @@ void* pmm_alloc_page(void)
|
||||
{
|
||||
for (uint32_t i = 0; i < total_pages; ++i)
|
||||
{
|
||||
void* page = (void*)(i * 4096);
|
||||
|
||||
if ((uintptr_t)page >= (uintptr_t)&__kernel_start &&
|
||||
(uintptr_t)page < (uintptr_t)&__kernel_end)
|
||||
{
|
||||
printf("PMM allocating inside kernel at %x\n", page);
|
||||
}
|
||||
|
||||
if (!BITMAP_TEST(i))
|
||||
{
|
||||
BITMAP_SET(i);
|
||||
|
||||
@ -4,6 +4,8 @@
|
||||
#include <stdint.h>
|
||||
#include <drivers/serio.h>
|
||||
|
||||
#include <tty.h>
|
||||
|
||||
#include <printf.h>
|
||||
|
||||
static uint8_t color = 0xFF;
|
||||
|
||||
@ -3,13 +3,18 @@
|
||||
#include <processes.h>
|
||||
|
||||
|
||||
int32_t next_id = 9; /* 0 through 8 are reserved for kernel operations */
|
||||
pid_t next_id = 1; /* start at 1 */
|
||||
|
||||
int32_t make_process(char* name, char* group, elf_executable_t* exe)
|
||||
pid_t make_process(char* name, char* group, elf_executable_t* exe)
|
||||
{
|
||||
pid_t ret = (pid_t) 0;
|
||||
|
||||
if (!name || !group || !exe)
|
||||
{
|
||||
return -1;
|
||||
return ret; /* ret is already zero */
|
||||
}
|
||||
return 0;
|
||||
|
||||
next_id++;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
76
lib/scheduler.c
Normal file
76
lib/scheduler.c
Normal file
@ -0,0 +1,76 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <drivers/irq.h>
|
||||
|
||||
#include <scheduler.h>
|
||||
|
||||
|
||||
#define STACK_SIZE (8192)
|
||||
|
||||
task_t* current_task = NULL;
|
||||
task_t* task_list = NULL;
|
||||
uint32_t next_pid = 1;
|
||||
|
||||
|
||||
void init_scheduler(void)
|
||||
{
|
||||
set_irq_handler(0, (irq_func_t) schedule);
|
||||
}
|
||||
|
||||
void scheduler(registers_t* boot_regs)
|
||||
{
|
||||
task_t* task = malloc(sizeof(task_t));
|
||||
|
||||
task->id = next_pid++;
|
||||
task->regs = boot_regs;
|
||||
task->next = task;
|
||||
|
||||
task_list = task;
|
||||
current_task = task;
|
||||
}
|
||||
|
||||
registers_t* schedule(registers_t* regs)
|
||||
{
|
||||
if (!current_task)
|
||||
{
|
||||
return regs;
|
||||
}
|
||||
|
||||
current_task->regs = regs;
|
||||
|
||||
current_task = current_task->next;
|
||||
|
||||
return current_task->regs;
|
||||
}
|
||||
|
||||
task_t* create_task(void (*entry)())
|
||||
{
|
||||
task_t* task = malloc(sizeof(task_t));
|
||||
uint32_t* stack = malloc(STACK_SIZE);
|
||||
|
||||
uint32_t stack_top = (uint32_t)stack + 4096;
|
||||
|
||||
stack_top -= sizeof(registers_t);
|
||||
registers_t* regs = (registers_t*)stack_top;
|
||||
|
||||
memset(regs, 0, sizeof(registers_t));
|
||||
|
||||
regs->eip = (uint32_t) entry;
|
||||
regs->cs = 0x08; /* kernel code */
|
||||
regs->ds = 0x10;
|
||||
regs->es = 0x10;
|
||||
regs->fs = 0x10;
|
||||
regs->gs = 0x10;
|
||||
regs->eflags = 0x202; /* IF = 1 */
|
||||
|
||||
task->id = next_pid++;
|
||||
task->regs = regs;
|
||||
|
||||
/* insert into circular list */
|
||||
task->next = task_list->next;
|
||||
task_list->next = task;
|
||||
|
||||
return task;
|
||||
}
|
||||
94
lib/stdio.c
94
lib/stdio.c
@ -2,8 +2,45 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <kernel/syscall.h>
|
||||
#include <tty.h>
|
||||
|
||||
#include <new_tty.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int write(uint32_t fd, void* data, size_t len)
|
||||
{
|
||||
if (fd == STDOUT)
|
||||
{
|
||||
print_uint((uint32_t) len);
|
||||
terminal_write((char*) data, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int read(uint32_t fd, void* data, size_t max_len)
|
||||
{
|
||||
int rv = 0;
|
||||
|
||||
if (fd == STDIN)
|
||||
{
|
||||
char* sptr = (char*) data; /* this really shouldn't be needed... */
|
||||
sptr = gets_new(&rv);
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
extern bool ps2keyboard_initialized;
|
||||
|
||||
char getchar(void)
|
||||
@ -31,40 +68,33 @@ char* gets(void)
|
||||
return kbd_gets();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*char* fgets(char* buf, int n, FILE file)
|
||||
char* gets_new(int* num)
|
||||
{
|
||||
if (!buf || n <= 1 || file < 1)
|
||||
char* __s = malloc(256);
|
||||
|
||||
memset(__s, 0, 256);
|
||||
|
||||
ssize_t n = tty_read_active(__s, 255);
|
||||
|
||||
*num = (int) n;
|
||||
|
||||
return __s;
|
||||
}
|
||||
|
||||
int getstr(char* dest)
|
||||
{
|
||||
int i = 0;
|
||||
char* p = gets_new(&i);
|
||||
|
||||
if (i != 0)
|
||||
{
|
||||
return NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int total_read = 0;
|
||||
char c;
|
||||
strcpy(dest, p);
|
||||
}
|
||||
|
||||
while (total_read < n - 1)
|
||||
{
|
||||
int bytes = 0*//*read_file(file, &c, 1)*/;
|
||||
|
||||
/*if (bytes <= 0)
|
||||
{
|
||||
break; *//* EOF or error */
|
||||
/*}
|
||||
|
||||
buf[total_read++] = c;
|
||||
|
||||
if (c == '\n')
|
||||
{
|
||||
break; *//* Stop at newline */
|
||||
/*}
|
||||
}
|
||||
|
||||
if (total_read == 0)
|
||||
{
|
||||
return NULL; *//* Nothing read (e.g. EOF) */
|
||||
/*}
|
||||
|
||||
buf[total_read] = '\0';
|
||||
return buf;
|
||||
}*/
|
||||
void putc(char c)
|
||||
{
|
||||
syscall1(SYS_TERMINAL_PUTCHAR, c);
|
||||
}
|
||||
|
||||
47
lib/string.c
47
lib/string.c
@ -1,10 +1,12 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <vector_extensions/sse.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifdef DEBUG_USE_SSE2
|
||||
#include <vector_extensions/sse.h>
|
||||
extern int32_t sse_initialized;
|
||||
#endif
|
||||
|
||||
size_t strlen(const char* str)
|
||||
{
|
||||
@ -76,10 +78,12 @@ char* strcpy(char *dst, const char *src)
|
||||
|
||||
char* strncpy(char *dest, const char *src, uint32_t n)
|
||||
{
|
||||
#ifdef DEBUG_USE_SSE2
|
||||
if (sse_initialized > 0)
|
||||
{
|
||||
return sse2_strncpy(dest, src, n);
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32_t i = 0;
|
||||
for (; i < n && src[i]; ++i)
|
||||
@ -217,10 +221,12 @@ void* memset(void* dst, int c, size_t n)
|
||||
|
||||
void* memcpy(void *dst, const void *src, uint32_t n)
|
||||
{
|
||||
#ifdef DEBUG_USE_SSE2
|
||||
if (sse_initialized > 1)
|
||||
{
|
||||
return sse2_memcpy(dst, src, n);
|
||||
}
|
||||
#endif
|
||||
|
||||
char *d = dst;
|
||||
const char *s = src;
|
||||
@ -234,8 +240,8 @@ void* memcpy(void *dst, const void *src, uint32_t n)
|
||||
|
||||
int32_t memcmp(const void *s1, const void *s2, size_t n)
|
||||
{
|
||||
const uint8_t *p1 = (const uint8_t *)s1;
|
||||
const uint8_t *p2 = (const uint8_t *)s2;
|
||||
const uint8_t *p1 = (const uint8_t*) s1;
|
||||
const uint8_t *p2 = (const uint8_t*) s2;
|
||||
|
||||
/*printf("p1: %i, p2: %i\n", (int32_t)*p1, (int32_t)*p2);*/
|
||||
|
||||
@ -252,10 +258,12 @@ int32_t memcmp(const void *s1, const void *s2, size_t n)
|
||||
|
||||
void* memclr(void* m_start, size_t m_count)
|
||||
{
|
||||
#ifdef DEBUG_USE_SSE2
|
||||
if (sse_initialized > 1)
|
||||
{
|
||||
return memclr_sse2(m_start, m_count);
|
||||
}
|
||||
#endif
|
||||
|
||||
return memset(m_start, '\0', (uint32_t)m_count);
|
||||
}
|
||||
@ -451,3 +459,36 @@ double atof(const char *str)
|
||||
return sign * (res + frac / frac_div);
|
||||
}
|
||||
|
||||
char* strnlstrip(const char* s)
|
||||
{
|
||||
if (!s)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char* new = strdup(s);
|
||||
if (!new)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t len = strlen(new);
|
||||
|
||||
while (len > 0 && (new[len-1] == '\n' || new[len-1] == '\r'))
|
||||
{
|
||||
new[len-1] = '\0';
|
||||
len--;
|
||||
}
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
void strlnstripip(char* s)
|
||||
{
|
||||
size_t len = strlen(s);
|
||||
|
||||
if (len > 0 && s[len-1] == '\n')
|
||||
{
|
||||
s[len-1] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
40
lib/sync.c
Normal file
40
lib/sync.c
Normal file
@ -0,0 +1,40 @@
|
||||
|
||||
|
||||
#include <sync.h>
|
||||
|
||||
|
||||
void spinlock_init(spinlock_t* lock)
|
||||
{
|
||||
lock->locked = 0;
|
||||
}
|
||||
|
||||
static inline int atomic_xchg(volatile int* addr, int newval)
|
||||
{
|
||||
int result;
|
||||
|
||||
asm volatile (
|
||||
"xchg %0, %1"
|
||||
: "=r"(result), "+m"(*addr)
|
||||
: "0"(newval)
|
||||
: "memory"
|
||||
);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void spin_lock(spinlock_t* lock)
|
||||
{
|
||||
while (atomic_xchg(&lock->locked, 1))
|
||||
{
|
||||
while (lock->locked)
|
||||
{
|
||||
asm volatile("pause");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void spin_unlock(spinlock_t* lock)
|
||||
{
|
||||
__atomic_clear(&lock->locked, __ATOMIC_RELEASE);
|
||||
}
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
#ifdef DEBUG_USE_SSE2
|
||||
|
||||
#include <types.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@ -248,3 +250,5 @@ void* memclr_sse2(void *m_start, size_t m_count)
|
||||
|
||||
return m_start;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user