Changeset 450 for soft/giet_vm/giet_libs/mwmr_channel.c
- Timestamp:
- Nov 11, 2014, 4:18:38 PM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
soft/giet_vm/giet_libs/mwmr_channel.c
r345 r450 1 1 ////////////////////////////////////////////////////////////////////////////////// 2 // File : mwmr_channel _.c2 // File : mwmr_channel.c 3 3 // Date : 01/04/2012 4 4 // Author : alain greiner 5 5 // Copyright (c) UPMC-LIP6 6 6 /////////////////////////////////////////////////////////////////////////////////// 7 // The mwmr_channel.c and mwmr_channel.h files are part of the GIET nano-kernel.8 // This middleware implements a user level Multi-Writers / Multi-Readers9 // communication channel, that can be used by parallel multi-tasks applications10 // respecting the TCG (Tasks and Communications Graph) formalism.11 //12 // The mwmr_read() and mwmr_write() functions do not require a system call.13 // The channel itself must have been allocated in a non cacheable segment,14 // if the platform does not provide hardware cache coherence.15 //16 // ALL MWMR channels 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 channel from it's name.20 //21 // An MWMR transaction transfer an integer number of items, and an item is22 // an integer number of unsigned int (32 bits words).23 // The max number of words that can be stored in a MWMR channel is defined by the24 // "depth" parameter, and the "width" parameter define the minimal number of25 // word contained in an atomic item. Therefore, the "depth" parameter must be26 // a multiple of the "width" parameter.27 //28 // Both the mwmr_read() and mwmr_write() functions are blocking functions.29 // A private lock provides exclusive access to the MWMR channel, that can have30 // a variable number of producers and a variable number of consumers.31 ///////////////////////////////////////////////////////////////////////////////////32 7 33 8 #include <mwmr_channel.h> 34 9 #include <stdio.h> 35 10 36 ////////////////////////////////////////////////////////////////////////////// 37 // mwmr_lock_aquire() 38 // This blocking function returns only when the lock has been taken. 39 // If the lock is already taken a fixed delay is introduced before retry. 40 ////////////////////////////////////////////////////////////////////////////// 41 void mwmr_lock_acquire(unsigned int * lock_address) { 42 register unsigned int * plock = lock_address; 43 register unsigned int delay = 100; 11 ////////////////////////////////////// 12 void mwmr_init( mwmr_channel_t* mwmr, 13 unsigned int width, // numer of words per item 14 unsigned int items ) // max number of items 15 { 16 if ( ((items * width)) > 1018 ) 17 giet_exit("[MWMR ERROR] in mwmr_init() : buffer size larger than 4072 bytes\n"); 18 19 mwmr->ptw = 0; 20 mwmr->ptr = 0; 21 mwmr->sts = 0; 22 mwmr->width = width; 23 mwmr->depth = width * items; 24 mwmr->lock = 0; 25 26 #if GIET_DEBUG_MWMR 27 giet_shr_printf("[MWMR DEBUG] Initialise MWMR channel\n" 28 " - vbase = %x\n" 29 " - width = %d\n" 30 " - depth = %d\n", 31 (unsigned int)mwmr, width, items ); 32 #endif 33 } 34 35 36 /////////////////////////////////////////////////// 37 static void mwmr_lock_acquire( unsigned int* lock ) 38 { 39 register unsigned int* plock = lock; 40 register unsigned int delay = 100; 44 41 asm volatile ( 45 42 "1: \n" … … 63 60 64 61 65 ////////////////////////////////////////////////////////////////////////////// 66 // nb_mwmr_write() 67 // This is a non-blocking function. 68 // The nitems parameter is the number of items to be transfered. 69 // The requested transfer is therefore (nitems * width) words. 70 // It takes the lock for exclusive access before testing the channel state. 71 // If there is not enough data in mwmr channel to read nitems, 72 // it reads as many items as possible, releases the lock, and returns 73 // the number of read items (it can be 0). 74 ////////////////////////////////////////////////////////////////////////////// 75 unsigned int nb_mwmr_write(mwmr_channel_t * mwmr, unsigned int * buffer, unsigned int nitems) { 62 /////////////////////////////////////////////////// 63 unsigned int nb_mwmr_write( mwmr_channel_t * mwmr, 64 unsigned int * buffer, 65 unsigned int nitems) 66 { 76 67 unsigned int x; 77 68 unsigned int spaces; // number of empty slots (in words) … … 82 73 unsigned int ptw; // channel ptw 83 74 84 if (nitems == 0) { 85 return 0; 86 } 75 if (nitems == 0) return 0; 87 76 88 77 // get the lock … … 97 86 nwords = width * nitems; 98 87 99 if (spaces >= nwords) { // transfer nitems, release lock and return 100 for (x = 0; x < nwords; x++) { 88 if (spaces >= nwords) // transfer nitems, release lock and return 89 { 90 for (x = 0; x < nwords; x++) 91 { 101 92 mwmr->data[ptw] = buffer[x]; 102 if ((ptw + 1) == depth) { 103 ptw = 0; 104 } 105 else { 106 ptw = ptw + 1; 107 } 93 if ((ptw + 1) == depth) ptw = 0; 94 else ptw = ptw + 1; 108 95 } 109 96 mwmr->sts = mwmr->sts + nwords; … … 112 99 return nitems; 113 100 } 114 else if (spaces < width) {115 // release lock and return101 else if (spaces < width) // release lock and return 102 { 116 103 mwmr->lock = 0; 117 104 return 0; 118 105 } 119 else {120 // transfer as many items as possible, release lock and return106 else // transfer as many items as possible, release lock and return 107 { 121 108 nwords = (spaces / width) * width; // integer number of items 122 for (x = 0; x < nwords; x++) { 109 for (x = 0; x < nwords; x++) 110 { 123 111 mwmr->data[ptw] = buffer[x]; 124 if ((ptw + 1) == depth) { 125 ptw = 0; 126 } 127 else { 128 ptw = ptw + 1; 129 } 112 if ((ptw + 1) == depth) ptw = 0; 113 else ptw = ptw + 1; 130 114 } 131 115 mwmr->sts = sts + nwords; … … 137 121 138 122 139 ////////////////////////////////////////////////////////////////////////////// 140 // mwmr_write() 141 // This blocking function returns only when the transfer is completed. 142 // The nitems parameter is the number of items to be transfered. 143 // The requested transfer is therefore (nitems * width) words. 144 // It takes the lock for exclusive access before testing the channel state. 145 // If there is not enough space in mwmr channel to write nitems, 146 // it writes as many items as possible, releases the lock, and retry 147 // after a random delay. 148 ////////////////////////////////////////////////////////////////////////////// 149 void mwmr_write(mwmr_channel_t * mwmr, unsigned int * buffer, unsigned int nitems) { 123 124 ////////////////////////////////////////////////// 125 unsigned int nb_mwmr_read( mwmr_channel_t * mwmr, 126 unsigned int * buffer, 127 unsigned int nitems) 128 { 129 unsigned int x; 130 unsigned int nwords; // requested transfer length (in words) 131 unsigned int depth; // channel depth (in words) 132 unsigned int width; // channel width (in words) 133 unsigned int sts; // channel sts 134 unsigned int ptr; // channel ptr 135 136 if (nitems == 0) return 0; 137 138 // get the lock 139 mwmr_lock_acquire(&mwmr->lock); 140 141 // access fifo status 142 depth = mwmr->depth; 143 width = mwmr->width; 144 sts = mwmr->sts; 145 ptr = mwmr->ptr; 146 nwords = width * nitems; 147 148 if (sts >= nwords) // transfer nitems, release lock and return 149 { 150 for (x = 0; x < nwords; x++) 151 { 152 buffer[x] = mwmr->data[ptr]; 153 if ((ptr + 1) == depth) ptr = 0; 154 else ptr = ptr + 1; 155 } 156 mwmr->sts = mwmr->sts - nwords; 157 mwmr->ptr = ptr; 158 mwmr->lock = 0; 159 return nitems; 160 } 161 else if (sts < width) // release lock and return 162 { 163 mwmr->lock = 0; 164 return 0; 165 } 166 else // transfer as many items as possible, release lock and return 167 { 168 nwords = (sts / width) * width; // integer number of items 169 for (x = 0 ; x < nwords ; x++) 170 { 171 buffer[x] = mwmr->data[ptr]; 172 if ((ptr + 1) == depth) ptr = 0; 173 else ptr = ptr + 1; 174 } 175 mwmr->sts = sts - nwords; 176 mwmr->ptr = ptr; 177 mwmr->lock = 0; 178 return (nwords / width); 179 } 180 } // nb_mwmr_read() 181 182 183 184 //////////////////////////////////////// 185 void mwmr_write( mwmr_channel_t * mwmr, 186 unsigned int * buffer, 187 unsigned int nitems ) 188 { 150 189 unsigned int x; 151 190 unsigned int spaces; // number of empty slots (in words) … … 156 195 unsigned int ptw; // channel ptw 157 196 158 if (nitems == 0) { 159 return; 160 } 161 162 while (1) { 197 if (nitems == 0) return; 198 199 while (1) 200 { 163 201 // get the lock 164 202 mwmr_lock_acquire(&mwmr->lock); … … 172 210 nwords = width * nitems; 173 211 174 if (spaces >= nwords) { 175 // write nwords, release lock and return 176 for (x = 0; x < nwords; x++) { 212 if (spaces >= nwords) // write nwords, release lock and return 213 { 214 for (x = 0; x < nwords; x++) 215 { 177 216 mwmr->data[ptw] = buffer[x]; 178 if ((ptw + 1) == depth) { 179 ptw = 0; 180 } 181 else { 182 ptw = ptw + 1; 183 } 217 if ((ptw + 1) == depth) ptw = 0; 218 else ptw = ptw + 1; 184 219 } 185 220 mwmr->ptw = ptw; … … 188 223 return; 189 224 } 190 else if (spaces < width) {191 // release lock and retry after delay192 mwmr->lock = 0; 193 } 194 else {195 // write as many items as possible, release lock and retry after delay225 else if (spaces < width) // release lock and deschedule 226 { 227 mwmr->lock = 0; 228 } 229 else // write as many items as possible, release lock and deschedule 230 { 196 231 nwords = (spaces / width) * width; // integer number of items 197 for (x = 0; x < nwords; x++) { 232 for (x = 0; x < nwords; x++) 233 { 198 234 mwmr->data[ptw] = buffer[x]; 199 if ((ptw + 1) == depth) { 200 ptw = 0; 201 } 202 else { 203 ptw = ptw + 1; 204 } 235 if ((ptw + 1) == depth) ptw = 0; 236 else ptw = ptw + 1; 205 237 } 206 238 mwmr->sts = sts + nwords; … … 215 247 216 248 217 ////////////////////////////////////////////////////////////////////////////// 218 // nb_mwmr_read() 219 // This is a non-blocking function. 220 // The nitems parameter is the number of items to be transfered. 221 // The requested transfer is therefore (nitems * width) words. 222 // It takes the lock for exclusive access before testing the channel state. 223 // If there is not enough data in mwmr channel to read nitems, 224 // it reads as many items as possible, releases the lock, and returns 225 // the number of read items (it can be 0). 226 ////////////////////////////////////////////////////////////////////////////// 227 unsigned int nb_mwmr_read(mwmr_channel_t * mwmr, unsigned int * buffer, unsigned int nitems) { 249 ////////////////////////////////////// 250 void mwmr_read( mwmr_channel_t * mwmr, 251 unsigned int * buffer, 252 unsigned int nitems) 253 { 228 254 unsigned int x; 229 255 unsigned int nwords; // requested transfer length (in words) … … 233 259 unsigned int ptr; // channel ptr 234 260 235 if (nitems == 0) { 236 return 0; 237 } 238 239 // get the lock 240 mwmr_lock_acquire(&mwmr->lock); 241 242 // access fifo status 243 depth = mwmr->depth; 244 width = mwmr->width; 245 sts = mwmr->sts; 246 ptr = mwmr->ptr; 247 nwords = width * nitems; 248 249 if (sts >= nwords) { 250 // transfer nitems, release lock and return 251 for (x = 0; x < nwords; x++) { 252 buffer[x] = mwmr->data[ptr]; 253 if ((ptr + 1) == depth) { 254 ptr = 0; 255 } 256 else { 257 ptr = ptr + 1; 258 } 259 } 260 mwmr->sts = mwmr->sts - nwords; 261 mwmr->ptr = ptr; 262 mwmr->lock = 0; 263 return nitems; 264 } 265 else if (sts < width) { 266 // release lock and return 267 mwmr->lock = 0; 268 return 0; 269 } 270 else { 271 // transfer as many items as possible, release lock and return 272 nwords = (sts / width) * width; // integer number of items 273 for (x = 0 ; x < nwords ; x++) { 274 buffer[x] = mwmr->data[ptr]; 275 if ((ptr + 1) == depth) { 276 ptr = 0; 277 } 278 else { 279 ptr = ptr + 1; 280 } 281 } 282 mwmr->sts = sts - nwords; 283 mwmr->ptr = ptr; 284 mwmr->lock = 0; 285 return (nwords / width); 286 } 287 } // nb_mwmr_read() 288 289 290 ////////////////////////////////////////////////////////////////////////////// 291 // mwmr_read() 292 // This blocking function returns only when the transfer is completed. 293 // The nitems parameter is the number of items to be transfered. 294 // The requested transfer is therefore (nitems * width) words. 295 // It takes the lock for exclusive access before testing the channel state. 296 // If there is not enough data in mwmr channel to read nitems, 297 // it reads as many items as possible, releases the lock, and retry 298 // after a random delay. 299 ////////////////////////////////////////////////////////////////////////////// 300 void mwmr_read( mwmr_channel_t * mwmr, unsigned int * buffer, unsigned int nitems) { 301 unsigned int x; 302 unsigned int nwords; // requested transfer length (in words) 303 unsigned int depth; // channel depth (in words) 304 unsigned int width; // channel width (in words) 305 unsigned int sts; // channel sts 306 unsigned int ptr; // channel ptr 307 308 if (nitems == 0) { 309 return; 310 } 311 312 while (1) { 261 if (nitems == 0) return; 262 263 while (1) 264 { 313 265 // get the lock 314 266 mwmr_lock_acquire(&mwmr->lock); … … 321 273 nwords = width * nitems; 322 274 323 if (sts >= nwords) { 324 // read nwords, release lock and return 325 for (x = 0; x < nwords; x++) { 275 if (sts >= nwords) // read nwords, release lock and return 276 { 277 for (x = 0; x < nwords; x++) 278 { 326 279 buffer[x] = mwmr->data[ptr]; 327 if ((ptr + 1) == depth) { 328 ptr = 0; 329 } 330 else { 331 ptr = ptr + 1; 332 } 280 if ((ptr + 1) == depth) ptr = 0; 281 else ptr = ptr + 1; 333 282 } 334 283 mwmr->sts = mwmr->sts - nwords; … … 337 286 return; 338 287 } 339 else if (sts < width) { 340 // release lock and retry after delay 341 mwmr->lock = 0; 342 } 343 else { // read as many items as possible, release lock and retry after delay 288 else if (sts < width) // release lock and deschedule 289 { 290 mwmr->lock = 0; 291 } 292 else // read as many items as possible, release lock and deschedule 293 { 344 294 nwords = (sts / width) * width; // integer number of items 345 for (x = 0; x < nwords; x++) { 295 for (x = 0; x < nwords; x++) 296 { 346 297 buffer[x] = mwmr->data[ptr]; 347 if ((ptr + 1) == depth) { 348 ptr = 0; 349 } 350 else { 351 ptr = ptr + 1; 352 } 298 if ((ptr + 1) == depth) ptr = 0; 299 else ptr = ptr + 1; 353 300 } 354 301 mwmr->sts = sts - nwords;
Note: See TracChangeset
for help on using the changeset viewer.