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 | 
