diff options
Diffstat (limited to 'src/thread-utils.h')
| -rw-r--r-- | src/thread-utils.h | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/src/thread-utils.h b/src/thread-utils.h index 2ca290adf..49b5f3b5e 100644 --- a/src/thread-utils.h +++ b/src/thread-utils.h @@ -18,6 +18,28 @@ typedef struct { #endif } git_atomic; +#ifdef GIT_ARCH_64 + +typedef struct { +#if defined(GIT_WIN32) + __int64 val; +#else + int64_t val; +#endif +} git_atomic64; + +typedef git_atomic64 git_atomic_ssize; + +#define git_atomic_ssize_add git_atomic64_add + +#else + +typedef git_atomic git_atomic_ssize; + +#define git_atomic_ssize_add git_atomic_add + +#endif + GIT_INLINE(void) git_atomic_set(git_atomic *a, int val) { a->val = val; @@ -57,6 +79,17 @@ GIT_INLINE(int) git_atomic_inc(git_atomic *a) #endif } +GIT_INLINE(int) git_atomic_add(git_atomic *a, int32_t addend) +{ +#if defined(GIT_WIN32) + return InterlockedExchangeAdd(&a->val, addend); +#elif defined(__GNUC__) + return __sync_add_and_fetch(&a->val, addend); +#else +# error "Unsupported architecture for atomic operations" +#endif +} + GIT_INLINE(int) git_atomic_dec(git_atomic *a) { #if defined(GIT_WIN32) @@ -68,6 +101,35 @@ GIT_INLINE(int) git_atomic_dec(git_atomic *a) #endif } +GIT_INLINE(void *) git___compare_and_swap( + volatile void **ptr, void *oldval, void *newval) +{ + volatile void *foundval; +#if defined(GIT_WIN32) + foundval = InterlockedCompareExchangePointer(ptr, newval, oldval); +#elif defined(__GNUC__) + foundval = __sync_val_compare_and_swap(ptr, oldval, newval); +#else +# error "Unsupported architecture for atomic operations" +#endif + return (foundval == oldval) ? oldval : newval; +} + +#ifdef GIT_ARCH_64 + +GIT_INLINE(int64_t) git_atomic64_add(git_atomic64 *a, int64_t addend) +{ +#if defined(GIT_WIN32) + return InterlockedExchangeAdd64(&a->val, addend); +#elif defined(__GNUC__) + return __sync_add_and_fetch(&a->val, addend); +#else +# error "Unsupported architecture for atomic operations" +#endif +} + +#endif + #else #define git_thread unsigned int @@ -96,13 +158,55 @@ GIT_INLINE(int) git_atomic_inc(git_atomic *a) return ++a->val; } +GIT_INLINE(int) git_atomic_add(git_atomic *a, int32_t addend) +{ + a->val += addend; + return a->val; +} + GIT_INLINE(int) git_atomic_dec(git_atomic *a) { return --a->val; } +GIT_INLINE(void *) git___compare_and_swap( + volatile void **ptr, void *oldval, void *newval) +{ + if (*ptr == oldval) + *ptr = newval; + else + oldval = newval; + return oldval; +} + +#ifdef GIT_ARCH_64 + +GIT_INLINE(int64_t) git_atomic64_add(git_atomic64 *a, int64_t addend) +{ + a->val += addend; + return a->val; +} + +#endif + #endif +/* Atomically replace oldval with newval + * @return oldval if it was replaced or newval if it was not + */ +#define git__compare_and_swap(P,O,N) \ + git___compare_and_swap((volatile void **)P, O, N) + +#define git__swap(ptr, val) git__compare_and_swap(&ptr, ptr, val) + extern int git_online_cpus(void); +#if defined(GIT_THREADS) && defined(GIT_WIN32) +# define GIT_MEMORY_BARRIER MemoryBarrier() +#elif defined(GIT_THREADS) +# define GIT_MEMORY_BARRIER __sync_synchronize() +#else +# define GIT_MEMORY_BARRIER /* noop */ +#endif + #endif /* INCLUDE_thread_utils_h__ */ |
