-
Notifications
You must be signed in to change notification settings - Fork 29
Refactor list node for embedded usage #60
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
85cf328
fd54343
f800aaa
6ad49bd
5a1c997
b24db92
b7bce6e
efced21
eb7db10
fe87986
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,7 +15,6 @@ | |
| /* List node */ | ||
| typedef struct list_node { | ||
| struct list_node *next; | ||
| void *data; | ||
| } list_node_t; | ||
|
|
||
| /* Public list descriptor */ | ||
|
|
@@ -45,10 +44,8 @@ static inline list_t *list_create(void) | |
| } | ||
|
|
||
| head->next = tail; | ||
| head->data = NULL; | ||
|
|
||
| tail->next = NULL; | ||
| tail->data = NULL; | ||
|
|
||
| list->head = head; | ||
| list->tail = tail; | ||
|
|
@@ -78,16 +75,11 @@ static inline list_node_t *list_cnext(const list_t *list, | |
|
|
||
| /* Push and pop */ | ||
|
|
||
| static inline list_node_t *list_pushback(list_t *list, void *data) | ||
| static inline list_node_t *list_pushback(list_t *list, list_node_t *node) | ||
| { | ||
| if (unlikely(!list)) | ||
| return NULL; | ||
|
|
||
| list_node_t *node = malloc(sizeof(*node)); | ||
| if (unlikely(!node)) | ||
| if (unlikely(!list || !node || node->next)) | ||
| return NULL; | ||
|
|
||
| node->data = data; | ||
| node->next = list->tail; | ||
|
|
||
| /* Insert before tail sentinel */ | ||
|
|
@@ -100,22 +92,21 @@ static inline list_node_t *list_pushback(list_t *list, void *data) | |
| return node; | ||
| } | ||
|
|
||
| static inline void *list_pop(list_t *list) | ||
| static inline list_node_t *list_pop(list_t *list) | ||
| { | ||
| if (unlikely(list_is_empty(list))) | ||
| return NULL; | ||
|
|
||
| list_node_t *first = list->head->next; | ||
| list->head->next = first->next; | ||
| first->next = NULL; | ||
|
|
||
| void *data = first->data; | ||
| free(first); | ||
| list->length--; | ||
| return data; | ||
| return first; | ||
| } | ||
|
|
||
| /* Remove a specific node; returns its data */ | ||
| static inline void *list_remove(list_t *list, list_node_t *target) | ||
| /* Remove a specific node from the list */ | ||
| static inline list_node_t *list_remove(list_t *list, list_node_t *target) | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The return value is required for the exception handling when removing the waiter node from the mutex waiting list. |
||
| { | ||
| if (unlikely(!list || !target || list_is_empty(list))) | ||
| return NULL; | ||
|
|
@@ -128,10 +119,9 @@ static inline void *list_remove(list_t *list, list_node_t *target) | |
| return NULL; /* node not found */ | ||
|
|
||
| prev->next = target->next; | ||
| void *data = target->data; | ||
| free(target); | ||
| target->next = NULL; | ||
| list->length--; | ||
| return data; | ||
| return target; | ||
| } | ||
|
|
||
| /* Iteration */ | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -45,35 +45,33 @@ static inline void cond_invalidate(cond_t *c) | |
| */ | ||
| static bool remove_self_from_waiters(list_t *waiters) | ||
| { | ||
| if (unlikely(!waiters || !kcb || !kcb->task_current || | ||
| !kcb->task_current->data)) | ||
| if (unlikely(!waiters || !kcb || !kcb->task_current)) | ||
| return false; | ||
|
|
||
| tcb_t *self = kcb->task_current->data; | ||
| tcb_t *self = tcb_from_global_node(kcb->task_current); | ||
|
|
||
| /* Search for and remove self from waiters list */ | ||
| list_node_t *curr = waiters->head->next; | ||
| while (curr && curr != waiters->tail) { | ||
| if (curr->data == self) { | ||
| list_remove(waiters, curr); | ||
| list_node_t *curr_mutex_node = waiters->head->next; | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This name is better aligned with the embedded list node. |
||
| while (curr_mutex_node && curr_mutex_node != waiters->tail) { | ||
| if (tcb_from_mutex_node(curr_mutex_node) == self) { | ||
| list_remove(waiters, curr_mutex_node); | ||
| return true; | ||
| } | ||
| curr = curr->next; | ||
| curr_mutex_node = curr_mutex_node->next; | ||
| } | ||
| return false; | ||
| } | ||
|
|
||
| /* Atomic block operation with enhanced error checking */ | ||
| static void mutex_block_atomic(list_t *waiters) | ||
| { | ||
| if (unlikely(!waiters || !kcb || !kcb->task_current || | ||
| !kcb->task_current->data)) | ||
| if (unlikely(!waiters || !kcb || !kcb->task_current)) | ||
| panic(ERR_SEM_OPERATION); | ||
|
|
||
| tcb_t *self = kcb->task_current->data; | ||
| tcb_t *self = tcb_from_global_node(kcb->task_current); | ||
|
|
||
| /* Add to waiters list */ | ||
| if (unlikely(!list_pushback(waiters, self))) | ||
| if (unlikely(!list_pushback(waiters, &self->mutex_node))) | ||
| panic(ERR_SEM_OPERATION); | ||
|
|
||
| /* Block and yield atomically */ | ||
|
|
@@ -218,8 +216,8 @@ int32_t mo_mutex_timedlock(mutex_t *m, uint32_t ticks) | |
| } | ||
|
|
||
| /* Slow path: must block with timeout using delay mechanism */ | ||
| tcb_t *self = kcb->task_current->data; | ||
| if (unlikely(!list_pushback(m->waiters, self))) { | ||
| tcb_t *self = tcb_from_global_node(kcb->task_current); | ||
| if (unlikely(!list_pushback(m->waiters, &self->mutex_node))) { | ||
| NOSCHED_LEAVE(); | ||
| panic(ERR_SEM_OPERATION); | ||
| } | ||
|
|
@@ -277,7 +275,8 @@ int32_t mo_mutex_unlock(mutex_t *m) | |
| m->owner_tid = 0; | ||
| } else { | ||
| /* Transfer ownership to next waiter (FIFO) */ | ||
| tcb_t *next_owner = (tcb_t *) list_pop(m->waiters); | ||
| list_node_t *next_owner_node = (list_node_t *) list_pop(m->waiters); | ||
| tcb_t *next_owner = tcb_from_mutex_node(next_owner_node); | ||
| if (likely(next_owner)) { | ||
| /* Validate task state before waking */ | ||
| if (likely(next_owner->state == TASK_BLOCKED)) { | ||
|
|
@@ -378,11 +377,11 @@ int32_t mo_cond_wait(cond_t *c, mutex_t *m) | |
| if (unlikely(!mo_mutex_owned_by_current(m))) | ||
| return ERR_NOT_OWNER; | ||
|
|
||
| tcb_t *self = kcb->task_current->data; | ||
| tcb_t *self = tcb_from_global_node(kcb->task_current); | ||
|
|
||
| /* Atomically add to wait list */ | ||
| NOSCHED_ENTER(); | ||
| if (unlikely(!list_pushback(c->waiters, self))) { | ||
| if (unlikely(!list_pushback(c->waiters, &self->mutex_node))) { | ||
| NOSCHED_LEAVE(); | ||
| panic(ERR_SEM_OPERATION); | ||
| } | ||
|
|
@@ -420,11 +419,11 @@ int32_t mo_cond_timedwait(cond_t *c, mutex_t *m, uint32_t ticks) | |
| return ERR_TIMEOUT; | ||
| } | ||
|
|
||
| tcb_t *self = kcb->task_current->data; | ||
| tcb_t *self = tcb_from_global_node(kcb->task_current); | ||
|
|
||
| /* Atomically add to wait list with timeout */ | ||
| NOSCHED_ENTER(); | ||
| if (unlikely(!list_pushback(c->waiters, self))) { | ||
| if (unlikely(!list_pushback(c->waiters, &self->mutex_node))) { | ||
| NOSCHED_LEAVE(); | ||
| panic(ERR_SEM_OPERATION); | ||
| } | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.