diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-12-14 14:22:35 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-12-14 14:30:47 -0500 |
commit | 9b194e831fb2c322ed81a373e49620f34edc2778 (patch) | |
tree | 60c3c292a5af83b01a03f0d9f54e69bb635a7c9b /arch/x86/include/asm/atomic_32.h | |
parent | 92bf73e90a35d40ebc1446488218f03833b36f86 (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.h | 218 |
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 | |||
260 | typedef 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 | |||
275 | static inline unsigned long long | ||
276 | cmpxchg8b(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 | |||
294 | static inline unsigned long long | ||
295 | atomic64_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 | */ | ||
308 | static 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 | */ | ||
323 | static 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 | */ | ||
341 | static inline unsigned long long | ||
342 | atomic64_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 | |||
355 | static inline long atomic64_sub_return(unsigned long long delta, atomic64_t *ptr) | ||
356 | { | ||
357 | return atomic64_add_return(-delta, ptr); | ||
358 | } | ||
359 | |||
360 | static inline long atomic64_inc_return(atomic64_t *ptr) | ||
361 | { | ||
362 | return atomic64_add_return(1, ptr); | ||
363 | } | ||
364 | |||
365 | static 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 | */ | ||
377 | static 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 | */ | ||
389 | static 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 | */ | ||
403 | static inline int | ||
404 | atomic64_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 | */ | ||
417 | static 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 | */ | ||
428 | static 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 | */ | ||
441 | static 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 | */ | ||
454 | static 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 | */ | ||
468 | static inline int | ||
469 | atomic64_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 */ |