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

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

First implementation of fork/exec.

File size: 28.5 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 *
10 * This file is part of ALMOS-MKH..
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>
30#include <errno.h>
31#include <printk.h>
32#include <memcpy.h>
33#include <bits.h>
34#include <kmem.h>
35#include <page.h>
36#include <vmm.h>
37#include <vfs.h>
38#include <core.h>
39#include <thread.h>
40#include <list.h>
[407]41#include <string.h>
[1]42#include <scheduler.h>
43#include <remote_spinlock.h>
44#include <dqdt.h>
45#include <cluster.h>
46#include <ppm.h>
47#include <boot_info.h>
48#include <process.h>
49#include <elf.h>
[23]50#include <syscalls.h>
[1]51
52//////////////////////////////////////////////////////////////////////////////////////////
53// Extern global variables
54//////////////////////////////////////////////////////////////////////////////////////////
55
56extern process_t process_zero;
57
58//////////////////////////////////////////////////////////////////////////////////////////
59// Process initialisation related functions
60//////////////////////////////////////////////////////////////////////////////////////////
61
62///////////////////////////
63process_t * process_alloc()
64{
65        kmem_req_t   req;
66
67    req.type  = KMEM_PROCESS;
68        req.size  = sizeof(process_t);
69        req.flags = AF_KERNEL;
70
71    return (process_t *)kmem_alloc( &req );
72}
73
74////////////////////////////////////////
75void process_free( process_t * process )
76{
77    kmem_req_t  req;
78
79        req.type = KMEM_PROCESS;
80        req.ptr  = process;
81        kmem_free( &req );
82}
83
[101]84/////////////////////////////////////////////////
85void process_reference_init( process_t * process,
86                             pid_t       pid,
87                             xptr_t      parent_xp )
[1]88{
[101]89    cxy_t       parent_cxy;
90    process_t * parent_ptr;
91    pid_t       parent_pid;
[1]92
[407]93        error_t     error1;
94        error_t     error2;
95        error_t     error3;
96    xptr_t      stdin_xp;
97    xptr_t      stdout_xp;
98    xptr_t      stderr_xp;
99    uint32_t    stdin_id;
100    uint32_t    stdout_id;
101    uint32_t    stderr_id;
[1]102
[407]103process_dmsg("\n[DBG] %s : core[%x,%d] enters for process %x\n",
104__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , pid );
105
[101]106    // get parent process cluster, local pointer, and pid
[407]107    // for all processes other than kernel process
108    if( process == &process_zero )                   // kernel process
[101]109    {
110        assert( (pid == 0) , __FUNCTION__ , "process_zero must have PID = 0\n");
[1]111
[188]112        parent_cxy = 0;
113        parent_ptr = NULL;
[407]114        parent_pid = 0;     
[101]115    }
[407]116    else                                             // user process
[101]117    {
118        parent_cxy = GET_CXY( parent_xp );
119        parent_ptr = (process_t *)GET_PTR( parent_xp );
120        parent_pid = hal_remote_lw( XPTR( parent_cxy , &parent_ptr->pid ) );
121    }
[1]122
[407]123    // initialize PID, PPID, and REF
124        process->pid    = pid;
125    process->ppid   = parent_pid;
126    process->ref_xp = XPTR( local_cxy , process );
[204]127
[407]128    // initialize vmm, fd array and others structures for user processes.
129    // These structures are not used by the kernel process.
130    if( pid )
131    {
132        // initialize vmm (not for kernel)
133        vmm_init( process );
[101]134
[407]135process_dmsg("\n[DBG] %s : core[%x,%d] / vmm initialised for process %x\n", 
136__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , pid );
[1]137
[407]138        // initialize fd_array (not for kernel)
139        process_fd_init( process );
[1]140
[407]141        // create stdin / stdout / stderr pseudo-files (not for kernel)
142        if( parent_pid == 0 )                                              // process_init
143        {
144            error1 = vfs_open( process,
145                               CONFIG_INIT_STDIN,
146                               O_RDONLY, 
147                               0,                // FIXME chmod
148                               &stdin_xp, 
149                               &stdin_id );
[1]150
[407]151            error2 = vfs_open( process,
152                               CONFIG_INIT_STDOUT,
153                               O_WRONLY, 
154                               0,                // FIXME chmod
155                               &stdout_xp, 
156                               &stdout_id );
[1]157
[407]158            error3 = vfs_open( process,
159                               CONFIG_INIT_STDERR,
160                               O_WRONLY, 
161                               0,                // FIXME chmod
162                               &stderr_xp, 
163                               &stderr_id );
164        }
165        else                                                               // user process
166        {
167            error1 = vfs_open( process,
168                               CONFIG_USER_STDIN,
169                               O_RDONLY, 
170                               0,                // FIXME chmod
171                               &stdin_xp, 
172                               &stdin_id );
173
174            error2 = vfs_open( process,
175                               CONFIG_USER_STDOUT,
176                               O_WRONLY, 
177                               0,                // FIXME chmod
178                               &stdout_xp, 
179                               &stdout_id );
180
181            error3 = vfs_open( process,
182                               CONFIG_USER_STDERR,
183                               O_WRONLY, 
184                               0,                // FIXME chmod
185                               &stderr_xp, 
186                               &stderr_id );
187        }
188
189        assert( ((error1 == 0) && (error2 == 0) && (error3 == 0)) , __FUNCTION__ ,
190        "cannot open stdin/stdout/stderr pseudo files\n");
191
192        assert( ((stdin_id == 0) && (stdout_id == 1) && (stderr_id == 2)) , __FUNCTION__ ,
193        "bad indexes : stdin %d / stdout %d / stderr %d \n", stdin_id , stdout_id , stderr_id );
194
195process_dmsg("\n[DBG] %s : core[%x,%d] / fd array initialised for process %x\n", 
196__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , pid );
197
198
199        // reset reference process files structures and cwd_lock (not for kernel)
200            process->vfs_root_xp     = XPTR_NULL;
201            process->vfs_bin_xp      = XPTR_NULL;
202            process->vfs_cwd_xp      = XPTR_NULL;
203        remote_rwlock_init( XPTR( local_cxy , &process->cwd_lock ) );
204
205        // reset children list root (not for kernel)
206        xlist_root_init( XPTR( local_cxy , &process->children_root ) );
207            process->children_nr     = 0;
208
209        // reset semaphore / mutex / barrier / condvar list roots (nor for kernel)
210        xlist_root_init( XPTR( local_cxy , &process->sem_root ) );
211        xlist_root_init( XPTR( local_cxy , &process->mutex_root ) );
212        xlist_root_init( XPTR( local_cxy , &process->barrier_root ) );
213        xlist_root_init( XPTR( local_cxy , &process->condvar_root ) );
214        remote_spinlock_init( XPTR( local_cxy , &process->sync_lock ) );
215
216        // register new process in the parent children list (nor for kernel)
[101]217        xptr_t entry = XPTR( local_cxy  , &process->brothers_list );
218        xptr_t root  = XPTR( parent_cxy , &parent_ptr->children_root );
219        xlist_add_first( root , entry );
220    }
[172]221
[23]222    // reset th_tbl[] array as empty
[1]223    uint32_t i;
224    for( i = 0 ; i < CONFIG_THREAD_MAX_PER_CLUSTER ; i++ )
225        {
226        process->th_tbl[i] = NULL;
227    }
228    process->th_nr  = 0;
229    spinlock_init( &process->th_lock );
230
231    // register new process descriptor in local cluster manager local_list
232    cluster_process_local_link( process );
233
234    // register new process descriptor in owner cluster manager copies_list
235    cluster_process_copies_link( process );
236
[172]237    // initialize signal manager TODO [AG]
[23]238
[124]239        hal_fence();
[1]240
[407]241process_dmsg("\n[DBG] %s : core[%x,%d] exit for process %x\n",
242__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , pid );
[101]243
[204]244}  // process_reference init()
245
[1]246/////////////////////////////////////////////////////
247error_t process_copy_init( process_t * local_process,
248                           xptr_t      reference_process_xp )
249{
[23]250    // get reference process cluster and local pointer
251    cxy_t       ref_cxy = GET_CXY( reference_process_xp );
252    process_t * ref_ptr = (process_t *)GET_PTR( reference_process_xp );
[1]253
[407]254    // set the pid, ppid, ref_xp fields in local process
255    local_process->pid    = hal_remote_lw( XPTR( ref_cxy , &ref_ptr->pid ) );
256    local_process->ppid   = hal_remote_lw( XPTR( ref_cxy , &ref_ptr->ppid ) );
257    local_process->ref_xp = reference_process_xp;
258
259process_dmsg("\n[DBG] %s : core[%x,%d] enters for process %x in cluster %x\n",
260__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , local_process->pid );
261
[172]262    // reset local process vmm
[23]263    vmm_init( local_process );
[1]264
[172]265    // reset process file descriptors array
[23]266        process_fd_init( local_process );
[1]267
[23]268    // reset vfs_root_xp / vfs_bin_xp / vfs_cwd_xp fields
269    local_process->vfs_root_xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->vfs_root_xp ) );
270    local_process->vfs_bin_xp  = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->vfs_bin_xp ) );
271    local_process->vfs_cwd_xp  = XPTR_NULL;
[1]272
273    // reset children list root (not used in a process descriptor copy)
274    xlist_root_init( XPTR( local_cxy , &local_process->children_root ) );
[172]275    local_process->children_nr   = 0;
[1]276
277    // reset brothers list (not used in a process descriptor copy)
278    xlist_entry_init( XPTR( local_cxy , &local_process->brothers_list ) );
279
280    // reset semaphores list root (not used in a process descriptor copy)
281    xlist_root_init( XPTR( local_cxy , &local_process->sem_root ) );
[23]282    xlist_root_init( XPTR( local_cxy , &local_process->mutex_root ) );
283    xlist_root_init( XPTR( local_cxy , &local_process->barrier_root ) );
284    xlist_root_init( XPTR( local_cxy , &local_process->condvar_root ) );
[1]285
[23]286    // reset th_tbl[] array as empty
[1]287    uint32_t i;
288    for( i = 0 ; i < CONFIG_THREAD_MAX_PER_CLUSTER ; i++ )
289        {
290        local_process->th_tbl[i] = NULL;
291    }
292    local_process->th_nr  = 0;
293    spinlock_init( &local_process->th_lock );
294
295    // register new process descriptor in local cluster manager local_list
296    cluster_process_local_link( local_process );
297
298    // register new process descriptor in owner cluster manager copies_list
299    cluster_process_copies_link( local_process );
300
[172]301    // initialize signal manager TODO [AG]
[23]302
[124]303        hal_fence();
[1]304
[407]305process_dmsg("\n[DBG] %s : core[%x,%d] exit for process %x in cluster %x\n",
306__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , local_process->pid );
[279]307
[1]308    return 0;
309
[204]310} // end process_copy_init()
311
[1]312///////////////////////////////////////////
313void process_destroy( process_t * process )
314{
[172]315        if( process->th_nr != 0 )
[1]316    {
[374]317        panic("process %x in cluster %x has still active threads",
[373]318              process->pid , local_cxy );
[1]319    }
320
321    // get local process manager pointer
322    pmgr_t * pmgr = &LOCAL_CLUSTER->pmgr;
323
[23]324    // get the lock protecting the list of local process descriptors
325    remote_spinlock_lock( XPTR( local_cxy , &pmgr->local_lock ) );
326
[172]327    // remove the process descriptor from local_list in local cluster manager
[1]328    xlist_unlink( XPTR( local_cxy , &process->local_list ) );
329
[23]330    // release the lock protecting the list of local process descriptors
331    remote_spinlock_unlock( XPTR( local_cxy , &pmgr->local_lock ) );
332
[1]333    // get extended pointer on copies_lock in owner cluster manager
334    cxy_t  owner_cxy    = CXY_FROM_PID( process->pid );
335        lpid_t lpid         = LPID_FROM_PID( process->pid );
[326]336    xptr_t copies_lock  = XPTR( owner_cxy , &pmgr->copies_lock[lpid] );
[1]337
338    // remove the local process descriptor from copies_list
339    remote_spinlock_lock( copies_lock );
340    xlist_unlink( XPTR( local_cxy , &process->copies_list ) );
341    remote_spinlock_unlock( copies_lock );
[172]342
[1]343    // synchronize memory
[124]344        hal_fence();
[1]345
[172]346    // From this point, the process descriptor is unreachable
[1]347
[23]348    // close all open files and update dirty TODO [AG]
349
[1]350    // release signal manager TODO [AG]
351
[23]352    // Decrease refcount for bin file, root file and cwd file
[337]353        if( process->vfs_bin_xp  != XPTR_NULL ) vfs_file_count_down( process->vfs_bin_xp );
354        if( process->vfs_root_xp != XPTR_NULL ) vfs_file_count_down( process->vfs_root_xp );
355        if( process->vfs_cwd_xp  != XPTR_NULL ) vfs_file_count_down( process->vfs_cwd_xp );
[1]356
357    // Destroy VMM
358    vmm_destroy( process );
359
[407]360        process_dmsg("\n[DBG] %s for pid %d / page_faults = %d\n",
[1]361                 __FUNCTION__ , process->pid, process->vmm.pgfault_nr );
362
[407]363}  // end process_destroy()
364
[1]365////////////////////////////////////////
366void process_kill( process_t * process )
367{
368    thread_t     * thread;    // pointer on current thead descriptor
369    uint32_t       ltid;      // index in process th_tbl
370    uint32_t       count;     // thread counter
371
[407]372printk("\n@@@ %s enter\n", __FUNCTION__ );
373
[1]374    // get lock protecting th_tbl[]
375    spinlock_lock( &process->th_lock );
376
[5]377    // first loop on threads to send the THREAD_SIG_KILL signal to all process threads
[1]378    // we use both "ltid" and "count" indexes, because it can exist "holes" in th_tbl
[172]379    for( ltid = 0 , count = 0  ;
380         (ltid < CONFIG_THREAD_MAX_PER_CLUSTER) && (count < process->th_nr) ;
[1]381         ltid++ )
382    {
383        thread = process->th_tbl[ltid];
384
385        if( thread != NULL )
386        {
387            thread_kill( thread );
388            count++;
389        }
[172]390    }
391
[407]392printk("\n@@@ %s : %d signal(s) sent\n", __FUNCTION__, count );
[1]393
394    // second loop on threads to wait acknowledge from scheduler,
395    // unlink thread from process and parent thread, and release thread descriptor
[172]396    for( ltid = 0 , count = 0  ;
[1]397         (ltid < CONFIG_THREAD_MAX_PER_CLUSTER) && (count < process->th_nr) ;
398         ltid++ )
399    {
400        thread = process->th_tbl[ltid];
401
402        if( thread != NULL )
403        {
404
[407]405printk("\n@@@ %s start polling at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
[1]406
[407]407            // poll the THREAD_SIG_KILL bit until reset
408            while( thread->signals & THREAD_SIG_KILL ) asm volatile( "nop" );
409
410printk("\n@@@ %s exit polling\n", __FUNCTION__ );
411
412            // detach target thread from parent if attached
413            if( (thread->flags & THREAD_FLAG_DETACHED) != 0 ) 
414            thread_child_parent_unlink( thread->parent , XPTR( local_cxy , thread ) );
415
[1]416            // unlink thread from process
417            process_remove_thread( thread );
418
419            // release memory for thread descriptor
420            thread_destroy( thread );
421
422            count++;
423        }
424    }
425
[407]426printk("\n@@@ %s : %d ack(s) received\n", __FUNCTION__, count );
427
[1]428    // release lock protecting th_tbl[]
429    spinlock_unlock( &process->th_lock );
430
431    // release memory allocated for process descriptor
432    process_destroy( process );
433
[407]434printk("\n[@@@] %s : core[%x,%d] exit\n",
435__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid );
436
437}  // end process_kill()
438
[1]439///////////////////////////////////////////////
440process_t * process_get_local_copy( pid_t pid )
441{
442    error_t        error;
[172]443    process_t    * process_ptr;   // local pointer on process
[23]444    xptr_t         process_xp;    // extended pointer on process
[1]445
446    cluster_t * cluster = LOCAL_CLUSTER;
447
448    // get lock protecting local list of processes
[23]449    remote_spinlock_lock( XPTR( local_cxy , &cluster->pmgr.local_lock ) );
[1]450
451    // scan the local list of process descriptors to find the process
[23]452    xptr_t  iter;
453    bool_t  found = false;
454    XLIST_FOREACH( XPTR( local_cxy , &cluster->pmgr.local_root ) , iter )
[1]455    {
[23]456        process_xp  = XLIST_ELEMENT( iter , process_t , local_list );
457        process_ptr = (process_t *)GET_PTR( process_xp );
458        if( process_ptr->pid == pid )
[1]459        {
460            found = true;
461            break;
462        }
463    }
464
465    // release lock protecting local list of processes
[23]466    remote_spinlock_unlock( XPTR( local_cxy , &cluster->pmgr.local_lock ) );
[1]467
[172]468    // allocate memory for a new local process descriptor
[23]469    // and initialise it from reference cluster if required
[1]470    if( !found )
471    {
472        // get extended pointer on reference process descriptor
[23]473        xptr_t ref_xp = cluster_get_reference_process_from_pid( pid );
[1]474
[23]475        assert( (ref_xp != XPTR_NULL) , __FUNCTION__ , "illegal pid\n" );
476
[1]477        // allocate memory for local process descriptor
[23]478        process_ptr = process_alloc();
479        if( process_ptr == NULL )  return NULL;
[1]480
481        // initialize local process descriptor copy
[23]482        error = process_copy_init( process_ptr , ref_xp );
[1]483        if( error ) return NULL;
484    }
485
[23]486    return process_ptr;
[172]487}
[1]488
489//////////////////////////////////////////////////////////////////////////////////////////
490// File descriptor array related functions
491//////////////////////////////////////////////////////////////////////////////////////////
492
493///////////////////////////////////////////
494void process_fd_init( process_t * process )
495{
496    uint32_t fd;
497
498    remote_spinlock_init( XPTR( local_cxy , &process->fd_array.lock ) );
499
[23]500    process->fd_array.current = 0;
501
[1]502    // initialize array
[23]503    for ( fd = 0 ; fd < CONFIG_PROCESS_FILE_MAX_NR ; fd++ )
[1]504    {
505        process->fd_array.array[fd] = XPTR_NULL;
506    }
507}
508
[23]509//////////////////////////////
510bool_t process_fd_array_full()
[1]511{
[172]512    // get extended pointer on reference process
[23]513    xptr_t ref_xp = CURRENT_THREAD->process->ref_xp;
[1]514
[23]515    // get reference process cluster and local pointer
516    process_t * ref_ptr = (process_t *)GET_PTR( ref_xp );
517    cxy_t       ref_cxy = GET_CXY( ref_xp );
[1]518
[23]519    // get number of open file descriptors from reference fd_array
520    uint32_t current = hal_remote_lw( XPTR( ref_cxy , &ref_ptr->fd_array.current ) );
521
[172]522        return ( current >= CONFIG_PROCESS_FILE_MAX_NR );
[1]523}
524
525/////////////////////////////////////////////////
[407]526error_t process_fd_register( process_t * process,
527                             xptr_t      file_xp,
528                             uint32_t  * fdid )
[1]529{
530    bool_t    found;
[23]531    uint32_t  id;
532    xptr_t    xp;
[1]533
[23]534    // get reference process cluster and local pointer
[407]535    xptr_t ref_xp = process->ref_xp;
[23]536    process_t * ref_ptr = (process_t *)GET_PTR( ref_xp );
537    cxy_t       ref_cxy = GET_CXY( ref_xp );
538
539    // take lock protecting reference fd_array
540        remote_spinlock_lock( XPTR( ref_cxy , &ref_ptr->fd_array.lock ) );
541
[1]542    found   = false;
543
[23]544    for ( id = 0; id < CONFIG_PROCESS_FILE_MAX_NR ; id++ )
[1]545    {
[23]546        xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->fd_array.array[id] ) );
547        if ( xp == XPTR_NULL )
[1]548        {
549            found = true;
[23]550            hal_remote_swd( XPTR( ref_cxy , &ref_ptr->fd_array.array[id] ) , file_xp );
551                hal_remote_atomic_add( XPTR( ref_cxy , &ref_ptr->fd_array.current ) , 1 );
[407]552                        *fdid = id;
[1]553            break;
554        }
555    }
556
[23]557    // release lock protecting reference fd_array
558        remote_spinlock_unlock( XPTR( ref_cxy , &ref_ptr->fd_array.lock ) );
[1]559
560    if ( !found ) return EMFILE;
561    else          return 0;
[172]562}
[1]563
[172]564////////////////////////////////////////////////
[23]565xptr_t process_fd_get_xptr( process_t * process,
[407]566                            uint32_t    fdid )
[1]567{
[23]568    xptr_t  file_xp;
[1]569
[23]570    // access local copy of process descriptor
[407]571    file_xp = process->fd_array.array[fdid];
[1]572
[23]573    if( file_xp == XPTR_NULL )
574    {
575        // get reference process cluster and local pointer
576        xptr_t      ref_xp  = process->ref_xp;
577        cxy_t       ref_cxy = GET_CXY( ref_xp );
578        process_t * ref_ptr = (process_t *)GET_PTR( ref_xp );
[1]579
[23]580        // access reference process descriptor
[407]581        file_xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->fd_array.array[fdid] ) );
[1]582
[23]583        // update local fd_array if found
584        if( file_xp != XPTR_NULL )
585        {
[407]586            process->fd_array.array[fdid] = file_xp;
[23]587        }
588    }
[1]589
[23]590    return file_xp;
[1]591
[407]592}  // end process_fd_get_xptr()
593
[1]594///////////////////////////////////////////
595void process_fd_remote_copy( xptr_t dst_xp,
596                             xptr_t src_xp )
597{
598    uint32_t fd;
599    xptr_t   entry;
600
601    // get cluster and local pointer for src fd_array
602    cxy_t        src_cxy = GET_CXY( src_xp );
603    fd_array_t * src_ptr = (fd_array_t *)GET_PTR( src_xp );
604
605    // get cluster and local pointer for dst fd_array
606    cxy_t        dst_cxy = GET_CXY( dst_xp );
607    fd_array_t * dst_ptr = (fd_array_t *)GET_PTR( dst_xp );
608
609    // get the remote lock protecting the src fd_array
610        remote_spinlock_lock( XPTR( src_cxy , &src_ptr->lock ) );
611
[172]612    // loop on all entries in source process fd_array
[23]613    for( fd = 0 ; fd < CONFIG_PROCESS_FILE_MAX_NR ; fd++ )
[1]614        {
615                entry = (xptr_t)hal_remote_lwd( XPTR( src_cxy , &src_ptr->array[fd] ) );
616
617                if( entry != XPTR_NULL )
618                {
619            // increment file descriptor ref count
620            vfs_file_count_up( entry );
621
622                        // copy entry in destination process fd_array
623                        hal_remote_swd( XPTR( dst_cxy , &dst_ptr->array[fd] ) , entry );
624                }
625        }
626
627    // release lock on source process fd_array
628        remote_spinlock_unlock( XPTR( src_cxy , &src_ptr->lock ) );
629
[407]630}  // end process_fd_remote_copy()
631
[1]632////////////////////////////////////////////////////////////////////////////////////
633//  Thread related functions
634////////////////////////////////////////////////////////////////////////////////////
635
636/////////////////////////////////////////////////////
637error_t process_register_thread( process_t * process,
638                                 thread_t  * thread,
639                                 trdid_t   * trdid )
640{
641    ltid_t   ltid;
642    bool_t   found;
643
[14]644    assert( (process != NULL) , __FUNCTION__ , "process argument is NULL" );
[1]645
[14]646    assert( (thread != NULL) , __FUNCTION__ , "thread argument is NULL" );
647
[407]648    // search a free slot in th_tbl[]
649    // 0 is not a valid ltid value
[1]650    found = false;
[407]651    for( ltid = 1 ; ltid < CONFIG_THREAD_MAX_PER_CLUSTER ; ltid++ )
[1]652    {
653        if( process->th_tbl[ltid] == NULL )
654        {
655            found = true;
656            break;
657        }
658    }
659
660    if( found )
661    {
662        // register thread in th_tbl[]
663        process->th_tbl[ltid] = thread;
664        process->th_nr++;
665
666        // returns trdid
667        *trdid = TRDID( local_cxy , ltid );
668    }
669
670    return (found) ? 0 : ENOMEM;
[204]671
672}  // end process_register_thread()
673
[1]674///////////////////////////////////////////////
675void process_remove_thread( thread_t * thread )
676{
[373]677    assert( (thread != NULL) , __FUNCTION__ , "thread argument is NULL" );
[172]678
[1]679    process_t * process = thread->process;
680
681    // get thread local index
682    ltid_t  ltid = LTID_FROM_TRDID( thread->trdid );
683
684    // remove thread from th_tbl[]
685    process->th_tbl[ltid] = NULL;
686    process->th_nr--;
687
[204]688}  // process_remove_thread()
689
[1]690/////////////////////////////////////////////////////
691error_t process_make_exec( exec_info_t  * exec_info )
692{
693    char           * path;                            // pathname to .elf file
[407]694    bool_t           keep_pid;                        // new process keep parent PID if true
[172]695    process_t      * process;                         // local pointer on new process
[1]696    pid_t            pid;                             // new process pid
[101]697    xptr_t           parent_xp;                       // extended pointer on parent process
[407]698    cxy_t            parent_cxy;                      // parent process local cluster
699    process_t      * parent_ptr;                      // local pointer on parent process
700    uint32_t         parent_pid;                      // parent process identifier
[1]701    thread_t       * thread;                          // pointer on new thread
702    pthread_attr_t   attr;                            // main thread attributes
703    core_t         * core;                            // pointer on selected core
704    lid_t            lid;                             // selected core local index
[172]705        error_t          error;
[1]706
[407]707        // get .elf pathname, parent_xp, and keep_pid flag from exec_info
[101]708        path      = exec_info->path;
709    parent_xp = exec_info->parent_xp;
[407]710    keep_pid  = exec_info->keep_pid;
[101]711
[407]712process_dmsg("\n[DBG] %s : core[%x,%d] enters for path = %s\n",
713__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, path );
714
[101]715    // get parent process cluster and local pointer
716    parent_cxy = GET_CXY( parent_xp );
717    parent_ptr = (process_t *)GET_PTR( parent_xp );
718    parent_pid = hal_remote_lw( XPTR( parent_cxy , &parent_ptr->pid ) );
[172]719
[407]720    // allocates memory for process descriptor
721        process = process_alloc(); 
722        if( process == NULL ) return -1;
[1]723
[407]724    // get PID
725    if( keep_pid )    // keep parent PID
[1]726    {
[407]727        pid = parent_pid;
[1]728    }
[407]729    else              // get new PID from local cluster
[101]730    {
[407]731        error = cluster_pid_alloc( XPTR( local_cxy , process ) , &pid );
732        if( error ) return -1;
[101]733    }
[172]734
[407]735process_dmsg("\n[DBG] %s : core[%x,%d] created process %x for path = %s\n",
736__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, pid, path );
737
[1]738    // initialize the process descriptor as the reference
[101]739    process_reference_init( process , pid , parent_xp );
[172]740
[407]741process_dmsg("\n[DBG] %s : core[%x,%d] initialized process %x / path = %s\n",
742__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, pid, path );
[1]743
[172]744    // initialize vfs_root and vfs_cwd from parent process
[101]745    xptr_t  vfs_root_xp = hal_remote_lwd( XPTR( parent_cxy , &parent_ptr->vfs_root_xp ) );
746        vfs_file_count_up( vfs_root_xp );
747        process->vfs_root_xp = vfs_root_xp;
[1]748
[101]749    xptr_t  vfs_cwd_xp = hal_remote_lwd( XPTR( parent_cxy , &parent_ptr->vfs_cwd_xp ) );
750        vfs_file_count_up( vfs_cwd_xp );
751        process->vfs_cwd_xp = vfs_cwd_xp;
752
753    // initialize embedded fd_array from parent process
[204]754    process_fd_remote_copy( XPTR( local_cxy  , &process->fd_array ),
[101]755                            XPTR( parent_cxy , &parent_ptr->fd_array) );
756
[407]757process_dmsg("\n[DBG] %s :  core[%x,%d] copied fd_array for process %x\n",
758__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, pid );
[204]759
[172]760    // register "code" and "data" vsegs as well as the process entry-point in VMM,
761    // using information contained in the elf file.
[1]762        error = elf_load_process( path , process );
763
764        if( error )
765        {
[407]766                printk("\n[ERROR] in %s : failed to access .elf file for process %x / path = %s\n",
[1]767                       __FUNCTION__, pid , path );
768        process_destroy( process );
769        return error;
770        }
771
[407]772process_dmsg("\n[DBG] %s : core[%x,%d] registered code/data vsegs for process %x / path = %s\n",
773__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, pid, path );
[1]774
775    // select a core in cluster
776    lid  = cluster_select_local_core();
777    core = &LOCAL_CLUSTER->core_tbl[lid];
778
779    // initialize pthread attributes for main thread
[23]780    attr.attributes = PT_ATTR_DETACH | PT_ATTR_CLUSTER_DEFINED | PT_ATTR_CORE_DEFINED;
781    attr.cxy        = local_cxy;
782    attr.lid        = lid;
[1]783
[172]784    // create and initialize thread descriptor
[23]785        error = thread_user_create( pid,
786                                (void *)process->vmm.entry_point,
787                                exec_info->args_pointers,
[1]788                                &attr,
[172]789                                &thread );
[1]790        if( error )
791        {
792                printk("\n[ERROR] in %s : cannot create thread for process %x / path = %s\n",
[407]793                       __FUNCTION__, pid , path );
[1]794        process_destroy( process );
795        return error;
796        }
797
[407]798process_dmsg("\n[DBG] %s : core[%x,%d] created thread %x for process %x / path = %s\n",
799__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, thread->trdid, pid, path  );
[204]800
[101]801    // update children list in parent process
802        xlist_add_last( XPTR( parent_cxy , &parent_ptr->children_root ),
803                    XPTR( local_cxy  , &process->brothers_list ) );
804        hal_remote_atomic_add( XPTR( parent_cxy , &parent_ptr->children_nr) , 1 );
805
[172]806    // activate new thread
[1]807        thread_unblock( XPTR( local_cxy , thread ) , THREAD_BLOCKED_GLOBAL );
808
[407]809process_dmsg("\n[DBG] %s : core[%x,%d] exit for path = %s\n",
810__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, path  );
[204]811
[1]812        return 0;
813
[407]814}  // end process_make_exec()
[204]815
[1]816//////////////////////////
817void process_init_create()
818{
819    exec_info_t   exec_info;     // structure to be passed to process_make_exec()
[407]820    xptr_t        parent_xp;     // extended pointer on parent process.
821    error_t       error;
[1]822
[407]823process_dmsg("\n[DBG] %s : enters in cluster %x\n", 
824__FUNCTION__ , local_cxy );
[1]825
[407]826    // parent process is local kernel process
827    parent_xp = XPTR( local_cxy , &process_zero );
[101]828
[1]829    // initialize the exec_info structure
[407]830    exec_info.keep_pid     = false;
831    exec_info.parent_xp    = parent_xp;
[101]832    strcpy( exec_info.path , CONFIG_PROCESS_INIT_PATH );
833    exec_info.args_nr      = 0;
834    exec_info.envs_nr      = 0;
[1]835
[407]836    // initialize process_init and create thread_init
837        error = process_make_exec( &exec_info );
[101]838
[407]839        if( error ) panic("cannot initialize process_init in cluster %x", local_cxy );
[1]840
[407]841process_dmsg("\n[DBG] %s : exit in cluster %x\n", 
842__FUNCTION__ , local_cxy );
[1]843               
[124]844    hal_fence();
[1]845
[204]846}  // end process_init_create()
847
Note: See TracBrowser for help on using the repository browser.