Browse code

- try first to spin a little and only if this fails go through the futex syscalls (uses ADAPTIVE_WAIT and ADAPTIVE_WAIT_LOOPS like FAST_LOCK). This gives a 5% performance increase compared to the "pure" futex version on my machine (for tm).

Andrei Pelinescu-Onciul authored on 12/06/2007 22:43:19
Showing 1 changed files
... ...
@@ -33,6 +33,7 @@
33 33
  * History:
34 34
  * --------
35 35
  *  2007-05-13  created by andrei
36
+ *  2007-06-12  added ADAPTIVE_WAIT busy waiting (andrei)
36 37
  */
37 38
 
38 39
 #ifndef _futexlock_h
... ...
@@ -49,7 +50,8 @@
49 49
 #include <unistd.h>
50 50
 #include "compiler_opt.h"
51 51
 
52
-
52
+/* either syscall directly or #include <sys/linux/syscall.h> and use
53
+ * sys_futex directly */
53 54
 #define sys_futex(addr, op, val, timeout, addr2, val3) \
54 55
 	syscall(__NR_futex , (addr), (op), (val), (timeout), (addr2), (val3))
55 56
 
... ...
@@ -70,13 +72,18 @@ inline static futex_lock_t* futex_init(futex_lock_t* lock)
70 70
 inline static void futex_get(futex_lock_t* lock)
71 71
 {
72 72
 	int v;
73
+#ifdef ADAPTIVE_WAIT
74
+	register int i=ADAPTIVE_WAIT_LOOPS;
75
+	
76
+retry:
77
+#endif
73 78
 	
74 79
 	v=atomic_cmpxchg(lock, 0, 1); /* lock if 0 */
75 80
 	if (likely(v==0)){  /* optimize for the uncontended case */
76 81
 		/* success */
77 82
 		membar_enter_lock();
78 83
 		return;
79
-	}else if (likely(v==2)){ /* if contended, optimize for the several waiters
84
+	}else if (unlikely(v==2)){ /* if contended, optimize for the one waiter
80 85
 								case */
81 86
 		/* waiting processes/threads => add ourselves to the queue */
82 87
 		do{
... ...
@@ -85,6 +92,12 @@ inline static void futex_get(futex_lock_t* lock)
85 85
 		}while(v);
86 86
 	}else{
87 87
 		/* v==1 */
88
+#ifdef ADAPTIVE_WAIT
89
+		if (i>0){
90
+			i--;
91
+			goto retry;
92
+		}
93
+#endif
88 94
 		v=atomic_get_and_set(lock, 2);
89 95
 		while(v){
90 96
 			sys_futex(&(lock)->val, FUTEX_WAIT, 2, 0, 0, 0);