| 1 | /* | 
|---|
| 2 |  * cluster.c - Cluster-Manager related operations | 
|---|
| 3 |  * | 
|---|
| 4 |  * Author  Ghassan Almaless (2008,2009,2010,2011,2012) | 
|---|
| 5 |  *         Mohamed Lamine Karaoui (2015) | 
|---|
| 6 |  *         Alain Greiner (2016,2017) | 
|---|
| 7 |  * | 
|---|
| 8 |  * Copyright (c) UPMC Sorbonne Universites | 
|---|
| 9 |  * | 
|---|
| 10 |  * This file is part of ALMOS-MKH.. | 
|---|
| 11 |  * | 
|---|
| 12 |  * ALMOS-MKH. is free software; you can redistribute it and/or modify it | 
|---|
| 13 |  * under the terms of the GNU General Public License as published by | 
|---|
| 14 |  * the Free Software Foundation; version 2.0 of the License. | 
|---|
| 15 |  * | 
|---|
| 16 |  * ALMOS-MKH. is distributed in the hope that it will be useful, but | 
|---|
| 17 |  * WITHOUT ANY WARRANTY; without even the implied warranty of | 
|---|
| 18 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|---|
| 19 |  * General Public License for more details. | 
|---|
| 20 |  * | 
|---|
| 21 |  * You should have received a copy of the GNU General Public License | 
|---|
| 22 |  * along with ALMOS-MKH.; if not, write to the Free Software Foundation, | 
|---|
| 23 |  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 
|---|
| 24 |  */ | 
|---|
| 25 |  | 
|---|
| 26 | #include <kernel_config.h> | 
|---|
| 27 | #include <hal_types.h> | 
|---|
| 28 | #include <hal_atomic.h> | 
|---|
| 29 | #include <hal_special.h> | 
|---|
| 30 | #include <hal_ppm.h> | 
|---|
| 31 | #include <remote_fifo.h> | 
|---|
| 32 | #include <printk.h> | 
|---|
| 33 | #include <errno.h> | 
|---|
| 34 | #include <spinlock.h> | 
|---|
| 35 | #include <core.h> | 
|---|
| 36 | #include <scheduler.h> | 
|---|
| 37 | #include <list.h> | 
|---|
| 38 | #include <cluster.h> | 
|---|
| 39 | #include <boot_info.h> | 
|---|
| 40 | #include <bits.h> | 
|---|
| 41 | #include <ppm.h> | 
|---|
| 42 | #include <thread.h> | 
|---|
| 43 | #include <kmem.h> | 
|---|
| 44 | #include <process.h> | 
|---|
| 45 | #include <dqdt.h> | 
|---|
| 46 |  | 
|---|
| 47 | ///////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 48 | // Extern global variables | 
|---|
| 49 | ///////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 50 |  | 
|---|
| 51 | extern process_t process_zero;     // allocated in kernel_init.c file | 
|---|
| 52 |  | 
|---|
| 53 |  | 
|---|
| 54 | ///////////////////////////////////////////////// | 
|---|
| 55 | error_t cluster_init( struct boot_info_s * info ) | 
|---|
| 56 | { | 
|---|
| 57 |     error_t         error; | 
|---|
| 58 |     lpid_t          lpid;     // local process_index | 
|---|
| 59 |     lid_t           lid;      // local core index | 
|---|
| 60 |     uint32_t        i;        // index in loop on external peripherals | 
|---|
| 61 |     boot_device_t * dev;      // pointer on external peripheral | 
|---|
| 62 |     uint32_t        func;     // external peripheral functionnal type | 
|---|
| 63 |  | 
|---|
| 64 |         cluster_t * cluster = LOCAL_CLUSTER; | 
|---|
| 65 |  | 
|---|
| 66 |     // initialize cluster global parameters | 
|---|
| 67 |         cluster->paddr_width     = info->paddr_width; | 
|---|
| 68 |         cluster->x_width         = info->x_width; | 
|---|
| 69 |         cluster->y_width         = info->y_width; | 
|---|
| 70 |         cluster->x_size          = info->x_size; | 
|---|
| 71 |         cluster->y_size          = info->y_size; | 
|---|
| 72 |         cluster->io_cxy          = info->io_cxy; | 
|---|
| 73 |  | 
|---|
| 74 |     // initialize external peripherals channels | 
|---|
| 75 |     for( i = 0 ; i < info->ext_dev_nr ; i++ ) | 
|---|
| 76 |     { | 
|---|
| 77 |         dev  = &info->ext_dev[i]; | 
|---|
| 78 |         func = FUNC_FROM_TYPE( dev->type );    | 
|---|
| 79 |         if( func == DEV_FUNC_TXT ) cluster->nb_txt_channels = dev->channels; | 
|---|
| 80 |         if( func == DEV_FUNC_NIC ) cluster->nb_nic_channels = dev->channels; | 
|---|
| 81 |         if( func == DEV_FUNC_IOC ) cluster->nb_ioc_channels = dev->channels; | 
|---|
| 82 |         if( func == DEV_FUNC_FBF ) cluster->nb_fbf_channels = dev->channels; | 
|---|
| 83 |     } | 
|---|
| 84 |  | 
|---|
| 85 |     // initialize cluster local parameters | 
|---|
| 86 |         cluster->cores_nr        = info->cores_nr; | 
|---|
| 87 |  | 
|---|
| 88 |     // initialize the lock protecting the embedded kcm allocator | 
|---|
| 89 |         spinlock_init( &cluster->kcm_lock ); | 
|---|
| 90 |  | 
|---|
| 91 | #if CONFIG_DEBUG_CLUSTER_INIT | 
|---|
| 92 | uint32_t cycle = (uint32_t)hal_get_cycles(); | 
|---|
| 93 | if( CONFIG_DEBUG_CLUSTER_INIT < cycle ) | 
|---|
| 94 | printk("\n[DBG] %s enters for cluster %x / cycle %d\n", | 
|---|
| 95 | __FUNCTION__ , local_cxy , cycle ); | 
|---|
| 96 | #endif | 
|---|
| 97 |  | 
|---|
| 98 |     // initialises DQDT | 
|---|
| 99 |     cluster->dqdt_root_level = dqdt_init( info->x_size, | 
|---|
| 100 |                                           info->y_size, | 
|---|
| 101 |                                           info->y_width ); | 
|---|
| 102 |     cluster->threads_var = 0; | 
|---|
| 103 |     cluster->pages_var   = 0; | 
|---|
| 104 |  | 
|---|
| 105 |     // initialises embedded PPM | 
|---|
| 106 |         error = hal_ppm_init( info ); | 
|---|
| 107 |  | 
|---|
| 108 |     if( error ) | 
|---|
| 109 |     { | 
|---|
| 110 |         printk("\n[ERROR] in %s : cannot initialize PPM in cluster %x\n", | 
|---|
| 111 |                __FUNCTION__ , local_cxy ); | 
|---|
| 112 |         return ENOMEM; | 
|---|
| 113 |     } | 
|---|
| 114 |  | 
|---|
| 115 | #if CONFIG_DEBUG_CLUSTER_INIT | 
|---|
| 116 | cycle = (uint32_t)hal_get_cycles(); | 
|---|
| 117 | if( CONFIG_DEBUG_CLUSTER_INIT < cycle ) | 
|---|
| 118 | cluster_dmsg("\n[DBG] %s : PPM initialized in cluster %x / cycle %d\n", | 
|---|
| 119 | __FUNCTION__ , local_cxy , cycle ); | 
|---|
| 120 | #endif | 
|---|
| 121 |  | 
|---|
| 122 |     // initialises embedded KHM | 
|---|
| 123 |         khm_init( &cluster->khm ); | 
|---|
| 124 |  | 
|---|
| 125 |     cluster_dmsg("\n[DBG] %s : KHM initialized in cluster %x at cycle %d\n", | 
|---|
| 126 |                  __FUNCTION__ , local_cxy , hal_get_cycles() ); | 
|---|
| 127 |  | 
|---|
| 128 |     // initialises embedded KCM | 
|---|
| 129 |         kcm_init( &cluster->kcm , KMEM_KCM ); | 
|---|
| 130 |  | 
|---|
| 131 |     cluster_dmsg("\n[DBG] %s : KCM initialized in cluster %x at cycle %d\n", | 
|---|
| 132 |                  __FUNCTION__ , local_cxy , hal_get_cycles() ); | 
|---|
| 133 |  | 
|---|
| 134 |     // initialises all cores descriptors  | 
|---|
| 135 |         for( lid = 0 ; lid < cluster->cores_nr; lid++ ) | 
|---|
| 136 |         { | 
|---|
| 137 |                 core_init( &cluster->core_tbl[lid],    // target core descriptor | 
|---|
| 138 |                        lid,                        // local core index | 
|---|
| 139 |                        info->core[lid].gid );      // gid from boot_info_t | 
|---|
| 140 |         } | 
|---|
| 141 |  | 
|---|
| 142 | #if CONFIG_DEBUG_CLUSTER_INIT | 
|---|
| 143 | cycle = (uint32_t)hal_get_cycles(); | 
|---|
| 144 | if( CONFIG_DEBUG_CLUSTER_INIT < cycle ) | 
|---|
| 145 | cluster_dmsg("\n[DBG] %s : cores initialized in cluster %x / cycle %d\n", | 
|---|
| 146 | __FUNCTION__ , local_cxy , cycle ); | 
|---|
| 147 | #endif | 
|---|
| 148 |  | 
|---|
| 149 |     // initialises RPC fifo | 
|---|
| 150 |         local_fifo_init( &cluster->rpc_fifo ); | 
|---|
| 151 |     cluster->rpc_threads = 0; | 
|---|
| 152 |  | 
|---|
| 153 | cluster_dmsg("\n[DBG] %s : RPC fifo inialized in cluster %x at cycle %d\n", | 
|---|
| 154 | __FUNCTION__ , local_cxy , hal_get_cycles() ); | 
|---|
| 155 |  | 
|---|
| 156 |     // initialise pref_tbl[] in process manager | 
|---|
| 157 |         spinlock_init( &cluster->pmgr.pref_lock ); | 
|---|
| 158 |     cluster->pmgr.pref_nr = 0; | 
|---|
| 159 |     cluster->pmgr.pref_tbl[0] = XPTR( local_cxy , &process_zero ); | 
|---|
| 160 |     for( lpid = 1 ; lpid < CONFIG_MAX_PROCESS_PER_CLUSTER ; lpid++ ) | 
|---|
| 161 |     { | 
|---|
| 162 |         cluster->pmgr.pref_tbl[lpid] = XPTR_NULL; | 
|---|
| 163 |     } | 
|---|
| 164 |  | 
|---|
| 165 |     // initialise local_list in process manager | 
|---|
| 166 |         remote_spinlock_init( XPTR( local_cxy , &cluster->pmgr.local_lock ) ); | 
|---|
| 167 |     xlist_root_init( XPTR( local_cxy , &cluster->pmgr.local_root ) ); | 
|---|
| 168 |     cluster->pmgr.local_nr = 0; | 
|---|
| 169 |  | 
|---|
| 170 |     // initialise copies_lists in process manager | 
|---|
| 171 |     for( lpid = 0 ; lpid < CONFIG_MAX_PROCESS_PER_CLUSTER ; lpid++ ) | 
|---|
| 172 |     { | 
|---|
| 173 |             remote_spinlock_init( XPTR( local_cxy , &cluster->pmgr.copies_lock[lpid] ) ); | 
|---|
| 174 |         cluster->pmgr.copies_nr[lpid] = 0; | 
|---|
| 175 |         xlist_root_init( XPTR( local_cxy , &cluster->pmgr.copies_root[lpid] ) ); | 
|---|
| 176 |     } | 
|---|
| 177 |  | 
|---|
| 178 | #if CONFIG_DEBUG_CLUSTER_INIT | 
|---|
| 179 | cycle = (uint32_t)hal_get_cycles(); | 
|---|
| 180 | if( CONFIG_DEBUG_CLUSTER_INIT < cycle ) | 
|---|
| 181 | cluster_dmsg("\n[DBG] %s Process Manager initialized in cluster %x / cycle %d\n", | 
|---|
| 182 | __FUNCTION__ , local_cxy , cycle ); | 
|---|
| 183 | #endif | 
|---|
| 184 |  | 
|---|
| 185 |     hal_fence(); | 
|---|
| 186 |  | 
|---|
| 187 |         return 0; | 
|---|
| 188 | } // end cluster_init() | 
|---|
| 189 |  | 
|---|
| 190 | //////////////////////////////////////// | 
|---|
| 191 | bool_t cluster_is_undefined( cxy_t cxy ) | 
|---|
| 192 | { | 
|---|
| 193 |     cluster_t * cluster = LOCAL_CLUSTER; | 
|---|
| 194 |  | 
|---|
| 195 |     uint32_t y_width = cluster->y_width; | 
|---|
| 196 |  | 
|---|
| 197 |     uint32_t x = cxy >> y_width; | 
|---|
| 198 |     uint32_t y = cxy & ((1<<y_width)-1); | 
|---|
| 199 |  | 
|---|
| 200 |     if( x >= cluster->x_size ) return true; | 
|---|
| 201 |     if( y >= cluster->y_size ) return true; | 
|---|
| 202 |  | 
|---|
| 203 |     return false; | 
|---|
| 204 | } | 
|---|
| 205 |  | 
|---|
| 206 | //////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 207 | //  Cores related functions | 
|---|
| 208 | //////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 209 |  | 
|---|
| 210 | ///////////////////////////////// | 
|---|
| 211 | lid_t cluster_select_local_core() | 
|---|
| 212 | { | 
|---|
| 213 |     uint32_t min = 100; | 
|---|
| 214 |     lid_t    sel = 0; | 
|---|
| 215 |     lid_t    lid; | 
|---|
| 216 |  | 
|---|
| 217 |     cluster_t * cluster = LOCAL_CLUSTER; | 
|---|
| 218 |  | 
|---|
| 219 |     for( lid = 0 ; lid < cluster->cores_nr ; lid++ ) | 
|---|
| 220 |     { | 
|---|
| 221 |         if( cluster->core_tbl[lid].usage < min ) | 
|---|
| 222 |         { | 
|---|
| 223 |             min = cluster->core_tbl[lid].usage; | 
|---|
| 224 |             sel = lid; | 
|---|
| 225 |         } | 
|---|
| 226 |     } | 
|---|
| 227 |     return sel; | 
|---|
| 228 | } | 
|---|
| 229 |  | 
|---|
| 230 | //////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 231 | //  Process related functions | 
|---|
| 232 | //////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 233 |  | 
|---|
| 234 |  | 
|---|
| 235 | ////////////////////////////////////////////////////// | 
|---|
| 236 | xptr_t cluster_get_owner_process_from_pid( pid_t pid ) | 
|---|
| 237 | { | 
|---|
| 238 |     xptr_t      root_xp;       // xptr on root of list of processes in owner cluster | 
|---|
| 239 |     xptr_t      lock_xp;       // xptrr on lock protecting this list | 
|---|
| 240 |     xptr_t      iter_xp;       // iterator | 
|---|
| 241 |     xptr_t      current_xp;    // xptr on current process descriptor | 
|---|
| 242 |     process_t * current_ptr;   // local pointer on current process | 
|---|
| 243 |     pid_t       current_pid;   // current process identifier | 
|---|
| 244 |     bool_t      found; | 
|---|
| 245 |  | 
|---|
| 246 |     cluster_t * cluster = LOCAL_CLUSTER; | 
|---|
| 247 |  | 
|---|
| 248 |     // get owner cluster and lpid | 
|---|
| 249 |     cxy_t  owner_cxy = CXY_FROM_PID( pid ); | 
|---|
| 250 |  | 
|---|
| 251 |     // get lock & root of list of process in owner cluster | 
|---|
| 252 |     root_xp = XPTR( owner_cxy , &cluster->pmgr.local_root ); | 
|---|
| 253 |     lock_xp = XPTR( owner_cxy , &cluster->pmgr.local_lock ); | 
|---|
| 254 |  | 
|---|
| 255 |     // take the lock protecting the list of processes | 
|---|
| 256 |     remote_spinlock_lock( lock_xp ); | 
|---|
| 257 |  | 
|---|
| 258 |     // scan list of processes in owner cluster | 
|---|
| 259 |     found = false; | 
|---|
| 260 |     XLIST_FOREACH( root_xp , iter_xp ) | 
|---|
| 261 |     { | 
|---|
| 262 |         current_xp  = XLIST_ELEMENT( iter_xp , process_t , local_list ); | 
|---|
| 263 |         current_ptr = GET_PTR( current_xp ); | 
|---|
| 264 |         current_pid = hal_remote_lw( XPTR( owner_cxy , ¤t_ptr->pid ) ); | 
|---|
| 265 |  | 
|---|
| 266 |         if( current_pid == pid ) | 
|---|
| 267 |         { | 
|---|
| 268 |             found = true; | 
|---|
| 269 |             break; | 
|---|
| 270 |         } | 
|---|
| 271 |     } | 
|---|
| 272 |  | 
|---|
| 273 |     // release the lock protecting the list of processes | 
|---|
| 274 |     remote_spinlock_unlock( lock_xp ); | 
|---|
| 275 |  | 
|---|
| 276 |     // return extended pointer on process descriptor in owner cluster | 
|---|
| 277 |     if( found ) return current_xp; | 
|---|
| 278 |     else        return XPTR_NULL; | 
|---|
| 279 | } | 
|---|
| 280 |  | 
|---|
| 281 | ////////////////////////////////////////////////////////// | 
|---|
| 282 | xptr_t cluster_get_reference_process_from_pid( pid_t pid ) | 
|---|
| 283 | { | 
|---|
| 284 |     xptr_t ref_xp;   // extended pointer on reference process descriptor | 
|---|
| 285 |  | 
|---|
| 286 |     cluster_t * cluster = LOCAL_CLUSTER; | 
|---|
| 287 |  | 
|---|
| 288 |     // get owner cluster and lpid | 
|---|
| 289 |     cxy_t  owner_cxy = CXY_FROM_PID( pid ); | 
|---|
| 290 |     lpid_t lpid      = LPID_FROM_PID( pid ); | 
|---|
| 291 |  | 
|---|
| 292 |     // Check valid PID | 
|---|
| 293 |     if( lpid >= CONFIG_MAX_PROCESS_PER_CLUSTER )  return XPTR_NULL; | 
|---|
| 294 |  | 
|---|
| 295 |     if( local_cxy == owner_cxy )   // local cluster is owner cluster | 
|---|
| 296 |     { | 
|---|
| 297 |         ref_xp = cluster->pmgr.pref_tbl[lpid]; | 
|---|
| 298 |     } | 
|---|
| 299 |     else                              // use a remote_lwd to access owner cluster | 
|---|
| 300 |     { | 
|---|
| 301 |         ref_xp = (xptr_t)hal_remote_lwd( XPTR( owner_cxy , &cluster->pmgr.pref_tbl[lpid] ) ); | 
|---|
| 302 |     } | 
|---|
| 303 |  | 
|---|
| 304 |     return ref_xp; | 
|---|
| 305 | } | 
|---|
| 306 |  | 
|---|
| 307 | /////////////////////////////////////////////// | 
|---|
| 308 | error_t cluster_pid_alloc( process_t * process, | 
|---|
| 309 |                            pid_t     * pid ) | 
|---|
| 310 | { | 
|---|
| 311 |     lpid_t      lpid; | 
|---|
| 312 |     bool_t      found; | 
|---|
| 313 |  | 
|---|
| 314 |     pmgr_t    * pm         = &LOCAL_CLUSTER->pmgr; | 
|---|
| 315 |  | 
|---|
| 316 |     // get the process manager lock | 
|---|
| 317 |     spinlock_lock( &pm->pref_lock ); | 
|---|
| 318 |  | 
|---|
| 319 |     // search an empty slot | 
|---|
| 320 |     found = false; | 
|---|
| 321 |     for( lpid = 0 ; lpid < CONFIG_MAX_PROCESS_PER_CLUSTER ; lpid++ ) | 
|---|
| 322 |     { | 
|---|
| 323 |         if( pm->pref_tbl[lpid] == XPTR_NULL ) | 
|---|
| 324 |         { | 
|---|
| 325 |             found = true; | 
|---|
| 326 |             break; | 
|---|
| 327 |         } | 
|---|
| 328 |     } | 
|---|
| 329 |  | 
|---|
| 330 |     if( found ) | 
|---|
| 331 |     { | 
|---|
| 332 |         // register process in pref_tbl[] | 
|---|
| 333 |         pm->pref_tbl[lpid] = XPTR( local_cxy , process ); | 
|---|
| 334 |         pm->pref_nr++; | 
|---|
| 335 |  | 
|---|
| 336 |         // returns pid | 
|---|
| 337 |         *pid = PID( local_cxy , lpid ); | 
|---|
| 338 |  | 
|---|
| 339 |         // release the processs_manager lock | 
|---|
| 340 |         spinlock_unlock( &pm->pref_lock ); | 
|---|
| 341 |  | 
|---|
| 342 |         return 0; | 
|---|
| 343 |     } | 
|---|
| 344 |     else | 
|---|
| 345 |     { | 
|---|
| 346 |         // release the processs_manager lock | 
|---|
| 347 |         spinlock_unlock( &pm->pref_lock ); | 
|---|
| 348 |  | 
|---|
| 349 |         return -1; | 
|---|
| 350 |     } | 
|---|
| 351 |  | 
|---|
| 352 | } // end cluster_pid_alloc() | 
|---|
| 353 |  | 
|---|
| 354 | ///////////////////////////////////// | 
|---|
| 355 | void cluster_pid_release( pid_t pid ) | 
|---|
| 356 | { | 
|---|
| 357 |     cxy_t  owner_cxy  = CXY_FROM_PID( pid ); | 
|---|
| 358 |     lpid_t lpid       = LPID_FROM_PID( pid ); | 
|---|
| 359 |  | 
|---|
| 360 |     pmgr_t  * pm = &LOCAL_CLUSTER->pmgr; | 
|---|
| 361 |  | 
|---|
| 362 |     // check pid argument | 
|---|
| 363 |     assert( (lpid < CONFIG_MAX_PROCESS_PER_CLUSTER) && (owner_cxy == local_cxy) , | 
|---|
| 364 |     __FUNCTION__ , "illegal PID" ); | 
|---|
| 365 |  | 
|---|
| 366 |     // get the process manager lock | 
|---|
| 367 |     spinlock_lock( &pm->pref_lock ); | 
|---|
| 368 |  | 
|---|
| 369 |     // remove process from pref_tbl[] | 
|---|
| 370 |     pm->pref_tbl[lpid] = XPTR_NULL; | 
|---|
| 371 |     pm->pref_nr--; | 
|---|
| 372 |  | 
|---|
| 373 |     // release the processs_manager lock | 
|---|
| 374 |     spinlock_unlock( &pm->pref_lock ); | 
|---|
| 375 |  | 
|---|
| 376 | } // end cluster_pid_release() | 
|---|
| 377 |  | 
|---|
| 378 | /////////////////////////////////////////////////////////// | 
|---|
| 379 | process_t * cluster_get_local_process_from_pid( pid_t pid ) | 
|---|
| 380 | { | 
|---|
| 381 |     xptr_t         process_xp; | 
|---|
| 382 |     process_t    * process_ptr; | 
|---|
| 383 |     xptr_t         root_xp; | 
|---|
| 384 |     xptr_t         iter_xp; | 
|---|
| 385 |     bool_t         found; | 
|---|
| 386 |  | 
|---|
| 387 |     found   = false; | 
|---|
| 388 |     root_xp = XPTR( local_cxy , &LOCAL_CLUSTER->pmgr.local_root ); | 
|---|
| 389 |  | 
|---|
| 390 |     XLIST_FOREACH( root_xp , iter_xp ) | 
|---|
| 391 |     { | 
|---|
| 392 |         process_xp  = XLIST_ELEMENT( iter_xp , process_t , local_list ); | 
|---|
| 393 |         process_ptr = (process_t *)GET_PTR( process_xp ); | 
|---|
| 394 |         if( process_ptr->pid == pid ) | 
|---|
| 395 |         { | 
|---|
| 396 |             found = true; | 
|---|
| 397 |             break; | 
|---|
| 398 |         } | 
|---|
| 399 |     } | 
|---|
| 400 |  | 
|---|
| 401 |     if (found ) return process_ptr; | 
|---|
| 402 |     else        return NULL; | 
|---|
| 403 |  | 
|---|
| 404 | }  // end cluster_get_local_process_from_pid() | 
|---|
| 405 |  | 
|---|
| 406 | ////////////////////////////////////////////////////// | 
|---|
| 407 | void cluster_process_local_link( process_t * process ) | 
|---|
| 408 | { | 
|---|
| 409 |     uint32_t irq_state; | 
|---|
| 410 |     pmgr_t * pm = &LOCAL_CLUSTER->pmgr; | 
|---|
| 411 |  | 
|---|
| 412 |     // get lock protecting the process manager local list | 
|---|
| 413 |     remote_spinlock_lock_busy( XPTR( local_cxy , &pm->local_lock ) , & irq_state ); | 
|---|
| 414 |  | 
|---|
| 415 |     xlist_add_last( XPTR( local_cxy , &pm->local_root ), | 
|---|
| 416 |                     XPTR( local_cxy , &process->local_list ) ); | 
|---|
| 417 |     pm->local_nr++; | 
|---|
| 418 |  | 
|---|
| 419 |     // release lock protecting the process manager local list | 
|---|
| 420 |     remote_spinlock_unlock_busy( XPTR( local_cxy , &pm->local_lock ) , irq_state ); | 
|---|
| 421 | } | 
|---|
| 422 |  | 
|---|
| 423 | //////////////////////////////////////////////////////// | 
|---|
| 424 | void cluster_process_local_unlink( process_t * process ) | 
|---|
| 425 | { | 
|---|
| 426 |     uint32_t irq_state; | 
|---|
| 427 |     pmgr_t * pm = &LOCAL_CLUSTER->pmgr; | 
|---|
| 428 |  | 
|---|
| 429 |     // get lock protecting the process manager local list | 
|---|
| 430 |     remote_spinlock_lock_busy( XPTR( local_cxy , &pm->local_lock ) , &irq_state ); | 
|---|
| 431 |  | 
|---|
| 432 |     xlist_unlink( XPTR( local_cxy , &process->local_list ) ); | 
|---|
| 433 |     pm->local_nr--; | 
|---|
| 434 |  | 
|---|
| 435 |     // release lock protecting the process manager local list | 
|---|
| 436 |     remote_spinlock_unlock_busy( XPTR( local_cxy , &pm->local_lock ) , irq_state ); | 
|---|
| 437 | } | 
|---|
| 438 |  | 
|---|
| 439 | /////////////////////////////////////////////////////// | 
|---|
| 440 | void cluster_process_copies_link( process_t * process ) | 
|---|
| 441 | { | 
|---|
| 442 |     uint32_t irq_state; | 
|---|
| 443 |     pmgr_t * pm = &LOCAL_CLUSTER->pmgr; | 
|---|
| 444 |  | 
|---|
| 445 |     // get owner cluster identifier CXY and process LPID | 
|---|
| 446 |     pid_t    pid        = process->pid; | 
|---|
| 447 |     cxy_t    owner_cxy  = CXY_FROM_PID( pid ); | 
|---|
| 448 |     lpid_t   lpid       = LPID_FROM_PID( pid ); | 
|---|
| 449 |  | 
|---|
| 450 |     // get extended pointer on lock protecting copies_list[lpid] | 
|---|
| 451 |     xptr_t copies_lock  = XPTR( owner_cxy , &pm->copies_lock[lpid] ); | 
|---|
| 452 |  | 
|---|
| 453 |     // get extended pointer on the copies_list[lpid] root | 
|---|
| 454 |     xptr_t copies_root  = XPTR( owner_cxy , &pm->copies_root[lpid] ); | 
|---|
| 455 |  | 
|---|
| 456 |     // get extended pointer on the local copies_list entry | 
|---|
| 457 |     xptr_t copies_entry = XPTR( local_cxy , &process->copies_list ); | 
|---|
| 458 |  | 
|---|
| 459 |     // get lock protecting copies_list[lpid] | 
|---|
| 460 |     remote_spinlock_lock_busy( copies_lock , &irq_state ); | 
|---|
| 461 |  | 
|---|
| 462 |     xlist_add_first( copies_root , copies_entry ); | 
|---|
| 463 |     hal_remote_atomic_add( XPTR( owner_cxy , &pm->copies_nr[lpid] ) , 1 ); | 
|---|
| 464 |  | 
|---|
| 465 |     // release lock protecting copies_list[lpid] | 
|---|
| 466 |     remote_spinlock_unlock_busy( copies_lock , irq_state ); | 
|---|
| 467 | } | 
|---|
| 468 |  | 
|---|
| 469 | ///////////////////////////////////////////////////////// | 
|---|
| 470 | void cluster_process_copies_unlink( process_t * process ) | 
|---|
| 471 | { | 
|---|
| 472 |     uint32_t irq_state; | 
|---|
| 473 |     pmgr_t * pm = &LOCAL_CLUSTER->pmgr; | 
|---|
| 474 |  | 
|---|
| 475 |     // get owner cluster identifier CXY and process LPID | 
|---|
| 476 |     pid_t    pid        = process->pid; | 
|---|
| 477 |     cxy_t    owner_cxy  = CXY_FROM_PID( pid ); | 
|---|
| 478 |     lpid_t   lpid       = LPID_FROM_PID( pid ); | 
|---|
| 479 |  | 
|---|
| 480 |     // get extended pointer on lock protecting copies_list[lpid] | 
|---|
| 481 |     xptr_t copies_lock  = hal_remote_lwd( XPTR( owner_cxy , &pm->copies_lock[lpid] ) ); | 
|---|
| 482 |  | 
|---|
| 483 |     // get extended pointer on the local copies_list entry | 
|---|
| 484 |     xptr_t copies_entry = XPTR( local_cxy , &process->copies_list ); | 
|---|
| 485 |  | 
|---|
| 486 |     // get lock protecting copies_list[lpid] | 
|---|
| 487 |     remote_spinlock_lock_busy( copies_lock , &irq_state ); | 
|---|
| 488 |  | 
|---|
| 489 |     xlist_unlink( copies_entry ); | 
|---|
| 490 |     hal_remote_atomic_add( XPTR( owner_cxy , &pm->copies_nr[lpid] ) , -1 ); | 
|---|
| 491 |  | 
|---|
| 492 |     // release lock protecting copies_list[lpid] | 
|---|
| 493 |     remote_spinlock_unlock_busy( copies_lock , irq_state ); | 
|---|
| 494 | } | 
|---|
| 495 |  | 
|---|
| 496 | /////////////////////////////////////////// | 
|---|
| 497 | void cluster_processes_display( cxy_t cxy ) | 
|---|
| 498 | { | 
|---|
| 499 |     xptr_t        root_xp; | 
|---|
| 500 |     xptr_t        iter_xp; | 
|---|
| 501 |     xptr_t        process_xp;      | 
|---|
| 502 |  | 
|---|
| 503 |     // get extended pointer on root of process in cluster cxy | 
|---|
| 504 |     root_xp = XPTR( cxy , &LOCAL_CLUSTER->pmgr.local_root ); | 
|---|
| 505 |  | 
|---|
| 506 |     // skip one line | 
|---|
| 507 |     printk("\n***** processes in cluster %x / cycle %d\n", cxy , (uint32_t)hal_get_cycles() ); | 
|---|
| 508 |  | 
|---|
| 509 |     // loop on all reference processes in cluster cxy  | 
|---|
| 510 |     XLIST_FOREACH( root_xp , iter_xp ) | 
|---|
| 511 |     { | 
|---|
| 512 |         process_xp = XLIST_ELEMENT( iter_xp , process_t , local_list ); | 
|---|
| 513 |         process_display( process_xp ); | 
|---|
| 514 |     } | 
|---|
| 515 | }  // end cluster_processes_display()  | 
|---|
| 516 |  | 
|---|
| 517 |  | 
|---|