From fc9b279c9984af18815b683ddb85c3d97d081bfd Mon Sep 17 00:00:00 2001 From: Aleksander Kaminski Date: Wed, 11 Sep 2024 17:18:05 +0200 Subject: [PATCH 1/4] lib: Fix void * arithmetic JIRA: RTOS-373 --- lib/idtree.h | 2 +- lib/rb.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/idtree.h b/lib/idtree.h index 49b13191f..697a3b108 100644 --- a/lib/idtree.h +++ b/lib/idtree.h @@ -35,7 +35,7 @@ typedef struct { #define lib_idtreeof(type, node_field, node) ({ \ long _off = (long)&(((type *)0)->node_field); \ idnode_t *tmpnode = (node); \ - (type *)((tmpnode == NULL) ? NULL : ((void *)tmpnode - _off)); \ + (type *)((tmpnode == NULL) ? NULL : ((char *)tmpnode - _off)); \ }) diff --git a/lib/rb.h b/lib/rb.h index 0c7ecdab6..5066858fb 100644 --- a/lib/rb.h +++ b/lib/rb.h @@ -20,7 +20,7 @@ #define lib_treeof(type, node_field, node) ({ \ long _off = (long)&(((type *)0)->node_field); \ rbnode_t *tmpnode = (node); \ - (type *)((tmpnode == NULL) ? NULL : ((void *)tmpnode - _off)); \ + (type *)((tmpnode == NULL) ? NULL : ((char *)tmpnode - _off)); \ }) From ee1f7e3c02a5989ef0ee5249d665ae9dc626098d Mon Sep 17 00:00:00 2001 From: Aleksander Kaminski Date: Wed, 11 Sep 2024 17:18:57 +0200 Subject: [PATCH 2/4] lib: Add binary heap implementation JIRA: RTOS-917 --- lib/Makefile | 3 +- lib/bheap.c | 344 +++++++++++++++++++++++++++++++++++++++++++++++++++ lib/bheap.h | 65 ++++++++++ lib/lib.h | 1 + 4 files changed, 412 insertions(+), 1 deletion(-) create mode 100644 lib/bheap.c create mode 100644 lib/bheap.h diff --git a/lib/Makefile b/lib/Makefile index de858b25d..1401e958b 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -5,5 +5,6 @@ # Author: Pawel Pisarczyk # -OBJS += $(addprefix $(PREFIX_O)lib/, assert.o printf.o bsearch.o rand.o strtoul.o rb.o list.o cbuffer.o strutil.o idtree.o) +OBJS += $(addprefix $(PREFIX_O)lib/, assert.o printf.o bsearch.o rand.o strtoul.o \ + rb.o list.o cbuffer.o strutil.o idtree.o bheap.o) diff --git a/lib/bheap.c b/lib/bheap.c new file mode 100644 index 000000000..087d50726 --- /dev/null +++ b/lib/bheap.c @@ -0,0 +1,344 @@ +/* + * Phoenix-RTOS + * + * Operating system kernel + * + * Min/max binary heap + * + * Copyright 2017, 2024 Phoenix Systems + * Author: Jakub Sejdak, Aleksander Kaminski + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + + +#include "hal/hal.h" +#include "include/errno.h" +#include "lib.h" + + +static void lib_bhSwapPtr(bhnode_t **p1, bhnode_t **p2) +{ + bhnode_t *t = *p1; + *p1 = *p2; + *p2 = t; +} + + +static void lib_bhAttachChildren(bhnode_t *node) +{ + if (node->left != NULL) { + node->left->parent = node; + } + if (node->right != NULL) { + node->right->parent = node; + } +} + + +static void lib_bhSwap(bheap_t *heap, bhnode_t *n1, bhnode_t *n2) +{ + /* Turn two symmetrical edge cases into one */ + if (n2->parent == n1) { + lib_bhSwapPtr(&n1, &n2); + } + + /* Swap all linkages */ + lib_bhSwapPtr(&n1->left, &n2->left); + lib_bhSwapPtr(&n1->right, &n2->right); + lib_bhSwapPtr(&n1->parent, &n2->parent); + + /* Handle parent-child edge case */ + if (n2->parent == n2) { + n2->parent = n1; + + if (n1->left == n1) { + n1->left = n2; + } + else { + n1->right = n2; + } + } + + /* Handle siblings edge case or fix parents */ + if (n1->parent == n2->parent) { + lib_bhSwapPtr(&n1->parent->left, &n2->parent->right); + } + else { + if (n1->parent != NULL) { + if (n1->parent->left == n2) { + n1->parent->left = n1; + } + else if (n1->parent->right == n2) { + n1->parent->right = n1; + } + } + + if (n2->parent != NULL) { + if (n2->parent->left == n1) { + n2->parent->left = n2; + } + else if (n2->parent->right == n2) { + n2->parent->right = n2; + } + } + } + + /* Set children parent */ + lib_bhAttachChildren(n1); + lib_bhAttachChildren(n2); + + /* Fix global pointers */ + if (heap->root == n1) { + heap->root = n2; + } + else if (heap->root == n2) { + heap->root = n1; + } + + if (heap->tail == n1) { + heap->tail = n2; + } + else if (heap->tail == n2) { + heap->tail = n1; + } +} + + +static void lib_bhHeapify(bheap_t *heap, bhnode_t *node) +{ + bhnode_t *parent = node->parent, *n = node; + + while ((parent != NULL) && (heap->comp(n, parent) > 0)) { + lib_bhSwap(heap, n, parent); + parent = n->parent; + } +} + + +static void lib_bhRevHeapify(bheap_t *heap, bhnode_t *node) +{ + bhnode_t *n = node, *min; + + while ((n != NULL) && (n->left != NULL)) { + min = n->left; + if ((n->right != NULL) && (heap->comp(n->right, min) > 0)) { + min = n->right; + } + if (heap->comp(n, min) >= 0) { + break; + } + + lib_bhSwap(heap, n, min); + } +} + + +static void lib_bhNextTail(bheap_t *heap) +{ + bhnode_t *t = heap->tail; + + for (;;) { + if (t->parent == NULL) { + heap->tail = t; + while (heap->tail->left != NULL) { + heap->tail = heap->tail->left; + } + break; + } + else if (t->parent->left == t) { + heap->tail = t->parent->right; + while (heap->tail->left != NULL) { + heap->tail = heap->tail->left; + } + break; + } + + t = t->parent; + } +} + + +static bhnode_t *lib_bhPrevTail(bheap_t *heap) +{ + bhnode_t *prev = heap->tail; + + while ((prev->parent != NULL) && (prev->parent->left == prev)) { + prev = prev->parent; + } + + if (prev->parent != NULL) { + prev = prev->parent->left; + } + + while (prev->right != NULL) { + prev = prev->right; + } + + return prev; +} + + +void lib_bhInsert(bheap_t *heap, bhnode_t *node) +{ + if (heap->root == NULL) { + heap->root = node; + heap->tail = node; + node->parent = NULL; + node->left = NULL; + node->right = NULL; + } + else if (heap->tail->left == NULL) { + heap->tail->left = node; + node->parent = heap->tail; + node->left = NULL; + node->right = NULL; + lib_bhHeapify(heap, node); + } + else { + heap->tail->right = node; + node->parent = heap->tail; + node->left = NULL; + node->right = NULL; + lib_bhHeapify(heap, node); + lib_bhNextTail(heap); + } +} + + +void lib_bhRemove(bheap_t *heap, bhnode_t *node) +{ + bhnode_t *prev, *swap; + + for (;;) { + if (heap->tail->right != NULL) { + if (heap->tail->right == node) { + heap->tail->right = NULL; + break; + } + + swap = heap->tail->right; + lib_bhSwap(heap, swap, node); + heap->tail->right = NULL; + + if (heap->comp(node, swap) < 0) { + lib_bhHeapify(heap, swap); + } + else { + lib_bhRevHeapify(heap, swap); + } + break; + } + else if (heap->tail->left != NULL) { + if (heap->tail->left == node) { + heap->tail->left = NULL; + break; + } + + swap = heap->tail->left; + lib_bhSwap(heap, swap, node); + heap->tail->left = NULL; + + if (heap->comp(node, swap) < 0) { + lib_bhHeapify(heap, swap); + } + else { + lib_bhRevHeapify(heap, swap); + } + break; + } + else if (heap->tail == heap->root) { + heap->tail = NULL; + heap->root = NULL; + break; + } + + prev = lib_bhPrevTail(heap); + + if ((prev->left == NULL) && (prev->right == NULL)) { + /* Special case - current tail is actually the newest node */ + heap->tail = prev->parent; + } + else { + heap->tail = prev; + } + } +} + + +bhnode_t *lib_bhPop(bheap_t *heap) +{ + bhnode_t *ret = heap->root; + + if (heap->root != NULL) { + lib_bhRemove(heap, heap->root); + } + + return ret; +} + + +bhnode_t *lib_bhPeek(bheap_t *heap) +{ + return heap->root; +} + + +#define BH_DUMP_DEPTH 16 + + +static void lib_bhDumpEx(bhnode_t *node, bhdump_t dump, unsigned int *depth, unsigned char d[BH_DUMP_DEPTH]) +{ + unsigned int i; + + for (i = 0; i < *depth; i++) { + lib_printf("%c ", d[i] ? '|' : ' '); + } + + if (node == NULL) { + lib_printf("%s() *\n", *depth ? "`-" : ""); + return; + } + + lib_printf("%s(", *depth ? "`-" : ""); + dump(node); + lib_printf(")\n"); + + (*depth)++; + if ((node->left != NULL) || (node->right != NULL)) { + if (*depth < BH_DUMP_DEPTH) { + d[*depth] = 1; + lib_bhDumpEx(node->left, dump, depth, d); + d[*depth] = 0; + lib_bhDumpEx(node->right, dump, depth, d); + } + else { + for (i = 0; i < *depth; i++) { + lib_printf("%c ", d[i] ? '|' : ' '); + } + + lib_printf("%s(..)\n", *depth ? "`-" : ""); + } + } + (*depth)--; +} + + +void lib_bhDump(bhnode_t *node, bhdump_t dump) +{ + unsigned int depth = 0; + unsigned char d[BH_DUMP_DEPTH]; + + hal_memset(d, 0, BH_DUMP_DEPTH); + lib_bhDumpEx(node, dump, &depth, d); +} + + +void lib_bhInit(bheap_t *heap, bhcomp_t compare) +{ + heap->root = NULL; + heap->tail = NULL; + heap->comp = compare; +} diff --git a/lib/bheap.h b/lib/bheap.h new file mode 100644 index 000000000..1ef0aca9b --- /dev/null +++ b/lib/bheap.h @@ -0,0 +1,65 @@ +/* + * Phoenix-RTOS + * + * Operating system kernel + * + * Min/max binary heap + * + * Copyright 2024 Phoenix Systems + * Author: Aleksander Kaminski + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#ifndef _PHOENIX_BHEAP_H_ +#define _PHOENIX_BHEAP_H_ + + +typedef struct _bhnode_t { + struct _bhnode_t *parent; + struct _bhnode_t *left; + struct _bhnode_t *right; +} bhnode_t; + + +#define lib_bhof(type, nodeField, node) ({ \ + long _off = (long)&(((type *)0)->nodeField); \ + bhnode_t *tmpnode = (node); \ + (type *)((tmpnode == NULL) ? NULL : ((char *)tmpnode - _off)); \ +}) + + +typedef int (*bhcomp_t)(bhnode_t *n1, bhnode_t *n2); + + +typedef void (*bhdump_t)(bhnode_t *node); + + +typedef struct { + bhnode_t *root; + bhnode_t *tail; + bhcomp_t comp; +} bheap_t; + + +void lib_bhInsert(bheap_t *heap, bhnode_t *node); + + +void lib_bhRemove(bheap_t *heap, bhnode_t *node); + + +bhnode_t *lib_bhPop(bheap_t *heap); + + +bhnode_t *lib_bhPeek(bheap_t *heap); + + +void lib_bhDump(bhnode_t *node, bhdump_t dump); + + +void lib_bhInit(bheap_t *heap, bhcomp_t compare); + + +#endif diff --git a/lib/lib.h b/lib/lib.h index 1b20d00d2..5e7e14557 100644 --- a/lib/lib.h +++ b/lib/lib.h @@ -27,6 +27,7 @@ #include "assert.h" #include "strutil.h" #include "idtree.h" +#include "bheap.h" #define lib_atomicIncrement(ptr) __atomic_add_fetch(ptr, 1, __ATOMIC_RELAXED) From 4a2e055a3fcd574f2271d4a67e27bc3418646e63 Mon Sep 17 00:00:00 2001 From: Aleksander Kaminski Date: Wed, 11 Sep 2024 17:19:18 +0200 Subject: [PATCH 3/4] threads: Use binary heap for sleeping threads data structure JIRA: RTOS-917 --- proc/threads.c | 63 +++++++++++++++++++++++++------------------------- proc/threads.h | 2 +- 2 files changed, 32 insertions(+), 33 deletions(-) diff --git a/proc/threads.c b/proc/threads.c index 1b9280c9d..697a79ae9 100644 --- a/proc/threads.c +++ b/proc/threads.c @@ -40,7 +40,7 @@ struct { time_t utcoffs; /* Synchronized by spinlock */ - rbtree_t sleeping; + bheap_t sleeping; /* Synchronized by mutex */ unsigned int idcounter; @@ -83,17 +83,16 @@ static time_t _proc_gettimeRaw(void) } -static int threads_sleepcmp(rbnode_t *n1, rbnode_t *n2) +static int threads_sleepcmp(bhnode_t *n1, bhnode_t *n2) { - thread_t *t1 = lib_treeof(thread_t, sleeplinkage, n1); - thread_t *t2 = lib_treeof(thread_t, sleeplinkage, n2); + thread_t *t1 = lib_bhof(thread_t, sleeplinkage, n1); + thread_t *t2 = lib_bhof(thread_t, sleeplinkage, n2); - if (t1->wakeup != t2->wakeup) { - return (t1->wakeup > t2->wakeup) ? 1 : -1; - } - else { - return (proc_getTid(t1) > proc_getTid(t2)) ? 1 : -1; + if (t1->wakeup == t2->wakeup) { + return 0; } + + return (t1->wakeup < t2->wakeup) ? 1 : -1; } /* @@ -395,28 +394,26 @@ int perf_finish() */ -static void _threads_updateWakeup(time_t now, thread_t *min) +static void _threads_updateWakeup(time_t now) { - thread_t *t; + thread_t *t = lib_bhof(thread_t, sleeplinkage, lib_bhPeek(&threads_common.sleeping)); time_t wakeup; - if (min != NULL) - t = min; - else - t = lib_treeof(thread_t, sleeplinkage, lib_rbMinimum(threads_common.sleeping.root)); - if (t != NULL) { - if (now >= t->wakeup) + if (now >= t->wakeup) { wakeup = 1; - else + } + else { wakeup = t->wakeup - now; + } } else { wakeup = SYSTICK_INTERVAL; } - if (wakeup > SYSTICK_INTERVAL + SYSTICK_INTERVAL / 8) + if (wakeup > SYSTICK_INTERVAL + SYSTICK_INTERVAL / 8) { wakeup = SYSTICK_INTERVAL; + } hal_timerSetWakeup(wakeup); } @@ -437,9 +434,9 @@ int threads_timeintr(unsigned int n, cpu_context_t *context, void *arg) now = _proc_gettimeRaw(); for (;;) { - t = lib_treeof(thread_t, sleeplinkage, lib_rbMinimum(threads_common.sleeping.root)); + t = lib_bhof(thread_t, sleeplinkage, lib_bhPeek(&threads_common.sleeping)); - if (t == NULL || t->wakeup > now) { + if ((t == NULL) || (t->wakeup > now)) { break; } @@ -447,7 +444,7 @@ int threads_timeintr(unsigned int n, cpu_context_t *context, void *arg) hal_cpuSetReturnValue(t->context, (void *)-ETIME); } - _threads_updateWakeup(now, t); + _threads_updateWakeup(now); hal_spinlockClear(&threads_common.spinlock, &sc); @@ -1047,8 +1044,8 @@ static void _proc_threadDequeue(thread_t *t) LIST_REMOVE(t->wait, t); } - if (t->wakeup) { - lib_rbRemove(&threads_common.sleeping, &t->sleeplinkage); + if (t->wakeup != 0) { + lib_bhRemove(&threads_common.sleeping, &t->sleeplinkage); } t->wakeup = 0; @@ -1089,8 +1086,8 @@ static void _proc_threadEnqueue(thread_t **queue, time_t timeout, int interrupti if (timeout) { current->wakeup = timeout; - lib_rbInsert(&threads_common.sleeping, ¤t->sleeplinkage); - _threads_updateWakeup(_proc_gettimeRaw(), NULL); + lib_bhInsert(&threads_common.sleeping, ¤t->sleeplinkage); + _threads_updateWakeup(_proc_gettimeRaw()); } _perf_enqueued(current); @@ -1132,10 +1129,10 @@ int proc_threadSleep(time_t us) current->wakeup = now + us; current->interruptible = 1; - lib_rbInsert(&threads_common.sleeping, ¤t->sleeplinkage); + lib_bhInsert(&threads_common.sleeping, ¤t->sleeplinkage); _perf_enqueued(current); - _threads_updateWakeup(now, NULL); + _threads_updateWakeup(now); } err = hal_cpuReschedule(&threads_common.spinlock, &sc); @@ -1377,13 +1374,15 @@ static time_t _proc_nextWakeup(void) time_t wakeup = 0; time_t now; - thread = lib_treeof(thread_t, sleeplinkage, lib_rbMinimum(threads_common.sleeping.root)); + thread = lib_bhof(thread_t, sleeplinkage, lib_bhPeek(&threads_common.sleeping)); if (thread != NULL) { now = _proc_gettimeRaw(); - if (now >= thread->wakeup) + if (now >= thread->wakeup) { wakeup = 0; - else + } + else { wakeup = thread->wakeup - now; + } } return wakeup; @@ -2042,7 +2041,7 @@ int _threads_init(vm_map_t *kmap, vm_object_t *kernel) for (i = 0; i < sizeof(threads_common.ready) / sizeof(thread_t *); i++) threads_common.ready[i] = NULL; - lib_rbInit(&threads_common.sleeping, threads_sleepcmp, NULL); + lib_bhInit(&threads_common.sleeping, threads_sleepcmp); lib_idtreeInit(&threads_common.id); lib_printf("proc: Initializing thread scheduler, priorities=%d\n", sizeof(threads_common.ready) / sizeof(thread_t *)); diff --git a/proc/threads.h b/proc/threads.h index f98206f7b..3dda113af 100644 --- a/proc/threads.h +++ b/proc/threads.h @@ -41,7 +41,7 @@ typedef struct _thread_t { struct _thread_t *prev; struct _lock_t *locks; - rbnode_t sleeplinkage; + bhnode_t sleeplinkage; idnode_t idlinkage; struct _process_t *process; From 889e50222d9b0823f99dfbe24e336745721c8993 Mon Sep 17 00:00:00 2001 From: Aleksander Kaminski Date: Thu, 12 Sep 2024 11:55:41 +0200 Subject: [PATCH 4/4] test: Add binary heap test JIRA: RTOS-917 --- test/Makefile | 2 +- test/bheap.c | 240 ++++++++++++++++++++++++++++++++++++++++++++++++++ test/bheap.h | 24 +++++ test/test.h | 7 +- 4 files changed, 270 insertions(+), 3 deletions(-) create mode 100644 test/bheap.c create mode 100644 test/bheap.h diff --git a/test/Makefile b/test/Makefile index 56a2fb88f..9c833046b 100644 --- a/test/Makefile +++ b/test/Makefile @@ -5,5 +5,5 @@ # Author: Pawel Pisarczyk # -OBJS += $(addprefix $(PREFIX_O)test/, test.o vm.o rb.o proc.o msg.o) +OBJS += $(addprefix $(PREFIX_O)test/, test.o vm.o rb.o proc.o msg.o bheap.o) diff --git a/test/bheap.c b/test/bheap.c new file mode 100644 index 000000000..9e796ec9b --- /dev/null +++ b/test/bheap.c @@ -0,0 +1,240 @@ +/* + * Phoenix-RTOS + * + * Operating system kernel + * + * Min/max binary heap test + * + * Copyright 2024 Phoenix Systems + * Author: Aleksander Kaminski + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#include "hal/hal.h" +#include "lib/lib.h" +#include "proc/proc.h" +#include "vm/vm.h" + +#define NODE_CNT 50 + + +typedef struct _test_data_t { + bhnode_t linkage; + struct _test_data_t *prev; + struct _test_data_t *next; + int key; +} test_data_t; + + +static struct { + bheap_t heap; + test_data_t *list; +} test_bhCommon; + + +static int test_bhCompare(bhnode_t *n1, bhnode_t *n2) +{ + test_data_t *d1 = lib_bhof(test_data_t, linkage, n1); + test_data_t *d2 = lib_bhof(test_data_t, linkage, n2); + + return d2->key - d1->key; +} + + +static int test_bhCheckCondition(bhnode_t *node) +{ + if (node == NULL) { + return 0; + } + + if (node->left != NULL) { + if (test_bhCompare(node, node->left) < 0) { + return -1; + } + + if (test_bhCheckCondition(node->left) < 0) { + return -1; + } + } + + if (node->right != NULL) { + if (test_bhCompare(node, node->right) < 0) { + return -1; + } + + if (test_bhCheckCondition(node->right) < 0) { + return -1; + } + } + + return 0; +} + + +static int test_bhAddNode(int key) +{ + test_data_t *data = vm_kmalloc(sizeof(*data)); + if (data == NULL) { + return -1; + } + + data->key = key; + lib_bhInsert(&test_bhCommon.heap, &data->linkage); + LIST_ADD(&test_bhCommon.list, data); + + return 0; +} + + +static int test_bhRemoveNode(int key) +{ + test_data_t *curr = test_bhCommon.list; + + if (curr == NULL) { + return -1; + } + + do { + if (curr->key == key) { + LIST_REMOVE(&test_bhCommon.list, curr); + lib_bhRemove(&test_bhCommon.heap, &curr->linkage); + vm_kfree(curr); + return 0; + } + curr = curr->next; + } while (curr != test_bhCommon.list); + + return -1; +} + + +static void test_bhDump(bhnode_t *node) +{ + test_data_t *data = lib_bhof(test_data_t, linkage, node); + + lib_printf("%d", data->key); +} + + +void test_bh(void) +{ + int i; + unsigned int seed = 5318008; + + lib_bhInit(&test_bhCommon.heap, test_bhCompare); + + lib_printf("test bh: Adding nodes ascending order\n"); + for (i = 0; i < NODE_CNT; ++i) { + if (test_bhAddNode(i) < 0) { + lib_printf("test bh: node add fail\n"); + } + if (test_bhCheckCondition(test_bhCommon.heap.root) < 0) { + lib_printf("test bh: Heap is damaged!\n"); + lib_bhDump(test_bhCommon.heap.root, test_bhDump); + return; + } + } + + lib_bhDump(test_bhCommon.heap.root, test_bhDump); + + lib_printf("test bh: Removing nodes ascending order\n"); + for (i = 0; i < NODE_CNT; ++i) { + if (test_bhRemoveNode(i) < 0) { + lib_printf("test bh: node remove fail\n"); + } + if (test_bhCheckCondition(test_bhCommon.heap.root) < 0) { + lib_printf("test bh: Heap is damaged!\n"); + lib_bhDump(test_bhCommon.heap.root, test_bhDump); + return; + } + } + + lib_bhDump(test_bhCommon.heap.root, test_bhDump); + + lib_printf("test bh: Adding nodes decreasing order\n"); + for (i = NODE_CNT - 1; i >= 0; --i) { + if (test_bhAddNode(i) < 0) { + lib_printf("test bh: node add fail\n"); + } + if (test_bhCheckCondition(test_bhCommon.heap.root) < 0) { + lib_printf("test bh: Heap is damaged!\n"); + lib_bhDump(test_bhCommon.heap.root, test_bhDump); + return; + } + } + + lib_bhDump(test_bhCommon.heap.root, test_bhDump); + + lib_printf("test bh: Removing nodes decreasing order\n"); + for (i = NODE_CNT - 1; i >= 0; --i) { + if (test_bhRemoveNode(i) < 0) { + lib_printf("test bh: node remove fail\n"); + } + if (test_bhCheckCondition(test_bhCommon.heap.root) < 0) { + lib_printf("test bh: Heap is damaged!\n"); + lib_bhDump(test_bhCommon.heap.root, test_bhDump); + return; + } + } + + lib_bhDump(test_bhCommon.heap.root, test_bhDump); + + lib_printf("test bh: Adding pseudo-random keys\n"); + for (i = 0; i < NODE_CNT; ++i) { + if (test_bhAddNode(lib_rand(&seed) % 32768) < 0) { + lib_printf("test bh: node add fail\n"); + } + if (test_bhCheckCondition(test_bhCommon.heap.root) < 0) { + lib_printf("test bh: Heap is damaged!\n"); + lib_bhDump(test_bhCommon.heap.root, test_bhDump); + return; + } + } + + lib_bhDump(test_bhCommon.heap.root, test_bhDump); + + lib_printf("test bh: Removing pseudo-random keys\n"); + while (test_bhCommon.list != NULL) { + if (test_bhRemoveNode(test_bhCommon.list->key) < 0) { + lib_printf("test bh: node remove fail\n"); + } + if (test_bhCheckCondition(test_bhCommon.heap.root) < 0) { + lib_printf("test bh: Heap is damaged!\n"); + lib_bhDump(test_bhCommon.heap.root, test_bhDump); + return; + } + } + + lib_bhDump(test_bhCommon.heap.root, test_bhDump); + + lib_printf("test bh: Adding identical key\n"); + for (i = NODE_CNT - 1; i >= 0; --i) { + if (test_bhAddNode(420) < 0) { + lib_printf("test bh: node add fail\n"); + } + if (test_bhCheckCondition(test_bhCommon.heap.root) < 0) { + lib_printf("test bh: Heap is damaged!\n"); + lib_bhDump(test_bhCommon.heap.root, test_bhDump); + return; + } + } + + lib_bhDump(test_bhCommon.heap.root, test_bhDump); + + lib_printf("test bh: cleanup\n"); + for (i = NODE_CNT - 1; i >= 0; --i) { + if (test_bhRemoveNode(420) < 0) { + lib_printf("test bh: node remove fail\n"); + } + if (test_bhCheckCondition(test_bhCommon.heap.root) < 0) { + lib_printf("test bh: Heap is damaged!\n"); + lib_bhDump(test_bhCommon.heap.root, test_bhDump); + return; + } + } + + lib_bhDump(test_bhCommon.heap.root, test_bhDump); +} diff --git a/test/bheap.h b/test/bheap.h new file mode 100644 index 000000000..c60c0b232 --- /dev/null +++ b/test/bheap.h @@ -0,0 +1,24 @@ +/* + * Phoenix-RTOS + * + * Operating system kernel + * + * Min/max binary heap test + * + * Copyright 2024 Phoenix Systems + * Author: Aleksander Kaminski + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + + +#ifndef _TEST_BH_H_ +#define _TEST_BH_H_ + + +extern void test_bh(void); + + +#endif diff --git a/test/test.h b/test/test.h index 154824de4..08209908b 100644 --- a/test/test.h +++ b/test/test.h @@ -17,7 +17,10 @@ #ifndef _TEST_TEST_H_ #define _TEST_TEST_H_ -#include "vm.h" -#include "proc.h" +#include "test/bheap.h" +#include "test/msg.h" +#include "test/proc.h" +#include "test/rb.h" +#include "test/vm.h" #endif