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

Last change on this file since 238 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.6 KB
RevLine 
[158]1//////////////////////////////////////////////////////////////////////////////////
2// File     : barrier.c     
3// Date     : 01/04/2012
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
[160]7// These barrier.c and barrier.h files are part of the GIET nano-kernel.
[158]8// This user-level library provides a synchronisation service between several
9// tasks sharing the same address space in a parallel multi-tasks application.
[160]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.
[158]12///////////////////////////////////////////////////////////////////////////////////
13
[165]14#include "barrier.h"
15
[158]16///////////////////////////////////////////////////////////////////////////////////
[228]17//     barrier_init()
[158]18// This function makes a cooperative initialisation of the barrier:
19// several tasks try to initialize the barrier, but the initialisation
20// is done by only one task, using LL/SC instructions.
21///////////////////////////////////////////////////////////////////////////////////
[228]22void barrier_init( giet_barrier_t * barrier, unsigned int value) {
23    unsigned int * pinit  = (unsigned int *) &barrier->init;
24    unsigned int * pcount = (unsigned int *) &barrier->count;
[158]25
26    // parallel initialisation using atomic instructions LL/SC
27    // inputs : pinit, pcount, value
28    // no output
29    asm volatile ("_barrier_init_test:                  \n"
[228]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            :
39            : "r"(pinit), "r"(pcount), "r"(value)
40            : "$2", "$3");
[158]41}
[228]42
43
[158]44///////////////////////////////////////////////////////////////////////////////////
[228]45//    barrier_wait()
[158]46// This blocking function uses LL/SC to decrement the barrier's counter.
47// Then, it uses a busy_waiting mechanism if it is not the last.
48// (because the GIET does not support dynamic task scheduling/descheduling)
49///////////////////////////////////////////////////////////////////////////////////
[228]50void barrier_wait(giet_barrier_t * barrier) {
51    unsigned int * pcount  = (unsigned int *) &barrier->count;
[158]52    unsigned int maxcount = barrier->init;
53    unsigned int count;
54
55    // parallel decrement barrier counter using atomic instructions LL/SC
56    // - input : pointer on the barrier counter
57    // - output : counter value
58    asm volatile ("_barrier_decrement:          \n"
[228]59            "ll   %0, 0(%1)               \n"
60            "addi $3, %0,     -1          \n"
61            "sc   $3, 0(%1)               \n"
62            "beqz $3, _barrier_decrement  \n"
63            : "=&r"(count)
64            : "r"(pcount)
65            : "$2", "$3");
[158]66
67    // the last task re-initializes the barrier counter to the max value,
68    // waking up all other waiting tasks
69
[228]70    if (count == 1) {
71        // last task
[158]72        *pcount = maxcount;
73    }
[228]74    else {
75        // other tasks busy-wait
[158]76        while (*pcount != maxcount) asm volatile ("nop");
77    }
78}
79
[228]80// Local Variables:
81// tab-width: 4
82// c-basic-offset: 4
83// c-file-offsets:((innamespace . 0)(inline-open . 0))
84// indent-tabs-mode: nil
85// End:
86// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
87
Note: See TracBrowser for help on using the repository browser.