| 1 | /*
|
|---|
| 2 | * almosmkh.c - User level ALMOS-MKH specific library implementation.
|
|---|
| 3 | *
|
|---|
| 4 | * Author Alain Greiner (2016,2017,2018,2019,2020)
|
|---|
| 5 | *
|
|---|
| 6 | * Copyright (c) UPMC Sorbonne Universites
|
|---|
| 7 | *
|
|---|
| 8 | * This file is part of ALMOS-MKH.
|
|---|
| 9 | *
|
|---|
| 10 | * ALMOS-MKH is free software; you can redistribute it and/or modify it
|
|---|
| 11 | * under the terms of the GNU General Public License as published by
|
|---|
| 12 | * the Free Software Foundation; version 2.0 of the License.
|
|---|
| 13 | *
|
|---|
| 14 | * ALMOS-MKH is distributed in the hope that it will be useful, but
|
|---|
| 15 | * WITHOUT ANY WARRANTY; without even the implied warranty of
|
|---|
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|---|
| 17 | * General Public License for more details.
|
|---|
| 18 | *
|
|---|
| 19 | * You should have received a copy of the GNU General Public License
|
|---|
| 20 | * along with ALMOS-MKH; if not, write to the Free Software Foundation,
|
|---|
| 21 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|---|
| 22 | */
|
|---|
| 23 |
|
|---|
| 24 | #include <almosmkh.h>
|
|---|
| 25 | #include <shared_almos.h>
|
|---|
| 26 | #include <hal_user.h>
|
|---|
| 27 | #include <hal_macros.h>
|
|---|
| 28 | #include <hal_shared_types.h>
|
|---|
| 29 | #include <shared_fbf.h>
|
|---|
| 30 | #include <syscalls_numbers.h>
|
|---|
| 31 | #include <string.h>
|
|---|
| 32 | #include <stdio.h>
|
|---|
| 33 | #include <stdlib.h>
|
|---|
| 34 | #include <unistd.h>
|
|---|
| 35 | #include <mman.h>
|
|---|
| 36 |
|
|---|
| 37 | #define DEBUG_REMOTE_MALLOC 0
|
|---|
| 38 | #define DEBUG_PTHREAD_PARALLEL 0
|
|---|
| 39 |
|
|---|
| 40 | //////////////////////////////////////////////////////////////////////////////////////
|
|---|
| 41 | ///////////// Non standard system calls ///////////////////////////////////////
|
|---|
| 42 | //////////////////////////////////////////////////////////////////////////////////////
|
|---|
| 43 |
|
|---|
| 44 | //////////////////////////
|
|---|
| 45 | int fg( unsigned int pid )
|
|---|
| 46 | {
|
|---|
| 47 | return hal_user_syscall( SYS_FG,
|
|---|
| 48 | (reg_t)pid, 0, 0, 0 );
|
|---|
| 49 | }
|
|---|
| 50 |
|
|---|
| 51 | //////////////////////////////
|
|---|
| 52 | int is_fg( unsigned int pid,
|
|---|
| 53 | unsigned int * owner )
|
|---|
| 54 | {
|
|---|
| 55 | return hal_user_syscall( SYS_IS_FG,
|
|---|
| 56 | (reg_t)pid,
|
|---|
| 57 | (reg_t)owner, 0, 0 );
|
|---|
| 58 | }
|
|---|
| 59 |
|
|---|
| 60 | ///////////////////////////////////////////////
|
|---|
| 61 | int get_config( struct hard_config_s * config )
|
|---|
| 62 | {
|
|---|
| 63 | return hal_user_syscall( SYS_GET,
|
|---|
| 64 | GET_CONFIG,
|
|---|
| 65 | (reg_t)config, 0, 0);
|
|---|
| 66 | }
|
|---|
| 67 |
|
|---|
| 68 | ////////////////////////////////////
|
|---|
| 69 | int get_core_id( unsigned int * cxy,
|
|---|
| 70 | unsigned int * lid )
|
|---|
| 71 | {
|
|---|
| 72 | return hal_user_syscall( SYS_GET,
|
|---|
| 73 | GET_CORE_ID,
|
|---|
| 74 | (reg_t)cxy,
|
|---|
| 75 | (reg_t)lid, 0 );
|
|---|
| 76 | }
|
|---|
| 77 |
|
|---|
| 78 | /////////////////////////////////////
|
|---|
| 79 | int get_nb_cores( unsigned int cxy,
|
|---|
| 80 | unsigned int * ncores )
|
|---|
| 81 | {
|
|---|
| 82 | return hal_user_syscall( SYS_GET,
|
|---|
| 83 | GET_NB_CORES,
|
|---|
| 84 | (reg_t)cxy,
|
|---|
| 85 | (reg_t)ncores, 0 );
|
|---|
| 86 | }
|
|---|
| 87 |
|
|---|
| 88 | ///////////////////////////////////////////
|
|---|
| 89 | int get_best_core( unsigned int base_cxy,
|
|---|
| 90 | unsigned int level,
|
|---|
| 91 | unsigned int * cxy,
|
|---|
| 92 | unsigned int * lid )
|
|---|
| 93 | {
|
|---|
| 94 | return hal_user_syscall( SYS_GET,
|
|---|
| 95 | GET_BEST_CORE,
|
|---|
| 96 | (reg_t)((base_cxy << 16) | (level & 0xFFFF)),
|
|---|
| 97 | (reg_t)cxy,
|
|---|
| 98 | (reg_t)lid );
|
|---|
| 99 | }
|
|---|
| 100 |
|
|---|
| 101 | //////////////////////////////////////////////
|
|---|
| 102 | int get_processes( unsigned int cxy,
|
|---|
| 103 | unsigned int owned,
|
|---|
| 104 | char * u_buf,
|
|---|
| 105 | unsigned int size )
|
|---|
| 106 | {
|
|---|
| 107 | return hal_user_syscall( SYS_GET,
|
|---|
| 108 | GET_PROCESSES,
|
|---|
| 109 | (reg_t)((cxy << 16) | (owned & 0xFFFF)),
|
|---|
| 110 | (reg_t)u_buf,
|
|---|
| 111 | (reg_t)size );
|
|---|
| 112 | }
|
|---|
| 113 |
|
|---|
| 114 | ///////////////////////////////////////////
|
|---|
| 115 | int get_cycle( unsigned long long * cycle )
|
|---|
| 116 | {
|
|---|
| 117 | return hal_user_syscall( SYS_GET,
|
|---|
| 118 | GET_CYCLE,
|
|---|
| 119 | (reg_t)cycle, 0, 0 );
|
|---|
| 120 | }
|
|---|
| 121 |
|
|---|
| 122 | ///////////////////////////////////////////
|
|---|
| 123 | int get_thread_info( thread_info_t * info )
|
|---|
| 124 | {
|
|---|
| 125 | return hal_user_syscall( SYS_GET,
|
|---|
| 126 | GET_THREAD_INFO,
|
|---|
| 127 | (reg_t)info, 0, 0 );
|
|---|
| 128 | }
|
|---|
| 129 |
|
|---|
| 130 | //////////////////////////////////
|
|---|
| 131 | int place_fork( unsigned int cxy )
|
|---|
| 132 | {
|
|---|
| 133 | return hal_user_syscall( SYS_PLACE_FORK,
|
|---|
| 134 | (reg_t)cxy, 0, 0, 0 );
|
|---|
| 135 | }
|
|---|
| 136 |
|
|---|
| 137 | /////////////////////////////////
|
|---|
| 138 | int utls( unsigned int operation,
|
|---|
| 139 | unsigned int value )
|
|---|
| 140 | {
|
|---|
| 141 | return hal_user_syscall( SYS_UTLS,
|
|---|
| 142 | (reg_t)operation,
|
|---|
| 143 | (reg_t)value, 0, 0 );
|
|---|
| 144 | }
|
|---|
| 145 |
|
|---|
| 146 | ////////////////////////////////////////
|
|---|
| 147 | void get_uint32( unsigned int * buffer )
|
|---|
| 148 | {
|
|---|
| 149 | unsigned int i;
|
|---|
| 150 | int c; // ASCII character value
|
|---|
| 151 |
|
|---|
| 152 | unsigned char buf[32];
|
|---|
| 153 |
|
|---|
| 154 | unsigned int save = 0;
|
|---|
| 155 | unsigned int value = 0;
|
|---|
| 156 | unsigned int done = 0;
|
|---|
| 157 | unsigned int overflow = 0;
|
|---|
| 158 | unsigned int length = 0;
|
|---|
| 159 |
|
|---|
| 160 | // get characters
|
|---|
| 161 | while (done == 0)
|
|---|
| 162 | {
|
|---|
| 163 | // read one character
|
|---|
| 164 | c = getchar();
|
|---|
| 165 |
|
|---|
| 166 | // analyse this character
|
|---|
| 167 | if ( ((c > 0x2F) && (c < 0x3A)) || // 0 to 9
|
|---|
| 168 | ((c > 0x40) && (c < 0x47)) || // A to F
|
|---|
| 169 | ((c > 0x60) && (c < 0x67)) || // a to f
|
|---|
| 170 | (((c == 0x58) || (c == 0x78)) && (length == 1)) ) // X or x
|
|---|
| 171 | {
|
|---|
| 172 | putchar( c ); // echo
|
|---|
| 173 | if ( c > 0x60 ) c = c - 0x20; // to upper case
|
|---|
| 174 | buf[length] = (unsigned char)c;
|
|---|
| 175 | length++;
|
|---|
| 176 | }
|
|---|
| 177 | else if (c == 0x0A) // LF character
|
|---|
| 178 | {
|
|---|
| 179 | done = 1;
|
|---|
| 180 | }
|
|---|
| 181 | else if ( (c == 0x7F) || // DEL character
|
|---|
| 182 | (c == 0x08) ) // BS character
|
|---|
| 183 | {
|
|---|
| 184 | if ( length > 0 )
|
|---|
| 185 | {
|
|---|
| 186 | length--;
|
|---|
| 187 | printf("\b \b"); // BS / / BS
|
|---|
| 188 | }
|
|---|
| 189 | }
|
|---|
| 190 | else if ( c == 0 ) // EOF character
|
|---|
| 191 | {
|
|---|
| 192 | overflow = 1;
|
|---|
| 193 | done = 1;
|
|---|
| 194 | }
|
|---|
| 195 |
|
|---|
| 196 | // test buffer overflow
|
|---|
| 197 | if ( length >= 32 )
|
|---|
| 198 | {
|
|---|
| 199 | overflow = 1;
|
|---|
| 200 | done = 1;
|
|---|
| 201 | }
|
|---|
| 202 | } // end while characters
|
|---|
| 203 |
|
|---|
| 204 | // string to int conversion with overflow detection
|
|---|
| 205 | if ( overflow == 0 )
|
|---|
| 206 | {
|
|---|
| 207 | // test (decimal / hexa)
|
|---|
| 208 | if( (buf[0] == 0x30) && ((buf[1] == 0x58) || (buf[1] == 0x78)) ) // hexa input
|
|---|
| 209 | {
|
|---|
| 210 | for (i = 2; (i < length) && (overflow == 0) ; i++)
|
|---|
| 211 | {
|
|---|
| 212 | if( buf[i] < 0x40 ) value = (value << 4) + (buf[i] - 0x30);
|
|---|
| 213 | else value = (value << 4) + (buf[i] - 0x37);
|
|---|
| 214 | if (value < save) overflow = 1;
|
|---|
| 215 | save = value;
|
|---|
| 216 | }
|
|---|
| 217 | }
|
|---|
| 218 | else // decimal input
|
|---|
| 219 | {
|
|---|
| 220 | for (i = 0; (i < length) && (overflow == 0) ; i++)
|
|---|
| 221 | {
|
|---|
| 222 | value = (value * 10) + (buf[i] - 0x30);
|
|---|
| 223 | if (value < save) overflow = 1;
|
|---|
| 224 | save = value;
|
|---|
| 225 | }
|
|---|
| 226 | }
|
|---|
| 227 | }
|
|---|
| 228 |
|
|---|
| 229 | // write value to buffer
|
|---|
| 230 | if ( overflow == 0 )
|
|---|
| 231 | {
|
|---|
| 232 | // return value
|
|---|
| 233 | *buffer = value;
|
|---|
| 234 | }
|
|---|
| 235 | else
|
|---|
| 236 | {
|
|---|
| 237 | // cancel all echo characters
|
|---|
| 238 | for (i = 0; i < length ; i++)
|
|---|
| 239 | {
|
|---|
| 240 | printf("\b \b"); // BS / / BS
|
|---|
| 241 | }
|
|---|
| 242 |
|
|---|
| 243 | // echo character '0'
|
|---|
| 244 | putchar( '0' );
|
|---|
| 245 |
|
|---|
| 246 | // return 0 value
|
|---|
| 247 | *buffer = 0;
|
|---|
| 248 | }
|
|---|
| 249 | } // end get_uint32()
|
|---|
| 250 |
|
|---|
| 251 | ///////////////////////////////
|
|---|
| 252 | int get_string( char * string,
|
|---|
| 253 | int maxlen )
|
|---|
| 254 | {
|
|---|
| 255 | int c;
|
|---|
| 256 | int length = 0;
|
|---|
| 257 |
|
|---|
| 258 | while( 1 )
|
|---|
| 259 | {
|
|---|
| 260 | // check buffer overflow
|
|---|
| 261 | if( length >= maxlen-1 )
|
|---|
| 262 | {
|
|---|
| 263 | // cancel all echo characters
|
|---|
| 264 | while( length )
|
|---|
| 265 | {
|
|---|
| 266 | printf("\b \b"); // cancel one echo character
|
|---|
| 267 | length--;
|
|---|
| 268 | }
|
|---|
| 269 | }
|
|---|
| 270 |
|
|---|
| 271 | // read one character
|
|---|
| 272 | c = getchar();
|
|---|
| 273 |
|
|---|
| 274 | // analyse this character
|
|---|
| 275 | if ( (c >= 0x20) && (c < 0x7F) ) // printable character
|
|---|
| 276 | {
|
|---|
| 277 | putchar( c ); // echo
|
|---|
| 278 | string[length] = (char)c; // register character in string
|
|---|
| 279 | length++; // update length
|
|---|
| 280 | }
|
|---|
| 281 | else if( c == 0x0A ) // LF character marks end of string
|
|---|
| 282 | {
|
|---|
| 283 | putchar( c ); // echo
|
|---|
| 284 | string[length] = 0; // register NUL character in string
|
|---|
| 285 | return length + 1;
|
|---|
| 286 | }
|
|---|
| 287 | else if ( (c == 0x7F) || // DEL character
|
|---|
| 288 | (c == 0x08) ) // BS character
|
|---|
| 289 | {
|
|---|
| 290 | if ( length > 0 )
|
|---|
| 291 | {
|
|---|
| 292 | printf("\b \b"); // cancel one echo character
|
|---|
| 293 | length--;
|
|---|
| 294 | }
|
|---|
| 295 | }
|
|---|
| 296 | }
|
|---|
| 297 | } // end get_string()
|
|---|
| 298 |
|
|---|
| 299 |
|
|---|
| 300 | //////////////////////////////////////////////////////////////////////////////////////
|
|---|
| 301 | /////////////// non standard debug functions ///////////////////////////////////
|
|---|
| 302 | //////////////////////////////////////////////////////////////////////////////////////
|
|---|
| 303 |
|
|---|
| 304 | ////////////////////////////////////
|
|---|
| 305 | void display_string( char * string )
|
|---|
| 306 | {
|
|---|
| 307 | hal_user_syscall( SYS_DISPLAY,
|
|---|
| 308 | DISPLAY_STRING,
|
|---|
| 309 | (reg_t)string, 0, 0 );
|
|---|
| 310 | }
|
|---|
| 311 |
|
|---|
| 312 | /////////////////////////////////////////////////////
|
|---|
| 313 | int display_vmm( unsigned int cxy,
|
|---|
| 314 | unsigned int pid,
|
|---|
| 315 | unsigned int mapping )
|
|---|
| 316 | {
|
|---|
| 317 | return hal_user_syscall( SYS_DISPLAY,
|
|---|
| 318 | DISPLAY_VMM,
|
|---|
| 319 | (reg_t)cxy,
|
|---|
| 320 | (reg_t)pid,
|
|---|
| 321 | (reg_t)mapping );
|
|---|
| 322 | }
|
|---|
| 323 |
|
|---|
| 324 | ////////////////////////////////////
|
|---|
| 325 | int display_sched( unsigned int cxy,
|
|---|
| 326 | unsigned int lid )
|
|---|
| 327 | {
|
|---|
| 328 | return hal_user_syscall( SYS_DISPLAY,
|
|---|
| 329 | DISPLAY_SCHED,
|
|---|
| 330 | (reg_t)cxy,
|
|---|
| 331 | (reg_t)lid, 0 );
|
|---|
| 332 | }
|
|---|
| 333 |
|
|---|
| 334 | ////////////////////////////////////////////////
|
|---|
| 335 | int display_cluster_processes( unsigned int cxy,
|
|---|
| 336 | unsigned int owned )
|
|---|
| 337 | {
|
|---|
| 338 | return hal_user_syscall( SYS_DISPLAY,
|
|---|
| 339 | DISPLAY_CLUSTER_PROCESSES,
|
|---|
| 340 | (reg_t)cxy,
|
|---|
| 341 | (reg_t)owned, 0 );
|
|---|
| 342 | }
|
|---|
| 343 |
|
|---|
| 344 | ////////////////////////////////////////
|
|---|
| 345 | int display_busylocks( unsigned int pid,
|
|---|
| 346 | unsigned int trdid )
|
|---|
| 347 | {
|
|---|
| 348 | return hal_user_syscall( SYS_DISPLAY,
|
|---|
| 349 | DISPLAY_BUSYLOCKS,
|
|---|
| 350 | (reg_t)pid,
|
|---|
| 351 | (reg_t)trdid, 0 );
|
|---|
| 352 | }
|
|---|
| 353 |
|
|---|
| 354 | /////////////////////////
|
|---|
| 355 | int display_chdev( void )
|
|---|
| 356 | {
|
|---|
| 357 | return hal_user_syscall( SYS_DISPLAY,
|
|---|
| 358 | DISPLAY_CHDEV, 0, 0, 0 );
|
|---|
| 359 | }
|
|---|
| 360 |
|
|---|
| 361 | ///////////////////////
|
|---|
| 362 | int display_vfs( void )
|
|---|
| 363 | {
|
|---|
| 364 | return hal_user_syscall( SYS_DISPLAY,
|
|---|
| 365 | DISPLAY_VFS, 0, 0, 0 );
|
|---|
| 366 | }
|
|---|
| 367 |
|
|---|
| 368 | ////////////////////////////////////////////////
|
|---|
| 369 | int display_txt_processes( unsigned int txt_id )
|
|---|
| 370 | {
|
|---|
| 371 | return hal_user_syscall( SYS_DISPLAY,
|
|---|
| 372 | DISPLAY_TXT_PROCESSES,
|
|---|
| 373 | (reg_t)txt_id, 0, 0 );
|
|---|
| 374 | }
|
|---|
| 375 |
|
|---|
| 376 | ////////////////////////
|
|---|
| 377 | int display_dqdt( void )
|
|---|
| 378 | {
|
|---|
| 379 | return hal_user_syscall( SYS_DISPLAY,
|
|---|
| 380 | DISPLAY_DQDT, 0, 0, 0 );
|
|---|
| 381 | }
|
|---|
| 382 |
|
|---|
| 383 | ///////////////////////////////////////
|
|---|
| 384 | int display_mapper( char * path,
|
|---|
| 385 | unsigned int page_id,
|
|---|
| 386 | unsigned int nbytes)
|
|---|
| 387 | {
|
|---|
| 388 | return hal_user_syscall( SYS_DISPLAY,
|
|---|
| 389 | DISPLAY_MAPPER,
|
|---|
| 390 | (reg_t)path,
|
|---|
| 391 | (reg_t)page_id,
|
|---|
| 392 | (reg_t)nbytes );
|
|---|
| 393 | }
|
|---|
| 394 |
|
|---|
| 395 | ///////////////////////////////////////
|
|---|
| 396 | int display_barrier( unsigned int pid )
|
|---|
| 397 | {
|
|---|
| 398 | return hal_user_syscall( SYS_DISPLAY,
|
|---|
| 399 | DISPLAY_BARRIER,
|
|---|
| 400 | (reg_t)pid, 0, 0 );
|
|---|
| 401 | }
|
|---|
| 402 |
|
|---|
| 403 | ///////////////////////////////////////
|
|---|
| 404 | int display_fat( unsigned int min_slot,
|
|---|
| 405 | unsigned int nb_slots )
|
|---|
| 406 | {
|
|---|
| 407 | return hal_user_syscall( SYS_DISPLAY,
|
|---|
| 408 | DISPLAY_FAT,
|
|---|
| 409 | (reg_t)min_slot,
|
|---|
| 410 | (reg_t)nb_slots, 0 );
|
|---|
| 411 | }
|
|---|
| 412 |
|
|---|
| 413 | /////////////////////////////////////
|
|---|
| 414 | int display_socket( unsigned int pid,
|
|---|
| 415 | unsigned int fdid )
|
|---|
| 416 | {
|
|---|
| 417 | return hal_user_syscall( SYS_DISPLAY,
|
|---|
| 418 | DISPLAY_SOCKET,
|
|---|
| 419 | (reg_t)pid,
|
|---|
| 420 | (reg_t)fdid, 0 );
|
|---|
| 421 | }
|
|---|
| 422 |
|
|---|
| 423 | ////////////////////////////////////////
|
|---|
| 424 | int display_fd_array( unsigned int pid )
|
|---|
| 425 | {
|
|---|
| 426 | return hal_user_syscall( SYS_DISPLAY,
|
|---|
| 427 | DISPLAY_FD,
|
|---|
| 428 | (reg_t)pid, 0, 0 );
|
|---|
| 429 | }
|
|---|
| 430 |
|
|---|
| 431 | ///////////////////////////////////////////
|
|---|
| 432 | int display_fbf_windows( unsigned int pid )
|
|---|
| 433 | {
|
|---|
| 434 | return hal_user_syscall( SYS_DISPLAY,
|
|---|
| 435 | DISPLAY_WINDOWS,
|
|---|
| 436 | (reg_t)pid, 0, 0 );
|
|---|
| 437 | }
|
|---|
| 438 |
|
|---|
| 439 | ///////////////////////////////
|
|---|
| 440 | int trace( unsigned int active,
|
|---|
| 441 | unsigned int cxy,
|
|---|
| 442 | unsigned int lid )
|
|---|
| 443 | {
|
|---|
| 444 | return hal_user_syscall( SYS_TRACE,
|
|---|
| 445 | (reg_t)active,
|
|---|
| 446 | (reg_t)cxy,
|
|---|
| 447 | (reg_t)lid, 0 );
|
|---|
| 448 | }
|
|---|
| 449 |
|
|---|
| 450 | /////////////////
|
|---|
| 451 | void idbg( void )
|
|---|
| 452 | {
|
|---|
| 453 | char cmd;
|
|---|
| 454 |
|
|---|
| 455 | while( 1 )
|
|---|
| 456 | {
|
|---|
| 457 | // display prompt
|
|---|
| 458 | printf("\n[idbg] cmd = ");
|
|---|
| 459 |
|
|---|
| 460 | // get a one character command
|
|---|
| 461 | cmd = (char)getchar();
|
|---|
| 462 |
|
|---|
| 463 | // display all busylocks owned by thread(pid,trdid)
|
|---|
| 464 | if( cmd == 'b' )
|
|---|
| 465 | {
|
|---|
| 466 | unsigned int pid;
|
|---|
| 467 | unsigned int trdid;
|
|---|
| 468 |
|
|---|
| 469 | printf("b / pid = ");
|
|---|
| 470 | get_uint32( &pid );
|
|---|
| 471 |
|
|---|
| 472 | printf(" / trdid = ");
|
|---|
| 473 | get_uint32( &trdid );
|
|---|
| 474 |
|
|---|
| 475 | display_busylocks( pid , trdid );
|
|---|
| 476 | }
|
|---|
| 477 | // return to calling process
|
|---|
| 478 | else if( cmd == 'c' )
|
|---|
| 479 | {
|
|---|
| 480 | printf("c\n");
|
|---|
| 481 | break;
|
|---|
| 482 | }
|
|---|
| 483 | // display FAT mapper(min,slots)
|
|---|
| 484 | else if( cmd == 'f' )
|
|---|
| 485 | {
|
|---|
| 486 | unsigned int min;
|
|---|
| 487 | unsigned int slots;
|
|---|
| 488 |
|
|---|
| 489 | printf(" / min = ");
|
|---|
| 490 | get_uint32( &min );
|
|---|
| 491 |
|
|---|
| 492 | printf(" / slots = ");
|
|---|
| 493 | get_uint32( &slots );
|
|---|
| 494 |
|
|---|
| 495 | display_fat( min , slots );
|
|---|
| 496 | }
|
|---|
| 497 | // list all supported commands
|
|---|
| 498 | else if( cmd == 'h' )
|
|---|
| 499 | {
|
|---|
| 500 | printf("h\n"
|
|---|
| 501 | "- b : display on TXT0 busylocks taken by thread[pid,trdid]\n"
|
|---|
| 502 | "- c : resume calling process execution\n"
|
|---|
| 503 | "- f : display on TXT0 FAT mapper[min_slot,nb_slotss]\n"
|
|---|
| 504 | "- h : list of supported commands\n"
|
|---|
| 505 | "- m : display on TXT0 mapper[path,page,nbytes]\n"
|
|---|
| 506 | "- p : display on TXT0 process descriptors in cluster[cxy]\n"
|
|---|
| 507 | "- q : display on TXT0 DQDT state\n"
|
|---|
| 508 | "- s : display on TXT0 scheduler state for core[cxy,lid]\n"
|
|---|
| 509 | "- t : display on TXT0 process decriptors attached to TXT[tid]\n"
|
|---|
| 510 | "- v : display on TXT0 VMM state for process[cxy,pid]\n"
|
|---|
| 511 | "- x : force calling process to exit\n"
|
|---|
| 512 | "- y : activate/desactivate trace for core[cxy,lid]\n"
|
|---|
| 513 | );
|
|---|
| 514 | }
|
|---|
| 515 | // display MAPPER(path,page,nbytes)
|
|---|
| 516 | else if( cmd == 'm' )
|
|---|
| 517 | {
|
|---|
| 518 | char path[128];
|
|---|
| 519 | unsigned int page;
|
|---|
| 520 | unsigned int nbytes;
|
|---|
| 521 |
|
|---|
| 522 | printf("m / path = ");
|
|---|
| 523 | get_string( path , 128 );
|
|---|
| 524 |
|
|---|
| 525 | printf(" / page = ");
|
|---|
| 526 | get_uint32( &page );
|
|---|
| 527 |
|
|---|
| 528 | printf(" / nbytes = ");
|
|---|
| 529 | get_uint32( &nbytes );
|
|---|
| 530 |
|
|---|
| 531 | display_mapper( path , page , nbytes );
|
|---|
| 532 | }
|
|---|
| 533 | // display all processes in cluster(cxy)
|
|---|
| 534 | else if( cmd == 'p' )
|
|---|
| 535 | {
|
|---|
| 536 | unsigned int cxy;
|
|---|
| 537 |
|
|---|
| 538 | printf("p / cxy = ");
|
|---|
| 539 | get_uint32( &cxy );
|
|---|
| 540 |
|
|---|
| 541 | display_cluster_processes( cxy , 0 );
|
|---|
| 542 | }
|
|---|
| 543 | // display DQDT
|
|---|
| 544 | else if( cmd == 'q' )
|
|---|
| 545 | {
|
|---|
| 546 | printf("q\n");
|
|---|
| 547 | display_dqdt();
|
|---|
| 548 | }
|
|---|
| 549 | // display scheduler state for core(cxy,lid)
|
|---|
| 550 | else if( cmd == 's' )
|
|---|
| 551 | {
|
|---|
| 552 | unsigned int cxy;
|
|---|
| 553 | unsigned int lid;
|
|---|
| 554 |
|
|---|
| 555 | printf("s / cxy = ");
|
|---|
| 556 | get_uint32( &cxy );
|
|---|
| 557 |
|
|---|
| 558 | printf(" / lid = ");
|
|---|
| 559 | get_uint32( &lid );
|
|---|
| 560 |
|
|---|
| 561 | display_sched( cxy , lid );
|
|---|
| 562 | }
|
|---|
| 563 | // display all processes attached to TXT(txt_id)
|
|---|
| 564 | else if( cmd == 't' )
|
|---|
| 565 | {
|
|---|
| 566 | unsigned int txt_id;
|
|---|
| 567 |
|
|---|
| 568 | printf("t / txt_id = ");
|
|---|
| 569 | get_uint32( &txt_id );
|
|---|
| 570 |
|
|---|
| 571 | display_txt_processes( txt_id );
|
|---|
| 572 | }
|
|---|
| 573 | // display vmm state for process(cxy, pid)
|
|---|
| 574 | else if( cmd == 'v' )
|
|---|
| 575 | {
|
|---|
| 576 | unsigned int cxy;
|
|---|
| 577 | unsigned int pid;
|
|---|
| 578 | unsigned int map;
|
|---|
| 579 |
|
|---|
| 580 | printf("v / cxy = ");
|
|---|
| 581 | get_uint32( &cxy );
|
|---|
| 582 |
|
|---|
| 583 | printf(" / pid = ");
|
|---|
| 584 | get_uint32( &pid );
|
|---|
| 585 |
|
|---|
| 586 | printf(" / mapping = ");
|
|---|
| 587 | get_uint32( &map );
|
|---|
| 588 |
|
|---|
| 589 | display_vmm( cxy , pid , map );
|
|---|
| 590 | }
|
|---|
| 591 | // force the calling process to exit
|
|---|
| 592 | else if( cmd == 'x' )
|
|---|
| 593 | {
|
|---|
| 594 | printf("x\n");
|
|---|
| 595 | exit( 0 );
|
|---|
| 596 | }
|
|---|
| 597 | // activate scheduler trace for core(cxy,lid)
|
|---|
| 598 | else if( cmd == 'y' )
|
|---|
| 599 | {
|
|---|
| 600 | unsigned int active;
|
|---|
| 601 | unsigned int cxy;
|
|---|
| 602 | unsigned int lid;
|
|---|
| 603 |
|
|---|
| 604 | printf("y / active = ");
|
|---|
| 605 | get_uint32( &active );
|
|---|
| 606 |
|
|---|
| 607 | printf(" / cxy = ");
|
|---|
| 608 | get_uint32( &cxy );
|
|---|
| 609 |
|
|---|
| 610 | printf(" / lid = ");
|
|---|
| 611 | get_uint32( &lid );
|
|---|
| 612 |
|
|---|
| 613 | trace( active , cxy , lid );
|
|---|
| 614 | }
|
|---|
| 615 | } // en while
|
|---|
| 616 | } // end idbg()
|
|---|
| 617 |
|
|---|
| 618 |
|
|---|
| 619 | /////////////////////////////////////////////////////////////////////////////////////////
|
|---|
| 620 | /////////////// non standard remote_malloc ////////////////////////////////////////
|
|---|
| 621 | /////////////////////////////////////////////////////////////////////////////////////////
|
|---|
| 622 |
|
|---|
| 623 | /////////////////////////////////////////////////////////////////////////////////////////
|
|---|
| 624 | // Global variable defining the allocator array (one per cluster)
|
|---|
| 625 | // This array (about 16 Kbytes ) will be stored in the data segment
|
|---|
| 626 | // of any application linked with this libray.
|
|---|
| 627 | /////////////////////////////////////////////////////////////////////////////////////////
|
|---|
| 628 |
|
|---|
| 629 | malloc_store_t store[MALLOC_MAX_CLUSTERS];
|
|---|
| 630 |
|
|---|
| 631 | // Macro returning the smallest power of 2 larger or equal to size value
|
|---|
| 632 |
|
|---|
| 633 | #define GET_SIZE_INDEX(size) (size <= 0x00000001) ? 0 :\
|
|---|
| 634 | (size <= 0x00000002) ? 1 :\
|
|---|
| 635 | (size <= 0x00000004) ? 2 :\
|
|---|
| 636 | (size <= 0x00000008) ? 3 :\
|
|---|
| 637 | (size <= 0x00000010) ? 4 :\
|
|---|
| 638 | (size <= 0x00000020) ? 5 :\
|
|---|
| 639 | (size <= 0x00000040) ? 6 :\
|
|---|
| 640 | (size <= 0x00000080) ? 7 :\
|
|---|
| 641 | (size <= 0x00000100) ? 8 :\
|
|---|
| 642 | (size <= 0x00000200) ? 9 :\
|
|---|
| 643 | (size <= 0x00000400) ? 10 :\
|
|---|
| 644 | (size <= 0x00000800) ? 11 :\
|
|---|
| 645 | (size <= 0x00001000) ? 12 :\
|
|---|
| 646 | (size <= 0x00002000) ? 13 :\
|
|---|
| 647 | (size <= 0x00004000) ? 14 :\
|
|---|
| 648 | (size <= 0x00008000) ? 15 :\
|
|---|
| 649 | (size <= 0x00010000) ? 16 :\
|
|---|
| 650 | (size <= 0x00020000) ? 17 :\
|
|---|
| 651 | (size <= 0x00040000) ? 18 :\
|
|---|
| 652 | (size <= 0x00080000) ? 19 :\
|
|---|
| 653 | (size <= 0x00100000) ? 20 :\
|
|---|
| 654 | (size <= 0x00200000) ? 21 :\
|
|---|
| 655 | (size <= 0x00400000) ? 22 :\
|
|---|
| 656 | (size <= 0x00800000) ? 23 :\
|
|---|
| 657 | (size <= 0x01000000) ? 24 :\
|
|---|
| 658 | (size <= 0x02000000) ? 25 :\
|
|---|
| 659 | (size <= 0x04000000) ? 26 :\
|
|---|
| 660 | (size <= 0x08000000) ? 27 :\
|
|---|
| 661 | (size <= 0x10000000) ? 28 :\
|
|---|
| 662 | (size <= 0x20000000) ? 29 :\
|
|---|
| 663 | (size <= 0x40000000) ? 30 :\
|
|---|
| 664 | (size <= 0x80000000) ? 31 :\
|
|---|
| 665 | 32
|
|---|
| 666 |
|
|---|
| 667 | ////////////////////////////////////////////////////////////////////////////////////////////
|
|---|
| 668 | // This static function display the current state of the allocator in cluster <cxy>.
|
|---|
| 669 | ////////////////////////////////////////////////////////////////////////////////////////////
|
|---|
| 670 |
|
|---|
| 671 | #if DEBUG_REMOTE_MALLOC
|
|---|
| 672 | static void display_free_array( unsigned int cxy )
|
|---|
| 673 | {
|
|---|
| 674 | unsigned int next;
|
|---|
| 675 | unsigned int id;
|
|---|
| 676 | unsigned int iter;
|
|---|
| 677 |
|
|---|
| 678 | printf("\n***** store[%x] base = %x / size = %x\n",
|
|---|
| 679 | cxy , store[cxy].store_base, store[cxy].store_size );
|
|---|
| 680 | for ( id = 0 ; id < 32 ; id++ )
|
|---|
| 681 | {
|
|---|
| 682 | next = store[cxy].free[id];
|
|---|
| 683 | printf(" - free[%d] = " , id );
|
|---|
| 684 | iter = 0;
|
|---|
| 685 | while ( next != 0 )
|
|---|
| 686 | {
|
|---|
| 687 | printf("%x | ", next );
|
|---|
| 688 | next = (*(unsigned int*)next);
|
|---|
| 689 | iter++;
|
|---|
| 690 | }
|
|---|
| 691 | printf("0\n");
|
|---|
| 692 | }
|
|---|
| 693 | } // end display_free_array()
|
|---|
| 694 | #endif
|
|---|
| 695 |
|
|---|
| 696 |
|
|---|
| 697 | ////////////////////////////////////////////////////////////////////i//////////////////////
|
|---|
| 698 | // This static function initialises the store in the cluster identified by the <cxy>
|
|---|
| 699 | // arguments. It is called by the remote_malloc() function when a specific store(x,y)
|
|---|
| 700 | // is accessed for the first time.
|
|---|
| 701 | // It uses the mmap( MAP_REMOTE ) syscall to allocate a new vseg mapped in cluster (cxy).
|
|---|
| 702 | ////////////////////////////////////////////////////////////////////i//////////////////////
|
|---|
| 703 | // @ cxy : target cluster identifier (fixed format).
|
|---|
| 704 | // @ store_size : store size (bytes).
|
|---|
| 705 | // # return without setting the initialized field in store(cxy) if failure.
|
|---|
| 706 | ////////////////////////////////////////////////////////////////////i//////////////////////
|
|---|
| 707 | static void store_init( unsigned int cxy,
|
|---|
| 708 | unsigned int store_size )
|
|---|
| 709 | {
|
|---|
| 710 | unsigned int store_base; // store base address
|
|---|
| 711 | unsigned int free_index; // index in free[array]
|
|---|
| 712 |
|
|---|
| 713 | unsigned int alloc_base; // alloc[] array base
|
|---|
| 714 | unsigned int alloc_size; // alloc[] array size
|
|---|
| 715 | unsigned int alloc_index; // index in alloc[array]
|
|---|
| 716 |
|
|---|
| 717 | unsigned int iter; // iterator
|
|---|
| 718 |
|
|---|
| 719 | #if DEBUG_REMOTE_MALLOC
|
|---|
| 720 | unsigned int core_cxy;
|
|---|
| 721 | unsigned int core_lid;
|
|---|
| 722 | get_core_id( &core_cxy , &core_lid );
|
|---|
| 723 | printf("\n[%s] core[%x,%d] enter for store[%x] / size = %x\n",
|
|---|
| 724 | __FUNCTION__, core_cxy, core_lid, cxy, store_size );
|
|---|
| 725 | #endif
|
|---|
| 726 |
|
|---|
| 727 | // get index in free[] array from size
|
|---|
| 728 | free_index = GET_SIZE_INDEX( store_size );
|
|---|
| 729 |
|
|---|
| 730 | // check store size power of 2
|
|---|
| 731 | if( store_size != (unsigned int)(1<<free_index) )
|
|---|
| 732 | {
|
|---|
| 733 | printf("\n[ERROR] in %s : store[%x] size not power of 2 / size = %x\n",
|
|---|
| 734 | __FUNCTION__, cxy , store_size );
|
|---|
| 735 | return;
|
|---|
| 736 | }
|
|---|
| 737 |
|
|---|
| 738 | // allocate store in virtual space
|
|---|
| 739 | void * vadr = mmap( NULL, // MAP_FIXED not supported
|
|---|
| 740 | store_size,
|
|---|
| 741 | PROT_READ | PROT_WRITE,
|
|---|
| 742 | MAP_REMOTE| MAP_SHARED,
|
|---|
| 743 | cxy, // fd is cluster identifier
|
|---|
| 744 | 0 ); // offset unused
|
|---|
| 745 |
|
|---|
| 746 | if( vadr == NULL )
|
|---|
| 747 | {
|
|---|
| 748 | printf("\n[ERROR] in %s : cannot mmap store[%x]\n",
|
|---|
| 749 | __FUNCTION__, cxy );
|
|---|
| 750 | return;
|
|---|
| 751 | }
|
|---|
| 752 |
|
|---|
| 753 | store_base = (unsigned int)vadr;
|
|---|
| 754 |
|
|---|
| 755 | // check allocated store alignment
|
|---|
| 756 | if( store_base % store_size )
|
|---|
| 757 | {
|
|---|
| 758 | printf("\n[ERROR] in %s : store[%x] not aligned / base = %x / size = %x\n",
|
|---|
| 759 | __FUNCTION__, cxy , store_base , store_size );
|
|---|
| 760 | return;
|
|---|
| 761 | }
|
|---|
| 762 |
|
|---|
| 763 | #if DEBUG_REMOTE_MALLOC
|
|---|
| 764 | printf("\n[%s] core[%x,%d] created vseg %x for store[%x]\n",
|
|---|
| 765 | __FUNCTION__, core_cxy, core_lid, store_base, cxy );
|
|---|
| 766 | #endif
|
|---|
| 767 |
|
|---|
| 768 | // compute size of block containing alloc[] array
|
|---|
| 769 | alloc_size = store_size / MALLOC_MIN_BLOCK_SIZE;
|
|---|
| 770 | if ( alloc_size < MALLOC_MIN_BLOCK_SIZE) alloc_size = MALLOC_MIN_BLOCK_SIZE;
|
|---|
| 771 |
|
|---|
| 772 | // get index for the corresponding block
|
|---|
| 773 | alloc_index = GET_SIZE_INDEX( alloc_size );
|
|---|
| 774 |
|
|---|
| 775 | // compute alloc[] array base address
|
|---|
| 776 | alloc_base = store_base + store_size - alloc_size;
|
|---|
| 777 |
|
|---|
| 778 | // reset the free[] array
|
|---|
| 779 | for ( iter = 0 ; iter < 32 ; iter++ )
|
|---|
| 780 | {
|
|---|
| 781 | store[cxy].free[iter] = 0;
|
|---|
| 782 | }
|
|---|
| 783 |
|
|---|
| 784 | // split the store into various sizes blocks,
|
|---|
| 785 | // initializes the free[] array and NEXT pointers
|
|---|
| 786 | // base is the block base address
|
|---|
| 787 | unsigned int base = store_base;
|
|---|
| 788 | unsigned int * ptr;
|
|---|
| 789 | for ( iter = free_index-1 ; iter >= alloc_index ; iter-- )
|
|---|
| 790 | {
|
|---|
| 791 | store[cxy].free[iter] = base;
|
|---|
| 792 | ptr = (unsigned int*)base;
|
|---|
| 793 | *ptr = 0;
|
|---|
| 794 | base = base + (1<<iter);
|
|---|
| 795 | }
|
|---|
| 796 |
|
|---|
| 797 | // initialize store mutex
|
|---|
| 798 | if( pthread_mutex_init( &store[cxy].mutex , NULL ) )
|
|---|
| 799 | {
|
|---|
| 800 | printf("\n[ERROR] in %s : cannot initialize mutex for store[%x]\n",
|
|---|
| 801 | __FUNCTION__, cxy );
|
|---|
| 802 | return;
|
|---|
| 803 | }
|
|---|
| 804 |
|
|---|
| 805 | store[cxy].cxy = cxy;
|
|---|
| 806 | store[cxy].store_base = store_base;
|
|---|
| 807 | store[cxy].store_size = store_size;
|
|---|
| 808 | store[cxy].alloc_size = alloc_size;
|
|---|
| 809 | store[cxy].alloc_base = alloc_base;
|
|---|
| 810 | store[cxy].initialized = MALLOC_INITIALIZED;
|
|---|
| 811 |
|
|---|
| 812 |
|
|---|
| 813 | #if DEBUG_REMOTE_MALLOC
|
|---|
| 814 | printf("\n[%s] core[%x,%d] completed store[%x] initialisation\n",
|
|---|
| 815 | __FUNCTION__, core_cxy, core_lid, cxy );
|
|---|
| 816 | #endif
|
|---|
| 817 |
|
|---|
| 818 | #if (DEBUG_REMOTE_MALLOC & 1)
|
|---|
| 819 | display_free_array( cxy );
|
|---|
| 820 | #endif
|
|---|
| 821 |
|
|---|
| 822 | } // end store_init()
|
|---|
| 823 |
|
|---|
| 824 | ////////////////////////////////////////////////////////
|
|---|
| 825 | static unsigned int split_block( malloc_store_t * store,
|
|---|
| 826 | unsigned int vaddr,
|
|---|
| 827 | unsigned int searched_index,
|
|---|
| 828 | unsigned int requested_index )
|
|---|
| 829 | {
|
|---|
| 830 | // push the upper half block into free[searched_index-1]
|
|---|
| 831 | unsigned int* new = (unsigned int*)(vaddr + (1<<(searched_index-1)));
|
|---|
| 832 | *new = store->free[searched_index-1];
|
|---|
| 833 | store->free[searched_index-1] = (unsigned int)new;
|
|---|
| 834 |
|
|---|
| 835 | if ( searched_index == requested_index + 1 ) // terminal case: return lower half block
|
|---|
| 836 | {
|
|---|
| 837 | return vaddr;
|
|---|
| 838 | }
|
|---|
| 839 | else // non terminal case : lower half block must be split again
|
|---|
| 840 | {
|
|---|
| 841 | return split_block( store, vaddr, searched_index-1, requested_index );
|
|---|
| 842 | }
|
|---|
| 843 | } // end split_block()
|
|---|
| 844 |
|
|---|
| 845 | //////////////////////////////////////////////////////
|
|---|
| 846 | static unsigned int get_block( malloc_store_t * store,
|
|---|
| 847 | unsigned int searched_index,
|
|---|
| 848 | unsigned int requested_index )
|
|---|
| 849 | {
|
|---|
| 850 | // test terminal case
|
|---|
| 851 | if ( (unsigned int)(1<<searched_index) > store->store_size ) // failure
|
|---|
| 852 | {
|
|---|
| 853 | return 0;
|
|---|
| 854 | }
|
|---|
| 855 | else // search a block in free[searched_index]
|
|---|
| 856 | {
|
|---|
| 857 | unsigned int vaddr = store->free[searched_index];
|
|---|
| 858 | if ( vaddr == 0 ) // block not found : search in free[searched_index+1]
|
|---|
| 859 | {
|
|---|
| 860 | return get_block( store, searched_index+1, requested_index );
|
|---|
| 861 | }
|
|---|
| 862 | else // block found : pop it from free[searched_index]
|
|---|
| 863 | {
|
|---|
| 864 | // pop the block from free[searched_index]
|
|---|
| 865 | unsigned int next = *((unsigned int*)vaddr);
|
|---|
| 866 | store->free[searched_index] = next;
|
|---|
| 867 |
|
|---|
| 868 | // test if the block must be split
|
|---|
| 869 | if ( searched_index == requested_index ) // no split required
|
|---|
| 870 | {
|
|---|
| 871 | return vaddr;
|
|---|
| 872 | }
|
|---|
| 873 | else // split is required
|
|---|
| 874 | {
|
|---|
| 875 | return split_block( store, vaddr, searched_index, requested_index );
|
|---|
| 876 | }
|
|---|
| 877 | }
|
|---|
| 878 | }
|
|---|
| 879 | } // end get_block()
|
|---|
| 880 |
|
|---|
| 881 | ////////////////////////////////////////
|
|---|
| 882 | void * remote_malloc( unsigned int size,
|
|---|
| 883 | unsigned int cxy )
|
|---|
| 884 | {
|
|---|
| 885 | int error;
|
|---|
| 886 |
|
|---|
| 887 | #if DEBUG_REMOTE_MALLOC
|
|---|
| 888 | unsigned int core_cxy;
|
|---|
| 889 | unsigned int core_lid;
|
|---|
| 890 | get_core_id( &core_cxy , &core_lid );
|
|---|
| 891 | printf("\n[%s] core[%x,%d] enter for size = %x / target_cxy = %x\n",
|
|---|
| 892 | __FUNCTION__ , core_cxy, core_lid, size , cxy );
|
|---|
| 893 | #endif
|
|---|
| 894 |
|
|---|
| 895 | // check arguments
|
|---|
| 896 | if( size == 0 )
|
|---|
| 897 | {
|
|---|
| 898 | printf("\n[ERROR] in %s : requested size = 0 \n",
|
|---|
| 899 | __FUNCTION__ );
|
|---|
| 900 | return NULL;
|
|---|
| 901 | }
|
|---|
| 902 | if( cxy >= MALLOC_MAX_CLUSTERS )
|
|---|
| 903 | {
|
|---|
| 904 | printf("\n[ERROR] in %s : illegal cluster %x\n",
|
|---|
| 905 | __FUNCTION__ , cxy );
|
|---|
| 906 | return NULL;
|
|---|
| 907 | }
|
|---|
| 908 |
|
|---|
| 909 | // initializes target store if required
|
|---|
| 910 | if( store[cxy].initialized != MALLOC_INITIALIZED )
|
|---|
| 911 | {
|
|---|
| 912 | store_init( cxy , MALLOC_LOCAL_STORE_SIZE );
|
|---|
| 913 |
|
|---|
| 914 | if( store[cxy].initialized != MALLOC_INITIALIZED )
|
|---|
| 915 | {
|
|---|
| 916 | printf("\n[ERROR] in %s : cannot allocate store in cluster %x\n",
|
|---|
| 917 | __FUNCTION__ , cxy );
|
|---|
| 918 | return NULL;
|
|---|
| 919 | }
|
|---|
| 920 | }
|
|---|
| 921 |
|
|---|
| 922 | // normalize size
|
|---|
| 923 | if ( size < MALLOC_MIN_BLOCK_SIZE ) size = MALLOC_MIN_BLOCK_SIZE;
|
|---|
| 924 |
|
|---|
| 925 | // compute requested_index for the free[] array
|
|---|
| 926 | unsigned int requested_index = GET_SIZE_INDEX( size );
|
|---|
| 927 |
|
|---|
| 928 | // take the lock protecting access to store[cxy]
|
|---|
| 929 | error = pthread_mutex_lock( &store[cxy].mutex );
|
|---|
| 930 |
|
|---|
| 931 | if( error )
|
|---|
| 932 | {
|
|---|
| 933 | printf("\n[ERROR] in %s : cannot take the lock protecting store in cluster %x\n",
|
|---|
| 934 | __FUNCTION__ , cxy );
|
|---|
| 935 | return NULL;
|
|---|
| 936 | }
|
|---|
| 937 |
|
|---|
| 938 | // call the recursive function get_block
|
|---|
| 939 | unsigned int base = get_block( &store[cxy],
|
|---|
| 940 | requested_index,
|
|---|
| 941 | requested_index );
|
|---|
| 942 |
|
|---|
| 943 | // check block found
|
|---|
| 944 | if (base == 0)
|
|---|
| 945 | {
|
|---|
| 946 | pthread_mutex_unlock( &store[cxy].mutex );
|
|---|
| 947 | printf("\n[ERROR] in %s : no more space in cluster %x\n",
|
|---|
| 948 | __FUNCTION__ , cxy );
|
|---|
| 949 | return NULL;
|
|---|
| 950 | }
|
|---|
| 951 |
|
|---|
| 952 | // compute pointer in alloc[] array
|
|---|
| 953 | unsigned offset = (base - store[cxy].store_base) / MALLOC_MIN_BLOCK_SIZE;
|
|---|
| 954 | unsigned char * ptr = (unsigned char*)(store[cxy].alloc_base + offset);
|
|---|
| 955 |
|
|---|
| 956 | // update alloc_array
|
|---|
| 957 | *ptr = requested_index;
|
|---|
| 958 |
|
|---|
| 959 | // release the lock
|
|---|
| 960 | pthread_mutex_unlock( &store[cxy].mutex );
|
|---|
| 961 |
|
|---|
| 962 | #if DEBUG_REMOTE_MALLOC
|
|---|
| 963 | printf("\n[%s] core[%x,%d] exit / base = %x / size = %x / from store[%x]\n",
|
|---|
| 964 | __FUNCTION__, core_cxy, core_lid, base , size , cxy );
|
|---|
| 965 | #endif
|
|---|
| 966 |
|
|---|
| 967 | return (void*) base;
|
|---|
| 968 |
|
|---|
| 969 | } // end remote_malloc()
|
|---|
| 970 |
|
|---|
| 971 | //////////////////////////////////////////
|
|---|
| 972 | void * remote_calloc ( unsigned int count,
|
|---|
| 973 | unsigned int size,
|
|---|
| 974 | unsigned int cxy )
|
|---|
| 975 | {
|
|---|
| 976 | void * ptr = remote_malloc( count * size , cxy );
|
|---|
| 977 | memset( ptr , 0 , count * size );
|
|---|
| 978 | return ptr;
|
|---|
| 979 | }
|
|---|
| 980 |
|
|---|
| 981 | //////////////////////////////////
|
|---|
| 982 | void * remote_realloc( void * ptr,
|
|---|
| 983 | unsigned int size,
|
|---|
| 984 | unsigned int cxy )
|
|---|
| 985 | {
|
|---|
| 986 | // simple allocation when (ptr == NULL)
|
|---|
| 987 | if( ptr == NULL )
|
|---|
| 988 | {
|
|---|
| 989 | return remote_malloc( size , cxy );
|
|---|
| 990 | }
|
|---|
| 991 |
|
|---|
| 992 | // simple free when (size == 0)
|
|---|
| 993 | if( size == 0 )
|
|---|
| 994 | {
|
|---|
| 995 | remote_free( ptr , cxy );
|
|---|
| 996 | return NULL;
|
|---|
| 997 | }
|
|---|
| 998 |
|
|---|
| 999 | // check cxy and ptr in general case
|
|---|
| 1000 | if( cxy >= MALLOC_MAX_CLUSTERS )
|
|---|
| 1001 | {
|
|---|
| 1002 | printf("\n[ERROR] in %s : illegal cluster index %x\n",
|
|---|
| 1003 | __FUNCTION__ , cxy );
|
|---|
| 1004 | return NULL;
|
|---|
| 1005 | }
|
|---|
| 1006 |
|
|---|
| 1007 | unsigned int base = (unsigned int)ptr;
|
|---|
| 1008 |
|
|---|
| 1009 | if( (base < store[cxy].store_base) ||
|
|---|
| 1010 | (base >= (store[cxy].store_base + store[cxy].store_size)) )
|
|---|
| 1011 | {
|
|---|
| 1012 | printf("\n[ERROR] in %s : illegal pointer = %x\n",
|
|---|
| 1013 | __FUNCTION__, ptr );
|
|---|
| 1014 | return NULL;
|
|---|
| 1015 | }
|
|---|
| 1016 |
|
|---|
| 1017 | // compute index in free[] array
|
|---|
| 1018 | int index = (base - store[cxy].store_base) / MALLOC_MIN_BLOCK_SIZE;
|
|---|
| 1019 |
|
|---|
| 1020 | // compute old size
|
|---|
| 1021 | char * pchar = (char *) (store[cxy].alloc_base + index);
|
|---|
| 1022 | unsigned int old_size = (unsigned int)(1 << ((int) *pchar));
|
|---|
| 1023 |
|
|---|
| 1024 | // allocate a new block
|
|---|
| 1025 | void * new_ptr = remote_malloc( size , cxy );
|
|---|
| 1026 |
|
|---|
| 1027 | // save old data to new block
|
|---|
| 1028 | int min_size = (int)((size < old_size) ? size : old_size);
|
|---|
| 1029 | memcpy( new_ptr, ptr, min_size );
|
|---|
| 1030 |
|
|---|
| 1031 | // release old block
|
|---|
| 1032 | remote_free( ptr , cxy );
|
|---|
| 1033 |
|
|---|
| 1034 | return new_ptr;
|
|---|
| 1035 |
|
|---|
| 1036 | } // end remote_realloc()
|
|---|
| 1037 |
|
|---|
| 1038 |
|
|---|
| 1039 | //////////////////////////////////////////////////////
|
|---|
| 1040 | static void update_free_array( malloc_store_t * store,
|
|---|
| 1041 | unsigned int base,
|
|---|
| 1042 | unsigned int size_index )
|
|---|
| 1043 | {
|
|---|
| 1044 | // This recursive function try to merge the released block
|
|---|
| 1045 | // with the companion block if this companion block is free.
|
|---|
| 1046 | // This companion has the same size, and almost the same address
|
|---|
| 1047 | // (only one address bit is different)
|
|---|
| 1048 | // - If the companion is not in free[size_index],
|
|---|
| 1049 | // the released block is pushed in free[size_index].
|
|---|
| 1050 | // - If the companion is found, it is evicted from free[size_index]
|
|---|
| 1051 | // and the merged bloc is pushed in the free[size_index+1].
|
|---|
| 1052 |
|
|---|
| 1053 |
|
|---|
| 1054 | // compute released block size
|
|---|
| 1055 | unsigned int size = 1<<size_index;
|
|---|
| 1056 |
|
|---|
| 1057 | // compute companion block and merged block base addresses
|
|---|
| 1058 | unsigned int companion_base;
|
|---|
| 1059 | unsigned int merged_base;
|
|---|
| 1060 |
|
|---|
| 1061 | if ( (base & size) == 0 ) // the released block is aligned on (2*size)
|
|---|
| 1062 | {
|
|---|
| 1063 | companion_base = base + size;
|
|---|
| 1064 | merged_base = base;
|
|---|
| 1065 | }
|
|---|
| 1066 | else
|
|---|
| 1067 | {
|
|---|
| 1068 | companion_base = base - size;
|
|---|
| 1069 | merged_base = base - size;
|
|---|
| 1070 | }
|
|---|
| 1071 |
|
|---|
| 1072 | // scan all blocks in free[size_index]
|
|---|
| 1073 | // the iter & prev variables are actually addresses
|
|---|
| 1074 | unsigned int found = 0;
|
|---|
| 1075 | unsigned int iter = store->free[size_index];
|
|---|
| 1076 | unsigned int prev = (unsigned int)&store->free[size_index];
|
|---|
| 1077 | while ( iter )
|
|---|
| 1078 | {
|
|---|
| 1079 | if ( iter == companion_base )
|
|---|
| 1080 | {
|
|---|
| 1081 | found = 1;
|
|---|
| 1082 | break;
|
|---|
| 1083 | }
|
|---|
| 1084 | prev = iter;
|
|---|
| 1085 | iter = *(unsigned int*)iter;
|
|---|
| 1086 | }
|
|---|
| 1087 |
|
|---|
| 1088 | if ( found == 0 ) // Companion not found => push in free[size_index]
|
|---|
| 1089 | {
|
|---|
| 1090 | *(unsigned int*)base = store->free[size_index];
|
|---|
| 1091 | store->free[size_index] = base;
|
|---|
| 1092 | }
|
|---|
| 1093 | else // Companion found : merge
|
|---|
| 1094 | {
|
|---|
| 1095 | // evict the searched block from free[size_index]
|
|---|
| 1096 | *(unsigned int*)prev = *(unsigned int*)iter;
|
|---|
| 1097 |
|
|---|
| 1098 | // call the update_free() function for free[size_index+1]
|
|---|
| 1099 | update_free_array( store, merged_base , size_index+1 );
|
|---|
| 1100 | }
|
|---|
| 1101 | } // end update_free_array()
|
|---|
| 1102 |
|
|---|
| 1103 | ////////////////////////////////////
|
|---|
| 1104 | void remote_free( void * ptr,
|
|---|
| 1105 | unsigned int cxy )
|
|---|
| 1106 | {
|
|---|
| 1107 |
|
|---|
| 1108 | #if DEBUG_REMOTE_MALLOC
|
|---|
| 1109 | printf("\n[MALLOC] %s : enter for block = %x / cxy = %x\n",
|
|---|
| 1110 | __FUNCTION__, ptr, cxy );
|
|---|
| 1111 | #endif
|
|---|
| 1112 |
|
|---|
| 1113 | unsigned int base = (unsigned int)ptr;
|
|---|
| 1114 |
|
|---|
| 1115 | // check cxy value
|
|---|
| 1116 | if( cxy >= MALLOC_MAX_CLUSTERS )
|
|---|
| 1117 | {
|
|---|
| 1118 | printf("\n[ERROR] in %s : illegal cluster index %x\n",
|
|---|
| 1119 | __FUNCTION__ , cxy );
|
|---|
| 1120 | return;
|
|---|
| 1121 | }
|
|---|
| 1122 |
|
|---|
| 1123 | // check ptr value
|
|---|
| 1124 | if( (base < store[cxy].store_base) ||
|
|---|
| 1125 | (base >= (store[cxy].store_base + store[cxy].store_size)) )
|
|---|
| 1126 | {
|
|---|
| 1127 | printf("\n[ERROR] in %s : illegal pointer for released block = %x\n",
|
|---|
| 1128 | __FUNCTION__, ptr );
|
|---|
| 1129 | return;
|
|---|
| 1130 | }
|
|---|
| 1131 |
|
|---|
| 1132 | // get the lock protecting store[cxy]
|
|---|
| 1133 | pthread_mutex_lock( &store[cxy].mutex );
|
|---|
| 1134 |
|
|---|
| 1135 | // compute released block index in alloc[] array
|
|---|
| 1136 | unsigned index = (base - store[cxy].store_base ) / MALLOC_MIN_BLOCK_SIZE;
|
|---|
| 1137 |
|
|---|
| 1138 | // get the released block size_index
|
|---|
| 1139 | unsigned char* pchar = (unsigned char*)(store[cxy].alloc_base + index);
|
|---|
| 1140 | unsigned int size_index = (unsigned int)*pchar;
|
|---|
| 1141 |
|
|---|
| 1142 | // check block is allocated
|
|---|
| 1143 | if ( size_index == 0 )
|
|---|
| 1144 | {
|
|---|
| 1145 | pthread_mutex_unlock( &store[cxy].mutex );
|
|---|
| 1146 | printf("\n[ERROR] in %s : released block not allocated / ptr = %x\n",
|
|---|
| 1147 | __FUNCTION__, ptr );
|
|---|
| 1148 | return;
|
|---|
| 1149 | }
|
|---|
| 1150 |
|
|---|
| 1151 | // check released block alignment
|
|---|
| 1152 | if ( base % (1 << size_index) )
|
|---|
| 1153 | {
|
|---|
| 1154 | pthread_mutex_unlock( &store[cxy].mutex );
|
|---|
| 1155 | printf("\n[ERROR] in %s : released block not aligned / ptr = %x\n",
|
|---|
| 1156 | __FUNCTION__, ptr );
|
|---|
| 1157 | return;
|
|---|
| 1158 | }
|
|---|
| 1159 |
|
|---|
| 1160 | // reset the alloc[index] entry
|
|---|
| 1161 | *pchar = 0;
|
|---|
| 1162 |
|
|---|
| 1163 | // call the recursive function update_free_array()
|
|---|
| 1164 | update_free_array( &store[cxy], base, size_index );
|
|---|
| 1165 |
|
|---|
| 1166 | // release the lock
|
|---|
| 1167 | pthread_mutex_unlock( &store[cxy].mutex );
|
|---|
| 1168 |
|
|---|
| 1169 | #if DEBUG_REMOTE_MALLOC
|
|---|
| 1170 | printf("\n[MALLOC] %s : conmpletes for block = %x / cxy = %x\n",
|
|---|
| 1171 | __FUNCTION__, ptr, cxy );
|
|---|
| 1172 | #endif
|
|---|
| 1173 |
|
|---|
| 1174 | } // end remote_free()
|
|---|
| 1175 |
|
|---|
| 1176 | /////////////////////////////////////////////////////////////////////////////////////////
|
|---|
| 1177 | /////////////// non standard pthread_parallel_create //////////////////////////////
|
|---|
| 1178 | /////////////////////////////////////////////////////////////////////////////////////////
|
|---|
| 1179 |
|
|---|
| 1180 | #define X_MAX 16 // max number of clusters in a row
|
|---|
| 1181 | #define Y_MAX 16 // max number of clusters in a column
|
|---|
| 1182 | #define CLUSTERS_MAX X_MAX * Y_MAX // max number of clusters
|
|---|
| 1183 | #define LEVEL_MAX 5 // max level of DQT
|
|---|
| 1184 | #define CORES_MAX 4 // max number of cores per cluster
|
|---|
| 1185 |
|
|---|
| 1186 | /////////////////////////////////////////////////////////////////////////////////////////
|
|---|
| 1187 | // Global variables
|
|---|
| 1188 | //
|
|---|
| 1189 | // WARNING : arguments of the pthread_create() function MUST be global variables.
|
|---|
| 1190 | /////////////////////////////////////////////////////////////////////////////////////////
|
|---|
| 1191 |
|
|---|
| 1192 | // 2D array of <build> threads attributes / indexed by [cid][level]
|
|---|
| 1193 | __attribute__((aligned(4096)))
|
|---|
| 1194 | pthread_attr_t pthread_build_attr[CLUSTERS_MAX][LEVEL_MAX];
|
|---|
| 1195 |
|
|---|
| 1196 | // 2D array of <build> threads arguments / indexed by [cid][level]
|
|---|
| 1197 | __attribute__((aligned(4096)))
|
|---|
| 1198 | pthread_parallel_build_args_t pthread_build_args[CLUSTERS_MAX][LEVEL_MAX];
|
|---|
| 1199 |
|
|---|
| 1200 | // 1D array of <work> threads attributes / indexed by [tid]
|
|---|
| 1201 | __attribute__((aligned(4096)))
|
|---|
| 1202 | pthread_attr_t pthread_work_attr[CLUSTERS_MAX * CORES_MAX];
|
|---|
| 1203 |
|
|---|
| 1204 | // 1D array of <work> threads arguments / indexed by [tid]
|
|---|
| 1205 | __attribute__((aligned(4096)))
|
|---|
| 1206 | pthread_parallel_work_args_t pthread_work_args[CLUSTERS_MAX * CORES_MAX];
|
|---|
| 1207 |
|
|---|
| 1208 | // kernel thread identifier / unused, but required by pthread_create()
|
|---|
| 1209 | __attribute__((aligned(4096)))
|
|---|
| 1210 | pthread_t trdid;
|
|---|
| 1211 |
|
|---|
| 1212 | ///////////////////////////////////////////////////////////////////////////
|
|---|
| 1213 | static void pthread_recursive_build( pthread_parallel_build_args_t * args )
|
|---|
| 1214 | {
|
|---|
| 1215 |
|
|---|
| 1216 | // get arguments
|
|---|
| 1217 | unsigned int cid = args->cid;
|
|---|
| 1218 | unsigned int level = args->level;
|
|---|
| 1219 | unsigned int parent_cid = args->parent_cid;
|
|---|
| 1220 | pthread_barrier_t * parent_barrier = args->parent_barrier;
|
|---|
| 1221 | unsigned int root_level = args->root_level;
|
|---|
| 1222 | void * work_func = args->work_func;
|
|---|
| 1223 | unsigned int x_size = args->x_size;
|
|---|
| 1224 | unsigned int y_size = args->y_size;
|
|---|
| 1225 | unsigned int ncores = args->ncores;
|
|---|
| 1226 |
|
|---|
| 1227 | #if DEBUG_PTHREAD_PARALLEL
|
|---|
| 1228 | printf("\n[%s] <build> thread[%d][%d] enters / parent_cid %d / work_func %x\n",
|
|---|
| 1229 | __FUNCTION__, cid , level , parent_cid , work_func );
|
|---|
| 1230 | #endif
|
|---|
| 1231 |
|
|---|
| 1232 | // set error default value in pthread_build_args[cid][level]
|
|---|
| 1233 | pthread_build_args[cid][level].error = 0;
|
|---|
| 1234 |
|
|---|
| 1235 | // get cxy from cid
|
|---|
| 1236 | unsigned int cxy = HAL_CXY_FROM_XY( cid / y_size , cid % y_size );
|
|---|
| 1237 |
|
|---|
| 1238 | // allocate the parent/child barrier in local cluster
|
|---|
| 1239 | pthread_barrier_t * barrier = (pthread_barrier_t *)malloc( sizeof(pthread_barrier_t) );
|
|---|
| 1240 |
|
|---|
| 1241 | if( barrier == NULL )
|
|---|
| 1242 | {
|
|---|
| 1243 | printf("\n[ERROR] in %s : cannot allocate barrier for <build> thread[%d][%d]\n",
|
|---|
| 1244 | __FUNCTION__ , cid , level );
|
|---|
| 1245 |
|
|---|
| 1246 | // report error to parent
|
|---|
| 1247 | pthread_build_args[parent_cid][level+1].error = 1;
|
|---|
| 1248 | }
|
|---|
| 1249 |
|
|---|
| 1250 | ///////////////////////////////////////////////////////////
|
|---|
| 1251 | if( level == 0 ) // children are <work> threads
|
|---|
| 1252 | {
|
|---|
| 1253 |
|
|---|
| 1254 | // check number of cores in local cluster
|
|---|
| 1255 | unsigned int actual_ncores;
|
|---|
| 1256 | get_nb_cores( cxy , &actual_ncores );
|
|---|
| 1257 |
|
|---|
| 1258 | if( actual_ncores != ncores )
|
|---|
| 1259 | {
|
|---|
| 1260 | printf("\n[ERROR] in %s : actual_ncores (%d) in cluster %x\n",
|
|---|
| 1261 | __FUNCTION__ , actual_ncores, cxy );
|
|---|
| 1262 |
|
|---|
| 1263 | // report error to parent
|
|---|
| 1264 | pthread_build_args[parent_cid][level+1].error = 1;
|
|---|
| 1265 | }
|
|---|
| 1266 |
|
|---|
| 1267 | // initializes barrier for (ncores + 1) in flat mode
|
|---|
| 1268 | if( pthread_barrier_init( barrier , NULL , ncores + 1 ) )
|
|---|
| 1269 | {
|
|---|
| 1270 | printf("\n[ERROR] in %s : cannot init barrier for <build> thread[%d][%d]\n",
|
|---|
| 1271 | __FUNCTION__ , cid , level );
|
|---|
| 1272 |
|
|---|
| 1273 | // report error to parent
|
|---|
| 1274 | pthread_build_args[parent_cid][level+1].error = 1;
|
|---|
| 1275 | }
|
|---|
| 1276 |
|
|---|
| 1277 | #if DEBUG_PTHREAD_PARALLEL
|
|---|
| 1278 | printf("\n[%s] <build> thread[%d][%d] initialized barrier / %d children\n",
|
|---|
| 1279 | __FUNCTION__, cid, level, ncores );
|
|---|
| 1280 | #endif
|
|---|
| 1281 | unsigned int lid; // core local index for <work> thread
|
|---|
| 1282 | unsigned int tid; // <work> thread continuous index
|
|---|
| 1283 |
|
|---|
| 1284 | // <build> thread creates ncores <work> threads
|
|---|
| 1285 | for ( lid = 0 ; lid < ncores ; lid++ )
|
|---|
| 1286 | {
|
|---|
| 1287 | // compute work thread tid
|
|---|
| 1288 | tid = (cid * ncores) + lid;
|
|---|
| 1289 |
|
|---|
| 1290 | // set attributes for <work> thread[tid]
|
|---|
| 1291 | pthread_work_attr[tid].attributes = PT_ATTR_DETACH |
|
|---|
| 1292 | PT_ATTR_CLUSTER_DEFINED |
|
|---|
| 1293 | PT_ATTR_CORE_DEFINED;
|
|---|
| 1294 | pthread_work_attr[tid].cxy = cxy;
|
|---|
| 1295 | pthread_work_attr[tid].lid = lid;
|
|---|
| 1296 |
|
|---|
| 1297 | // set tid and barrier arguments for <work> thread[tid]
|
|---|
| 1298 | pthread_work_args[tid].tid = tid;
|
|---|
| 1299 | pthread_work_args[tid].barrier = barrier;
|
|---|
| 1300 |
|
|---|
| 1301 | // create <work> thread
|
|---|
| 1302 | if ( pthread_create( &trdid, // unused
|
|---|
| 1303 | &pthread_work_attr[tid],
|
|---|
| 1304 | work_func,
|
|---|
| 1305 | &pthread_work_args[tid] ) )
|
|---|
| 1306 | {
|
|---|
| 1307 | printf("\n[ERROR] in %s : <build> thread[%d][%d] cannot create <work> thread[%d]\n",
|
|---|
| 1308 | __FUNCTION__ , cid , level , tid );
|
|---|
| 1309 |
|
|---|
| 1310 | // report error to parent
|
|---|
| 1311 | pthread_build_args[parent_cid][level+1].error = 1;
|
|---|
| 1312 | }
|
|---|
| 1313 |
|
|---|
| 1314 | #if DEBUG_PTHREAD_PARALLEL
|
|---|
| 1315 | printf("\n[%s] <build> thread[%d][%d] created <work> thread[%d]\n",
|
|---|
| 1316 | __FUNCTION__, cid, level, tid );
|
|---|
| 1317 | #endif
|
|---|
| 1318 | }
|
|---|
| 1319 |
|
|---|
| 1320 | // wait on barrier until all <work> children threads completed
|
|---|
| 1321 | if( pthread_barrier_wait( barrier ) )
|
|---|
| 1322 | {
|
|---|
| 1323 | printf("\n[ERROR] in %s / barrier for <build> thread[%x][%d]\n",
|
|---|
| 1324 | __FUNCTION__ , cid , level );
|
|---|
| 1325 |
|
|---|
| 1326 | // report error to parent
|
|---|
| 1327 | pthread_build_args[parent_cid][level+1].error = 1;
|
|---|
| 1328 | }
|
|---|
| 1329 |
|
|---|
| 1330 | #if DEBUG_PTHREAD_PARALLEL
|
|---|
| 1331 | printf("\n[%s] <build> thread[%d][%d] resume after children completion\n",
|
|---|
| 1332 | __FUNCTION__ , cid , level );
|
|---|
| 1333 | #endif
|
|---|
| 1334 |
|
|---|
| 1335 | } // end level == 0
|
|---|
| 1336 |
|
|---|
| 1337 | ////////////////////////////////////////////////////////////
|
|---|
| 1338 | else // children are "build" threads
|
|---|
| 1339 | {
|
|---|
| 1340 | // the 4 children threads can be linked to any core in each
|
|---|
| 1341 | // sub-macro-cluster[i][j] with [ij] in {00,01,10,11}
|
|---|
| 1342 |
|
|---|
| 1343 | unsigned int parent_x; // X coordinate of parent macro-cluster
|
|---|
| 1344 | unsigned int parent_y; // Y coordinate of parent macro-cluster
|
|---|
| 1345 | unsigned int child_x; // X coordinate of child macro-cluster
|
|---|
| 1346 | unsigned int child_y; // Y coordinate of child macro-cluster
|
|---|
| 1347 | unsigned int child_cid[2][2]; // selected cluster cid for child[i][j]
|
|---|
| 1348 | unsigned int child_cxy[2][2]; // selected cluster cxy for child[i][j]
|
|---|
| 1349 | unsigned int child_lid[2][2]; // selected core index for child[i][j]
|
|---|
| 1350 | int child_sts[2][2]; // -1 if error / 0 if success / +1 if no core
|
|---|
| 1351 | unsigned int i; // loop index for children
|
|---|
| 1352 | unsigned int j; // loop index for children
|
|---|
| 1353 |
|
|---|
| 1354 | unsigned int nb_children = 0; // actual number of children (can be < 4)
|
|---|
| 1355 |
|
|---|
| 1356 | // get parent macro-cluster mask and half-size from level
|
|---|
| 1357 | unsigned int mask = (1 << level) - 1;
|
|---|
| 1358 | unsigned int half = (level > 0) ? (1 << (level - 1)) : 0;
|
|---|
| 1359 |
|
|---|
| 1360 | // get parent macro-cluster coordinates
|
|---|
| 1361 | parent_x = HAL_X_FROM_CXY( cxy ) & ~mask;
|
|---|
| 1362 | parent_y = HAL_Y_FROM_CXY( cxy ) & ~mask;
|
|---|
| 1363 |
|
|---|
| 1364 | // First step : select core for each child thread
|
|---|
| 1365 | for (i = 0 ; i < 2 ; i++)
|
|---|
| 1366 | {
|
|---|
| 1367 | // compute child macro-cluster X coordinate
|
|---|
| 1368 | child_x = (i == 0) ? parent_x : (parent_x + half);
|
|---|
| 1369 |
|
|---|
| 1370 | for (j = 0 ; j < 2 ; j++)
|
|---|
| 1371 | {
|
|---|
| 1372 | // compute child macro-cluster Y coordinate
|
|---|
| 1373 | child_y = (j == 0) ? parent_y : (parent_y + half);
|
|---|
| 1374 |
|
|---|
| 1375 | // select the best core in macro-cluster
|
|---|
| 1376 | unsigned int best_cxy;
|
|---|
| 1377 | unsigned int best_lid;
|
|---|
| 1378 |
|
|---|
| 1379 | child_sts[i][j] = get_best_core( HAL_CXY_FROM_XY( child_x , child_y ),
|
|---|
| 1380 | level-1,
|
|---|
| 1381 | &best_cxy,
|
|---|
| 1382 | &best_lid );
|
|---|
| 1383 |
|
|---|
| 1384 | if( child_sts[i][j] < 0 ) // failure => report error
|
|---|
| 1385 | {
|
|---|
| 1386 | printf("\n[ERROR] in %s : child[%d,%d] of <build> thread[%d,%d]\n",
|
|---|
| 1387 | __FUNCTION__ , i , j , cid , level );
|
|---|
| 1388 |
|
|---|
| 1389 | // report error to parent
|
|---|
| 1390 | pthread_build_args[parent_cid][level+1].error = 1;
|
|---|
| 1391 | }
|
|---|
| 1392 | else if (child_sts[i][j] > 0 ) // macro-cluster empty => does nothing
|
|---|
| 1393 | {
|
|---|
| 1394 | }
|
|---|
| 1395 | else // core found
|
|---|
| 1396 | {
|
|---|
| 1397 | child_cxy[i][j] = best_cxy;
|
|---|
| 1398 | child_lid[i][j] = best_lid;
|
|---|
| 1399 | child_cid[i][j] = (HAL_X_FROM_CXY(best_cxy) * y_size) + HAL_Y_FROM_CXY( best_cxy);
|
|---|
| 1400 | nb_children++;
|
|---|
| 1401 |
|
|---|
| 1402 | #if DEBUG_PTHREAD_PARALLEL
|
|---|
| 1403 | printf("\n[%s] <build> thread[%d][%d] select core[%x][%d] for child[%d][%d]\n",
|
|---|
| 1404 | __FUNCTION__ , cid , level , best_cxy , best_lid , i , j );
|
|---|
| 1405 | #endif
|
|---|
| 1406 |
|
|---|
| 1407 | }
|
|---|
| 1408 | } // end for j
|
|---|
| 1409 | } // end for i
|
|---|
| 1410 |
|
|---|
| 1411 | // second step : initialize barrier for (nb_children + 1) in flat mode
|
|---|
| 1412 | if( pthread_barrier_init( barrier , NULL , nb_children + 1 ) )
|
|---|
| 1413 | {
|
|---|
| 1414 | printf("\n[ERROR] in %s : cannot init barrier for <build> thread[%d][%d]\n",
|
|---|
| 1415 | __FUNCTION__ , cid , level );
|
|---|
| 1416 |
|
|---|
| 1417 | // report error to parent
|
|---|
| 1418 | pthread_build_args[parent_cid][level+1].error = 1;
|
|---|
| 1419 | }
|
|---|
| 1420 |
|
|---|
| 1421 | #if DEBUG_PTHREAD_PARALLEL
|
|---|
| 1422 | printf("\n[%s] <build> thread[%d][%d] initialized barrier / %d children\n",
|
|---|
| 1423 | __FUNCTION__, cid, level, nb_children );
|
|---|
| 1424 | #endif
|
|---|
| 1425 |
|
|---|
| 1426 | // Third step : actually create the children threads
|
|---|
| 1427 | for (i = 0 ; i < 2 ; i++)
|
|---|
| 1428 | {
|
|---|
| 1429 | for (j = 0 ; j < 2 ; j++)
|
|---|
| 1430 | {
|
|---|
| 1431 | // thread is created only if macro-cluster is active
|
|---|
| 1432 | if( child_sts[i][j] == 0 )
|
|---|
| 1433 | {
|
|---|
| 1434 | unsigned int tgt_cid = child_cid[i][j];
|
|---|
| 1435 | unsigned int tgt_lid = child_lid[i][j];
|
|---|
| 1436 | unsigned int tgt_cxy = child_cxy[i][j];
|
|---|
| 1437 |
|
|---|
| 1438 | // set child thread attributes
|
|---|
| 1439 | pthread_build_attr[tgt_cid][level-1].attributes = PT_ATTR_DETACH |
|
|---|
| 1440 | PT_ATTR_CLUSTER_DEFINED |
|
|---|
| 1441 | PT_ATTR_CORE_DEFINED;
|
|---|
| 1442 | pthread_build_attr[tgt_cid][level-1].cxy = tgt_cxy;
|
|---|
| 1443 | pthread_build_attr[tgt_cid][level-1].lid = tgt_lid;
|
|---|
| 1444 |
|
|---|
| 1445 | // propagate build function arguments from parent to child
|
|---|
| 1446 | pthread_build_args[tgt_cid][level-1].cid = tgt_cid;
|
|---|
| 1447 | pthread_build_args[tgt_cid][level-1].level = level-1;
|
|---|
| 1448 | pthread_build_args[tgt_cid][level-1].parent_cid = cid;
|
|---|
| 1449 | pthread_build_args[tgt_cid][level-1].parent_barrier = barrier;
|
|---|
| 1450 | pthread_build_args[tgt_cid][level-1].root_level = root_level;
|
|---|
| 1451 | pthread_build_args[tgt_cid][level-1].work_func = work_func;
|
|---|
| 1452 | pthread_build_args[tgt_cid][level-1].x_size = x_size;
|
|---|
| 1453 | pthread_build_args[tgt_cid][level-1].y_size = y_size;
|
|---|
| 1454 | pthread_build_args[tgt_cid][level-1].ncores = ncores;
|
|---|
| 1455 |
|
|---|
| 1456 | // create thread
|
|---|
| 1457 | if( pthread_create( &trdid,
|
|---|
| 1458 | &pthread_build_attr[tgt_cid][level-1],
|
|---|
| 1459 | &pthread_recursive_build,
|
|---|
| 1460 | &pthread_build_args[tgt_cid][level-1] ) )
|
|---|
| 1461 | {
|
|---|
| 1462 | printf("\n[ERROR] in %s : cannot create <build> thread[%x][%d]\n",
|
|---|
| 1463 | __FUNCTION__ , child_cid , level -1 );
|
|---|
| 1464 |
|
|---|
| 1465 | // report error to parent
|
|---|
| 1466 | pthread_build_args[parent_cid][level+1].error = 1;
|
|---|
| 1467 | }
|
|---|
| 1468 |
|
|---|
| 1469 | #if DEBUG_PTHREAD_PARALLEL
|
|---|
| 1470 | printf("\n[%s] <build> thread[%d][%d] created <build> thread[%d][%d] on core[%x,%d]\n",
|
|---|
| 1471 | __FUNCTION__, cid, level, tgt_cid, (level - 1), tgt_cxy, tgt_lid );
|
|---|
| 1472 | #endif
|
|---|
| 1473 | } //end if sts[x][y]
|
|---|
| 1474 | } // end for y
|
|---|
| 1475 | } // end for x
|
|---|
| 1476 |
|
|---|
| 1477 | // wait on barrier until all <build> children threads completed
|
|---|
| 1478 | if( pthread_barrier_wait( barrier ) )
|
|---|
| 1479 | {
|
|---|
| 1480 | printf("\n[ERROR] in %s / barrier for <build> thread[%d][%d]\n",
|
|---|
| 1481 | __FUNCTION__ , cid , level );
|
|---|
| 1482 |
|
|---|
| 1483 | // report error to parent
|
|---|
| 1484 | pthread_build_args[parent_cid][level+1].error = 1;
|
|---|
| 1485 | }
|
|---|
| 1486 |
|
|---|
| 1487 | #if DEBUG_PTHREAD_PARALLEL
|
|---|
| 1488 | printf("\n[%s] <build> thread[%x][%d] resume after children completion\n",
|
|---|
| 1489 | __FUNCTION__, cid, level );
|
|---|
| 1490 | #endif
|
|---|
| 1491 |
|
|---|
| 1492 | } // end level > 0
|
|---|
| 1493 |
|
|---|
| 1494 | // report error to parent when required
|
|---|
| 1495 | if( pthread_build_args[cid][level].error )
|
|---|
| 1496 | {
|
|---|
| 1497 | pthread_build_args[parent_cid][level+1].error = 1;
|
|---|
| 1498 | }
|
|---|
| 1499 |
|
|---|
| 1500 | // all <build> threads - but the root - signal completion to parent thread and exit
|
|---|
| 1501 | if( level < root_level )
|
|---|
| 1502 | {
|
|---|
| 1503 | if( pthread_barrier_wait( parent_barrier ) )
|
|---|
| 1504 | {
|
|---|
| 1505 | printf("\n[ERROR] in %s / parent barrier for <build> thread[%d][%d]\n",
|
|---|
| 1506 | __FUNCTION__ , cid , level );
|
|---|
| 1507 |
|
|---|
| 1508 | // report error to parent
|
|---|
| 1509 | pthread_build_args[parent_cid][level+1].error = 1;
|
|---|
| 1510 | }
|
|---|
| 1511 |
|
|---|
| 1512 | #if DEBUG_PTHREAD_PARALLEL
|
|---|
| 1513 | printf("\n[%s] <build> thread[%x][%d] exit\n",
|
|---|
| 1514 | __FUNCTION__, cid , level );
|
|---|
| 1515 | #endif
|
|---|
| 1516 | // <build> thread exit
|
|---|
| 1517 | pthread_exit( NULL );
|
|---|
| 1518 | }
|
|---|
| 1519 | } // end pthread_recursive_build()
|
|---|
| 1520 |
|
|---|
| 1521 |
|
|---|
| 1522 | //////////////////////////////////////////////////////
|
|---|
| 1523 | int pthread_parallel_create( unsigned int root_level,
|
|---|
| 1524 | void * work_func )
|
|---|
| 1525 | {
|
|---|
| 1526 |
|
|---|
| 1527 | #if DEBUG_PTHREAD_PARALLEL
|
|---|
| 1528 | printf("\n[%s] enter / root_level %d / func %x\n",
|
|---|
| 1529 | __FUNCTION__, root_level, work_func );
|
|---|
| 1530 | #endif
|
|---|
| 1531 |
|
|---|
| 1532 | // get platform parameters
|
|---|
| 1533 | hard_config_t config;
|
|---|
| 1534 | get_config( &config );
|
|---|
| 1535 | unsigned int x_size = config.x_size;
|
|---|
| 1536 | unsigned int y_size = config.y_size;
|
|---|
| 1537 | unsigned int ncores = config.ncores;
|
|---|
| 1538 |
|
|---|
| 1539 | // get calling thread cluster identifier
|
|---|
| 1540 | unsigned int root_cxy;
|
|---|
| 1541 | unsigned int root_lid; // unused, but required by get_core_id()
|
|---|
| 1542 | get_core_id( &root_cxy , &root_lid );
|
|---|
| 1543 |
|
|---|
| 1544 | // get calling thread continuous index
|
|---|
| 1545 | unsigned int x = HAL_X_FROM_CXY( root_cxy );
|
|---|
| 1546 | unsigned int y = HAL_Y_FROM_CXY( root_cxy );
|
|---|
| 1547 | unsigned int root_cid = (y_size * x) + y;
|
|---|
| 1548 |
|
|---|
| 1549 | // set the build function arguments for the root <build> thread
|
|---|
| 1550 | pthread_build_args[root_cid][root_level].cid = root_cid;
|
|---|
| 1551 | pthread_build_args[root_cid][root_level].level = root_level;
|
|---|
| 1552 | pthread_build_args[root_cid][root_level].parent_cid = -1;
|
|---|
| 1553 | pthread_build_args[root_cid][root_level].parent_barrier = NULL;
|
|---|
| 1554 | pthread_build_args[root_cid][root_level].root_level = root_level;
|
|---|
| 1555 | pthread_build_args[root_cid][root_level].work_func = work_func;
|
|---|
| 1556 | pthread_build_args[root_cid][root_level].x_size = x_size;
|
|---|
| 1557 | pthread_build_args[root_cid][root_level].y_size = y_size;
|
|---|
| 1558 | pthread_build_args[root_cid][root_level].ncores = ncores;
|
|---|
| 1559 |
|
|---|
| 1560 | // call the recursive function
|
|---|
| 1561 | pthread_recursive_build( &pthread_build_args[root_cid][root_level] );
|
|---|
| 1562 |
|
|---|
| 1563 | // check error when execution completes
|
|---|
| 1564 | if( pthread_build_args[root_cid][root_level].error )
|
|---|
| 1565 | {
|
|---|
| 1566 | printf("\n[error] in %s\n", __FUNCTION__ );
|
|---|
| 1567 | return -1;
|
|---|
| 1568 | }
|
|---|
| 1569 |
|
|---|
| 1570 | return 0;
|
|---|
| 1571 |
|
|---|
| 1572 | } // end pthread_parallel_create()
|
|---|
| 1573 |
|
|---|
| 1574 | /////////////////////////////////////////////////////////////////////////////////////////
|
|---|
| 1575 | /////////////// non standard Frame Buffer related syscalls
|
|---|
| 1576 | /////////////////////////////////////////////////////////////////////////////////////////
|
|---|
| 1577 |
|
|---|
| 1578 | ////////////////////////////////
|
|---|
| 1579 | int fbf_get_config( int * width,
|
|---|
| 1580 | int * height,
|
|---|
| 1581 | int * type )
|
|---|
| 1582 | {
|
|---|
| 1583 | return hal_user_syscall( SYS_FBF,
|
|---|
| 1584 | (reg_t)FBF_GET_CONFIG,
|
|---|
| 1585 | (reg_t)width,
|
|---|
| 1586 | (reg_t)height,
|
|---|
| 1587 | (reg_t)type );
|
|---|
| 1588 | }
|
|---|
| 1589 |
|
|---|
| 1590 | ////////////////////////////
|
|---|
| 1591 | int fbf_read( void * buffer,
|
|---|
| 1592 | int length,
|
|---|
| 1593 | int offset )
|
|---|
| 1594 | {
|
|---|
| 1595 | printf("[WARNING] the <%s> syscall is deprecated\n", __FUNCTION__ );
|
|---|
| 1596 |
|
|---|
| 1597 | return hal_user_syscall( SYS_FBF,
|
|---|
| 1598 | (reg_t)FBF_DIRECT_READ,
|
|---|
| 1599 | (reg_t)buffer,
|
|---|
| 1600 | (reg_t)length,
|
|---|
| 1601 | (reg_t)offset );
|
|---|
| 1602 | }
|
|---|
| 1603 |
|
|---|
| 1604 | /////////////////////////////
|
|---|
| 1605 | int fbf_write( void * buffer,
|
|---|
| 1606 | int length,
|
|---|
| 1607 | int offset )
|
|---|
| 1608 | {
|
|---|
| 1609 | printf("[WARNING] the <%s> syscall is deprecated\n", __FUNCTION__ );
|
|---|
| 1610 |
|
|---|
| 1611 | return hal_user_syscall( SYS_FBF,
|
|---|
| 1612 | (reg_t)FBF_DIRECT_WRITE,
|
|---|
| 1613 | (reg_t)buffer,
|
|---|
| 1614 | (reg_t)length,
|
|---|
| 1615 | (reg_t)offset );
|
|---|
| 1616 | }
|
|---|
| 1617 |
|
|---|
| 1618 | //////////////////////////////////////
|
|---|
| 1619 | int fbf_create_window( int l_zero,
|
|---|
| 1620 | int p_zero,
|
|---|
| 1621 | int nlines,
|
|---|
| 1622 | int npixels,
|
|---|
| 1623 | void ** buffer )
|
|---|
| 1624 | {
|
|---|
| 1625 | return hal_user_syscall( SYS_FBF,
|
|---|
| 1626 | (reg_t)FBF_CREATE_WINDOW,
|
|---|
| 1627 | (reg_t)((l_zero << 16) | p_zero),
|
|---|
| 1628 | (reg_t)((nlines << 16) | npixels),
|
|---|
| 1629 | (reg_t)buffer );
|
|---|
| 1630 | }
|
|---|
| 1631 |
|
|---|
| 1632 | ///////////////////////////////
|
|---|
| 1633 | int fbf_active_window( int wid,
|
|---|
| 1634 | int active )
|
|---|
| 1635 | {
|
|---|
| 1636 | return hal_user_syscall( SYS_FBF,
|
|---|
| 1637 | (reg_t)FBF_ACTIVE_WINDOW,
|
|---|
| 1638 | (reg_t)wid,
|
|---|
| 1639 | (reg_t)active, 0 );
|
|---|
| 1640 | }
|
|---|
| 1641 |
|
|---|
| 1642 | /////////////////////////////////
|
|---|
| 1643 | int fbf_delete_window( int wid )
|
|---|
| 1644 | {
|
|---|
| 1645 | return hal_user_syscall( SYS_FBF,
|
|---|
| 1646 | (reg_t)FBF_DELETE_WINDOW,
|
|---|
| 1647 | (reg_t)wid, 0, 0 );
|
|---|
| 1648 | }
|
|---|
| 1649 |
|
|---|
| 1650 | //////////////////////////////
|
|---|
| 1651 | int fbf_move_window( int wid,
|
|---|
| 1652 | int l_zero,
|
|---|
| 1653 | int p_zero )
|
|---|
| 1654 | {
|
|---|
| 1655 | return hal_user_syscall( SYS_FBF,
|
|---|
| 1656 | (reg_t)FBF_MOVE_WINDOW,
|
|---|
| 1657 | (reg_t)wid,
|
|---|
| 1658 | (reg_t)l_zero,
|
|---|
| 1659 | (reg_t)p_zero );
|
|---|
| 1660 | }
|
|---|
| 1661 |
|
|---|
| 1662 | ////////////////////////////////
|
|---|
| 1663 | int fbf_resize_window( int wid,
|
|---|
| 1664 | int width,
|
|---|
| 1665 | int height )
|
|---|
| 1666 | {
|
|---|
| 1667 | return hal_user_syscall( SYS_FBF,
|
|---|
| 1668 | (reg_t)FBF_RESIZE_WINDOW,
|
|---|
| 1669 | (reg_t)wid,
|
|---|
| 1670 | (reg_t)width,
|
|---|
| 1671 | (reg_t)height );
|
|---|
| 1672 | }
|
|---|
| 1673 |
|
|---|
| 1674 | /////////////////////////////////
|
|---|
| 1675 | int fbf_refresh_window( int wid,
|
|---|
| 1676 | int line_first,
|
|---|
| 1677 | int line_last )
|
|---|
| 1678 | {
|
|---|
| 1679 | return hal_user_syscall( SYS_FBF,
|
|---|
| 1680 | (reg_t)FBF_REFRESH_WINDOW,
|
|---|
| 1681 | (reg_t)wid,
|
|---|
| 1682 | (reg_t)line_first,
|
|---|
| 1683 | (reg_t)line_last );
|
|---|
| 1684 | }
|
|---|
| 1685 |
|
|---|
| 1686 | /////////////////////////////////
|
|---|
| 1687 | int fbf_front_window( int wid )
|
|---|
| 1688 | {
|
|---|
| 1689 | return hal_user_syscall( SYS_FBF,
|
|---|
| 1690 | (reg_t)FBF_FRONT_WINDOW,
|
|---|
| 1691 | (reg_t)wid, 0, 0 );
|
|---|
| 1692 | }
|
|---|
| 1693 |
|
|---|
| 1694 | // Local Variables:
|
|---|
| 1695 | // tab-width: 4
|
|---|
| 1696 | // c-basic-offset: 4
|
|---|
| 1697 | // c-file-offsets:((innamespace . 0)(inline-open . 0))
|
|---|
| 1698 | // indent-tabs-mode: nil
|
|---|
| 1699 | // End:
|
|---|
| 1700 | // vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
|
|---|
| 1701 |
|
|---|
| 1702 |
|
|---|
| 1703 |
|
|---|