PERFORCE change 103633 for review
Roman Divacky
rdivacky at FreeBSD.org
Fri Aug 11 11:11:01 UTC 2006
http://perforce.freebsd.org/chv.cgi?CH=103633
Change 103633 by rdivacky at rdivacky_witten on 2006/08/11 11:10:09
Giantify futex code - this is necessary because the futex code is expected to be atomic.
I need to assure the atomicity. I am using Giant because its sleepable mutex. I hope
someone will point me to some other better solution.
This helps my pthread testing program reliably with with upto 37 threads (later it coredumps
but I think this is userspace issue - its running out of memory for threads and starts
doing wild things).
Also - update comment in linux_machdep to satisfy netchild.
Affected files ...
.. //depot/projects/soc2006/rdivacky_linuxolator/compat/linux/linux_futex.c#19 edit
.. //depot/projects/soc2006/rdivacky_linuxolator/i386/linux/linux_machdep.c#39 edit
Differences ...
==== //depot/projects/soc2006/rdivacky_linuxolator/compat/linux/linux_futex.c#19 (text+ko) ====
@@ -68,7 +68,7 @@
};
LIST_HEAD(futex_list, futex) futex_list;
-struct mtx futex_mtx;
+struct mtx futex_mtx; /* this protects the LIST of futexes */
#define FUTEX_LOCK mtx_lock(&futex_mtx)
#define FUTEX_UNLOCK mtx_unlock(&futex_mtx)
@@ -76,6 +76,9 @@
#define FUTEX_LOCKED 1
#define FUTEX_UNLOCKED 0
+#define FUTEX_SYSTEM_LOCK mtx_lock(&Giant)
+#define FUTEX_SYSTEM_UNLOCK mtx_unlock(&Giant)
+
static struct futex *futex_get(void *, int);
static void futex_put(struct futex *);
static int futex_sleep(struct futex *, struct thread *, unsigned long);
@@ -109,17 +112,25 @@
switch (args->op) {
case LINUX_FUTEX_WAIT:
+ FUTEX_SYSTEM_LOCK;
+
if ((error = copyin(args->uaddr,
- &val, sizeof(val))) != 0)
+ &val, sizeof(val))) != 0) {
+ FUTEX_SYSTEM_UNLOCK;
return error;
+ }
- if (val != args->val)
+ if (val != args->val) {
+ FUTEX_SYSTEM_UNLOCK;
return EWOULDBLOCK;
+ }
if (args->timeout != NULL) {
if ((error = copyin(args->timeout,
- &timeout, sizeof(timeout))) != 0)
+ &timeout, sizeof(timeout))) != 0) {
+ FUTEX_SYSTEM_UNLOCK;
return error;
+ }
}
#ifdef DEBUG
@@ -157,6 +168,7 @@
"ret = %d\n", td->td_proc->p_pid, args->uaddr, ret);
#endif
+ FUTEX_SYSTEM_UNLOCK;
switch (ret) {
case EWOULDBLOCK: /* timeout */
return ETIMEDOUT;
@@ -184,6 +196,8 @@
break;
case LINUX_FUTEX_WAKE:
+ FUTEX_SYSTEM_LOCK;
+
/*
* XXX: Linux is able cope with different addresses
* corresponding to the same mapped memory in the sleeping
@@ -197,24 +211,43 @@
f = futex_get(args->uaddr, FUTEX_UNLOCKED);
td->td_retval[0] = futex_wake(f, args->val, NULL);
futex_put(f);
+
+ FUTEX_SYSTEM_UNLOCK;
break;
case LINUX_FUTEX_CMP_REQUEUE:
+ FUTEX_SYSTEM_LOCK;
+
if ((error = copyin(args->uaddr,
- &val, sizeof(val))) != 0)
+ &val, sizeof(val))) != 0) {
+ FUTEX_SYSTEM_UNLOCK;
return error;
+ }
- if (val != args->val3)
+ if (val != args->val3) {
+ FUTEX_SYSTEM_UNLOCK;
return EAGAIN;
- /* FALLTHROUGH */
+ }
+
+ f = futex_get(args->uaddr, FUTEX_UNLOCKED);
+ newf = futex_get(args->uaddr2, FUTEX_UNLOCKED);
+ td->td_retval[0] = futex_wake(f, args->val, newf);
+ futex_put(f);
+ futex_put(newf);
+
+ FUTEX_SYSTEM_UNLOCK;
+ break;
case LINUX_FUTEX_REQUEUE:
+ FUTEX_SYSTEM_LOCK;
+
f = futex_get(args->uaddr, FUTEX_UNLOCKED);
newf = futex_get(args->uaddr2, FUTEX_UNLOCKED);
td->td_retval[0] = futex_wake(f, args->val, newf);
futex_put(f);
futex_put(newf);
+ FUTEX_SYSTEM_UNLOCK;
break;
case LINUX_FUTEX_FD:
@@ -223,6 +256,7 @@
break;
case LINUX_FUTEX_WAKE_OP:
+ FUTEX_SYSTEM_LOCK;
#ifdef DEBUG
if (ldebug(sys_futex))
printf("FUTEX_WAKE_OP: %d: uaddr = %p, op = %d, val = %d, uaddr2 = %p, val3 = %d\n",
@@ -238,12 +272,14 @@
if (op_ret != -EFAULT) {
futex_put(f);
futex_put(f2);
+ FUTEX_SYSTEM_UNLOCK;
return (-op_ret);
}
futex_put(f);
futex_put(f2);
+ FUTEX_SYSTEM_UNLOCK;
return (EFAULT);
}
@@ -259,6 +295,8 @@
}
futex_put(f2);
td->td_retval[0] = ret;
+
+ FUTEX_SYSTEM_UNLOCK;
break;
default:
==== //depot/projects/soc2006/rdivacky_linuxolator/i386/linux/linux_machdep.c#39 (text+ko) ====
@@ -1168,7 +1168,7 @@
MALLOC(em, struct linux_emuldata *, sizeof *em, M_LINUX, M_WAITOK | M_ZERO);
em->pid = child;
if (flags & CLONE_VM) {
- /* handled later */
+ /* handled later in the code */
} else {
struct linux_emuldata_shared *s;
More information about the p4-projects
mailing list