Skip to content

Conversation

@ClaCodes
Copy link
Contributor

@ClaCodes ClaCodes commented May 13, 2024

Implement the non-standard facilities for joining pthreads.

Open Questions

  • naming _np for non-standard as gnu does?
  • test allowed to sleep 300 ms?
  • use maximum value of time_t to represent forever in the timespec, which is the correct/portable makro?
  • convert timespec to timeout -> handle overflow?

This is my first PR, so let me know, if something formal is wrong. @cfriedt please let me know your opinion on this.

@zephyrbot zephyrbot added the area: POSIX POSIX API Library label May 13, 2024
@zephyrbot zephyrbot requested review from cfriedt and ycsin May 13, 2024 06:43
@github-actions
Copy link

Hello @ClaCodes, and thank you very much for your first pull request to the Zephyr project!
Our Continuous Integration pipeline will execute a series of checks on your Pull Request commit messages and code, and you are expected to address any failures by updating the PR. Please take a look at our commit message guidelines to find out how to format your commit messages, and at our contribution workflow to understand how to update your Pull Request. If you haven't already, please make sure to review the project's Contributor Expectations and update (by amending and force-pushing the commits) your pull request if necessary.
If you are stuck or need help please join us on Discord and ask your question there. Additionally, you can escalate the review when applicable. 😊

@cfriedt
Copy link
Member

cfriedt commented May 13, 2024

@ClaCodes - I would definitely add the _np suffix (and also tests passing).

I'll add a more detailed review in a few minutes.

Copy link
Member

@cfriedt cfriedt left a comment

Choose a reason for hiding this comment

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

I think we should convert to k_timeout at the point of entry, rename pthread_join() to static pthread_timedjoin_internal(), also accept a k_timeout_t timeout, and then the other join functions can be 1-line wrappers for the internal version.

Additionally, please add tests in a second commit and follow the commit guidelines.

Tests should be directed to individual functions, so add

ZTEST(pthread, test_pthread_timedjoin)
ZTEST(pthread, test_pthread_tryjoin)

following the existing conventions (see git log), where each test case tests various permutations of invalid input and then valid input.

Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
int pthread_timedjoin_np(pthread_t thread, void **status, const struct timespec abstime);
int pthread_timedjoin_np(pthread_t thread, void **status, const struct timespec *abstime);

Copy link
Member

Choose a reason for hiding this comment

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

One possibly cleaner way to go about this is to convert all absolute struct timespec to k_timeout at the point of entry, and have an internal pthread_timedjoin_internal(pthread_t th, void **status, k_timeout_t timeout) (where the timeout is already specified as a k_timeout_t instead of struct timespec).

That way, e.g.

  • pthread_join(th, st) -> pthread_timedjoin_internal(th, st, K_FOREVER)
  • pthread_tryjoin(th, st) -> pthread_timedjoin_internal(th, st, K_NO_WAIT)
  • pthread_timedjoin_np(th, st, to) -> pthread_timedjoin_internal(th, st, K_MSEC(timespec_to_timeoutms(to)))

@cfriedt
Copy link
Member

cfriedt commented May 13, 2024

@ClaCodes - be sure to tests prior to pushing via

twister -i -T tests/posix

and check compliance via

./scripts/checkpatch.pl -g <commit-before-yours>..

@ClaCodes ClaCodes force-pushed the pthread_timed_join branch from 58beb60 to ab80996 Compare June 1, 2024 16:26
@ClaCodes
Copy link
Contributor Author

ClaCodes commented Jun 1, 2024

@cfriedt I tried to address your suggestions and used checkpatch. I am unable to run the test locally because I am on an unsupported system. Will have to rely on the CI for that currently.

@ClaCodes ClaCodes force-pushed the pthread_timed_join branch 2 times, most recently from 451fa74 to 2dddd68 Compare June 1, 2024 17:14
@ClaCodes ClaCodes changed the title RFC: Implement non-standart pthread_tryjoin and pthread_timedjoin. Implement non-standart pthread_tryjoin and pthread_timedjoin. Jun 1, 2024
Copy link
Member

@cfriedt cfriedt left a comment

Choose a reason for hiding this comment

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

I think we need to check the return value of k_thread_join() now that the assertion is gone.

Otherwise, looks ok.

I'm just on mobile atm, so cannot look in detail.

Please double check that all meaningful input permutations are made in the testsuite as well.

@ClaCodes ClaCodes force-pushed the pthread_timed_join branch from 2dddd68 to db20d74 Compare June 1, 2024 19:30
@ClaCodes
Copy link
Contributor Author

ClaCodes commented Jun 1, 2024

Please double check that all meaningful input permutations are made in the testsuite as well.

There is probably more that could be done. For now idea was:

  • tryjoin:

    • spawn thread that ends after 1s
    • immediately tryjoin expect EBUSY
    • sleep 1s
    • tryjoin expect success
  • timedjoin:

    • create thread that ends after 1s
    • Test -EINVALID for negativ seconds, negative nanoseconds and nanonseconds == NSEC_PER_SEC
    • timed join with timeout less then 1s after start, excpect -ETIMEDOUT
    • timed join with timeout later then 1s after start, excpect success

@ClaCodes ClaCodes force-pushed the pthread_timed_join branch 2 times, most recently from 5063dc3 to 2e47c43 Compare June 1, 2024 21:09
Copy link
Member

@cfriedt cfriedt left a comment

Choose a reason for hiding this comment

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

A null check would be good before dereferencing abstime

@ClaCodes ClaCodes force-pushed the pthread_timed_join branch 3 times, most recently from 99e26d2 to 3ba76d2 Compare June 5, 2024 05:53
@github-actions
Copy link

github-actions bot commented Aug 5, 2024

This pull request has been marked as stale because it has been open (more than) 60 days with no activity. Remove the stale label or add a comment saying that you would like to have the label removed otherwise this pull request will automatically be closed in 14 days. Note, that you can always re-open a closed pull request at any time.

@github-actions github-actions bot added the Stale label Aug 5, 2024
@cfriedt cfriedt removed the Stale label Aug 5, 2024
Copy link
Member

@cfriedt cfriedt left a comment

Choose a reason for hiding this comment

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

Probably could use a rebase, and there are a couple of platforms where tests are not passing.

@cfriedt
Copy link
Member

cfriedt commented Aug 5, 2024

@ClaCodes - would be nice to get this in - can you make some changes and resubmit?

@ClaCodes ClaCodes force-pushed the pthread_timed_join branch 2 times, most recently from 0532093 to 69417b0 Compare August 6, 2024 20:31
@ClaCodes
Copy link
Contributor Author

ClaCodes commented Aug 6, 2024

@ClaCodes - would be nice to get this in - can you make some changes and resubmit?

I rebased and tried to make test more robust by adding a bit more time. I am not sure, why some test are failing. I might have some time to look into it more, if adding more time was not good enough.
Maybe you could have a look at the test to see if I have some wrong assumptions.

@cfriedt
Copy link
Member

cfriedt commented Nov 29, 2024

@ClaCodes - this is pretty close - just needs a nudge past the finish line 🏁

@cfriedt cfriedt changed the title Implement non-standart pthread_tryjoin and pthread_timedjoin. Implement non-standard pthread_tryjoin and pthread_timedjoin. Dec 1, 2024
@ClaCodes
Copy link
Contributor Author

ClaCodes commented Dec 1, 2024

Unfortunately, I am still having trouble with the tests. If someone wants to pick this up, you are welcome to. Otherwise I will be closing.

Thanks for understanding and sorry.

@cfriedt
Copy link
Member

cfriedt commented Dec 3, 2024

@ClaCodes - there is a subtle bug that needs to be fixed in the commit titled "posix: pthread: implement non-standard try-join and timed-join".

diff --git a/lib/posix/options/pthread.c b/lib/posix/options/pthread.c
index 5dfd6599784..db5d37fc8cc 100644
--- a/lib/posix/options/pthread.c
+++ b/lib/posix/options/pthread.c
@@ -1112,6 +1112,11 @@ static int pthread_timedjoin_internal(pthread_t pthread, void **status, k_timeou
        }
 
        ret = k_thread_join(&t->thread, timeout);
+       if (ret != 0) {
+               SYS_SEM_LOCK(&pthread_pool_lock) {
+                       t->attr.detachstate = PTHREAD_CREATE_JOINABLE;
+               }
+       }
        if (ret == -EBUSY) {
                return EBUSY;
        } else if (ret == -EAGAIN) {

@ClaCodes
Copy link
Contributor Author

ClaCodes commented Dec 8, 2024

@ClaCodes - there is a subtle bug that needs to be fixed in the commit titled "posix: pthread: implement non-standard try-join and timed-join".

diff --git a/lib/posix/options/pthread.c b/lib/posix/options/pthread.c
index 5dfd6599784..db5d37fc8cc 100644
--- a/lib/posix/options/pthread.c
+++ b/lib/posix/options/pthread.c
@@ -1112,6 +1112,11 @@ static int pthread_timedjoin_internal(pthread_t pthread, void **status, k_timeou
        }
 
        ret = k_thread_join(&t->thread, timeout);
+       if (ret != 0) {
+               SYS_SEM_LOCK(&pthread_pool_lock) {
+                       t->attr.detachstate = PTHREAD_CREATE_JOINABLE;
+               }
+       }
        if (ret == -EBUSY) {
                return EBUSY;
        } else if (ret == -EAGAIN) {

@cfriedt Thank you for sending this patch.
I have applied it and rebased.
Let me know, what you think

@ghost
Copy link

ghost commented Dec 9, 2024

@ClaCodes - there is a subtle bug that needs to be fixed in the commit titled "posix: pthread: implement non-standard try-join and timed-join".

diff --git a/lib/posix/options/pthread.c b/lib/posix/options/pthread.c
index 5dfd6599784..db5d37fc8cc 100644
--- a/lib/posix/options/pthread.c
+++ b/lib/posix/options/pthread.c
@@ -1112,6 +1112,11 @@ static int pthread_timedjoin_internal(pthread_t pthread, void **status, k_timeou
        }
 
        ret = k_thread_join(&t->thread, timeout);
+       if (ret != 0) {
+               SYS_SEM_LOCK(&pthread_pool_lock) {
+                       t->attr.detachstate = PTHREAD_CREATE_JOINABLE;
+               }
+       }
        if (ret == -EBUSY) {
                return EBUSY;
        } else if (ret == -EAGAIN) {

@cfriedt Thank you for sending this patch. I have applied it and rebased. Let me know, what you think

@cfriedt This seems to have fixed the tests. Could you resolve all conversations you consider resolved and then I will attempt to fix the rests (naming, return codes, ... etc.).

cfriedt
cfriedt previously approved these changes Dec 9, 2024
Copy link
Member

Choose a reason for hiding this comment

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

The comments should match the updated sleep time

Copy link
Contributor Author

Choose a reason for hiding this comment

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

adjusted. Nice catch.

Copy link
Member

Choose a reason for hiding this comment

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

I think it would be nice to pass the sleep time as arg as well:

Suggested change
zassert_ok(pthread_create(&th, NULL, timedjoin_thread, NULL));
useconds_t sleep_time;
...
/* Creating a threads that exits after 200ms */
sleep_time = USEC_PER_MSEC * 200U;
zassert_ok(pthread_create(&th, NULL, timedjoin_thread, (void *)sleep_time);

but probably just personal preference, so non-blocking

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Is a useconds_t guaranteed to fit into a void *?
For now, I have adjusted the comment.

Copy link
Member

Choose a reason for hiding this comment

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

It's not a bad suggestion, but INT_TO_POINTER() and POINTER_TO_INT() should be used.

Copy link
Member

Choose a reason for hiding this comment

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

Also, we should use "create a thread" instead of "create a threads".

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have added this. But with type int instead of useconds_t, so that I could use the INT_TO_POINTER/POINTER_TO_INT macros. Let me know what you think.

Copy link
Member

Choose a reason for hiding this comment

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

Could have use the sleep_time variable if my suggestion above is adopted

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I generally like the sugestion. See my concern above.

Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
/* Attempting to join immediately should fail */
/* Attempting to join without blocking should fail */

I was wondering why the comment says 'join immediately' when we slept for 100ms above

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fair enough. I adjusted to /* Attempting to join, when thread is still running, should fail */, what do you think?

Copy link
Member

Choose a reason for hiding this comment

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

Just thought that this might be clearer (at least for me)

Suggested change
/* Attempting to join immediately should succeed now */
/* Attempting to join without blocking should succeed now */

Copy link
Contributor Author

Choose a reason for hiding this comment

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

applied. Thanks.

Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
/* Creating a threads that exits after 200ms*/
/* Creating a thread that exits after 200ms*/

Copy link
Member

Choose a reason for hiding this comment

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

Also, we should use "create a thread" instead of "create a threads".

@ClaCodes
Copy link
Contributor Author

@cfriedt @ycsin Thanks for the suggestions and fixes.
I tried to apply them. Please have another look.

These functions can be used to join pthreads in a non-standard way.
The function pthread_tryjoin will not block and simply test whether the
thread has exited already. The function pthread_timed_join will only block
until the specified time. The functions are wrappers for calling the
k_thread_join with timeout K_NO_WAIT and with a specific timeout as opposed
to calling it with K_FOREVER.

Signed-off-by: Cla Galliard <[email protected]>
Test for the non-standard but useful pthread_timed_join- and
pthread_try_join-functions.

Signed-off-by: Cla Galliard <[email protected]>
@ClaCodes
Copy link
Contributor Author

@cfriedt @ycsin It looks like it is passing. Is there anything missing?

@cfriedt cfriedt requested a review from ycsin December 14, 2024 22:43
@ClaCodes
Copy link
Contributor Author

@ycsin @cfriedt Thank you for your support on this.
It still says 'Merging is blocked`. Do you require any more action from my side?

@ycsin
Copy link
Member

ycsin commented Dec 15, 2024

@ycsin @cfriedt Thank you for your support on this.
It still says 'Merging is blocked`. Do you require any more action from my side?

Just sit back and relax - you will be notified if there's another review/ when it get merged

@kartben kartben merged commit b0baeee into zephyrproject-rtos:main Dec 15, 2024
26 checks passed
@github-actions
Copy link

Hi @ClaCodes!
Congratulations on getting your very first Zephyr pull request merged 🎉🥳. This is a fantastic achievement, and we're thrilled to have you as part of our community!

To celebrate this milestone and showcase your contribution, we'd love to award you the Zephyr Technical Contributor badge. If you're interested, please claim your badge by filling out this form: Claim Your Zephyr Badge.

Thank you for your valuable input, and we look forward to seeing more of your contributions in the future! 🪁

@ClaCodes ClaCodes deleted the pthread_timed_join branch October 19, 2025 19:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: POSIX POSIX API Library

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants