overhaul clone syscall wrapping
authorRich Felker <dalias@aerifal.cx>
Sun, 18 Sep 2011 14:14:37 +0000 (10:14 -0400)
committerRich Felker <dalias@aerifal.cx>
Sun, 18 Sep 2011 14:14:37 +0000 (10:14 -0400)
several things are changed. first, i have removed the old __uniclone
function signature and replaced it with the "standard" linux
__clone/clone signature. this was necessary to expose clone to
applications anyway, and it makes it easier to port __clone to new
archs, since it's now testable independently of pthread_create.

secondly, i have removed all references to the ugly ldt descriptor
structure (i386 only) from the c code and pthread structure. in places
where it is needed, it is now created on the stack just when it's
needed, in assembly code. thus, the i386 __clone function takes the
desired thread pointer as its argument, rather than an ldt descriptor
pointer, just like on all other sane archs. this should not affect
applications since there is really no way an application can use clone
with threads/tls in a way that doesn't horribly conflict with and
clobber the underlying implementation's use. applications are expected
to use clone only for creating actual processes, possibly with new
namespace features and whatnot.

include/sched.h
src/internal/pthread_impl.h
src/thread/__set_thread_area.c
src/thread/clone.c
src/thread/forkall.c
src/thread/i386/__set_thread_area.s
src/thread/i386/clone.s
src/thread/pthread_create.c
src/thread/x86_64/clone.s

index 4d8bd3db92e82d5ee79f63f43ca6982e71c20f4c..7b3f1600481c27dce8eb5ba420ddb3a0a3b4d664 100644 (file)
@@ -31,6 +31,33 @@ int     sched_yield(void);
 #define SCHED_FIFO 1
 #define SCHED_RR 2
 
+#ifdef _GNU_SOURCE
+#define CSIGNAL                0x000000ff
+#define CLONE_VM       0x00000100
+#define CLONE_FS       0x00000200
+#define CLONE_FILES    0x00000400
+#define CLONE_SIGHAND  0x00000800
+#define CLONE_PTRACE   0x00002000
+#define CLONE_VFORK    0x00004000
+#define CLONE_PARENT   0x00008000
+#define CLONE_THREAD   0x00010000
+#define CLONE_NEWNS    0x00020000
+#define CLONE_SYSVSEM  0x00040000
+#define CLONE_SETTLS   0x00080000
+#define CLONE_PARENT_SETTID    0x00100000
+#define CLONE_CHILD_CLEARTID   0x00200000
+#define CLONE_DETACHED 0x00400000
+#define CLONE_UNTRACED 0x00800000
+#define CLONE_CHILD_SETTID     0x01000000
+#define CLONE_NEWUTS   0x04000000
+#define CLONE_NEWIPC   0x08000000
+#define CLONE_NEWUSER  0x10000000
+#define CLONE_NEWPID   0x20000000
+#define CLONE_NEWNET   0x40000000
+#define CLONE_IO       0x80000000
+int clone (int (*)(void *), void *, int, void *, ...);
+#endif
+
 #ifdef __cplusplus
 }
 #endif
index 95ec9487baae1f902d798d9a7818cec2990ee4c9..26164d832abd2d7d8bb72e07469a0797b718e6fe 100644 (file)
@@ -22,7 +22,6 @@
 
 struct pthread {
        struct pthread *self;
-       unsigned long tlsdesc[4];
        pid_t tid, pid;
        int tsd_used, errno_val, *errno_ptr;
        volatile uintptr_t cp_sp, cp_ip;
@@ -87,7 +86,7 @@ struct __timer {
 
 pthread_t __pthread_self_init(void);
 
-int __uniclone(void *, void (*)(pthread_t), void *);
+int __clone(int (*)(void *), void *, int, void *, ...);
 int __set_thread_area(void *);
 int __libc_sigaction(int, const struct sigaction *, struct sigaction *);
 int __libc_sigprocmask(int, const sigset_t *, sigset_t *);
index f2ac6e97a61bf745b3b005c621fd4f594f8fdfaf..136be575b8c4245a6cea788763d0081d5602ce25 100644 (file)
@@ -1,4 +1,4 @@
-#include <pthread_impl.h>
+#include "pthread_impl.h"
 
 int __set_thread_area(void *p)
 {
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..339e28a3fe6fb2b12c41921183dd08c819aa8018 100644 (file)
@@ -0,0 +1,10 @@
+#include <errno.h>
+#include "libc.h"
+
+int __clone(int (*func)(void *), void *stack, int flags, void *arg, ...)
+{
+       errno = ENOSYS;
+       return -1;
+}
+
+weak_alias(__clone, clone);
index 403818ec956edab5c5195a185c70ca77a73bb4ab..6810ea50f0aed0200f7158d77b980b3337b3fa79 100644 (file)
@@ -1,3 +1,4 @@
+#if 0
 #include "pthread_impl.h"
 #include <setjmp.h>
 
@@ -64,3 +65,4 @@ pid_t forkall()
        __synccall(do_forkall, &c);
        return c.pid;
 }
+#endif
index a43525ece153bc2b40462f17ba981248d072b82f..cccf1cd3dd751f2a1446d4f927a29aca4b992bbb 100644 (file)
@@ -2,20 +2,21 @@
 .global __set_thread_area
 .type   __set_thread_area,@function
 __set_thread_area:
-       pushl %ebx
-       movl 8(%esp),%ecx
-       movl $-1,4(%ecx)
-       movl %ecx,8(%ecx)
-       movl $0xfffff,12(%ecx)
-       movl $0x51,16(%ecx)
-       leal 4(%ecx),%ebx
-       movl $243,%eax
+       push %ebx
+       push $0x51
+       push $0xfffff
+       push 16(%esp)
+       push $-1
+       mov %esp,%ebx
+       xor %eax,%eax
+       mov $243,%al
        int $128
-       popl %ebx
        testl %eax,%eax
        jnz 1f
-       movl 4(%ecx),%ecx
+       movl (%esp),%ecx
        leal 3(,%ecx,8),%ecx
        movw %cx,%gs
 1:
+       addl $16,%esp
+       popl %ebx
        ret
index 7af5f5db0715032af8f5745d48670ea0ed5f50d6..bebf01a3a16f03df03831e78bb7ff662cdcf8606 100644 (file)
@@ -1,26 +1,51 @@
 .text
-.global __uniclone
-.type   __uniclone,@function
-__uniclone:
-       movl    4(%esp),%ecx
-       subl    $24,%ecx
-       movl    8(%esp),%eax
-       movl    %eax,16(%ecx)
-       movl    12(%esp),%eax
-       movl    %eax,24(%ecx)
-       pushl   %ebx
-       pushl   %esi
-       pushl   %edi
-       pushl   %ebp
-       movl    %eax,8(%eax)
-       leal    20(%eax),%edx
-       leal    4(%eax),%esi
-       movl    %edx,%edi
-       movl    $0x7d0f00,%ebx
-       movl    $120,%eax
-       int     $128
-       popl    %ebp
-       popl    %edi
-       popl    %esi
-       popl    %ebx
+.global __clone
+.weak clone
+.type   __clone,@function
+.type   clone,@function
+__clone:
+clone:
+       push %ebp
+       mov %esp,%ebp
+       push %ebx
+       push %esi
+       push %edi
+
+       xor %eax,%eax
+       push $0x51
+       mov %gs,%ax
+       push $0xfffff
+       shr $3,%eax
+       push 28(%ebp)
+       push %eax
+       mov $120,%al
+
+       mov 12(%ebp),%ecx
+       mov 16(%ebp),%ebx
+       and $-16,%ecx
+       sub $16,%ecx
+       mov 20(%ebp),%edi
+       mov %edi,(%ecx)
+       mov 24(%ebp),%edx
+       mov %esp,%esi
+       mov 32(%ebp),%edi
+       mov 8(%ebp),%ebp
+       int $128
+       test %eax,%eax
+       jnz 1f
+
+       mov %ebp,%eax
+       xor %ebp,%ebp
+       call *%eax
+       mov %eax,%ebx
+       xor %eax,%eax
+       inc %eax
+       int $128
+       hlt
+
+1:     add $16,%esp
+       pop %edi
+       pop %esi
+       pop %ebx
+       pop %ebp
        ret
index bef25539cbb362474ce44b2b5e16efb25bbf3b68..f7768d8d03dd1dc9e8c5c26c974d9a86a8176571 100644 (file)
@@ -52,11 +52,13 @@ void __pthread_do_unregister(struct __ptcb *cb)
        self->cancelbuf = self->cancelbuf->__next;
 }
 
-static void start(pthread_t self)
+static int start(void *p)
 {
+       pthread_t self = p;
        if (self->unblock_cancel)
                __syscall(SYS_rt_sigprocmask, SIG_UNBLOCK, SIGPT_SET, 0, 8);
        pthread_exit(self->start(self->start_arg));
+       return 0;
 }
 
 #define ROUND(x) (((x)+PAGE_SIZE-1)&-PAGE_SIZE)
@@ -115,14 +117,12 @@ int pthread_create(pthread_t *res, const pthread_attr_t *attr, void *(*entry)(vo
        new->tsd = (void *)tsd;
        if (attr) new->detached = attr->_a_detach;
        new->unblock_cancel = self->cancel;
-       memcpy(new->tlsdesc, self->tlsdesc, sizeof new->tlsdesc);
-       new->tlsdesc[1] = (uintptr_t)new;
-       stack = (void *)((uintptr_t)new-1 & ~(uintptr_t)15);
+       stack = (void *)new;
 
        __synccall_lock();
 
        a_inc(&libc.threads_minus_1);
-       ret = __uniclone(stack, start, new);
+       ret = __clone(start, stack, 0x7d8f00, new, &new->tid, new, &new->tid);
 
        __synccall_unlock();
 
index bf128a47536d19b04acca470bebf89addc4a7d33..4db081cd26f17c3de3e655c08d9586cce1e17220 100644 (file)
@@ -1,21 +1,30 @@
-/* Copyright 2011 Nicholas J. Kain, licensed GNU LGPL 2.1 or later */
 .text
-.global __uniclone
-.type   __uniclone,@function
-/* rdi = child_stack, rsi = start, rdx = pthread_struct */
-__uniclone:
-        subq    $8,%rsp         /* pad parent stack to prevent branch later */
-        subq    $24,%rdi        /* grow child_stack */
-        mov     %rsi,8(%rdi)    /* push start onto child_stack as return ptr */
-        mov     %rdx,0(%rdi)    /* push pthread_struct onto child_stack */
-        mov     %rdx,%r8        /* r8 = tls */
-        mov     %rdi,%rsi       /* rsi = child_stack */
-        leaq    40(%rdx),%r10   /* r10 = child_id */
-        movl    $56,%eax        /* clone syscall number */
-        movl    $0x7d0f00,%edi  /* rdi = flags */
-        mov     %r10,%rdx       /* rdx = parent_id */
-        syscall                 /* clone(flags, child_stack, parent_id,
-                                 *       child_id, tls) */
-        pop     %rdi            /* child stack: restore pthread_struct
-                                 * parent stack: undo rsp displacement */
-        ret
+.global __clone
+.weak clone
+.type   __clone,@function
+.type   clone,@function
+__clone:
+clone:
+       xor %eax,%eax
+       mov $56,%al
+       mov %rdi,%r11
+       mov %rdx,%rdi
+       mov %r8,%rdx
+       mov %r9,%r8
+       mov 8(%rsp),%r10
+       mov %r11,%r9
+       and $-16,%rsi
+       sub $8,%rsi
+       mov %rcx,(%rsi)
+       syscall
+       test %eax,%eax
+       jnz 1f
+       xor %ebp,%ebp
+       pop %rdi
+       call *%r9
+       mov %eax,%edi
+       xor %eax,%eax
+       mov $60,%al
+       syscall
+       hlt
+1:     ret