source: soft/giet_vm/libs/barrier.c @ 159

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

Introducing the spin_locks / modifying the MWMR channels and the barriers

File size: 3.8 KB
Line 
1//////////////////////////////////////////////////////////////////////////////////
2// File     : barrier.c     
3// Date     : 01/04/2012
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7// The barrier.c and barrier.h files are part of the GIET nano-kernel.
8// This user-level library provides a synchronisation service between several
9// tasks sharing the same address space in a parallel multi-tasks application.
10//
11// The barrier_init(), and the barrier_wait() functions do not require a syscall.
12// The barrier itself must have been allocated in a non cacheable segment,
13// if the platform does not provide hardwate cache coherence.
14//
15// ALL barriers 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 barrier from it's name.
19///////////////////////////////////////////////////////////////////////////////////
20
21#include <barrier.h>
22
23///////////////////////////////////////////////////////////////////////////////////
24//      barrier_init()
25// This function makes a cooperative initialisation of the barrier:
26// several tasks try to initialize the barrier, but the initialisation
27// is done by only one task, using LL/SC instructions.
28///////////////////////////////////////////////////////////////////////////////////
29void barrier_init( giet_barrier_t*      barrier, 
30                   unsigned int         value )
31{
32    unsigned int* pinit  = (unsigned int*)&barrier->init;
33    unsigned int* pcount = (unsigned int*)&barrier->count;
34
35    // parallel initialisation using atomic instructions LL/SC
36    // inputs : pinit, pcount, value
37    // no output
38    asm volatile ("_barrier_init_test:                  \n"
39                  "ll   $2,     0(%0)                   \n" /* read initial value */
40                  "bnez $2,     _barrier_init_done      \n"
41                  "move $3,     %2                      \n"
42                  "sc   $3,     0(%0)                   \n" /* write initial value */
43                  "beqz $3,     _barrier_init_test      \n"
44                  "move $3,     %2                      \n"
45                  "sw   $3,     0(%1)                   \n" /* write count */
46                  "_barrier_init_done:                  \n"
47                  :: "r"(pinit), "r"(pcount), "r"(value)
48                  : "$2", "$3");
49}
50///////////////////////////////////////////////////////////////////////////////////
51//      barrier_wait()
52// This blocking function uses LL/SC to decrement the barrier's counter.
53// Then, it uses a busy_waiting mechanism if it is not the last.
54// (because the GIET does not support dynamic task scheduling/descheduling)
55///////////////////////////////////////////////////////////////////////////////////
56void barrier_wait( giet_barrier_t* barrier )
57{
58    unsigned int* pcount  = (unsigned int*)&barrier->count;
59    unsigned int maxcount = barrier->init;
60    unsigned int count;
61
62    // parallel decrement barrier counter using atomic instructions LL/SC
63    // - input : pointer on the barrier counter
64    // - output : counter value
65    asm volatile ("_barrier_decrement:          \n"
66                  "ll   %0, 0(%1)               \n"
67                  "addi $3, %0,     -1          \n"
68                  "sc   $3, 0(%1)               \n"
69                  "beqz $3, _barrier_decrement  \n"
70                  : "=&r"(count)
71                  : "r"(pcount)
72                  : "$2", "$3");
73
74    // the last task re-initializes the barrier counter to the max value,
75    // waking up all other waiting tasks
76
77    if (count == 1)             // last task
78    {
79        *pcount = maxcount;
80    }
81    else                        // other tasks busy-wait
82    {
83        while (*pcount != maxcount) asm volatile ("nop");
84    }
85}
86
Note: See TracBrowser for help on using the repository browser.