Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 12 Aug 2006 10:31:26 GMT
From:      Roman Divacky <rdivacky@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 103698 for review
Message-ID:  <200608121031.k7CAVQvH013670@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=103698

Change 103698 by rdivacky@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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200608121031.k7CAVQvH013670>