123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113 |
- /* Copyright (C) 2014 OSCAR lab, Stony Brook University
- This file is part of Graphene Library OS.
- Graphene Library OS is free software: you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation, either version 3 of the
- License, or (at your option) any later version.
- Graphene Library OS is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
- /*
- * bitop.h
- */
- #ifndef _BITOP_H
- #define _BITOP_H
- #define ADDR (*(volatile long *) addr)
- #define LOCK_PREFIX ""
- /**
- * set_bit - Atomically set a bit in memory
- * @nr: the bit to set
- * @addr: the address to start counting from
- *
- * This function is atomic and may not be reordered. See __set_bit()
- * if you do not require the atomic guarantees.
- * Note that @nr may be almost arbitrarily large; this function is not
- * restricted to acting on a single-word quantity.
- */
- static __inline__ void set_bit(int nr, volatile void * addr)
- {
- __asm__ __volatile__( LOCK_PREFIX
- "btsl %1,%0"
- :"=m" (ADDR)
- :"dIr" (nr) : "memory");
- }
- /**
- * __set_bit - Set a bit in memory
- * @nr: the bit to set
- * @addr: the address to start counting from
- *
- * Unlike set_bit(), this function is non-atomic and may be reordered.
- * If it's called on the same region of memory simultaneously, the effect
- * may be that only one operation succeeds.
- */
- static __inline__ void __set_bit(int nr, volatile void * addr)
- {
- __asm__ volatile(
- "btsl %1,%0"
- :"=m" (ADDR)
- :"dIr" (nr) : "memory");
- }
- /**
- * clear_bit - Clears a bit in memory
- * @nr: Bit to clear
- * @addr: Address to start counting from
- *
- * clear_bit() is atomic and may not be reordered. However, it does
- * not contain a memory barrier, so if it is used for locking purposes,
- * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit()
- * in order to ensure changes are visible on other processors.
- */
- static __inline__ void clear_bit(int nr, volatile void * addr)
- {
- __asm__ __volatile__( LOCK_PREFIX
- "btrl %1,%0"
- :"=m" (ADDR)
- :"dIr" (nr));
- }
- static __inline__ void __clear_bit(int nr, volatile void * addr)
- {
- __asm__ __volatile__(
- "btrl %1,%0"
- :"=m" (ADDR)
- :"dIr" (nr));
- }
- static __inline__ int constant_test_bit(int nr, const volatile void * addr)
- {
- return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
- }
- static __inline__ int variable_test_bit(int nr, volatile const void * addr)
- {
- int oldbit;
- __asm__ __volatile__(
- "btl %2,%1\n\tsbbl %0,%0"
- :"=r" (oldbit)
- :"m" (ADDR),"dIr" (nr));
- return oldbit;
- }
- #define test_bit(nr,addr) \
- (__builtin_constant_p(nr) ? \
- constant_test_bit((nr),(addr)) : \
- variable_test_bit((nr),(addr)))
- #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
- #endif
|