Compare commits

...

4 commits

Author SHA1 Message Date
Imbus
d583dbaced Initial implementation of a freelist. blocks contain a header 2025-09-08 05:03:40 +02:00
Imbus
f01b71f4a6 next_power_of_two bit hack function 2025-09-08 05:02:38 +02:00
Imbus
45ad16efb0 xv6-riscv license 2025-09-08 00:48:13 +02:00
Imbus
e9f2eef252 String: strncmp, strncpy 2025-09-08 00:45:41 +02:00
7 changed files with 209 additions and 3 deletions

View file

@ -55,6 +55,7 @@ quickstart:
KERNEL_OBJ := \
kern/entry.o \
kern/start.o \
kern/libkern/freelist.o \
kern/libkern/string.o \
kern/libkern/proc.o \
kern/libkern/uart.o \

117
kern/libkern/freelist.c Normal file
View file

@ -0,0 +1,117 @@
#include "freelist.h"
#include "stddef.h"
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
/* Fiddle these around according to your need. */
#ifdef FREELIST_NOALIGN
#define ALIGN(x) (x)
#else // FREELIST_NOALIGN
/* Align to nearest multiple of sizeof(void*) */
static inline size_t align_up(size_t n) {
return (n + sizeof(void *) - 1) & ~(sizeof(void *) - 1);
}
#define ALIGN(x) (align_up(x))
#endif // FREELIST_NOALIGN
/* Initialize the FreeList */
int fl_init(FreeList *fl, uintptr_t start, uintptr_t end, size_t itemsize) {
size_t size = ALIGN(itemsize + sizeof(FreeListBlock));
if (!fl || end <= start)
return EXIT_FAILURE;
fl->start = start;
fl->end = end;
fl->size = size;
fl->allocated = 0;
FreeListBlock *block = (FreeListBlock *)start;
for (size_t i = 0; i < fl_capacity(fl); i++) {
block->next = (FreeListBlock *)((void *)block + size);
block->block_state = FL_FREE;
block = block->next;
}
block->next = NULL;
fl->free = (FreeListBlock *)start;
return EXIT_SUCCESS;
}
/* Allocate some memory from the FreeList */
void *fl_alloc(FreeList *fl) {
if (!fl->free || fl->free->block_state != FL_FREE)
return NULL;
FreeListBlock *m = fl->free;
m->block_state = FL_USED;
fl->free = fl->free->next;
fl->allocated++;
return ((void *)m) + sizeof(FreeListBlock);
}
/* Return some memory to the FreeList */
int fl_free(FreeList *fl, void *ptr) {
if (!fl_is_managed(fl, ptr)) {
return EXIT_FAILURE; /* We cant free memory we do not own */
}
FreeListBlock *block = (FreeListBlock *)((uintptr_t)ptr - sizeof(FreeListBlock));
if (block->block_state != FL_USED) {
return EXIT_FAILURE; /* Block must be used */
}
block->block_state = FL_FREE;
block->next = fl->free;
fl->free = block;
fl->allocated--;
return EXIT_SUCCESS;
}
/* Returns how many slots are occupied */
size_t fl_allocated(FreeList *fl) {
return fl->allocated;
}
/* Returns how many free slots are available (O(1)) */
size_t fl_available(FreeList *fl) {
return fl_capacity(fl) - fl->allocated;
}
/* Returns the total amount of items the freelist will hold */
size_t fl_capacity(FreeList *fl) {
return (fl->end - fl->start) / fl->size;
}
/* Check if a piece of memory is managed by the FreeList */
int fl_is_managed(FreeList *fl, void *ptr) {
return ((uintptr_t)ptr >= fl->start && (uintptr_t)ptr < fl->end);
}
/* Returns the ratio of metadata versus data as a scalar in range 0..1 */
float fl_utilization(FreeList *fl, size_t itemsize) {
return (float)itemsize / fl->size;
}
/* Walks the free pages/slots, returns total count (O(n), given no cycles) */
size_t fl_check(FreeList *fl) {
int avail = 0;
FreeListBlock *cursor = fl->free;
while (cursor->next != NULL) {
avail++;
assert(cursor->block_state == FL_FREE);
cursor = cursor->next;
}
return avail;
}

34
kern/libkern/freelist.h Normal file
View file

@ -0,0 +1,34 @@
#ifndef FREELIST_H
#define FREELIST_H
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#define FL_FREE ((uint8_t)0x00)
#define FL_USED ((uint8_t)0x01)
typedef struct FreeListBlock {
struct FreeListBlock *next;
uint8_t block_state;
} FreeListBlock;
typedef struct {
uintptr_t start;
uintptr_t end;
FreeListBlock *free;
size_t size;
size_t allocated;
} FreeList;
int fl_init(FreeList *fl, uintptr_t start, uintptr_t end, size_t itemsize);
int fl_free(FreeList *fl, void *ptr);
int fl_is_managed(FreeList *fl, void *ptr);
void *fl_alloc(FreeList *fl);
size_t fl_check(FreeList *fl);
size_t fl_allocated(FreeList *fl);
size_t fl_available(FreeList *fl);
size_t fl_capacity(FreeList *fl);
float fl_utilization(FreeList *fl, size_t itemsize);
#endif // FREELIST_H

View file

@ -178,3 +178,20 @@ size_t strnlen(const char *s, size_t maxlen) {
}
return len;
}
int strncmp(const char *p, const char *q, u32 n) {
while (n > 0 && *p && *p == *q) n--, p++, q++;
if (n == 0)
return 0;
return (u8)*p - (u8)*q;
}
char *strncpy(char *s, const char *t, int n) {
char *os;
os = s;
while (n-- > 0 && (*s++ = *t++) != 0) {
}
while (n-- > 0) *s++ = 0;
return os;
}

View file

@ -31,13 +31,14 @@ size_t strlen(const char *s);
/** Return length of string `s`, up to a max of `maxlen` bytes */
size_t strnlen(const char *s, size_t maxlen);
int strncmp(const char *p, const char *q, u32 n);
char *strncpy(char *s, const char *t, int n);
// TODO: These:
/*
int strcmp(const char *s1, const char *s2);
int strncmp(const char *s1, const char *s2, size_t n);
char *strcpy(char *dst, const char *src);
char *strncpy(char *dst, const char *src, size_t n);
char *strchr(const char *s, int c);
char *strrchr(const char *s, int c);

View file

@ -4,6 +4,7 @@
/*
* Give hints to the compiler for branch prediction optimization.
*/
#include <stdint.h>
#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 2))
#define likely(c) (__builtin_expect(!!(c), 1))
#define unlikely(c) (__builtin_expect(!!(c), 0))
@ -12,4 +13,16 @@
#define unlikely(c) (c)
#endif
/* Round up to nearest power of two */
static inline uint32_t next_power_of_two(uint32_t v) {
/* See: https://graphics.stanford.edu/%7Eseander/bithacks.html#RoundUpPowerOf2 */
v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
return ++v;
}
#endif // UTIL_H

View file

@ -0,0 +1,23 @@
The xv6 software is:
Copyright (c) 2006-2024 Frans Kaashoek, Robert Morris, Russ Cox,
Massachusetts Institute of Technology
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.