Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions src/os/kernel/algo.h → include/cmrx/algo.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,21 @@
#pragma once

#include <stdint.h>
/** @defgroup api_algo Algorithm templates
* @ingroup api
* Templates for algorithms to work with some common data types. Algorithms
* implemented here are "templates". They are provided as macros which adapt
* to underlying types. This means these algorithms can run faster as they
* are not generic, but it also means that each use will generate its own
* copy.
*
* Currently algorithms to work with arrays (insert, delete, binary search),
* hash tables (searching) and bitmaps (set, clear, test, find first) are
* implemented. Main user of these algorithms is kernel itself yet as they
* are optimized for embedded they are accessible to userspace programs
* as well.
* @{
*/

/** Binary search algorithm.
* This is a template for binary searching over a sorted compacted array.
Expand Down Expand Up @@ -174,6 +189,7 @@ inline uint32_t os_hash_key(uint32_t key)
}
#endif

/** Reserved value denoting that tash table key is empty */
#define HASH_EMPTY 0xFFFFFFFFU

/** Find entry in hash table.
Expand Down Expand Up @@ -227,3 +243,56 @@ inline uint32_t os_hash_key(uint32_t key)
}\
pos;\
})

/** Template for setting bit in bitmap.
* Sets bit in bitmap of arbitrary size as if it was one continuous array of bits.
*
* @param _BITMAP bitmap identity
* @param _POS bit to be set
* @param _SIZE bitmap size
*/
#define BITMAP_SET(_BITMAP, _POS, _SIZE) _BITMAP[(_POS) >> 5] |= (1U << ((_POS) & 31));

/** Template for clearing bit in bitmap.
* Clears bit in bitmap of arbitrary size as if it was one continuous array of bits.
*
* @param _BITMAP bitmap identity
* @param _POS bit to be set
* @param _SIZE bitmap size
*/
#define BITMAP_CLEAR(_BITMAP, _POS, _SIZE) _BITMAP[(_POS) >> 5] &= ~(1U << ((_POS) & 31));

/** Template for testing if bit is set in bitmap.
* Tests if bit in bitmap of arbitrary size is set.
*
* @param _BITMAP bitmap identity
* @param _POS bit to be set
* @param _SIZE bitmap size
*/
#define BITMAP_TEST(_BITMAP, _POS, _SIZE) ((_BITMAP[(_POS) >> 5] & (1U << ((_POS) & 31))) != 0)

/** Return first set bit in the bitmap.
* Returns first bit set in bitmap of arbitrary size as if it was one continuous array of bits.
*
* @param _BITMAP bitmap identity
* @param _SIZE bitmap size
* @returns position of first bit counted from the beginning of bitmap, or ~0U if no bit is set.
*/
#define BITMAP_FIRST(_BITMAP, _SIZE) \
({\
uint32_t first = ~0;\
for (unsigned word = 0; word < _SIZE; ++word) {\
uint32_t ready = _BITMAP[word];\
if (ready) {\
uint8_t bit = __builtin_ctz(ready);\
first = (word << 5) + bit;\
break;\
}\
}\
first;\
})
#define BITMAP_COPY(_TARGET, _SOURCE, _SIZE) \
for (unsigned q = 0; q < _SIZE; ++q) _TARGET[q] = _SOURCE[q];


/* }@ */
2 changes: 1 addition & 1 deletion src/os/kernel/algo.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
#include "algo.h"
#include <cmrx/algo.h>

uint32_t os_hash_key(uint32_t key);
2 changes: 1 addition & 1 deletion src/os/kernel/notify.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#include <cmrx/assert.h>
#include <conf/kernel.h>
#include <cmrx/sys/notify.h>
#include "algo.h"
#include <cmrx/algo.h>

static struct NotificationObject os_notification_buffer[OS_NOTIFICATION_BUFFER_SIZE];
unsigned os_notification_buffer_size;
Expand Down
1 change: 1 addition & 0 deletions src/os/kernel/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ set(test_algo_SRCS
algo_binary_search.c
algo_insert_sort.c
algo_hash_search.c
algo_bitmap.c
)

add_executable(test_algo ${test_algo_SRCS})
Expand Down
2 changes: 1 addition & 1 deletion src/os/kernel/tests/algo_binary_search.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#include <ctest.h>
#include <kernel/algo.h>
#include <cmrx/algo.h>
#include "algo_data.h"

CTEST_DATA(algo_binary_search) {
Expand Down
104 changes: 104 additions & 0 deletions src/os/kernel/tests/algo_bitmap.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
#include <ctest.h>
#include <cmrx/algo.h>
#include "algo_data.h"

#define BITMAP_SIZE 4
#define BITMAP_MAX (BITMAP_SIZE * 8 * sizeof(uint32_t))

CTEST_DATA(algo_bitmap) {
uint32_t bitmap[BITMAP_SIZE];
};

CTEST_SETUP(algo_bitmap) {
for (unsigned q = 0; q < BITMAP_SIZE; ++q)
{
data->bitmap[q] = 0;
}
}

CTEST2(algo_bitmap, find_empty) {
uint32_t item = BITMAP_FIRST(data->bitmap, BITMAP_SIZE);
ASSERT_EQUAL(item, ~0U);
}

CTEST2(algo_bitmap, set_one) {
BITMAP_SET(data->bitmap, 0, BITMAP_MAX);
bool is_set = BITMAP_TEST(data->bitmap, 0, BITMAP_SIZE);
ASSERT_TRUE(is_set);
}

CTEST2(algo_bitmap, set_multiple) {
BITMAP_SET(data->bitmap, 0, BITMAP_MAX);
bool is_set = BITMAP_TEST(data->bitmap, 0, BITMAP_SIZE);
ASSERT_TRUE(is_set);

BITMAP_SET(data->bitmap, 1, BITMAP_MAX);
is_set = BITMAP_TEST(data->bitmap, 1, BITMAP_SIZE);
ASSERT_TRUE(is_set);

BITMAP_SET(data->bitmap, 2, BITMAP_MAX);
is_set = BITMAP_TEST(data->bitmap, 2, BITMAP_SIZE);
ASSERT_TRUE(is_set);
}

/* Set last bit, check no previous was set */
CTEST2(algo_bitmap, set_and_check_correct_item) {
BITMAP_SET(data->bitmap, BITMAP_MAX - 1, BITMAP_SIZE);
uint32_t item = BITMAP_FIRST(data->bitmap, BITMAP_SIZE);
ASSERT_EQUAL(item, BITMAP_MAX - 1);
}

/* Set multiple bits at the end of list, check no previous were set and no set bit was cleared */
CTEST2(algo_bitmap, set_multiple_check_correct) {
BITMAP_SET(data->bitmap, BITMAP_MAX - 1, BITMAP_SIZE);

BITMAP_SET(data->bitmap, BITMAP_MAX - 2, BITMAP_SIZE);

uint32_t item = BITMAP_FIRST(data->bitmap, BITMAP_SIZE);
ASSERT_EQUAL(item, BITMAP_MAX - 2);
bool is_set = BITMAP_TEST(data->bitmap, BITMAP_MAX - 1, BITMAP_SIZE);
ASSERT_TRUE(is_set);
}

CTEST2(algo_bitmap, set_and_clear_one) {
BITMAP_SET(data->bitmap, 0, BITMAP_MAX);
BITMAP_CLEAR(data->bitmap, 0, BITMAP_MAX);
bool is_set = BITMAP_TEST(data->bitmap, 0, BITMAP_SIZE);
ASSERT_FALSE(is_set);
}

CTEST2(algo_bitmap, set_and_clear_no_residues) {
BITMAP_SET(data->bitmap, 0, BITMAP_MAX);
BITMAP_CLEAR(data->bitmap, 0, BITMAP_MAX);

uint32_t item = BITMAP_FIRST(data->bitmap, BITMAP_SIZE);
ASSERT_EQUAL(item, ~0U);
}


CTEST2(algo_bitmap, set_and_clear_correct) {
BITMAP_SET(data->bitmap, 0, BITMAP_MAX);
BITMAP_SET(data->bitmap, 1, BITMAP_MAX);
BITMAP_CLEAR(data->bitmap, 0, BITMAP_MAX);
bool is_set = BITMAP_TEST(data->bitmap, 0, BITMAP_SIZE);
ASSERT_FALSE(is_set);

is_set = BITMAP_TEST(data->bitmap, 1, BITMAP_SIZE);
ASSERT_TRUE(is_set);
}

CTEST2(algo_bitmap, set_copy_and_check) {
uint32_t my_bitmap[BITMAP_SIZE];

BITMAP_SET(data->bitmap, BITMAP_MAX - 1, BITMAP_SIZE);

BITMAP_SET(data->bitmap, BITMAP_MAX - 2, BITMAP_SIZE);

BITMAP_COPY(my_bitmap, data->bitmap, BITMAP_SIZE);

uint32_t item = BITMAP_FIRST(my_bitmap, BITMAP_SIZE);
ASSERT_EQUAL(item, BITMAP_MAX - 2);
bool is_set = BITMAP_TEST(my_bitmap, BITMAP_MAX - 1, BITMAP_SIZE);
ASSERT_TRUE(is_set);

}
2 changes: 1 addition & 1 deletion src/os/kernel/tests/algo_data.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#include "algo_data.h"
#include <kernel/algo.h>
#include <cmrx/algo.h>

// To force hashing function emission
uint32_t os_hash_key(uint32_t key);
Expand Down
2 changes: 1 addition & 1 deletion src/os/kernel/tests/algo_hash_search.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#include <ctest.h>
#include <kernel/algo.h>
#include <cmrx/algo.h>
#include "algo_data.h"

void hash_insert(uint32_t key)
Expand Down
2 changes: 1 addition & 1 deletion src/os/kernel/tests/algo_insert_sort.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#include <ctest.h>
#include <kernel/algo.h>
#include <cmrx/algo.h>
#include "algo_data.h"

CTEST_DATA(algo_insert_sort) {
Expand Down
2 changes: 1 addition & 1 deletion src/os/kernel/tests/os_setitimer.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include <kernel/timer.h>
#include <kernel/runtime.h>
#include <kernel/algo.h>
#include <cmrx/algo.h>
#include <ctest.h>
#include <arch/corelocal.h>

Expand Down
2 changes: 1 addition & 1 deletion src/os/kernel/timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#include "signal.h"
#include "notify.h"
#include "txn.h"
#include "algo.h"
#include <cmrx/algo.h>
#include <conf/kernel.h>

#include <stdint.h>
Expand Down