about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--include/sched.h27
-rw-r--r--src/internal/pthread_impl.h3
-rw-r--r--src/thread/__set_thread_area.c2
-rw-r--r--src/thread/clone.c10
-rw-r--r--src/thread/forkall.c2
-rw-r--r--src/thread/i386/__set_thread_area.s21
-rw-r--r--src/thread/i386/clone.s73
-rw-r--r--src/thread/pthread_create.c10
-rw-r--r--src/thread/x86_64/clone.s49
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