Blame src/thread/nt32/clone.c
|
|
9912f3 |
#define _GNU_SOURCE
|
|
|
9912f3 |
|
|
|
296178 |
#include <syscall.h>
|
|
|
9912f3 |
#include <sched.h>
|
|
|
296178 |
|
|
|
cde352 |
/* take advantage of i686 vararg abi */
|
|
|
cde352 |
#define __clone ____clone
|
|
|
cde352 |
#include "pthread_impl.h"
|
|
|
cde352 |
#undef __clone
|
|
|
cde352 |
|
|
|
296178 |
struct pt_regs {
|
|
|
296178 |
unsigned long ebx;
|
|
|
296178 |
unsigned long ecx;
|
|
|
296178 |
unsigned long edx;
|
|
|
296178 |
unsigned long esi;
|
|
|
296178 |
unsigned long edi;
|
|
|
cde352 |
unsigned long ebp;
|
|
|
cde352 |
unsigned long eax;
|
|
|
cde352 |
unsigned long xds;
|
|
|
cde352 |
unsigned long xes;
|
|
|
cde352 |
unsigned long xfs;
|
|
|
cde352 |
unsigned long xgs;
|
|
|
296178 |
unsigned long orig_eax;
|
|
|
296178 |
unsigned long eip;
|
|
|
cde352 |
unsigned long xcs;
|
|
|
296178 |
unsigned long eflags;
|
|
|
296178 |
unsigned long esp;
|
|
|
cde352 |
unsigned long xss;
|
|
|
cde352 |
unsigned long sbase;
|
|
|
cde352 |
unsigned long slimit;
|
|
|
cde352 |
unsigned long sbottom;
|
|
|
296178 |
};
|
|
|
296178 |
|
|
|
296178 |
typedef long __sys_clone(
|
|
|
296178 |
unsigned long flags,
|
|
|
296178 |
void * child_stack,
|
|
|
296178 |
void * ptid,
|
|
|
296178 |
void * ctid,
|
|
|
296178 |
struct pt_regs *regs);
|
|
|
296178 |
|
|
|
296178 |
extern unsigned long ** __syscall_vtbl;
|
|
|
296178 |
|
|
|
296178 |
int __clone(
|
|
|
296178 |
__entry_point * fn,
|
|
|
296178 |
void * child_stack,
|
|
|
296178 |
int flags,
|
|
|
296178 |
void * arg,
|
|
|
296178 |
int * ptid,
|
|
|
296178 |
void * pthread_self_addr,
|
|
|
296178 |
int * ctid)
|
|
|
296178 |
{
|
|
|
296178 |
struct pt_regs regs;
|
|
|
296178 |
__sys_clone * pfn_clone;
|
|
|
cde352 |
pthread_t pthread;
|
|
|
296178 |
|
|
|
296178 |
regs.eip = (unsigned long)fn;
|
|
|
296178 |
regs.ecx = (unsigned long)arg;
|
|
|
296178 |
regs.edx = (unsigned long)pthread_self_addr;
|
|
|
296178 |
|
|
|
296178 |
pfn_clone = (__sys_clone *)(__syscall_vtbl[SYS_clone]);
|
|
|
296178 |
|
|
|
cfeeec |
if (flags == (CLONE_VM|CLONE_VFORK|SIGCHLD)) {
|
|
|
9912f3 |
regs.sbase = 0;
|
|
|
9912f3 |
regs.slimit = 0;
|
|
|
9912f3 |
regs.sbottom = 0;
|
|
|
9912f3 |
|
|
|
9912f3 |
return (int)pfn_clone(
|
|
|
9912f3 |
flags,
|
|
|
9912f3 |
child_stack,
|
|
|
9912f3 |
0,0,®s;;
|
|
|
9912f3 |
}
|
|
|
9912f3 |
|
|
|
cde352 |
pthread = (pthread_t)pthread_self_addr;
|
|
|
cde352 |
regs.sbase = (unsigned long)pthread->stack;
|
|
|
cde352 |
regs.slimit = regs.sbase - pthread->stack_size;
|
|
|
cde352 |
regs.sbottom = regs.slimit - pthread->guard_size;
|
|
|
cde352 |
|
|
|
296178 |
return (int)pfn_clone(
|
|
|
296178 |
flags,
|
|
|
296178 |
child_stack,
|
|
|
296178 |
ptid,
|
|
|
296178 |
ctid,
|
|
|
296178 |
®s;;
|
|
|
296178 |
}
|