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

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

Few bugs.

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