diff options
| author | Jérémy Zurcher <jeremy@asynk.ch> | 2013-01-30 11:21:19 +0100 | 
|---|---|---|
| committer | Jérémy Zurcher <jeremy@asynk.ch> | 2013-01-30 11:21:19 +0100 | 
| commit | 66037a508b737ea8f0ed0be53a57e88992cc0da3 (patch) | |
| tree | ee5e663c93502bf288af7607a3762f108a1f2aeb | |
| parent | 0042a0da85c2bd0d321e1e6ec22dfe0330ba6b9b (diff) | |
| download | lock_free-66037a508b737ea8f0ed0be53a57e88992cc0da3.zip lock_free-66037a508b737ea8f0ed0be53a57e88992cc0da3.tar.gz  | |
lf_cas.h rewrite
| -rw-r--r-- | lf_cas.h | 95 | 
1 files changed, 67 insertions, 28 deletions
@@ -1,7 +1,7 @@  /*   * File     : lf_cas.h   * Author   : Jérémy Zurcher  <jeremy@asynk.ch> - * Date     : 01/11/09  + * Date     : 2009/11/01   * License  :   *   *  Permission is hereby granted, free of charge, to any person obtaining @@ -11,10 +11,10 @@   *  distribute, sublicense, and/or sell copies of the Software, and to   *  permit persons to whom the Software is furnished to do so, subject to   *  the following conditions: - *   + *   *  The above copyright notice and this permission notice shall be   *  included in all copies or substantial portions of the Software. - *   + *   *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,   *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF   *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -32,31 +32,70 @@  extern "C" {  # endif /* __cplusplus */ -struct lf_pointer; - -typedef struct lf_pointer { -    volatile struct lf_pointer *ptr; -    volatile unsigned int count; -} lf_pointer_t; - -union ptr_u { -    lf_pointer_t ptr; -    volatile long long concat; -}; - -#define lf_eql(ptra,ptrb) (((union ptr_u)(ptra)).concat == ((union ptr_u)(ptrb)).concat) - -/* CMPXCHG8B m64   Compare EDX:EAX with m64. If equal, set ZF and load ECX:EBX into m64. Else, clear ZF and load m64 into EDX:EAX. */ -static inline unsigned int cas( volatile lf_pointer_t *mem, -                                volatile lf_pointer_t old, -                                volatile lf_pointer_t new ) { -    char result; -    __asm__ __volatile__("lock; cmpxchg8b %0; setz %1;" -            : "=m"(*mem), "=q"(result) -            : "m"(*mem), "d" (old.count), "a" (old.ptr), -            "c" (new.count), "b" (new.ptr) -            : "memory"); -    return (int)result; +#include <stdint.h> + +#if defined(__i386__) && defined(__GNUC__) + +#define _cas_field_t uint32_t +#define _cas_aligned 8 + +#elif defined(__x86_64__) && defined(__GNUC__) + +#define _cas_field_t uint64_t +#define _cas_aligned 16 + +#else +#error "cas not implemented yet for your arch" +#endif + +struct _lf_pointer_t +{ +   _cas_field_t pointer; +   _cas_field_t counter; +} __attribute__ (( __aligned__( _cas_aligned ) )); + +typedef struct _lf_pointer_t lf_pointer_t; + +#define lf_counter_set(p,v)   ((p).counter=(_cas_field_t)(v)) +#define lf_pointer_set(p,v)   ((p).pointer=(_cas_field_t)(v)) +#define lf_eq(p0,p1)          ((p0).pointer==(p1).pointer && (p0).counter==(p1).counter) +#define lf_pointer_null(p)    ((p).pointer==(_cas_field_t)NULL) + +static inline int lf_cas(volatile lf_pointer_t* mem, lf_pointer_t old_val, lf_pointer_t new_val) +{ +   char success; + +#if defined(__i386__) && defined(__GNUC__) + +   asm volatile("lock cmpxchg8b (%6);" +         "setz %7;" +         : "=a" ( old_val.pointer ) +         , "=d" ( old_val.counter ) +         : "0"  ( old_val.pointer ) +         , "1"  ( old_val.counter ) +         , "b"  ( new_val.pointer ) +         , "c"  ( new_val.counter ) +         , "r"  ( mem ) +         , "m"  ( success ) +         : "cc", "memory" +         ); + +#elif defined(__x86_64__) && defined(__GNUC__) + +   asm volatile ( +         "lock cmpxchg16b %1;" +         "setz %0;" +         : "=q" ( success ) +         , "+m" ( *mem ) +         , "+d" ( old_val.counter ) +         , "+a" ( old_val.pointer ) +         : "c"  ( new_val.counter ) +         , "b"  ( new_val.pointer ) +         : "cc", "memory" +         ); +#endif + +   return (int)success;  }  # ifdef __cplusplus  | 
