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

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

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

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