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

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

Fix bugs in exec

File size: 48.0 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)
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 <list.h>
42#include <string.h>
43#include <scheduler.h>
44#include <remote_spinlock.h>
45#include <dqdt.h>
46#include <cluster.h>
47#include <ppm.h>
48#include <boot_info.h>
49#include <process.h>
50#include <elf.h>
51#include <syscalls.h>
52#include <signal.h>
53
54//////////////////////////////////////////////////////////////////////////////////////////
55// Extern global variables
56//////////////////////////////////////////////////////////////////////////////////////////
57
58extern process_t process_zero;
59
60//////////////////////////////////////////////////////////////////////////////////////////
61// Process initialisation related functions
62//////////////////////////////////////////////////////////////////////////////////////////
63
64///////////////////////////
65process_t * process_alloc()
66{
67        kmem_req_t   req;
68
69    req.type  = KMEM_PROCESS;
70        req.size  = sizeof(process_t);
71        req.flags = AF_KERNEL;
72
73    return (process_t *)kmem_alloc( &req );
74}
75
76////////////////////////////////////////
77void process_free( process_t * process )
78{
79    kmem_req_t  req;
80
81        req.type = KMEM_PROCESS;
82        req.ptr  = process;
83        kmem_free( &req );
84}
85
86/////////////////////////////////////////////
87void process_zero_init( process_t * process )
88{
89    // initialize PID, PPID anf PREF
90    process->pid    = 0;
91    process->ppid   = 0;
92    process->ref_xp = XPTR( local_cxy , process );
93
94    // reset th_tbl[] array as empty
95    uint32_t i;
96    for( i = 0 ; i < CONFIG_THREAD_MAX_PER_CLUSTER ; i++ )
97        {
98        process->th_tbl[i] = NULL;
99    }
100    process->th_nr  = 0;
101    spinlock_init( &process->th_lock );
102
103        hal_fence();
104
105process_dmsg("\n[DBG] %s : core[%x,%d] exit for process %x\n",
106__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , process->pid );
107
108}  // end process_zero_init()
109
110/////////////////////////////////////////////////
111void process_reference_init( process_t * process,
112                             pid_t       pid,
113                             pid_t       ppid,
114                             xptr_t      model_xp )
115{
116    cxy_t       model_cxy;
117    process_t * model_ptr;
118        error_t     error1;
119        error_t     error2;
120        error_t     error3;
121    xptr_t      stdin_xp;
122    xptr_t      stdout_xp;
123    xptr_t      stderr_xp;
124    uint32_t    stdin_id;
125    uint32_t    stdout_id;
126    uint32_t    stderr_id;
127
128process_dmsg("\n[DBG] %s : core[%x,%d] enters for process %x / ppid = %x\n",
129__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , pid , ppid );
130
131    // get model process cluster and local pointer
132    model_cxy = GET_CXY( model_xp );
133    model_ptr = (process_t *)GET_PTR( model_xp );
134
135    // initialize PID, PPID, and REF
136        process->pid    = pid;
137    process->ppid   = ppid;
138    process->ref_xp = XPTR( local_cxy , process );
139
140    // initialize vmm as empty
141    vmm_init( process );
142
143process_dmsg("\n[DBG] %s : core[%x,%d] / vmm empty for process %x\n", 
144__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , pid );
145
146    // initialize fd_array as empty
147    process_fd_init( process );
148
149    // create stdin / stdout / stderr pseudo-files
150    if( ppid == 0 )                                       // process_init
151    {
152        error1 = vfs_open( process,
153                           CONFIG_INIT_STDIN,
154                           O_RDONLY, 
155                           0,                // FIXME chmod
156                           &stdin_xp, 
157                           &stdin_id );
158
159        error2 = vfs_open( process,
160                           CONFIG_INIT_STDOUT,
161                           O_WRONLY, 
162                           0,                // FIXME chmod
163                           &stdout_xp, 
164                           &stdout_id );
165
166        error3 = vfs_open( process,
167                           CONFIG_INIT_STDERR,
168                           O_WRONLY, 
169                           0,                // FIXME chmod
170                           &stderr_xp, 
171                           &stderr_id );
172    }
173    else                                                  // any other process
174    {
175        error1 = vfs_open( process,
176                           CONFIG_USER_STDIN,
177                           O_RDONLY, 
178                           0,                // FIXME chmod
179                           &stdin_xp, 
180                           &stdin_id );
181
182        error2 = vfs_open( process,
183                           CONFIG_USER_STDOUT,
184                           O_WRONLY, 
185                           0,                // FIXME chmod
186                           &stdout_xp, 
187                           &stdout_id );
188
189        error3 = vfs_open( process,
190                           CONFIG_USER_STDERR,
191                           O_WRONLY, 
192                           0,                // FIXME chmod
193                           &stderr_xp, 
194                           &stderr_id );
195    }
196
197    assert( ((error1 == 0) && (error2 == 0) && (error3 == 0)) , __FUNCTION__ ,
198    "cannot open stdin/stdout/stderr pseudo files\n");
199
200    assert( ((stdin_id == 0) && (stdout_id == 1) && (stderr_id == 2)) , __FUNCTION__ ,
201    "bad indexes : stdin %d / stdout %d / stderr %d \n", stdin_id , stdout_id , stderr_id );
202
203    // initialize specific inodes root and cwd
204    process->vfs_root_xp = (xptr_t)hal_remote_lwd( XPTR( model_cxy,
205                                                         &model_ptr->vfs_root_xp ) );
206    process->vfs_cwd_xp  = (xptr_t)hal_remote_lwd( XPTR( model_cxy,
207                                                         &model_ptr->vfs_cwd_xp ) );
208    vfs_inode_remote_up( process->vfs_root_xp );
209    vfs_inode_remote_up( process->vfs_cwd_xp );
210
211    remote_rwlock_init( XPTR( local_cxy , &process->cwd_lock ) );
212
213    // copy all open file descriptors (other than stdin / stdout / stderr)
214    process_fd_remote_copy( XPTR( local_cxy , &process->fd_array ),
215                            XPTR( model_cxy , &model_ptr->fd_array ) );
216
217process_dmsg("\n[DBG] %s : core[%x,%d] / fd array for process %x\n", 
218__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , pid );
219
220    // reset children list root
221    xlist_root_init( XPTR( local_cxy , &process->children_root ) );
222    process->children_nr     = 0;
223
224    // reset semaphore / mutex / barrier / condvar list roots
225    xlist_root_init( XPTR( local_cxy , &process->sem_root ) );
226    xlist_root_init( XPTR( local_cxy , &process->mutex_root ) );
227    xlist_root_init( XPTR( local_cxy , &process->barrier_root ) );
228    xlist_root_init( XPTR( local_cxy , &process->condvar_root ) );
229    remote_spinlock_init( XPTR( local_cxy , &process->sync_lock ) );
230
231    // register new process in the local cluster manager pref_tbl[]
232    lpid_t lpid = LPID_FROM_PID( pid );
233    LOCAL_CLUSTER->pmgr.pref_tbl[lpid] = XPTR( local_cxy , process );
234
235    // register new process descriptor in local cluster manager local_list
236    cluster_process_local_link( process );
237
238    // register new process descriptor in local cluster manager copies_list
239    cluster_process_copies_link( process );
240
241    // reset th_tbl[] array as empty in process descriptor
242    uint32_t i;
243    for( i = 0 ; i < CONFIG_THREAD_MAX_PER_CLUSTER ; i++ )
244        {
245        process->th_tbl[i] = NULL;
246    }
247    process->th_nr  = 0;
248    spinlock_init( &process->th_lock );
249
250        hal_fence();
251
252process_dmsg("\n[DBG] %s : core[%x,%d] exit for process %x\n",
253__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , pid );
254
255}  // process_reference init()
256
257/////////////////////////////////////////////////////
258error_t process_copy_init( process_t * local_process,
259                           xptr_t      reference_process_xp )
260{
261    // get reference process cluster and local pointer
262    cxy_t       ref_cxy = GET_CXY( reference_process_xp );
263    process_t * ref_ptr = (process_t *)GET_PTR( reference_process_xp );
264
265    // set the pid, ppid, ref_xp fields in local process
266    local_process->pid    = hal_remote_lw( XPTR( ref_cxy , &ref_ptr->pid ) );
267    local_process->ppid   = hal_remote_lw( XPTR( ref_cxy , &ref_ptr->ppid ) );
268    local_process->ref_xp = reference_process_xp;
269
270process_dmsg("\n[DBG] %s : core[%x,%d] enters for process %x in cluster %x\n",
271__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , local_process->pid );
272
273    // reset local process vmm
274    vmm_init( local_process );
275
276    // reset process file descriptors array
277        process_fd_init( local_process );
278
279    // reset vfs_root_xp / vfs_bin_xp / vfs_cwd_xp fields
280    local_process->vfs_root_xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->vfs_root_xp ) );
281    local_process->vfs_bin_xp  = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->vfs_bin_xp ) );
282    local_process->vfs_cwd_xp  = XPTR_NULL;
283
284    // reset children list root (not used in a process descriptor copy)
285    xlist_root_init( XPTR( local_cxy , &local_process->children_root ) );
286    local_process->children_nr   = 0;
287
288    // reset brothers list (not used in a process descriptor copy)
289    xlist_entry_init( XPTR( local_cxy , &local_process->brothers_list ) );
290
291    // reset semaphores list root (not used in a process descriptor copy)
292    xlist_root_init( XPTR( local_cxy , &local_process->sem_root ) );
293    xlist_root_init( XPTR( local_cxy , &local_process->mutex_root ) );
294    xlist_root_init( XPTR( local_cxy , &local_process->barrier_root ) );
295    xlist_root_init( XPTR( local_cxy , &local_process->condvar_root ) );
296
297    // reset th_tbl[] array as empty
298    uint32_t i;
299    for( i = 0 ; i < CONFIG_THREAD_MAX_PER_CLUSTER ; i++ )
300        {
301        local_process->th_tbl[i] = NULL;
302    }
303    local_process->th_nr  = 0;
304    spinlock_init( &local_process->th_lock );
305
306    // register new process descriptor in local cluster manager local_list
307    cluster_process_local_link( local_process );
308
309    // register new process descriptor in owner cluster manager copies_list
310    cluster_process_copies_link( local_process );
311
312    // initialize signal manager TODO [AG]
313
314        hal_fence();
315
316process_dmsg("\n[DBG] %s : core[%x,%d] exit for process %x in cluster %x\n",
317__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , local_process->pid );
318
319    return 0;
320
321} // end process_copy_init()
322
323///////////////////////////////////////////
324void process_destroy( process_t * process )
325{
326        if( process->th_nr != 0 )
327    {
328        panic("process %x in cluster %x has still active threads",
329              process->pid , local_cxy );
330    }
331
332    // get local process manager pointer
333    pmgr_t * pmgr = &LOCAL_CLUSTER->pmgr;
334
335    // get the lock protecting the list of local process descriptors
336    remote_spinlock_lock( XPTR( local_cxy , &pmgr->local_lock ) );
337
338    // remove the process descriptor from local_list in local cluster manager
339    xlist_unlink( XPTR( local_cxy , &process->local_list ) );
340
341    // release the lock protecting the list of local process descriptors
342    remote_spinlock_unlock( XPTR( local_cxy , &pmgr->local_lock ) );
343
344    // get extended pointer on copies_lock in owner cluster manager
345    cxy_t  owner_cxy    = CXY_FROM_PID( process->pid );
346        lpid_t lpid         = LPID_FROM_PID( process->pid );
347    xptr_t copies_lock  = XPTR( owner_cxy , &pmgr->copies_lock[lpid] );
348
349    // remove the local process descriptor from copies_list
350    remote_spinlock_lock( copies_lock );
351    xlist_unlink( XPTR( local_cxy , &process->copies_list ) );
352    remote_spinlock_unlock( copies_lock );
353
354        hal_fence();
355
356    // From this point, the process descriptor is unreachable
357
358    // FIXME close all open files and update dirty [AG]
359
360    // Decrease refcount for bin file, root file and cwd file
361        if( process->vfs_bin_xp  != XPTR_NULL ) vfs_file_count_down( process->vfs_bin_xp );
362        if( process->vfs_root_xp != XPTR_NULL ) vfs_file_count_down( process->vfs_root_xp );
363        if( process->vfs_cwd_xp  != XPTR_NULL ) vfs_file_count_down( process->vfs_cwd_xp );
364
365    // Destroy VMM
366    vmm_destroy( process );
367
368        process_dmsg("\n[DBG] %s for pid %d / page_faults = %d\n",
369                 __FUNCTION__ , process->pid, process->vmm.pgfault_nr );
370
371}  // end process_destroy()
372
373/////////////////////////////////////////////////
374char * process_action_str( uint32_t action_type )
375{
376    if     ( action_type == BLOCK_ALL_THREADS   ) return "BLOCK";
377    else if( action_type == UNBLOCK_ALL_THREADS ) return "UNBLOCK";
378    else if( action_type == DELETE_ALL_THREADS  ) return "DELETE";
379    else                                          return "undefined";
380}
381
382////////////////////////////////////////////
383void process_sigaction( process_t * process,
384                        uint32_t    action_type )
385{
386    cxy_t              owner_cxy;         // owner cluster identifier
387    lpid_t             lpid;              // process index in owner cluster
388    cluster_t        * cluster;           // pointer on cluster manager
389    xptr_t             root_xp;           // extended pointer on root of copies
390    xptr_t             lock_xp;           // extended pointer on lock protecting copies
391    xptr_t             client_xp;         // extended pointer on client thread
392    uint32_t           rsp_count;         // number of expected responses
393    xptr_t             rsp_xp;            // extended pointer on responses counter
394    xptr_t             iter_xp;           // iterator on copies list
395    xptr_t             process_xp;        // extended pointer on process copy
396    cxy_t              process_cxy;       // process copy cluster identifier
397    process_t        * process_ptr;       // local pointer on process copy
398
399signal_dmsg("\n[DBG] %s : enter for signal %s to process %x in cluster %x\n",
400__FUNCTION__ , process_action_str( action_type ) , process , local_cxy );
401
402    thread_t         * this = CURRENT_THREAD;
403
404    // get extended pointer on client thread and response counter
405    client_xp = XPTR( local_cxy , this );
406    rsp_xp    = XPTR( local_cxy , &rsp_count );
407
408    // get owner cluster identifier and process lpid
409    owner_cxy = CXY_FROM_PID( process->pid );
410    lpid      = LPID_FROM_PID( process->pid );
411
412    assert( (owner_cxy == local_cxy) , __FUNCTION__ , "illegal cluster\n" ); 
413   
414    // get local pointer on local cluster manager
415    cluster = LOCAL_CLUSTER;
416
417    // get extended pointers on copies root, copies lock, and number of copies
418    root_xp   = XPTR( local_cxy , &cluster->pmgr.copies_root[lpid] );
419    lock_xp   = XPTR( local_cxy , &cluster->pmgr.copies_lock[lpid] );
420
421    // initialize responses number
422    rsp_count = cluster->pmgr.copies_nr[lpid];
423
424    // take the lock protecting the copies
425    remote_spinlock_lock( lock_xp );
426
427    // send RPCs to all process copies
428    XLIST_FOREACH( root_xp , iter_xp )
429    {
430        process_xp  = XLIST_ELEMENT( iter_xp , process_t , copies_list );
431        process_cxy = GET_CXY( process_xp );
432        process_ptr = (process_t *)GET_PTR( process_xp );
433
434printk("\n    @@@ %s : process = %x / pid = %x / ppid = %x\n",
435__FUNCTION__ , process_ptr , process_ptr->pid , process_ptr->ppid );
436
437        rpc_process_sigaction_client( process_cxy, 
438                                      process_ptr,
439                                      action_type,
440                                      rsp_xp,
441                                      client_xp );
442    }
443   
444    // release the lock protecting process copies
445    remote_spinlock_unlock( lock_xp );
446
447    // block and deschedule to wait response
448    thread_block( CURRENT_THREAD , THREAD_BLOCKED_RPC );
449    sched_yield("BLOCKED on RPC");
450
451signal_dmsg("\n[DBG] %s : exit for signal %s to process %x in cluster %x\n",
452__FUNCTION__ , process_action_str( action_type ) , process , local_cxy );
453
454}  // end process_sigaction()
455
456////////////////////////////////////////
457void process_block( process_t * process,
458                    xptr_t      rsp_xp,
459                    xptr_t      client_xp )
460{
461    thread_t          * target;         // pointer on target thread
462    uint32_t            ltid;           // index in process th_tbl
463    thread_t          * killer;         // killer thread pointer
464    uint32_t            count;          // requests counter
465    volatile uint32_t   sig_rsp_count;  // responses counter
466    cxy_t               client_cxy;     // client thread cluster identifier
467    thread_t          * client_ptr;     // client thread pointer
468    core_t            * client_core;    // client thread core pointer
469
470    // get local killer thread pointer
471    killer = CURRENT_THREAD;
472
473signal_dmsg("\n[DBG] %s : enter for process %x in cluster %x\n",
474__FUNCTION__ , process->pid , local_cxy );
475
476    // get lock protecting process th_tbl[]
477    spinlock_lock( &process->th_lock );
478
479    // initialize local responses counter
480    sig_rsp_count = process->th_nr;
481
482    // loop on process threads to block and deschedule all threads in cluster
483    // we use both "ltid" and "count" because it can exist "holes" in th_tbl
484    for( ltid = 0 , count = 0 ; count < process->th_nr ; ltid++ )
485    {
486        target = process->th_tbl[ltid];
487
488        if( target != NULL )             // thread found
489        {
490            count++;
491
492            // set signal in target thread descriptor
493            thread_set_signal( target , (uint32_t *)sig_rsp_count );
494
495            // set the global blocked bit in target thread descriptor.
496            thread_block( target , THREAD_BLOCKED_GLOBAL );
497
498            // - if the killer thread and the target thread are not on the same core
499            //   we want the scheduler of target thread to acknowlege the signal
500            //   to be sure that the target thread is descheduled
501            // - if the killer thread and the target thread are on the same core
502            //   we simply decrement the response counter.
503            if( killer->core->lid != target->core->lid )
504            {
505                dev_pic_send_ipi( local_cxy , target->core->lid );
506            }
507            else                                                         
508            {
509                hal_atomic_add( (void *)&sig_rsp_count , -1 );
510            }
511        }
512    }
513
514    // poll the reponses counter
515    while( 1 )
516    {
517        // exit loop when all responses received
518        if ( sig_rsp_count == 0 ) break;
519   
520        // wait 1000 cycles before retry
521        hal_fixed_delay( 1000 );
522    }
523
524    // acknowledge client thread & unblock client thread if last response
525    client_cxy  = GET_CXY( client_xp );
526    client_ptr  = (thread_t *)GET_PTR( client_xp );
527    client_core = (core_t *)hal_remote_lpt( XPTR( client_cxy , &client_ptr->core ) );
528    if( hal_remote_atomic_add( rsp_xp , -1 ) == 1 ) 
529    {
530        thread_unblock( client_xp , THREAD_BLOCKED_RPC);
531        dev_pic_send_ipi( client_cxy , client_core->lid );
532    }
533
534signal_dmsg("\n[DBG] %s : exit for process %x in cluster %x / %d threads blocked\n",
535__FUNCTION__ , process->pid , local_cxy , count );
536
537}  // end process_block()
538
539//////////////////////////////////////////
540void process_unblock( process_t * process,
541                      xptr_t      rsp_xp,
542                      xptr_t      client_xp )
543{
544    thread_t          * target;        // pointer on target thead
545    uint32_t            ltid;          // index in process th_tbl
546    thread_t          * killer;        // killer thread pointer
547    uint32_t            req_count;     // requests counter
548    cxy_t               client_cxy;    // client thread cluster identifier
549    thread_t          * client_ptr;    // client thread pointer
550    core_t            * client_core;   // client thread core pointer
551
552    // get local killer thread pointer
553    killer = CURRENT_THREAD;
554
555signal_dmsg("\n[DBG] %s : enter for process %x in cluster %x\n",
556__FUNCTION__ , process->pid , local_cxy );
557
558    // get lock protecting process th_tbl[]
559    spinlock_lock( &process->th_lock );
560
561    // loop on process threads to unblock all threads in cluster
562    // we use both "ltid" and "req_count" because it can exist "holes" in th_tbl
563    for( ltid = 0 , req_count = 0 ;
564         req_count < process->th_nr ;
565         ltid++ )
566    {
567        target = process->th_tbl[ltid];
568
569        if( target != NULL )             // thread found
570        {
571            req_count++;
572
573            // reset the global blocked bit in target thread descriptor.
574            thread_unblock( XPTR( local_cxy , target ) , THREAD_BLOCKED_GLOBAL );
575        }
576    }
577
578    // acknowledge client thread & unblock client thread if last response
579    client_cxy  = GET_CXY( client_xp );
580    client_ptr  = (thread_t *)GET_PTR( client_xp );
581    client_core = (core_t *)hal_remote_lpt( XPTR( client_cxy , &client_ptr->core ) );
582    if( hal_remote_atomic_add( rsp_xp , -1 ) == 1 ) 
583    {
584        thread_unblock( client_xp , THREAD_BLOCKED_RPC);
585        dev_pic_send_ipi( client_cxy , client_core->lid );
586    }
587
588signal_dmsg("\n[DBG] %s : exit for process %x in cluster %x / %d threads blocked\n",
589__FUNCTION__ , process->pid , local_cxy , req_count );
590
591}  // end process_unblock()
592
593/////////////////////////////////////////
594void process_delete( process_t * process,
595                     xptr_t      rsp_xp,
596                     xptr_t      client_xp )
597{
598    thread_t          * thread;        // pointer on target thread
599    uint32_t            ltid;          // index in process th_tbl
600    uint32_t            count;         // request counter
601    pid_t               pid;           // process PID
602    cxy_t               client_cxy;    // client thread cluster identifier
603    thread_t          * client_ptr;    // client thread pointer
604    core_t            * client_core;   // client thread core pointer
605
606    // get process PID
607    pid = process->pid;
608
609signal_dmsg("\n[DBG] %s : enter for process %x in cluster %x at cycle %d\n",
610__FUNCTION__ , pid , local_cxy , (uint32_t)hal_get_cycles() );
611
612    // loop on threads to release memory allocated to threads
613    for( ltid = 0 , count = 0  ; count < process->th_nr ; ltid++ )
614    {
615        thread = process->th_tbl[ltid];
616
617        if( thread != NULL )             // thread found
618        {
619            count++;
620
621            // detach thread from parent if attached
622            if( (thread->flags & THREAD_FLAG_DETACHED) == 0 ) 
623            thread_child_parent_unlink( thread->parent , XPTR( local_cxy , thread ) );
624
625            // detach thread from process
626            process_remove_thread( thread );
627
628            // remove thread from scheduler
629            sched_remove_thread( thread );
630
631            // release memory allocated to thread
632            thread_destroy( thread );
633        }
634    }
635
636    // release memory allocated to process descriptors
637    // for all clusters other than the owner cluster
638    if( local_cxy != CXY_FROM_PID( process->pid ) ) process_destroy( process );
639
640    // acknowledge client thread & unblock client thread if last response
641    client_cxy  = GET_CXY( client_xp );
642    client_ptr  = (thread_t *)GET_PTR( client_xp );
643    client_core = (core_t *)hal_remote_lpt( XPTR( client_cxy , &client_ptr->core ) );
644    if( hal_remote_atomic_add( rsp_xp , -1 ) == 1 ) 
645    {
646        thread_unblock( client_xp , THREAD_BLOCKED_RPC);
647        dev_pic_send_ipi( client_cxy , client_core->lid );
648    }
649
650signal_dmsg("\n[DBG] %s : exit for process %x in cluster %x at cycle %d\n",
651__FUNCTION__ , pid , local_cxy , (uint32_t)hal_get_cycles() );
652
653}  // end process_delete()
654
655///////////////////////////////////////////////
656process_t * process_get_local_copy( pid_t pid )
657{
658    error_t        error;
659    process_t    * process_ptr;   // local pointer on process
660    xptr_t         process_xp;    // extended pointer on process
661
662    cluster_t * cluster = LOCAL_CLUSTER;
663
664    // get lock protecting local list of processes
665    remote_spinlock_lock( XPTR( local_cxy , &cluster->pmgr.local_lock ) );
666
667    // scan the local list of process descriptors to find the process
668    xptr_t  iter;
669    bool_t  found = false;
670    XLIST_FOREACH( XPTR( local_cxy , &cluster->pmgr.local_root ) , iter )
671    {
672        process_xp  = XLIST_ELEMENT( iter , process_t , local_list );
673        process_ptr = (process_t *)GET_PTR( process_xp );
674        if( process_ptr->pid == pid )
675        {
676            found = true;
677            break;
678        }
679    }
680
681    // release lock protecting local list of processes
682    remote_spinlock_unlock( XPTR( local_cxy , &cluster->pmgr.local_lock ) );
683
684    // allocate memory for a new local process descriptor
685    // and initialise it from reference cluster if required
686    if( !found )
687    {
688        // get extended pointer on reference process descriptor
689        xptr_t ref_xp = cluster_get_reference_process_from_pid( pid );
690
691        assert( (ref_xp != XPTR_NULL) , __FUNCTION__ , "illegal pid\n" );
692
693        // allocate memory for local process descriptor
694        process_ptr = process_alloc();
695        if( process_ptr == NULL )  return NULL;
696
697        // initialize local process descriptor copy
698        error = process_copy_init( process_ptr , ref_xp );
699        if( error ) return NULL;
700    }
701
702    return process_ptr;
703
704}  // end process_get_local_copy()
705
706//////////////////////////////////////////////////////////////////////////////////////////
707// File descriptor array related functions
708//////////////////////////////////////////////////////////////////////////////////////////
709
710///////////////////////////////////////////
711void process_fd_init( process_t * process )
712{
713    uint32_t fd;
714
715    remote_spinlock_init( XPTR( local_cxy , &process->fd_array.lock ) );
716
717    process->fd_array.current = 0;
718
719    // initialize array
720    for ( fd = 0 ; fd < CONFIG_PROCESS_FILE_MAX_NR ; fd++ )
721    {
722        process->fd_array.array[fd] = XPTR_NULL;
723    }
724}
725
726//////////////////////////////
727bool_t process_fd_array_full()
728{
729    // get extended pointer on reference process
730    xptr_t ref_xp = CURRENT_THREAD->process->ref_xp;
731
732    // get reference process cluster and local pointer
733    process_t * ref_ptr = (process_t *)GET_PTR( ref_xp );
734    cxy_t       ref_cxy = GET_CXY( ref_xp );
735
736    // get number of open file descriptors from reference fd_array
737    uint32_t current = hal_remote_lw( XPTR( ref_cxy , &ref_ptr->fd_array.current ) );
738
739        return ( current >= CONFIG_PROCESS_FILE_MAX_NR );
740}
741
742/////////////////////////////////////////////////
743error_t process_fd_register( process_t * process,
744                             xptr_t      file_xp,
745                             uint32_t  * fdid )
746{
747    bool_t    found;
748    uint32_t  id;
749    xptr_t    xp;
750
751    // get reference process cluster and local pointer
752    xptr_t ref_xp = process->ref_xp;
753    process_t * ref_ptr = (process_t *)GET_PTR( ref_xp );
754    cxy_t       ref_cxy = GET_CXY( ref_xp );
755
756    // take lock protecting reference fd_array
757        remote_spinlock_lock( XPTR( ref_cxy , &ref_ptr->fd_array.lock ) );
758
759    found   = false;
760
761    for ( id = 0; id < CONFIG_PROCESS_FILE_MAX_NR ; id++ )
762    {
763        xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->fd_array.array[id] ) );
764        if ( xp == XPTR_NULL )
765        {
766            found = true;
767            hal_remote_swd( XPTR( ref_cxy , &ref_ptr->fd_array.array[id] ) , file_xp );
768                hal_remote_atomic_add( XPTR( ref_cxy , &ref_ptr->fd_array.current ) , 1 );
769                        *fdid = id;
770            break;
771        }
772    }
773
774    // release lock protecting reference fd_array
775        remote_spinlock_unlock( XPTR( ref_cxy , &ref_ptr->fd_array.lock ) );
776
777    if ( !found ) return EMFILE;
778    else          return 0;
779}
780
781////////////////////////////////////////////////
782xptr_t process_fd_get_xptr( process_t * process,
783                            uint32_t    fdid )
784{
785    xptr_t  file_xp;
786
787    // access local copy of process descriptor
788    file_xp = process->fd_array.array[fdid];
789
790    if( file_xp == XPTR_NULL )
791    {
792        // get reference process cluster and local pointer
793        xptr_t      ref_xp  = process->ref_xp;
794        cxy_t       ref_cxy = GET_CXY( ref_xp );
795        process_t * ref_ptr = (process_t *)GET_PTR( ref_xp );
796
797        // access reference process descriptor
798        file_xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->fd_array.array[fdid] ) );
799
800        // update local fd_array if found
801        if( file_xp != XPTR_NULL )
802        {
803            process->fd_array.array[fdid] = file_xp;
804        }
805    }
806
807    return file_xp;
808
809}  // end process_fd_get_xptr()
810
811///////////////////////////////////////////
812void process_fd_remote_copy( xptr_t dst_xp,
813                             xptr_t src_xp )
814{
815    uint32_t fd;
816    xptr_t   entry;
817
818    // get cluster and local pointer for src fd_array
819    cxy_t        src_cxy = GET_CXY( src_xp );
820    fd_array_t * src_ptr = (fd_array_t *)GET_PTR( src_xp );
821
822    // get cluster and local pointer for dst fd_array
823    cxy_t        dst_cxy = GET_CXY( dst_xp );
824    fd_array_t * dst_ptr = (fd_array_t *)GET_PTR( dst_xp );
825
826    // get the remote lock protecting the src fd_array
827        remote_spinlock_lock( XPTR( src_cxy , &src_ptr->lock ) );
828
829    // loop on all entries other than
830    // the three first entries: stdin/stdout/stderr
831    for( fd = 3 ; fd < CONFIG_PROCESS_FILE_MAX_NR ; fd++ )
832        {
833                entry = (xptr_t)hal_remote_lwd( XPTR( src_cxy , &src_ptr->array[fd] ) );
834
835                if( entry != XPTR_NULL )
836                {
837            // increment file descriptor ref count
838            vfs_file_count_up( entry );
839
840                        // copy entry in destination process fd_array
841                        hal_remote_swd( XPTR( dst_cxy , &dst_ptr->array[fd] ) , entry );
842                }
843        }
844
845    // release lock on source process fd_array
846        remote_spinlock_unlock( XPTR( src_cxy , &src_ptr->lock ) );
847
848}  // end process_fd_remote_copy()
849
850////////////////////////////////////////////////////////////////////////////////////
851//  Thread related functions
852////////////////////////////////////////////////////////////////////////////////////
853
854/////////////////////////////////////////////////////
855error_t process_register_thread( process_t * process,
856                                 thread_t  * thread,
857                                 trdid_t   * trdid )
858{
859    ltid_t   ltid;
860    bool_t   found;
861
862    assert( (process != NULL) , __FUNCTION__ , "process argument is NULL" );
863
864    assert( (thread != NULL) , __FUNCTION__ , "thread argument is NULL" );
865
866    // search a free slot in th_tbl[]
867    // 0 is not a valid ltid value
868    found = false;
869    for( ltid = 1 ; ltid < CONFIG_THREAD_MAX_PER_CLUSTER ; ltid++ )
870    {
871        if( process->th_tbl[ltid] == NULL )
872        {
873            found = true;
874            break;
875        }
876    }
877
878    if( found )
879    {
880        // register thread in th_tbl[]
881        process->th_tbl[ltid] = thread;
882        process->th_nr++;
883
884        // returns trdid
885        *trdid = TRDID( local_cxy , ltid );
886    }
887
888    return (found) ? 0 : ENOMEM;
889
890}  // end process_register_thread()
891
892///////////////////////////////////////////////
893void process_remove_thread( thread_t * thread )
894{
895    assert( (thread != NULL) , __FUNCTION__ , "thread argument is NULL" );
896
897    process_t * process = thread->process;
898
899    // get thread local index
900    ltid_t  ltid = LTID_FROM_TRDID( thread->trdid );
901
902    // remove thread from th_tbl[]
903    process->th_tbl[ltid] = NULL;
904    process->th_nr--;
905
906}  // process_remove_thread()
907
908/////////////////////////////////////////////////////////
909error_t process_make_fork( xptr_t      parent_process_xp,
910                           xptr_t      parent_thread_xp,
911                           pid_t     * child_pid,
912                           thread_t ** child_thread )
913{
914    process_t * process;         // local pointer on child process descriptor
915    thread_t  * thread;          // local pointer on child thread descriptor
916    pid_t       new_pid;         // process identifier for child process
917    pid_t       parent_pid;      // process identifier for parent process
918    xptr_t      ref_xp;          // extended pointer on reference process
919    error_t     error;
920
921    // get cluster and local pointer for parent process
922    cxy_t       parent_process_cxy = GET_CXY( parent_process_xp );
923    process_t * parent_process_ptr = (process_t *)GET_PTR( parent_process_xp );
924
925    // get parent process PID
926    parent_pid = hal_remote_lw( XPTR( parent_process_cxy , &parent_process_ptr->pid ) );
927   
928    // check parent process is the reference
929    ref_xp = hal_remote_lwd( XPTR( parent_process_cxy , &parent_process_ptr->ref_xp ) );
930    assert( (parent_process_xp == ref_xp ) , __FUNCTION__ ,
931    "parent process must be the reference process\n" );
932
933fork_dmsg("\n[DBG] %s : core[%x,%d] enter at cycle %d\n",
934__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid , (uint32_t)hal_get_cycles() );
935
936    // allocate a process descriptor
937    process = process_alloc();
938    if( process == NULL )
939    {
940        printk("\n[ERROR] in %s : cannot get process in cluster %x\n", 
941        __FUNCTION__, local_cxy ); 
942        return -1;
943    }
944
945fork_dmsg("\n[DBG] %s : core[%x,%d] child process descriptor allocated at cycle %d\n",
946 __FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, (uint32_t)hal_get_cycles() );
947
948    // allocate a child PID from local cluster
949    error = cluster_pid_alloc( XPTR( local_cxy , process ) , &new_pid );
950    if( (error != 0) || (new_pid == 0) )
951    {
952        printk("\n[ERROR] in %s : cannot get PID in cluster %x\n", 
953        __FUNCTION__, local_cxy ); 
954        process_free( process );
955        return -1;
956    }
957
958fork_dmsg("\n[DBG] %s : core[%x, %d] child process PID allocated = %x at cycle %d\n",
959 __FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, new_pid , (uint32_t)hal_get_cycles() );
960
961    // initializes child process descriptor from parent process descriptor
962    process_reference_init( process,
963                            new_pid,
964                            parent_pid,
965                            parent_process_xp );
966
967fork_dmsg("\n[DBG] %s : core[%x, %d] child process initialised at cycle %d\n",
968__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, hal_get_cycles() );
969
970    // copy VMM from parent descriptor to child descriptor
971    error = vmm_fork_copy( process,
972                           parent_process_xp );
973    if( error )
974    {
975        printk("\n[ERROR] in %s : cannot copy VMM in cluster %x\n", 
976        __FUNCTION__, local_cxy ); 
977        process_free( process );
978        cluster_pid_release( new_pid );
979        return -1;
980    }
981
982fork_dmsg("\n[DBG] %s : core[%x, %d] child process VMM copied at cycle %d\n",
983__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, (uint32_t)hal_get_cycles() );
984
985    // create child thread descriptor from parent thread descriptor
986    error = thread_user_fork( parent_thread_xp,
987                              process,
988                              &thread );
989    if( error )
990    {
991        printk("\n[ERROR] in %s : cannot create thread in cluster %x\n",
992        __FUNCTION__, local_cxy ); 
993        process_free( process );
994        cluster_pid_release( new_pid );
995        return -1;
996    }
997
998fork_dmsg("\n[DBG] %s : core[%x,%d] child thread created at cycle %d\n", 
999__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, (uint32_t)hal_get_cycles() );
1000
1001    // update parent process GPT to set Copy_On_Write for shared data vsegs
1002    // this includes all replicated GPT copies
1003    if( parent_process_cxy == local_cxy )   // reference is local
1004    {
1005        vmm_set_cow( parent_process_ptr );
1006    }
1007    else                                    // reference is remote
1008    {
1009        rpc_vmm_set_cow_client( parent_process_cxy,
1010                                parent_process_ptr );
1011    }
1012
1013fork_dmsg("\n[DBG] %s : core[%x,%d] COW set in parent_process at cycle %d\n",
1014__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, (uint32_t)hal_get_cycles() );
1015
1016    // update children list in parent process
1017        xlist_add_last( XPTR( parent_process_cxy , &parent_process_ptr->children_root ),
1018                    XPTR( local_cxy , &process->brothers_list ) );
1019        hal_remote_atomic_add( XPTR( parent_process_cxy,
1020                                 &parent_process_ptr->children_nr), 1 );
1021
1022// vmm_display( process , true );
1023// vmm_display( parent_process_ptr , true );
1024// sched_display( 0 );
1025
1026    // return success
1027    *child_thread = thread;
1028    *child_pid    = new_pid;
1029
1030fork_dmsg("\n[DBG] %s : core[%x,%d] exit at cycle %d\n",
1031__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, (uint32_t)hal_get_cycles() );
1032
1033    return 0;
1034
1035}  // end process_make_fork()
1036
1037/*  deprecated because we don't wand to destroy the existing process descriptor
1038
1039/////////////////////////////////////////////////////
1040error_t process_make_exec( exec_info_t  * exec_info )
1041{
1042    char           * path;                    // pathname to .elf file
1043    process_t      * old;                     // local pointer on old process
1044    process_t      * new;                     // local pointer on new process
1045    pid_t            pid;                     // old process identifier
1046    thread_t       * thread;                  // pointer on new thread
1047    pthread_attr_t   attr;                    // main thread attributes
1048    lid_t            lid;                     // selected core local index
1049        error_t          error;
1050
1051        // get .elf pathname and PID from exec_info
1052        path = exec_info->path;
1053    pid  = exec_info->pid;
1054
1055    // check local cluster is process owner
1056    assert( (CXY_FROM_PID( pid ) == local_cxy), __FUNCTION__,
1057    "local cluster %x is not owner for process %x\n", local_cxy, pid );
1058
1059exec_dmsg("\n[DBG] %s : core[%x,%d] enters for process %x / path = %s\n",
1060__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, pid , path );
1061
1062    // get old process local pointer
1063    old = (process_t *)cluster_get_local_process_from_pid( pid );
1064   
1065    assert( (old != NULL ) , __FUNCTION__ ,
1066    "process %x not found in cluster %x\n", pid , local_cxy );
1067
1068    // allocate memory for new process descriptor
1069    new = process_alloc();
1070
1071    // initialize new process descriptor
1072    process_reference_init( new,
1073                            old->pid,                   // same as old
1074                            old->ppid,                  // same as old
1075                            XPTR( local_cxy , old ) );
1076
1077exec_dmsg("\n[DBG] %s : core[%x,%d] created new process %x / path = %s\n",
1078__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, pid, path );
1079
1080    // register "code" and "data" vsegs as well as entry-point
1081    // in new process VMM, using information contained in the elf file.
1082        if( elf_load_process( path , new ) )
1083        {
1084                printk("\n[ERROR] in %s : failed to access .elf file for process %x / path = %s\n",
1085                __FUNCTION__, pid , path );
1086        process_destroy( new );
1087        return -1;
1088        }
1089
1090exec_dmsg("\n[DBG] %s : core[%x,%d] vsegs registered / path = %s\n",
1091__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, path );
1092
1093    // select a core in local cluster to execute the main thread
1094    lid  = cluster_select_local_core();
1095
1096    // initialize pthread attributes for main thread
1097    attr.attributes = PT_ATTR_DETACH | PT_ATTR_CLUSTER_DEFINED | PT_ATTR_CORE_DEFINED;
1098    attr.cxy        = local_cxy;
1099    attr.lid        = lid;
1100
1101    // create and initialize thread descriptor
1102        error = thread_user_create( pid,
1103                                (void *)new->vmm.entry_point,
1104                                exec_info->args_pointers,
1105                                &attr,
1106                                &thread );
1107        if( error )
1108        {
1109                printk("\n[ERROR] in %s : cannot create thread for process %x / path = %s\n",
1110                       __FUNCTION__, pid , path );
1111        process_destroy( new );
1112        return -1;
1113        }
1114
1115exec_dmsg("\n[DBG] %s : core[%x,%d] created main thread %x for new process %x\n",
1116__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, thread->trdid, pid );
1117
1118    // update children list (rooted in parent process)
1119        xlist_replace( XPTR( local_cxy , &old->brothers_list ) ,
1120                   XPTR( local_cxy , &new->brothers_list ) );
1121
1122    // request destruction of old process copies and threads in all clusters
1123    process_sigaction( old , SIGKILL );
1124
1125    // activate new thread
1126        thread_unblock( XPTR( local_cxy , thread ) , THREAD_BLOCKED_GLOBAL );
1127
1128exec_dmsg("\n[DBG] %s : core[%x,%d] exit for path = %s\n",
1129__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, path  );
1130
1131        return 0;
1132
1133}  // end process_make_exec()
1134
1135*/
1136
1137/////////////////////////////////////////////////////
1138error_t process_make_exec( exec_info_t  * exec_info )
1139{
1140    char           * path;                    // pathname to .elf file
1141    process_t      * process;                 // local pointer on old process
1142    pid_t            pid;                     // old process identifier
1143    thread_t       * thread;                  // pointer on new main thread
1144    pthread_attr_t   attr;                    // main thread attributes
1145    lid_t            lid;                     // selected core local index
1146        error_t          error;
1147
1148        // get .elf pathname and PID from exec_info
1149        path = exec_info->path;
1150    pid  = exec_info->pid;
1151
1152    // check local cluster is process owner
1153    assert( (CXY_FROM_PID( pid ) == local_cxy), __FUNCTION__,
1154    "local cluster %x is not owner for process %x\n", local_cxy, pid );
1155
1156exec_dmsg("\n[DBG] %s : core[%x,%d] enters for process %x / path = %s\n",
1157__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, pid , path );
1158
1159    // get process local pointer
1160    process = (process_t *)cluster_get_local_process_from_pid( pid );
1161   
1162    assert( (process != NULL ) , __FUNCTION__ , 
1163    "process %x not found in cluster %x\n", pid , local_cxy ); 
1164
1165    // reset the existing vmm
1166    vmm_destroy( process );
1167
1168exec_dmsg("\n[DBG] %s : core[%x,%d] VMM cleared\n",
1169__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid );
1170
1171    // block all existing process threads
1172    process_sigaction( process , BLOCK_ALL_THREADS );
1173
1174    // kill all existing threads and process descriptors (other than owner)
1175    process_sigaction( process , DELETE_ALL_THREADS );
1176
1177    // check no threads
1178    assert( (process->th_nr == 0) , __FUNCTION__ , "no threads at this point" );
1179
1180exec_dmsg("\n[DBG] %s : core[%x,%d] all threads deleted\n",
1181__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid );
1182
1183    // re-initialize VMM
1184    vmm_init( process );
1185
1186    // register "code" and "data" vsegs as well as entry-point and vfs_bin_xp
1187    // in VMM, using information contained in the elf file.
1188        if( elf_load_process( path , process ) )
1189        {
1190                printk("\n[ERROR] in %s : failed to access .elf file for process %x / path = %s\n",
1191                __FUNCTION__, pid , path );
1192        process_destroy( process );
1193        return -1;
1194        }
1195
1196exec_dmsg("\n[DBG] %s : core[%x,%d] new vsegs registered / path = %s\n",
1197__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, path );
1198
1199// @@@
1200vmm_display( process , true );
1201// @@@
1202
1203    // select a core in local cluster to execute the new main thread
1204    lid  = cluster_select_local_core();
1205
1206    // initialize pthread attributes for new main thread
1207    attr.attributes = PT_ATTR_DETACH | PT_ATTR_CLUSTER_DEFINED | PT_ATTR_CORE_DEFINED;
1208    attr.cxy        = local_cxy;
1209    attr.lid        = lid;
1210
1211    // create and initialize thread descriptor
1212        error = thread_user_create( pid,
1213                                (void *)process->vmm.entry_point,
1214                                exec_info->args_pointers,
1215                                &attr,
1216                                &thread );
1217        if( error )
1218        {
1219                printk("\n[ERROR] in %s : cannot create thread for process %x / path = %s\n",
1220                       __FUNCTION__, pid , path );
1221        process_destroy( process );
1222        return -1;
1223        }
1224
1225exec_dmsg("\n[DBG] %s : core[%x,%d] created main thread %x for new process %x\n",
1226__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, thread->trdid, pid );
1227
1228    // activate new thread
1229        thread_unblock( XPTR( local_cxy , thread ) , THREAD_BLOCKED_GLOBAL );
1230
1231exec_dmsg("\n[DBG] %s : core[%x,%d] exit for path = %s\n",
1232__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, path  );
1233
1234        return 0;
1235
1236}  // end process_make_exec()
1237
1238////////////////////////////////////////////
1239void process_make_kill( process_t * process,
1240                        uint32_t    sig_id )
1241{
1242    // this function must be executed by a thread running in owner cluster
1243    assert( (CXY_FROM_PID( process->pid ) == local_cxy) , __FUNCTION__ ,
1244    "must execute in owner cluster" );
1245
1246    // analyse signal type
1247    switch( sig_id )
1248    {
1249        case SIGSTOP:     // block all threads
1250        {
1251            process_sigaction( process , BLOCK_ALL_THREADS );
1252        }
1253        break;
1254        case SIGCONT:     // unblock all threads
1255        {
1256            process_sigaction( process , UNBLOCK_ALL_THREADS );
1257        }
1258        break;
1259        case SIGKILL:  // block all threads, then delete all threads
1260        {
1261            process_sigaction( process , BLOCK_ALL_THREADS );
1262            process_sigaction( process , DELETE_ALL_THREADS );
1263            process_destroy( process );
1264        }
1265        break;
1266    }
1267}  // end process_make_kill()
1268
1269////////////////////////////////////////////
1270void process_make_exit( process_t * process,
1271                        uint32_t    status )
1272{
1273    // this function must be executed by a thread running in owner cluster
1274    assert( (CXY_FROM_PID( process->pid ) == local_cxy) , __FUNCTION__ ,
1275    "must execute in owner cluster" );
1276
1277    // block all threads in all clusters
1278    process_sigaction( process , BLOCK_ALL_THREADS );
1279
1280    // delete all threads in all clusters
1281    process_sigaction( process , DELETE_ALL_THREADS );
1282
1283    // delete local process descriptor
1284    process_destroy( process ); 
1285
1286}  // end process_make_exit()
1287
1288//////////////////////////
1289void process_init_create()
1290{
1291    process_t      * process;       // local pointer on process_init descriptor
1292    pid_t            pid;           // process_init identifier
1293    thread_t       * thread;        // local pointer on main thread
1294    pthread_attr_t   attr;          // main thread attributes
1295    lid_t            lid;           // selected core local index for main thread
1296    error_t          error;
1297
1298kinit_dmsg("\n[DBG] %s :  core[%x,%d] enters\n", 
1299__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid );
1300
1301    // allocates memory for process descriptor from local cluster
1302        process = process_alloc(); 
1303        if( process == NULL )
1304    {
1305                printk("\n[PANIC] in %s : no memory for process descriptor in cluster %x\n",
1306                __FUNCTION__, local_cxy  );
1307    }
1308
1309    // get PID from local cluster
1310    error = cluster_pid_alloc( XPTR( local_cxy , process ) , &pid );
1311    if( error )
1312    {
1313                printk("\n[PANIC] in %s : cannot allocate PID in cluster %x\n",
1314                __FUNCTION__, local_cxy );
1315        process_destroy( process );
1316    }
1317
1318    assert( (LPID_FROM_PID(pid) == 1) , __FUNCTION__ , "LPID must be 1 for process_init" );
1319
1320    // initialize process descriptor / parent is local process_zero
1321    process_reference_init( process,
1322                            pid,
1323                            0,
1324                            XPTR( local_cxy , &process_zero ) );
1325
1326kinit_dmsg("\n[DBG] %s : core[%x,%d] / process initialised\n", 
1327__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid );
1328
1329    // register "code" and "data" vsegs as well as entry-point
1330    // in process VMM, using information contained in the elf file.
1331        if( elf_load_process( CONFIG_PROCESS_INIT_PATH , process ) )
1332        {
1333                printk("\n[PANIC] in %s : cannot access .elf file / path = %s\n",
1334                __FUNCTION__, CONFIG_PROCESS_INIT_PATH );
1335        process_destroy( process );
1336        }
1337
1338kinit_dmsg("\n[DBG] %s : core[%x,%d] vsegs registered / path = %s\n",
1339__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, CONFIG_PROCESS_INIT_PATH );
1340
1341    // select a core in local cluster to execute the main thread
1342    lid  = cluster_select_local_core();
1343
1344    // initialize pthread attributes for main thread
1345    attr.attributes = PT_ATTR_DETACH | PT_ATTR_CLUSTER_DEFINED | PT_ATTR_CORE_DEFINED;
1346    attr.cxy        = local_cxy;
1347    attr.lid        = lid;
1348
1349    // create and initialize thread descriptor
1350        error = thread_user_create( pid,
1351                                (void *)process->vmm.entry_point,
1352                                NULL,
1353                                &attr,
1354                                &thread );
1355        if( error )
1356        {
1357                printk("\n[PANIC] in %s : cannot create main thread / path = %s\n",
1358                __FUNCTION__, CONFIG_PROCESS_INIT_PATH );
1359        process_destroy( process );
1360        }
1361
1362    // activate thread
1363        thread_unblock( XPTR( local_cxy , thread ) , THREAD_BLOCKED_GLOBAL );
1364
1365    hal_fence();
1366
1367kinit_dmsg("\n[DBG] %s : core[%x,%d] exit / main thread = %x\n",
1368__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, thread );
1369
1370}  // end process_init_create()
1371
Note: See TracBrowser for help on using the repository browser.