PERFORCE change 103698 for review
Roman Divacky
rdivacky at FreeBSD.org
Sat Aug 12 10:31:28 UTC 2006
http://perforce.freebsd.org/chv.cgi?CH=103698
Change 103698 by rdivacky at rdivacky_witten on 2006/08/12 10:31:23
o remove SLIST of linux processes emuldata and use proc->p_emuldata instead
o change locking to use sx (because its sleepable) so we are LOR-less
o split locking of shared->threads and p->p_emuldata
o change em_find() prototype to take proc instead of pid
Affected files ...
.. //depot/projects/soc2006/rdivacky_linuxolator/compat/linux/linux_misc.c#9 edit
.. //depot/projects/soc2006/rdivacky_linuxolator/compat/linux/linux_signal.c#4 edit
.. //depot/projects/soc2006/rdivacky_linuxolator/i386/linux/linux.h#15 edit
.. //depot/projects/soc2006/rdivacky_linuxolator/i386/linux/linux_machdep.c#40 edit
.. //depot/projects/soc2006/rdivacky_linuxolator/i386/linux/linux_sysvec.c#14 edit
Differences ...
==== //depot/projects/soc2006/rdivacky_linuxolator/compat/linux/linux_misc.c#9 (text+ko) ====
@@ -93,8 +93,8 @@
#define BSD_TO_LINUX_SIGNAL(sig) \
(((sig) <= LINUX_SIGTBLSZ) ? bsd_to_linux_signal[_SIG_IDX(sig)] : sig)
-struct linux_emuldata *em_find(pid_t pid, int locked);
-extern struct rwlock emul_lock;
+extern struct sx emul_shared_lock;
+extern struct sx emul_lock;
static unsigned int linux_to_bsd_resource[LINUX_RLIM_NLIMITS] = {
RLIMIT_CPU, RLIMIT_FSIZE, RLIMIT_DATA, RLIMIT_STACK,
@@ -1335,7 +1335,7 @@
{
struct linux_emuldata *em;
- em = em_find(td->td_proc->p_pid, EMUL_UNLOCKED);
+ em = em_find(td->td_proc, EMUL_UNLOCKED);
if (em == NULL) {
#ifdef DEBUG
@@ -1345,7 +1345,7 @@
}
td->td_retval[0] = em->shared->group_pid;
- EMUL_RUNLOCK(&emul_lock);
+ EMUL_UNLOCK(&emul_lock);
return (0);
}
@@ -1355,7 +1355,7 @@
struct linux_emuldata *em;
struct proc *p, *pp;
- em = em_find(td->td_proc->p_pid, EMUL_UNLOCKED);
+ em = em_find(td->td_proc, EMUL_UNLOCKED);
if (em == NULL) {
#ifdef DEBUG
@@ -1380,7 +1380,7 @@
/* if its also linux process */
if (pp->p_sysent == &elf_linux_sysvec) {
- em = em_find(pp->p_pid, EMUL_LOCKED);
+ em = em_find(pp, EMUL_LOCKED);
if (em == NULL) {
#ifdef DEBUG
printf(LMSG("emuldata for parent process not found in getppid.\n"));
@@ -1392,7 +1392,7 @@
} else
td->td_retval[0] = pp->p_pid;
- EMUL_RUNLOCK(&emul_lock);
+ EMUL_UNLOCK(&emul_lock);
PROC_UNLOCK(pp);
return (0);
==== //depot/projects/soc2006/rdivacky_linuxolator/compat/linux/linux_signal.c#4 (text+ko) ====
@@ -50,8 +50,8 @@
#include <compat/linux/linux_signal.h>
#include <compat/linux/linux_util.h>
-struct linux_emuldata *em_find(pid_t pid, int locked);
-extern struct rwlock emul_lock;
+extern struct sx emul_shared_lock;
+extern struct sx emul_lock;
void
linux_to_bsd_sigset(l_sigset_t *lss, sigset_t *bss)
@@ -477,7 +477,7 @@
PROC_UNLOCK(p);
- em = em_find(args->pid, EMUL_UNLOCKED);
+ em = em_find(p, EMUL_UNLOCKED);
if (em == NULL) {
#ifdef DEBUG
@@ -489,7 +489,7 @@
if (em->shared->group_pid != args->tgid)
return ESRCH;
- EMUL_RUNLOCK(&emul_lock);
+ EMUL_UNLOCK(&emul_lock);
return linux_kill(td, &ka);
}
==== //depot/projects/soc2006/rdivacky_linuxolator/i386/linux/linux.h#15 (text+ko) ====
@@ -34,7 +34,8 @@
#include <sys/signal.h> /* for sigval union */
#include <sys/param.h>
#include <sys/lock.h>
-#include <sys/rwlock.h>
+#include <sys/mutex.h>
+#include <sys/sx.h>
#include <i386/linux/linux_syscall.h>
@@ -798,15 +799,18 @@
struct linux_emuldata_shared *shared;
- SLIST_ENTRY(linux_emuldata) emuldatas;
-
LIST_ENTRY(linux_emuldata) threads; /* list of linux threads */
};
-#define EMUL_RLOCK(l) rw_rlock(l)
-#define EMUL_RUNLOCK(l) rw_runlock(l)
-#define EMUL_WLOCK(l) rw_wlock(l)
-#define EMUL_WUNLOCK(l) rw_wunlock(l)
+struct linux_emuldata *em_find(struct proc *, int locked);
+
+#define EMUL_LOCK(l) sx_xlock(l)
+#define EMUL_UNLOCK(l) sx_xunlock(l)
+
+#define EMUL_SHARED_RLOCK(l) sx_slock(l)
+#define EMUL_SHARED_RUNLOCK(l) sx_sunlock(l)
+#define EMUL_SHARED_WLOCK(l) sx_xlock(l)
+#define EMUL_SHARED_WUNLOCK(l) sx_xunlock(l)
/* for em_find use */
#define EMUL_LOCKED 1
==== //depot/projects/soc2006/rdivacky_linuxolator/i386/linux/linux_machdep.c#40 (text+ko) ====
@@ -36,6 +36,7 @@
#include <sys/malloc.h>
#include <sys/mman.h>
#include <sys/mutex.h>
+#include <sys/sx.h>
#include <sys/proc.h>
#include <sys/queue.h>
#include <sys/resource.h>
@@ -64,16 +65,13 @@
#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 */
-struct rwlock emul_lock;
-
static int linux_proc_init(struct thread *, pid_t, int);
void linux_proc_exit(void *, struct proc *);
void linux_schedtail(void *, struct proc *);
void linux_proc_exec(void *, struct proc *, struct image_params *);
-struct linux_emuldata *em_find(pid_t pid, int locked);
+
+struct sx emul_shared_lock;
+struct sx emul_lock;
extern struct sysentvec elf32_freebsd_sysvec; /* defined in i386/i386/elf_machdep.c */
@@ -294,19 +292,17 @@
/* this returns locked reference to the emuldata entry (if found) */
struct linux_emuldata *
-em_find(pid_t pid, int locked)
+em_find(struct proc *p, int locked)
{
struct linux_emuldata *em;
if (locked == EMUL_UNLOCKED)
- EMUL_RLOCK(&emul_lock);
+ EMUL_LOCK(&emul_lock);
- SLIST_FOREACH(em, &emuldata_head, emuldatas)
- if (em->pid == pid)
- break;
+ em = p->p_emuldata;
if (em == NULL && locked == EMUL_UNLOCKED)
- EMUL_RUNLOCK(&emul_lock);
+ EMUL_UNLOCK(&emul_lock);
return (em);
}
@@ -425,17 +421,17 @@
/* create the emuldata */
error = linux_proc_init(td, p2->p_pid, args->flags);
/* reference it - no need to check this */
- em = em_find(p2->p_pid, EMUL_UNLOCKED);
+ em = em_find(p2, EMUL_UNLOCKED);
KASSERT(em != NULL, ("no emuldata after proc_init()!\n"));
/* and adjust it */
if (args->flags & CLONE_PARENT_SETTID) {
if (args->parent_tidptr == NULL) {
- EMUL_RUNLOCK(&emul_lock);
+ EMUL_UNLOCK(&emul_lock);
return (EINVAL);
}
error = copyout(&p2->p_pid, args->parent_tidptr, sizeof(p2->p_pid));
if (error) {
- EMUL_RUNLOCK(&emul_lock);
+ EMUL_UNLOCK(&emul_lock);
return (error);
}
}
@@ -459,7 +455,7 @@
em->child_clear_tid = args->child_tidptr;
else
em->child_clear_tid = NULL;
- EMUL_RUNLOCK(&emul_lock);
+ EMUL_UNLOCK(&emul_lock);
PROC_LOCK(p2);
p2->p_sigparent = exit_signal;
@@ -1179,11 +1175,14 @@
LIST_INIT(&s->threads);
}
- EMUL_WLOCK(&emul_lock);
- SLIST_INSERT_HEAD(&emuldata_head, em, emuldatas);
+ p = pfind(child);
+ if (p == NULL)
+ panic("process not found in proc_init\n");
+ p->p_emuldata = em;
+ PROC_UNLOCK(p);
} else {
/* lookup the old one */
- em = em_find(td->td_proc->p_pid, EMUL_UNLOCKED);
+ em = em_find(td->td_proc, EMUL_UNLOCKED);
/* XXX: this might be turned into KASSERT once its tested enough */
if (em == NULL) {
/* this should not happen */
@@ -1204,7 +1203,7 @@
if (child != 0) {
if (flags & CLONE_VM) {
/* lookup the parent */
- p_em = em_find(td->td_proc->p_pid, EMUL_LOCKED);
+ p_em = em_find(td->td_proc, EMUL_LOCKED);
if (p_em == NULL) {
#ifdef DEBUG
#endif
@@ -1221,15 +1220,16 @@
if (child != 0) {
+ EMUL_SHARED_WLOCK(&emul_shared_lock);
LIST_INSERT_HEAD(&em->shared->threads, em, threads);
- EMUL_WUNLOCK(&emul_lock);
+ EMUL_SHARED_WUNLOCK(&emul_shared_lock);
p = pfind(child);
PROC_UNLOCK(p);
/* we might have a sleeping linux_schedtail */
wakeup(&p->p_emuldata);
} else
- EMUL_RUNLOCK(&emul_lock);
+ EMUL_UNLOCK(&emul_lock);
return (0);
}
@@ -1246,7 +1246,7 @@
return;
/* find the emuldata */
- em = em_find(p->p_pid, EMUL_UNLOCKED);
+ em = em_find(p, EMUL_UNLOCKED);
if (em == NULL) {
#ifdef DEBUG
@@ -1257,19 +1257,19 @@
child_clear_tid = em->child_clear_tid;
- EMUL_RUNLOCK(&emul_lock);
- /* XXX: there is a race but I think we can ommit that
- * because its not very possible that the same process
- * will exit on different cpus etc.
- */
- EMUL_WLOCK(&emul_lock);
+ EMUL_UNLOCK(&emul_lock);
+
+ EMUL_SHARED_WLOCK(&emul_shared_lock);
LIST_REMOVE(em, threads);
- SLIST_REMOVE(&emuldata_head, em, linux_emuldata, emuldatas);
+
+ PROC_LOCK(p);
+ p->p_emuldata = NULL;
+ PROC_UNLOCK(p);
em->shared->refs--;
if (em->shared->refs == 0)
FREE(em->shared, M_LINUX);
- EMUL_WUNLOCK(&emul_lock);
+ EMUL_SHARED_WUNLOCK(&emul_shared_lock);
if (child_clear_tid != NULL) {
struct linux_sys_futex_args cup;
@@ -1277,10 +1277,8 @@
/* XXX: doesnt futex use the addr? */
error = copyout(&null, child_clear_tid, sizeof(null));
- if (error) {
- EMUL_RUNLOCK(&emul_lock);
+ if (error)
return;
- }
/* futexes stuff */
cup.uaddr = child_clear_tid;
@@ -1311,7 +1309,7 @@
&& p->p_sysent == &elf_linux_sysvec)) {
struct linux_emuldata *em;
- em = em_find(p->p_pid, EMUL_UNLOCKED);
+ em = em_find(p, EMUL_UNLOCKED);
if (em == NULL) {
#ifdef DEBUG
@@ -1321,19 +1319,19 @@
return;
}
- EMUL_RUNLOCK(&emul_lock);
- /* XXX: there is a race but I think we can ommit that
- * because its not very possible that the same process
- * will exit on different cpus etc.
- */
- EMUL_WLOCK(&emul_lock);
+ EMUL_UNLOCK(&emul_lock);
+
+ EMUL_SHARED_WLOCK(&emul_shared_lock);
LIST_REMOVE(em, threads);
- SLIST_REMOVE(&emuldata_head, em, linux_emuldata, emuldatas);
+
+ PROC_LOCK(p);
+ p->p_emuldata = NULL;
+ PROC_UNLOCK(p);
em->shared->refs--;
if (em->shared->refs == 0)
FREE(em->shared, M_LINUX);
- EMUL_WUNLOCK(&emul_lock);
+ EMUL_SHARED_WUNLOCK(&emul_shared_lock);
FREE(em, M_LINUX);
}
@@ -1356,7 +1354,7 @@
retry:
/* find the emuldata */
- em = em_find(p->p_pid, EMUL_UNLOCKED);
+ em = em_find(p, EMUL_UNLOCKED);
if (em == NULL) {
/* We might have been called before proc_init for this process so
@@ -1372,7 +1370,7 @@
return;
}
child_set_tid = em->child_set_tid;
- EMUL_RUNLOCK(&emul_lock);
+ EMUL_UNLOCK(&emul_lock);
if (child_set_tid != NULL)
error = copyout(&p->p_pid, (int *) child_set_tid, sizeof(p->p_pid));
@@ -1391,7 +1389,7 @@
#endif
/* find the emuldata */
- em = em_find(td->td_proc->p_pid, EMUL_UNLOCKED);
+ em = em_find(td->td_proc, EMUL_UNLOCKED);
if (em == NULL) {
#ifdef DEBUG
@@ -1403,7 +1401,7 @@
em->child_clear_tid = args->tidptr;
td->td_retval[0] = td->td_proc->p_pid;
- EMUL_RUNLOCK(&emul_lock);
+ EMUL_UNLOCK(&emul_lock);
return 0;
}
@@ -1418,7 +1416,7 @@
printf(ARGS(exit_group, "%i"), args->error_code);
#endif
- td_em = em_find(td->td_proc->p_pid, EMUL_UNLOCKED);
+ td_em = em_find(td->td_proc, EMUL_UNLOCKED);
if (td_em == NULL) {
#ifdef DEBUG
@@ -1427,6 +1425,7 @@
return (0);
}
+ EMUL_SHARED_RLOCK(&emul_shared_lock);
LIST_FOREACH_SAFE(em, &td_em->shared->threads, threads, tmp_em) {
if (em->pid == td_em->pid)
continue;
@@ -1439,7 +1438,8 @@
#endif
}
- EMUL_RUNLOCK(&emul_lock);
+ EMUL_SHARED_RUNLOCK(&emul_shared_lock);
+ EMUL_UNLOCK(&emul_lock);
exit1(td, W_EXITCODE(args->error_code,0));
==== //depot/projects/soc2006/rdivacky_linuxolator/i386/linux/linux_sysvec.c#14 (text+ko) ====
@@ -92,7 +92,6 @@
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);
@@ -110,8 +109,9 @@
extern void linux_proc_exit(void *, struct proc *, struct image_params *);
extern void linux_proc_exec(void *, struct proc *, struct image_params *);
extern void linux_schedtail(void *, struct proc *);
-extern struct rwlock emul_lock;
extern LIST_HEAD(futex_list, futex) futex_list;
+extern struct sx emul_shared_lock;
+extern struct sx emul_lock;
extern struct mtx futex_mtx;
static eventhandler_tag linux_exit_tag;
@@ -921,8 +921,8 @@
linux_ioctl_register_handler(*lihp);
SET_FOREACH(ldhp, linux_device_handler_set)
linux_device_register_handler(*ldhp);
- SLIST_INIT(&emuldata_head);
- rw_init(&emul_lock, "emuldata lock");
+ sx_init(&emul_lock, "emuldata lock");
+ sx_init(&emul_shared_lock, "emuldata->shared lock");
LIST_INIT(&futex_list);
mtx_init(&futex_mtx, "futex protection lock", NULL, MTX_DEF);
linux_exit_tag = EVENTHANDLER_REGISTER(process_exit, linux_proc_exit,
@@ -952,13 +952,12 @@
linux_ioctl_unregister_handler(*lihp);
SET_FOREACH(ldhp, linux_device_handler_set)
linux_device_unregister_handler(*ldhp);
- rw_destroy(&emul_lock);
+ sx_destroy(&emul_lock);
+ sx_destroy(&emul_shared_lock);
mtx_destroy(&futex_mtx);
EVENTHANDLER_DEREGISTER(process_exit, linux_exit_tag);
EVENTHANDLER_DEREGISTER(schedtail, linux_schedtail_tag);
EVENTHANDLER_DEREGISTER(process_exec, linux_exec_tag);
- printf("Emuldata slist empty: %i\n", SLIST_EMPTY(&emuldata_head));
- printf("Futex slist empty: %i\n", LIST_EMPTY(&futex_list));
if (bootverbose)
printf("Linux ELF exec handler removed\n");
} else
More information about the p4-projects
mailing list