source: soft/giet_vm/libs/mwmr.c @ 160

Last change on this file since 160 was 160, checked in by karaoui, 12 years ago

giet-vm new version

File size: 7.6 KB
Line 
1//////////////////////////////////////////////////////////////////////////////////
2// File     : mwmr.c         
3// Date     : 01/04/2012
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7// The mwmr.c and mwmr.h files are part of the GIET nano-kernel.
8// This  middlewre implements a user level Multi-Writers / Multi-Readers
9// communication channel, that can be sued by parallel multi-tasks applications
10// respecting the TCG (Tasks and Communications Graph) formalism.
11//
12// The mwmr_read() and mwmr_write() functions do not require a system call,
13//
14// The mwmr_get_base() returns the virtual base address of the MWMR channel.
15// As this function requires a system call, it is defined in the stdio.c and
16// stdio.h files.
17//
18// ALL MWMR channels must be defined in the mapping_info data structure,
19// to be initialised by the GIET in the boot phase.
20// The max number of words that can be stored in a MWMR channel is defined by the
21// depth parameter, but all MWMR channels are implemented as fixed size buffers,
22// and the size is defined by the GIET_MWMR_SIZE_MAX configuration parameter.
23// An MWMR transaction is an integer number of unsigned int (32 bits mwords).
24// Both the mwmr_read() and mwmr_write() functions are blocking functions.
25// A private lock provides exclusive access to the MWMR channel, that can have
26// a variable number of producers and a variable number of consumers.
27///////////////////////////////////////////////////////////////////////////////////
28
29#include <mwmr.h>
30#include <stdio.h>
31
32#define MWMR_PART
33//#define MWMR_DEBUG_READ
34//#define MWMR_DEBUG_WRITE
35
36///////////////////////////////////////////////////////////////////////////////////
37//      mwmr_lock_acquire()
38// We use a fixed delay befor retry, in order to avoid the system call
39// associated to the rand() function.
40// This is probably a weakness, that can be improved...
41///////////////////////////////////////////////////////////////////////////////////
42inline void mwmr_lock_acquire(unsigned int* lock)
43{
44    asm volatile (
45            "lock_try:              \n"
46            "ll   $2,    0(%0)      \n" /* $2 <= lock current value */
47            "bnez $2,    lock_delay \n" /* retry if lock already taken */
48            "li   $3,    1          \n" /* $3 <= argument for sc */
49            "sc   $3,    0(%0)      \n" /* try to get lock */
50            "bnez $3,    lock_ok    \n" /* exit if atomic */
51            "lock_delay:            \n"
52            "li   $4,    100        \n" /* $4 <= delay */
53            "lock_loop:             \n"
54            "addi $4,    $4,  -1    \n" /* $4 <= $4 - 1 */
55            "beqz $4,    lock_loop  \n" /* test end delay */
56            "nop                    \n"
57            "j           lock_try   \n" /* retry if not atomic */
58            "nop                    \n"
59            "lock_ok:               \n"
60            :
61            :"r"(lock)
62            :"$2", "$3", "$4");
63} 
64
65inline void print_state( mwmr_channel_t* mwmr)
66{
67
68    tty_printf("PTR %d", mwmr->ptr);
69    tty_printf("/PTW %d", mwmr->ptw);
70    tty_printf("/STS %d", mwmr->sts);
71    tty_printf("/DEPTH %d", mwmr->depth);
72    tty_printf("/LOCK %d\n", mwmr->lock);
73
74}
75
76
77//////////////////////////////////////////////////////////////////////////////
78//      mwmr_write()
79// This blocking function returns only when the transfer is completed.
80// It takes the lock for exclusive access before testing the channel state.
81// If there is not enough space in mwmr channel to write nwords words,
82// it writes as many words as possible, release the lock, and retry after
83// a random delay.
84//////////////////////////////////////////////////////////////////////////////
85void mwmr_write( mwmr_channel_t*        mwmr, 
86                 unsigned int*          buffer,
87                 unsigned int           nwords )
88{
89    unsigned int        x;
90    unsigned int        spaces;
91
92    while(1)
93    {
94        // get the lock
95        mwmr_lock_acquire((unsigned int*)&mwmr->lock);
96#ifdef MWMR_DEBUG_WRITE
97tty_printf("write: lock done\n");
98print_state(mwmr);
99#endif
100
101        // compute number of empty slots
102        spaces = mwmr->depth - mwmr->sts;
103
104        if( spaces >= nwords )  // write nwords, release lock and return
105        {
106            for ( x = 0 ; x < nwords ; x++ ) 
107            {
108                mwmr->data[mwmr->ptw] = buffer[x];
109                mwmr->ptw  = (mwmr->ptw + 1) % mwmr->depth;
110#ifdef MWMR_DEBUG_WRITE
111tty_printf("/PTW %d\n", mwmr->ptw);
112#endif
113            }
114            mwmr->sts  = mwmr->sts + nwords;
115#ifdef MWMR_DEBUG_WRITE
116tty_printf("write done\n");
117print_state(mwmr);
118#endif
119            mwmr->lock = 0;
120            return;
121        }
122        else if ( spaces == 0 ) // release lock and retry after delay
123        {
124            mwmr->lock = 0;
125            for ( x = rand()>>8 ; x > 0 ; x-- ) asm volatile ( "nop" );
126        }
127        else            // write spaces, release lock and retry after delay
128        {
129#ifdef MWMR_PART
130            for ( x = 0 ; x < spaces ; x++ ) 
131            {
132                mwmr->data[mwmr->ptw] = buffer[x];
133                mwmr->ptw  = (mwmr->ptw + 1) % mwmr->depth;
134            }
135            mwmr->sts  = mwmr->depth;
136            nwords     = nwords - spaces;
137            buffer     = buffer + spaces;
138#ifdef MWMR_DEBUG_WRITE
139tty_printf("write part done\n");
140print_state(mwmr);
141#endif
142#endif
143            mwmr->lock = 0;
144        }
145
146        // random delay before retry
147        for ( x = rand()>>6 ; x > 0 ; x-- ) asm volatile ( "nop" );
148    }
149} 
150
151
152//////////////////////////////////////////////////////////////////////////////
153//      mwmr_read()
154// This blocking function returns only when the transfer is completed.
155// It takes the lock for exclusive access before testing the channel state.
156// If there is not enough data in mwmr channel to read nwords words,
157// it reads as many words as possible, release the lock, and retry after
158// a random delay.
159//////////////////////////////////////////////////////////////////////////////
160void mwmr_read( mwmr_channel_t*         mwmr, 
161                unsigned int*           buffer,
162                unsigned int            nwords )
163{
164    unsigned int        x;
165    unsigned int        dispos;
166
167    while(1)
168    {
169        // get the lock
170        mwmr_lock_acquire((unsigned int*)&mwmr->lock);
171
172#ifdef MWMR_DEBUG_READ
173tty_printf("lock done\n");
174print_state(mwmr);
175#endif
176
177        // compute number of available words
178        dispos = mwmr->sts;
179
180        if( dispos >= nwords )  // read nwords, release lock and return
181        {
182            for ( x = 0 ; x < nwords ; x++ ) 
183            {
184                buffer[x] = mwmr->data[mwmr->ptr];
185                mwmr->ptr  = (mwmr->ptr + 1) % mwmr->depth;
186#ifdef MWMR_DEBUG_WRITE
187tty_printf("PTR %d\n", mwmr->ptr);
188#endif
189            }
190            mwmr->sts  = mwmr->sts - nwords;
191#ifdef MWMR_DEBUG_READ
192tty_printf("read done\n");
193print_state(mwmr);
194#endif
195            mwmr->lock = 0;
196            return;
197        }
198        else if ( dispos == 0 ) // release lock and retry after delay
199        {
200            mwmr->lock = 0;
201            for ( x = rand()>>8 ; x > 0 ; x-- ) asm volatile ( "nop" );
202        }
203        else            // read dispos, release lock and retry after delay
204        {
205#ifdef MWMR_PART
206            for ( x = 0 ; x < dispos ; x++ ) 
207            {
208                buffer[x] = mwmr->data[mwmr->ptr];
209                mwmr->ptr  = (mwmr->ptr + 1) % mwmr->depth;
210            }
211            mwmr->sts  = 0;
212            nwords     = nwords - dispos;
213            buffer     = buffer + dispos;
214
215#ifdef MWMR_DEBUG_READ
216tty_printf("read part done\n");
217print_state(mwmr);
218#endif
219
220#endif
221            mwmr->lock = 0;
222        }
223
224        // random delay before retry
225        for ( x = rand()>>6 ; x > 0 ; x-- ) asm volatile ( "nop" );
226    }
227} 
228
Note: See TracBrowser for help on using the repository browser.