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

Last change on this file since 436 was 436, checked in by alain, 7 years ago

1) improve the threads and process destruction mechanism.
2) introduce FIFOs in the soclib_tty driver.

File size: 17.0 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)
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 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
116cycle = (uint32_t)hal_get_cycles();
117if( CONFIG_DEBUG_CLUSTER_INIT < cycle )
118cluster_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
143cycle = (uint32_t)hal_get_cycles();
144if( CONFIG_DEBUG_CLUSTER_INIT < cycle )
145cluster_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
153cluster_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
179cycle = (uint32_t)hal_get_cycles();
180if( CONFIG_DEBUG_CLUSTER_INIT < cycle )
181cluster_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////////////////////////////////////////
191bool_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/////////////////////////////////
211lid_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//////////////////////////////////////////////////////
236xptr_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;       // xptr 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 , &current_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}  // end cluster_get_owner_process_from_pid()
281
282//////////////////////////////////////////////////////////
283xptr_t cluster_get_reference_process_from_pid( pid_t pid )
284{
285    xptr_t ref_xp;   // extended pointer on reference process descriptor
286
287    cluster_t * cluster = LOCAL_CLUSTER;
288
289    // get owner cluster and lpid
290    cxy_t  owner_cxy = CXY_FROM_PID( pid );
291    lpid_t lpid      = LPID_FROM_PID( pid );
292
293    // Check valid PID
294    if( lpid >= CONFIG_MAX_PROCESS_PER_CLUSTER )  return XPTR_NULL;
295
296    if( local_cxy == owner_cxy )   // local cluster is owner cluster
297    {
298        ref_xp = cluster->pmgr.pref_tbl[lpid];
299    }
300    else                              // use a remote_lwd to access owner cluster
301    {
302        ref_xp = (xptr_t)hal_remote_lwd( XPTR( owner_cxy , &cluster->pmgr.pref_tbl[lpid] ) );
303    }
304
305    return ref_xp;
306}
307
308///////////////////////////////////////////////
309error_t cluster_pid_alloc( process_t * process,
310                           pid_t     * pid )
311{
312    lpid_t      lpid;
313    bool_t      found;
314
315    pmgr_t    * pm         = &LOCAL_CLUSTER->pmgr;
316
317    // get the process manager lock
318    spinlock_lock( &pm->pref_lock );
319
320    // search an empty slot
321    found = false;
322    for( lpid = 0 ; lpid < CONFIG_MAX_PROCESS_PER_CLUSTER ; lpid++ )
323    {
324        if( pm->pref_tbl[lpid] == XPTR_NULL )
325        {
326            found = true;
327            break;
328        }
329    }
330
331    if( found )
332    {
333        // register process in pref_tbl[]
334        pm->pref_tbl[lpid] = XPTR( local_cxy , process );
335        pm->pref_nr++;
336
337        // returns pid
338        *pid = PID( local_cxy , lpid );
339
340        // release the processs_manager lock
341        spinlock_unlock( &pm->pref_lock );
342
343        return 0;
344    }
345    else
346    {
347        // release the processs_manager lock
348        spinlock_unlock( &pm->pref_lock );
349
350        return -1;
351    }
352
353} // end cluster_pid_alloc()
354
355/////////////////////////////////////
356void cluster_pid_release( pid_t pid )
357{
358    cxy_t  owner_cxy  = CXY_FROM_PID( pid );
359    lpid_t lpid       = LPID_FROM_PID( pid );
360
361    pmgr_t  * pm = &LOCAL_CLUSTER->pmgr;
362
363    // check pid argument
364    assert( (lpid < CONFIG_MAX_PROCESS_PER_CLUSTER) && (owner_cxy == local_cxy) ,
365    __FUNCTION__ , "illegal PID" );
366
367    // get the process manager lock
368    spinlock_lock( &pm->pref_lock );
369
370    // remove process from pref_tbl[]
371    pm->pref_tbl[lpid] = XPTR_NULL;
372    pm->pref_nr--;
373
374    // release the processs_manager lock
375    spinlock_unlock( &pm->pref_lock );
376
377} // end cluster_pid_release()
378
379///////////////////////////////////////////////////////////
380process_t * cluster_get_local_process_from_pid( pid_t pid )
381{
382    xptr_t         process_xp;
383    process_t    * process_ptr;
384    xptr_t         root_xp;
385    xptr_t         iter_xp;
386    bool_t         found;
387
388    found   = false;
389    root_xp = XPTR( local_cxy , &LOCAL_CLUSTER->pmgr.local_root );
390
391    XLIST_FOREACH( root_xp , iter_xp )
392    {
393        process_xp  = XLIST_ELEMENT( iter_xp , process_t , local_list );
394        process_ptr = (process_t *)GET_PTR( process_xp );
395        if( process_ptr->pid == pid )
396        {
397            found = true;
398            break;
399        }
400    }
401
402    if (found ) return process_ptr;
403    else        return NULL;
404
405}  // end cluster_get_local_process_from_pid()
406
407//////////////////////////////////////////////////////
408void cluster_process_local_link( process_t * process )
409{
410    uint32_t irq_state;
411    pmgr_t * pm = &LOCAL_CLUSTER->pmgr;
412
413    // get lock protecting the process manager local list
414    remote_spinlock_lock_busy( XPTR( local_cxy , &pm->local_lock ) , & irq_state );
415
416    xlist_add_last( XPTR( local_cxy , &pm->local_root ),
417                    XPTR( local_cxy , &process->local_list ) );
418    pm->local_nr++;
419
420    // release lock protecting the process manager local list
421    remote_spinlock_unlock_busy( XPTR( local_cxy , &pm->local_lock ) , irq_state );
422}
423
424////////////////////////////////////////////////////////
425void cluster_process_local_unlink( process_t * process )
426{
427    uint32_t irq_state;
428    pmgr_t * pm = &LOCAL_CLUSTER->pmgr;
429
430    // get lock protecting the process manager local list
431    remote_spinlock_lock_busy( XPTR( local_cxy , &pm->local_lock ) , &irq_state );
432
433    xlist_unlink( XPTR( local_cxy , &process->local_list ) );
434    pm->local_nr--;
435
436    // release lock protecting the process manager local list
437    remote_spinlock_unlock_busy( XPTR( local_cxy , &pm->local_lock ) , irq_state );
438}
439
440///////////////////////////////////////////////////////
441void cluster_process_copies_link( process_t * process )
442{
443    reg_t    irq_state;
444    pmgr_t * pm = &LOCAL_CLUSTER->pmgr;
445
446#if CONFIG_DEBUG_CLUSTER_PROCESS_COPIES
447uint32_t cycle = (uint32_t)hal_get_cycles();
448if( CONFIG_DEBUG_CLUSTER_PROCESS_COPIES < cycle )
449printk("\n[DBG] %s enters / cluster %x / process %x / cycle %d\n",
450__FUNCTION__ , local_cxy , process , cycle );
451#endif
452
453    // get owner cluster identifier CXY and process LPID
454    pid_t    pid        = process->pid;
455    cxy_t    owner_cxy  = CXY_FROM_PID( pid );
456    lpid_t   lpid       = LPID_FROM_PID( pid );
457
458    // get extended pointer on lock protecting copies_list[lpid]
459    xptr_t copies_lock  = XPTR( owner_cxy , &pm->copies_lock[lpid] );
460
461    // get extended pointer on the copies_list[lpid] root
462    xptr_t copies_root  = XPTR( owner_cxy , &pm->copies_root[lpid] );
463
464    // get extended pointer on the local copies_list entry
465    xptr_t copies_entry = XPTR( local_cxy , &process->copies_list );
466
467    // get lock protecting copies_list[lpid]
468    remote_spinlock_lock_busy( copies_lock , &irq_state );
469
470    // add copy to copies_list
471    xlist_add_first( copies_root , copies_entry );
472    hal_remote_atomic_add( XPTR( owner_cxy , &pm->copies_nr[lpid] ) , 1 );
473
474    // release lock protecting copies_list[lpid]
475    remote_spinlock_unlock_busy( copies_lock , irq_state );
476
477#if CONFIG_DEBUG_CLUSTER_PROCESS_COPIES
478cycle = (uint32_t)hal_get_cycles();
479if( CONFIG_DEBUG_CLUSTER_PROCESS_COPIES < cycle )
480printk("\n[DBG] %s exit / cluster %x / process %x / cycle %d\n",
481__FUNCTION__ , local_cxy , process , cycle );
482#endif
483
484}  // end cluster_process_copies_link()
485
486/////////////////////////////////////////////////////////
487void cluster_process_copies_unlink( process_t * process )
488{
489    uint32_t irq_state;
490    pmgr_t * pm = &LOCAL_CLUSTER->pmgr;
491
492#if CONFIG_DEBUG_CLUSTER_PROCESS_COPIES
493uint32_t cycle = (uint32_t)hal_get_cycles();
494if( CONFIG_DEBUG_CLUSTER_PROCESS_COPIES < cycle )
495printk("\n[DBG] %s enters / cluster %x / process %x / cycle %d\n",
496__FUNCTION__ , local_cxy , process , cycle );
497#endif
498
499    // get owner cluster identifier CXY and process LPID
500    pid_t    pid        = process->pid;
501    cxy_t    owner_cxy  = CXY_FROM_PID( pid );
502    lpid_t   lpid       = LPID_FROM_PID( pid );
503
504    // get extended pointer on lock protecting copies_list[lpid]
505    xptr_t copies_lock  = XPTR( owner_cxy , &pm->copies_lock[lpid] );
506
507    // get extended pointer on the local copies_list entry
508    xptr_t copies_entry = XPTR( local_cxy , &process->copies_list );
509
510    // get lock protecting copies_list[lpid]
511    remote_spinlock_lock_busy( copies_lock , &irq_state );
512
513    // remove copy from copies_list
514    xlist_unlink( copies_entry );
515    hal_remote_atomic_add( XPTR( owner_cxy , &pm->copies_nr[lpid] ) , -1 );
516
517    // release lock protecting copies_list[lpid]
518    remote_spinlock_unlock_busy( copies_lock , irq_state );
519
520#if CONFIG_DEBUG_CLUSTER_PROCESS_COPIES
521cycle = (uint32_t)hal_get_cycles();
522if( CONFIG_DEBUG_CLUSTER_PROCESS_COPIES < cycle )
523printk("\n[DBG] %s exit / cluster %x / process %x / cycle %d\n",
524__FUNCTION__ , local_cxy , process , cycle );
525#endif
526
527}  // end cluster_process_copies_unlink()
528
529///////////////////////////////////////////
530void cluster_processes_display( cxy_t cxy )
531{
532    xptr_t        root_xp;
533    xptr_t        iter_xp;
534    xptr_t        process_xp;     
535
536    // get extended pointer on root of process in cluster cxy
537    root_xp = XPTR( cxy , &LOCAL_CLUSTER->pmgr.local_root );
538
539    // skip one line
540    printk("\n***** processes in cluster %x / cycle %d\n", cxy , (uint32_t)hal_get_cycles() );
541
542    // loop on all reference processes in cluster cxy
543    XLIST_FOREACH( root_xp , iter_xp )
544    {
545        process_xp = XLIST_ELEMENT( iter_xp , process_t , local_list );
546        process_display( process_xp );
547    }
548}  // end cluster_processes_display()
549
550
Note: See TracBrowser for help on using the repository browser.