Module Name: src Committed By: riastradh Date: Sun Sep 8 15:37:04 UTC 2013
Modified Files: src/sys/external/bsd/drm2/include/linux [riastradh-drm2]: atomic.h Log Message: Fix Linux atomic set/clear/change_bit to work on arrays. To generate a diff of this commit: cvs rdiff -u -r1.1.2.9 -r1.1.2.10 \ src/sys/external/bsd/drm2/include/linux/atomic.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/external/bsd/drm2/include/linux/atomic.h diff -u src/sys/external/bsd/drm2/include/linux/atomic.h:1.1.2.9 src/sys/external/bsd/drm2/include/linux/atomic.h:1.1.2.10 --- src/sys/external/bsd/drm2/include/linux/atomic.h:1.1.2.9 Wed Jul 24 03:35:50 2013 +++ src/sys/external/bsd/drm2/include/linux/atomic.h Sun Sep 8 15:37:04 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: atomic.h,v 1.1.2.9 2013/07/24 03:35:50 riastradh Exp $ */ +/* $NetBSD: atomic.h,v 1.1.2.10 2013/09/08 15:37:04 riastradh Exp $ */ /*- * Copyright (c) 2013 The NetBSD Foundation, Inc. @@ -34,6 +34,8 @@ #include <sys/atomic.h> +#include <machine/limits.h> + struct atomic { union { int au_int; @@ -125,53 +127,69 @@ atomic_inc_not_zero(atomic_t *atomic) } static inline void -set_bit(unsigned long bit, volatile unsigned long *ptr) +set_bit(unsigned int bit, volatile unsigned long *ptr) { - atomic_or_ulong(ptr, (1 << bit)); + const unsigned int units = (sizeof(*ptr) * CHAR_BIT); + + atomic_or_ulong(&ptr[bit / units], (1UL << (bit % units))); } static inline void -clear_bit(unsigned long bit, volatile unsigned long *ptr) +clear_bit(unsigned int bit, volatile unsigned long *ptr) { - atomic_and_ulong(ptr, ~(1 << bit)); + const unsigned int units = (sizeof(*ptr) * CHAR_BIT); + + atomic_and_ulong(&ptr[bit / units], ~(1UL << (bit % units))); } static inline void -change_bit(unsigned long bit, volatile unsigned long *ptr) +change_bit(unsigned int bit, volatile unsigned long *ptr) { + const unsigned int units = (sizeof(*ptr) * CHAR_BIT); + volatile unsigned long *const p = &ptr[bit / units]; + const unsigned long mask = (1UL << (bit % units)); unsigned long v; - do v = *ptr; while (atomic_cas_ulong(ptr, v, v ^ (1 << bit)) != v); + do v = *p; while (atomic_cas_ulong(p, v, (v ^ mask)) != v); } static inline unsigned long -test_and_set_bit(unsigned long bit, volatile unsigned long *ptr) +test_and_set_bit(unsigned int bit, volatile unsigned long *ptr) { + const unsigned int units = (sizeof(*ptr) * CHAR_BIT); + volatile unsigned long *const p = &ptr[bit / units]; + const unsigned long mask = (1UL << (bit % units)); unsigned long v; - do v = *ptr; while (atomic_cas_ulong(ptr, v, v | (1 << bit)) != v); + do v = *p; while (atomic_cas_ulong(p, v, (v | mask)) != v); - return (v & (1 << bit)); + return (v & mask); } static inline unsigned long -test_and_clear_bit(unsigned long bit, volatile unsigned long *ptr) +test_and_clear_bit(unsigned int bit, volatile unsigned long *ptr) { + const unsigned int units = (sizeof(*ptr) * CHAR_BIT); + volatile unsigned long *const p = &ptr[bit / units]; + const unsigned long mask = (1UL << (bit % units)); unsigned long v; - do v = *ptr; while (atomic_cas_ulong(ptr, v, v &~ (1 << bit)) != v); + do v = *p; while (atomic_cas_ulong(p, v, (v & ~mask)) != v); - return (v & (1 << bit)); + return (v & mask); } static inline unsigned long -test_and_change_bit(unsigned long bit, volatile unsigned long *ptr) +test_and_change_bit(unsigned int bit, volatile unsigned long *ptr) { + const unsigned int units = (sizeof(*ptr) * CHAR_BIT); + volatile unsigned long *const p = &ptr[bit / units]; + const unsigned long mask = (1UL << (bit % units)); unsigned long v; - do v = *ptr; while (atomic_cas_ulong(ptr, v, v ^ (1 << bit)) != v); + do v = *p; while (atomic_cas_ulong(p, v, (v ^ mask)) != v); - return (v & (1 << bit)); + return (v & mask); } #if defined(MULTIPROCESSOR) && !defined(__HAVE_ATOMIC_AS_MEMBAR)