aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/include/asm/atomic_32.h
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-12-14 14:22:35 -0500
committerIngo Molnar <mingo@elte.hu>2008-12-14 14:30:47 -0500
commit9b194e831fb2c322ed81a373e49620f34edc2778 (patch)
tree60c3c292a5af83b01a03f0d9f54e69bb635a7c9b /arch/x86/include/asm/atomic_32.h
parent92bf73e90a35d40ebc1446488218f03833b36f86 (diff)
x86: implement atomic64_t on 32-bit
Impact: new API Implement the atomic64_t APIs on 32-bit as well. Will be used by the performance counters code. Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/include/asm/atomic_32.h')
-rw-r--r--arch/x86/include/asm/atomic_32.h218
1 files changed, 218 insertions, 0 deletions
diff --git a/arch/x86/include/asm/atomic_32.h b/arch/x86/include/asm/atomic_32.h
index ad5b9f6ecddf..9927e01b03c2 100644
--- a/arch/x86/include/asm/atomic_32.h
+++ b/arch/x86/include/asm/atomic_32.h
@@ -255,5 +255,223 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
255#define smp_mb__before_atomic_inc() barrier() 255#define smp_mb__before_atomic_inc() barrier()
256#define smp_mb__after_atomic_inc() barrier() 256#define smp_mb__after_atomic_inc() barrier()
257 257
258/* An 64bit atomic type */
259
260typedef struct {
261 unsigned long long counter;
262} atomic64_t;
263
264#define ATOMIC64_INIT(val) { (val) }
265
266/**
267 * atomic64_read - read atomic64 variable
268 * @v: pointer of type atomic64_t
269 *
270 * Atomically reads the value of @v.
271 * Doesn't imply a read memory barrier.
272 */
273#define __atomic64_read(ptr) ((ptr)->counter)
274
275static inline unsigned long long
276cmpxchg8b(unsigned long long *ptr, unsigned long long old, unsigned long long new)
277{
278 asm volatile(
279
280 LOCK_PREFIX "cmpxchg8b (%[ptr])\n"
281
282 : "=A" (old)
283
284 : [ptr] "D" (ptr),
285 "A" (old),
286 "b" (ll_low(new)),
287 "c" (ll_high(new))
288
289 : "memory");
290
291 return old;
292}
293
294static inline unsigned long long
295atomic64_cmpxchg(atomic64_t *ptr, unsigned long long old_val,
296 unsigned long long new_val)
297{
298 return cmpxchg8b(&ptr->counter, old_val, new_val);
299}
300
301/**
302 * atomic64_set - set atomic64 variable
303 * @ptr: pointer to type atomic64_t
304 * @new_val: value to assign
305 *
306 * Atomically sets the value of @ptr to @new_val.
307 */
308static inline void atomic64_set(atomic64_t *ptr, unsigned long long new_val)
309{
310 unsigned long long old_val;
311
312 do {
313 old_val = atomic_read(ptr);
314 } while (atomic64_cmpxchg(ptr, old_val, new_val) != old_val);
315}
316
317/**
318 * atomic64_read - read atomic64 variable
319 * @ptr: pointer to type atomic64_t
320 *
321 * Atomically reads the value of @ptr and returns it.
322 */
323static inline unsigned long long atomic64_read(atomic64_t *ptr)
324{
325 unsigned long long curr_val;
326
327 do {
328 curr_val = __atomic64_read(ptr);
329 } while (atomic64_cmpxchg(ptr, curr_val, curr_val) != curr_val);
330
331 return curr_val;
332}
333
334/**
335 * atomic64_add_return - add and return
336 * @delta: integer value to add
337 * @ptr: pointer to type atomic64_t
338 *
339 * Atomically adds @delta to @ptr and returns @delta + *@ptr
340 */
341static inline unsigned long long
342atomic64_add_return(unsigned long long delta, atomic64_t *ptr)
343{
344 unsigned long long old_val, new_val;
345
346 do {
347 old_val = atomic_read(ptr);
348 new_val = old_val + delta;
349
350 } while (atomic64_cmpxchg(ptr, old_val, new_val) != old_val);
351
352 return new_val;
353}
354
355static inline long atomic64_sub_return(unsigned long long delta, atomic64_t *ptr)
356{
357 return atomic64_add_return(-delta, ptr);
358}
359
360static inline long atomic64_inc_return(atomic64_t *ptr)
361{
362 return atomic64_add_return(1, ptr);
363}
364
365static inline long atomic64_dec_return(atomic64_t *ptr)
366{
367 return atomic64_sub_return(1, ptr);
368}
369
370/**
371 * atomic64_add - add integer to atomic64 variable
372 * @delta: integer value to add
373 * @ptr: pointer to type atomic64_t
374 *
375 * Atomically adds @delta to @ptr.
376 */
377static inline void atomic64_add(unsigned long long delta, atomic64_t *ptr)
378{
379 atomic64_add_return(delta, ptr);
380}
381
382/**
383 * atomic64_sub - subtract the atomic64 variable
384 * @delta: integer value to subtract
385 * @ptr: pointer to type atomic64_t
386 *
387 * Atomically subtracts @delta from @ptr.
388 */
389static inline void atomic64_sub(unsigned long long delta, atomic64_t *ptr)
390{
391 atomic64_add(-delta, ptr);
392}
393
394/**
395 * atomic64_sub_and_test - subtract value from variable and test result
396 * @delta: integer value to subtract
397 * @ptr: pointer to type atomic64_t
398 *
399 * Atomically subtracts @delta from @ptr and returns
400 * true if the result is zero, or false for all
401 * other cases.
402 */
403static inline int
404atomic64_sub_and_test(unsigned long long delta, atomic64_t *ptr)
405{
406 unsigned long long old_val = atomic64_sub_return(delta, ptr);
407
408 return old_val == 0;
409}
410
411/**
412 * atomic64_inc - increment atomic64 variable
413 * @ptr: pointer to type atomic64_t
414 *
415 * Atomically increments @ptr by 1.
416 */
417static inline void atomic64_inc(atomic64_t *ptr)
418{
419 atomic64_add(1, ptr);
420}
421
422/**
423 * atomic64_dec - decrement atomic64 variable
424 * @ptr: pointer to type atomic64_t
425 *
426 * Atomically decrements @ptr by 1.
427 */
428static inline void atomic64_dec(atomic64_t *ptr)
429{
430 atomic64_sub(1, ptr);
431}
432
433/**
434 * atomic64_dec_and_test - decrement and test
435 * @ptr: pointer to type atomic64_t
436 *
437 * Atomically decrements @ptr by 1 and
438 * returns true if the result is 0, or false for all other
439 * cases.
440 */
441static inline int atomic64_dec_and_test(atomic64_t *ptr)
442{
443 return atomic64_sub_and_test(1, ptr);
444}
445
446/**
447 * atomic64_inc_and_test - increment and test
448 * @ptr: pointer to type atomic64_t
449 *
450 * Atomically increments @ptr by 1
451 * and returns true if the result is zero, or false for all
452 * other cases.
453 */
454static inline int atomic64_inc_and_test(atomic64_t *ptr)
455{
456 return atomic64_sub_and_test(-1, ptr);
457}
458
459/**
460 * atomic64_add_negative - add and test if negative
461 * @delta: integer value to add
462 * @ptr: pointer to type atomic64_t
463 *
464 * Atomically adds @delta to @ptr and returns true
465 * if the result is negative, or false when
466 * result is greater than or equal to zero.
467 */
468static inline int
469atomic64_add_negative(unsigned long long delta, atomic64_t *ptr)
470{
471 long long old_val = atomic64_add_return(delta, ptr);
472
473 return old_val < 0;
474}
475
258#include <asm-generic/atomic.h> 476#include <asm-generic/atomic.h>
259#endif /* _ASM_X86_ATOMIC_32_H */ 477#endif /* _ASM_X86_ATOMIC_32_H */