-
Notifications
You must be signed in to change notification settings - Fork 2k
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
Thread-local memory #506
Thread-local memory #506
Conversation
👍 |
I further just found the discussion "Thread-local Storage" from Nov 14th 2013 on the developer mailing-list. In my implementation there is no need to keep track of any pointer, as you can always acces the thread specific memory through |
@@ -55,6 +55,8 @@ | |||
cib_t msg_queue; | |||
msg_t *msg_array; | |||
|
|||
char *lcoal_mem; |
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.
typo?
Yes, it was -> came from copying after my last compilation, shame on me... |
Why not just
or something similar. |
would work, but I guess its not really user-friendly -> for this method you really have to know the core and i guess one of the RIOT goals is to make it easily programmable by users without having go know all the OS-details?! |
well,
No need to extend the tcb. |
This was acutally my first implementation, but for a reason I changed again... Now I just have to remember the reason: I was trying to put the thread-local memory in after calling thread_create (by altering the already initialized tcb), and that lead to problems depending on how the platform handles it's stack. But yours looks better, I will adept the PR! |
Setting thread's status to |
Ok, new try, this acutally looks way cleaner (why havn't I thought about this...). I made one further enhancement by 'hijacking' a bit in the tcb->status field to mark if a thread-local memory exists. |
- new setting the STATUS_LOCAL_MEMORY flag - not trying to set the tcb->local_mem field anymore
|
what do you need |
if you don't have a measure to find out if thread-local memory is used, thread_get_local_mem() would return either 1) the correct address to the local memory or 2) something something. And what to you mean with the bitfield, status is uint16 and |
@kaspar030 means that adding this "flag" to the
to see what he mean. ;) |
Ok, I see :-) I gues there are three possible ways to solve this:
|
Let's got with well documented 2) for now. Users using get_localmem must have used create_localmem before. Two simple functions for professionals understanding memory in C... Use-cases are hard to find, anyways. Your uart example can easily be rewritten without this kind of TLS. |
Seems sensible to be, so #2 it is for now. But I would be very interested in the rewritten version of my example (and if that would then work for further usages I have thought of...)! |
Something like
|
@kaspar030 Actually that is exactly the code I use in my other projects (where I don't yet use RIOT). In my opinion it has the disadvantage of introducing a lot of configuration values. For example you have to statically define the number of instances for say high-level uarts, smb380s, cc1100s etc etc. So this means, that your board-config needs to define all these numbers. But especially for some multi-purpose boards as the STM32discoverys, where you connect devices as to your needs, you would always have to edit the board-config or install some other means to set those values in your user-makefile or so. With the thread local memory you could go completely around this issue, all you need to do is call the init-function of your device and tell it, which pins/periphial to use. For example init_smb380(SPI_1, GPIO_2, GPIO_3) will create an instance of the smb380 driver which uses the given periphials, no further configuration needed... |
Well,
... and have thread local my_state ... keep it simple. ;) |
Yes, but again, in that case each function that is called from the main loop would need a pointer to that struct in the argument list, and that does not work well with my sense for aesthetic :-) But if thats what we agree on, I could do with it... |
Otherwise every function that is called would need a function call to "thread_get_localmem"... If there can be multiple instances of an "uart driver", you should use normal C object orientation techniques. Use a struct as object state and hand that to every "method" you call. You're using a global variable here. That is against (my sense of) asthetics, even if you put the global out of reach, call it TLS and then make it accessible through stack magic... |
I'm strictly against C OO techniques. C is not meant to be object oriented and there's a good reason for it: performance! |
Are you serious? |
I mean, we're using structs as objects and functions with the struct as parameter for the object instance all over the place... |
Do we? Then let's remove this shit! |
While we're at it, we can also finally remove the C stuff altogether. Performance is king! |
Agreed. But let's open a new PR for that, are you gonna do it? |
To get this serious again: What I've meant was that I want to avoid constructs like
and so one, which leads to nice oo interface but a nasty chain of passing around function pointers. |
@OlegHahm I know and I'm with you there. ;) |
@haukepetersen, can you rebase? |
discussed with @haukepetersen close |
@haukepetersen @mehlis How about you share the reasons for closing it here? |
I think having thread-local storage would be nice. |
I came to the conclusion that (at least for the applications I had the thread-local storage in mind) it was not useful. At the moment I can not really think of any application that can't be done (in an easy way) without this PR, so I see no reason to merge it... |
This PR is a proposal for an implementation to reserve a memory section of the stack memory for thread-local memory. This is especially useful for device drivers that run in their own thread, as there can be any amount of driver instances without the need of reserving memory inside the driver code in advance.
For example if you want to use multiple UARTs on a board, you can just create one thread for each device and each thread will use the same code. The usage could look like this:
The advantages of this implementation over using malloc() are:
The only drawback is the use of sizeof(char*) bytes more in the tcb_t struct (e.g. 80byte when having 20 threads on a 32-bit machine...)
Does this work for you or does anyone have a better idea how to do this? I'm open for discussion!