source: soft/giet_vm/giet_libs/spin_lock.c @ 276

Last change on this file since 276 was 266, checked in by cfuguet, 11 years ago

Bugfix in spin_lock library:

  • Compute the delay cycles before the assembler code because some registers were erased during the function call.
  • Property svn:executable set to *
File size: 3.2 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    unsigned int delay = giet_rand();
33
34    if (delay == 0) delay++;
35
36    asm volatile (
37            "giet_lock_try:              \n"
38            "ll   $2,    0(%0)           \n" /* $2 <= _ioc_lock current value */
39            "bnez $2,    giet_lock_delay \n" /* delay if _ioc_lock already taken */
40            "li   $3,    1               \n" /* $3 <= argument for sc */
41            "sc   $3,    0(%0)           \n" /* try to set _ioc_lock */
42            "bnez $3,    giet_lock_ok    \n" /* exit if atomic */
43
44            "giet_lock_delay:            \n"
45            "move $4,    %1              \n" /* $4 <= delay */
46
47            "giet_lock_loop:             \n"
48            "addi $4,    $4,    -1       \n" /* $4 <= $4 - 1 */
49            "bnez $4,    giet_lock_loop  \n" /* test end delay */
50            "nop                         \n"
51            "j           giet_lock_try   \n" /* retry */
52            "nop                         \n"
53
54            "giet_lock_ok:               \n"
55            :
56            :"r"(plock), "r"(delay)
57            :"$2", "$3", "$4");
58}
59
60
61//////////////////////////////////////////////////////////////////////////////
62// lock_release()
63//////////////////////////////////////////////////////////////////////////////
64void lock_release(giet_lock_t * lock) {
65    unsigned int * plock = &lock->value;
66
67    asm volatile ( "sync\n" ); // necessary because of the TSAR consistency model
68    *plock = 0;
69}
70
71
72// Local Variables:
73// tab-width: 4
74// c-basic-offset: 4
75// c-file-offsets:((innamespace . 0)(inline-open . 0))
76// indent-tabs-mode: nil
77// End:
78// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
79
Note: See TracBrowser for help on using the repository browser.