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

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

blip

File size: 13.8 KB
RevLine 
[1]1/*
2 * cluster.c - Cluster-Manager related operations
[19]3 *
[1]4 * Author  Ghassan Almaless (2008,2009,2010,2011,2012)
5 *         Mohamed Lamine Karaoui (2015)
[23]6 *         Alain Greiner (2016,2017)
[1]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
[14]26#include <kernel_config.h>
[1]27#include <hal_types.h>
28#include <hal_atomic.h>
29#include <hal_special.h>
[50]30#include <hal_ppm.h>
[407]31#include <remote_fifo.h>
[1]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
[408]47/////////////////////////////////////////////////////////////////////////////////////
[1]48// Extern global variables
[408]49/////////////////////////////////////////////////////////////////////////////////////
[1]50
[23]51extern process_t process_zero;     // allocated in kernel_init.c file
[1]52
53
54/////////////////////////////////////////////////
55error_t cluster_init( struct boot_info_s * info )
56{
[428]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
[1]63
64        cluster_t * cluster = LOCAL_CLUSTER;
65
66    // initialize cluster global parameters
[19]67        cluster->paddr_width     = info->paddr_width;
[1]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
[428]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
[1]85    // initialize cluster local parameters
86        cluster->cores_nr        = info->cores_nr;
87
[19]88    // initialize the lock protecting the embedded kcm allocator
[1]89        spinlock_init( &cluster->kcm_lock );
90
[407]91cluster_dmsg("\n[DBG] %s for cluster %x enters\n",
92__FUNCTION__ , local_cxy );
[50]93
[19]94    // initialises DQDT
95    cluster->dqdt_root_level = dqdt_init( info->x_size,
96                                          info->y_size,
[1]97                                          info->y_width );
98    cluster->threads_var = 0;
99    cluster->pages_var   = 0;
100
101    // initialises embedded PPM
[50]102        error = hal_ppm_init( info );
[1]103
[50]104    if( error )
105    {
106        printk("\n[ERROR] in %s : cannot initialize PPM in cluster %x\n",
107               __FUNCTION__ , local_cxy );
108        return ENOMEM;
109    }
110
[407]111cluster_dmsg("\n[DBG] %s : PPM initialized in cluster %x at cycle %d\n",
112__FUNCTION__ , local_cxy , hal_get_cycles() );
[50]113
[1]114    // initialises embedded KHM
115        khm_init( &cluster->khm );
[19]116
[407]117    cluster_dmsg("\n[DBG] %s : KHM initialized in cluster %x at cycle %d\n",
[101]118                 __FUNCTION__ , local_cxy , hal_get_cycles() );
[50]119
[19]120    // initialises embedded KCM
[5]121        kcm_init( &cluster->kcm , KMEM_KCM );
[1]122
[407]123    cluster_dmsg("\n[DBG] %s : KCM initialized in cluster %x at cycle %d\n",
[101]124                 __FUNCTION__ , local_cxy , hal_get_cycles() );
[50]125
[296]126    // initialises all cores descriptors
[1]127        for( lid = 0 ; lid < cluster->cores_nr; lid++ )
128        {
129                core_init( &cluster->core_tbl[lid],    // target core descriptor
130                       lid,                        // local core index
131                       info->core[lid].gid );      // gid from boot_info_t
132        }
[19]133
[407]134cluster_dmsg("\n[DBG] %s : cores initialized in cluster %x at cycle %d\n",
135__FUNCTION__ , local_cxy , hal_get_cycles() );
[50]136
[1]137    // initialises RPC fifo
[407]138        local_fifo_init( &cluster->rpc_fifo );
[279]139    cluster->rpc_threads = 0;
[1]140
[407]141cluster_dmsg("\n[DBG] %s : RPC fifo inialized in cluster %x at cycle %d\n",
142__FUNCTION__ , local_cxy , hal_get_cycles() );
[50]143
[1]144    // initialise pref_tbl[] in process manager
145        spinlock_init( &cluster->pmgr.pref_lock );
146    cluster->pmgr.pref_nr = 0;
[19]147    cluster->pmgr.pref_tbl[0] = XPTR( local_cxy , &process_zero );
[1]148    for( lpid = 1 ; lpid < CONFIG_MAX_PROCESS_PER_CLUSTER ; lpid++ )
149    {
150        cluster->pmgr.pref_tbl[lpid] = XPTR_NULL;
151    }
152
153    // initialise local_list in process manager
[23]154        remote_spinlock_init( XPTR( local_cxy , &cluster->pmgr.local_lock ) );
155    xlist_root_init( XPTR( local_cxy , &cluster->pmgr.local_root ) );
[1]156    cluster->pmgr.local_nr = 0;
157
158    // initialise copies_lists in process manager
[101]159    for( lpid = 0 ; lpid < CONFIG_MAX_PROCESS_PER_CLUSTER ; lpid++ )
[1]160    {
161            remote_spinlock_init( XPTR( local_cxy , &cluster->pmgr.copies_lock[lpid] ) );
162        cluster->pmgr.copies_nr[lpid] = 0;
163        xlist_root_init( XPTR( local_cxy , &cluster->pmgr.copies_root[lpid] ) );
[19]164    }
[1]165
[407]166cluster_dmsg("\n[DBG] %s Process Manager initialized in cluster %x at cycle %d\n",
167__FUNCTION__ , local_cxy , hal_get_cycles() );
[50]168
[124]169    hal_fence();
[1]170
171        return 0;
172} // end cluster_init()
173
174////////////////////////////////////////
175bool_t cluster_is_undefined( cxy_t cxy )
176{
177    cluster_t * cluster = LOCAL_CLUSTER;
178
179    uint32_t y_width = cluster->y_width;
180
181    uint32_t x = cxy >> y_width;
182    uint32_t y = cxy & ((1<<y_width)-1);
183
[19]184    if( x >= cluster->x_size ) return true;
185    if( y >= cluster->y_size ) return true;
[1]186
187    return false;
188}
189
190////////////////////////////////////////////////////////////////////////////////////
191//  Cores related functions
192////////////////////////////////////////////////////////////////////////////////////
193
194/////////////////////////////////
195lid_t cluster_select_local_core()
196{
197    uint32_t min = 100;
198    lid_t    sel = 0;
199    lid_t    lid;
200
201    cluster_t * cluster = LOCAL_CLUSTER;
202
203    for( lid = 0 ; lid < cluster->cores_nr ; lid++ )
204    {
205        if( cluster->core_tbl[lid].usage < min )
206        {
207            min = cluster->core_tbl[lid].usage;
208            sel = lid;
209        }
[19]210    }
[1]211    return sel;
212}
213
214////////////////////////////////////////////////////////////////////////////////////
[428]215//  Process related functions
[1]216////////////////////////////////////////////////////////////////////////////////////
217
218//////////////////////////////////////////////////////////
219xptr_t cluster_get_reference_process_from_pid( pid_t pid )
[19]220{
[23]221    xptr_t ref_xp;   // extended pointer on reference process descriptor
[1]222
223    cluster_t * cluster = LOCAL_CLUSTER;
224
225    // get owner cluster and lpid
226    cxy_t  owner_cxy = CXY_FROM_PID( pid );
227    lpid_t lpid      = LPID_FROM_PID( pid );
228
[19]229    // Check valid PID
[23]230    if( lpid >= CONFIG_MAX_PROCESS_PER_CLUSTER )  return XPTR_NULL;
[1]231
232    if( local_cxy == owner_cxy )   // local cluster is owner cluster
[19]233    {
[23]234        ref_xp = cluster->pmgr.pref_tbl[lpid];
[1]235    }
236    else                              // use a remote_lwd to access owner cluster
237    {
[23]238        ref_xp = (xptr_t)hal_remote_lwd( XPTR( owner_cxy , &cluster->pmgr.pref_tbl[lpid] ) );
[1]239    }
240
[23]241    return ref_xp;
[1]242}
243
[416]244///////////////////////////////////////////////
245error_t cluster_pid_alloc( process_t * process,
246                           pid_t     * pid )
[1]247{
248    lpid_t      lpid;
249    bool_t      found;
250
251    pmgr_t    * pm         = &LOCAL_CLUSTER->pmgr;
252
253    // get the process manager lock
254    spinlock_lock( &pm->pref_lock );
255
256    // search an empty slot
257    found = false;
258    for( lpid = 0 ; lpid < CONFIG_MAX_PROCESS_PER_CLUSTER ; lpid++ )
259    {
260        if( pm->pref_tbl[lpid] == XPTR_NULL )
261        {
262            found = true;
263            break;
264        }
265    }
266
267    if( found )
268    {
269        // register process in pref_tbl[]
[416]270        pm->pref_tbl[lpid] = XPTR( local_cxy , process );
[1]271        pm->pref_nr++;
272
273        // returns pid
274        *pid = PID( local_cxy , lpid );
275
[416]276        // release the processs_manager lock
277        spinlock_unlock( &pm->pref_lock );
278
279        return 0;
[1]280    }
281    else
282    {
[416]283        // release the processs_manager lock
284        spinlock_unlock( &pm->pref_lock );
285
286        return -1;
[19]287    }
[1]288
289} // end cluster_pid_alloc()
290
291/////////////////////////////////////
292void cluster_pid_release( pid_t pid )
293{
294    cxy_t  owner_cxy  = CXY_FROM_PID( pid );
295    lpid_t lpid       = LPID_FROM_PID( pid );
296
[409]297    pmgr_t  * pm = &LOCAL_CLUSTER->pmgr;
298
[1]299    // check pid argument
[409]300    assert( (lpid < CONFIG_MAX_PROCESS_PER_CLUSTER) && (owner_cxy == local_cxy) ,
301    __FUNCTION__ , "illegal PID" );
[1]302
303    // get the process manager lock
304    spinlock_lock( &pm->pref_lock );
305
306    // remove process from pref_tbl[]
307    pm->pref_tbl[lpid] = XPTR_NULL;
308    pm->pref_nr--;
309
310    // release the processs_manager lock
311    spinlock_unlock( &pm->pref_lock );
312
313} // end cluster_pid_release()
314
315///////////////////////////////////////////////////////////
316process_t * cluster_get_local_process_from_pid( pid_t pid )
317{
[23]318    xptr_t         process_xp;
319    process_t    * process_ptr;
320    xptr_t         root_xp;
321    xptr_t         iter_xp;
322    bool_t         found;
[19]323
[23]324    found   = false;
325    root_xp = XPTR( local_cxy , &LOCAL_CLUSTER->pmgr.local_root );
326
327    XLIST_FOREACH( root_xp , iter_xp )
[1]328    {
[23]329        process_xp  = XLIST_ELEMENT( iter_xp , process_t , local_list );
330        process_ptr = (process_t *)GET_PTR( process_xp );
331        if( process_ptr->pid == pid )
[1]332        {
[23]333            found = true;
[1]334            break;
335        }
336    }
337
[23]338    if (found ) return process_ptr;
339    else        return NULL;
340
[1]341}  // end cluster_get_local_process_from_pid()
342
343//////////////////////////////////////////////////////
344void cluster_process_local_link( process_t * process )
345{
[407]346    uint32_t irq_state;
[1]347    pmgr_t * pm = &LOCAL_CLUSTER->pmgr;
348
349    // get lock protecting the process manager local list
[407]350    remote_spinlock_lock_busy( XPTR( local_cxy , &pm->local_lock ) , & irq_state );
[1]351
[428]352    xlist_add_last( XPTR( local_cxy , &pm->local_root ),
353                    XPTR( local_cxy , &process->local_list ) );
[1]354    pm->local_nr++;
355
356    // release lock protecting the process manager local list
[407]357    remote_spinlock_unlock_busy( XPTR( local_cxy , &pm->local_lock ) , irq_state );
[1]358}
359
360////////////////////////////////////////////////////////
361void cluster_process_local_unlink( process_t * process )
362{
[407]363    uint32_t irq_state;
[1]364    pmgr_t * pm = &LOCAL_CLUSTER->pmgr;
365
366    // get lock protecting the process manager local list
[407]367    remote_spinlock_lock_busy( XPTR( local_cxy , &pm->local_lock ) , &irq_state );
[1]368
[23]369    xlist_unlink( XPTR( local_cxy , &process->local_list ) );
[1]370    pm->local_nr--;
371
372    // release lock protecting the process manager local list
[407]373    remote_spinlock_unlock_busy( XPTR( local_cxy , &pm->local_lock ) , irq_state );
[1]374}
375
376///////////////////////////////////////////////////////
377void cluster_process_copies_link( process_t * process )
378{
[407]379    uint32_t irq_state;
[1]380    pmgr_t * pm = &LOCAL_CLUSTER->pmgr;
381
382    // get owner cluster identifier CXY and process LPID
383    pid_t    pid        = process->pid;
384    cxy_t    owner_cxy  = CXY_FROM_PID( pid );
385    lpid_t   lpid       = LPID_FROM_PID( pid );
386
387    // get extended pointer on lock protecting copies_list[lpid]
[120]388    xptr_t copies_lock  = XPTR( owner_cxy , &pm->copies_lock[lpid] );
[1]389
390    // get extended pointer on the copies_list[lpid] root
[120]391    xptr_t copies_root  = XPTR( owner_cxy , &pm->copies_root[lpid] );
[1]392
393    // get extended pointer on the local copies_list entry
394    xptr_t copies_entry = XPTR( local_cxy , &process->copies_list );
395
[19]396    // get lock protecting copies_list[lpid]
[407]397    remote_spinlock_lock_busy( copies_lock , &irq_state );
[1]398
399    xlist_add_first( copies_root , copies_entry );
400    hal_remote_atomic_add( XPTR( owner_cxy , &pm->copies_nr[lpid] ) , 1 );
401
[19]402    // release lock protecting copies_list[lpid]
[407]403    remote_spinlock_unlock_busy( copies_lock , irq_state );
[1]404}
405
406/////////////////////////////////////////////////////////
407void cluster_process_copies_unlink( process_t * process )
408{
[407]409    uint32_t irq_state;
[1]410    pmgr_t * pm = &LOCAL_CLUSTER->pmgr;
411
412    // get owner cluster identifier CXY and process LPID
413    pid_t    pid        = process->pid;
414    cxy_t    owner_cxy  = CXY_FROM_PID( pid );
415    lpid_t   lpid       = LPID_FROM_PID( pid );
416
417    // get extended pointer on lock protecting copies_list[lpid]
418    xptr_t copies_lock  = hal_remote_lwd( XPTR( owner_cxy , &pm->copies_lock[lpid] ) );
419
420    // get extended pointer on the local copies_list entry
421    xptr_t copies_entry = XPTR( local_cxy , &process->copies_list );
422
[19]423    // get lock protecting copies_list[lpid]
[407]424    remote_spinlock_lock_busy( copies_lock , &irq_state );
[1]425
426    xlist_unlink( copies_entry );
427    hal_remote_atomic_add( XPTR( owner_cxy , &pm->copies_nr[lpid] ) , -1 );
428
[19]429    // release lock protecting copies_list[lpid]
[407]430    remote_spinlock_unlock_busy( copies_lock , irq_state );
[1]431}
432
[428]433///////////////////////////////////////////
434void cluster_processes_display( cxy_t cxy )
[1]435{
[428]436    xptr_t        root_xp;
437    xptr_t        iter_xp;
438    xptr_t        process_xp;     
[1]439
[428]440    // get extended pointer on root of process in cluster cxy
441    root_xp = XPTR( cxy , &LOCAL_CLUSTER->pmgr.local_root );
[1]442
[428]443    // skip one line
444    printk("\n");
[1]445
[428]446    // loop on all reference processes in cluster cxy
447    XLIST_FOREACH( root_xp , iter_xp )
448    {
449        process_xp = XLIST_ELEMENT( iter_xp , process_t , local_list );
450        process_display( process_xp );
451    }
452}  // end cluster_processes_display()
[1]453
[19]454
Note: See TracBrowser for help on using the repository browser.