New PHP5 APC - version 3.0.19, using PHP5 5.2.0-8+etch11,
[php5-apc.git] / apc_futex.c
1 /*
2   +----------------------------------------------------------------------+
3   | APC                                                                  |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 2008 The PHP Group                                     |
6   +----------------------------------------------------------------------+
7   | This source file is subject to version 3.01 of the PHP license,      |
8   | that is bundled with this package in the file LICENSE, and is        |
9   | available through the world-wide-web at the following url:           |
10   | http://www.php.net/license/3_01.txt                                  |
11   | If you did not receive a copy of the PHP license and are unable to   |
12   | obtain it through the world-wide-web, please send a note to          |
13   | license@php.net so we can mail you a copy immediately.               |
14   +----------------------------------------------------------------------+
15   | Authors: Brian Shire <shire@php.net>                                 |
16   +----------------------------------------------------------------------+
17
18  */
19
20 /* $Id: apc_futex.c,v 3.2.2.1 2008/05/11 18:57:00 rasmus Exp $ */
21
22 /***************************************************************************
23 * Futex (Fast Userspace Mutex) support for APC
24
25 * Futex support provides user space locking with system calls only
26 * for the contended cases.  Some required reading for this functionality is:
27 *
28 * 'Fuss, Futexes and Furwocks: Fast Userlevel Locking in Linux' 
29 *  by Hubertus Franke, Rusty Russell, and Matthew Kirkwood
30 *   http://www.realitydiluted.com/nptl-uclibc/docs/futex.pdf
31 *
32 * 'Futexes are Tricky' by Ulrich Drepper 
33 *    http://people.redhat.com/drepper/futex.pdf
34 *
35
36 * This implementation is optimized and designed for the i386 and x86_64 
37 * architectures.  Other architectures may require additional design 
38 * to efficiently and safely implement this functionality. 
39 *
40 * Lock values are:
41 * 0 = Unlocked
42 * 1 = Locked without any waiting processes
43 * 2 = Locked with an unknown number of waiting processes
44 *
45 ***************************************************************************/
46
47 #include "apc.h"
48 #include "apc_futex.h"
49
50 #ifdef APC_FUTEX_LOCKS
51
52
53 inline int apc_futex_create()
54 {
55     return 0;
56 }
57
58 inline void apc_futex_destroy(volatile int* lock)
59 {
60     return;
61 }
62
63 void apc_futex_lock(volatile int* lock)
64 {
65     int c;
66   
67     /*  Attempt to obtain a lock if not currently locked.  If the previous
68      *  value was not 0 then we did not obtain the lock, and must wait.
69      *  If the previous value was 1 (has no waiting processes) then we
70      *  set the lock to 2 before blocking on the futex wait operation.  
71      *  This implementation suffers from the possible difficulty of 
72      *  efficently implementing the atomic xchg operation on some
73      *  architectures, and could also cause unecessary wake operations by
74      *  setting the lock to 2 when there are no additional waiters.
75      */ 
76     if((c = apc_cmpxchg(lock, 0, 1)) != 0) {
77         if(c != 2) {
78             c = apc_xchg(lock, 2);
79         }
80         while(c != 0) {
81             apc_futex_wait(lock, 2);
82             c = apc_xchg(lock, 2);
83         }
84     }
85     
86 }
87
88 /* non-blocking lock returns 1 when the lock has been obtained, 0 if it would block */
89 inline zend_bool apc_futex_nonblocking_lock(volatile int* lock)
90 {
91     return apc_cmpxchg(lock, 0, 1) == 0;
92 }
93
94
95 inline void apc_futex_unlock(volatile int* lock)
96 {
97     /* set the lock to 0, if it's previous values was not 1 (no waiters)
98      * then perform a wake operation on one process letting it know the lock 
99      * is available.  This is an optimization to save wake calls if there
100      * are no waiting processes for the lock 
101      */
102     if(apc_xchg(lock,0) != 1) {
103         apc_futex_wake(lock, 1);
104     }
105 }
106
107 #endif
108
109 /*
110  * Local variables:
111  * tab-width: 4
112  * c-basic-offset: 4
113  * End:
114  * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
115  * vim<600: expandtab sw=4 ts=4 sts=4
116  */