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

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

blip

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