PERFORCE change 102283 for review
Roman Divacky
rdivacky at FreeBSD.org
Mon Jul 24 14:11:16 UTC 2006
http://perforce.freebsd.org/chv.cgi?CH=102283
Change 102283 by rdivacky at rdivacky_witten on 2006/07/24 14:10:38
Implement CLONE_TLS semantic for clone() syscall. This let me pass my pthread testing stuff
(trivial 2 threads program). Also make it compilable without -DDEBUG.
Affected files ...
.. //depot/projects/soc2006/rdivacky_linuxolator/i386/linux/linux_machdep.c#22 edit
Differences ...
==== //depot/projects/soc2006/rdivacky_linuxolator/i386/linux/linux_machdep.c#22 (text+ko) ====
@@ -447,10 +447,6 @@
em->child_clear_tid = NULL;
EMUL_RUNLOCK(&emul_lock);
- if (args->flags & CLONE_SETTLS) {
- /* XXX: set the TLS */
- }
-
PROC_LOCK(p2);
p2->p_sigparent = exit_signal;
PROC_UNLOCK(p2);
@@ -461,8 +457,64 @@
if (args->stack)
td2->td_frame->tf_esp = (unsigned int)args->stack;
+ if (args->flags & CLONE_SETTLS) {
+ struct l_user_desc info;
+ int idx;
+ int a[2];
+ struct segment_descriptor sd;
+
+ error = copyin((void *)td->td_frame->tf_esi, &info, sizeof(struct l_user_desc));
+ if (error)
+ return (error);
+
+ idx = info.entry_number;
+
+ /* looks like we're getting the idx we returned
+ * in the set_thread_area() syscall
+ */
+ if (idx != 6 && idx != 3)
+ return (EINVAL);
+
+#ifdef notyet
+ /* this doesnt happen in practice */
+ if (idx == 6) {
+ /* we might copy out the entry_number as 3 */
+ idx = info.entry_number = 3;
+ error = copyout(&info, args->desc, sizeof(struct l_user_desc));
+ if (error)
+ return (error);
+ }
+#endif
+
+ a[0] = LDT_entry_a(&info);
+ a[1] = LDT_entry_b(&info);
+
+ memcpy(&sd, &a, sizeof(a));
#ifdef DEBUG
if (ldebug(clone))
+ printf("Segment created in clone with CLONE_SETTLS: lobase: %x, hibase: %x, lolimit: %x, hilimit: %x, type: %i, dpl: %i, p: %i, xx: %i, def32: %i, gran: %i\n", sd.sd_lobase,
+ sd.sd_hibase,
+ sd.sd_lolimit,
+ sd.sd_hilimit,
+ sd.sd_type,
+ sd.sd_dpl,
+ sd.sd_p,
+ sd.sd_xx,
+ sd.sd_def32,
+ sd.sd_gran);
+#endif
+
+ /* this is taken from i386 version of cpu_set_user_tls() */
+ critical_enter();
+ /* set %gs */
+ td2->td_pcb->pcb_gsd = sd;
+ PCPU_GET(fsgs_gdt)[1] = sd;
+ load_gs(GSEL(GUGS_SEL, SEL_UPL));
+ critical_exit();
+ }
+
+#ifdef DEBUG
+ if (ldebug(clone))
printf(LMSG("clone: successful rfork to %ld, stack %p sig = %d"),
(long)p2->p_pid, args->stack, exit_signal);
#endif
@@ -1185,12 +1237,12 @@
if (__predict_false(imgp->sysent == &elf32_freebsd_sysvec
&& p->p_sysent == &elf_linux_sysvec)) {
struct linux_emuldata *em;
- struct thread *td = FIRST_THREAD_IN_PROC(p);
em = em_find(p->p_pid, EMUL_UNLOCKED);
if (em == NULL) {
#ifdef DEBUG
+ struct thread *td = FIRST_THREAD_IN_PROC(p);
printf(LMSG("we didnt find emuldata for the execing process.\n"));
#endif
return;
More information about the p4-projects
mailing list