25 #ifndef __XRD_SYS_LINUX_SEMAPHORE__ 26 #define __XRD_SYS_LINUX_SEMAPHORE__ 28 #if defined(__linux__) && defined(HAVE_ATOMICS) 31 #include <linux/futex.h> 32 #include <sys/syscall.h> 44 class LinuxSemaphoreError:
public std::exception
47 LinuxSemaphoreError(
const std::string &error ): pError( error ) {}
48 virtual ~LinuxSemaphoreError() throw() {};
50 virtual const char *what()
const throw()
52 return pError.c_str();
99 Unpack( pValue, value, val, waiters );
102 newVal = Pack( --val, waiters );
103 if( __sync_bool_compare_and_swap( pValue, value, newVal ) )
128 Unpack( pValue, value, val, waiters );
138 if( waiters == WaitersMask )
139 throw LinuxSemaphoreError(
"Reached maximum number of waiters" );
141 int newVal = Pack( val, ++waiters );
151 pthread_setcanceltype( PTHREAD_CANCEL_DEFERRED, &cancelType );
152 if( __sync_bool_compare_and_swap( pValue, value, newVal ) )
158 pthread_cleanup_push( Cleanup, pValue );
159 pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, 0 );
161 r = syscall( SYS_futex, pValue, FUTEX_WAIT, newVal, 0, 0, 0 );
163 pthread_setcanceltype( PTHREAD_CANCEL_DEFERRED, 0 );
164 pthread_cleanup_pop( 0 );
172 if( errno == EWOULDBLOCK )
175 throw LinuxSemaphoreError(
"FUTEX_WAIT syscall error" );
184 Unpack( pValue, value, val, waiters );
185 newVal = Pack( val, --waiters );
187 while( !__sync_bool_compare_and_swap( pValue, value, newVal ) );
201 pthread_setcanceltype( cancelType, 0 );
224 Unpack( pValue, value, val, waiters );
226 if( val == ValueMask )
227 throw LinuxSemaphoreError(
"Reached maximum value" );
229 newVal = Pack( ++val, waiters );
230 if( __sync_bool_compare_and_swap( pValue, value, newVal ) )
233 syscall( SYS_futex, pValue, FUTEX_WAKE, 1, 0, 0, 0 );
244 int value = __sync_fetch_and_add( pValue, 0 );
245 return value & ValueMask;
253 LinuxSemaphore(
int value )
255 pValue = (
int *)malloc(
sizeof(
int));
256 *pValue = (value & ValueMask);
268 static const int ValueMask = 0x000fffff;
269 static const int WaitersOffset = 20;
270 static const int WaitersMask = 0x00000fff;
275 static inline void Unpack(
int *sourcePtr,
280 source = __sync_fetch_and_add( sourcePtr, 0 );
281 value = source & ValueMask;
282 nwaiters = (source >> WaitersOffset) & WaitersMask;
288 static inline int Pack(
int value,
int nwaiters )
290 return (nwaiters << WaitersOffset) | (value & ValueMask);
296 static void Cleanup(
void *param )
298 int *iParam = (
int*)param;
306 Unpack( iParam, value, val, waiters );
307 newVal = Pack( val, --waiters );
309 while( !__sync_bool_compare_and_swap( iParam, value, newVal ) );
316 #endif // __linux__ && HAVE_ATOMICS 318 #endif // __XRD_SYS_LINUX_SEMAPHORE__ Definition: XrdClPollerBuiltIn.hh:28