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

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

Fix various bugs

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