-
Notifications
You must be signed in to change notification settings - Fork 2.1k
core: mutex: several optimizations #4557
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
core: mutex: several optimizations #4557
Conversation
Result is 4% more speed, 20 bytes code saved and |
|
||
#define ENABLE_DEBUG (0) | ||
#include "debug.h" | ||
|
||
static void mutex_wait(struct mutex_t *mutex); | ||
#define MUTEX_LOCKED ((void*)0xFFFFFFFF) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(this needs 16bit adjustments)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just use -1
instead of 0xFF…FF
.
Re-usuing tcb_t::rq_entry makes sense. I did not look into the diff properly, yet. |
One advantage of reusing "rq_entry" is that mutexes don't need any space in tcb_t anymore. Before, they shared "wait_data" with msg. |
found another ~2.5% |
needs rebase |
351a2fe
to
c4e3849
Compare
|
Could you make a short summary of the benefits of the new linked list implementation? The casts from |
list_node_t *new_node = (list_node_t*)&thread->rq_entry; | ||
new_node->next = NULL; | ||
|
||
while (list->next) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this will exit on next == MUTEX_LOCKED
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't _mutex_lock() catch that case before calling thread_add_to_list()?
The main difference to clist is that clist is doubly-linked and circular, while the new list is only singly-linked and has two ends. This way, mutex_t is only one-field-sized (a list entry). (After a short |
c4e3849
to
48acafa
Compare
|
* @param[in] node list node before new entry | ||
* @param[in] new_node list node to insert | ||
*/ | ||
static inline void list_add(list_node_t *node, list_node_t *new_node) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would do
static inline void list_add(list_node_t **node, list_node_t *new_node) {
if (*node == NULL) {
*node = new_node;
}
else {
new_node->next = node->next;
node->next = new_node;
}
}
To make the API more consistent with clist_node_t
(empty list is NULL).
edit: fixed dereferencialization in if statement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Somehow I dislike replacing two lines with four for API consistency.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then how is an empty list represented in your version?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As pointer to the first element. edit misread.
A list is represented as pointer to the first element, and that struct is conveniently the same as that of a list node. So if the list is empty, the list node representing the list has a NULL next ptr.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So you always need one extra element in memory? That's not ideal either ;-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah okay. I did not read it that way. So an empty list is still a NULL pointer in your version? Wouldn't this just require the user to add the check I introduced above anyways i.e. just put the code outside the API?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, every list is a "list_node_t". That struct just happens to only contain a pointer. If there are elements, that pointer points to the first element, if not, it is NULL.
The add function inserts an element after another. If the root node of the list is specified as first parameter, the new object will be the new head of the list.
The remove_head function removes the first and returns it, if any.
No further checks needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function is never called.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't have the time to understand the full PR, I'm just a bit confused why you introduce a new list implementation and use only the "remove head" function.
Could be solved by using a union... |
48acafa
to
7cad459
Compare
4cc6e0e
to
3cbcf3c
Compare
Needs a rebase. |
3cbcf3c
to
0b5ea41
Compare
|
*/ | ||
|
||
#ifndef __LIST_H | ||
#define __LIST_H |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought these underscores were forbidden?
0b5ea41
to
a93196c
Compare
list = list->next; | ||
} | ||
|
||
list->next = new_node; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't you use list_add()
here, so you don't break the list? So if the current list->next
is somewhere in the middle of the list, and we run the line above, the items that have been pointed to by list->next
before are dropped from the list, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ups, overlooked l119, so everything should be ok. You might want to more l119 out of the loop and remove l114 though.
|
Code looks good, tested with #5190 and |
f60ec99
to
3d9020e
Compare
|
* the container_of() macro in list operations. | ||
* See @ref thread_add_to_list() as example. | ||
*/ | ||
typedef struct list_node { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we don't want the struct name here, or am I missing something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, I missed the next line. sorry (:
code looks good. ACK |
And go. Thanks for reviewing! |
(The last three were adopted from @Kijewski's #4555)