461 //
462 // The return value is the (unchanged) value from memory as it was when the
463 // compare-and-swap instruction completed. A successful exchange operation
464 // is indicated by (return value == compare_value). If unsuccessful, a new
465 // exchange value can be calculated based on the return value which is the
466 // latest contents of the memory location.
467 //
468 // Inspecting the return value is the only way for the caller to determine
469 // if the compare-and-swap instruction was successful:
470 // - If return value and compare value compare equal, the compare-and-swap
471 // instruction was successful and the value in memory was replaced by the
472 // exchange value.
473 // - If return value and compare value compare unequal, the compare-and-swap
474 // instruction was not successful. The value in memory was left unchanged.
475 //
476 // The s390 processors always fence before and after the csg instructions.
477 // Thus we ignore the memory ordering argument. The docu says: "A serialization
478 // function is performed before the operand is fetched and again after the
479 // operation is completed."
480
481 template<>
482 struct Atomic::PlatformCmpxchg<1> : Atomic::CmpxchgByteUsingInt {};
483
484 template<>
485 template<typename T>
486 inline T Atomic::PlatformCmpxchg<4>::operator()(T xchg_val,
487 T volatile* dest,
488 T cmp_val,
489 cmpxchg_memory_order unused) const {
490 unsigned long old;
491
492 __asm__ __volatile__ (
493 " CS %[old],%[upd],%[mem] \n\t" // Try to xchg upd with mem.
494 // outputs
495 : [old] "=&d" (old) // Write-only, prev value irrelevant.
496 , [mem] "+Q" (*dest) // Read/write, memory to be updated atomically.
497 // inputs
498 : [upd] "d" (xchg_val)
499 , "0" (cmp_val) // Read-only, initial value for [old] (operand #0).
500 // clobbered
501 : "cc"
502 );
503
504 return IntegerTypes::cast<T>((uint32_t)old);
505 }
506
507 template<>
508 template<typename T>
509 inline T Atomic::PlatformCmpxchg<8>::operator()(T xchg_val,
510 T volatile* dest,
511 T cmp_val,
512 cmpxchg_memory_order unused) const {
513 unsigned long old;
514
515 __asm__ __volatile__ (
516 " CSG %[old],%[upd],%[mem] \n\t" // Try to xchg upd with mem.
517 // outputs
518 : [old] "=&d" (old) // Write-only, prev value irrelevant.
519 , [mem] "+Q" (*dest) // Read/write, memory to be updated atomically.
520 // inputs
521 : [upd] "d" (xchg_val)
522 , "0" (cmp_val) // Read-only, initial value for [old] (operand #0).
523 // clobbered
524 : "cc"
525 );
526
527 return IntegerTypes::cast<T>(old);
528 }
529
530 inline jlong Atomic::load(const volatile jlong* src) { return *src; }
531
532 #endif // OS_CPU_LINUX_S390_VM_ATOMIC_LINUX_S390_INLINE_HPP
|
461 //
462 // The return value is the (unchanged) value from memory as it was when the
463 // compare-and-swap instruction completed. A successful exchange operation
464 // is indicated by (return value == compare_value). If unsuccessful, a new
465 // exchange value can be calculated based on the return value which is the
466 // latest contents of the memory location.
467 //
468 // Inspecting the return value is the only way for the caller to determine
469 // if the compare-and-swap instruction was successful:
470 // - If return value and compare value compare equal, the compare-and-swap
471 // instruction was successful and the value in memory was replaced by the
472 // exchange value.
473 // - If return value and compare value compare unequal, the compare-and-swap
474 // instruction was not successful. The value in memory was left unchanged.
475 //
476 // The s390 processors always fence before and after the csg instructions.
477 // Thus we ignore the memory ordering argument. The docu says: "A serialization
478 // function is performed before the operand is fetched and again after the
479 // operation is completed."
480
481 // No direct support for cmpxchg of bytes; emulate using int.
482 template<>
483 struct Atomic::PlatformCmpxchg<1> : Atomic::CmpxchgByteUsingInt {};
484
485 template<>
486 template<typename T>
487 inline T Atomic::PlatformCmpxchg<4>::operator()(T xchg_val,
488 T volatile* dest,
489 T cmp_val,
490 cmpxchg_memory_order unused) const {
491 STATIC_ASSERT(4 == sizeof(T));
492 unsigned long old;
493
494 __asm__ __volatile__ (
495 " CS %[old],%[upd],%[mem] \n\t" // Try to xchg upd with mem.
496 // outputs
497 : [old] "=&d" (old) // Write-only, prev value irrelevant.
498 , [mem] "+Q" (*dest) // Read/write, memory to be updated atomically.
499 // inputs
500 : [upd] "d" (xchg_val)
501 , "0" (cmp_val) // Read-only, initial value for [old] (operand #0).
502 // clobbered
503 : "cc"
504 );
505
506 return IntegerTypes::cast<T>((uint32_t)old);
507 }
508
509 template<>
510 template<typename T>
511 inline T Atomic::PlatformCmpxchg<8>::operator()(T xchg_val,
512 T volatile* dest,
513 T cmp_val,
514 cmpxchg_memory_order unused) const {
515 STATIC_ASSERT(8 == sizeof(T));
516 T old;
517
518 __asm__ __volatile__ (
519 " CSG %[old],%[upd],%[mem] \n\t" // Try to xchg upd with mem.
520 // outputs
521 : [old] "=&d" (old) // Write-only, prev value irrelevant.
522 , [mem] "+Q" (*dest) // Read/write, memory to be updated atomically.
523 // inputs
524 : [upd] "d" (xchg_val)
525 , "0" (cmp_val) // Read-only, initial value for [old] (operand #0).
526 // clobbered
527 : "cc"
528 );
529
530 return old;
531 }
532
533 inline jlong Atomic::load(const volatile jlong* src) { return *src; }
534
535 #endif // OS_CPU_LINUX_S390_VM_ATOMIC_LINUX_S390_INLINE_HPP
|