PERFORCE change 100719 for review
Roman Divacky
rdivacky at FreeBSD.org
Thu Jul 6 11:05:20 UTC 2006
http://perforce.freebsd.org/chv.cgi?CH=100719
Change 100719 by rdivacky at rdivacky_witten on 2006/07/06 11:04:26
TID handling
o introduction of P_LINUX proc flag
o introduction of linux hooks into exit1() and userret()
o TID handling in i386 version of linuxolator
this has not been tested much. More testing will come once the futexes are finished.
Affected files ...
.. //depot/projects/soc2006/rdivacky_linuxolator/i386/linux/linux_dummy.c#5 edit
.. //depot/projects/soc2006/rdivacky_linuxolator/i386/linux/linux_machdep.c#7 edit
.. //depot/projects/soc2006/rdivacky_linuxolator/i386/linux/linux_proto.h#8 edit
.. //depot/projects/soc2006/rdivacky_linuxolator/i386/linux/linux_syscall.h#8 edit
.. //depot/projects/soc2006/rdivacky_linuxolator/i386/linux/linux_sysent.c#8 edit
.. //depot/projects/soc2006/rdivacky_linuxolator/i386/linux/linux_sysvec.c#5 edit
.. //depot/projects/soc2006/rdivacky_linuxolator/i386/linux/syscalls.master#8 edit
.. //depot/projects/soc2006/rdivacky_linuxolator/kern/kern_exit.c#3 edit
.. //depot/projects/soc2006/rdivacky_linuxolator/kern/subr_trap.c#2 edit
.. //depot/projects/soc2006/rdivacky_linuxolator/sys/proc.h#2 edit
Differences ...
==== //depot/projects/soc2006/rdivacky_linuxolator/i386/linux/linux_dummy.c#5 (text+ko) ====
@@ -73,7 +73,6 @@
DUMMY(epoll_ctl);
DUMMY(epoll_wait);
DUMMY(remap_file_pages);
-DUMMY(set_tid_address);
DUMMY(timer_create);
DUMMY(timer_settime);
DUMMY(timer_gettime);
==== //depot/projects/soc2006/rdivacky_linuxolator/i386/linux/linux_machdep.c#7 (text+ko) ====
@@ -37,6 +37,7 @@
#include <sys/mman.h>
#include <sys/mutex.h>
#include <sys/proc.h>
+#include <sys/queue.h>
#include <sys/resource.h>
#include <sys/resourcevar.h>
#include <sys/signalvar.h>
@@ -61,6 +62,14 @@
#include <i386/include/pcb.h> /* needed for pcb definition in linux_set_thread_area */
+SLIST_HEAD(emuldata_head, linux_emuldata) emuldata_head =
+ SLIST_HEAD_INITIALIZER(emuldata_head);
+struct linux_emuldata *emuldata_headp; /* where we store the emulation data */
+
+static int linux_proc_init(struct thread *, pid_t);
+int linux_proc_exit(struct thread *);
+int linux_userret(struct thread *);
+
struct l_descriptor {
l_uint entry_number;
l_ulong base_addr;
@@ -124,6 +133,8 @@
free(newpath, M_TEMP);
if (error == 0)
error = kern_execve(td, &eargs, NULL);
+ if (error == 0)
+ error = linux_proc_init(td, 0);
return (error);
}
@@ -278,6 +289,9 @@
linux_fork(struct thread *td, struct linux_fork_args *args)
{
int error;
+#if 0
+ struct linux_emuldata *em;
+#endif
#ifdef DEBUG
if (ldebug(fork))
@@ -289,6 +303,16 @@
if (td->td_retval[1] == 1)
td->td_retval[0] = 0;
+ error = linux_proc_init(td, td->td_retval[0]);
+ if (error)
+ return (error);
+
+#if 0
+ /* impossible to not find it */
+ SLIST_FOREACH(em, &emuldata_head, emuldatas)
+ if (em->pid == td->td_retval[0])
+ break;
+#endif
return (0);
}
@@ -307,6 +331,9 @@
/* Are we the child? */
if (td->td_retval[1] == 1)
td->td_retval[0] = 0;
+ error = linux_proc_init(td, td->td_retval[0]);
+ if (error)
+ return (error);
return (0);
}
@@ -316,6 +343,9 @@
#define CLONE_SIGHAND 0x800
#define CLONE_PID 0x1000
#define CLONE_THREAD 0x10000
+#define CLONE_CHILD_CLEARTID 0x00200000
+#define CLONE_CHILD_SETTID 0x01000000
+#define CLONE_PARENT_SETTID 0x00100000
#define THREADING_FLAGS (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND)
@@ -326,11 +356,14 @@
struct proc *p2;
struct thread *td2;
int exit_signal;
+ struct linux_emuldata *em;
#ifdef DEBUG
if (ldebug(clone)) {
- printf(ARGS(clone, "flags %x, stack %x"),
- (unsigned int)args->flags, (unsigned int)args->stack);
+ printf(ARGS(clone, "flags %x, stack %x, parent tid: %x,
+ child tid: %x"),
+ (unsigned int)args->flags, (unsigned int)args->stack,
+ (unsigned int) args->parent_tidptr, (unsigned int)args->child_tidptr);
if (args->flags & CLONE_PID)
printf(LMSG("CLONE_PID not yet supported"));
}
@@ -350,6 +383,7 @@
if (!(args->flags & CLONE_FILES))
ff |= RFFDG;
+
/*
* Attempt to detect when linux_clone(2) is used for creating
* kernel threads. Unfortunately despite the existence of the
@@ -370,6 +404,29 @@
if (error)
return (error);
+ /* create the emuldata */
+ linux_proc_init(td, td->td_retval[0]);
+ SLIST_FOREACH(em, &emuldata_head, emuldatas)
+ if (em->pid == td->td_retval[0])
+ break;
+ /* and adjust it */
+ if (args->flags & CLONE_PARENT_SETTID) {
+ if (args->parent_tidptr == NULL)
+ return (EINVAL);
+ error = copyout(&td->td_proc->p_pid, args->parent_tidptr, sizeof(td->td_proc->p_pid));
+ if (error)
+ return (error);
+ }
+
+ if (args->flags & CLONE_CHILD_CLEARTID)
+ em->child_clear_tid = args->child_tidptr;
+ else
+ em->child_clear_tid = NULL;
+
+ if (args->flags & CLONE_CHILD_SETTID)
+ em->child_set_tid = args->child_tidptr;
+ else
+ em->child_set_tid = NULL;
PROC_LOCK(p2);
p2->p_sigparent = exit_signal;
@@ -961,3 +1018,110 @@
return (linux_kill(td, (struct linux_kill_args *) args));
}
+static int
+linux_proc_init(struct thread *td, pid_t child)
+{
+ struct linux_emuldata *em, *p_em;
+ int found = 0;
+
+ /* XXX: locking? */
+ MALLOC(em, struct linux_emuldata *, sizeof *em, M_LINUX, M_WAITOK | M_ZERO);
+
+ /* exec call */
+ if (child != 0)
+ em->pid = child;
+ em->child_clear_tid = NULL;
+ em->child_set_tid = NULL;
+
+ /* SLIST is inefficient - use hash instead */
+ /* find the emuldata for the parent process */
+ SLIST_FOREACH(p_em, &emuldata_head, emuldatas)
+ if (p_em->pid == td->td_proc->p_pid) {
+ found = 1;
+ break;
+ }
+
+ if (found) {
+ em->clear_tid = p_em->clear_tid;
+ em->set_tid = p_em->set_tid;
+ }
+
+ /* we have to free the old emuldata */
+ if (child == 0) {
+ found = 0;
+ /* lookup the old one */
+ SLIST_FOREACH(p_em, &emuldata_head, emuldatas)
+ if (em->pid == td->td_proc->p_pid) {
+ found = 1;
+ break;
+ }
+ if (found)
+ FREE(em, M_LINUX);
+ }
+
+ SLIST_INSERT_HEAD(&emuldata_head, em, emuldatas);
+
+ /* XXX: sched_lock locking? */
+
+ return (0);
+}
+
+int
+linux_proc_exit(struct thread *td)
+{
+ struct linux_emuldata *em;
+ int error;
+
+ /* find the emuldata */
+ SLIST_FOREACH(em, &emuldata_head, emuldatas)
+ if (em->pid == td->td_proc->p_pid)
+ break;
+
+ if (em->clear_tid != NULL) {
+ int null = 0;
+
+ error = copyout(&null, em->clear_tid, sizeof(null));
+ if (error)
+ return (error);
+
+ /* TODO: futexes stuff */
+ }
+
+ /* clean the stuff up */
+ FREE(em, M_LINUX);
+
+ return (0);
+}
+
+int
+linux_userret(struct thread *td)
+{
+ struct linux_emuldata *em;
+ int error = 0;
+
+ /* find the emuldata */
+ SLIST_FOREACH(em, &emuldata_head, emuldatas)
+ if (em->pid == td->td_proc->p_pid)
+ break;
+
+ if (em->set_tid != NULL)
+ error = copyout(&td->td_proc->p_pid, em->set_tid, sizeof(td->td_proc->p_pid));
+
+ return (error);
+}
+
+int
+linux_set_tid_address(struct thread *td, struct linux_set_tid_address_args *args)
+{
+ struct linux_emuldata *em;
+
+ /* find the emuldata */
+ SLIST_FOREACH(em, &emuldata_head, emuldatas)
+ if (em->pid == td->td_proc->p_pid)
+ break;
+
+ em->clear_tid = args->tidptr;
+ td->td_retval[0] = td->td_proc->p_pid;
+
+ return 0;
+}
==== //depot/projects/soc2006/rdivacky_linuxolator/i386/linux/linux_proto.h#8 (text+ko) ====
@@ -2,7 +2,7 @@
* System call prototypes.
*
* DO NOT EDIT-- this file is automatically generated.
- * $FreeBSD: src/sys/i386/linux/linux_proto.h,v 1.72 2006/06/26 18:37:36 jhb Exp $
+ * $FreeBSD$
* created from FreeBSD: src/sys/i386/linux/syscalls.master,v 1.69 2006/06/26 18:36:16 jhb Exp
*/
@@ -374,6 +374,8 @@
struct linux_clone_args {
char flags_l_[PADL_(l_int)]; l_int flags; char flags_r_[PADR_(l_int)];
char stack_l_[PADL_(void *)]; void * stack; char stack_r_[PADR_(void *)];
+ char parent_tidptr_l_[PADL_(void *)]; void * parent_tidptr; char parent_tidptr_r_[PADR_(void *)];
+ char child_tidptr_l_[PADL_(void *)]; void * child_tidptr; char child_tidptr_r_[PADR_(void *)];
};
struct linux_newuname_args {
char buf_l_[PADL_(struct l_new_utsname *)]; struct l_new_utsname * buf; char buf_r_[PADR_(struct l_new_utsname *)];
@@ -724,7 +726,7 @@
register_t dummy;
};
struct linux_set_tid_address_args {
- register_t dummy;
+ char tidptr_l_[PADL_(int *)]; int * tidptr; char tidptr_r_[PADR_(int *)];
};
struct linux_timer_create_args {
register_t dummy;
==== //depot/projects/soc2006/rdivacky_linuxolator/i386/linux/linux_syscall.h#8 (text+ko) ====
@@ -2,7 +2,7 @@
* System call numbers.
*
* DO NOT EDIT-- this file is automatically generated.
- * $FreeBSD: src/sys/i386/linux/linux_syscall.h,v 1.66 2006/06/26 18:37:36 jhb Exp $
+ * $FreeBSD$
* created from FreeBSD: src/sys/i386/linux/syscalls.master,v 1.69 2006/06/26 18:36:16 jhb Exp
*/
==== //depot/projects/soc2006/rdivacky_linuxolator/i386/linux/linux_sysent.c#8 (text+ko) ====
@@ -2,7 +2,7 @@
* System call switch table.
*
* DO NOT EDIT-- this file is automatically generated.
- * $FreeBSD: src/sys/i386/linux/linux_sysent.c,v 1.73 2006/06/26 18:37:36 jhb Exp $
+ * $FreeBSD$
* created from FreeBSD: src/sys/i386/linux/syscalls.master,v 1.69 2006/06/26 18:36:16 jhb Exp
*/
@@ -277,7 +277,7 @@
{ SYF_MPSAFE | 0, (sy_call_t *)linux_epoll_ctl, AUE_NULL }, /* 255 = linux_epoll_ctl */
{ SYF_MPSAFE | 0, (sy_call_t *)linux_epoll_wait, AUE_NULL }, /* 256 = linux_epoll_wait */
{ SYF_MPSAFE | 0, (sy_call_t *)linux_remap_file_pages, AUE_NULL }, /* 257 = linux_remap_file_pages */
- { SYF_MPSAFE | 0, (sy_call_t *)linux_set_tid_address, AUE_NULL }, /* 258 = linux_set_tid_address */
+ { SYF_MPSAFE | AS(linux_set_tid_address_args), (sy_call_t *)linux_set_tid_address, AUE_NULL }, /* 258 = linux_set_tid_address */
{ SYF_MPSAFE | 0, (sy_call_t *)linux_timer_create, AUE_NULL }, /* 259 = linux_timer_create */
{ SYF_MPSAFE | 0, (sy_call_t *)linux_timer_settime, AUE_NULL }, /* 260 = linux_timer_settime */
{ SYF_MPSAFE | 0, (sy_call_t *)linux_timer_gettime, AUE_NULL }, /* 261 = linux_timer_gettime */
==== //depot/projects/soc2006/rdivacky_linuxolator/i386/linux/linux_sysvec.c#5 (text+ko) ====
@@ -91,6 +91,7 @@
extern int linux_szsigcode;
extern struct sysent linux_sysent[LINUX_SYS_MAXSYSCALL];
+extern SLIST_HEAD(emuldata_head, linux_emuldata) emuldata_head;
SET_DECLARE(linux_ioctl_handler_set, struct linux_ioctl_handler);
SET_DECLARE(linux_device_handler_set, struct linux_device_handler);
@@ -105,6 +106,12 @@
static void exec_linux_setregs(struct thread *td, u_long entry,
u_long stack, u_long ps_strings);
+extern int (*linux_proc_exit_p)(struct thread *);
+extern int (*linux_userret_p)(struct thread *);
+
+extern int linux_userret(struct thread *);
+extern int linux_proc_exit(struct thread *);
+
/*
* Linux syscalls return negative errno's, we do positive and map them
*/
@@ -907,6 +914,9 @@
printf("Linux ELF exec handler installed\n");
} else
printf("cannot insert Linux ELF brand handler\n");
+ SLIST_INIT(&emuldata_head);
+ linux_proc_exit_p = linux_proc_exit;
+ linux_userret_p = linux_userret;
break;
case MOD_UNLOAD:
for (brandinfo = &linux_brandlist[0]; *brandinfo != NULL;
@@ -928,6 +938,8 @@
printf("Linux ELF exec handler removed\n");
} else
printf("Could not deinstall ELF interpreter entry\n");
+ linux_proc_exit_p = NULL;
+ linux_userret_p = NULL;
break;
default:
return EOPNOTSUPP;
==== //depot/projects/soc2006/rdivacky_linuxolator/i386/linux/syscalls.master#8 (text+ko) ====
@@ -219,7 +219,8 @@
118 AUE_FSYNC MNOPROTO { int fsync(int fd); }
119 AUE_SIGRETURN MSTD { int linux_sigreturn( \
struct l_sigframe *sfp); }
-120 AUE_RFORK MSTD { int linux_clone(l_int flags, void *stack); }
+120 AUE_RFORK MSTD { int linux_clone(l_int flags, void *stack, \
+ void *parent_tidptr, void * child_tidptr); }
121 AUE_SYSCTL MNOPROTO { int setdomainname(char *name, \
int len); }
122 AUE_NULL MSTD { int linux_newuname( \
@@ -424,7 +425,7 @@
255 AUE_NULL MSTD { int linux_epoll_ctl(void); }
256 AUE_NULL MSTD { int linux_epoll_wait(void); }
257 AUE_NULL MSTD { int linux_remap_file_pages(void); }
-258 AUE_NULL MSTD { int linux_set_tid_address(void); }
+258 AUE_NULL MSTD { int linux_set_tid_address(int *tidptr); }
259 AUE_NULL MSTD { int linux_timer_create(void); }
260 AUE_NULL MSTD { int linux_timer_settime(void); }
261 AUE_NULL MSTD { int linux_timer_gettime(void); }
==== //depot/projects/soc2006/rdivacky_linuxolator/kern/kern_exit.c#3 (text+ko) ====
@@ -87,6 +87,7 @@
/* Hook for NFS teardown procedure. */
void (*nlminfo_release_p)(struct proc *p);
+int (*linux_proc_exit_p)(struct thread *) = NULL; /* necessary for linuxolator */
/*
* exit --
@@ -236,6 +237,9 @@
*/
EVENTHANDLER_INVOKE(process_exit, p);
+ /* we have to call linux exit hook */
+ if (p->p_flag & P_LINUX && linux_proc_exit_p != NULL)
+ (linux_proc_exit_p)(td);
MALLOC(p->p_ru, struct rusage *, sizeof(struct rusage),
M_ZOMBIE, M_WAITOK);
/*
==== //depot/projects/soc2006/rdivacky_linuxolator/kern/subr_trap.c#2 (text+ko) ====
@@ -67,6 +67,8 @@
#include <machine/cpu.h>
#include <machine/pcb.h>
+int (*linux_userret_p)(struct thread *) = NULL; /* for linuxolator */
+
/*
* Define the code needed before returning to user mode, for
* trap and syscall.
@@ -128,6 +130,10 @@
addupc_task(td, TRAPF_PC(frame), td->td_pticks * psratio);
}
+ /* linux userret */
+ if (p->p_flag & P_LINUX && linux_userret_p != NULL)
+ (linux_userret_p)(td);
+
/*
* Let the scheduler adjust our priority etc.
*/
==== //depot/projects/soc2006/rdivacky_linuxolator/sys/proc.h#2 (text+ko) ====
@@ -655,6 +655,7 @@
#define P_HWPMC 0x800000 /* Process is using HWPMCs */
#define P_JAILED 0x1000000 /* Process is in jail. */
+#define P_LINUX 0x2000000 /* linux binary */
#define P_INEXEC 0x4000000 /* Process is in execve(). */
#define P_STATCHILD 0x8000000 /* Child process stopped or exited. */
More information about the p4-projects
mailing list