Would userpace_s need to have an additional function pointer for
pthread_cleanup? Similar to pthread_startup?
Is the up_pthread_start/pthread_startup functions a good example to
follow
for how to call in user mode?
If you look at Issue 1263, that is not what I am proposing:
https://github.com/apache/incubator-nuttx/issues/1263. That is
similar to the solution in the TODO list. But it is overly complex
and would not work for KERNEL mode where there is no userspace_s.
I am rather proposing dividing pthread_exit() into two pieces: A user
space function called pthread_exit() the resides in
libs/lib/pthread/lib_pthread_exit.c and a kernel space functions, say
nxthread_exit() that resides in sched/pthread/pthread_exit.c:
1. pthread_exit() in libs/lib/pthread/lib_pthread_exit.c would
execute when the thread exits. It would only do the things that need
to be done in the same context as the pthread execution environment.
This would including executing all of the pthread_cleanup functions.
That would would have to be migrated from
sched/pthread/pthread_exit.c. It would also include the new logic to
execute the the new pthread-specific data destructors. And, finally,
is would all the nxthread_exit() system function.
2. nxthread_exit() would become a system call (replacing the existing
system pthread_exit() system call in syscall/ and in
include/sys/syscall*.h.
3. nxthread_exit() would essentially be the existing pthread exit
logic sans pthread_cleanup function calls.
This sounds straight forward, but there is a complication: We also
have to catch the case were the pthread main function does not call
pthread_exit() but instead just returns. Currently that is handled
in the function pthread_start() in sched/pthread/pthread_create.c.
In FLAT mode, it just calls the pthread main function; in other modes
it calls up_pthread_start() which will switch to user mode.
I have not thought through all of the details, but this would require
changes like:
1. Instead of calling the pthread main function, pthread_start()
would call a trampoline function in user-space. This already happens
in the PROTECTED mode via the pthread_startup() function in the
userspace_s structure. But not in KERNEL mode. In KERNEL mode, it
uses the SYS_pthread_start system call to start the pthread main
function directly.
2. pthread_start would not call pthread_exit().
3. The trampoline function in user space would simply call the
pthread main function and call pthread_exit() is the pthread main
function returns.
Hmm.. The kernel gets the address of the pthread trampoline from the
userspace_s structure. How would the kernel know the address of a
process specific pthread thread trampoline function in the KERNEL
mode? I am not sure righit now.
The design that you describe is probably easier to define. But one
objective that I have is to move all of the pthread logic out of the
kernel and into libs/libs/pthread. The pthreads interfaces are not
part of the kernel in other Unix-like implementations. The kernel
does provide certain necessary hooks, but the majority of the
implementation of the pthread logic is implemented in libpthread, in
user-space and not within the kernel. This is a model that I think
that NuttX should follow as well, but things are not well structured
to do that now.
"Hmm.. The kernel gets the address of the pthread trampoline from the
userspace_s structure. How would the kernel know the address of a
process specific pthread thread trampoline function in the KERNEL
mode? I am not sure righit now." ... Yes, after sleeping on it, I
know what would need to happen:
1. Rename pthread_create() in sched/pthread/pthread_create.c to
nxthread_create(). Add on new parameter: The address of the
user-space pthread startup function. Instead of calling the pthread
main entry (directly or indirectly), pthread_start() would scall the
pthread startup function, passing it the real address of the pthread
main function.
The call to pthread_exist would be removed from pthread_startup() and
move into a new function in user space.
2. Add libs/libc/pthread/lib_pthread_start.c that would contain two
trivial functions:
static void pthread_startup(pthread_startroutine_t startroutine,
pthread_addr_t arg)
{
pthread_exit(startroutine(arg));
}
int pthread_create(FAR pthread_t *thread, FAR const pthread_attr_t *attr,
pthread_startroutine_t startroutine, pthread_addr_t
arg)
{
return nxthread_create(pthread_startup, thread, attr, startroutine,
arg);
}
And that should handle all cases.
I created draft PR 1328 that adds the basic changes to move the
trampoline into user space. Please help be contributing to this
branch. You are a committer so you should have privileges to modify my
nuttx_incubator/pthread branch.