#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
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;
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 *);
-#include <pthread_impl.h>
+#include "pthread_impl.h"
int __set_thread_area(void *p)
{
+#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);
+#if 0
#include "pthread_impl.h"
#include <setjmp.h>
__synccall(do_forkall, &c);
return c.pid;
}
+#endif
.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
.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
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)
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();
-/* 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