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

Last change on this file since 580 was 580, checked in by alain, 3 years ago

1) Register the kernel process in the cluster manager local list.
2) Introduce a new service in idbg : display the set of busylocks taken by a given thread.

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