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

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

Introducing the giet_vm and some example applications

File size: 3.5 KB
Line 
1//////////////////////////////////////////////////////////////////////////////////
2// File     : barrier.c     
3// Date     : 01/04/2012
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7// These 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// Neither the barrier_init(), nor the barrier_wait() function require a syscall.
11// The barrier itself must have been allocated in a shared data segment.
12///////////////////////////////////////////////////////////////////////////////////
13
14///////////////////////////////////////////////////////////////////////////////////
15//      barrier_init()
16// This function makes a cooperative initialisation of the barrier:
17// several tasks try to initialize the barrier, but the initialisation
18// is done by only one task, using LL/SC instructions.
19///////////////////////////////////////////////////////////////////////////////////
20void barrier_init( giet_barrier_t*      barrier, 
21                   unsigned int         value )
22{
23    unsigned int* pinit  = (unsigned int*)&barrier->init;
24    unsigned int* pcount = (unsigned int*)&barrier->count;
25
26    // parallel initialisation using atomic instructions LL/SC
27    // inputs : pinit, pcount, value
28    // no output
29    asm volatile ("_barrier_init_test:                  \n"
30                  "ll   $2,     0(%0)                   \n" /* read initial value */
31                  "bnez $2,     _barrier_init_done      \n"
32                  "move $3,     %2                      \n"
33                  "sc   $3,     0(%0)                   \n" /* write initial value */
34                  "beqz $3,     _barrier_init_test      \n"
35                  "move $3,     %2                      \n"
36                  "sw   $3,     0(%1)                   \n" /* write count */
37                  "_barrier_init_done:                  \n"
38                  :: "r"(pinit), "r"(pcount), "r"(value)
39                  : "$2", "$3");
40}
41///////////////////////////////////////////////////////////////////////////////////
42//      barrier_wait()
43// This blocking function uses LL/SC to decrement the barrier's counter.
44// Then, it uses a busy_waiting mechanism if it is not the last.
45// (because the GIET does not support dynamic task scheduling/descheduling)
46///////////////////////////////////////////////////////////////////////////////////
47void barrier_wait( giet_barrier_t* barrier )
48{
49    unsigned int* pcount  = (unsigned int*)&barrier->count;
50    unsigned int maxcount = barrier->init;
51    unsigned int count;
52
53    // parallel decrement barrier counter using atomic instructions LL/SC
54    // - input : pointer on the barrier counter
55    // - output : counter value
56    asm volatile ("_barrier_decrement:          \n"
57                  "ll   %0, 0(%1)               \n"
58                  "addi $3, %0,     -1          \n"
59                  "sc   $3, 0(%1)               \n"
60                  "beqz $3, _barrier_decrement  \n"
61                  : "=&r"(count)
62                  : "r"(pcount)
63                  : "$2", "$3");
64
65    // the last task re-initializes the barrier counter to the max value,
66    // waking up all other waiting tasks
67
68    if (count == 1)             // last task
69    {
70        *pcount = maxcount;
71    }
72    else                        // other tasks busy-wait
73    {
74        while (*pcount != maxcount) asm volatile ("nop");
75    }
76}
77
Note: See TracBrowser for help on using the repository browser.