source: trunk/kernel/kern/cluster.c @ 437

Last change on this file since 437 was 437, checked in by alain, 6 years ago

Fix various bugs

File size: 17.4 KB
Line 
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,2018)
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
51extern process_t process_zero;     // allocated in kernel_init.c file
52
53
54/////////////////////////////////////////////////
55error_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
92uint32_t cycle = (uint32_t)hal_get_cycles();
93if( CONFIG_DEBUG_CLUSTER_INIT < cycle )
94printk("\n[DBG] %s : thread %x enters for cluster %x / cycle %d\n",
95__FUNCTION__ , CURRENT_THREAD , 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 & 1 )
116cycle = (uint32_t)hal_get_cycles();
117if( CONFIG_DEBUG_CLUSTER_INIT < cycle )
118printk("\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#if( CONFIG_DEBUG_CLUSTER_INIT & 1 )
126uint32_t cycle = (uint32_t)hal_get_cycles();
127if( CONFIG_DEBUG_CLUSTER_INIT < cycle )
128printk("\n[DBG] %s : KHM initialized in cluster %x at cycle %d\n",
129__FUNCTION__ , local_cxy , hal_get_cycles() );
130#endif
131
132    // initialises embedded KCM
133        kcm_init( &cluster->kcm , KMEM_KCM );
134
135#if( CONFIG_DEBUG_CLUSTER_INIT & 1 )
136uint32_t cycle = (uint32_t)hal_get_cycles();
137if( CONFIG_DEBUG_CLUSTER_INIT < cycle )
138printk("\n[DBG] %s : KCM initialized in cluster %x at cycle %d\n",
139__FUNCTION__ , local_cxy , hal_get_cycles() );
140#endif
141
142    // initialises all cores descriptors
143        for( lid = 0 ; lid < cluster->cores_nr; lid++ )
144        {
145                core_init( &cluster->core_tbl[lid],    // target core descriptor
146                       lid,                        // local core index
147                       info->core[lid].gid );      // gid from boot_info_t
148        }
149
150#if( CONFIG_DEBUG_CLUSTER_INIT & 1 )
151cycle = (uint32_t)hal_get_cycles();
152if( CONFIG_DEBUG_CLUSTER_INIT < cycle )
153printk("\n[DBG] %s : cores initialized in cluster %x / cycle %d\n",
154__FUNCTION__ , local_cxy , cycle );
155#endif
156
157    // initialises RPC fifo
158        local_fifo_init( &cluster->rpc_fifo );
159    cluster->rpc_threads = 0;
160
161#if( CONFIG_DEBUG_CLUSTER_INIT & 1 )
162cycle = (uint32_t)hal_get_cycles();
163if( CONFIG_DEBUG_CLUSTER_INIT < cycle )
164printk("\n[DBG] %s : RPC fifo inialized in cluster %x at cycle %d\n",
165__FUNCTION__ , local_cxy , hal_get_cycles() );
166#endif
167
168    // initialise pref_tbl[] in process manager
169        spinlock_init( &cluster->pmgr.pref_lock );
170    cluster->pmgr.pref_nr = 0;
171    cluster->pmgr.pref_tbl[0] = XPTR( local_cxy , &process_zero );
172    for( lpid = 1 ; lpid < CONFIG_MAX_PROCESS_PER_CLUSTER ; lpid++ )
173    {
174        cluster->pmgr.pref_tbl[lpid] = XPTR_NULL;
175    }
176
177    // initialise local_list in process manager
178        remote_spinlock_init( XPTR( local_cxy , &cluster->pmgr.local_lock ) );
179    xlist_root_init( XPTR( local_cxy , &cluster->pmgr.local_root ) );
180    cluster->pmgr.local_nr = 0;
181
182    // initialise copies_lists in process manager
183    for( lpid = 0 ; lpid < CONFIG_MAX_PROCESS_PER_CLUSTER ; lpid++ )
184    {
185            remote_spinlock_init( XPTR( local_cxy , &cluster->pmgr.copies_lock[lpid] ) );
186        cluster->pmgr.copies_nr[lpid] = 0;
187        xlist_root_init( XPTR( local_cxy , &cluster->pmgr.copies_root[lpid] ) );
188    }
189
190#if CONFIG_DEBUG_CLUSTER_INIT
191cycle = (uint32_t)hal_get_cycles();
192if( CONFIG_DEBUG_CLUSTER_INIT < cycle )
193printk("\n[DBG] %s , thread %x exit for cluster %x / cycle %d\n",
194__FUNCTION__ , CURRENT_THREAD , local_cxy , cycle );
195#endif
196
197    hal_fence();
198
199        return 0;
200} // end cluster_init()
201
202////////////////////////////////////////
203bool_t cluster_is_undefined( cxy_t cxy )
204{
205    cluster_t * cluster = LOCAL_CLUSTER;
206
207    uint32_t y_width = cluster->y_width;
208
209    uint32_t x = cxy >> y_width;
210    uint32_t y = cxy & ((1<<y_width)-1);
211
212    if( x >= cluster->x_size ) return true;
213    if( y >= cluster->y_size ) return true;
214
215    return false;
216}
217
218////////////////////////////////////////////////////////////////////////////////////
219//  Cores related functions
220////////////////////////////////////////////////////////////////////////////////////
221
222/////////////////////////////////
223lid_t cluster_select_local_core()
224{
225    uint32_t min = 100;
226    lid_t    sel = 0;
227    lid_t    lid;
228
229    cluster_t * cluster = LOCAL_CLUSTER;
230
231    for( lid = 0 ; lid < cluster->cores_nr ; lid++ )
232    {
233        if( cluster->core_tbl[lid].usage < min )
234        {
235            min = cluster->core_tbl[lid].usage;
236            sel = lid;
237        }
238    }
239    return sel;
240}
241
242////////////////////////////////////////////////////////////////////////////////////
243//  Process related functions
244////////////////////////////////////////////////////////////////////////////////////
245
246
247//////////////////////////////////////////////////////
248xptr_t cluster_get_owner_process_from_pid( pid_t pid )
249{
250    xptr_t      root_xp;       // xptr on root of list of processes in owner cluster
251    xptr_t      lock_xp;       // xptr on lock protecting this list
252    xptr_t      iter_xp;       // iterator
253    xptr_t      current_xp;    // xptr on current process descriptor
254    process_t * current_ptr;   // local pointer on current process
255    pid_t       current_pid;   // current process identifier
256    bool_t      found;
257
258    cluster_t * cluster = LOCAL_CLUSTER;
259
260    // get owner cluster and lpid
261    cxy_t  owner_cxy = CXY_FROM_PID( pid );
262
263    // get lock & root of list of process in owner cluster
264    root_xp = XPTR( owner_cxy , &cluster->pmgr.local_root );
265    lock_xp = XPTR( owner_cxy , &cluster->pmgr.local_lock );
266
267    // take the lock protecting the list of processes
268    remote_spinlock_lock( lock_xp );
269
270    // scan list of processes in owner cluster
271    found = false;
272    XLIST_FOREACH( root_xp , iter_xp )
273    {
274        current_xp  = XLIST_ELEMENT( iter_xp , process_t , local_list );
275        current_ptr = GET_PTR( current_xp );
276        current_pid = hal_remote_lw( XPTR( owner_cxy , &current_ptr->pid ) );
277
278        if( current_pid == pid )
279        {
280            found = true;
281            break;
282        }
283    }
284
285    // release the lock protecting the list of processes
286    remote_spinlock_unlock( lock_xp );
287
288    // return extended pointer on process descriptor in owner cluster
289    if( found ) return current_xp;
290    else        return XPTR_NULL;
291
292}  // end cluster_get_owner_process_from_pid()
293
294//////////////////////////////////////////////////////////
295xptr_t cluster_get_reference_process_from_pid( pid_t pid )
296{
297    xptr_t ref_xp;   // extended pointer on reference process descriptor
298
299    cluster_t * cluster = LOCAL_CLUSTER;
300
301    // get owner cluster and lpid
302    cxy_t  owner_cxy = CXY_FROM_PID( pid );
303    lpid_t lpid      = LPID_FROM_PID( pid );
304
305    // Check valid PID
306    if( lpid >= CONFIG_MAX_PROCESS_PER_CLUSTER )  return XPTR_NULL;
307
308    if( local_cxy == owner_cxy )   // local cluster is owner cluster
309    {
310        ref_xp = cluster->pmgr.pref_tbl[lpid];
311    }
312    else                              // use a remote_lwd to access owner cluster
313    {
314        ref_xp = (xptr_t)hal_remote_lwd( XPTR( owner_cxy , &cluster->pmgr.pref_tbl[lpid] ) );
315    }
316
317    return ref_xp;
318}
319
320///////////////////////////////////////////////
321error_t cluster_pid_alloc( process_t * process,
322                           pid_t     * pid )
323{
324    lpid_t      lpid;
325    bool_t      found;
326
327    pmgr_t    * pm         = &LOCAL_CLUSTER->pmgr;
328
329    // get the process manager lock
330    spinlock_lock( &pm->pref_lock );
331
332    // search an empty slot
333    found = false;
334    for( lpid = 0 ; lpid < CONFIG_MAX_PROCESS_PER_CLUSTER ; lpid++ )
335    {
336        if( pm->pref_tbl[lpid] == XPTR_NULL )
337        {
338            found = true;
339            break;
340        }
341    }
342
343    if( found )
344    {
345        // register process in pref_tbl[]
346        pm->pref_tbl[lpid] = XPTR( local_cxy , process );
347        pm->pref_nr++;
348
349        // returns pid
350        *pid = PID( local_cxy , lpid );
351
352        // release the processs_manager lock
353        spinlock_unlock( &pm->pref_lock );
354
355        return 0;
356    }
357    else
358    {
359        // release the processs_manager lock
360        spinlock_unlock( &pm->pref_lock );
361
362        return -1;
363    }
364
365} // end cluster_pid_alloc()
366
367/////////////////////////////////////
368void cluster_pid_release( pid_t pid )
369{
370    cxy_t  owner_cxy  = CXY_FROM_PID( pid );
371    lpid_t lpid       = LPID_FROM_PID( pid );
372
373    pmgr_t  * pm = &LOCAL_CLUSTER->pmgr;
374
375    // check pid argument
376    assert( (lpid < CONFIG_MAX_PROCESS_PER_CLUSTER) && (owner_cxy == local_cxy) ,
377    __FUNCTION__ , "illegal PID" );
378
379    // get the process manager lock
380    spinlock_lock( &pm->pref_lock );
381
382    // remove process from pref_tbl[]
383    pm->pref_tbl[lpid] = XPTR_NULL;
384    pm->pref_nr--;
385
386    // release the processs_manager lock
387    spinlock_unlock( &pm->pref_lock );
388
389} // end cluster_pid_release()
390
391///////////////////////////////////////////////////////////
392process_t * cluster_get_local_process_from_pid( pid_t pid )
393{
394    xptr_t         process_xp;
395    process_t    * process_ptr;
396    xptr_t         root_xp;
397    xptr_t         iter_xp;
398    bool_t         found;
399
400    found   = false;
401    root_xp = XPTR( local_cxy , &LOCAL_CLUSTER->pmgr.local_root );
402
403    XLIST_FOREACH( root_xp , iter_xp )
404    {
405        process_xp  = XLIST_ELEMENT( iter_xp , process_t , local_list );
406        process_ptr = (process_t *)GET_PTR( process_xp );
407        if( process_ptr->pid == pid )
408        {
409            found = true;
410            break;
411        }
412    }
413
414    if (found ) return process_ptr;
415    else        return NULL;
416
417}  // end cluster_get_local_process_from_pid()
418
419//////////////////////////////////////////////////////
420void cluster_process_local_link( process_t * process )
421{
422    uint32_t irq_state;
423    pmgr_t * pm = &LOCAL_CLUSTER->pmgr;
424
425    // get lock protecting the process manager local list
426    remote_spinlock_lock_busy( XPTR( local_cxy , &pm->local_lock ) , & irq_state );
427
428    xlist_add_last( XPTR( local_cxy , &pm->local_root ),
429                    XPTR( local_cxy , &process->local_list ) );
430    pm->local_nr++;
431
432    // release lock protecting the process manager local list
433    remote_spinlock_unlock_busy( XPTR( local_cxy , &pm->local_lock ) , irq_state );
434}
435
436////////////////////////////////////////////////////////
437void cluster_process_local_unlink( process_t * process )
438{
439    uint32_t irq_state;
440    pmgr_t * pm = &LOCAL_CLUSTER->pmgr;
441
442    // get lock protecting the process manager local list
443    remote_spinlock_lock_busy( XPTR( local_cxy , &pm->local_lock ) , &irq_state );
444
445    xlist_unlink( XPTR( local_cxy , &process->local_list ) );
446    pm->local_nr--;
447
448    // release lock protecting the process manager local list
449    remote_spinlock_unlock_busy( XPTR( local_cxy , &pm->local_lock ) , irq_state );
450}
451
452///////////////////////////////////////////////////////
453void cluster_process_copies_link( process_t * process )
454{
455    reg_t    irq_state;
456    pmgr_t * pm = &LOCAL_CLUSTER->pmgr;
457
458#if CONFIG_DEBUG_CLUSTER_PROCESS_COPIES
459uint32_t cycle = (uint32_t)hal_get_cycles();
460if( CONFIG_DEBUG_CLUSTER_PROCESS_COPIES < cycle )
461printk("\n[DBG] %s enters / cluster %x / process %x / cycle %d\n",
462__FUNCTION__ , local_cxy , process , cycle );
463#endif
464
465    // get owner cluster identifier CXY and process LPID
466    pid_t    pid        = process->pid;
467    cxy_t    owner_cxy  = CXY_FROM_PID( pid );
468    lpid_t   lpid       = LPID_FROM_PID( pid );
469
470    // get extended pointer on lock protecting copies_list[lpid]
471    xptr_t copies_lock  = XPTR( owner_cxy , &pm->copies_lock[lpid] );
472
473    // get extended pointer on the copies_list[lpid] root
474    xptr_t copies_root  = XPTR( owner_cxy , &pm->copies_root[lpid] );
475
476    // get extended pointer on the local copies_list entry
477    xptr_t copies_entry = XPTR( local_cxy , &process->copies_list );
478
479    // get lock protecting copies_list[lpid]
480    remote_spinlock_lock_busy( copies_lock , &irq_state );
481
482    // add copy to copies_list
483    xlist_add_first( copies_root , copies_entry );
484    hal_remote_atomic_add( XPTR( owner_cxy , &pm->copies_nr[lpid] ) , 1 );
485
486    // release lock protecting copies_list[lpid]
487    remote_spinlock_unlock_busy( copies_lock , irq_state );
488
489#if CONFIG_DEBUG_CLUSTER_PROCESS_COPIES
490cycle = (uint32_t)hal_get_cycles();
491if( CONFIG_DEBUG_CLUSTER_PROCESS_COPIES < cycle )
492printk("\n[DBG] %s exit / cluster %x / process %x / cycle %d\n",
493__FUNCTION__ , local_cxy , process , cycle );
494#endif
495
496}  // end cluster_process_copies_link()
497
498/////////////////////////////////////////////////////////
499void cluster_process_copies_unlink( process_t * process )
500{
501    uint32_t irq_state;
502    pmgr_t * pm = &LOCAL_CLUSTER->pmgr;
503
504#if CONFIG_DEBUG_CLUSTER_PROCESS_COPIES
505uint32_t cycle = (uint32_t)hal_get_cycles();
506if( CONFIG_DEBUG_CLUSTER_PROCESS_COPIES < cycle )
507printk("\n[DBG] %s enters / cluster %x / process %x / cycle %d\n",
508__FUNCTION__ , local_cxy , process , cycle );
509#endif
510
511    // get owner cluster identifier CXY and process LPID
512    pid_t    pid        = process->pid;
513    cxy_t    owner_cxy  = CXY_FROM_PID( pid );
514    lpid_t   lpid       = LPID_FROM_PID( pid );
515
516    // get extended pointer on lock protecting copies_list[lpid]
517    xptr_t copies_lock  = XPTR( owner_cxy , &pm->copies_lock[lpid] );
518
519    // get extended pointer on the local copies_list entry
520    xptr_t copies_entry = XPTR( local_cxy , &process->copies_list );
521
522    // get lock protecting copies_list[lpid]
523    remote_spinlock_lock_busy( copies_lock , &irq_state );
524
525    // remove copy from copies_list
526    xlist_unlink( copies_entry );
527    hal_remote_atomic_add( XPTR( owner_cxy , &pm->copies_nr[lpid] ) , -1 );
528
529    // release lock protecting copies_list[lpid]
530    remote_spinlock_unlock_busy( copies_lock , irq_state );
531
532#if CONFIG_DEBUG_CLUSTER_PROCESS_COPIES
533cycle = (uint32_t)hal_get_cycles();
534if( CONFIG_DEBUG_CLUSTER_PROCESS_COPIES < cycle )
535printk("\n[DBG] %s exit / cluster %x / process %x / cycle %d\n",
536__FUNCTION__ , local_cxy , process , cycle );
537#endif
538
539}  // end cluster_process_copies_unlink()
540
541///////////////////////////////////////////
542void cluster_processes_display( cxy_t cxy )
543{
544    xptr_t        root_xp;
545    xptr_t        iter_xp;
546    xptr_t        process_xp;     
547
548    // get extended pointer on root of process in cluster cxy
549    root_xp = XPTR( cxy , &LOCAL_CLUSTER->pmgr.local_root );
550
551    // skip one line
552    printk("\n***** processes in cluster %x / cycle %d\n", cxy , (uint32_t)hal_get_cycles() );
553
554    // loop on all reference processes in cluster cxy
555    XLIST_FOREACH( root_xp , iter_xp )
556    {
557        process_xp = XLIST_ELEMENT( iter_xp , process_t , local_list );
558        process_display( process_xp );
559    }
560}  // end cluster_processes_display()
561
562
Note: See TracBrowser for help on using the repository browser.