Hi Jason - Can you explain why the existing atomics interface in Atomics.chpl is not sufficient?
Then, assuming you need some different functionality, why not extend the existing atomics implementation instead of creating a completely new one? The existing implementation defines functions like atomic_fetch_add_explicit_uint_least64 in runtime/include/atomics/*/chpl-atomics.h For example, to create XLC style Power intrinsics, it would make sense to add a new directory there with a different .h file. You can call these C functions directly from Chapel, although I could believe that you need to change something to get them to do what you want. The Atomics module mostly adds an 'on' statement around these calls. Cheers, -michael ________________________________________ From: Jason Riedy [[email protected]] Sent: Tuesday, November 19, 2013 18:50 To: [email protected] Subject: Atomic-intrinsics.chpl sanity check [this is a bit of a follow-up to in-person interactions at SC13, but posting it here for a wider audience (aka not pestering Brad *again*)...] Does the following seem like a half-way sane method for adapting to different compilers' intrinsics in Chapel? There's heavy cheating around the ll/sc, and I don't have a Power account handy for testing, so consider this a sketch... // module Atomic-intrinsics.chpl use Atomics; module impl { use ChapelBase; // XXX: Don't recall if pgi implements these... inline proc gccish_intrinsics() param { return CHPL_TARGET_COMPILER == "gnu" || CHPL_TARGET_COMPILER == "intel" || CHPL_TARGET_COMPILER == "pgi" || CHPL_TARGET_COMPILER == "cray-prgenv-gnu" || CHPL_TARGET_COMPILER == "cray-prgenv-intel" || CHPL_TARGET_COMPILER == "cray-prgenv-pgi"; } // XXX: This should be for xlc on power and not other platforms. inline proc xlcish_power_intrinsics() param { return CHPL_TARGET_COMPILER == "xlc"; } inline proc xmtish_intrinsics() param { compilerError("Get a real machine."); return false; } inline proc target_compiler_name() param { return CHPL_TARGET_COMPILER; } } use impl; // local{} clauses just to make sure... // OP: add inline proc atomic_fetch_add(ref x, val: x.type, const order:memory_order=memory_order_seq_cst) : x.type { if (gccish_intrinsics()) { extern proc __atomic_fetch_add(ref x: real(64), val: real(64), order:memory_order) : real(64); extern proc __atomic_fetch_add(ref x: int(64), val: int(64), order:memory_order) : int(64); extern proc __atomic_fetch_add(ref x: uint(64), val: uint(64), order:memory_order) : uint(64); extern proc __atomic_fetch_add(ref x: real(32), val: real(32), order:memory_order) : real(32); extern proc __atomic_fetch_add(ref x: int(32), val: int(32), order:memory_order) : int(32); extern proc __atomic_fetch_add(ref x: uint(32), val: uint(32), order:memory_order) : uint(32); extern proc __atomic_fetch_add(ref x: int(16), val: int(16), order:memory_order) : int(16); extern proc __atomic_fetch_add(ref x: uint(16), val: uint(16), order:memory_order) : uint(16); extern proc __atomic_fetch_add(ref x: int(8), val: int(8), order:memory_order) : int(8); extern proc __atomic_fetch_add(ref x: uint(8), val: uint(8), order:memory_order) : uint(8); inline proc __atomic_fetch_add(x, val, order) { compilerError("No fetch and add for this type."); return 0:x.type; } var retval : x.type; local { retval = __atomic_fetch_add(x, val, order); } return retval; } else if (xlcish_power_intrinsics()) { compilerWarning("Completely untested atomics for ", target_compiler_name()); compilerWarning(" Needs isync, eieio, etc. for memory order."); var retval : x.type; inline proc __fa(ref x: int(32), in val: int(32)) { extern proc __fetch_and_add(ref x: int(32), in val: int(32)) : int(32); return __fetch_and_add(x, val); } inline proc __fa(ref x: int(64), in val: int(64)) { extern proc __fetch_and_addlp(ref x: int(64), in val: int(64)) : int(64); return __fetch_and_addlp(x, val); } inline proc __fa(ref x: real(32), in val: real(32)) { extern proc __lwarx(ref x: real(32)) : real(32); extern proc __stwcx(ref x: real(32), in val: real(32)) : int(32); var outval : real(32); var newval : real(32); do { outval = __lwarx(x); newval = outval + val; } while !(__stwcx (x, newval)); return outval; } inline proc __fa(ref x: real(64), in val: real(64)) { extern proc __ldarx(ref x: real(64)) : real(64); extern proc __stdcx(ref x: real(64), in val: real(64)) : int(64); var outval : real(64); var newval : real(64); do { outval = __ldarx(x); newval = outval + val; } while !(__stdcx (x, newval)); return outval; } inline proc __fa(x, val) { compilerError("No fetch and add for this type."); } local { retval = __fa(x, val); } return retval; } else { compilerError("Unrecognized target compiler: ", target_compiler_name()); } } inline proc atomic_add_fetch(ref x, val: x.type, const order:memory_order=memory_order_seq_cst) : x.type { if (gccish_intrinsics()) { extern proc __atomic_add_fetch(ref x: real(64), val: real(64), order:memory_order) : real(64); extern proc __atomic_add_fetch(ref x: int(64), val: int(64), order:memory_order) : int(64); extern proc __atomic_add_fetch(ref x: uint(64), val: uint(64), order:memory_order) : uint(64); extern proc __atomic_add_fetch(ref x: real(32), val: real(32), order:memory_order) : real(32); extern proc __atomic_add_fetch(ref x: int(32), val: int(32), order:memory_order) : int(32); extern proc __atomic_add_fetch(ref x: uint(32), val: uint(32), order:memory_order) : uint(32); extern proc __atomic_add_fetch(ref x: int(16), val: int(16), order:memory_order) : int(16); extern proc __atomic_add_fetch(ref x: uint(16), val: uint(16), order:memory_order) : uint(16); extern proc __atomic_add_fetch(ref x: int(8), val: int(8), order:memory_order) : int(8); extern proc __atomic_add_fetch(ref x: uint(8), val: uint(8), order:memory_order) : uint(8); inline proc __atomic_add_fetch(x, val, order) { compilerError("No fetch and add for this type."); return 0:x.type; } var retval : x.type; local { retval = __atomic_add_fetch(x, val, order); } return retval; } else if (xlcish_power_intrinsics()) { compilerWarning("Completely untested atomics for ", target_compiler_name()); compilerWarning(" Needs isync, eieio, etc. for memory order."); var retval : x.type; inline proc __fa(ref x: int(32), in val: int(32)) { extern proc __fetch_and_add(ref x: int(32), in val: int(32)) : int(32); return __fetch_and_add(x, val) + val; } inline proc __fa(ref x: int(64), in val: int(64)) { extern proc __fetch_and_addlp(ref x: int(64), in val: int(64)) : int(64); return __fetch_and_addlp(x, val) + val; } inline proc __fa(ref x: real(32), in val: real(32)) { extern proc __lwarx(ref x: real(32)) : real(32); extern proc __stwcx(ref x: real(32), in val: real(32)) : int(32); var outval : real(32); var newval : real(32); do { outval = __lwarx(x); newval = outval + val; } while !(__stwcx (x, newval)); return newval; } inline proc __fa(ref x: real(64), in val: real(64)) { extern proc __ldarx(ref x: real(64)) : real(64); extern proc __stdcx(ref x: real(64), in val: real(64)) : int(64); var outval : real(64); var newval : real(64); do { outval = __ldarx(x); newval = outval + val; } while !(__stdcx (x, newval)); return newval; } inline proc __fa(x, val) { compilerError("No fetch and add for this type."); } local { retval = __fa(x, val); } return retval; } else { compilerError("Unrecognized target compiler: ", target_compiler_name()); } } inline proc atomic_add(ref x, val: x.type, const order:memory_order=memory_order_seq_cst) : x.type { // Sufficient. return atomic_fetch_add(x, val, order); } -- Jason Riedy ------------------------------------------------------------------------------ Shape the Mobile Experience: Free Subscription Software experts and developers: Be at the forefront of tech innovation. Intel(R) Software Adrenaline delivers strategic insight and game-changing conversations that shape the rapidly evolving mobile landscape. Sign up now. http://pubads.g.doubleclick.net/gampad/clk?id=63431311&iu=/4140/ostg.clktrk _______________________________________________ Chapel-users mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/chapel-users ------------------------------------------------------------------------------ Shape the Mobile Experience: Free Subscription Software experts and developers: Be at the forefront of tech innovation. Intel(R) Software Adrenaline delivers strategic insight and game-changing conversations that shape the rapidly evolving mobile landscape. Sign up now. http://pubads.g.doubleclick.net/gampad/clk?id=63431311&iu=/4140/ostg.clktrk _______________________________________________ Chapel-users mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/chapel-users
