Revision 1b6b029e linux-user/syscall.c
b/linux-user/syscall.c | ||
---|---|---|
762 | 762 |
} |
763 | 763 |
return ret; |
764 | 764 |
} |
765 |
|
|
766 |
/* this stack is the equivalent of the kernel stack associated with a |
|
767 |
thread/process */ |
|
768 |
#define NEW_STACK_SIZE 8192 |
|
769 |
|
|
770 |
static int clone_func(void *arg) |
|
771 |
{ |
|
772 |
CPUX86State *env = arg; |
|
773 |
cpu_loop(env); |
|
774 |
/* never exits */ |
|
775 |
return 0; |
|
776 |
} |
|
777 |
|
|
778 |
int do_fork(CPUX86State *env, unsigned int flags, unsigned long newsp) |
|
779 |
{ |
|
780 |
int ret; |
|
781 |
uint8_t *new_stack; |
|
782 |
CPUX86State *new_env; |
|
783 |
|
|
784 |
if (flags & CLONE_VM) { |
|
785 |
if (!newsp) |
|
786 |
newsp = env->regs[R_ESP]; |
|
787 |
new_stack = malloc(NEW_STACK_SIZE); |
|
788 |
|
|
789 |
/* we create a new CPU instance. */ |
|
790 |
new_env = cpu_x86_init(); |
|
791 |
memcpy(new_env, env, sizeof(CPUX86State)); |
|
792 |
new_env->regs[R_ESP] = newsp; |
|
793 |
new_env->regs[R_EAX] = 0; |
|
794 |
ret = clone(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env); |
|
795 |
} else { |
|
796 |
/* if no CLONE_VM, we consider it is a fork */ |
|
797 |
if ((flags & ~CSIGNAL) != 0) |
|
798 |
return -EINVAL; |
|
799 |
ret = fork(); |
|
800 |
} |
|
801 |
return ret; |
|
802 |
} |
|
803 |
|
|
765 | 804 |
#endif |
766 | 805 |
|
806 |
|
|
767 | 807 |
void syscall_init(void) |
768 | 808 |
{ |
769 | 809 |
#define STRUCT(name, list...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def); |
... | ... | |
788 | 828 |
#ifdef HAVE_GPROF |
789 | 829 |
_mcleanup(); |
790 | 830 |
#endif |
831 |
/* XXX: should free thread stack and CPU env */ |
|
791 | 832 |
_exit(arg1); |
792 | 833 |
ret = 0; /* avoid warning */ |
793 | 834 |
break; |
... | ... | |
807 | 848 |
ret = do_brk((char *)arg1); |
808 | 849 |
break; |
809 | 850 |
case TARGET_NR_fork: |
810 |
ret = get_errno(fork());
|
|
851 |
ret = get_errno(do_fork(cpu_env, SIGCHLD, 0));
|
|
811 | 852 |
break; |
812 | 853 |
case TARGET_NR_waitpid: |
813 | 854 |
{ |
... | ... | |
1241 | 1282 |
case TARGET_NR_sigreturn: |
1242 | 1283 |
goto unimplemented; |
1243 | 1284 |
case TARGET_NR_clone: |
1244 |
goto unimplemented; |
|
1285 |
ret = get_errno(do_fork(cpu_env, arg1, arg2)); |
|
1286 |
break; |
|
1245 | 1287 |
case TARGET_NR_setdomainname: |
1246 | 1288 |
ret = get_errno(setdomainname((const char *)arg1, arg2)); |
1247 | 1289 |
break; |
... | ... | |
1310 | 1352 |
case TARGET_NR_sysfs: |
1311 | 1353 |
goto unimplemented; |
1312 | 1354 |
case TARGET_NR_personality: |
1313 |
ret = get_errno(mprotect((void *)arg1, arg2, arg3));
|
|
1355 |
ret = get_errno(personality(arg1));
|
|
1314 | 1356 |
break; |
1315 | 1357 |
case TARGET_NR_afs_syscall: |
1316 | 1358 |
goto unimplemented; |
... | ... | |
1447 | 1489 |
case TARGET_NR_sched_get_priority_max: |
1448 | 1490 |
case TARGET_NR_sched_get_priority_min: |
1449 | 1491 |
case TARGET_NR_sched_rr_get_interval: |
1492 |
goto unimplemented; |
|
1493 |
|
|
1450 | 1494 |
case TARGET_NR_nanosleep: |
1495 |
{ |
|
1496 |
struct target_timespec *target_req = (void *)arg1; |
|
1497 |
struct target_timespec *target_rem = (void *)arg2; |
|
1498 |
struct timespec req, rem; |
|
1499 |
req.tv_sec = tswapl(target_req->tv_sec); |
|
1500 |
req.tv_nsec = tswapl(target_req->tv_nsec); |
|
1501 |
ret = get_errno(nanosleep(&req, &rem)); |
|
1502 |
if (target_rem) { |
|
1503 |
target_rem->tv_sec = tswapl(rem.tv_sec); |
|
1504 |
target_rem->tv_nsec = tswapl(rem.tv_nsec); |
|
1505 |
} |
|
1506 |
} |
|
1507 |
break; |
|
1508 |
|
|
1451 | 1509 |
case TARGET_NR_mremap: |
1452 | 1510 |
case TARGET_NR_setresuid: |
1453 | 1511 |
case TARGET_NR_getresuid: |
... | ... | |
1481 | 1539 |
case TARGET_NR_getpmsg: |
1482 | 1540 |
case TARGET_NR_putpmsg: |
1483 | 1541 |
case TARGET_NR_vfork: |
1484 |
ret = get_errno(vfork());
|
|
1542 |
ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD, 0));
|
|
1485 | 1543 |
break; |
1486 | 1544 |
case TARGET_NR_ugetrlimit: |
1487 | 1545 |
case TARGET_NR_truncate64: |
Also available in: Unified diff