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