Changeset 709 for soft/giet_vm/giet_libs/user_lock.c
- Timestamp:
- Oct 1, 2015, 4:20:46 PM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
soft/giet_vm/giet_libs/user_lock.c
r693 r709 9 9 10 10 #include "user_lock.h" 11 #include "malloc.h" 11 12 #include "giet_config.h" 12 13 #include "stdio.h" 13 14 14 15 ////////////////////////////////////////////////////////////////////////////////// 15 // This function uses LL/SC to make an atomic increment.16 // atomic access functions 16 17 ////////////////////////////////////////////////////////////////////////////////// 18 19 ////////////////////////////////////////////////// 17 20 unsigned int atomic_increment( unsigned int* ptr, 18 21 unsigned int increment ) … … 37 40 38 41 /////////////////////////////////////////////////////////////////////////////////// 39 // This blocking function returns only when the lock has been taken. 40 /////////////////////////////////////////////////////////////////////////////////// 42 // simple lock access functions 43 /////////////////////////////////////////////////////////////////////////////////// 44 45 ////////////////////////////////////// 41 46 void lock_acquire( user_lock_t* lock ) 42 47 { … … 49 54 unsigned int lpid; 50 55 giet_proc_xyp( &x, &y, &lpid ); 51 giet_tty_printf("\n[USER_LOCK DEBUG] P[%d,%d,%d] get ticket = %d"56 giet_tty_printf("\n[USER_LOCK DEBUG] lock_acquire() : P[%d,%d,%d] get ticket = %d" 52 57 " for lock %x at cycle %d (current = %d / free = %d)\n", 53 58 x, y, lpid, ticket, … … 65 70 66 71 #if GIET_DEBUG_USER_LOCK 67 giet_tty_printf("\n[USER_LOCK DEBUG] P[%d,%d,%d] get lock %x"72 giet_tty_printf("\n[USER_LOCK DEBUG] lock_acquire() : P[%d,%d,%d] get lock %x" 68 73 " at cycle %d (current = %d / free = %d)\n", 69 74 x, y, lpid, (unsigned int)lock, … … 73 78 } 74 79 75 ////////////////////////////////////////////////////////////////////////////// 76 // This function releases the lock. 77 ////////////////////////////////////////////////////////////////////////////// 80 ////////////////////////////////////// 78 81 void lock_release( user_lock_t* lock ) 79 82 { … … 87 90 unsigned int lpid; 88 91 giet_proc_xyp( &x, &y, &lpid ); 89 giet_tty_printf("\n[USER_LOCK DEBUG] P[%d,%d,%d] release lock %x"92 giet_tty_printf("\n[USER_LOCK DEBUG] lock_release() : P[%d,%d,%d] release lock %x" 90 93 " at cycle %d (current = %d / free = %d)\n", 91 94 x, y, lpid, (unsigned int)lock, … … 95 98 } 96 99 97 ////////////////////////////////////////////////////////////////////////////// 98 // This function initializes the lock. 99 ////////////////////////////////////////////////////////////////////////////// 100 /////////////////////////////////// 100 101 void lock_init( user_lock_t* lock ) 101 102 { … … 108 109 unsigned int lpid; 109 110 giet_proc_xyp( &x, &y, &lpid ); 110 giet_tty_printf("\n[USER_LOCK DEBUG] P[%d,%d,%d] init lock %x"111 giet_tty_printf("\n[USER_LOCK DEBUG] lock_init() : P[%d,%d,%d] init lock %x" 111 112 " at cycle %d (current = %d / free = %d)\n", 112 113 x, y, lpid, (unsigned int)lock, … … 114 115 #endif 115 116 117 } 118 119 /////////////////////////////////////////////////////////////////////////////////// 120 // SQT lock access functions 121 /////////////////////////////////////////////////////////////////////////////////// 122 123 ////////////////////////////////////////////////// 124 static void sqt_lock_build( sqt_lock_t* lock, // pointer on the SQT lock 125 unsigned int x, // node X coordinate 126 unsigned int y, // node Y coordinate 127 unsigned int level, // node level 128 sqt_lock_node_t* parent, // pointer on parent node 129 unsigned int xmax, // SQT X size 130 unsigned int ymax ) // SQT Y size 131 { 132 133 #if GIET_DEBUG_USER_LOCK 134 unsigned int px; 135 unsigned int py; 136 unsigned int pl; 137 giet_proc_xyp( &px, &py, &pl ); 138 #endif 139 140 // get target node pointer 141 sqt_lock_node_t* node = lock->node[x][y][level]; 142 143 if (level == 0 ) // terminal case 144 { 145 // initializes target node 146 node->current = 0; 147 node->free = 0; 148 node->level = 0; 149 node->parent = parent; 150 node->child[0] = NULL; 151 node->child[1] = NULL; 152 node->child[2] = NULL; 153 node->child[3] = NULL; 154 155 #if GIET_DEBUG_USER_LOCK 156 giet_tty_printf("\n[USER_LOCK DEBUG] sqt_lock_build() : " 157 "P[%d,%d,%d] initialises SQT node[%d,%d,%d] = %x :\n" 158 " parent = %x / child0 = %x / child1 = %x / child2 = %x / child3 = %x\n", 159 px , py , pl , x , y , level , (unsigned int)node , 160 (unsigned int)node->parent , 161 (unsigned int)node->child[0] , 162 (unsigned int)node->child[1] , 163 (unsigned int)node->child[2] , 164 (unsigned int)node->child[3] ); 165 #endif 166 167 } 168 else // non terminal case 169 { 170 unsigned int cx[4]; // x coordinate for children 171 unsigned int cy[4]; // y coordinate for children 172 unsigned int i; // child index 173 174 // the child0 coordinates are equal to the parent coordinates 175 // other childs coordinates are incremented depending on the level value 176 cx[0] = x; 177 cy[0] = y; 178 179 cx[1] = x + (1 << (level-1)); 180 cy[1] = y; 181 182 cx[2] = x; 183 cy[2] = y + (1 << (level-1)); 184 185 cx[3] = x + (1 << (level-1)); 186 cy[3] = y + (1 << (level-1)); 187 188 // initializes target node 189 for ( i = 0 ; i < 4 ; i++ ) 190 { 191 if ( (cx[i] < xmax) && (cy[i] < ymax) ) 192 node->child[i] = lock->node[cx[i]][cy[i]][level-1]; 193 else 194 node->child[i] = NULL; 195 } 196 node->current = 0; 197 node->free = 0; 198 node->level = level; 199 node->parent = parent; 200 201 #if GIET_DEBUG_USER_LOCK 202 giet_tty_printf("\n[USER_LOCK DEBUG] sqt_lock_init() : " 203 "P[%d,%d,%d] initialises SQT node[%d,%d,%d] : \n" 204 " parent = %x / childO = %x / child1 = %x / child2 = %x / child3 = %x\n", 205 px , py , pl , x , y , level , 206 (unsigned int)node->parent , 207 (unsigned int)node->child[0] , 208 (unsigned int)node->child[1] , 209 (unsigned int)node->child[2] , 210 (unsigned int)node->child[3] ); 211 #endif 212 213 // recursive calls for children nodes 214 for ( i = 0 ; i < 4 ; i++ ) 215 { 216 if ( (cx[i] < xmax) && (cy[i] < ymax) ) 217 sqt_lock_build( lock, 218 cx[i], 219 cy[i], 220 level-1, 221 node, 222 xmax, 223 ymax ); 224 } 225 } 226 } // end _sqt_lock_build() 227 228 229 230 ////////////////////////////////////// 231 void sqt_lock_init( sqt_lock_t* lock, 232 unsigned int x_size, // number of clusters in a row 233 unsigned int y_size, // number of clusters in a col 234 unsigned int nthreads ) // threads per clusters 235 { 236 // check parameters 237 if ( x_size > 16 ) giet_pthread_exit("SQT LOCK ERROR : x_size too large"); 238 if ( y_size > 16 ) giet_pthread_exit("SQT LOCK ERROR : y_size too large"); 239 if ( nthreads > 8 ) giet_pthread_exit("SQT LOCK ERROR : nthreads too large"); 240 241 // compute SQT levels 242 unsigned int levels; 243 unsigned int z = (x_size > y_size) ? x_size : y_size; 244 levels = (z < 2) ? 1 : (z < 3) ? 2 : (z < 5) ? 3 : (z < 9) ? 4 : 5; 245 246 #if GIET_DEBUG_USER_LOCK 247 unsigned int px; 248 unsigned int py; 249 unsigned int pp; 250 giet_proc_xyp(&px, &py, &pp); 251 unsigned int side = (z < 2) ? 1 : (z < 3) ? 2 : (z < 5) ? 4 : (z < 9) ? 8 : 16; 252 giet_tty_printf("\n[USER_LOCK DEBUG] sqt_lock_init() : " 253 "P[%d,%d%d] makes sqt_nodes allocation for lock %x\n" 254 " x_size = %d / y_size = %d / levels = %d / side = %d\n", 255 px, py, pp, (unsigned int) lock, x_size , y_size , levels , side ); 256 #endif 257 258 259 unsigned int x; // x coordinate for one SQT node 260 unsigned int y; // y coordinate for one SQT node 261 unsigned int l; // level for one SQT node 262 263 for ( x = 0 ; x < x_size ; x++ ) 264 { 265 for ( y = 0 ; y < y_size ; y++ ) 266 { 267 for ( l = 0 ; l < levels ; l++ ) // level 0 nodes 268 { 269 270 if ( ( (l == 0) && ((x&0x00) == 0) && ((y&0x00) == 0) ) || 271 ( (l == 1) && ((x&0x01) == 0) && ((y&0x01) == 0) ) || 272 ( (l == 2) && ((x&0x03) == 0) && ((y&0x03) == 0) ) || 273 ( (l == 3) && ((x&0x07) == 0) && ((y&0x07) == 0) ) || 274 ( (l == 4) && ((x&0x0F) == 0) && ((y&0x0F) == 0) ) ) 275 { 276 lock->node[x][y][l] = 277 (sqt_lock_node_t*)remote_malloc( sizeof(sqt_lock_node_t), 278 x, y ); 279 280 #if GIET_DEBUG_USER_LOCK 281 giet_tty_printf("\n[USER_LOCK DEBUG] squt_lock_init() : " 282 "P[%d,%d,%d] allocates SQT node[%d,%d,%d] = %x\n", 283 px , py , pp , x , y , l , (unsigned int)lock->node[x][y][l] ); 284 #endif 285 } 286 } 287 } 288 } 289 290 // recursively initialize all SQT nodes from root to bottom 291 sqt_lock_build( lock, 292 0, 293 0, 294 levels-1, 295 NULL, 296 x_size, 297 y_size ); 298 299 asm volatile ("sync" ::: "memory"); 300 301 #if GIET_DEBUG_USER_LOCK 302 giet_tty_printf("\n[USER_LOCK DEBUG] sqt_lock_init() : " 303 "P[%d,%d,%d] completes SQT nodes initialisation\n", px, py, pp); 304 #endif 305 306 } // end sqt_lock_init() 307 308 309 ////////////////////////////////////////////////// 310 static void sqt_lock_take( sqt_lock_node_t* node ) 311 { 312 // get next free ticket from local lock 313 unsigned int ticket = atomic_increment( &node->free, 1 ); 314 315 #if GIET_DEBUG_USER_LOCK 316 unsigned int x; 317 unsigned int y; 318 unsigned int l; 319 giet_proc_xyp(&x, &y, &l); 320 giet_tty_printf("\n[USER_LOCK DEBUG] sqt_lock_take() : " 321 "P[%d,%d,%d] get ticket %d for SQT lock %x" 322 " / level = %d / current = %d / free = %d\n", 323 x , y , l , ticket , (unsigned int)node , 324 node->level , node->current , node->free ); 325 #endif 326 327 // poll the local lock current index 328 while ( (*(volatile unsigned int *)( &node->current )) != ticket ) asm volatile( "nop" ); 329 330 #if GIET_DEBUG_USER_LOCK 331 giet_tty_printf("\n[DEBUG SQT_LOCK] sqt_lock_take() : " 332 "P[%d,%d,%d] get SQT lock %x" 333 " / level = %d / current = %d / free = %d\n", 334 x , y , l , (unsigned int)node , 335 node->level , node->current , node->free ); 336 #endif 337 338 // try to take the parent node lock until top is reached 339 if ( node->parent != NULL ) sqt_lock_take( node->parent ); 340 341 } // end _sqt_lock_take() 342 343 344 ////////////////////////////////////////// 345 void sqt_lock_acquire( sqt_lock_t* lock ) 346 { 347 unsigned int x; 348 unsigned int y; 349 unsigned int p; 350 351 // get cluster coordinates 352 giet_proc_xyp( &x, &y, &p ); 353 354 #if GIET_DEBUG_USER_LOCK 355 giet_tty_printf("\n[DEBUG SQT_LOCK] sqt_lock_acquire() : " 356 "P[%d,%d,%d] try to take lock = %x / lock_node = %x\n", 357 x, y, p, lock, lock->node[x][y][0] ); 358 #endif 359 360 // try to recursively take the distributed locks (from bottom to top) 361 sqt_lock_take( lock->node[x][y][0] ); 362 } 363 364 ////////////////////////////////////////////////// 365 static void sqt_lock_give( sqt_lock_node_t* node ) 366 { 367 // release the local lock 368 node->current = node->current + 1; 369 370 #if GIET_DEBUG_USER_LOCK 371 unsigned int x; 372 unsigned int y; 373 unsigned int l; 374 giet_proc_xyp(&x, &y, &l); 375 giet_tty_printf("\n[USER_LOCK DEBUG] sqt_lock_give() : " 376 "P[%d,%d,%d] release SQT lock_node %x" 377 " / level = %d / current = %d / free = %d\n", 378 x , y , l , (unsigned int)node, 379 node->level , node->current , node->free ); 380 #endif 381 382 // reset parent node until top is reached 383 if ( node->parent != NULL ) sqt_lock_give( node->parent ); 384 385 } // end _sqt_lock_give() 386 387 ////////////////////////////////////////// 388 void sqt_lock_release( sqt_lock_t* lock ) 389 { 390 asm volatile ( "sync" ); // for consistency 391 392 unsigned int x; 393 unsigned int y; 394 unsigned int p; 395 // get cluster coordinates 396 giet_proc_xyp( &x, &y, &p ); 397 398 // recursively reset the distributed locks (from bottom to top) 399 sqt_lock_give( lock->node[x][y][0] ); 116 400 } 117 401
Note: See TracChangeset
for help on using the changeset viewer.