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

Last change on this file since 223 was 189, checked in by alain, 12 years ago

Introducing a new release where all initialisation
is done in the boot code.

File size: 2.7 KB
RevLine 
[159]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//
[189]12// The lock_acquire() and lock_release() functions do not require a system call.
13// The barrier itself must have been allocated in a non cacheable segment,
14// if the platform does not provide hardwate cache coherence.
[159]15//
16// ALL locks must be defined in the mapping_info data structure,
17// to be initialised by the GIET in the boot phase.
18// The vobj_get_vbase() system call (defined in stdio.c and stdio.h files)
[189]19// can be used to get the virtual base address of the lock fro it's name.
[159]20///////////////////////////////////////////////////////////////////////////////////
21
22#include <spin_lock.h>
23#include <stdio.h>
24
25///////////////////////////////////////////////////////////////////////////////////
26// lock_acquire()
27// This blocking function returns only when the lock has been taken.
28// If the lock is already taken a random delay is introduced before retry.
29///////////////////////////////////////////////////////////////////////////////////
[165]30void lock_acquire( giet_lock_t* lock )
[159]31{
[165]32    unsigned int*       plock = &lock->value;
[159]33 
34    asm volatile (
35            "giet_lock_try:                                     \n"
36            "ll   $2,    0(%0)                          \n" /* $2 <= lock current value */
37            "bnez $2,    giet_lock_delay        \n" /* retry if lock already taken */
38            "li   $3,    1                                      \n" /* $3 <= argument for sc */
39            "sc   $3,    0(%0)                          \n" /* try to get lock */
40            "bnez $3,    giet_lock_ok           \n" /* exit if atomic */
41
42            "giet_lock_delay:                           \n"
[165]43            "jal  giet_rand                                 \n" /* giet_rand() system call */
[159]44            "nop                                                        \n"
[165]45            "andi $4,   $2,     0xFF                    \n"     /* $4 <= delay < 256 cycles */
[159]46
47            "giet_lock_loop:                            \n"
48            "addi $4,    $4,  -1                        \n" /* $4 <= $4 - 1 */
49            "beqz $4,    giet_lock_loop         \n" /* test end delay */
50            "nop                                                        \n"
51            "j           giet_lock_try          \n" /* retry */
52            "nop                                                        \n"
53            "giet_lock_ok:                                      \n"
54            :
55            :"r"(plock)
56            :"$2", "$3", "$4");
57} 
58
59//////////////////////////////////////////////////////////////////////////////
60// lock_release()
61//////////////////////////////////////////////////////////////////////////////
62void lock_release( giet_lock_t* lock)
63{
64    lock->value = 0;
65}
66
Note: See TracBrowser for help on using the repository browser.