diff --git a/src/kernel/include/queue.h b/src/kernel/include/queue.h index bd48111..b7359f9 100644 --- a/src/kernel/include/queue.h +++ b/src/kernel/include/queue.h @@ -1,15 +1,28 @@ #pragma once +// This header file contains macros for making FIFO queues from structures +// A queue is set up via a preprocessor definition +// #define QueueName header_name, spot_name, struct type +// where +// QueueName is the queue identifying name +// header_name is a unique name used for the queue head +// spot_name is the name of the queue placeholder in the struct +// struct type is the type of struct the queue is made from +// +// Each queue requires a declaration +// QUEUE_DECLARE(QueueName); +// and a definition +// QUEUE_DEFINE(QueueName); + #define _QUEUE_DECL(queue, entry, type) \ struct queue{ \ type *first; \ type *last; \ - } -#define QUEUE_DECL(...) _QUEUE_DECL(__VA_ARGS__) + } queue +#define QUEUE_DECLARE(...) _QUEUE_DECL(__VA_ARGS__) #define _QUEUE_HEAD(queue, entry, type) \ - struct queue queue -#define QUEUE_HEAD(...) _QUEUE_HEAD(__VA_ARGS__) -#define QUEUE_HEAD_EMPTY(...) _QUEUE_HEAD(__VA_ARGS__) = {0,0} + struct queue queue = {0, 0} +#define QUEUE_DEFINE(...) _QUEUE_HEAD(__VA_ARGS__) #define _QUEUE_SPOT(queue, entry, type) \ type *entry @@ -17,23 +30,23 @@ #define _QUEUE_EMPTY(queue, entry, type) \ (!(queue.last)) -#define QUEUE_EMPTY(...) _QUEUE_EMPTY(__VA_ARGS__) -#define QUEUE_NOT_EMPTY(...) (!(_QUEUE_EMPTY(__VA_ARGS__))) +#define queue_empty(...) _QUEUE_EMPTY(__VA_ARGS__) +#define queue_not_empty(...) (!(_QUEUE_EMPTY(__VA_ARGS__))) #define _QUEUE_ADD(queue, entry, type, item) \ if(!queue.last) \ - queue.first = item; \ + queue.first = (item); \ else \ - queue.last->entry = item; \ + queue.last->entry = (item); \ queue.last = item; \ - item->entry = 0; -#define QUEUE_ADD(...) _QUEUE_ADD(__VA_ARGS__) + (item)->entry = 0; +#define queue_add(...) _QUEUE_ADD(__VA_ARGS__) #define _QUEUE_DROP(queue, entry, type) \ - if(!(queue.first = queue.first->entry)) \ + if(queue.first && !(queue.first = queue.first->entry)) \ queue.last = 0; -#define QUEUE_DROP(...) _QUEUE_DROP(__VA_ARGS__) +#define queue_drop(...) _QUEUE_DROP(__VA_ARGS__) #define _QUEUE_PEEK(queue, entry, type) \ (queue.first) -#define QUEUE_PEEK(...) _QUEUE_PEEK(__VA_ARGS__) +#define queue_peek(...) _QUEUE_PEEK(__VA_ARGS__) diff --git a/src/kernel/include/queue.tt b/src/kernel/include/queue.tt new file mode 100644 index 0000000..f7b7bfa --- /dev/null +++ b/src/kernel/include/queue.tt @@ -0,0 +1,60 @@ +// vim: ft=c +#include + +#include "queue.h" + +#define TestQ test_queue, test_queue_next, struct item +QUEUE_DECLARE(TestQ); +QUEUE_DEFINE(TestQ); + +struct item +{ + int id; + QUEUE_SPOT(TestQ); +}; + +struct item item1 = {1, 0}; +struct item item2 = {2, 0}; + +TEST(peek_returns_queued_item) +{ + queue_add(TestQ, &item1); + struct item *i = queue_peek(TestQ); + ASSERT_EQ_INT(i->id, 1); +} +TEST(peek_returns_first_queued_item) +{ + queue_add(TestQ, &item1); + queue_add(TestQ, &item2); + struct item *i = queue_peek(TestQ); + ASSERT_EQ_INT(i->id, 1); +} +TEST(peek_returns_zero_for_empty_queue) +{ + struct item *i = queue_peek(TestQ); + ASSERT_EQ_PTR(i, 0); +} + +TEST(drop_drops_item_from_queue) +{ + queue_add(TestQ, &item1); + queue_add(TestQ, &item2); + queue_drop(TestQ); + struct item *i = queue_peek(TestQ); + ASSERT_EQ_INT(i->id, 2); +} +TEST(drop_empty_queue_does_not_crash) +{ + queue_drop(TestQ); + ASSERT_EQ_INT(!!queue_empty(TestQ), 1); +} + +TEST(empty_reports_empty_queue_empty) +{ + ASSERT_EQ_INT(!!queue_empty(TestQ), 1); +} +TEST(empty_reports_nonempty_queue_not_empty) +{ + queue_add(TestQ, &item1); + ASSERT_EQ_INT(!!queue_empty(TestQ), 0); +} diff --git a/src/kernel/include/scheduler.h b/src/kernel/include/scheduler.h index 888fecb..d4abad6 100644 --- a/src/kernel/include/scheduler.h +++ b/src/kernel/include/scheduler.h @@ -2,8 +2,7 @@ #include #define READYQ readyQ, readyQ_next, struct thread -QUEUE_DECL(READYQ); -QUEUE_HEAD(READYQ); +QUEUE_DECLARE(READYQ); void ready(struct thread *th); struct thread *scheduler_next(); diff --git a/src/kernel/proc/scheduler.c b/src/kernel/proc/scheduler.c index f4e1395..f671502 100644 --- a/src/kernel/proc/scheduler.c +++ b/src/kernel/proc/scheduler.c @@ -2,16 +2,16 @@ #include #include -QUEUE_HEAD_EMPTY(READYQ); +QUEUE_DEFINE(READYQ); void ready(struct thread *th) { - QUEUE_ADD(READYQ, th); + queue_add(READYQ, th); } struct thread *scheduler_next() { - struct thread *th = QUEUE_PEEK(READYQ); - QUEUE_DROP(READYQ); + struct thread *th = queue_peek(READYQ); + queue_drop(READYQ); return th; }