////////////////////////////////////////////////////////////////////////////////// // File : spin_lock.c // Date : 01/04/2012 // Author : alain greiner // Copyright (c) UPMC-LIP6 /////////////////////////////////////////////////////////////////////////////////// // The spin_lock.c and spin_lock.h files are part of the GIET nano-kernel. // This middlewre implements a user-level lock (busy waiting mechanism, // because the GIET does not support task scheduling / descheduling). // It is a simple binary lock, without waiting queue. // // The lock_acquire() and lock_release() functions do not require a system call. // The barrier itself must have been allocated in a non cacheable segment, // if the platform does not provide hardwate cache coherence. // // ALL locks must be defined in the mapping_info data structure, // to be initialised by the GIET in the boot phase. // The vobj_get_vbase() system call (defined in stdio.c and stdio.h files) // can be used to get the virtual base address of the lock fro it's name. /////////////////////////////////////////////////////////////////////////////////// #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