mirror of
https://github.com/subhobhai943/SUB-OS.git
synced 2026-10-25 16:52:29 +00:00
feat(kernel): Add RB-tree/kfifo/hashtable, wait queues, futex, tiny RCU, page cache and KTest harness
Expands the kernel-and-TTY core with the primitives the higher layers have
been missing, plus an in-kernel harness that proves they work.
Data structures (lib/):
- rbtree.c: Linux-compatible red-black tree with parent pointers, full
insert/erase rebalancing, in-order iteration and an invariant validator.
- kfifo.c: power-of-two byte ring with free-running indices, so the wrap
path costs one mask instead of a branch per byte.
- hashtable.c: separately-chained table with FNV-1a hashing, string or
u64 keys, and rehash-on-growth at a 3/4 load factor.
Kernel subsystems:
- kernel/wait.c: wait queues and one-shot completion barriers, backed by a
static sleeper pool so a blocking path never re-enters the allocator.
- kernel/futex.c: 32-bucket futex hash with value re-check, requeue, and an
fmutex_t sleeping mutex built on the uncontended-fastpath protocol.
- kernel/rcu.c: tiny RCU with reader nesting, deferred callbacks, kfree_rcu
and rcu_assign_pointer/rcu_dereference publish barriers.
- mm/page_cache.c: write-back block page cache, 4 KB pages indexed by
(device, page), CLOCK second-chance eviction and dirty write-back.
- kernel/ktest.c: KUnit-style harness with 6 built-in suites, 21 cases and
735 assertions covering every subsystem above (all passing under QEMU).
LazyBox userland:
- coreutils.c: sort, uniq, cut, tr, rev, tac, nl, seq, diff, xxd, du,
factor, sum and truncate, reading through the VFS and handling the
zero-length synthetic nodes that procfs and sysfs expose.
- ktest, rcuinfo, futexinfo, waitinfo and pagecache diagnostics applets.
Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01L5yKJT4Wo2cV3rfPrwY5MP
This commit is contained in:
1 parent
492045b24d
commit
f9400f6ac4
22 files changed
+3631
-5
No files matched your search
@@ -0,0 +1,50 @@
|
||||
#ifndef _LIB_HASHTABLE_H
|
||||
#define _LIB_HASHTABLE_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
// Separately-chained hash table with FNV-1a hashing and automatic growth.
|
||||
// Keys are either NUL-terminated strings (owned copies) or raw 64-bit ids.
|
||||
|
||||
typedef struct hnode {
|
||||
uint64_t hash;
|
||||
char* skey; // NULL for integer-keyed entries
|
||||
uint64_t ikey;
|
||||
void* value;
|
||||
struct hnode* next;
|
||||
} hnode_t;
|
||||
|
||||
typedef struct hashtable {
|
||||
hnode_t** buckets;
|
||||
size_t bucket_count;
|
||||
size_t entries;
|
||||
size_t collisions;
|
||||
bool string_keys;
|
||||
} hashtable_t;
|
||||
|
||||
uint64_t hash_fnv1a(const void* data, size_t len);
|
||||
uint64_t hash_string(const char* s);
|
||||
uint64_t hash_u64(uint64_t v);
|
||||
|
||||
hashtable_t* hashtable_create(size_t initial_buckets, bool string_keys);
|
||||
void hashtable_destroy(hashtable_t* ht);
|
||||
|
||||
int hashtable_put(hashtable_t* ht, const char* key, void* value);
|
||||
void* hashtable_get(const hashtable_t* ht, const char* key);
|
||||
bool hashtable_remove(hashtable_t* ht, const char* key);
|
||||
|
||||
int hashtable_put_u64(hashtable_t* ht, uint64_t key, void* value);
|
||||
void* hashtable_get_u64(const hashtable_t* ht, uint64_t key);
|
||||
bool hashtable_remove_u64(hashtable_t* ht, uint64_t key);
|
||||
|
||||
size_t hashtable_size(const hashtable_t* ht);
|
||||
size_t hashtable_buckets(const hashtable_t* ht);
|
||||
size_t hashtable_collisions(const hashtable_t* ht);
|
||||
size_t hashtable_longest_chain(const hashtable_t* ht);
|
||||
|
||||
typedef void (*hashtable_iter_fn)(const hnode_t* node, void* ctx);
|
||||
void hashtable_foreach(const hashtable_t* ht, hashtable_iter_fn fn, void* ctx);
|
||||
|
||||
#endif // _LIB_HASHTABLE_H
|
||||
@@ -0,0 +1,40 @@
|
||||
#ifndef _LIB_KFIFO_H
|
||||
#define _LIB_KFIFO_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <kernel/sync.h>
|
||||
|
||||
// Power-of-two byte ring buffer with an unsigned index-wrap discipline,
|
||||
// mirroring the classic Linux kfifo. Producer and consumer indices are
|
||||
// free-running; masking happens only at access time.
|
||||
|
||||
typedef struct kfifo {
|
||||
uint8_t* buffer;
|
||||
size_t size; // Always a power of two
|
||||
size_t mask; // size - 1
|
||||
size_t in; // Free-running producer index
|
||||
size_t out; // Free-running consumer index
|
||||
bool owns_buffer;
|
||||
spinlock_t lock;
|
||||
} kfifo_t;
|
||||
|
||||
int kfifo_alloc(kfifo_t* fifo, size_t size);
|
||||
int kfifo_init_static(kfifo_t* fifo, void* buffer, size_t size);
|
||||
void kfifo_free(kfifo_t* fifo);
|
||||
void kfifo_reset(kfifo_t* fifo);
|
||||
|
||||
size_t kfifo_in(kfifo_t* fifo, const void* src, size_t len);
|
||||
size_t kfifo_out(kfifo_t* fifo, void* dst, size_t len);
|
||||
size_t kfifo_peek(const kfifo_t* fifo, void* dst, size_t len);
|
||||
|
||||
size_t kfifo_len(const kfifo_t* fifo);
|
||||
size_t kfifo_avail(const kfifo_t* fifo);
|
||||
bool kfifo_is_empty(const kfifo_t* fifo);
|
||||
bool kfifo_is_full(const kfifo_t* fifo);
|
||||
|
||||
int kfifo_put_byte(kfifo_t* fifo, uint8_t byte);
|
||||
int kfifo_get_byte(kfifo_t* fifo, uint8_t* byte_out);
|
||||
|
||||
#endif // _LIB_KFIFO_H
|
||||
@@ -0,0 +1,63 @@
|
||||
#ifndef _LIB_RBTREE_H
|
||||
#define _LIB_RBTREE_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
// Linux-style Red-Black Tree: O(log n) ordered container used by the
|
||||
// CFS-style scheduler index, VMA lookup and the page cache radix index.
|
||||
|
||||
#define RB_RED 0
|
||||
#define RB_BLACK 1
|
||||
|
||||
struct rb_node {
|
||||
struct rb_node* rb_parent;
|
||||
struct rb_node* rb_left;
|
||||
struct rb_node* rb_right;
|
||||
int rb_color;
|
||||
};
|
||||
|
||||
struct rb_root {
|
||||
struct rb_node* rb_node;
|
||||
};
|
||||
|
||||
#define RB_ROOT_INIT { NULL }
|
||||
|
||||
#define rb_entry(ptr, type, member) \
|
||||
((type*)((char*)(ptr) - offsetof(type, member)))
|
||||
|
||||
static inline void rb_root_init(struct rb_root* root) {
|
||||
root->rb_node = NULL;
|
||||
}
|
||||
|
||||
static inline bool rb_empty(const struct rb_root* root) {
|
||||
return root->rb_node == NULL;
|
||||
}
|
||||
|
||||
// Attach a freshly allocated node into the tree, then recolour.
|
||||
static inline void rb_link_node(struct rb_node* node, struct rb_node* parent,
|
||||
struct rb_node** rb_link) {
|
||||
node->rb_parent = parent;
|
||||
node->rb_color = RB_RED;
|
||||
node->rb_left = NULL;
|
||||
node->rb_right = NULL;
|
||||
*rb_link = node;
|
||||
}
|
||||
|
||||
void rb_insert_color(struct rb_node* node, struct rb_root* root);
|
||||
void rb_erase(struct rb_node* node, struct rb_root* root);
|
||||
|
||||
struct rb_node* rb_first(const struct rb_root* root);
|
||||
struct rb_node* rb_last(const struct rb_root* root);
|
||||
struct rb_node* rb_next(const struct rb_node* node);
|
||||
struct rb_node* rb_prev(const struct rb_node* node);
|
||||
|
||||
size_t rb_count(const struct rb_root* root);
|
||||
int rb_black_height(const struct rb_root* root);
|
||||
bool rb_validate(const struct rb_root* root);
|
||||
|
||||
#define rb_for_each(pos, root) \
|
||||
for (pos = rb_first(root); pos != NULL; pos = rb_next(pos))
|
||||
|
||||
#endif // _LIB_RBTREE_H
|
||||
Reference in new issue
Block a user