/* * @(#)alpha.gcc 10.1 (Sleepycat) 4/12/97 * * The code appearing below is taken from Richard L. Sites, ed. "Alpha * Architecture Reference Manual", Digital Press, 1992, page 5-7 and 5-8. * There are 2 modifications: * * 1. The jump from blbs __r1,30f to !__r1, which is dictated by the way the * TSL_SET macro is used. The code suggested in Sites includes the main loop * of the spin lock, whereas in this code the rest the loop is specified in C. * The generated code might be suboptimal if the compiler generates a forward * branch for the usual case in which the mutex is uncontested. * * 2. At label 20, Sites suggests including code for testing for an excessive * number of _processor_ lock conflicts. (The seq_c instruction stores its * first argument provided that no other processor has written to a byte range * including its memory-location argument.) Absent such checking the code * below could conceivably stall silently on a multiprocessor alpha, depending * on how often processor/processor conflicts occur in a particular byte range. * * Note that the mb ("memory-barrier") instruction in TSL_UNSET is critical to * correct operation in a multiprocessor alpha (as is, of course, the mb in * the TSL_SET macro). Without the mb, changes to shared memory that occurred * inside the critical section (before the TSL_UNSET) might reach shared memory * _after_ the change of tsl to 0, thereby permitting another processor to see * an inconsistent view of the data protected by the mutex. * * For gcc/alpha, 0 is clear, 1 is set. */ #define TSL_SET(tsl) ({ \ register tsl_t *__l = (tsl); \ register tsl_t __r1, __r2; \ __asm__ volatile(" \n\ 10: ldq_l %0,(%2) \n\ blbs %0,30f \n\ or %0,1,%1 \n\ stq_c %1,(%2) \n\ beq %1,20f \n\ mb \n\ br 30f \n\ 20: br 10b \n\ 30: " \ : "=&r" (__r1), "=&r" (__r2) \ : "r" (__l)); \ !__r1; \ }) #define TSL_UNSET(tsl) ({ \ register tsl_t *__l = (tsl); \ __asm__ volatile("mb; stq $31,(%0);" : : "r" (__l)); \ }) #define TSL_INIT(tsl) TSL_UNSET(tsl)