kernel: atomic_*() functions rework
* No need for the atomically changed variables to be declared as volatile. * Drop support for atomically getting and setting unaligned data. * Introduce atomic_get_and_set[64]() which works the same as atomic_set[64]() used to. atomic_set[64]() does not return the previous value anymore.
This commit is contained in:
@@ -118,17 +118,19 @@ struct media_node;
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern int32 atomic_set(vint32 *value, int32 newValue);
|
||||
extern int32 atomic_test_and_set(vint32 *value, int32 newValue,
|
||||
extern void atomic_set(int32* value, int32 newValue);
|
||||
extern int32 atomic_get_and_set(int32* value, int32 newValue);
|
||||
extern int32 atomic_test_and_set(int32 *value, int32 newValue,
|
||||
int32 testAgainst);
|
||||
extern int32 atomic_get(vint32 *value);
|
||||
extern int64 atomic_set64(vint64 *value, int64 newValue);
|
||||
extern int64 atomic_test_and_set64(vint64 *value, int64 newValue,
|
||||
extern int32 atomic_get(int32 *value);
|
||||
extern void atomic_set64(int64* value, int64 newValue);
|
||||
extern int64 atomic_get_and_set64(int64* value, int64 newValue);
|
||||
extern int64 atomic_test_and_set64(int64 *value, int64 newValue,
|
||||
int64 testAgainst);
|
||||
extern int64 atomic_get64(vint64 *value);
|
||||
extern int64 atomic_add64(vint64 *value, int64 addValue);
|
||||
extern int64 atomic_and64(vint64 *value, int64 andValue);
|
||||
extern int64 atomic_or64(vint64 *value, int64 orValue);
|
||||
extern int64 atomic_get64(int64 *value);
|
||||
extern int64 atomic_add64(int64 *value, int64 addValue);
|
||||
extern int64 atomic_and64(int64 *value, int64 andValue);
|
||||
extern int64 atomic_or64(int64 *value, int64 orValue);
|
||||
|
||||
extern size_t strnlen(const char *string, size_t count);
|
||||
|
||||
|
||||
@@ -20,9 +20,9 @@ typedef ulong cpu_status;
|
||||
|
||||
#if B_DEBUG_SPINLOCK_CONTENTION
|
||||
typedef struct {
|
||||
vint32 lock;
|
||||
vint32 count_low;
|
||||
vint32 count_high;
|
||||
int32 lock;
|
||||
int32 count_low;
|
||||
int32 count_high;
|
||||
} spinlock;
|
||||
|
||||
# define B_SPINLOCK_INITIALIZER { 0, 0, 0 }
|
||||
@@ -33,7 +33,7 @@ typedef ulong cpu_status;
|
||||
} while (false)
|
||||
# define B_SPINLOCK_IS_LOCKED(spinlock) ((spinlock)->lock > 0)
|
||||
#else
|
||||
typedef vint32 spinlock;
|
||||
typedef int32 spinlock;
|
||||
|
||||
# define B_SPINLOCK_INITIALIZER 0
|
||||
# define B_INITIALIZE_SPINLOCK(lock) do { *(lock) = 0; } while (false)
|
||||
|
||||
@@ -396,8 +396,8 @@ private:
|
||||
int32 withLength);
|
||||
|
||||
private:
|
||||
vint32& _ReferenceCount();
|
||||
const vint32& _ReferenceCount() const;
|
||||
int32& _ReferenceCount();
|
||||
const int32& _ReferenceCount() const;
|
||||
bool _IsShareable() const;
|
||||
void _FreePrivateData();
|
||||
|
||||
|
||||
@@ -196,19 +196,21 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/* Atomic functions; previous value is returned */
|
||||
extern int32 atomic_set(vint32 *value, int32 newValue);
|
||||
extern int32 atomic_test_and_set(vint32 *value, int32 newValue, int32 testAgainst);
|
||||
extern int32 atomic_add(vint32 *value, int32 addValue);
|
||||
extern int32 atomic_and(vint32 *value, int32 andValue);
|
||||
extern int32 atomic_or(vint32 *value, int32 orValue);
|
||||
extern int32 atomic_get(vint32 *value);
|
||||
extern void atomic_set(int32* value, int32 newValue);
|
||||
extern int32 atomic_get_and_set(int32* value, int32 newValue);
|
||||
extern int32 atomic_test_and_set(int32 *value, int32 newValue, int32 testAgainst);
|
||||
extern int32 atomic_add(int32 *value, int32 addValue);
|
||||
extern int32 atomic_and(int32 *value, int32 andValue);
|
||||
extern int32 atomic_or(int32 *value, int32 orValue);
|
||||
extern int32 atomic_get(int32 *value);
|
||||
|
||||
extern int64 atomic_set64(vint64 *value, int64 newValue);
|
||||
extern int64 atomic_test_and_set64(vint64 *value, int64 newValue, int64 testAgainst);
|
||||
extern int64 atomic_add64(vint64 *value, int64 addValue);
|
||||
extern int64 atomic_and64(vint64 *value, int64 andValue);
|
||||
extern int64 atomic_or64(vint64 *value, int64 orValue);
|
||||
extern int64 atomic_get64(vint64 *value);
|
||||
extern void atomic_set64(int64* value, int64 newValue);
|
||||
extern int64 atomic_get_and_set64(int64* value, int64 newValue);
|
||||
extern int64 atomic_test_and_set64(int64 *value, int64 newValue, int64 testAgainst);
|
||||
extern int64 atomic_add64(int64 *value, int64 addValue);
|
||||
extern int64 atomic_and64(int64 *value, int64 andValue);
|
||||
extern int64 atomic_or64(int64 *value, int64 orValue);
|
||||
extern int64 atomic_get64(int64 *value);
|
||||
|
||||
/* Other stuff */
|
||||
extern void* get_stack_frame(void);
|
||||
@@ -240,15 +242,6 @@ extern void* get_stack_frame(void);
|
||||
__sync_fetch_and_and(valuePointer, andValue)
|
||||
#define atomic_or(valuePointer, orValue) \
|
||||
__sync_fetch_and_or(valuePointer, orValue)
|
||||
#define atomic_get(valuePointer) \
|
||||
__sync_fetch_and_or(valuePointer, 0)
|
||||
// No equivalent to atomic_get(). We simulate it via atomic or. On most
|
||||
// (all?) 32+ bit architectures aligned 32 bit reads will be atomic anyway,
|
||||
// though.
|
||||
|
||||
// Note: No equivalent for atomic_set(). It could be simulated by a
|
||||
// get + atomic test and set loop, but calling the atomic_set() implementation
|
||||
// might be faster.
|
||||
|
||||
#endif // B_USE_BUILTIN_ATOMIC_FUNCTIONS && __GNUC__ >= 4
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
typedef uint32_t bus_addr_t;
|
||||
typedef uint32_t bus_size_t;
|
||||
|
||||
#define atomic_readandclear_int(ptr) atomic_set((int32 *)(ptr), 0)
|
||||
#define atomic_readandclear_int(ptr) atomic_get_and_set((int32*)(ptr), 0)
|
||||
#define atomic_set_int(ptr, value) atomic_or((int32 *)(ptr), value)
|
||||
|
||||
#define mtx_lock mutex_lock
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
// #pragma mark - fssh_atomic.h
|
||||
|
||||
#define atomic_set fssh_atomic_set
|
||||
#define atomic_get_and_Set fssh_atomic_get_and_set
|
||||
#define atomic_test_and_set fssh_atomic_test_and_set
|
||||
#define atomic_add fssh_atomic_add
|
||||
#define atomic_and fssh_atomic_and
|
||||
|
||||
@@ -15,21 +15,23 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
int32_t fssh_atomic_set(vint32_t *value, int32_t newValue);
|
||||
int32_t fssh_atomic_test_and_set(vint32_t *value, int32_t newValue,
|
||||
void fssh_atomic_set(int32_t* value, int32_t newValue);
|
||||
int32_t fssh_atomic_get_and_set(int32_t* value, int32_t newValue);
|
||||
int32_t fssh_atomic_test_and_set(int32_t *value, int32_t newValue,
|
||||
int32_t testAgainst);
|
||||
int32_t fssh_atomic_add(vint32_t *value, int32_t addValue);
|
||||
int32_t fssh_atomic_and(vint32_t *value, int32_t andValue);
|
||||
int32_t fssh_atomic_or(vint32_t *value, int32_t orValue);
|
||||
int32_t fssh_atomic_get(vint32_t *value);
|
||||
int32_t fssh_atomic_add(int32_t *value, int32_t addValue);
|
||||
int32_t fssh_atomic_and(int32_t *value, int32_t andValue);
|
||||
int32_t fssh_atomic_or(int32_t *value, int32_t orValue);
|
||||
int32_t fssh_atomic_get(int32_t *value);
|
||||
|
||||
int64_t fssh_atomic_set64(vint64_t *value, int64_t newValue);
|
||||
int64_t fssh_atomic_test_and_set64(vint64_t *value, int64_t newValue,
|
||||
void fssh_atomic_set64(int64_t* value, int64_t newValue);
|
||||
int64_t fssh_atomic_get_and_set64(int64_t* value, int64_t newValue);
|
||||
int64_t fssh_atomic_test_and_set64(int64_t *value, int64_t newValue,
|
||||
int64_t testAgainst);
|
||||
int64_t fssh_atomic_add64(vint64_t *value, int64_t addValue);
|
||||
int64_t fssh_atomic_and64(vint64_t *value, int64_t andValue);
|
||||
int64_t fssh_atomic_or64(vint64_t *value, int64_t orValue);
|
||||
int64_t fssh_atomic_get64(vint64_t *value);
|
||||
int64_t fssh_atomic_add64(int64_t *value, int64_t addValue);
|
||||
int64_t fssh_atomic_and64(int64_t *value, int64_t andValue);
|
||||
int64_t fssh_atomic_or64(int64_t *value, int64_t orValue);
|
||||
int64_t fssh_atomic_get64(int64_t *value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ status_t smp_per_cpu_init(struct kernel_args *args, int32 cpu);
|
||||
status_t smp_init_post_generic_syscalls(void);
|
||||
bool smp_trap_non_boot_cpus(int32 cpu, uint32* rendezVous);
|
||||
void smp_wake_up_non_boot_cpus(void);
|
||||
void smp_cpu_rendezvous(volatile uint32 *var, int current_cpu);
|
||||
void smp_cpu_rendezvous(uint32 *var, int current_cpu);
|
||||
void smp_send_ici(int32 targetCPU, int32 message, addr_t data, addr_t data2, addr_t data3,
|
||||
void *data_ptr, uint32 flags);
|
||||
void smp_send_multicast_ici(cpu_mask_t cpuMask, int32 message, addr_t data,
|
||||
@@ -107,7 +107,7 @@ static inline bool
|
||||
try_acquire_write_seqlock_inline(seqlock* lock) {
|
||||
bool succeed = try_acquire_spinlock(&lock->lock);
|
||||
if (succeed)
|
||||
atomic_add(&lock->count, 1);
|
||||
atomic_add((int32*)&lock->count, 1);
|
||||
return succeed;
|
||||
}
|
||||
|
||||
@@ -115,26 +115,26 @@ try_acquire_write_seqlock_inline(seqlock* lock) {
|
||||
static inline void
|
||||
acquire_write_seqlock_inline(seqlock* lock) {
|
||||
acquire_spinlock(&lock->lock);
|
||||
atomic_add(&lock->count, 1);
|
||||
atomic_add((int32*)&lock->count, 1);
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
release_write_seqlock_inline(seqlock* lock) {
|
||||
atomic_add(&lock->count, 1);
|
||||
atomic_add((int32*)&lock->count, 1);
|
||||
release_spinlock(&lock->lock);
|
||||
}
|
||||
|
||||
|
||||
static inline uint32
|
||||
acquire_read_seqlock_inline(seqlock* lock) {
|
||||
return atomic_get(&lock->count);
|
||||
return atomic_get((int32*)&lock->count);
|
||||
}
|
||||
|
||||
|
||||
static inline bool
|
||||
release_read_seqlock_inline(seqlock* lock, uint32 count) {
|
||||
uint32 current = atomic_get(&lock->count);
|
||||
uint32 current = atomic_get((int32*)&lock->count);
|
||||
|
||||
return count % 2 == 0 && current == count;
|
||||
}
|
||||
|
||||
@@ -18,22 +18,34 @@ atomic_pointer_test_and_set(PointerType** _pointer, const PointerType* set,
|
||||
const PointerType* test)
|
||||
{
|
||||
#if LONG_MAX == INT_MAX
|
||||
return (PointerType*)atomic_test_and_set((vint32*)_pointer, (int32)set,
|
||||
return (PointerType*)atomic_test_and_set((int32*)_pointer, (int32)set,
|
||||
(int32)test);
|
||||
#else
|
||||
return (PointerType*)atomic_test_and_set64((vint64*)_pointer, (int64)set,
|
||||
return (PointerType*)atomic_test_and_set64((int64*)_pointer, (int64)set,
|
||||
(int64)test);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
template<typename PointerType> PointerType*
|
||||
atomic_pointer_set(PointerType** _pointer, const PointerType* set)
|
||||
atomic_pointer_get_and_set(PointerType** _pointer, const PointerType* set)
|
||||
{
|
||||
#if LONG_MAX == INT_MAX
|
||||
return (PointerType*)atomic_set((vint32*)_pointer, (int32)set);
|
||||
return (PointerType*)atomic_get_and_set((int32*)_pointer, (int32)set);
|
||||
#else
|
||||
return (PointerType*)atomic_set64((vint64*)_pointer, (int64)set);
|
||||
return (PointerType*)atomic_get_and_set64((int64*)_pointer, (int64)set);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
template<typename PointerType> void
|
||||
atomic_pointer_set(PointerType** _pointer, const PointerType* set)
|
||||
{
|
||||
ASSERT((addr_t(_pointer) & (sizeof(PointerType*) - 1)) == 0);
|
||||
#if LONG_MAX == INT_MAX
|
||||
atomic_set((int32*)_pointer, (int32)set);
|
||||
#else
|
||||
atomic_set64((int64*)_pointer, (int64)set);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -41,10 +53,11 @@ atomic_pointer_set(PointerType** _pointer, const PointerType* set)
|
||||
template<typename PointerType> PointerType*
|
||||
atomic_pointer_get(PointerType** _pointer)
|
||||
{
|
||||
ASSERT((addr_t(_pointer) & (sizeof(PointerType*) - 1)) == 0);
|
||||
#if LONG_MAX == INT_MAX
|
||||
return (PointerType*)atomic_get((vint32*)_pointer);
|
||||
return (PointerType*)atomic_get((int32*)_pointer);
|
||||
#else
|
||||
return (PointerType*)atomic_get64((vint64*)_pointer);
|
||||
return (PointerType*)atomic_get64((int64*)_pointer);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -50,12 +50,12 @@ typedef struct _pthread_rwlockattr {
|
||||
typedef void (*pthread_key_destructor)(void *data);
|
||||
|
||||
struct pthread_key {
|
||||
vint32 sequence;
|
||||
int32 sequence;
|
||||
pthread_key_destructor destructor;
|
||||
};
|
||||
|
||||
struct pthread_key_data {
|
||||
vint32 sequence;
|
||||
int32 sequence;
|
||||
void *value;
|
||||
};
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ private:
|
||||
|
||||
private:
|
||||
BDirectory fBaseDirectory;
|
||||
vint32 fNextNumber;
|
||||
int32 fNextNumber;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ protected:
|
||||
virtual void LastReferenceReleased();
|
||||
|
||||
protected:
|
||||
vint32 fReferenceCount;
|
||||
int32 fReferenceCount;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ public:
|
||||
void GetUnchecked();
|
||||
|
||||
private:
|
||||
vint32 fUseCount;
|
||||
int32 fUseCount;
|
||||
BWeakReferenceable* fObject;
|
||||
};
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ int32 recursive_lock_get_recursion(recursive_lock *lock);
|
||||
#define INIT_ONCE_UNINITIALIZED -1
|
||||
#define INIT_ONCE_INITIALIZED -4
|
||||
|
||||
status_t __init_once(vint32* control, status_t (*initRoutine)(void*),
|
||||
status_t __init_once(int32* control, status_t (*initRoutine)(void*),
|
||||
void* data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -32,12 +32,12 @@ public:
|
||||
return fString._IsShareable();
|
||||
}
|
||||
|
||||
static vint32& DataRefCount(char* data)
|
||||
static int32& DataRefCount(char* data)
|
||||
{
|
||||
return *(((int32 *)data) - 2);
|
||||
}
|
||||
|
||||
vint32& DataRefCount()
|
||||
int32& DataRefCount()
|
||||
{
|
||||
return DataRefCount(Data());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user