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

Last change on this file since 241 was 228, checked in by meunier, 12 years ago

Added support for memspaces and const.
Added an interrupt masking to the "giet_context_switch" syscall
Corrected two bugs in boot/boot_init.c (one minor and one regarding barriers initialization)
Reformatted the code in all files.

File size: 3.1 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() 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.
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)
19// can be used to get the virtual base address of the lock fro it's name.
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///////////////////////////////////////////////////////////////////////////////////
30void lock_acquire(giet_lock_t * lock) {
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//////////////////////////////////////////////////////////////////////////////
60// lock_release()
61//////////////////////////////////////////////////////////////////////////////
62void lock_release(giet_lock_t * lock) {
63    lock->value = 0;
64}
65
66
67// Local Variables:
68// tab-width: 4
69// c-basic-offset: 4
70// c-file-offsets:((innamespace . 0)(inline-open . 0))
71// indent-tabs-mode: nil
72// End:
73// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
74
Note: See TracBrowser for help on using the repository browser.