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 | |
| 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>
| -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 */ |
