/////////////////////////////////////////////////////////////////////////////////// // File : locks.c // Date : 01/12/2014 // Author : alain greiner // Copyright (c) UPMC-LIP6 /////////////////////////////////////////////////////////////////////////////////// #include "locks.h" #include "giet_config.h" #include "utils.h" /////////////////////////////////////////////////// unsigned int _atomic_increment( unsigned int* ptr, unsigned int increment ) { unsigned int value; asm volatile ( "1234: \n" "move $10, %1 \n" /* $10 <= ptr */ "move $11, %2 \n" /* $11 <= increment */ "ll $12, 0($10) \n" /* $12 <= *ptr */ "addu $13, $11, $12 \n" /* $13 <= *ptr + increment */ "sc $13, 0($10) \n" /* M[ptr] <= new */ "beqz $13, 1234b \n" /* retry if failure */ "move %0, $12 \n" /* value <= *ptr if success */ : "=r" (value) : "r" (ptr), "r" (increment) : "$10", "$11", "$12", "$13", "memory" ); return value; } //////////////////////////////////// void _lock_init( spin_lock_t* lock ) { lock->current = 0; lock->free = 0; #if GIET_DEBUG_SYS_LOCK unsigned int gpid = _get_procid(); unsigned int x = gpid >> (Y_WIDTH + P_WIDTH); unsigned int y = (gpid >> P_WIDTH) & ((1<current, lock->free ); #endif } //////////////////////////////////////// void _lock_acquire( spin_lock_t* lock ) { // get next free slot index fromlock unsigned int ticket = _atomic_increment( &lock->free, 1 ); #if GIET_DEBUG_SYS_LOCK unsigned int gpid = _get_procid(); unsigned int x = gpid >> (Y_WIDTH + P_WIDTH); unsigned int y = (gpid >> P_WIDTH) & ((1<current, lock->free ); #endif // poll the spin_lock current slot index asm volatile("5678: \n" "lw $10, 0(%0) \n" "move $11, %1 \n" "bne $10, $11, 5678b \n" : : "r"(lock), "r"(ticket) : "$10", "$11" ); #if GIET_DEBUG_SYS_LOCK _printf("\n[SYS_LOCK DEBUG] P[%d,%d,%d] get lock = %x" " at cycle %d (current = %d / free = %d)\n", x, y, l, (unsigned int)lock, _get_proctime(), lock->current, lock->free ); #endif } //////////////////////////////////////// void _lock_release( spin_lock_t* lock ) { unsigned int current = lock->current; if ( current == (GIET_LOCK_MAX_TICKET - 1) ) current = 0; else current = current + 1; asm volatile ( "sync \n" /* for consistency */ "sw %1, 0(%0) \n" /* release lock */ : : "r"(lock), "r"(current) : "memory" ); #if GIET_DEBUG_SYS_LOCK unsigned int gpid = _get_procid(); unsigned int x = gpid >> (Y_WIDTH + P_WIDTH); unsigned int y = (gpid >> P_WIDTH) & ((1<current, lock->free ); #endif } //////////////////////////////////////////////// void _simple_lock_acquire( simple_lock_t* lock ) { asm volatile ( "1515: \n" "lw $2, 0(%0) \n" /* $2 <= lock current value */ "bnez $2, 1515b \n" /* retry if lock already taken */ "ll $2, 0(%0) \n" /* ll_buffer <= lock current value */ "bnez $2, 1515b \n" /* retry if lock already taken */ "li $3, 1 \n" /* $3 <= argument for sc */ "sc $3, 0(%0) \n" /* try to set lock */ "beqz $3, 1515b \n" /* retry if sc failure */ : : "r"(lock) : "$2", "$3", "memory" ); } //////////////////////////////////////////////// void _simple_lock_release( simple_lock_t* lock ) { asm volatile ( "sync \n" /* for consistency */ "sw $0, 0(%0) \n" /* release lock */ : : "r"(lock) : "memory" ); } // 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