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

Initialize main thread pthread structure #59

Closed

Conversation

alexhoppus
Copy link

It seems some steps were missing in pthread structure initialization. This patch does the following:

  • zeroes pthread memory (previously potentially contained garbage after uk_mem_align allocation)
  • initializes tsd
  • sets detach_state to joinable

It seems some steps were missing in pthread structure initialization.
This patch does the following:
- zeroes pthread memory (previously potentially contained garbage after
uk_mem_align allocation)
- initializes tsd
- sets detach_state to joinable

Signed-off-by: Aleksandr Iashchenko <Aleksandr.Iashchenko@opensynergy.com>
@alexhoppus
Copy link
Author

alexhoppus commented Jul 3, 2023

previously discussed here unikraft/unikraft#961 (review)

regarding joinable for main thread please grep here https://pubs.opengroup.org/onlinepubs/009695399/functions/exec.html

@razvand razvand requested review from andreittr and flpostolache and removed request for eduardvintila July 4, 2023 09:38
@razvand razvand added the enhancement New feature or request label Jul 4, 2023
@razvand razvand added this to the v0.14.0 (Prometheus) milestone Jul 4, 2023
@@ -84,6 +84,7 @@
* map + size ----------------------------------------------------------
*/

static const size_t __uk_tsd_size = sizeof(void *) * PTHREAD_KEYS_MAX;
Copy link
Member

@skuenzer skuenzer Jul 4, 2023

Choose a reason for hiding this comment

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

This could be also provided as a macro, no symbol is effectively required.

#define UK_TSD_SIZE (sizeof(void *) * PTHREAD_KEYS_MAX)

I did not check the whole musl code yet, sorry for these questions:

  • Is sizeof(void *) big enough to hold a TSD entry?
  • Isn't somewhere else a size definition that we should use instead (to avoid code-out-of-sync type of errors in the future)?
  • Do we need to allocate TSD here already? The dangerous part is, because __uk_copy_tls() is called on every TLS memory allocation that we crash at any TLS creation (which happens at any thread creation) if we run out of memory instead of returning ENOMEM.

Copy link
Author

@alexhoppus alexhoppus Jul 5, 2023

Choose a reason for hiding this comment

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

Hi @skuenzer . Thank you for the comment.

This could be also provided as a macro, no symbol is effectively required.

Is sizeof(void *) big enough to hold a TSD entry?

Isn't somewhere else a size definition that we should use instead (to avoid code-out-of-sync type of errors in the future)?

Actually, I have not introduced this, that was before me, I just moved this line from below. That is how TSD was created for other threads. If we are not sure if that logic is correct, maybe we should target a different PR to fix this? The macro I can do of course if needed, but again I have not invented this.

Do we need to allocate TSD here already? The dangerous part is, because __uk_copy_tls() is called on every TLS memory allocation that we crash at any TLS creation (which happens at any thread creation) if we run out of memory instead of returning ENOMEM.

Sorry, I don't understand how __uk_copy_tls() relates to this. It is in __uk_init_tp()

Copy link
Contributor

Choose a reason for hiding this comment

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

Re: macro vs static const: I think it hardly matters; in general I'd go for the option of least change.
Re: __uk_copy_tls indeed it's not relevant; all the changed code is in __uk_init_tp which gets called only for the main thread.

Copy link
Member

Choose a reason for hiding this comment

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

Actually, I have not introduced this, that was before me, I just moved this line from below. That is how TSD was created for other threads. If we are not sure if that logic is correct, maybe we should target a different PR to fix this? The macro I can do of course if needed, but again I have not invented this.

True, sorry, it is a pure style preference. I usually do not like introducing a static const variable where a macro achieves the same. But it is true, you just moved it up. I leave it up to you if you want to change it or leave it. I am just less hesitant for changes here (but normally I agree with @andreittr) because this file is purely our code.

Do we need to allocate TSD here already? The dangerous part is, because __uk_copy_tls() is called on every TLS memory allocation that we crash at any TLS creation (which happens at any thread creation) if we run out of memory instead of returning ENOMEM.

Sorry, I don't understand how __uk_copy_tls() relates to this. It is in __uk_init_tp()

In fact, my fault. It seems I was in a rush last time. Forget this comment. Btw, is there a way to return and propagate an error out of __uk_init_tp() instead of crashing?

Copy link
Contributor

@kubanrob kubanrob Aug 8, 2023

Choose a reason for hiding this comment

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

Btw, is there a way to return and propagate an error out of __uk_init_tp() instead of crashing?

If we propagate this error up, it will end up in ukarch_tls_tcb_init, which then requires changes to both lib-musl and the Unikraft code that calls it. I am also not sure what the calling code could do to fix this, other then crash in Unikraft.

Copy link
Author

Choose a reason for hiding this comment

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

Btw, is there a way to return and propagate an error out of __uk_init_tp() instead of crashing?

We can propagate, but it is not clear for what purpose. If we can't allocate tsd even for init thread, then it is a fatal error and we can't recover from that.

I usually do not like introducing a static const variable where a macro achieves the same. But it is true, you just moved it up. I leave it up to you if you want to change it or leave it.

I prefer to leave as is.

Copy link
Member

Choose a reason for hiding this comment

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

Yes, this makes sense, and I think we should change the return type of __uk_init_tp from int to void.

@kubanrob kubanrob requested a review from skuenzer July 11, 2023 09:38
@razvand
Copy link
Contributor

razvand commented Aug 5, 2023

@alexhoppus , @kubanrob , could you please ensure this PR is updated in the next days to have it part of the 0.14 release?

@kubanrob
Copy link
Contributor

kubanrob commented Aug 5, 2023

@razvand To be honest I am not sure what exactly needs to be changed given @alexhoppus and @andreittr answers.

@skuenzer Please review again given the answers. To me it seems like the requested three changes are not really needed / desired.

macro

@skuenzer

  • Is sizeof(void *) big enough to hold a TSD entry?
  • Isn't somewhere else a size definition that we should use instead (to avoid code-out-of-sync type of errors in the future)?

@alexhoppus

Actually, I have not introduced this, that was before me, I just moved this line from below. That is how TSD was created for other threads.

@andreittr

macro vs static const: I think it hardly matters; in general I'd go for the option of least change.

TSD

@skuenzer

Do we need to allocate TSD here already? The dangerous part is, because __uk_copy_tls() is called on every TLS memory allocation that we crash at any TLS creation

@alexhoppus

__uk_copy_tls() relates to this. It is in __uk_init_tp()

@andreittr

__uk_copy_tls indeed it's not relevant; all the changed code is in __uk_init_tp which gets called only for the main thread.

@andreittr
Copy link
Contributor

@razvand To be honest I am not sure what exactly needs to be changed given @alexhoppus and @andreittr answers.

No changes per se, but there are some pending questions in the latest comment from @skuenzer and in my review above.
@alexhoppus could you please have a look?

@alexhoppus
Copy link
Author

alexhoppus commented Aug 8, 2023

but there are some pending questions in the latest comment from @skuenzer and in my review above.

@andreittr I answered about error propagation and macro vs static const questions. I don't see any other questions. Please let me know if I missed something. Thank you.

* - information about stack
* - canary
*/
memset(td, 0, sizeof(*td));
Copy link
Contributor

Choose a reason for hiding this comment

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

  • Is a complete zeroing out of memory ok here? The init function called for other threads (uk_thread_uktcb_init) seems to set a few important fields (stack & self pointer); are these set somewhere else for the main thread?
  • In the interest of not repeating oneself, we shouldn't duplicate the tcb/tsd init code here; we likely can't piggyback on top of uk_thread_uktcb_init and call it directly, but can we factor out the tcb/td init code into a subroutine called by both?

Copy link
Author

@alexhoppus alexhoppus Aug 9, 2023

Choose a reason for hiding this comment

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

The init function called for other threads (uk_thread_uktcb_init) seems to set a few important fields (stack & self pointer)

Yes, there are several things which are not initialized, that is specified in the FIXME block above memset. self pointer is set here. The stack is not set, I have not found an easy way to propagate this information to __uk_init_tp and that will affect related pthread api which retrieves stack information, however that also didn't work before. There is a way to do that, and that relates to your second question.

we likely can't piggyback on top of uk_thread_uktcb_init

I think that is exactly what we should do, but to do that properly, I assume we should also propagate / initialize earlier uk_thread for main thread Ideally, the mechanic for creating init thread & native threads should be the same and that might be the target for the refactoring. The other approaches like creating some subroutine unifying parts of uk_thread_uktcb_init and __uk_init_tp I don't like. My suggestion is to merge this and then to target a separate pr for refactoring. But in case if you insist, I can do that in this PR, however, as I said I don't see it as a small change,so I'm not sure that will be in line with the purpose of PR (bugfix).

Copy link
Member

@skuenzer skuenzer Aug 9, 2023

Choose a reason for hiding this comment

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

Hum... it sounds like that we probably should brainstorm and discuss the initialization unification. I am not sure what you have in mind for unifying it for the init thread with a refactoring of uk_thread_uktcb_init but I am curious. I agree with you that this would be beyond the purpose of this PR. On the other hand, I think, @andreittr just commented about a smaller deduplication work within this file for improving the code readability without changing the model right now which also sounds okay to me. Maybe you can explain a bit more why you don't like it.

For full transparency of my opinion: I rather accept and merge the PR "as is" before not having any fix as part of the upcoming release. If some changes need bigger discussions and brainstorming, I am all for a meeting after the release to discuss a solution. On the other hand, minor things that are clear to do, we should try to fix with this PR.

What do you think @alexhoppus , @andreittr , @eduardvintila ?

Copy link
Author

@alexhoppus alexhoppus Aug 10, 2023

Choose a reason for hiding this comment

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

On the other hand, I think, @andreittr just commented about a smaller deduplication work within this file for improving the code readability without changing the model right now which also sounds okay to me. Maybe you can explain a bit more why you don't like it.

There should be possible to make common API (unified function) which could be used for all native threads tcb initialization (including init thread). Maybe that will be just uk_thread_uktcb_init or some other function it is not clear to me yet. Also it makes sense to check what else could we unify on the paths of native threads/init thread initialization. However, that requires some work with external code also, so can't be done in isolated manner. Unifying parts of uk_thread_uktcb_init and __uk_init_tp now looks like a half-measure to me. Anyway, as I said, if you or @andreittr think differently I will do. I don't have particular plan, all above just generic thoughts.

Thank you.

Copy link
Member

Choose a reason for hiding this comment

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

Okay, from my side I think it makes sense to investigate more time after the release for finding a solution. You have my okay for this PR. @andreittr would you prefer restructuring the functions with this PR or we also move this to be discussed as part of the brainstorming as @alexhoppus suggested?

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm ok with merging this fix as-is, seeing that it doesn't break anything, and revisit refactoring later.

@andreittr
Copy link
Contributor

but there are some pending questions in the latest comment from @skuenzer and in my review above.

@andreittr I answered about error propagation and macro vs static const questions. I don't see any other questions. Please let me know if I missed something. Thank you.

Oops, my bad, I had left my review in draft form and it wouldn't show to others; fixed now, my 2 questions should now be visible.

@kubanrob kubanrob requested a review from andreittr August 9, 2023 11:11
Copy link
Member

@skuenzer skuenzer left a comment

Choose a reason for hiding this comment

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

As discussed, let's revisit this code base after a brainstorming discussion about TLS initialization. I am okay with integrating it "as is".

Reviewed-by: Simon Kuenzer simon@unikraft.io

Copy link
Contributor

@andreittr andreittr left a comment

Choose a reason for hiding this comment

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

As discussed, approved as-is, will pursue refactoring later.

Reviewed-by: Andrei Tatar andrei@unikraft.io

Copy link
Contributor

@kubanrob kubanrob left a comment

Choose a reason for hiding this comment

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

Thank you @alexhoppus

Reviewed-by: Robert Kuban robert.kuban@opensynergy.com

@razvand razvand assigned razvand and unassigned eduardvintila Aug 10, 2023
Copy link
Contributor

@razvand razvand left a comment

Choose a reason for hiding this comment

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

Approved-by: Razvan Deaconescu razvand@unikraft.io

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ci/merged enhancement New feature or request
Projects
Status: Done!
Development

Successfully merging this pull request may close these issues.

None yet

7 participants