diff options
-rw-r--r-- | include/sched.h | 27 | ||||
-rw-r--r-- | src/internal/pthread_impl.h | 3 | ||||
-rw-r--r-- | src/thread/__set_thread_area.c | 2 | ||||
-rw-r--r-- | src/thread/clone.c | 10 | ||||
-rw-r--r-- | src/thread/forkall.c | 2 | ||||
-rw-r--r-- | src/thread/i386/__set_thread_area.s | 21 | ||||
-rw-r--r-- | src/thread/i386/clone.s | 73 | ||||
-rw-r--r-- | src/thread/pthread_create.c | 10 | ||||
-rw-r--r-- | src/thread/x86_64/clone.s | 49 |
9 files changed, 135 insertions, 62 deletions
diff --git a/include/sched.h b/include/sched.h index 4d8bd3db..7b3f1600 100644 --- a/include/sched.h +++ b/include/sched.h @@ -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 diff --git a/src/internal/pthread_impl.h b/src/internal/pthread_impl.h index 95ec9487..26164d83 100644 --- a/src/internal/pthread_impl.h +++ b/src/internal/pthread_impl.h @@ -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 *); diff --git a/src/thread/__set_thread_area.c b/src/thread/__set_thread_area.c index f2ac6e97..136be575 100644 --- a/src/thread/__set_thread_area.c +++ b/src/thread/__set_thread_area.c @@ -1,4 +1,4 @@ -#include <pthread_impl.h> +#include "pthread_impl.h" int __set_thread_area(void *p) { diff --git a/src/thread/clone.c b/src/thread/clone.c index e69de29b..339e28a3 100644 --- a/src/thread/clone.c +++ b/src/thread/clone.c @@ -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); diff --git a/src/thread/forkall.c b/src/thread/forkall.c index 403818ec..6810ea50 100644 --- a/src/thread/forkall.c +++ b/src/thread/forkall.c @@ -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 diff --git a/src/thread/i386/__set_thread_area.s b/src/thread/i386/__set_thread_area.s index a43525ec..cccf1cd3 100644 --- a/src/thread/i386/__set_thread_area.s +++ b/src/thread/i386/__set_thread_area.s @@ -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 diff --git a/src/thread/i386/clone.s b/src/thread/i386/clone.s index 7af5f5db..bebf01a3 100644 --- a/src/thread/i386/clone.s +++ b/src/thread/i386/clone.s @@ -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 diff --git a/src/thread/pthread_create.c b/src/thread/pthread_create.c index bef25539..f7768d8d 100644 --- a/src/thread/pthread_create.c +++ b/src/thread/pthread_create.c @@ -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(); diff --git a/src/thread/x86_64/clone.s b/src/thread/x86_64/clone.s index bf128a47..4db081cd 100644 --- a/src/thread/x86_64/clone.s +++ b/src/thread/x86_64/clone.s @@ -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 |