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

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

Fix a bug in scheduler related to RPC blocking.

File size: 68.7 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 DEBUG_PROCESS_REFERENCE_INIT
127uint32_t cycle = (uint32_t)hal_get_cycles();
128if( 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 (DEBUG_PROCESS_REFERENCE_INIT & 1)
144cycle = (uint32_t)hal_get_cycles();
145if( 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 (DEBUG_PROCESS_REFERENCE_INIT & 1)
235cycle = (uint32_t)hal_get_cycles();
236if( 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 (DEBUG_PROCESS_REFERENCE_INIT & 1)
275cycle = (uint32_t)hal_get_cycles();
276if( 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 DEBUG_PROCESS_COPY_INIT
300uint32_t cycle = (uint32_t)hal_get_cycles();
301if( 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 DEBUG_PROCESS_COPY_INIT
350cycle = (uint32_t)hal_get_cycles();
351if( 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 DEBUG_PROCESS_DESTROY
374uint32_t cycle = (uint32_t)hal_get_cycles();
375if( 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    // remove process from local_list in local cluster manager
381    cluster_process_local_unlink( process );
382
383    // remove process from copies_list in owner cluster manager
384    cluster_process_copies_unlink( process );
385
386    // remove process from children_list if process is in owner cluster
387    if( CXY_FROM_PID( pid ) == local_cxy )
388    {
389        // get pointers on parent process
390        parent_xp  = process->parent_xp;
391        parent_cxy = GET_CXY( parent_xp );
392        parent_ptr = GET_PTR( parent_xp );
393
394        // get extended pointer on children_lock in parent process
395        children_lock_xp = XPTR( parent_cxy , &parent_ptr->children_lock );
396
397        // remove process from children_list
398        remote_spinlock_lock( children_lock_xp );
399        xlist_unlink( XPTR( local_cxy , &process->children_list ) );
400        remote_spinlock_unlock( children_lock_xp );
401    }
402
403    // release the process PID to cluster manager
404    cluster_pid_release( pid );
405
406    // FIXME close all open files and update dirty [AG]
407
408    // decrease refcount for bin file, root file and cwd file
409        if( process->vfs_bin_xp  != XPTR_NULL ) vfs_file_count_down( process->vfs_bin_xp );
410        if( process->vfs_root_xp != XPTR_NULL ) vfs_file_count_down( process->vfs_root_xp );
411        if( process->vfs_cwd_xp  != XPTR_NULL ) vfs_file_count_down( process->vfs_cwd_xp );
412
413    // Destroy VMM
414    vmm_destroy( process );
415
416    // release memory allocated to process descriptor
417    process_free( process );
418
419#if DEBUG_PROCESS_DESTROY
420cycle = (uint32_t)hal_get_cycles();
421if( DEBUG_PROCESS_DESTROY )
422printk("\n[DBG] %s : thread %x exit / destroyed process %x (pid = %x) / cycle %d\n",
423__FUNCTION__ , CURRENT_THREAD , process, pid, cycle );
424#endif
425
426}  // end process_destroy()
427
428/////////////////////////////////////////////////
429char * process_action_str( uint32_t action_type )
430{
431    if     ( action_type == BLOCK_ALL_THREADS   ) return "BLOCK";
432    else if( action_type == UNBLOCK_ALL_THREADS ) return "UNBLOCK";
433    else if( action_type == DELETE_ALL_THREADS  ) return "DELETE";
434    else                                          return "undefined";
435}
436
437////////////////////////////////////////
438void process_sigaction( pid_t       pid,
439                        uint32_t    action_type )
440{
441    cxy_t              owner_cxy;         // owner cluster identifier
442    lpid_t             lpid;              // process index in owner cluster
443    cluster_t        * cluster;           // pointer on cluster manager
444    xptr_t             root_xp;           // extended pointer on root of copies
445    xptr_t             lock_xp;           // extended pointer on lock protecting copies
446    xptr_t             iter_xp;           // iterator on copies list
447    xptr_t             process_xp;        // extended pointer on process copy
448    cxy_t              process_cxy;       // process copy cluster identifier
449    reg_t              save_sr;           // for critical section
450    rpc_desc_t         rpc;               // shared RPC descriptor
451
452    thread_t * client = CURRENT_THREAD;
453
454#if DEBUG_PROCESS_SIGACTION
455uint32_t cycle = (uint32_t)hal_get_cycles();
456if( DEBUG_PROCESS_SIGACTION < cycle )
457printk("\n[DBG] %s : thread %x enter to %s process %x / cycle %d\n",
458__FUNCTION__ , client, process_action_str( action_type ) , pid , cycle );
459#endif
460
461    // get pointer on local cluster manager
462    cluster = LOCAL_CLUSTER;
463
464    // get owner cluster identifier and process lpid
465    owner_cxy = CXY_FROM_PID( pid );
466    lpid      = LPID_FROM_PID( pid );
467
468    // get root of list of copies, lock, and number of copies from owner cluster
469    root_xp   = XPTR( owner_cxy , &cluster->pmgr.copies_root[lpid] );
470    lock_xp   = XPTR( owner_cxy , &cluster->pmgr.copies_lock[lpid] );
471
472    // check action type
473    assert( ((action_type == DELETE_ALL_THREADS ) ||
474             (action_type == BLOCK_ALL_THREADS )  ||
475             (action_type == UNBLOCK_ALL_THREADS )), __FUNCTION__ , "illegal action type" );
476             
477    // allocate a - shared - RPC descriptor in client thread stack
478    // it can be shared because all parallel, non-blocking, server threads
479    // use the same input arguments, and use the shared RPC response field
480
481    // the client thread makes the following sequence:
482    // 1. mask interrupts
483    // 2. block itself
484    // 3. send RPC requests to all copies
485    // 4. unmask interrupts
486    // 5. deschedule
487
488    // mask IRQs
489    hal_disable_irq( &save_sr);
490
491    // client register blocking condition for itself
492    thread_block( XPTR( local_cxy , client ) , THREAD_BLOCKED_RPC );
493
494    // take the lock protecting the copies
495    remote_spinlock_lock( lock_xp );
496
497    // initialize shared RPC descriptor
498    rpc.responses = 0;
499    rpc.blocking  = false;
500    rpc.index     = RPC_PROCESS_SIGACTION;
501    rpc.thread    = client;
502    rpc.lid       = client->core->lid;
503    rpc.args[0]   = action_type;
504    rpc.args[1]   = pid;
505
506    // send RPCs to all clusters containing process copiess
507    XLIST_FOREACH( root_xp , iter_xp )
508    {
509
510#if DEBUG_PROCESS_SIGACTION
511if( DEBUG_PROCESS_SIGACTION < cycle )
512printk("\n[DBG] %s : send RPC to %s process %x in cluster %x\n",
513__FUNCTION__ , process_action_str( action_type ) , pid , process_cxy );
514#endif
515        // atomically increment responses counter
516        hal_atomic_add( (void *)&rpc.responses , 1 );
517
518        process_xp  = XLIST_ELEMENT( iter_xp , process_t , copies_list );
519        process_cxy = GET_CXY( process_xp );
520
521        // call RPC in target cluster
522        rpc_process_sigaction_client( process_cxy , &rpc );
523    }
524   
525    // release the lock protecting process copies
526    remote_spinlock_unlock( lock_xp );
527
528    // restore IRQs
529    hal_restore_irq( save_sr);
530
531    // client deschedule : will be unblocked by the last RPC server thread
532    sched_yield("blocked on rpc_process_sigaction");
533
534#if DEBUG_PROCESS_SIGACTION
535cycle = (uint32_t)hal_get_cycles();
536if( DEBUG_PROCESS_SIGACTION < cycle )
537printk("\n[DBG] %s : thread %x exit after %s process %x in cluster %x / cycle %d\n",
538__FUNCTION__ , client, process_action_str( action_type ) , pid , local_cxy , cycle );
539#endif
540
541}  // end process_sigaction()
542
543/////////////////////////////////////////////////
544void process_block_threads( process_t * process )
545{
546    thread_t          * target;         // pointer on target thread
547    thread_t          * this;           // pointer on calling thread
548    uint32_t            ltid;           // index in process th_tbl
549    cxy_t               owner_cxy;      // target process owner cluster
550    uint32_t            count;          // requests counter
551    volatile uint32_t   ack_count;      // scheduler acknowledge counter
552
553    // get calling thread pointer
554    this = CURRENT_THREAD;
555
556    // get target process owner cluster
557    owner_cxy = CXY_FROM_PID( process->pid );
558
559#if DEBUG_PROCESS_SIGACTION
560uint32_t cycle = (uint32_t)hal_get_cycles();
561if( DEBUG_PROCESS_SIGACTION < cycle )
562printk("\n[DBG] %s : thread %x enter for process %x in cluster %x / cycle %d\n",
563__FUNCTION__ , this , process->pid , local_cxy , cycle );
564#endif
565
566    // get lock protecting process th_tbl[]
567    spinlock_lock( &process->th_lock );
568
569    // loop to block all threads but the main thread
570    // we use both "ltid" and "count" because it can exist "holes" in th_tbl
571    for( ltid = 0 , count = 0 , ack_count = 0 ; count < process->th_nr ; ltid++ )
572    {
573        target = process->th_tbl[ltid];
574
575        if( target != NULL )                                 // thread exist
576        {
577            count++;
578
579            // main thread should not be deleted
580            if( (ltid != 0) || (owner_cxy != local_cxy) )
581            {
582                // set the global blocked bit in target thread descriptor.
583                thread_block( XPTR( local_cxy , target ) , THREAD_BLOCKED_GLOBAL );
584 
585                // - if the calling thread and the target thread are on the same core,
586                //   we don't need confirmation from scheduler,
587                // - if the calling thread and the target thread are not running on the same
588                //   core, we ask the target scheduler to acknowlege the blocking
589                //   to be sure that the target thread is not running.
590           
591                if( this->core->lid != target->core->lid )
592                {
593                    // increment responses counter
594                    hal_atomic_add( (void*)&ack_count , 1 );
595
596                    // set FLAG_REQ_ACK and &ack_rsp_count in target descriptor
597                    thread_set_req_ack( target , (uint32_t *)&ack_count );
598
599                    // force scheduling on target thread
600                    dev_pic_send_ipi( local_cxy , target->core->lid );
601                }
602            }
603        }
604    }
605
606    // release lock protecting process th_tbl[]
607    spinlock_unlock( &process->th_lock );
608
609    // wait acknowledges
610    while( 1 )
611    {
612        // exit when all scheduler acknoledges received
613        if ( ack_count == 0 ) break;
614   
615        // wait 1000 cycles before retry
616        hal_fixed_delay( 1000 );
617    }
618
619#if DEBUG_PROCESS_SIGACTION
620cycle = (uint32_t)hal_get_cycles();
621if( DEBUG_PROCESS_SIGACTION < cycle )
622printk("\n[DBG] %s : thread %x exit for process %x in cluster %x / cycle %d\n",
623__FUNCTION__ , this , process->pid , local_cxy , cycle );
624#endif
625
626}  // end process_block_threads()
627
628///////////////////////////////////////////////////
629void process_unblock_threads( process_t * process )
630{
631    thread_t          * target;        // pointer on target thead
632    thread_t          * this;          // pointer on calling thread
633    uint32_t            ltid;          // index in process th_tbl
634    uint32_t            count;         // requests counter
635
636    // get calling thread pointer
637    this = CURRENT_THREAD;
638
639#if DEBUG_PROCESS_SIGACTION
640uint32_t cycle = (uint32_t)hal_get_cycles();
641if( DEBUG_PROCESS_SIGACTION < cycle )
642printk("\n[DBG] %s : thread %x enter for process %x in cluster %x / cycle %d\n",
643__FUNCTION__ , this , process->pid , local_cxy , cycle );
644#endif
645
646    // get lock protecting process th_tbl[]
647    spinlock_lock( &process->th_lock );
648
649    // loop on process threads to unblock all threads
650    // we use both "ltid" and "count" because it can exist "holes" in th_tbl
651    for( ltid = 0 , count = 0 ; count < process->th_nr ; ltid++ )
652    {
653        target = process->th_tbl[ltid];
654
655        if( target != NULL )             // thread found
656        {
657            count++;
658
659            // reset the global blocked bit in target thread descriptor.
660            thread_unblock( XPTR( local_cxy , target ) , THREAD_BLOCKED_GLOBAL );
661        }
662    }
663
664    // release lock protecting process th_tbl[]
665    spinlock_unlock( &process->th_lock );
666
667#if DEBUG_PROCESS_SIGACTION
668cycle = (uint32_t)hal_get_cycles();
669if( DEBUG_PROCESS_SIGACTION < cycle )
670printk("\n[DBG] %s : thread %x exit for process %x in cluster %x / cycle %d\n",
671__FUNCTION__ , this , process->pid , local_cxy , cycle );
672#endif
673
674}  // end process_unblock_threads()
675
676//////////////////////////////////////////////////
677void process_delete_threads( process_t * process )
678{
679    thread_t          * target;        // pointer on target thread
680    uint32_t            ltid;          // index in process th_tbl
681    uint32_t            count;         // threads counter
682
683#if DEBUG_PROCESS_SIGACTION
684uint32_t cycle = (uint32_t)hal_get_cycles();
685if( DEBUG_PROCESS_SIGACTION < cycle )
686printk("\n[DBG] %s : thread %x enter for process %x in cluster %x / cycle %d\n",
687__FUNCTION__ , CURRENT_THREAD , process->pid , local_cxy , cycle );
688#endif
689
690    // get lock protecting process th_tbl[]
691    spinlock_lock( &process->th_lock );
692
693    // loop to set the REQ_DELETE flag on all threads but the main
694    // we use both "ltid" and "count" because it can exist "holes" in th_tbl
695    for( ltid = 0 , count = 0  ; count < process->th_nr ; ltid++ )
696    {
697        target = process->th_tbl[ltid];
698
699        if( target != NULL ) 
700        {
701            count++;
702           
703            thread_kill( XPTR( local_cxy , target ), 
704                         false,                       // is_exit
705                         true );                      // is_forced
706        }
707    }
708
709    // release lock protecting process th_tbl[]
710    spinlock_unlock( &process->th_lock );
711
712#if DEBUG_PROCESS_SIGACTION
713cycle = (uint32_t)hal_get_cycles();
714if( DEBUG_PROCESS_SIGACTION < cycle )
715printk("\n[DBG] %s : thread %x exit for process %x in cluster %x / cycle %d\n",
716__FUNCTION__ , CURRENT_THREAD , process->pid , local_cxy , cycle );
717#endif
718
719}  // end process_delete_threads()
720
721///////////////////////////////////////////////
722process_t * process_get_local_copy( pid_t pid )
723{
724    error_t        error;
725    process_t    * process_ptr;   // local pointer on process
726    xptr_t         process_xp;    // extended pointer on process
727
728    cluster_t * cluster = LOCAL_CLUSTER;
729
730    // get lock protecting local list of processes
731    remote_spinlock_lock( XPTR( local_cxy , &cluster->pmgr.local_lock ) );
732
733    // scan the local list of process descriptors to find the process
734    xptr_t  iter;
735    bool_t  found = false;
736    XLIST_FOREACH( XPTR( local_cxy , &cluster->pmgr.local_root ) , iter )
737    {
738        process_xp  = XLIST_ELEMENT( iter , process_t , local_list );
739        process_ptr = GET_PTR( process_xp );
740        if( process_ptr->pid == pid )
741        {
742            found = true;
743            break;
744        }
745    }
746
747    // release lock protecting local list of processes
748    remote_spinlock_unlock( XPTR( local_cxy , &cluster->pmgr.local_lock ) );
749
750    // allocate memory for a new local process descriptor
751    // and initialise it from reference cluster if required
752    if( !found )
753    {
754        // get extended pointer on reference process descriptor
755        xptr_t ref_xp = cluster_get_reference_process_from_pid( pid );
756
757        assert( (ref_xp != XPTR_NULL) , __FUNCTION__ , "illegal pid\n" );
758
759        // allocate memory for local process descriptor
760        process_ptr = process_alloc();
761        if( process_ptr == NULL )  return NULL;
762
763        // initialize local process descriptor copy
764        error = process_copy_init( process_ptr , ref_xp );
765        if( error ) return NULL;
766    }
767
768    return process_ptr;
769
770}  // end process_get_local_copy()
771
772////////////////////////////////////////////
773pid_t process_get_ppid( xptr_t  process_xp )
774{
775    cxy_t       process_cxy;
776    process_t * process_ptr;
777    xptr_t      parent_xp;
778    cxy_t       parent_cxy;
779    process_t * parent_ptr;
780
781    // get process cluster and local pointer
782    process_cxy = GET_CXY( process_xp );
783    process_ptr = GET_PTR( process_xp );
784
785    // get pointers on parent process
786    parent_xp  = (xptr_t)hal_remote_lwd( XPTR( process_cxy , &process_ptr->parent_xp ) );
787    parent_cxy = GET_CXY( parent_xp );
788    parent_ptr = GET_PTR( parent_xp );
789
790    return hal_remote_lw( XPTR( parent_cxy , &parent_ptr->pid ) );
791}
792
793//////////////////////////////////////////////////////////////////////////////////////////
794// File descriptor array related functions
795//////////////////////////////////////////////////////////////////////////////////////////
796
797///////////////////////////////////////////
798void process_fd_init( process_t * process )
799{
800    uint32_t fd;
801
802    remote_spinlock_init( XPTR( local_cxy , &process->fd_array.lock ) );
803
804    process->fd_array.current = 0;
805
806    // initialize array
807    for ( fd = 0 ; fd < CONFIG_PROCESS_FILE_MAX_NR ; fd++ )
808    {
809        process->fd_array.array[fd] = XPTR_NULL;
810    }
811}
812
813//////////////////////////////
814bool_t process_fd_array_full()
815{
816    // get extended pointer on reference process
817    xptr_t ref_xp = CURRENT_THREAD->process->ref_xp;
818
819    // get reference process cluster and local pointer
820    process_t * ref_ptr = GET_PTR( ref_xp );
821    cxy_t       ref_cxy = GET_CXY( ref_xp );
822
823    // get number of open file descriptors from reference fd_array
824    uint32_t current = hal_remote_lw( XPTR( ref_cxy , &ref_ptr->fd_array.current ) );
825
826        return ( current >= CONFIG_PROCESS_FILE_MAX_NR );
827}
828
829/////////////////////////////////////////////////
830error_t process_fd_register( process_t * process,
831                             xptr_t      file_xp,
832                             uint32_t  * fdid )
833{
834    bool_t    found;
835    uint32_t  id;
836    xptr_t    xp;
837
838    // get reference process cluster and local pointer
839    xptr_t ref_xp = process->ref_xp;
840    process_t * ref_ptr = GET_PTR( ref_xp );
841    cxy_t       ref_cxy = GET_CXY( ref_xp );
842
843    // take lock protecting reference fd_array
844        remote_spinlock_lock( XPTR( ref_cxy , &ref_ptr->fd_array.lock ) );
845
846    found   = false;
847
848    for ( id = 0; id < CONFIG_PROCESS_FILE_MAX_NR ; id++ )
849    {
850        xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->fd_array.array[id] ) );
851        if ( xp == XPTR_NULL )
852        {
853            found = true;
854            hal_remote_swd( XPTR( ref_cxy , &ref_ptr->fd_array.array[id] ) , file_xp );
855                hal_remote_atomic_add( XPTR( ref_cxy , &ref_ptr->fd_array.current ) , 1 );
856                        *fdid = id;
857            break;
858        }
859    }
860
861    // release lock protecting reference fd_array
862        remote_spinlock_unlock( XPTR( ref_cxy , &ref_ptr->fd_array.lock ) );
863
864    if ( !found ) return -1;
865    else          return 0;
866}
867
868////////////////////////////////////////////////
869xptr_t process_fd_get_xptr( process_t * process,
870                            uint32_t    fdid )
871{
872    xptr_t  file_xp;
873
874    // access local copy of process descriptor
875    file_xp = process->fd_array.array[fdid];
876
877    if( file_xp == XPTR_NULL )
878    {
879        // get reference process cluster and local pointer
880        xptr_t      ref_xp  = process->ref_xp;
881        cxy_t       ref_cxy = GET_CXY( ref_xp );
882        process_t * ref_ptr = GET_PTR( ref_xp );
883
884        // access reference process descriptor
885        file_xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->fd_array.array[fdid] ) );
886
887        // update local fd_array if found
888        if( file_xp != XPTR_NULL )
889        {
890            process->fd_array.array[fdid] = file_xp;
891        }
892    }
893
894    return file_xp;
895
896}  // end process_fd_get_xptr()
897
898///////////////////////////////////////////
899void process_fd_remote_copy( xptr_t dst_xp,
900                             xptr_t src_xp )
901{
902    uint32_t fd;
903    xptr_t   entry;
904
905    // get cluster and local pointer for src fd_array
906    cxy_t        src_cxy = GET_CXY( src_xp );
907    fd_array_t * src_ptr = GET_PTR( src_xp );
908
909    // get cluster and local pointer for dst fd_array
910    cxy_t        dst_cxy = GET_CXY( dst_xp );
911    fd_array_t * dst_ptr = GET_PTR( dst_xp );
912
913    // get the remote lock protecting the src fd_array
914        remote_spinlock_lock( XPTR( src_cxy , &src_ptr->lock ) );
915
916    // loop on all fd_array entries
917    for( fd = 0 ; fd < CONFIG_PROCESS_FILE_MAX_NR ; fd++ )
918        {
919                entry = (xptr_t)hal_remote_lwd( XPTR( src_cxy , &src_ptr->array[fd] ) );
920
921                if( entry != XPTR_NULL )
922                {
923            // increment file descriptor ref count
924            vfs_file_count_up( entry );
925
926                        // copy entry in destination process fd_array
927                        hal_remote_swd( XPTR( dst_cxy , &dst_ptr->array[fd] ) , entry );
928                }
929        }
930
931    // release lock on source process fd_array
932        remote_spinlock_unlock( XPTR( src_cxy , &src_ptr->lock ) );
933
934}  // end process_fd_remote_copy()
935
936////////////////////////////////////////////////////////////////////////////////////
937//  Thread related functions
938////////////////////////////////////////////////////////////////////////////////////
939
940/////////////////////////////////////////////////////
941error_t process_register_thread( process_t * process,
942                                 thread_t  * thread,
943                                 trdid_t   * trdid )
944{
945    ltid_t   ltid;
946    bool_t   found = false;
947
948    assert( (process != NULL) , __FUNCTION__ , "process argument is NULL" );
949
950    assert( (thread != NULL) , __FUNCTION__ , "thread argument is NULL" );
951
952    // take lock protecting th_tbl
953    spinlock_lock( &process->th_lock );
954
955    // search a free slot in th_tbl[]
956    for( ltid = 0 ; ltid < CONFIG_THREAD_MAX_PER_CLUSTER ; ltid++ )
957    {
958        if( process->th_tbl[ltid] == NULL )
959        {
960            found = true;
961            break;
962        }
963    }
964
965    if( found )
966    {
967        // register thread in th_tbl[]
968        process->th_tbl[ltid] = thread;
969        process->th_nr++;
970
971        // returns trdid
972        *trdid = TRDID( local_cxy , ltid );
973    }
974
975
976    // release lock protecting th_tbl
977    hal_fence();
978    spinlock_unlock( &process->th_lock );
979
980    return (found) ? 0 : ENOMEM;
981
982}  // end process_register_thread()
983
984///////////////////////////////////////////////
985void process_remove_thread( thread_t * thread )
986{
987    assert( (thread != NULL) , __FUNCTION__ , "thread argument is NULL" );
988
989    process_t * process = thread->process;
990
991    // get thread local index
992    ltid_t  ltid = LTID_FROM_TRDID( thread->trdid );
993
994    // take lock protecting th_tbl
995    spinlock_lock( &process->th_lock );
996
997    assert( (process->th_nr) , __FUNCTION__ , "process th_nr cannot be 0\n" );
998
999    // remove thread from th_tbl[]
1000    process->th_tbl[ltid] = NULL;
1001    process->th_nr--;
1002
1003    hal_fence();
1004
1005    // release lock protecting th_tbl
1006    spinlock_unlock( &process->th_lock );
1007
1008}  // process_remove_thread()
1009
1010/////////////////////////////////////////////////////////
1011error_t process_make_fork( xptr_t      parent_process_xp,
1012                           xptr_t      parent_thread_xp,
1013                           pid_t     * child_pid,
1014                           thread_t ** child_thread )
1015{
1016    process_t * process;         // local pointer on child process descriptor
1017    thread_t  * thread;          // local pointer on child thread descriptor
1018    pid_t       new_pid;         // process identifier for child process
1019    pid_t       parent_pid;      // process identifier for parent process
1020    xptr_t      ref_xp;          // extended pointer on reference process
1021    xptr_t      vfs_bin_xp;      // extended pointer on .elf file
1022    error_t     error;
1023
1024    // get cluster and local pointer for parent process
1025    cxy_t       parent_process_cxy = GET_CXY( parent_process_xp );
1026    process_t * parent_process_ptr = GET_PTR( parent_process_xp );
1027
1028    // get parent process PID and extended pointer on .elf file
1029    parent_pid = hal_remote_lw (XPTR( parent_process_cxy , &parent_process_ptr->pid));
1030    vfs_bin_xp = hal_remote_lwd(XPTR( parent_process_cxy , &parent_process_ptr->vfs_bin_xp));
1031
1032    // check parent process is the reference process
1033    ref_xp = hal_remote_lwd( XPTR( parent_process_cxy , &parent_process_ptr->ref_xp ) );
1034
1035printk("\n@@@ %s : parent_cxy = %x / parent_ptr = %x / ref_cxy = %x / ref_ptr = %x\n",
1036__FUNCTION__, parent_process_cxy, parent_process_ptr, GET_CXY( ref_xp ), GET_PTR( ref_xp ) );
1037
1038    assert( (parent_process_xp == ref_xp ) , __FUNCTION__ ,
1039    "parent process must be the reference process\n" );
1040
1041#if DEBUG_PROCESS_MAKE_FORK
1042uint32_t cycle = (uint32_t)hal_get_cycles();
1043if( DEBUG_PROCESS_MAKE_FORK < cycle )
1044printk("\n[DBG] %s : thread %x enter for process %x / cluster %x / cycle %d\n",
1045__FUNCTION__, CURRENT_THREAD, parent_pid, local_cxy, cycle );
1046#endif
1047
1048    // allocate a process descriptor
1049    process = process_alloc();
1050    if( process == NULL )
1051    {
1052        printk("\n[ERROR] in %s : cannot get process in cluster %x\n", 
1053        __FUNCTION__, local_cxy ); 
1054        return -1;
1055    }
1056
1057    // allocate a child PID from local cluster
1058    error = cluster_pid_alloc( process , &new_pid );
1059    if( error ) 
1060    {
1061        printk("\n[ERROR] in %s : cannot get PID in cluster %x\n", 
1062        __FUNCTION__, local_cxy ); 
1063        process_free( process );
1064        return -1;
1065    }
1066
1067    // initializes child process descriptor from parent process descriptor
1068    process_reference_init( process,
1069                            new_pid,
1070                            parent_process_xp,
1071                            parent_process_xp );
1072
1073#if( DEBUG_PROCESS_MAKE_FORK & 1 )
1074cycle = (uint32_t)hal_get_cycles();
1075if( DEBUG_PROCESS_MAKE_FORK < cycle )
1076printk("\n[DBG] %s : thread %x created child_process %x / child_pid %x / cycle %d\n",
1077__FUNCTION__, CURRENT_THREAD, process, new_pid, cycle );
1078#endif
1079
1080    // copy VMM from parent descriptor to child descriptor
1081    error = vmm_fork_copy( process,
1082                           parent_process_xp );
1083    if( error )
1084    {
1085        printk("\n[ERROR] in %s : cannot copy VMM in cluster %x\n", 
1086        __FUNCTION__, local_cxy ); 
1087        process_free( process );
1088        cluster_pid_release( new_pid );
1089        return -1;
1090    }
1091
1092#if( DEBUG_PROCESS_MAKE_FORK & 1 )
1093cycle = (uint32_t)hal_get_cycles();
1094if( DEBUG_PROCESS_MAKE_FORK < cycle )
1095printk("\n[DBG] %s : thread %x copied VMM from parent %x to child %x / cycle %d\n",
1096__FUNCTION__ , CURRENT_THREAD , parent_pid, new_pid, cycle );
1097#endif
1098
1099    // update extended pointer on .elf file
1100    process->vfs_bin_xp = vfs_bin_xp;
1101
1102    // create child thread descriptor from parent thread descriptor
1103    error = thread_user_fork( parent_thread_xp,
1104                              process,
1105                              &thread );
1106    if( error )
1107    {
1108        printk("\n[ERROR] in %s : cannot create thread in cluster %x\n",
1109        __FUNCTION__, local_cxy ); 
1110        process_free( process );
1111        cluster_pid_release( new_pid );
1112        return -1;
1113    }
1114
1115    // check main thread LTID
1116    assert( (LTID_FROM_TRDID(thread->trdid) == 0) , __FUNCTION__ ,
1117    "main thread must have LTID == 0\n" );
1118
1119#if( DEBUG_PROCESS_MAKE_FORK & 1 )
1120cycle = (uint32_t)hal_get_cycles();
1121if( DEBUG_PROCESS_MAKE_FORK < cycle )
1122printk("\n[DBG] %s : thread %x created child thread %x / cycle %d\n", 
1123__FUNCTION__ , CURRENT_THREAD, thread, cycle );
1124#endif
1125
1126    // set Copy_On_Write flag in parent process GPT
1127    // this includes all replicated GPT copies
1128    if( parent_process_cxy == local_cxy )   // reference is local
1129    {
1130        vmm_set_cow( parent_process_ptr );
1131    }
1132    else                                    // reference is remote
1133    {
1134        rpc_vmm_set_cow_client( parent_process_cxy,
1135                                parent_process_ptr );
1136    }
1137
1138    // set Copy_On_Write flag in child process GPT
1139    vmm_set_cow( process );
1140 
1141#if( DEBUG_PROCESS_MAKE_FORK & 1 )
1142cycle = (uint32_t)hal_get_cycles();
1143if( DEBUG_PROCESS_MAKE_FORK < cycle )
1144printk("\n[DBG] %s : thread %x set COW in parent and child / cycle %d\n",
1145__FUNCTION__ , CURRENT_THREAD, cycle );
1146#endif
1147
1148    // get extended pointers on parent children_root, children_lock and children_nr
1149    xptr_t children_root_xp = XPTR( parent_process_cxy , &parent_process_ptr->children_root );
1150    xptr_t children_lock_xp = XPTR( parent_process_cxy , &parent_process_ptr->children_lock );
1151    xptr_t children_nr_xp   = XPTR( parent_process_cxy , &parent_process_ptr->children_nr   );
1152
1153    // register process in parent children list
1154    remote_spinlock_lock( children_lock_xp );
1155        xlist_add_last( children_root_xp , XPTR( local_cxy , &process->children_list ) );
1156        hal_remote_atomic_add( children_nr_xp , 1 );
1157    remote_spinlock_unlock( children_lock_xp );
1158
1159    // return success
1160    *child_thread = thread;
1161    *child_pid    = new_pid;
1162
1163#if DEBUG_PROCESS_MAKE_FORK
1164cycle = (uint32_t)hal_get_cycles();
1165if( DEBUG_PROCESS_MAKE_FORK < cycle )
1166printk("\n[DBG] %s : thread %x exit / cycle %d\n",
1167__FUNCTION__, CURRENT_THREAD, cycle );
1168#endif
1169
1170    return 0;
1171
1172}   // end process_make_fork()
1173
1174
1175/////////////////////////////////////////////////////
1176error_t process_make_exec( exec_info_t  * exec_info )
1177{
1178    char           * path;                    // pathname to .elf file
1179    pid_t            pid;                     // old_process PID / given to new_process
1180    pid_t            temp_pid;                // temporary PID / given to old_process
1181    process_t      * old_process;             // local pointer on old process
1182    thread_t       * old_thread;              // local pointer on old thread
1183    process_t      * new_process;             // local pointer on new process
1184    thread_t       * new_thread;              // local pointer on new thread
1185    xptr_t           parent_xp;               // extended pointer on parent process
1186    pthread_attr_t   attr;                    // new thread attributes
1187    lid_t            lid;                     // selected core local index
1188        error_t          error;
1189
1190    // get old_thread / old_process / PID / parent_xp
1191    old_thread  = CURRENT_THREAD;
1192    old_process = old_thread->process;
1193    pid         = old_process->pid;
1194    parent_xp   = old_process->parent_xp;
1195   
1196        // get .elf pathname from exec_info
1197        path     = exec_info->path;
1198
1199    // this function must be executed by a thread running in owner cluster
1200    assert( (CXY_FROM_PID( pid ) == local_cxy), __FUNCTION__,
1201    "local_cluster must be owner_cluster\n" );
1202
1203    assert( (LTID_FROM_TRDID( old_thread->trdid ) == 0) , __FUNCTION__,
1204    "must be called by the main thread\n" );
1205 
1206#if DEBUG_PROCESS_MAKE_EXEC
1207uint32_t cycle = (uint32_t)hal_get_cycles();
1208if( DEBUG_PROCESS_MAKE_EXEC < cycle )
1209printk("\n[DBG] %s : thread %x enters for process %x / %s / cycle %d\n",
1210__FUNCTION__, old_thread, pid, path, cycle );
1211#endif
1212
1213     // allocate memory for new_process descriptor
1214    new_process = process_alloc();
1215
1216    if( new_process == NULL )
1217    {
1218        printk("\n[ERROR] in %s : cannot allocate process descriptor in cluster %x\n",
1219        __FUNCTION__ , local_cxy );
1220        return -1;
1221    }
1222
1223    // get a temporary PID for old_process
1224    error = cluster_pid_alloc( old_process , &temp_pid );
1225    if( error ) 
1226    {
1227        printk("\n[ERROR] in %s : cannot get PID in cluster %x\n", 
1228        __FUNCTION__ , local_cxy ); 
1229        process_free( new_process );
1230        return -1;
1231    }
1232
1233    // set temporary PID to old_process
1234    old_process->pid = temp_pid;
1235
1236    // initialize new process descriptor
1237    process_reference_init( new_process,
1238                            pid,
1239                            parent_xp,                          // parent_process_xp
1240                            XPTR(local_cxy , old_process) );    // model_process
1241
1242    // give TXT ownership to new_process
1243    process_txt_set_ownership( XPTR( local_cxy , new_process) );
1244
1245#if( DEBUG_PROCESS_MAKE_EXEC & 1 )
1246cycle = (uint32_t)hal_get_cycles();
1247if( DEBUG_PROCESS_MAKE_EXEC < cycle )
1248printk("\n[DBG] %s : thread %x created new process %x / cycle %d \n",
1249__FUNCTION__ , old_thread , new_process , cycle );
1250#endif
1251
1252    // register code & data vsegs as well as entry-point in new process VMM,
1253    // and register extended pointer on .elf file in process descriptor
1254        if( elf_load_process( path , new_process ) )
1255        {
1256                printk("\n[ERROR] in %s : failed to access .elf file for path %s\n",
1257                __FUNCTION__ , path );
1258        process_destroy( new_process );
1259        return -1;
1260        }
1261
1262#if( DEBUG_PROCESS_MAKE_EXEC & 1 )
1263cycle = (uint32_t)hal_get_cycles();
1264if( DEBUG_PROCESS_MAKE_EXEC < cycle )
1265printk("\n[DBG] %s : thread %x registered code/data vsegs in new process %x / cycle %d\n",
1266__FUNCTION__, old_thread , new_process->pid , cycle );
1267#endif
1268
1269    // select a core in local cluster to execute the main thread
1270    lid  = cluster_select_local_core();
1271
1272    // initialize pthread attributes for main thread
1273    attr.attributes = PT_ATTR_DETACH | PT_ATTR_CLUSTER_DEFINED | PT_ATTR_CORE_DEFINED;
1274    attr.cxy        = local_cxy;
1275    attr.lid        = lid;
1276
1277    // create and initialize main thread in local cluster
1278        error = thread_user_create( pid,
1279                                (void *)new_process->vmm.entry_point,
1280                                exec_info->args_pointers,
1281                                &attr,
1282                                &new_thread );
1283        if( error )
1284        {
1285                printk("\n[ERROR] in %s : cannot create thread for process %x\n",
1286            __FUNCTION__ , new_process );
1287        process_destroy( new_process );
1288        return -1;
1289        }
1290
1291    // check main thread LTID
1292    assert( (LTID_FROM_TRDID(new_thread->trdid) == 0) , __FUNCTION__ ,
1293    "main thread must have LTID == 0\n" );
1294
1295#if( DEBUG_PROCESS_MAKE_EXEC & 1 )
1296cycle = (uint32_t)hal_get_cycles();
1297if( 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 DEBUG_PROCESS_MAKE_EXEC
1330cycle = (uint32_t)hal_get_cycles();
1331if( 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 DEBUG_PROCESS_ZERO_CREATE
1345uint32_t cycle = (uint32_t)hal_get_cycles();
1346if( 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 DEBUG_PROCESS_ZERO_CREATE
1373cycle = (uint32_t)hal_get_cycles();
1374if( 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 DEBUG_PROCESS_INIT_CREATE
1391uint32_t cycle = (uint32_t)hal_get_cycles();
1392if( 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 DEBUG_PROCESS_INIT_CREATE
1471cycle = (uint32_t)hal_get_cycles();
1472if( 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 DEBUG_PROCESS_TXT_ATTACH
1608uint32_t cycle = (uint32_t)hal_get_cycles();
1609if( 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 DEBUG_PROCESS_TXT_ATTACH
1637cycle = (uint32_t)hal_get_cycles();
1638if( 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 DEBUG_PROCESS_TXT_ATTACH
1667uint32_t cycle = (uint32_t)hal_get_cycles();
1668if( 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( DEBUG_PROCESS_TXT_ATTACH & 1 )
1693if( 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 DEBUG_PROCESS_TXT_ATTACH
1709cycle = (uint32_t)hal_get_cycles();
1710if( 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 DEBUG_PROCESS_TXT_ATTACH
1740uint32_t cycle = (uint32_t)hal_get_cycles();
1741if( 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 DEBUG_PROCESS_TXT_ATTACH
1758cycle = (uint32_t)hal_get_cycles();
1759if( 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 DEBUG_PROCESS_TXT_ATTACH
1797uint32_t cycle = (uint32_t)hal_get_cycles();
1798if( 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( DEBUG_PROCESS_TXT_ATTACH & 1 )
1816if( 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( DEBUG_PROCESS_TXT_ATTACH & 1 )
1835if( 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 DEBUG_PROCESS_TXT_ATTACH
1854cycle = (uint32_t)hal_get_cycles();
1855if( 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( DEBUG_PROCESS_TXT_ATTACH & 1 )
1876if( 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 DEBUG_PROCESS_TXT_ATTACH
1896cycle = (uint32_t)hal_get_cycles();
1897if( 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 DEBUG_PROCESS_TXT_ATTACH
1913cycle = (uint32_t)hal_get_cycles();
1914if( 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 DEBUG_PROCESS_TXT_ATTACH
1925cycle = (uint32_t)hal_get_cycles();
1926if( 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.