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 jint Atomic::cmpxchg(jint xchg_val, volatile jint* dest, jint cmp_val, cmpxchg_memory_order unused) {
482 unsigned long old;
483
484 __asm__ __volatile__ (
485 " CS %[old],%[upd],%[mem] \n\t" // Try to xchg upd with mem.
486 // outputs
487 : [old] "=&d" (old) // Write-only, prev value irrelevant.
488 , [mem] "+Q" (*dest) // Read/write, memory to be updated atomically.
489 // inputs
490 : [upd] "d" (xchg_val)
491 , "0" (cmp_val) // Read-only, initial value for [old] (operand #0).
492 // clobbered
493 : "cc"
494 );
495
496 return (jint)old;
497 }
498
499 jlong Atomic::cmpxchg(jlong xchg_val, volatile jlong* dest, jlong cmp_val, cmpxchg_memory_order unused) {
500 unsigned long old;
501
502 __asm__ __volatile__ (
503 " CSG %[old],%[upd],%[mem] \n\t" // Try to xchg upd with mem.
504 // outputs
505 : [old] "=&d" (old) // Write-only, prev value irrelevant.
506 , [mem] "+Q" (*dest) // Read/write, memory to be updated atomically.
507 // inputs
508 : [upd] "d" (xchg_val)
509 , "0" (cmp_val) // Read-only, initial value for [old] (operand #0).
510 // clobbered
511 : "cc"
512 );
513
514 return (jlong)old;
515 }
516
517 void* Atomic::cmpxchg_ptr(void *xchg_val, volatile void* dest, void* cmp_val, cmpxchg_memory_order unused) {
518 return (void*)cmpxchg((jlong)xchg_val, (volatile jlong*)dest, (jlong)cmp_val, unused);
519 }
520
521 intptr_t Atomic::cmpxchg_ptr(intptr_t xchg_val, volatile intptr_t* dest, intptr_t cmp_val, cmpxchg_memory_order unused) {
522 return (intptr_t)cmpxchg((jlong)xchg_val, (volatile jlong*)dest, (jlong)cmp_val, unused);
523 }
524
525 inline jlong Atomic::load(const volatile jlong* src) { return *src; }
526
527 #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 T 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 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
|