I've run in to a scenario where multiple calls to glibc/syscalls between two processors of which one was created by calling clone() with CLONE_VM will eventually cause my program to crash.
Based on my understanding, if I inten开发者_如何学Cd to use CLONE_VM t then I must also specify CLONE_SETTLS.
Can anyone give me an example of how to prepare TLS storage for my new clone and how to actually perform the clone() call using CLONE_SETTLS?
Take the following with a grain of salt, as I've only looked at this "during compiles" (no wooden swords here).
Glibc/NPTL uses TLS to store a lot of thread state. TLS points to a per-thread struct pthread pd
(pd
probably means pthread descriptor), allocated in the thread-local stack at allocate_stack()
, called from __pthread_create_2_1()
.
In x86, the first member of struct pthread
is void *tcb
, which should point to a struct user_desc
(its entry number will probably vary between architectures, and probably also between kernel versions, glibc on my system uses 6 for its internal TLS). This tcb
is passed as an argument to do_clone()
.
If you look through those functions, you will see that glibc stores a lot of information on TLS: information about the thread-local stack, whether this program has several threads, robust mutexes list, the thread start routine and its argument, pthread attribute flags, scheduling policy,...
In summary, if you can get away with a real pthread thread, it will be much simpler.
An alternative approach would be to first call clone
and then pthread_create
.
This way you are using the thread library to get a correct TLS (which is located on the stack of the thread).
Example code:
int tmp_run(void *arg) {
void *ret;
pthread_t thread;
// now call the wanted function
pthread_create(&thread, NULL, run, arg);
pthread_join(thread, &ret);
return (long) ret;
}
int main(...) {
...
int clone_pid = clone (tmp_run, stack, flags arg);
...
}
Look at pthread_create if more control over the threads attributes is needed (for example the stack location).
精彩评论