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

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

Fix a bad bug in scheduler...

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