source: soft/giet_vm/libs/spin_lock.c @ 178

Last change on this file since 178 was 178, checked in by karaoui, 12 years ago

updating libs.

File size: 3.4 KB
Line 
1//////////////////////////////////////////////////////////////////////////////////
2// File     : spin_lock.c         
3// Date     : 01/04/2012
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7// The spin_lock.c and spin_lock.h files are part of the GIET nano-kernel.
8// This  middlewre implements a user-level lock (busy waiting mechanism,
9// because the GIET does not support task scheduling / descheduling).
10// It is a simple binary lock, without waiting queue.
11//
12// The lock_acquire(), lock_try_acquire() and lock_release() functions do
13// not require a system call.
14//
15// ALL locks must be defined in the mapping_info data structure,
16// to be initialised by the GIET in the boot phase.
17// The vobj_get_vbase() system call (defined in stdio.c and stdio.h files)
18// can be used to get the virtual base address of the lock from it's name.
19///////////////////////////////////////////////////////////////////////////////////
20
21#include <spin_lock.h>
22#include <stdio.h>
23
24///////////////////////////////////////////////////////////////////////////////////
25// lock_acquire()
26// This blocking function returns only when the lock has been taken.
27// If the lock is already taken a random delay is introduced before retry.
28///////////////////////////////////////////////////////////////////////////////////
29void lock_acquire( giet_lock_t* lock )
30{
31    unsigned int*       plock = &lock->value;
32 
33    asm volatile (
34            "giet_lock_try:                                     \n"
35            "ll   $2,    0(%0)                          \n" /* $2 <= lock current value */
36            "bnez $2,    giet_lock_delay        \n" /* retry if lock already taken */
37            "li   $3,    1                                      \n" /* $3 <= argument for sc */
38            "sc   $3,    0(%0)                          \n" /* try to get lock */
39            "bnez $3,    giet_lock_ok           \n" /* exit if atomic */
40
41            "giet_lock_delay:                           \n"
42            "jal  giet_rand                                 \n" /* giet_rand() system call */
43            "nop                                                        \n"
44            "andi $4,   $2,     0xFF                    \n"     /* $4 <= delay < 256 cycles */
45
46            "giet_lock_loop:                            \n"
47            "addi $4,    $4,  -1                        \n" /* $4 <= $4 - 1 */
48            "beqz $4,    giet_lock_loop         \n" /* test end delay */
49            "nop                                                        \n"
50            "j           giet_lock_try          \n" /* retry */
51            "nop                                                        \n"
52            "giet_lock_ok:                                      \n"
53            :
54            :"r"(plock)
55            :"$2", "$3", "$4");
56} 
57
58//////////////////////////////////////////////////////////////////////////////
59// lock_release()
60//////////////////////////////////////////////////////////////////////////////
61void lock_release( giet_lock_t* lock)
62{
63    lock->value = 0;
64}
65
66//////////////////////////////////////////////////////////////////////////////
67// lock_try_acquire()
68//////////////////////////////////////////////////////////////////////////////
69int lock_try_acquire( giet_lock_t* lock )
70{
71        register int ret = 0;   
72    register unsigned int*      plock = &lock->value;
73
74        asm volatile ("ll   $2,    0(%1)                    \n" // $2 <= _locks_lock
75                  "bnez $2,    _lock_done           \n" // exitif busy
76                  "li   $3,    1                            \n" // prepare argument for sc 
77                  "sc   $3,    0(%1)                \n" // try to set _locks_busy
78                  "xori %0, $3, 1                   \n" // ret = !$3
79                  "_lock_done:                          \n"
80                  :"=r"(ret)
81                  :"r"(plock)
82                  :"$2","$3");
83    return ret;
84}
Note: See TracBrowser for help on using the repository browser.