Skip to content
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: add functionality to check queue state of another thread #16174

Merged
merged 2 commits into from
Mar 9, 2022

Conversation

miri64
Copy link
Member

@miri64 miri64 commented Mar 9, 2021

Contribution description

This adds functions to get the message slots still available in a queue as well as its total length from another thread. Using those a GNRC module can gauge how congested the input queue of a module it wants to send to is.

Testing procedure

make -C tests/msg_avail -j flash test
make -C tests/msg_queue_len -j flash test

should both pass, msg_avail does not increase in size when build with RIOT_CI_BUILD=1 compared to master (I tested on nrf52dk, z1, and arduino-mega2560).

Issues/PRs references

None

@miri64 miri64 added Area: core Area: RIOT kernel. Handle PRs marked with this with care! Type: new feature The issue requests / The PR implemements a new feature for RIOT CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Process: needs >1 ACK Integration Process: This PR requires more than one ACK labels Mar 9, 2021
core/msg.c Outdated Show resolved Hide resolved
core/include/cib.h Outdated Show resolved Hide resolved
core/include/msg.h Outdated Show resolved Hide resolved
Copy link
Contributor

@kaspar030 kaspar030 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly LGTM.

I've been trying to find any concurrency issues.
cib_size() shouldn't have any, as the size of a cib_t's backing array is unlikely to change.
Other than that, the new functions will fail or return bogus data (like many others) if the underlying thread dies / the thread_t gets re-used). This is a general problem and doesn't have to be addressed here.

@miri64
Copy link
Member Author

miri64 commented Mar 9, 2021

Addressed comments.

Copy link
Member

@maribu maribu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm. One comment inline

core/msg.c Outdated
Comment on lines 450 to 458
int msg_avail_thread(kernel_pid_t pid)
{
return _msg_avail(thread_get(pid));
}

int msg_avail(void)
{
return _msg_avail(thread_get_active());
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you checked if there is a benefit in providing only msg_avail_thread() as C function and msg_avail() as static inline header-only function on top? My gut feeling is that there is a small ROM benefit in this.

Copy link
Member Author

@miri64 miri64 Mar 9, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yepp. The problem was that this requires me to include the thread.h header for the common thread_t parameter type of msg_avail_thread() and the call to thread_get_active(), leading to a circular include (as that header includes msg.h). Alternatively, kernel_pid_t could be used as a parameter as I do in this version now. However, he current version (as pointed out in OP) does not increase the ROM, so even if there is new ROM bytes to be won would be lost, I think, by the added thread->pid operation in msg_avail(), especially since that would be multiplied with every inclusion of #include "msg.h", when made inline.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since that would be multiplied with every inclusion of #include "msg.h", when made inline.

You mean, by every call of msg_avail(), right?

If you prefer using kernel_pid_t as argument, you could use:

static inline int msg_avail(void)
{
    return msg_avail_thread(thread_getpid());
}

This should be one instruction more (one load). If there are few calls to msg_avail(), this should be less ROM. Right now there are zero calls in sys, drivers, core, pkg, and examples to msg_avail() - only tests are using it.

Also note that for pointers, the compiler doesn't really need to know the exact type. thread_t is typedefed in sched.h (as forward declaration). And since kernel_pid_t is also typedefed there, sched.h has to be included (at least indirectly) anyway. I see no reason against using thread_t * as argument without including thread.h.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you prefer using kernel_pid_t as argument, you could use:

static inline int msg_avail(void)
{
    return msg_avail_thread(thread_getpid());
}

For that I need to include thread.h as thread_getpid() is defined there...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same goes for something like this

diff --git a/core/include/msg.h b/core/include/msg.h
index 3c9c8ca02a..bacadebffc 100644
--- a/core/include/msg.h
+++ b/core/include/msg.h
@@ -364,7 +364,12 @@ int msg_reply_int(msg_t *m, msg_t *reply);
  * @return Number of messages available in queue of @p pid on success
  * @return -1, if no caller's message queue is initialized
  */
diff --git a/core/include/msg.h b/core/include/msg.h
index 3c9c8ca02a..bacadebffc 100644
--- a/core/include/msg.h
+++ b/core/include/msg.h
@@ -364,7 +364,12 @@ int msg_reply_int(msg_t *m, msg_t *reply);
  * @return Number of messages available in queue of @p pid on success
  * @return -1, if no caller's message queue is initialized
  */
-int msg_avail_thread(kernel_pid_t pid);
+int _msg_avail_thread(thread_t *thread);
+
+static inline int msg_avail_thread(kernel_pid_t pid)
+{
+    return _msg_avail_thread(thread_get(pid));
+}
 
 /**
  * @brief Check how many messages are available (waiting) in the message queue
@@ -372,7 +377,10 @@ int msg_avail_thread(kernel_pid_t pid);
  * @return Number of messages available in our queue on success
  * @return -1, if no caller's message queue is initialized
  */
-int msg_avail(void);
+static inline int msg_avail(void)
+{
+    return _msg_avail_thread(thread_get_active());
+}
 
 /**
  * @brief Get maximum capacity of a thread's queue length
diff --git a/core/msg.c b/core/msg.c
index 1a375e441e..9318dc63c5 100644
--- a/core/msg.c
+++ b/core/msg.c
@@ -433,10 +433,10 @@ static int _msg_receive(msg_t *m, int block)
     DEBUG("This should have never been reached!\n");
 }
 
-static int _msg_avail(thread_t *thread)
+int _msg_avail_thread(thread_t *thread)
 {
     DEBUG("msg_available: %" PRIkernel_pid ": msg_available.\n",
-          thread->pid);
+          pid);
 
     int queue_index = -1;
 
@@ -447,16 +447,6 @@ static int _msg_avail(thread_t *thread)
     return queue_index;
 }
 
-int msg_avail_thread(kernel_pid_t pid)
-{
-    return _msg_avail(thread_get(pid));
-}
-
-int msg_avail(void)
-{
-    return _msg_avail(thread_get_active());
-}
-
 int msg_queue_capacity(kernel_pid_t pid)
 {
     DEBUG("msg_queue_capacity: %" PRIkernel_pid ": msg_queue_capacity.\n",

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking like this:

diff --git a/core/include/msg.h b/core/include/msg.h
index 3c9c8ca02a..afb7c4b763 100644
--- a/core/include/msg.h
+++ b/core/include/msg.h
@@ -359,12 +359,12 @@ int msg_reply_int(msg_t *m, msg_t *reply);
  * @brief Check how many messages are available (waiting) in the message queue
  *        of a specific thread
  *
- * @param[in] pid    a PID
+ * @param[in] thread    Thread to get the number of available messages of
  *
  * @return Number of messages available in queue of @p pid on success
  * @return -1, if no caller's message queue is initialized
  */
-int msg_avail_thread(kernel_pid_t pid);
+int msg_avail_thread(thread_t *thread);
 
 /**
  * @brief Check how many messages are available (waiting) in the message queue
@@ -372,7 +372,10 @@ int msg_avail_thread(kernel_pid_t pid);
  * @return Number of messages available in our queue on success
  * @return -1, if no caller's message queue is initialized
  */
-int msg_avail(void);
+static inline int msg_avail(void)
+{
+    return msg_avail_thread(thread_get_active());
+}
 
 /**
  * @brief Get maximum capacity of a thread's queue length
diff --git a/core/include/sched.h b/core/include/sched.h
index ceea4771ba..34ff614eec 100644
--- a/core/include/sched.h
+++ b/core/include/sched.h
@@ -180,6 +180,32 @@ typedef enum {
 #define SCHED_PRIO_LEVELS 16
 #endif
 
+/**
+ * @brief Returns the process ID of the currently running thread
+ *
+ * @return          obviously you are not a golfer.
+ */
+static inline kernel_pid_t thread_getpid(void)
+{
+    extern volatile kernel_pid_t sched_active_pid;
+
+    return sched_active_pid;
+}
+
+/**
+ * @brief   Returns a pointer to the Thread Control Block of the currently
+ *          running thread
+ *
+ * @return  Pointer to the TCB of the currently running thread, or `NULL` if
+ *          no thread is running
+ */
+static inline thread_t *thread_get_active(void)
+{
+    extern volatile thread_t *sched_active_thread;
+
+    return (thread_t *)sched_active_thread;
+}
+
 /**
  * @brief   Triggers the scheduler to schedule the next thread
  *
diff --git a/core/include/thread.h b/core/include/thread.h
index 5bf9e05715..20ec7a100d 100644
--- a/core/include/thread.h
+++ b/core/include/thread.h
@@ -372,32 +372,6 @@ int thread_kill_zombie(kernel_pid_t pid);
  */
 int thread_wakeup(kernel_pid_t pid);
 
-/**
- * @brief Returns the process ID of the currently running thread
- *
- * @return          obviously you are not a golfer.
- */
-static inline kernel_pid_t thread_getpid(void)
-{
-    extern volatile kernel_pid_t sched_active_pid;
-
-    return sched_active_pid;
-}
-
-/**
- * @brief   Returns a pointer to the Thread Control Block of the currently
- *          running thread
- *
- * @return  Pointer to the TCB of the currently running thread, or `NULL` if
- *          no thread is running
- */
-static inline thread_t *thread_get_active(void)
-{
-    extern volatile thread_t *sched_active_thread;
-
-    return (thread_t *)sched_active_thread;
-}
-
 /**
  * @brief   Gets called upon thread creation to set CPU registers
  *
diff --git a/core/msg.c b/core/msg.c
index 1a375e441e..461d0beb85 100644
--- a/core/msg.c
+++ b/core/msg.c
@@ -433,7 +433,7 @@ static int _msg_receive(msg_t *m, int block)
     DEBUG("This should have never been reached!\n");
 }
 
-static int _msg_avail(thread_t *thread)
+int msg_avail_thread(thread_t *thread)
 {
     DEBUG("msg_available: %" PRIkernel_pid ": msg_available.\n",
           thread->pid);
@@ -447,16 +447,6 @@ static int _msg_avail(thread_t *thread)
     return queue_index;
 }
 
-int msg_avail_thread(kernel_pid_t pid)
-{
-    return _msg_avail(thread_get(pid));
-}
-
-int msg_avail(void)
-{
-    return _msg_avail(thread_get_active());
-}
-
 int msg_queue_capacity(kernel_pid_t pid)
 {
     DEBUG("msg_queue_capacity: %" PRIkernel_pid ": msg_queue_capacity.\n",

When tests/msg_avail is modified to contain both flavors, it safes 44 bytes. If only msg_avail() is used, it is 4 bytes larger.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TBH, that is to much of a rework for me with the added caveat of having 4 bytes more if only one of the functions is used. As you said, this function is used rarely and in my use case I will only use msg_avail_thread(), so most likely same problem. Also I want there to be a function using kernel_pid_t, as that is the type that is used in the rest of the header to identify a thread and since the msg API is used heavily outside of core IMHO it makes sense to not use a more or less internal type to core as a thread identifier.

@miri64
Copy link
Member Author

miri64 commented May 6, 2021

Squashed and rebased to current master. Ping @maribu?

* @return Number of total messages that fit in the queue of @p pid on success
* @return -1, if no caller's message queue is initialized
*/
int msg_queue_capacity(kernel_pid_t pid);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe rename to msg_queue_capacity_thread() for naming consistency? And add

static inline int msg_queue_capacity(void)
{
    retrurn msg_queue_capacity_thread(thread_getpid());
}

Even if there is no obvious use case for this now, it is hard to change APIs later on.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This causes a cyclic inclusion, as thread.h (where thread_getpid() is declared) is including msg.h. I would have used sched_active_pid, but that seems not to be exposed anymore. Last alternative would be to make it a non-static inline function.

@miri64 miri64 force-pushed the core/enh/msg-queue-metrics branch from b9e2912 to 92a2730 Compare May 7, 2021 10:10
@miri64
Copy link
Member Author

miri64 commented May 7, 2021

Squashed and rebased to current master. Ping @maribu?

(forgot to push, so did that now)

@MrKevinWeiss MrKevinWeiss added this to the Release 2021.07 milestone Jun 22, 2021
@MrKevinWeiss MrKevinWeiss removed this from the Release 2021.07 milestone Jul 15, 2021
@fjmolinas
Copy link
Contributor

ping @maribu @miri64

@miri64
Copy link
Member Author

miri64 commented Nov 18, 2021

ping @maribu @miri64

I addressed all change requests in comment and awaiting @maribu's response.

maribu
maribu previously approved these changes Nov 18, 2021
Copy link
Member

@maribu maribu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK

@miri64
Copy link
Member Author

miri64 commented Nov 19, 2021

Core change, so still needs a second ACK. @kaspar030?

@github-actions github-actions bot added the Area: tests Area: tests and testing framework label Nov 19, 2021
@miri64
Copy link
Member Author

miri64 commented Nov 19, 2021

Adapted and squashed tests to align with the latest changes from the review.

@maribu maribu added CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR and removed CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR labels Nov 19, 2021
benpicco
benpicco previously approved these changes Mar 3, 2022
@miri64
Copy link
Member Author

miri64 commented Mar 3, 2022

Shall I rebase? ;-)

@benpicco
Copy link
Contributor

benpicco commented Mar 3, 2022

Sure!

@miri64
Copy link
Member Author

miri64 commented Mar 3, 2022

This might need a re-review, since the signature of msg_avail() changed in current master.

@miri64 miri64 dismissed benpicco’s stale review March 3, 2022 15:45

Needs re-review

@miri64 miri64 requested a review from maribu March 3, 2022 15:45
@miri64 miri64 dismissed maribu’s stale review March 3, 2022 15:45

Needs re-review

@miri64 miri64 force-pushed the core/enh/msg-queue-metrics branch from d20faa6 to f9efe36 Compare March 3, 2022 15:50
@miri64
Copy link
Member Author

miri64 commented Mar 3, 2022

Shall I rebase? ;-)

Done

Copy link
Contributor

@benpicco benpicco left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The type of msg_avail() just became unsigned in the meantime, the change is still good.

@benpicco benpicco added CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR and removed CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR labels Mar 7, 2022
@benpicco benpicco added this to the Release 2022.04 milestone Mar 9, 2022
@benpicco benpicco requested a review from kfessel March 9, 2022 15:21
Copy link
Contributor

@kfessel kfessel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

read and checked previously raise issues (all are resolved)

@benpicco benpicco added Area: arduino API Area: Arduino wrapper API and removed Area: arduino API Area: Arduino wrapper API labels Mar 9, 2022
@benpicco benpicco enabled auto-merge March 9, 2022 16:10
@benpicco benpicco merged commit 840067c into RIOT-OS:master Mar 9, 2022
@miri64 miri64 deleted the core/enh/msg-queue-metrics branch March 10, 2022 10:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: core Area: RIOT kernel. Handle PRs marked with this with care! Area: tests Area: tests and testing framework CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR CI: run tests If set, CI server will run tests on hardware for the labeled PR Process: needs >1 ACK Integration Process: This PR requires more than one ACK Type: new feature The issue requests / The PR implemements a new feature for RIOT
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants