2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2006 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 +----------------------------------------------------------------------+
20 /* $Id: apc_futex.c,v 3.2 2006/10/12 08:23:16 shire Exp $ */
22 /***************************************************************************
23 * Futex (Fast Userspace Mutex) support for APC
25 * Futex support provides user space locking with system calls only
26 * for the contended cases. Some required reading for this functionality is:
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
32 * 'Futexes are Tricky' by Ulrich Drepper
33 * http://people.redhat.com/drepper/futex.pdf
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.
42 * 1 = Locked without any waiting processes
43 * 2 = Locked with an unknown number of waiting processes
45 ***************************************************************************/
48 #include "apc_futex.h"
50 #ifdef APC_FUTEX_LOCKS
53 inline int apc_futex_create()
58 inline void apc_futex_destroy(volatile int* lock)
63 void apc_futex_lock(volatile int* lock)
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.
76 if((c = apc_cmpxchg(lock, 0, 1)) != 0) {
78 c = apc_xchg(lock, 2);
81 apc_futex_wait(lock, 2);
82 c = apc_xchg(lock, 2);
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)
91 return apc_cmpxchg(lock, 0, 1) == 0;
95 inline void apc_futex_unlock(volatile int* lock)
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
102 if(apc_xchg(lock,0) != 1) {
103 apc_futex_wake(lock, 1);
114 * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
115 * vim<600: expandtab sw=4 ts=4 sts=4