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 50
 #include <unistd.h>
50 51
 #include "compiler_opt.h"
51 52
 
52
-
53
+/* either syscall directly or #include <sys/linux/syscall.h> and use
54
+ * sys_futex directly */
53 55
 #define sys_futex(addr, op, val, timeout, addr2, val3) \
54 56
 	syscall(__NR_futex , (addr), (op), (val), (timeout), (addr2), (val3))
55 57
 
... ...
@@ -70,13 +72,18 @@ inline static futex_lock_t* futex_init(futex_lock_t* lock)
70 72
 inline static void futex_get(futex_lock_t* lock)
71 73
 {
72 74
 	int v;
75
+#ifdef ADAPTIVE_WAIT
76
+	register int i=ADAPTIVE_WAIT_LOOPS;
77
+	
78
+retry:
79
+#endif
73 80
 	
74 81
 	v=atomic_cmpxchg(lock, 0, 1); /* lock if 0 */
75 82
 	if (likely(v==0)){  /* optimize for the uncontended case */
76 83
 		/* success */
77 84
 		membar_enter_lock();
78 85
 		return;
79
-	}else if (likely(v==2)){ /* if contended, optimize for the several waiters
86
+	}else if (unlikely(v==2)){ /* if contended, optimize for the one waiter
80 87
 								case */
81 88
 		/* waiting processes/threads => add ourselves to the queue */
82 89
 		do{
... ...
@@ -85,6 +92,12 @@ inline static void futex_get(futex_lock_t* lock)
85 92
 		}while(v);
86 93
 	}else{
87 94
 		/* v==1 */
95
+#ifdef ADAPTIVE_WAIT
96
+		if (i>0){
97
+			i--;
98
+			goto retry;
99
+		}
100
+#endif
88 101
 		v=atomic_get_and_set(lock, 2);
89 102
 		while(v){
90 103
 			sys_futex(&(lock)->val, FUTEX_WAIT, 2, 0, 0, 0);