source: trunk/kernel/kern/process.c @ 519

Last change on this file since 519 was 514, checked in by viala@…, 6 years ago

[process] fix undefined/declared variable in process_register_thread.

We made a typo.

Found with GCC:

kern/process.c: In function 'process_register_thread':
kern/process.c:1054:7: warning: 'type' may be used uninitialized in this function [-Wmaybe-uninitialized]

if( type == THREAD_IDLE ) spinlock_lock_busy( &process->th_lock , &save_sr );

File size: 72.8 KB
RevLine 
[1]1/*
2 * process.c - process related management
[172]3 *
[1]4 * Authors  Ghassan Almaless (2008,2009,2010,2011,2012)
5 *          Mohamed Lamine Karaoui (2015)
[433]6 *          Alain Greiner (2016,2017,2018)
[1]7 *
8 * Copyright (c) UPMC Sorbonne Universites
9 *
[409]10 * This file is part of ALMOS-MKH.
[1]11 *
[172]12 * ALMOS-MKH is free software; you can redistribute it and/or modify it
[1]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 *
[172]16 * ALMOS-MKH is distributed in the hope that it will be useful, but
[1]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
[172]22 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
[1]23 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 */
25
[14]26#include <kernel_config.h>
[457]27#include <hal_kernel_types.h>
[1]28#include <hal_remote.h>
29#include <hal_uspace.h>
[409]30#include <hal_irqmask.h>
[1]31#include <errno.h>
32#include <printk.h>
33#include <memcpy.h>
34#include <bits.h>
35#include <kmem.h>
36#include <page.h>
37#include <vmm.h>
38#include <vfs.h>
39#include <core.h>
40#include <thread.h>
[428]41#include <chdev.h>
[1]42#include <list.h>
[407]43#include <string.h>
[1]44#include <scheduler.h>
45#include <remote_spinlock.h>
46#include <dqdt.h>
47#include <cluster.h>
48#include <ppm.h>
49#include <boot_info.h>
50#include <process.h>
51#include <elf.h>
[23]52#include <syscalls.h>
[435]53#include <shared_syscalls.h>
[1]54
55//////////////////////////////////////////////////////////////////////////////////////////
56// Extern global variables
57//////////////////////////////////////////////////////////////////////////////////////////
58
[428]59extern process_t           process_zero;     // allocated in kernel_init.c
60extern chdev_directory_t   chdev_dir;        // allocated in kernel_init.c
[1]61
62//////////////////////////////////////////////////////////////////////////////////////////
63// Process initialisation related functions
64//////////////////////////////////////////////////////////////////////////////////////////
65
66///////////////////////////
[503]67process_t * process_alloc( void )
[1]68{
69        kmem_req_t   req;
70
71    req.type  = KMEM_PROCESS;
72        req.size  = sizeof(process_t);
73        req.flags = AF_KERNEL;
74
75    return (process_t *)kmem_alloc( &req );
76}
77
78////////////////////////////////////////
79void process_free( process_t * process )
80{
81    kmem_req_t  req;
82
83        req.type = KMEM_PROCESS;
84        req.ptr  = process;
85        kmem_free( &req );
86}
87
[101]88/////////////////////////////////////////////////
89void process_reference_init( process_t * process,
90                             pid_t       pid,
[457]91                             xptr_t      parent_xp )
[1]92{
[428]93    cxy_t       parent_cxy;
94    process_t * parent_ptr;
[407]95    xptr_t      stdin_xp;
96    xptr_t      stdout_xp;
97    xptr_t      stderr_xp;
98    uint32_t    stdin_id;
99    uint32_t    stdout_id;
100    uint32_t    stderr_id;
[415]101    error_t     error;
[428]102    uint32_t    txt_id;
103    char        rx_path[40];
104    char        tx_path[40];
[440]105    xptr_t      file_xp;
[428]106    xptr_t      chdev_xp;
107    chdev_t *   chdev_ptr;
108    cxy_t       chdev_cxy;
109    pid_t       parent_pid;
[1]110
[428]111    // get parent process cluster and local pointer
112    parent_cxy = GET_CXY( parent_xp );
[435]113    parent_ptr = GET_PTR( parent_xp );
[204]114
[457]115    // get parent_pid
[428]116    parent_pid = hal_remote_lw( XPTR( parent_cxy , &parent_ptr->pid ) );
117
[438]118#if DEBUG_PROCESS_REFERENCE_INIT
[433]119uint32_t cycle = (uint32_t)hal_get_cycles();
[438]120if( DEBUG_PROCESS_REFERENCE_INIT )
[457]121printk("\n[DBG] %s : thread %x in process %x enter to initalialize process %x / cycle %d\n",
122__FUNCTION__, CURRENT_THREAD->trdid, parent_pid , pid , cycle );
[433]123#endif
[428]124
125    // initialize PID, REF_XP, PARENT_XP, and STATE
[433]126        process->pid        = pid;
127    process->ref_xp     = XPTR( local_cxy , process );
[443]128    process->owner_xp   = XPTR( local_cxy , process );
[433]129    process->parent_xp  = parent_xp;
130    process->term_state = 0;
[428]131
[409]132    // initialize vmm as empty
[415]133    error = vmm_init( process );
[492]134    assert( (error == 0) , "cannot initialize VMM\n" );
[415]135 
[438]136#if (DEBUG_PROCESS_REFERENCE_INIT & 1)
[433]137cycle = (uint32_t)hal_get_cycles();
[438]138if( DEBUG_PROCESS_REFERENCE_INIT )
[457]139printk("\n[DBG] %s : thread %x in process %x / vmm empty for process %x / cycle %d\n", 
140__FUNCTION__, CURRENT_THREAD->trdid, parent_pid , cycle );
[433]141#endif
[1]142
[409]143    // initialize fd_array as empty
[408]144    process_fd_init( process );
[1]145
[428]146    // define the stdin/stdout/stderr pseudo files <=> select a TXT terminal.
[457]147    if( (pid == 1) || (parent_pid == 1)) // INIT or KSH process
[408]148    {
[457]149        // allocate a TXT channel
150        if( pid == 1 )  txt_id = 0;                     // INIT
151        else            txt_id = process_txt_alloc();   // KSH
[428]152
[457]153        // attach process to TXT
[428]154        process_txt_attach( process , txt_id ); 
155
[457]156#if (DEBUG_PROCESS_REFERENCE_INIT & 1)
157cycle = (uint32_t)hal_get_cycles();
158if( DEBUG_PROCESS_REFERENCE_INIT )
159printk("\n[DBG] %s : thread %x in process %x / process %x attached to TXT%d / cycle %d\n", 
160__FUNCTION__, CURRENT_THREAD->trdid, parent_pid, pid, txt_id, cycle );
161#endif
162
163
164
[428]165        // build path to TXT_RX[i] and TXT_TX[i] chdevs
166        snprintf( rx_path , 40 , "/dev/external/txt%d_rx", txt_id );
167        snprintf( tx_path , 40 , "/dev/external/txt%d_tx", txt_id );
168
169        // create stdin pseudo file         
170        error = vfs_open( process,
171                           rx_path,
[408]172                           O_RDONLY, 
173                           0,                // FIXME chmod
174                           &stdin_xp, 
175                           &stdin_id );
[1]176
[492]177        assert( (error == 0) , "cannot open stdin pseudo file" );
178        assert( (stdin_id == 0) , "stdin index must be 0" );
[428]179
[440]180#if (DEBUG_PROCESS_REFERENCE_INIT & 1)
181cycle = (uint32_t)hal_get_cycles();
182if( DEBUG_PROCESS_REFERENCE_INIT )
[457]183printk("\n[DBG] %s : thread %x in process %x / stdin open for process %x / cycle %d\n", 
184__FUNCTION__, CURRENT_THREAD->trdid, parent_pid, pid, cycle );
[440]185#endif
186
[428]187        // create stdout pseudo file         
188        error = vfs_open( process,
189                           tx_path,
[408]190                           O_WRONLY, 
191                           0,                // FIXME chmod
192                           &stdout_xp, 
193                           &stdout_id );
[1]194
[492]195        assert( (error == 0) , "cannot open stdout pseudo file" );
196        assert( (stdout_id == 1) , "stdout index must be 1" );
[428]197
[440]198#if (DEBUG_PROCESS_REFERENCE_INIT & 1)
199cycle = (uint32_t)hal_get_cycles();
200if( DEBUG_PROCESS_REFERENCE_INIT )
[457]201printk("\n[DBG] %s : thread %x in process %x / stdout open for process %x / cycle %d\n", 
202__FUNCTION__, CURRENT_THREAD->trdid, parent_pid, pid, cycle );
[440]203#endif
204
[428]205        // create stderr pseudo file         
206        error = vfs_open( process,
207                           tx_path,
[408]208                           O_WRONLY, 
209                           0,                // FIXME chmod
210                           &stderr_xp, 
211                           &stderr_id );
[428]212
[492]213        assert( (error == 0) , "cannot open stderr pseudo file" );
214        assert( (stderr_id == 2) , "stderr index must be 2" );
[428]215
[440]216#if (DEBUG_PROCESS_REFERENCE_INIT & 1)
217cycle = (uint32_t)hal_get_cycles();
218if( DEBUG_PROCESS_REFERENCE_INIT )
[457]219printk("\n[DBG] %s : thread %x in process %x / stderr open for process %x / cycle %d\n", 
220__FUNCTION__, CURRENT_THREAD->trdid, parent_pid, pid, cycle );
[440]221#endif
222
[408]223    }
[428]224    else                                            // normal user process
[408]225    {
[457]226        // get extended pointer on stdin pseudo file in parent process
227        file_xp = (xptr_t)hal_remote_lwd( XPTR( parent_cxy , &parent_ptr->fd_array.array[0] ) );
[440]228
[457]229        // get extended pointer on parent process TXT chdev
[440]230        chdev_xp = chdev_from_file( file_xp );
[428]231 
232        // get cluster and local pointer on chdev
233        chdev_cxy = GET_CXY( chdev_xp );
[435]234        chdev_ptr = GET_PTR( chdev_xp );
[428]235 
236        // get TXT terminal index
237        txt_id = hal_remote_lw( XPTR( chdev_cxy , &chdev_ptr->channel ) );
[407]238
[428]239        // attach process to TXT[txt_id]
240        process_txt_attach( process , txt_id ); 
[407]241
[457]242        // copy all open files from parent process fd_array to this process
[428]243        process_fd_remote_copy( XPTR( local_cxy , &process->fd_array ),
[457]244                                XPTR( parent_cxy , &parent_ptr->fd_array ) );
[408]245    }
[407]246
[409]247    // initialize specific inodes root and cwd
[457]248    process->vfs_root_xp = (xptr_t)hal_remote_lwd( XPTR( parent_cxy,
249                                                         &parent_ptr->vfs_root_xp ) );
250    process->vfs_cwd_xp  = (xptr_t)hal_remote_lwd( XPTR( parent_cxy,
251                                                         &parent_ptr->vfs_cwd_xp ) );
[409]252    vfs_inode_remote_up( process->vfs_root_xp );
253    vfs_inode_remote_up( process->vfs_cwd_xp );
[408]254
[409]255    remote_rwlock_init( XPTR( local_cxy , &process->cwd_lock ) );
256
[438]257#if (DEBUG_PROCESS_REFERENCE_INIT & 1)
[433]258cycle = (uint32_t)hal_get_cycles();
[438]259if( DEBUG_PROCESS_REFERENCE_INIT )
[433]260printk("\n[DBG] %s : thread %x / fd_array for process %x / cycle %d\n", 
261__FUNCTION__ , CURRENT_THREAD , pid , cycle );
262#endif
[407]263
[408]264    // reset children list root
265    xlist_root_init( XPTR( local_cxy , &process->children_root ) );
266    process->children_nr     = 0;
[428]267    remote_spinlock_init( XPTR( local_cxy , &process->children_lock ) );
[407]268
[408]269    // reset semaphore / mutex / barrier / condvar list roots
270    xlist_root_init( XPTR( local_cxy , &process->sem_root ) );
271    xlist_root_init( XPTR( local_cxy , &process->mutex_root ) );
272    xlist_root_init( XPTR( local_cxy , &process->barrier_root ) );
273    xlist_root_init( XPTR( local_cxy , &process->condvar_root ) );
274    remote_spinlock_init( XPTR( local_cxy , &process->sync_lock ) );
[407]275
[408]276    // register new process in the local cluster manager pref_tbl[]
277    lpid_t lpid = LPID_FROM_PID( pid );
278    LOCAL_CLUSTER->pmgr.pref_tbl[lpid] = XPTR( local_cxy , process );
[407]279
[408]280    // register new process descriptor in local cluster manager local_list
281    cluster_process_local_link( process );
[407]282
[408]283    // register new process descriptor in local cluster manager copies_list
284    cluster_process_copies_link( process );
[172]285
[408]286    // reset th_tbl[] array as empty in process descriptor
[1]287    uint32_t i;
288    for( i = 0 ; i < CONFIG_THREAD_MAX_PER_CLUSTER ; i++ )
289        {
290        process->th_tbl[i] = NULL;
291    }
292    process->th_nr  = 0;
293    spinlock_init( &process->th_lock );
294
[124]295        hal_fence();
[1]296
[438]297#if (DEBUG_PROCESS_REFERENCE_INIT & 1)
[433]298cycle = (uint32_t)hal_get_cycles();
[438]299if( DEBUG_PROCESS_REFERENCE_INIT )
[433]300printk("\n[DBG] %s : thread %x exit / process %x / cycle %d\n", 
301__FUNCTION__ , CURRENT_THREAD , pid , cycle );
302#endif
[101]303
[428]304}  // process_reference_init()
[204]305
[1]306/////////////////////////////////////////////////////
307error_t process_copy_init( process_t * local_process,
308                           xptr_t      reference_process_xp )
309{
[415]310    error_t error;
311
[23]312    // get reference process cluster and local pointer
313    cxy_t       ref_cxy = GET_CXY( reference_process_xp );
[435]314    process_t * ref_ptr = GET_PTR( reference_process_xp );
[1]315
[428]316    // initialize PID, REF_XP, PARENT_XP, and STATE
[433]317    local_process->pid        = hal_remote_lw(  XPTR( ref_cxy , &ref_ptr->pid ) );
318    local_process->parent_xp  = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->parent_xp ) );
319    local_process->ref_xp     = reference_process_xp;
[443]320    local_process->owner_xp   = reference_process_xp;
[433]321    local_process->term_state = 0;
[407]322
[438]323#if DEBUG_PROCESS_COPY_INIT
[433]324uint32_t cycle = (uint32_t)hal_get_cycles();
[438]325if( DEBUG_PROCESS_COPY_INIT )
[433]326printk("\n[DBG] %s : thread %x enter for process %x\n",
327__FUNCTION__ , CURRENT_THREAD , local_process->pid );
328#endif
[407]329
[172]330    // reset local process vmm
[415]331    error = vmm_init( local_process );
[492]332    assert( (error == 0) , "cannot initialize VMM\n");
[1]333
[172]334    // reset process file descriptors array
[23]335        process_fd_init( local_process );
[1]336
[23]337    // reset vfs_root_xp / vfs_bin_xp / vfs_cwd_xp fields
338    local_process->vfs_root_xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->vfs_root_xp ) );
339    local_process->vfs_bin_xp  = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->vfs_bin_xp ) );
340    local_process->vfs_cwd_xp  = XPTR_NULL;
[1]341
342    // reset children list root (not used in a process descriptor copy)
343    xlist_root_init( XPTR( local_cxy , &local_process->children_root ) );
[172]344    local_process->children_nr   = 0;
[428]345    remote_spinlock_init( XPTR( local_cxy , &local_process->children_lock ) );
[1]346
[428]347    // reset children_list (not used in a process descriptor copy)
348    xlist_entry_init( XPTR( local_cxy , &local_process->children_list ) );
[1]349
350    // reset semaphores list root (not used in a process descriptor copy)
351    xlist_root_init( XPTR( local_cxy , &local_process->sem_root ) );
[23]352    xlist_root_init( XPTR( local_cxy , &local_process->mutex_root ) );
353    xlist_root_init( XPTR( local_cxy , &local_process->barrier_root ) );
354    xlist_root_init( XPTR( local_cxy , &local_process->condvar_root ) );
[1]355
[23]356    // reset th_tbl[] array as empty
[1]357    uint32_t i;
358    for( i = 0 ; i < CONFIG_THREAD_MAX_PER_CLUSTER ; i++ )
359        {
360        local_process->th_tbl[i] = NULL;
361    }
362    local_process->th_nr  = 0;
363    spinlock_init( &local_process->th_lock );
364
365    // register new process descriptor in local cluster manager local_list
366    cluster_process_local_link( local_process );
367
368    // register new process descriptor in owner cluster manager copies_list
369    cluster_process_copies_link( local_process );
370
[124]371        hal_fence();
[1]372
[438]373#if DEBUG_PROCESS_COPY_INIT
[433]374cycle = (uint32_t)hal_get_cycles();
[438]375if( DEBUG_PROCESS_COPY_INIT )
[433]376printk("\n[DBG] %s : thread %x exit for process %x\n",
377__FUNCTION__ , CURRENT_THREAD , local_process->pid );
378#endif
[279]379
[1]380    return 0;
381
[204]382} // end process_copy_init()
383
[1]384///////////////////////////////////////////
385void process_destroy( process_t * process )
386{
[428]387    xptr_t      parent_xp;
388    process_t * parent_ptr;
389    cxy_t       parent_cxy;
390    xptr_t      children_lock_xp;
[446]391    xptr_t      children_nr_xp;
[1]392
[437]393    pid_t       pid = process->pid;
394
[492]395        assert( (process->th_nr == 0) ,
[437]396    "process %x in cluster %x has still active threads", pid , local_cxy );
[428]397
[438]398#if DEBUG_PROCESS_DESTROY
[433]399uint32_t cycle = (uint32_t)hal_get_cycles();
[438]400if( DEBUG_PROCESS_DESTROY )
[445]401printk("\n[DBG] %s : thread %x enter for process %x in cluster %x / cycle %d\n",
402__FUNCTION__ , CURRENT_THREAD , pid , local_cxy , cycle );
[433]403#endif
[428]404
[436]405    // remove process from local_list in local cluster manager
406    cluster_process_local_unlink( process );
[1]407
[436]408    // remove process from copies_list in owner cluster manager
409    cluster_process_copies_unlink( process );
[23]410
[450]411    // remove process from children_list
412    // and release PID if owner cluster
[437]413    if( CXY_FROM_PID( pid ) == local_cxy )
[428]414    {
415        // get pointers on parent process
416        parent_xp  = process->parent_xp;
417        parent_cxy = GET_CXY( parent_xp );
418        parent_ptr = GET_PTR( parent_xp );
419
420        // get extended pointer on children_lock in parent process
421        children_lock_xp = XPTR( parent_cxy , &parent_ptr->children_lock );
[446]422        children_nr_xp   = XPTR( parent_cxy , &parent_ptr->children_nr );
[428]423
424        // remove process from children_list
425        remote_spinlock_lock( children_lock_xp );
426        xlist_unlink( XPTR( local_cxy , &process->children_list ) );
[446]427            hal_remote_atomic_add( children_nr_xp , -1 );
[428]428        remote_spinlock_unlock( children_lock_xp );
[450]429
430    // release the process PID to cluster manager
431    cluster_pid_release( pid );
432
[428]433    }
434
[409]435    // FIXME close all open files and update dirty [AG]
[23]436
[428]437    // decrease refcount for bin file, root file and cwd file
[337]438        if( process->vfs_bin_xp  != XPTR_NULL ) vfs_file_count_down( process->vfs_bin_xp );
439        if( process->vfs_root_xp != XPTR_NULL ) vfs_file_count_down( process->vfs_root_xp );
440        if( process->vfs_cwd_xp  != XPTR_NULL ) vfs_file_count_down( process->vfs_cwd_xp );
[1]441
442    // Destroy VMM
443    vmm_destroy( process );
444
[416]445    // release memory allocated to process descriptor
446    process_free( process );
[1]447
[438]448#if DEBUG_PROCESS_DESTROY
[433]449cycle = (uint32_t)hal_get_cycles();
[438]450if( DEBUG_PROCESS_DESTROY )
[445]451printk("\n[DBG] %s : thread %x exit / destroyed process %x in cluster %x / cycle %d\n",
452__FUNCTION__ , CURRENT_THREAD , pid, local_cxy, cycle );
[433]453#endif
[428]454
[407]455}  // end process_destroy()
456
[409]457/////////////////////////////////////////////////
458char * process_action_str( uint32_t action_type )
459{
460    if     ( action_type == BLOCK_ALL_THREADS   ) return "BLOCK";
461    else if( action_type == UNBLOCK_ALL_THREADS ) return "UNBLOCK";
462    else if( action_type == DELETE_ALL_THREADS  ) return "DELETE";
463    else                                          return "undefined";
464}
465
[435]466////////////////////////////////////////
467void process_sigaction( pid_t       pid,
[457]468                        uint32_t    type )
[409]469{
470    cxy_t              owner_cxy;         // owner cluster identifier
471    lpid_t             lpid;              // process index in owner cluster
472    cluster_t        * cluster;           // pointer on cluster manager
473    xptr_t             root_xp;           // extended pointer on root of copies
474    xptr_t             lock_xp;           // extended pointer on lock protecting copies
475    xptr_t             iter_xp;           // iterator on copies list
476    xptr_t             process_xp;        // extended pointer on process copy
477    cxy_t              process_cxy;       // process copy cluster identifier
[457]478    process_t        * process_ptr;       // local pointer on process copy
[436]479    reg_t              save_sr;           // for critical section
480    rpc_desc_t         rpc;               // shared RPC descriptor
[457]481    thread_t         * client;            // pointer on client thread
482    xptr_t             client_xp;         // extended pointer on client thread
483    process_t        * local;             // pointer on process copy in local cluster
484    uint32_t           remote_nr;         // number of remote process copies
[409]485
[457]486    client    = CURRENT_THREAD;
487    client_xp = XPTR( local_cxy , client );
488    local     = NULL;
489    remote_nr = 0;
[435]490
[438]491#if DEBUG_PROCESS_SIGACTION
[433]492uint32_t cycle = (uint32_t)hal_get_cycles();
[438]493if( DEBUG_PROCESS_SIGACTION < cycle )
[457]494printk("\n[DBG] %s : thread %x in process %x enter to %s process %x / cycle %d\n",
495__FUNCTION__ , client->trdid, client->process->pid,
496process_action_str( type ) , pid , cycle );
[433]497#endif
[409]498
[436]499    // get pointer on local cluster manager
[416]500    cluster = LOCAL_CLUSTER;
501
[409]502    // get owner cluster identifier and process lpid
[435]503    owner_cxy = CXY_FROM_PID( pid );
504    lpid      = LPID_FROM_PID( pid );
[409]505
[435]506    // get root of list of copies, lock, and number of copies from owner cluster
[436]507    root_xp   = XPTR( owner_cxy , &cluster->pmgr.copies_root[lpid] );
508    lock_xp   = XPTR( owner_cxy , &cluster->pmgr.copies_lock[lpid] );
[435]509
[416]510    // check action type
[457]511    assert( ((type == DELETE_ALL_THREADS ) ||
512             (type == BLOCK_ALL_THREADS )  ||
[492]513             (type == UNBLOCK_ALL_THREADS )), "illegal action type" );
[416]514             
515
[457]516    // The client thread send parallel RPCs to all remote clusters containing
517    // target process copies, wait all responses, and then handles directly the
518    // threads in local cluster, when required.
519    // The client thread allocates a - shared - RPC descriptor in the stack,
520    // because all parallel, non-blocking, server threads use the same input
521    // arguments, and use the shared RPC response field
[436]522
523    // mask IRQs
524    hal_disable_irq( &save_sr);
525
[457]526    // client thread blocks itself
527    thread_block( client_xp , THREAD_BLOCKED_RPC );
[436]528
[409]529    // take the lock protecting the copies
530    remote_spinlock_lock( lock_xp );
531
[436]532    // initialize shared RPC descriptor
[438]533    rpc.responses = 0;
534    rpc.blocking  = false;
535    rpc.index     = RPC_PROCESS_SIGACTION;
536    rpc.thread    = client;
537    rpc.lid       = client->core->lid;
[457]538    rpc.args[0]   = type;
[438]539    rpc.args[1]   = pid;
[436]540
[457]541    // scan list of process copies
542    // to send RPCs to remote copies
[409]543    XLIST_FOREACH( root_xp , iter_xp )
544    {
[457]545        // get extended pointers and cluster on process
[440]546        process_xp  = XLIST_ELEMENT( iter_xp , process_t , copies_list );
547        process_cxy = GET_CXY( process_xp );
[457]548        process_ptr = GET_PTR( process_xp );
[440]549
[457]550        if( process_cxy == local_cxy )    // process is local
551        { 
552            local = process_ptr;
553        }
554        else                              // process is remote
555        {
556            // update number of remote process copies
557            remote_nr++;
558
559            // atomically increment responses counter
560            hal_atomic_add( (void *)&rpc.responses , 1 );
561
[438]562#if DEBUG_PROCESS_SIGACTION
563if( DEBUG_PROCESS_SIGACTION < cycle )
[457]564printk("\n[DBG] %s : thread %x in process %x handles remote process %x in cluster %x\n",
565__FUNCTION__, client->trdid, client->process->pid, pid , process_cxy );
[433]566#endif
[457]567            // call RPC in target cluster
568            rpc_process_sigaction_client( process_cxy , &rpc );
569        }
570    }  // end list of copies
571
[409]572    // release the lock protecting process copies
573    remote_spinlock_unlock( lock_xp );
574
[436]575    // restore IRQs
576    hal_restore_irq( save_sr);
[409]577
[457]578    // - if there is remote process copies, the client thread deschedules,
579    //   (it will be unblocked by the last RPC server thread).
580    // - if there is no remote copies, the client thread unblock itself.
581    if( remote_nr )
582    {
583        sched_yield("blocked on rpc_process_sigaction");
584    } 
585    else
586    {
587        thread_unblock( client_xp , THREAD_BLOCKED_RPC );
588    }
[409]589
[457]590    // handle the local process copy if required
591    if( local != NULL )
592    {
593
594#if DEBUG_PROCESS_SIGACTION
595if( DEBUG_PROCESS_SIGACTION < cycle )
596printk("\n[DBG] %s : thread %x in process %x handles local process %x in cluster %x\n",
597__FUNCTION__, client->trdid, client->process->pid, pid , local_cxy );
598#endif
599        if     (type == DELETE_ALL_THREADS  ) process_delete_threads ( local , client_xp ); 
600        else if(type == BLOCK_ALL_THREADS   ) process_block_threads  ( local , client_xp ); 
601        else if(type == UNBLOCK_ALL_THREADS ) process_unblock_threads( local );
602    }
603
[438]604#if DEBUG_PROCESS_SIGACTION
[433]605cycle = (uint32_t)hal_get_cycles();
[438]606if( DEBUG_PROCESS_SIGACTION < cycle )
[457]607printk("\n[DBG] %s : thread %x in process %x exit after %s process %x / cycle %d\n",
608__FUNCTION__, client->trdid, client->process->pid,
609process_action_str( type ), pid, cycle );
[433]610#endif
[416]611
[409]612}  // end process_sigaction()
613
[433]614/////////////////////////////////////////////////
[440]615void process_block_threads( process_t * process,
616                            xptr_t      client_xp )
[1]617{
[409]618    thread_t          * target;         // pointer on target thread
[433]619    thread_t          * this;           // pointer on calling thread
[409]620    uint32_t            ltid;           // index in process th_tbl
[436]621    cxy_t               owner_cxy;      // target process owner cluster
[409]622    uint32_t            count;          // requests counter
[436]623    volatile uint32_t   ack_count;      // scheduler acknowledge counter
[1]624
[416]625    // get calling thread pointer
[433]626    this = CURRENT_THREAD;
[407]627
[436]628    // get target process owner cluster
629    owner_cxy = CXY_FROM_PID( process->pid );
630
[438]631#if DEBUG_PROCESS_SIGACTION
[433]632uint32_t cycle = (uint32_t)hal_get_cycles();
[438]633if( DEBUG_PROCESS_SIGACTION < cycle )
[433]634printk("\n[DBG] %s : thread %x enter for process %x in cluster %x / cycle %d\n",
635__FUNCTION__ , this , process->pid , local_cxy , cycle );
636#endif
[409]637
638    // get lock protecting process th_tbl[]
[1]639    spinlock_lock( &process->th_lock );
640
[440]641    // loop on target process local threads
[409]642    // we use both "ltid" and "count" because it can exist "holes" in th_tbl
[436]643    for( ltid = 0 , count = 0 , ack_count = 0 ; count < process->th_nr ; ltid++ )
[1]644    {
[409]645        target = process->th_tbl[ltid];
[1]646
[436]647        if( target != NULL )                                 // thread exist
[1]648        {
649            count++;
[409]650
[440]651            // main thread and client thread should not be blocked
652            if( ((ltid != 0) || (owner_cxy != local_cxy)) &&         // not main thread
653                (client_xp) != XPTR( local_cxy , target ) )          // not client thread
[416]654            {
655                // set the global blocked bit in target thread descriptor.
[436]656                thread_block( XPTR( local_cxy , target ) , THREAD_BLOCKED_GLOBAL );
657 
658                // - if the calling thread and the target thread are on the same core,
659                //   we don't need confirmation from scheduler,
660                // - if the calling thread and the target thread are not running on the same
661                //   core, we ask the target scheduler to acknowlege the blocking
662                //   to be sure that the target thread is not running.
663           
664                if( this->core->lid != target->core->lid )
665                {
666                    // increment responses counter
667                    hal_atomic_add( (void*)&ack_count , 1 );
[409]668
[436]669                    // set FLAG_REQ_ACK and &ack_rsp_count in target descriptor
670                    thread_set_req_ack( target , (uint32_t *)&ack_count );
[409]671
[436]672                    // force scheduling on target thread
673                    dev_pic_send_ipi( local_cxy , target->core->lid );
674                }
[409]675            }
[1]676        }
[172]677    }
678
[428]679    // release lock protecting process th_tbl[]
[416]680    spinlock_unlock( &process->th_lock );
681
[436]682    // wait acknowledges
[409]683    while( 1 )
684    {
[436]685        // exit when all scheduler acknoledges received
686        if ( ack_count == 0 ) break;
[409]687   
688        // wait 1000 cycles before retry
689        hal_fixed_delay( 1000 );
690    }
[1]691
[438]692#if DEBUG_PROCESS_SIGACTION
[433]693cycle = (uint32_t)hal_get_cycles();
[438]694if( DEBUG_PROCESS_SIGACTION < cycle )
[433]695printk("\n[DBG] %s : thread %x exit for process %x in cluster %x / cycle %d\n",
696__FUNCTION__ , this , process->pid , local_cxy , cycle );
697#endif
[409]698
[428]699}  // end process_block_threads()
[409]700
[440]701/////////////////////////////////////////////////
702void process_delete_threads( process_t * process,
703                             xptr_t      client_xp )
[409]704{
[433]705    thread_t          * this;          // pointer on calling thread
[440]706    thread_t          * target;        // local pointer on target thread
707    xptr_t              target_xp;     // extended pointer on target thread
708    cxy_t               owner_cxy;     // owner process cluster
[409]709    uint32_t            ltid;          // index in process th_tbl
[440]710    uint32_t            count;         // threads counter
[409]711
[433]712    // get calling thread pointer
713    this = CURRENT_THREAD;
[409]714
[440]715    // get target process owner cluster
716    owner_cxy = CXY_FROM_PID( process->pid );
717
[438]718#if DEBUG_PROCESS_SIGACTION
[433]719uint32_t cycle = (uint32_t)hal_get_cycles();
[438]720if( DEBUG_PROCESS_SIGACTION < cycle )
[433]721printk("\n[DBG] %s : thread %x enter for process %x in cluster %x / cycle %d\n",
722__FUNCTION__ , this , process->pid , local_cxy , cycle );
723#endif
724
[409]725    // get lock protecting process th_tbl[]
726    spinlock_lock( &process->th_lock );
727
[440]728    // loop on target process local threads                       
[416]729    // we use both "ltid" and "count" because it can exist "holes" in th_tbl
[440]730    for( ltid = 0 , count = 0  ; count < process->th_nr ; ltid++ )
[1]731    {
[409]732        target = process->th_tbl[ltid];
[1]733
[440]734        if( target != NULL )    // valid thread 
[1]735        {
[416]736            count++;
[440]737            target_xp = XPTR( local_cxy , target );
[1]738
[440]739            // main thread and client thread should not be blocked
740            if( ((ltid != 0) || (owner_cxy != local_cxy)) &&         // not main thread
741                (client_xp) != target_xp )                           // not client thread
742            {
743                // mark target thread for delete and block it
744                thread_delete( target_xp , process->pid , false );   // not forced
745            }
[409]746        }
747    }
[1]748
[428]749    // release lock protecting process th_tbl[]
[416]750    spinlock_unlock( &process->th_lock );
[407]751
[438]752#if DEBUG_PROCESS_SIGACTION
[433]753cycle = (uint32_t)hal_get_cycles();
[438]754if( DEBUG_PROCESS_SIGACTION < cycle )
[433]755printk("\n[DBG] %s : thread %x exit for process %x in cluster %x / cycle %d\n",
756__FUNCTION__ , this , process->pid , local_cxy , cycle );
757#endif
[407]758
[440]759}  // end process_delete_threads()
[409]760
[440]761///////////////////////////////////////////////////
762void process_unblock_threads( process_t * process )
[409]763{
[440]764    thread_t          * target;        // pointer on target thead
765    thread_t          * this;          // pointer on calling thread
[409]766    uint32_t            ltid;          // index in process th_tbl
[440]767    uint32_t            count;         // requests counter
[409]768
[440]769    // get calling thread pointer
770    this = CURRENT_THREAD;
771
[438]772#if DEBUG_PROCESS_SIGACTION
[433]773uint32_t cycle = (uint32_t)hal_get_cycles();
[438]774if( DEBUG_PROCESS_SIGACTION < cycle )
[433]775printk("\n[DBG] %s : thread %x enter for process %x in cluster %x / cycle %d\n",
[440]776__FUNCTION__ , this , process->pid , local_cxy , cycle );
[433]777#endif
778
[416]779    // get lock protecting process th_tbl[]
780    spinlock_lock( &process->th_lock );
781
[440]782    // loop on process threads to unblock all threads
[416]783    // we use both "ltid" and "count" because it can exist "holes" in th_tbl
[440]784    for( ltid = 0 , count = 0 ; count < process->th_nr ; ltid++ )
[409]785    {
[416]786        target = process->th_tbl[ltid];
[409]787
[440]788        if( target != NULL )             // thread found
[409]789        {
790            count++;
[440]791
792            // reset the global blocked bit in target thread descriptor.
793            thread_unblock( XPTR( local_cxy , target ) , THREAD_BLOCKED_GLOBAL );
[1]794        }
795    }
796
[428]797    // release lock protecting process th_tbl[]
[416]798    spinlock_unlock( &process->th_lock );
[407]799
[438]800#if DEBUG_PROCESS_SIGACTION
[433]801cycle = (uint32_t)hal_get_cycles();
[438]802if( DEBUG_PROCESS_SIGACTION < cycle )
[433]803printk("\n[DBG] %s : thread %x exit for process %x in cluster %x / cycle %d\n",
[440]804__FUNCTION__ , this , process->pid , local_cxy , cycle );
[433]805#endif
[1]806
[440]807}  // end process_unblock_threads()
[407]808
[1]809///////////////////////////////////////////////
810process_t * process_get_local_copy( pid_t pid )
811{
812    error_t        error;
[172]813    process_t    * process_ptr;   // local pointer on process
[23]814    xptr_t         process_xp;    // extended pointer on process
[1]815
816    cluster_t * cluster = LOCAL_CLUSTER;
817
818    // get lock protecting local list of processes
[23]819    remote_spinlock_lock( XPTR( local_cxy , &cluster->pmgr.local_lock ) );
[1]820
821    // scan the local list of process descriptors to find the process
[23]822    xptr_t  iter;
823    bool_t  found = false;
824    XLIST_FOREACH( XPTR( local_cxy , &cluster->pmgr.local_root ) , iter )
[1]825    {
[23]826        process_xp  = XLIST_ELEMENT( iter , process_t , local_list );
[435]827        process_ptr = GET_PTR( process_xp );
[23]828        if( process_ptr->pid == pid )
[1]829        {
830            found = true;
831            break;
832        }
833    }
834
835    // release lock protecting local list of processes
[23]836    remote_spinlock_unlock( XPTR( local_cxy , &cluster->pmgr.local_lock ) );
[1]837
[172]838    // allocate memory for a new local process descriptor
[440]839    // and initialise it from reference cluster if not found
[1]840    if( !found )
841    {
842        // get extended pointer on reference process descriptor
[23]843        xptr_t ref_xp = cluster_get_reference_process_from_pid( pid );
[1]844
[492]845        assert( (ref_xp != XPTR_NULL) , "illegal pid\n" );
[23]846
[1]847        // allocate memory for local process descriptor
[23]848        process_ptr = process_alloc();
[443]849
[23]850        if( process_ptr == NULL )  return NULL;
[1]851
852        // initialize local process descriptor copy
[23]853        error = process_copy_init( process_ptr , ref_xp );
[443]854
[1]855        if( error ) return NULL;
856    }
857
[440]858#if DEBUG_PROCESS_GET_LOCAL_COPY
859uint32_t cycle = (uint32_t)hal_get_cycles();
860if( DEBUG_PROCESS_GET_LOCAL_COPY < cycle )
861printk("\n[DBG] %s : enter in cluster %x / pid %x / process %x / cycle %d\n",
862__FUNCTION__ , local_cxy , pid , process_ptr , cycle );
863#endif
864
[23]865    return process_ptr;
[1]866
[409]867}  // end process_get_local_copy()
868
[436]869////////////////////////////////////////////
870pid_t process_get_ppid( xptr_t  process_xp )
871{
872    cxy_t       process_cxy;
873    process_t * process_ptr;
874    xptr_t      parent_xp;
875    cxy_t       parent_cxy;
876    process_t * parent_ptr;
877
878    // get process cluster and local pointer
879    process_cxy = GET_CXY( process_xp );
880    process_ptr = GET_PTR( process_xp );
881
882    // get pointers on parent process
883    parent_xp  = (xptr_t)hal_remote_lwd( XPTR( process_cxy , &process_ptr->parent_xp ) );
884    parent_cxy = GET_CXY( parent_xp );
885    parent_ptr = GET_PTR( parent_xp );
886
887    return hal_remote_lw( XPTR( parent_cxy , &parent_ptr->pid ) );
888}
889
[1]890//////////////////////////////////////////////////////////////////////////////////////////
891// File descriptor array related functions
892//////////////////////////////////////////////////////////////////////////////////////////
893
894///////////////////////////////////////////
895void process_fd_init( process_t * process )
896{
897    uint32_t fd;
898
899    remote_spinlock_init( XPTR( local_cxy , &process->fd_array.lock ) );
900
[23]901    process->fd_array.current = 0;
902
[1]903    // initialize array
[23]904    for ( fd = 0 ; fd < CONFIG_PROCESS_FILE_MAX_NR ; fd++ )
[1]905    {
906        process->fd_array.array[fd] = XPTR_NULL;
907    }
908}
909
[23]910//////////////////////////////
[485]911bool_t process_fd_array_full( void )
[1]912{
[172]913    // get extended pointer on reference process
[23]914    xptr_t ref_xp = CURRENT_THREAD->process->ref_xp;
[1]915
[23]916    // get reference process cluster and local pointer
[435]917    process_t * ref_ptr = GET_PTR( ref_xp );
[23]918    cxy_t       ref_cxy = GET_CXY( ref_xp );
[1]919
[23]920    // get number of open file descriptors from reference fd_array
921    uint32_t current = hal_remote_lw( XPTR( ref_cxy , &ref_ptr->fd_array.current ) );
922
[172]923        return ( current >= CONFIG_PROCESS_FILE_MAX_NR );
[1]924}
925
926/////////////////////////////////////////////////
[407]927error_t process_fd_register( process_t * process,
928                             xptr_t      file_xp,
929                             uint32_t  * fdid )
[1]930{
931    bool_t    found;
[23]932    uint32_t  id;
933    xptr_t    xp;
[1]934
[23]935    // get reference process cluster and local pointer
[407]936    xptr_t ref_xp = process->ref_xp;
[435]937    process_t * ref_ptr = GET_PTR( ref_xp );
[23]938    cxy_t       ref_cxy = GET_CXY( ref_xp );
939
940    // take lock protecting reference fd_array
941        remote_spinlock_lock( XPTR( ref_cxy , &ref_ptr->fd_array.lock ) );
942
[1]943    found   = false;
944
[23]945    for ( id = 0; id < CONFIG_PROCESS_FILE_MAX_NR ; id++ )
[1]946    {
[23]947        xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->fd_array.array[id] ) );
948        if ( xp == XPTR_NULL )
[1]949        {
950            found = true;
[23]951            hal_remote_swd( XPTR( ref_cxy , &ref_ptr->fd_array.array[id] ) , file_xp );
952                hal_remote_atomic_add( XPTR( ref_cxy , &ref_ptr->fd_array.current ) , 1 );
[407]953                        *fdid = id;
[1]954            break;
955        }
956    }
957
[23]958    // release lock protecting reference fd_array
959        remote_spinlock_unlock( XPTR( ref_cxy , &ref_ptr->fd_array.lock ) );
[1]960
[428]961    if ( !found ) return -1;
[1]962    else          return 0;
[172]963}
[1]964
[172]965////////////////////////////////////////////////
[23]966xptr_t process_fd_get_xptr( process_t * process,
[407]967                            uint32_t    fdid )
[1]968{
[23]969    xptr_t  file_xp;
[1]970
[23]971    // access local copy of process descriptor
[407]972    file_xp = process->fd_array.array[fdid];
[1]973
[23]974    if( file_xp == XPTR_NULL )
975    {
976        // get reference process cluster and local pointer
977        xptr_t      ref_xp  = process->ref_xp;
978        cxy_t       ref_cxy = GET_CXY( ref_xp );
[435]979        process_t * ref_ptr = GET_PTR( ref_xp );
[1]980
[23]981        // access reference process descriptor
[407]982        file_xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->fd_array.array[fdid] ) );
[1]983
[23]984        // update local fd_array if found
985        if( file_xp != XPTR_NULL )
986        {
[407]987            process->fd_array.array[fdid] = file_xp;
[23]988        }
989    }
[1]990
[23]991    return file_xp;
[1]992
[407]993}  // end process_fd_get_xptr()
994
[1]995///////////////////////////////////////////
996void process_fd_remote_copy( xptr_t dst_xp,
997                             xptr_t src_xp )
998{
999    uint32_t fd;
1000    xptr_t   entry;
1001
1002    // get cluster and local pointer for src fd_array
1003    cxy_t        src_cxy = GET_CXY( src_xp );
[435]1004    fd_array_t * src_ptr = GET_PTR( src_xp );
[1]1005
1006    // get cluster and local pointer for dst fd_array
1007    cxy_t        dst_cxy = GET_CXY( dst_xp );
[435]1008    fd_array_t * dst_ptr = GET_PTR( dst_xp );
[1]1009
1010    // get the remote lock protecting the src fd_array
1011        remote_spinlock_lock( XPTR( src_cxy , &src_ptr->lock ) );
1012
[428]1013    // loop on all fd_array entries
1014    for( fd = 0 ; fd < CONFIG_PROCESS_FILE_MAX_NR ; fd++ )
[1]1015        {
1016                entry = (xptr_t)hal_remote_lwd( XPTR( src_cxy , &src_ptr->array[fd] ) );
1017
1018                if( entry != XPTR_NULL )
1019                {
[459]1020            // increment file descriptor refcount
[1]1021            vfs_file_count_up( entry );
1022
1023                        // copy entry in destination process fd_array
1024                        hal_remote_swd( XPTR( dst_cxy , &dst_ptr->array[fd] ) , entry );
1025                }
1026        }
1027
1028    // release lock on source process fd_array
1029        remote_spinlock_unlock( XPTR( src_cxy , &src_ptr->lock ) );
1030
[407]1031}  // end process_fd_remote_copy()
1032
[1]1033////////////////////////////////////////////////////////////////////////////////////
1034//  Thread related functions
1035////////////////////////////////////////////////////////////////////////////////////
1036
1037/////////////////////////////////////////////////////
1038error_t process_register_thread( process_t * process,
1039                                 thread_t  * thread,
1040                                 trdid_t   * trdid )
1041{
[472]1042    ltid_t         ltid;
1043    reg_t          save_sr;
1044    bool_t         found = false;
1045 
[1]1046
[492]1047    assert( (process != NULL) , "process argument is NULL" );
[1]1048
[492]1049    assert( (thread != NULL) , "thread argument is NULL" );
[14]1050
[472]1051    // take lock protecting th_tbl, depending on thread type:
1052    // we don't want to use a descheduling policy for idle thread initialisation
[514]1053    if ( thread->type == THREAD_IDLE ) {
1054        spinlock_lock_busy( &process->th_lock , &save_sr );
1055    } else {
1056        spinlock_lock( &process->th_lock );
1057    }
[428]1058
[407]1059    // search a free slot in th_tbl[]
[428]1060    for( ltid = 0 ; ltid < CONFIG_THREAD_MAX_PER_CLUSTER ; ltid++ )
[1]1061    {
1062        if( process->th_tbl[ltid] == NULL )
1063        {
1064            found = true;
1065            break;
1066        }
1067    }
1068
1069    if( found )
1070    {
1071        // register thread in th_tbl[]
1072        process->th_tbl[ltid] = thread;
1073        process->th_nr++;
1074
1075        // returns trdid
1076        *trdid = TRDID( local_cxy , ltid );
1077    }
1078
[428]1079    // release lock protecting th_tbl
1080    hal_fence();
[514]1081    if( thread->type == THREAD_IDLE ) {
1082        spinlock_unlock_busy( &process->th_lock , save_sr );
1083    } else {
1084        spinlock_unlock( &process->th_lock );
1085    }
[428]1086
[1]1087    return (found) ? 0 : ENOMEM;
[204]1088
1089}  // end process_register_thread()
1090
[443]1091/////////////////////////////////////////////////
1092bool_t process_remove_thread( thread_t * thread )
[1]1093{
[443]1094    uint32_t count;  // number of threads in local process descriptor
1095
[492]1096    assert( (thread != NULL) , "thread argument is NULL" );
[172]1097
[1]1098    process_t * process = thread->process;
1099
1100    // get thread local index
1101    ltid_t  ltid = LTID_FROM_TRDID( thread->trdid );
1102
[428]1103    // take lock protecting th_tbl
1104    spinlock_lock( &process->th_lock );
1105
[443]1106    count = process->th_nr;
[428]1107
[492]1108    assert( (count > 0) , "process th_nr cannot be 0\n" );
[443]1109
[1]1110    // remove thread from th_tbl[]
1111    process->th_tbl[ltid] = NULL;
[450]1112    process->th_nr = count-1;
[1]1113
[443]1114    // release lock protecting th_tbl
[428]1115    hal_fence();
1116    spinlock_unlock( &process->th_lock );
1117
[443]1118    return (count == 1);
1119
[450]1120}  // end process_remove_thread()
[204]1121
[408]1122/////////////////////////////////////////////////////////
1123error_t process_make_fork( xptr_t      parent_process_xp,
1124                           xptr_t      parent_thread_xp,
1125                           pid_t     * child_pid,
1126                           thread_t ** child_thread )
[1]1127{
[408]1128    process_t * process;         // local pointer on child process descriptor
1129    thread_t  * thread;          // local pointer on child thread descriptor
1130    pid_t       new_pid;         // process identifier for child process
1131    pid_t       parent_pid;      // process identifier for parent process
1132    xptr_t      ref_xp;          // extended pointer on reference process
[428]1133    xptr_t      vfs_bin_xp;      // extended pointer on .elf file
[408]1134    error_t     error;
[1]1135
[408]1136    // get cluster and local pointer for parent process
1137    cxy_t       parent_process_cxy = GET_CXY( parent_process_xp );
[435]1138    process_t * parent_process_ptr = GET_PTR( parent_process_xp );
[101]1139
[428]1140    // get parent process PID and extended pointer on .elf file
1141    parent_pid = hal_remote_lw (XPTR( parent_process_cxy , &parent_process_ptr->pid));
1142    vfs_bin_xp = hal_remote_lwd(XPTR( parent_process_cxy , &parent_process_ptr->vfs_bin_xp));
1143
[438]1144    // check parent process is the reference process
[408]1145    ref_xp = hal_remote_lwd( XPTR( parent_process_cxy , &parent_process_ptr->ref_xp ) );
[438]1146
[492]1147    assert( (parent_process_xp == ref_xp ) ,
[408]1148    "parent process must be the reference process\n" );
[407]1149
[438]1150#if DEBUG_PROCESS_MAKE_FORK
[433]1151uint32_t cycle = (uint32_t)hal_get_cycles();
[438]1152if( DEBUG_PROCESS_MAKE_FORK < cycle )
[457]1153printk("\n[DBG] %s : thread %x in process %x enter / cluster %x / cycle %d\n",
1154__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, local_cxy, cycle );
[433]1155#endif
[172]1156
[408]1157    // allocate a process descriptor
1158    process = process_alloc();
1159    if( process == NULL )
1160    {
1161        printk("\n[ERROR] in %s : cannot get process in cluster %x\n", 
1162        __FUNCTION__, local_cxy ); 
1163        return -1;
1164    }
[1]1165
[408]1166    // allocate a child PID from local cluster
[416]1167    error = cluster_pid_alloc( process , &new_pid );
[428]1168    if( error ) 
[1]1169    {
[408]1170        printk("\n[ERROR] in %s : cannot get PID in cluster %x\n", 
1171        __FUNCTION__, local_cxy ); 
1172        process_free( process );
1173        return -1;
[1]1174    }
[408]1175
[469]1176#if( DEBUG_PROCESS_MAKE_FORK & 1 )
[457]1177cycle = (uint32_t)hal_get_cycles();
1178if( DEBUG_PROCESS_MAKE_FORK < cycle )
1179printk("\n[DBG] %s : thread %x in process %x allocated process %x / cycle %d\n",
1180__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, new_pid, cycle );
1181#endif
1182
[408]1183    // initializes child process descriptor from parent process descriptor
1184    process_reference_init( process,
1185                            new_pid,
1186                            parent_process_xp );
1187
[438]1188#if( DEBUG_PROCESS_MAKE_FORK & 1 )
[433]1189cycle = (uint32_t)hal_get_cycles();
[438]1190if( DEBUG_PROCESS_MAKE_FORK < cycle )
[457]1191printk("\n[DBG] %s : thread %x in process %x initialized child_process %x / cycle %d\n",
1192__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, new_pid, cycle );
[433]1193#endif
[408]1194
[457]1195    // give TXT ownership to child process
1196    process_txt_set_ownership( XPTR( local_cxy , process ) );
1197
[408]1198    // copy VMM from parent descriptor to child descriptor
1199    error = vmm_fork_copy( process,
1200                           parent_process_xp );
1201    if( error )
[101]1202    {
[408]1203        printk("\n[ERROR] in %s : cannot copy VMM in cluster %x\n", 
1204        __FUNCTION__, local_cxy ); 
1205        process_free( process );
1206        cluster_pid_release( new_pid );
1207        return -1;
[101]1208    }
[172]1209
[438]1210#if( DEBUG_PROCESS_MAKE_FORK & 1 )
[433]1211cycle = (uint32_t)hal_get_cycles();
[438]1212if( DEBUG_PROCESS_MAKE_FORK < cycle )
[457]1213printk("\n[DBG] %s : thread %x in process %x copied VMM from parent %x to child %x / cycle %d\n",
1214__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, 
1215parent_pid, new_pid, cycle );
[433]1216#endif
[407]1217
[457]1218    // parent process gives TXT ownership to child process if required
1219    if( process_txt_is_owner(parent_process_xp) ) 
1220    {
1221        process_txt_set_ownership( XPTR( local_cxy , process ) );
1222
1223#if( DEBUG_PROCESS_MAKE_FORK & 1 )
1224cycle = (uint32_t)hal_get_cycles();
1225if( DEBUG_PROCESS_MAKE_EXEC < cycle )
1226printk("\n[DBG] %s : thread %x in process %x gives TXT from parent %x to child %x / cycle %d\n",
1227__FUNCTION__ , CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid,
1228parent_pid, new_pid, cycle );
1229#endif
1230
1231    }
1232
[428]1233    // update extended pointer on .elf file
1234    process->vfs_bin_xp = vfs_bin_xp;
1235
[408]1236    // create child thread descriptor from parent thread descriptor
1237    error = thread_user_fork( parent_thread_xp,
1238                              process,
1239                              &thread );
1240    if( error )
1241    {
1242        printk("\n[ERROR] in %s : cannot create thread in cluster %x\n",
1243        __FUNCTION__, local_cxy ); 
1244        process_free( process );
1245        cluster_pid_release( new_pid );
1246        return -1;
1247    }
[172]1248
[438]1249    // check main thread LTID
[492]1250    assert( (LTID_FROM_TRDID(thread->trdid) == 0) ,
[438]1251    "main thread must have LTID == 0\n" );
[428]1252
[469]1253//#if( DEBUG_PROCESS_MAKE_FORK & 1 )
1254#if DEBUG_PROCESS_MAKE_FORK
[433]1255cycle = (uint32_t)hal_get_cycles();
[438]1256if( DEBUG_PROCESS_MAKE_FORK < cycle )
[469]1257printk("\n[DBG] %s : thread %x in process %x created main thread %x / cycle %d\n", 
1258__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, thread, cycle );
[433]1259#endif
[1]1260
[433]1261    // set Copy_On_Write flag in parent process GPT
[408]1262    // this includes all replicated GPT copies
1263    if( parent_process_cxy == local_cxy )   // reference is local
1264    {
1265        vmm_set_cow( parent_process_ptr );
1266    }
1267    else                                    // reference is remote
1268    {
1269        rpc_vmm_set_cow_client( parent_process_cxy,
1270                                parent_process_ptr );
1271    }
[1]1272
[433]1273    // set Copy_On_Write flag in child process GPT
1274    vmm_set_cow( process );
1275 
[438]1276#if( DEBUG_PROCESS_MAKE_FORK & 1 )
[433]1277cycle = (uint32_t)hal_get_cycles();
[438]1278if( DEBUG_PROCESS_MAKE_FORK < cycle )
[457]1279printk("\n[DBG] %s : thread %x in process %x set COW in parent and child / cycle %d\n",
1280__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, cycle );
[433]1281#endif
[101]1282
[428]1283    // get extended pointers on parent children_root, children_lock and children_nr
1284    xptr_t children_root_xp = XPTR( parent_process_cxy , &parent_process_ptr->children_root );
1285    xptr_t children_lock_xp = XPTR( parent_process_cxy , &parent_process_ptr->children_lock );
1286    xptr_t children_nr_xp   = XPTR( parent_process_cxy , &parent_process_ptr->children_nr   );
[101]1287
[428]1288    // register process in parent children list
1289    remote_spinlock_lock( children_lock_xp );
1290        xlist_add_last( children_root_xp , XPTR( local_cxy , &process->children_list ) );
1291        hal_remote_atomic_add( children_nr_xp , 1 );
1292    remote_spinlock_unlock( children_lock_xp );
[204]1293
[408]1294    // return success
1295    *child_thread = thread;
1296    *child_pid    = new_pid;
[1]1297
[438]1298#if DEBUG_PROCESS_MAKE_FORK
[433]1299cycle = (uint32_t)hal_get_cycles();
[438]1300if( DEBUG_PROCESS_MAKE_FORK < cycle )
[457]1301printk("\n[DBG] %s : thread %x in process %x exit / created process %x / cycle %d\n",
1302__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, new_pid, cycle );
[433]1303#endif
[428]1304
[408]1305    return 0;
1306
[416]1307}   // end process_make_fork()
[408]1308
1309/////////////////////////////////////////////////////
1310error_t process_make_exec( exec_info_t  * exec_info )
1311{
[457]1312    thread_t       * thread;                  // local pointer on this thread
1313    process_t      * process;                 // local pointer on this process
1314    pid_t            pid;                     // this process identifier
[441]1315        error_t          error;                   // value returned by called functions
[457]1316    char           * path;                    // path to .elf file
1317    xptr_t           file_xp;                 // extended pointer on .elf file descriptor
1318    uint32_t         file_id;                 // file index in fd_array
1319    uint32_t         args_nr;                 // number of main thread arguments
1320    char          ** args_pointers;           // array of pointers on main thread arguments
[446]1321
[457]1322    // get thread, process & PID
1323    thread  = CURRENT_THREAD;
1324    process = thread->process;
1325    pid     = process->pid;
[408]1326
[457]1327        // get relevant infos from exec_info
1328        path          = exec_info->path;
1329    args_nr       = exec_info->args_nr;
1330    args_pointers = exec_info->args_pointers;
[408]1331
[438]1332#if DEBUG_PROCESS_MAKE_EXEC
[433]1333uint32_t cycle = (uint32_t)hal_get_cycles();
[438]1334if( DEBUG_PROCESS_MAKE_EXEC < cycle )
[446]1335printk("\n[DBG] %s : thread %x in process %x enters / path %s / cycle %d\n",
[457]1336__FUNCTION__, thread->trdid, pid, path, cycle );
[433]1337#endif
[408]1338
[457]1339    // open the file identified by <path>
1340    file_xp = XPTR_NULL;
1341    file_id = -1;
1342        error   = vfs_open( process,
1343                            path,
1344                            O_RDONLY,
1345                            0,
1346                            &file_xp,
1347                            &file_id );
1348        if( error )
1349        {
1350                printk("\n[ERROR] in %s : failed to open file <%s>\n", __FUNCTION__ , path );
1351                return -1;
1352        }
1353
[446]1354#if (DEBUG_PROCESS_MAKE_EXEC & 1)
[469]1355cycle = (uint32_t)hal_get_cycles();
[446]1356if( DEBUG_PROCESS_MAKE_EXEC < cycle )
[469]1357printk("\n[DBG] %s : thread %x in process %x opened file <%s> / cycle %d\n",
1358__FUNCTION__, thread->trdid, pid, path, cycle );
[446]1359#endif
1360
[457]1361    // delete all threads other than this main thread in all clusters
1362    process_sigaction( pid , DELETE_ALL_THREADS );
[446]1363
[469]1364#if (DEBUG_PROCESS_MAKE_EXEC & 1)
1365cycle = (uint32_t)hal_get_cycles();
1366if( DEBUG_PROCESS_MAKE_EXEC < cycle )
1367printk("\n[DBG] %s : thread %x in process %x deleted all threads / cycle %d\n",
1368__FUNCTION__, thread->trdid, pid, cycle );
1369#endif
1370
[457]1371    // reset local process VMM
1372    vmm_destroy( process );
[446]1373
[457]1374#if( DEBUG_PROCESS_MAKE_EXEC & 1 )
1375cycle = (uint32_t)hal_get_cycles();
1376if( DEBUG_PROCESS_MAKE_EXEC < cycle )
[469]1377printk("\n[DBG] %s : thread %x in process %x reset VMM / cycle %d\n",
[457]1378__FUNCTION__, thread->trdid, pid, cycle );
1379#endif
[408]1380
[457]1381    // re-initialize the VMM (kentry/args/envs vsegs registration)
1382    error = vmm_init( process );
1383    if( error )
[416]1384    {
[457]1385        printk("\n[ERROR] in %s : cannot initialise VMM for %s\n", __FUNCTION__ , path );
1386        vfs_close( file_xp , file_id );
1387        // FIXME restore old process VMM
[416]1388        return -1;
1389    }
[457]1390   
[438]1391#if( DEBUG_PROCESS_MAKE_EXEC & 1 )
[433]1392cycle = (uint32_t)hal_get_cycles();
[438]1393if( DEBUG_PROCESS_MAKE_EXEC < cycle )
[457]1394printk("\n[DBG] %s : thread %x in process %x / kentry/args/envs vsegs registered / cycle %d\n",
1395__FUNCTION__, thread->trdid, pid, cycle );
[433]1396#endif
[428]1397
[457]1398    // register code & data vsegs as well as entry-point in process VMM,
[428]1399    // and register extended pointer on .elf file in process descriptor
[457]1400        error = elf_load_process( file_xp , process );
[441]1401    if( error )
[1]1402        {
[441]1403                printk("\n[ERROR] in %s : failed to access <%s>\n", __FUNCTION__ , path );
[457]1404        vfs_close( file_xp , file_id );
1405        // FIXME restore old process VMM
[408]1406        return -1;
[1]1407        }
1408
[438]1409#if( DEBUG_PROCESS_MAKE_EXEC & 1 )
[433]1410cycle = (uint32_t)hal_get_cycles();
[438]1411if( DEBUG_PROCESS_MAKE_EXEC < cycle )
[457]1412printk("\n[DBG] %s : thread %x in process %x / code/data vsegs registered / cycle %d\n",
1413__FUNCTION__, thread->trdid, pid, cycle );
[433]1414#endif
[1]1415
[457]1416    // update the existing main thread descriptor... and jump to user code
1417    error = thread_user_exec( (void *)process->vmm.entry_point,
1418                              args_nr,
1419                              args_pointers );
1420    if( error )
1421    {
[469]1422        printk("\n[ERROR] in %s : cannot update main thread for %s\n", __FUNCTION__ , path );
[457]1423        vfs_close( file_xp , file_id );
1424        // FIXME restore old process VMM
[408]1425        return -1;
[457]1426    }
[1]1427
[492]1428    assert( false, "we should not execute this code");
[457]1429 
[409]1430        return 0;
1431
1432}  // end process_make_exec()
1433
[457]1434
[428]1435///////////////////////////////////////////////
1436void process_zero_create( process_t * process )
1437{
1438
[438]1439#if DEBUG_PROCESS_ZERO_CREATE
[433]1440uint32_t cycle = (uint32_t)hal_get_cycles();
[438]1441if( DEBUG_PROCESS_ZERO_CREATE < cycle )
[433]1442printk("\n[DBG] %s : thread %x enter / cycle %d\n", __FUNCTION__, CURRENT_THREAD, cycle );
1443#endif
[428]1444
1445    // initialize PID, REF_XP, PARENT_XP, and STATE
[433]1446    process->pid        = 0;
1447    process->ref_xp     = XPTR( local_cxy , process );
[443]1448    process->owner_xp   = XPTR( local_cxy , process );
[433]1449    process->parent_xp  = XPTR_NULL;
1450    process->term_state = 0;
[428]1451
1452    // reset th_tbl[] array as empty
1453    uint32_t i;
1454    for( i = 0 ; i < CONFIG_THREAD_MAX_PER_CLUSTER ; i++ )
1455        {
1456        process->th_tbl[i] = NULL;
1457    }
1458    process->th_nr  = 0;
1459    spinlock_init( &process->th_lock );
1460
1461    // reset children list as empty
1462    xlist_root_init( XPTR( local_cxy , &process->children_root ) );
1463    remote_spinlock_init( XPTR( local_cxy , &process->children_lock ) );
1464    process->children_nr = 0;
1465
1466        hal_fence();
1467
[438]1468#if DEBUG_PROCESS_ZERO_CREATE
[433]1469cycle = (uint32_t)hal_get_cycles();
[438]1470if( DEBUG_PROCESS_ZERO_CREATE < cycle )
[433]1471printk("\n[DBG] %s : thread %x exit / cycle %d\n", __FUNCTION__, CURRENT_THREAD, cycle );
1472#endif
[428]1473
1474}  // end process_zero_init()
1475
[1]1476//////////////////////////
[485]1477void process_init_create( void )
[1]1478{
[428]1479    process_t      * process;       // local pointer on process descriptor
[409]1480    pid_t            pid;           // process_init identifier
1481    thread_t       * thread;        // local pointer on main thread
1482    pthread_attr_t   attr;          // main thread attributes
1483    lid_t            lid;           // selected core local index for main thread
[457]1484    xptr_t           file_xp;       // extended pointer on .elf file descriptor
1485    uint32_t         file_id;       // file index in fd_array
[409]1486    error_t          error;
[1]1487
[438]1488#if DEBUG_PROCESS_INIT_CREATE
[433]1489uint32_t cycle = (uint32_t)hal_get_cycles();
[438]1490if( DEBUG_PROCESS_INIT_CREATE < cycle )
[457]1491printk("\n[DBG] %s : thread %x in process %x enter / cycle %d\n",
1492__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, cycle );
[433]1493#endif
[1]1494
[408]1495    // allocates memory for process descriptor from local cluster
1496        process = process_alloc(); 
[457]1497       
[492]1498    assert( (process != NULL),
[457]1499    "no memory for process descriptor in cluster %x\n", local_cxy  );
[101]1500
[409]1501    // get PID from local cluster
[416]1502    error = cluster_pid_alloc( process , &pid );
[408]1503
[492]1504    assert( (error == 0),
[457]1505    "cannot allocate PID in cluster %x\n", local_cxy );
[409]1506
[492]1507    assert( (pid == 1) ,
[457]1508    "process INIT must be first process in cluster 0\n" );
1509
[409]1510    // initialize process descriptor / parent is local process_zero
1511    process_reference_init( process,
[408]1512                            pid,
[457]1513                            XPTR( local_cxy , &process_zero ) ); 
[408]1514
[457]1515    // open the file identified by CONFIG_PROCESS_INIT_PATH
1516    file_xp = XPTR_NULL;
1517    file_id = -1;
1518        error   = vfs_open( process,
1519                            CONFIG_PROCESS_INIT_PATH,
1520                            O_RDONLY,
1521                            0,
1522                            &file_xp,
1523                            &file_id );
1524
[492]1525        assert( (error == 0),
[457]1526    "failed to open file <%s>\n", CONFIG_PROCESS_INIT_PATH );
1527
[409]1528    // register "code" and "data" vsegs as well as entry-point
1529    // in process VMM, using information contained in the elf file.
[457]1530        error = elf_load_process( file_xp , process );
[101]1531
[492]1532        assert( (error == 0),
[457]1533    "cannot access .elf file <%s>\n", CONFIG_PROCESS_INIT_PATH );
1534
[428]1535    // get extended pointers on process_zero children_root, children_lock
1536    xptr_t children_root_xp = XPTR( local_cxy , &process_zero.children_root );
1537    xptr_t children_lock_xp = XPTR( local_cxy , &process_zero.children_lock );
1538
1539    // register process INIT in parent local process_zero
1540    remote_spinlock_lock( children_lock_xp );
1541        xlist_add_last( children_root_xp , XPTR( local_cxy , &process->children_list ) );
1542        hal_atomic_add( &process_zero.children_nr , 1 );
1543    remote_spinlock_unlock( children_lock_xp );
1544
[409]1545    // select a core in local cluster to execute the main thread
1546    lid  = cluster_select_local_core();
1547
1548    // initialize pthread attributes for main thread
1549    attr.attributes = PT_ATTR_DETACH | PT_ATTR_CLUSTER_DEFINED | PT_ATTR_CORE_DEFINED;
1550    attr.cxy        = local_cxy;
1551    attr.lid        = lid;
1552
1553    // create and initialize thread descriptor
1554        error = thread_user_create( pid,
1555                                (void *)process->vmm.entry_point,
1556                                NULL,
1557                                &attr,
1558                                &thread );
[1]1559
[492]1560        assert( (error == 0),
[457]1561    "cannot create main thread for <%s>\n", CONFIG_PROCESS_INIT_PATH );
[428]1562
[492]1563    assert( (thread->trdid == 0),
[457]1564    "main thread must have index 0 for <%s>\n", CONFIG_PROCESS_INIT_PATH );
1565
[409]1566    // activate thread
1567        thread_unblock( XPTR( local_cxy , thread ) , THREAD_BLOCKED_GLOBAL );
1568
[124]1569    hal_fence();
[1]1570
[438]1571#if DEBUG_PROCESS_INIT_CREATE
[433]1572cycle = (uint32_t)hal_get_cycles();
[438]1573if( DEBUG_PROCESS_INIT_CREATE < cycle )
[457]1574printk("\n[DBG] %s : thread %x in process %x exit / cycle %d\n",
1575__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, cycle );
[433]1576#endif
[409]1577
[204]1578}  // end process_init_create()
1579
[428]1580/////////////////////////////////////////
1581void process_display( xptr_t process_xp )
1582{
1583    process_t   * process_ptr;
1584    cxy_t         process_cxy;
[443]1585
[428]1586    xptr_t        parent_xp;       // extended pointer on parent process
1587    process_t   * parent_ptr;
1588    cxy_t         parent_cxy;
1589
[443]1590    xptr_t        owner_xp;        // extended pointer on owner process
1591    process_t   * owner_ptr;
1592    cxy_t         owner_cxy;
1593
[428]1594    pid_t         pid;
1595    pid_t         ppid;
1596    uint32_t      state;
1597    uint32_t      th_nr;
1598
[443]1599    xptr_t        txt_file_xp;     // extended pointer on TXT_RX file descriptor
1600    xptr_t        txt_chdev_xp;    // extended pointer on TXT_RX chdev
1601    chdev_t     * txt_chdev_ptr;
1602    cxy_t         txt_chdev_cxy;
1603    xptr_t        txt_owner_xp;    // extended pointer on TXT owner process
[428]1604
1605    xptr_t        elf_file_xp;     // extended pointer on .elf file
1606    cxy_t         elf_file_cxy;
1607    vfs_file_t  * elf_file_ptr;
1608    vfs_inode_t * elf_inode_ptr;   // local pointer on .elf inode
1609
1610    char          txt_name[CONFIG_VFS_MAX_NAME_LENGTH];
1611    char          elf_name[CONFIG_VFS_MAX_NAME_LENGTH];
1612
1613    // get cluster and local pointer on process
1614    process_ptr = GET_PTR( process_xp );
1615    process_cxy = GET_CXY( process_xp );
1616
1617    // get PID and state
1618    pid   = hal_remote_lw( XPTR( process_cxy , &process_ptr->pid ) );
[433]1619    state = hal_remote_lw( XPTR( process_cxy , &process_ptr->term_state ) );
[428]1620
1621    // get PPID
1622    parent_xp  = hal_remote_lwd( XPTR( process_cxy , &process_ptr->parent_xp ) );
1623    parent_cxy = GET_CXY( parent_xp );
1624    parent_ptr = GET_PTR( parent_xp );
1625    ppid       = hal_remote_lw( XPTR( parent_cxy , &parent_ptr->pid ) );
1626
1627    // get number of threads
1628    th_nr      = hal_remote_lw( XPTR( process_cxy , &process_ptr->th_nr ) );
1629
[443]1630    // get pointers on owner process descriptor
1631    owner_xp  = hal_remote_lwd( XPTR( process_cxy , &process_ptr->owner_xp ) );
1632    owner_cxy = GET_CXY( owner_xp );
1633    owner_ptr = GET_PTR( owner_xp );
[428]1634
[443]1635    // get extended pointer on TXT_RX file descriptor attached to process
1636    txt_file_xp = hal_remote_lwd( XPTR( owner_cxy , &owner_ptr->fd_array.array[0] ) );
1637
[492]1638    assert( (txt_file_xp != XPTR_NULL) ,
[428]1639    "process must be attached to one TXT terminal\n" ); 
1640
[443]1641    // get TXT_RX chdev pointers
1642    txt_chdev_xp  = chdev_from_file( txt_file_xp );
1643    txt_chdev_cxy = GET_CXY( txt_chdev_xp );
1644    txt_chdev_ptr = GET_PTR( txt_chdev_xp );
1645
1646    // get TXT_RX name and ownership
[428]1647    hal_remote_strcpy( XPTR( local_cxy , txt_name ) ,
[443]1648                       XPTR( txt_chdev_cxy , txt_chdev_ptr->name ) );
[428]1649   
[443]1650    txt_owner_xp = (xptr_t)hal_remote_lwd( XPTR( txt_chdev_cxy, 
1651                                                 &txt_chdev_ptr->ext.txt.owner_xp ) );
1652   
[428]1653    // get process .elf name
1654    elf_file_xp   = hal_remote_lwd( XPTR( process_cxy , &process_ptr->vfs_bin_xp ) );
1655    elf_file_cxy  = GET_CXY( elf_file_xp );
1656    elf_file_ptr  = (vfs_file_t *)GET_PTR( elf_file_xp );
1657    elf_inode_ptr = (vfs_inode_t *)hal_remote_lpt( XPTR( elf_file_cxy , &elf_file_ptr->inode ) );
1658    vfs_inode_get_name( XPTR( elf_file_cxy , elf_inode_ptr ) , elf_name );
1659
1660    // display process info
[443]1661    if( txt_owner_xp == process_xp )
[428]1662    {
[446]1663        nolock_printk("PID %X | PPID %X | TS %X | %s (FG) | %X | %d | %s\n", 
[433]1664        pid, ppid, state, txt_name, process_ptr, th_nr, elf_name );
[428]1665    }
1666    else
1667    {
[446]1668        nolock_printk("PID %X | PPID %X | TS %X | %s (BG) | %X | %d | %s\n", 
[433]1669        pid, ppid, state, txt_name, process_ptr, th_nr, elf_name );
[428]1670    }
1671}  // end process_display()
1672
1673
1674////////////////////////////////////////////////////////////////////////////////////////
1675//     Terminals related functions
1676////////////////////////////////////////////////////////////////////////////////////////
1677
1678////////////////////////////
[485]1679uint32_t process_txt_alloc( void )
[428]1680{
1681    uint32_t  index;       // TXT terminal index
1682    xptr_t    chdev_xp;    // extended pointer on TXT_RX chdev
1683    chdev_t * chdev_ptr;   // local pointer on TXT_RX chdev
1684    cxy_t     chdev_cxy;   // TXT_RX chdev cluster
1685    xptr_t    root_xp;     // extended pointer on owner field in chdev
1686
1687    // scan the user TXT_RX chdevs (TXT0 is reserved for kernel)
1688    for( index = 1 ; index < LOCAL_CLUSTER->nb_txt_channels ; index ++ )
1689    {
1690        // get pointers on TXT_RX[index]
1691        chdev_xp  = chdev_dir.txt_rx[index];
1692        chdev_cxy = GET_CXY( chdev_xp );
1693        chdev_ptr = GET_PTR( chdev_xp );
1694
1695        // get extended pointer on root of attached process
1696        root_xp = XPTR( chdev_cxy , &chdev_ptr->ext.txt.root );
1697
1698        // return free TXT index if found
1699        if( xlist_is_empty( root_xp ) ) return index; 
1700    }
1701
[492]1702    assert( false , "no free TXT terminal found" );
[428]1703
1704    return -1;
1705
1706} // end process_txt_alloc()
1707
1708/////////////////////////////////////////////
1709void process_txt_attach( process_t * process,
1710                         uint32_t    txt_id )
1711{
1712    xptr_t      chdev_xp;     // extended pointer on TXT_RX chdev
1713    cxy_t       chdev_cxy;    // TXT_RX chdev cluster
1714    chdev_t *   chdev_ptr;    // local pointer on TXT_RX chdev
1715    xptr_t      root_xp;      // extended pointer on list root in chdev
1716    xptr_t      lock_xp;      // extended pointer on list lock in chdev
1717
[436]1718    // check process is in owner cluster
[492]1719    assert( (CXY_FROM_PID( process->pid ) == local_cxy) ,
[436]1720    "process descriptor not in owner cluster" );
[428]1721
1722    // check terminal index
1723    assert( (txt_id < LOCAL_CLUSTER->nb_txt_channels) ,
[492]1724    "illegal TXT terminal index" );
[428]1725
1726    // get pointers on TXT_RX[txt_id] chdev
1727    chdev_xp  = chdev_dir.txt_rx[txt_id];
1728    chdev_cxy = GET_CXY( chdev_xp );
1729    chdev_ptr = GET_PTR( chdev_xp );
1730
1731    // get extended pointer on root & lock of attached process list
1732    root_xp = XPTR( chdev_cxy , &chdev_ptr->ext.txt.root );
1733    lock_xp = XPTR( chdev_cxy , &chdev_ptr->ext.txt.lock );
1734
1735    // insert process in attached process list
1736    remote_spinlock_lock( lock_xp );
1737    xlist_add_last( root_xp , XPTR( local_cxy , &process->txt_list ) );
1738    remote_spinlock_unlock( lock_xp );
1739
[446]1740#if DEBUG_PROCESS_TXT
[457]1741uint32_t cycle = (uint32_t)hal_get_cycles();
[446]1742if( DEBUG_PROCESS_TXT < cycle )
[457]1743printk("\n[DBG] %s : thread %x in process %x attached process %x to TXT %d / cycle %d\n",
1744__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid,
1745process->pid, txt_id , cycle );
[433]1746#endif
[428]1747
1748} // end process_txt_attach()
1749
[436]1750/////////////////////////////////////////////
1751void process_txt_detach( xptr_t  process_xp )
[428]1752{
[436]1753    process_t * process_ptr;  // local pointer on process in owner cluster
1754    cxy_t       process_cxy;  // process owner cluster
1755    pid_t       process_pid;  // process identifier
1756    xptr_t      file_xp;      // extended pointer on stdin file
[428]1757    xptr_t      chdev_xp;     // extended pointer on TXT_RX chdev
1758    cxy_t       chdev_cxy;    // TXT_RX chdev cluster
1759    chdev_t *   chdev_ptr;    // local pointer on TXT_RX chdev
1760    xptr_t      lock_xp;      // extended pointer on list lock in chdev
1761
[436]1762    // get process cluster, local pointer, and PID
1763    process_cxy = GET_CXY( process_xp );
1764    process_ptr = GET_PTR( process_xp );
1765
1766    // check process descriptor in owner cluster
[457]1767    process_pid = hal_remote_lw( XPTR( process_cxy , &process_ptr->pid ) );
[492]1768    assert( (CXY_FROM_PID( process_pid ) == process_cxy ) ,
[436]1769    "process descriptor not in owner cluster" );
1770
1771    // release TXT ownership (does nothing if not TXT owner)
1772    process_txt_transfer_ownership( process_xp );
[428]1773
[436]1774    // get extended pointer on process stdin file
1775    file_xp = (xptr_t)hal_remote_lwd( XPTR( process_cxy , &process_ptr->fd_array.array[0] ) );
1776
1777    // get pointers on TXT_RX chdev
1778    chdev_xp  = chdev_from_file( file_xp );
[428]1779    chdev_cxy = GET_CXY( chdev_xp );
1780    chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
1781
[436]1782    // get extended pointer on lock protecting attached process list
[428]1783    lock_xp = XPTR( chdev_cxy , &chdev_ptr->ext.txt.lock );
1784
1785    // unlink process from attached process list
1786    remote_spinlock_lock( lock_xp );
[436]1787    xlist_unlink( XPTR( process_cxy , &process_ptr->txt_list ) );
[428]1788    remote_spinlock_unlock( lock_xp );
[436]1789
[446]1790#if DEBUG_PROCESS_TXT
[457]1791uint32_t cycle  = (uint32_t)hal_get_cycles();
[441]1792uint32_t txt_id = hal_remote_lw( XPTR( chdev_cxy , &chdev_ptr->channel ) );
[446]1793if( DEBUG_PROCESS_TXT < cycle )
[457]1794printk("\n[DBG] %s : thread %x in process %x detached process %x from TXT %d / cycle %d\n",
1795__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid,
1796process_pid, txt_id, cycle );
[433]1797#endif
[428]1798
1799} // end process_txt_detach()
1800
1801///////////////////////////////////////////////////
1802void process_txt_set_ownership( xptr_t process_xp )
1803{
1804    process_t * process_ptr;
1805    cxy_t       process_cxy;
[436]1806    pid_t       process_pid;
[428]1807    xptr_t      file_xp;
1808    xptr_t      txt_xp;     
1809    chdev_t   * txt_ptr;
1810    cxy_t       txt_cxy;
1811
[436]1812    // get pointers on process in owner cluster
[428]1813    process_cxy = GET_CXY( process_xp );
[435]1814    process_ptr = GET_PTR( process_xp );
[436]1815    process_pid = hal_remote_lw( XPTR( process_cxy , &process_ptr->pid ) );
1816
1817    // check owner cluster
[492]1818    assert( (process_cxy == CXY_FROM_PID( process_pid )) ,
[436]1819    "process descriptor not in owner cluster\n" );
1820
[428]1821    // get extended pointer on stdin pseudo file
1822    file_xp = hal_remote_lwd( XPTR( process_cxy , &process_ptr->fd_array.array[0] ) );
1823
1824    // get pointers on TXT chdev
1825    txt_xp  = chdev_from_file( file_xp );
1826    txt_cxy = GET_CXY( txt_xp );
[435]1827    txt_ptr = GET_PTR( txt_xp );
[428]1828
1829    // set owner field in TXT chdev
1830    hal_remote_swd( XPTR( txt_cxy , &txt_ptr->ext.txt.owner_xp ) , process_xp );
1831
[446]1832#if DEBUG_PROCESS_TXT
[457]1833uint32_t cycle  = (uint32_t)hal_get_cycles();
1834uint32_t txt_id = hal_remote_lw( XPTR( txt_cxy , &txt_ptr->channel ) );
[446]1835if( DEBUG_PROCESS_TXT < cycle )
[457]1836printk("\n[DBG] %s : thread %x in process %x give TXT %d to process %x / cycle %d\n",
1837__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, txt_id, process_pid, cycle );
[436]1838#endif
1839
[428]1840}  // end process_txt_set ownership()
1841
[436]1842////////////////////////////////////////////////////////
1843void process_txt_transfer_ownership( xptr_t process_xp )
[428]1844{
[436]1845    process_t * process_ptr;     // local pointer on process releasing ownership
1846    cxy_t       process_cxy;     // process cluster
1847    pid_t       process_pid;     // process identifier
[428]1848    xptr_t      file_xp;         // extended pointer on TXT_RX pseudo file
1849    xptr_t      txt_xp;          // extended pointer on TXT_RX chdev
[433]1850    chdev_t   * txt_ptr;         // local pointer on TXT_RX chdev
1851    cxy_t       txt_cxy;         // cluster of TXT_RX chdev
1852    uint32_t    txt_id;          // TXT_RX channel
[428]1853    xptr_t      owner_xp;        // extended pointer on current TXT_RX owner
1854    xptr_t      root_xp;         // extended pointer on root of attached process list
[436]1855    xptr_t      lock_xp;         // extended pointer on lock protecting attached process list
[428]1856    xptr_t      iter_xp;         // iterator for xlist
1857    xptr_t      current_xp;      // extended pointer on current process
[433]1858    process_t * current_ptr;     // local pointer on current process
1859    cxy_t       current_cxy;     // cluster for current process
[428]1860
[457]1861#if DEBUG_PROCESS_TXT
1862uint32_t cycle;
1863#endif
1864
[436]1865    // get pointers on process in owner cluster
[428]1866    process_cxy = GET_CXY( process_xp );
[435]1867    process_ptr = GET_PTR( process_xp );
[436]1868    process_pid = hal_remote_lw( XPTR( process_cxy , &process_ptr->pid ) );
1869
1870    // check owner cluster
[492]1871    assert( (process_cxy == CXY_FROM_PID( process_pid )) ,
[436]1872    "process descriptor not in owner cluster\n" );
1873
[428]1874    // get extended pointer on stdin pseudo file
1875    file_xp = hal_remote_lwd( XPTR( process_cxy , &process_ptr->fd_array.array[0] ) );
1876
1877    // get pointers on TXT chdev
1878    txt_xp  = chdev_from_file( file_xp );
1879    txt_cxy = GET_CXY( txt_xp );
[433]1880    txt_ptr = GET_PTR( txt_xp );
[428]1881
[433]1882    // get extended pointer on TXT_RX owner and TXT channel
[428]1883    owner_xp = hal_remote_lwd( XPTR( txt_cxy , &txt_ptr->ext.txt.owner_xp ) );
[433]1884    txt_id   = hal_remote_lw ( XPTR( txt_cxy , &txt_ptr->channel ) );
[428]1885
[436]1886    // transfer ownership only if process is the TXT owner
1887    if( (owner_xp == process_xp) && (txt_id > 0) ) 
[428]1888    {
[436]1889        // get extended pointers on root and lock of attached processes list
1890        root_xp = XPTR( txt_cxy , &txt_ptr->ext.txt.root );
1891        lock_xp = XPTR( txt_cxy , &txt_ptr->ext.txt.lock );
[428]1892
[436]1893        // get lock
1894        remote_spinlock_lock( lock_xp );
1895
1896        if( process_get_ppid( process_xp ) != 1 )           // process is not KSH
[428]1897        {
[436]1898            // scan attached process list to find KSH process
1899            XLIST_FOREACH( root_xp , iter_xp )
1900            {
1901                current_xp  = XLIST_ELEMENT( iter_xp , process_t , txt_list );
1902                current_cxy = GET_CXY( current_xp );
1903                current_ptr = GET_PTR( current_xp );
[435]1904
[436]1905                if( process_get_ppid( current_xp ) == 1 )  // current is KSH
1906                {
1907                    // release lock
1908                    remote_spinlock_unlock( lock_xp );
1909
1910                    // set owner field in TXT chdev
1911                    hal_remote_swd( XPTR( txt_cxy , &txt_ptr->ext.txt.owner_xp ) , current_xp );
1912
[446]1913#if DEBUG_PROCESS_TXT
[457]1914cycle   = (uint32_t)hal_get_cycles();
1915uint32_t ksh_pid = hal_remote_lw( XPTR( current_cxy , &current_ptr->pid ) );
[446]1916if( DEBUG_PROCESS_TXT < cycle )
[457]1917printk("\n[DBG] %s : thread %x in process %x release TXT %d to KSH %x / cycle %d\n",
1918__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, txt_id, ksh_pid, cycle );
1919process_txt_display( txt_id );
[436]1920#endif
1921                     return;
1922                }
1923            }
1924 
1925            // release lock
1926            remote_spinlock_unlock( lock_xp );
1927
1928            // PANIC if KSH not found
[492]1929            assert( false , "KSH process not found for TXT %d" );
[436]1930
1931            return;
1932        }
1933        else                                               // process is KSH
1934        {
1935            // scan attached process list to find another process
1936            XLIST_FOREACH( root_xp , iter_xp )
[428]1937            {
[436]1938                current_xp  = XLIST_ELEMENT( iter_xp , process_t , txt_list );
1939                current_cxy = GET_CXY( current_xp );
1940                current_ptr = GET_PTR( current_xp );
1941
1942                if( current_xp != process_xp )            // current is not KSH
1943                {
1944                    // release lock
1945                    remote_spinlock_unlock( lock_xp );
1946
1947                    // set owner field in TXT chdev
1948                    hal_remote_swd( XPTR( txt_cxy , &txt_ptr->ext.txt.owner_xp ) , current_xp );
1949
[446]1950#if DEBUG_PROCESS_TXT
[457]1951cycle   = (uint32_t)hal_get_cycles();
1952uint32_t new_pid = hal_remote_lw( XPTR( current_cxy , &current_ptr->pid ) );
[446]1953if( DEBUG_PROCESS_TXT < cycle )
[457]1954printk("\n[DBG] %s : thread %x in process %x release TXT %d to process %x / cycle %d\n",
1955__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, txt_id, new_pid, cycle );
1956process_txt_display( txt_id );
[436]1957#endif
1958                     return;
1959                }
[428]1960            }
[436]1961
1962            // release lock
1963            remote_spinlock_unlock( lock_xp );
1964
1965            // no more owner for TXT if no other process found
1966            hal_remote_swd( XPTR( txt_cxy , &txt_ptr->ext.txt.owner_xp ) , XPTR_NULL );
1967
[446]1968#if DEBUG_PROCESS_TXT
[436]1969cycle = (uint32_t)hal_get_cycles();
[446]1970if( DEBUG_PROCESS_TXT < cycle )
[457]1971printk("\n[DBG] %s : thread %x in process %x release TXT %d to nobody / cycle %d\n",
1972__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, txt_id, cycle );
1973process_txt_display( txt_id );
[436]1974#endif
1975            return;
[428]1976        }
[436]1977    }
1978    else
1979    {
[433]1980
[446]1981#if DEBUG_PROCESS_TXT
[436]1982cycle = (uint32_t)hal_get_cycles();
[446]1983if( DEBUG_PROCESS_TXT < cycle )
[457]1984printk("\n[DBG] %s : thread %x in process %d does nothing (not TXT owner) / cycle %d\n",
1985__FUNCTION__, CURRENT_THREAD->trdid, process_pid, cycle );
1986process_txt_display( txt_id );
[436]1987#endif
1988
[428]1989    }
[436]1990}  // end process_txt_transfer_ownership()
[428]1991
1992
[457]1993//////////////////////////////////////////////////
1994uint32_t process_txt_is_owner( xptr_t process_xp )
1995{
1996    // get local pointer and cluster of process in owner cluster
1997    cxy_t       process_cxy = GET_CXY( process_xp );
1998    process_t * process_ptr = GET_PTR( process_xp );
1999
2000    // check owner cluster
2001    pid_t process_pid = hal_remote_lw( XPTR( process_cxy , &process_ptr->pid ) );
[492]2002    assert( (process_cxy == CXY_FROM_PID( process_pid )) ,
[457]2003    "process descriptor not in owner cluster\n" );
2004
2005    // get extended pointer on stdin pseudo file
2006    xptr_t file_xp = hal_remote_lwd( XPTR( process_cxy , &process_ptr->fd_array.array[0] ) );
2007
2008    // get pointers on TXT chdev
2009    xptr_t    txt_xp  = chdev_from_file( file_xp );
2010    cxy_t     txt_cxy = GET_CXY( txt_xp );
2011    chdev_t * txt_ptr = GET_PTR( txt_xp );
2012
2013    // get extended pointer on TXT_RX owner process
2014    xptr_t owner_xp = hal_remote_lwd( XPTR( txt_cxy , &txt_ptr->ext.txt.owner_xp ) );
2015
2016    return (process_xp == owner_xp);
2017
2018}   // end process_txt_is_owner()
2019
[436]2020////////////////////////////////////////////////     
2021xptr_t process_txt_get_owner( uint32_t channel )
[435]2022{
2023    xptr_t      txt_rx_xp  = chdev_dir.txt_rx[channel];
2024    cxy_t       txt_rx_cxy = GET_CXY( txt_rx_xp );
2025    chdev_t *   txt_rx_ptr = GET_PTR( txt_rx_xp );
2026
[436]2027    return (xptr_t)hal_remote_lwd( XPTR( txt_rx_cxy , &txt_rx_ptr->ext.txt.owner_xp ) );
[435]2028
[457]2029}  // end process_txt_get_owner()
2030
[435]2031///////////////////////////////////////////
2032void process_txt_display( uint32_t txt_id )
2033{
2034    xptr_t      chdev_xp;
2035    cxy_t       chdev_cxy;
2036    chdev_t   * chdev_ptr;
2037    xptr_t      root_xp;
2038    xptr_t      lock_xp;
2039    xptr_t      current_xp;
2040    xptr_t      iter_xp;
[443]2041    cxy_t       txt0_cxy;
2042    chdev_t   * txt0_ptr;
2043    xptr_t      txt0_xp;
2044    xptr_t      txt0_lock_xp;
2045    reg_t       txt0_save_sr;    // save SR to take TXT0 lock in busy mode
2046   
[435]2047    assert( (txt_id < LOCAL_CLUSTER->nb_txt_channels) ,
[492]2048    "illegal TXT terminal index" );
[435]2049
[443]2050    // get pointers on TXT0 chdev
2051    txt0_xp  = chdev_dir.txt_tx[0];
2052    txt0_cxy = GET_CXY( txt0_xp );
2053    txt0_ptr = GET_PTR( txt0_xp );
2054
2055    // get extended pointer on TXT0 lock
2056    txt0_lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
2057
[435]2058    // get pointers on TXT_RX[txt_id] chdev
2059    chdev_xp  = chdev_dir.txt_rx[txt_id];
2060    chdev_cxy = GET_CXY( chdev_xp );
2061    chdev_ptr = GET_PTR( chdev_xp );
2062
2063    // get extended pointer on root & lock of attached process list
2064    root_xp = XPTR( chdev_cxy , &chdev_ptr->ext.txt.root );
2065    lock_xp = XPTR( chdev_cxy , &chdev_ptr->ext.txt.lock );
2066
[443]2067    // get lock on attached process list
2068    remote_spinlock_lock( lock_xp );
2069
2070    // get TXT0 lock in busy waiting mode
2071    remote_spinlock_lock_busy( txt0_lock_xp , &txt0_save_sr );
2072
[435]2073    // display header
[443]2074    nolock_printk("\n***** processes attached to TXT_%d / cycle %d\n",
2075    txt_id , (uint32_t)hal_get_cycles() );
[435]2076
[436]2077    // scan attached process list
[435]2078    XLIST_FOREACH( root_xp , iter_xp )
2079    {
2080        current_xp  = XLIST_ELEMENT( iter_xp , process_t , txt_list );
2081        process_display( current_xp );
2082    }
2083
[443]2084    // release TXT0 lock in busy waiting mode
2085    remote_spinlock_unlock_busy( txt0_lock_xp , txt0_save_sr );
2086
2087    // release lock on attached process list
[435]2088    remote_spinlock_unlock( lock_xp );
2089
2090}  // end process_txt_display
Note: See TracBrowser for help on using the repository browser.