static int allocate_transition_tls(int id) { /* Libc function to initialize TLS-based locale info for ctype functions. */ extern void __ctype_init(void); /* We want to free and then reallocate the tls rather than simply * reinitializing it because its size may have changed. TODO: not sure if * this is right. 0-ing is one thing, but freeing and reallocating can be * expensive, esp if syscalls are involved. Check out glibc's * allocatestack.c for what might work. */ free_transition_tls(id); void *tcb = allocate_tls(); if (!tcb) { errno = ENOMEM; return -1; } /* Setup some intitial TLS data for the newly allocated transition tls. */ void *temp_tcb = get_tls_desc(); set_tls_desc(tcb); begin_safe_access_tls_vars(); __vcoreid = id; __vcore_context = TRUE; __ctype_init(); end_safe_access_tls_vars(); set_tls_desc(temp_tcb); /* Install the new tls into the vcpd. */ set_vcpd_tls_desc(id, tcb); return 0; }
/* Helper, makes VC ctx tracks uthread as its current_uthread in its TLS. * * Whether or not uthreads have TLS, thread0 has TLS, given to it by glibc. * This TLS will get set whenever we use thread0, regardless of whether or not * we use TLS for uthreads in general. glibc cares about this TLS and will use * it at exit. We can't simply use that TLS for VC0 either, since we don't know * where thread0 will be running when the program ends. */ static void uthread_track_thread0(struct uthread *uthread) { set_tls_desc(get_vcpd_tls_desc(0)); begin_safe_access_tls_vars(); /* We might have a basic uthread already installed (from a prior call), so * free it before installing the new one. */ if (current_uthread) free(current_uthread); current_uthread = uthread; /* We may not be an MCP at this point (and thus not really working with * vcores), but there is still the notion of something vcore_context-like * even when running as an SCP (i.e. its more of a scheduler_context than a * vcore_context). Threfore we need to set __vcore_context to TRUE here to * represent this (otherwise we will hit some asserts of not being in * vcore_context when running in scheduler_context for the SCP. */ __vcore_context = TRUE; end_safe_access_tls_vars(); set_tls_desc(uthread->tls_desc); }