////////////////////////////////////////////////////////////////////////////////// // File : spin_lock.c // Date : 01/04/2012 // Author : alain greiner // Copyright (c) UPMC-LIP6 /////////////////////////////////////////////////////////////////////////////////// #include #include /////////////////////////////////////////////////////////////////////////////////// // lock_acquire() // This blocking function returns only when the lock has been taken. // If the lock is already taken a random delay is introduced before retry. /////////////////////////////////////////////////////////////////////////////////// void lock_acquire(giet_lock_t * lock) { unsigned int * plock = &lock->value; unsigned int delay = giet_rand(); if (delay == 0) delay++; asm volatile ( "giet_lock_try: \n" "ll $2, 0(%0) \n" /* $2 <= _ioc_lock current value */ "bnez $2, giet_lock_delay \n" /* delay if _ioc_lock already taken */ "li $3, 1 \n" /* $3 <= argument for sc */ "sc $3, 0(%0) \n" /* try to set _ioc_lock */ "bnez $3, giet_lock_ok \n" /* exit if atomic */ "giet_lock_delay: \n" "move $4, %1 \n" /* $4 <= delay */ "giet_lock_loop: \n" "addi $4, $4, -1 \n" /* $4 <= $4 - 1 */ "bnez $4, giet_lock_loop \n" /* test end delay */ "nop \n" "j giet_lock_try \n" /* retry */ "nop \n" "giet_lock_ok: \n" : :"r"(plock), "r"(delay) :"$2", "$3", "$4"); } ////////////////////////////////////////////////////////////////////////////// // lock_release() ////////////////////////////////////////////////////////////////////////////// void lock_release(giet_lock_t * lock) { unsigned int * plock = &lock->value; asm volatile ( "sync\n" ); // necessary because of the TSAR consistency model *plock = 0; } // Local Variables: // tab-width: 4 // c-basic-offset: 4 // c-file-offsets:((innamespace . 0)(inline-open . 0)) // indent-tabs-mode: nil // End: // vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4