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
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 <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>
41#include <string.h>
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>
50#include <syscalls.h>
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
84/////////////////////////////////////////////////
85void process_reference_init( process_t * process,
86                             pid_t       pid,
87                             xptr_t      parent_xp )
88{
89    cxy_t       parent_cxy;
90    process_t * parent_ptr;
91    pid_t       parent_pid;
92
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;
102
103process_dmsg("\n[DBG] %s : core[%x,%d] enters for process %x\n",
104__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , pid );
105
106    // get parent process cluster, local pointer, and pid
107    // for all processes other than kernel process
108    if( process == &process_zero )                   // kernel process
109    {
110        assert( (pid == 0) , __FUNCTION__ , "process_zero must have PID = 0\n");
111
112        parent_cxy = 0;
113        parent_ptr = NULL;
114        parent_pid = 0;     
115    }
116    else                                             // user process
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    }
122
123    // initialize PID, PPID, and REF
124        process->pid    = pid;
125    process->ppid   = parent_pid;
126    process->ref_xp = XPTR( local_cxy , process );
127
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 );
134
135process_dmsg("\n[DBG] %s : core[%x,%d] / vmm initialised for process %x\n", 
136__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , pid );
137
138        // initialize fd_array (not for kernel)
139        process_fd_init( process );
140
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 );
150
151            error2 = vfs_open( process,
152                               CONFIG_INIT_STDOUT,
153                               O_WRONLY, 
154                               0,                // FIXME chmod
155                               &stdout_xp, 
156                               &stdout_id );
157
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)
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    }
221
222    // reset th_tbl[] array as empty
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
237    // initialize signal manager TODO [AG]
238
239        hal_fence();
240
241process_dmsg("\n[DBG] %s : core[%x,%d] exit for process %x\n",
242__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , pid );
243
244}  // process_reference init()
245
246/////////////////////////////////////////////////////
247error_t process_copy_init( process_t * local_process,
248                           xptr_t      reference_process_xp )
249{
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 );
253
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
262    // reset local process vmm
263    vmm_init( local_process );
264
265    // reset process file descriptors array
266        process_fd_init( local_process );
267
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;
272
273    // reset children list root (not used in a process descriptor copy)
274    xlist_root_init( XPTR( local_cxy , &local_process->children_root ) );
275    local_process->children_nr   = 0;
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 ) );
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 ) );
285
286    // reset th_tbl[] array as empty
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
301    // initialize signal manager TODO [AG]
302
303        hal_fence();
304
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 );
307
308    return 0;
309
310} // end process_copy_init()
311
312///////////////////////////////////////////
313void process_destroy( process_t * process )
314{
315        if( process->th_nr != 0 )
316    {
317        panic("process %x in cluster %x has still active threads",
318              process->pid , local_cxy );
319    }
320
321    // get local process manager pointer
322    pmgr_t * pmgr = &LOCAL_CLUSTER->pmgr;
323
324    // get the lock protecting the list of local process descriptors
325    remote_spinlock_lock( XPTR( local_cxy , &pmgr->local_lock ) );
326
327    // remove the process descriptor from local_list in local cluster manager
328    xlist_unlink( XPTR( local_cxy , &process->local_list ) );
329
330    // release the lock protecting the list of local process descriptors
331    remote_spinlock_unlock( XPTR( local_cxy , &pmgr->local_lock ) );
332
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 );
336    xptr_t copies_lock  = XPTR( owner_cxy , &pmgr->copies_lock[lpid] );
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 );
342
343    // synchronize memory
344        hal_fence();
345
346    // From this point, the process descriptor is unreachable
347
348    // close all open files and update dirty TODO [AG]
349
350    // release signal manager TODO [AG]
351
352    // Decrease refcount for bin file, root file and cwd file
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 );
356
357    // Destroy VMM
358    vmm_destroy( process );
359
360        process_dmsg("\n[DBG] %s for pid %d / page_faults = %d\n",
361                 __FUNCTION__ , process->pid, process->vmm.pgfault_nr );
362
363}  // end process_destroy()
364
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
372printk("\n@@@ %s enter\n", __FUNCTION__ );
373
374    // get lock protecting th_tbl[]
375    spinlock_lock( &process->th_lock );
376
377    // first loop on threads to send the THREAD_SIG_KILL signal to all process threads
378    // we use both "ltid" and "count" indexes, because it can exist "holes" in th_tbl
379    for( ltid = 0 , count = 0  ;
380         (ltid < CONFIG_THREAD_MAX_PER_CLUSTER) && (count < process->th_nr) ;
381         ltid++ )
382    {
383        thread = process->th_tbl[ltid];
384
385        if( thread != NULL )
386        {
387            thread_kill( thread );
388            count++;
389        }
390    }
391
392printk("\n@@@ %s : %d signal(s) sent\n", __FUNCTION__, count );
393
394    // second loop on threads to wait acknowledge from scheduler,
395    // unlink thread from process and parent thread, and release thread descriptor
396    for( ltid = 0 , count = 0  ;
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
405printk("\n@@@ %s start polling at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
406
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
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
426printk("\n@@@ %s : %d ack(s) received\n", __FUNCTION__, count );
427
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
434printk("\n[@@@] %s : core[%x,%d] exit\n",
435__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid );
436
437}  // end process_kill()
438
439///////////////////////////////////////////////
440process_t * process_get_local_copy( pid_t pid )
441{
442    error_t        error;
443    process_t    * process_ptr;   // local pointer on process
444    xptr_t         process_xp;    // extended pointer on process
445
446    cluster_t * cluster = LOCAL_CLUSTER;
447
448    // get lock protecting local list of processes
449    remote_spinlock_lock( XPTR( local_cxy , &cluster->pmgr.local_lock ) );
450
451    // scan the local list of process descriptors to find the process
452    xptr_t  iter;
453    bool_t  found = false;
454    XLIST_FOREACH( XPTR( local_cxy , &cluster->pmgr.local_root ) , iter )
455    {
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 )
459        {
460            found = true;
461            break;
462        }
463    }
464
465    // release lock protecting local list of processes
466    remote_spinlock_unlock( XPTR( local_cxy , &cluster->pmgr.local_lock ) );
467
468    // allocate memory for a new local process descriptor
469    // and initialise it from reference cluster if required
470    if( !found )
471    {
472        // get extended pointer on reference process descriptor
473        xptr_t ref_xp = cluster_get_reference_process_from_pid( pid );
474
475        assert( (ref_xp != XPTR_NULL) , __FUNCTION__ , "illegal pid\n" );
476
477        // allocate memory for local process descriptor
478        process_ptr = process_alloc();
479        if( process_ptr == NULL )  return NULL;
480
481        // initialize local process descriptor copy
482        error = process_copy_init( process_ptr , ref_xp );
483        if( error ) return NULL;
484    }
485
486    return process_ptr;
487}
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
500    process->fd_array.current = 0;
501
502    // initialize array
503    for ( fd = 0 ; fd < CONFIG_PROCESS_FILE_MAX_NR ; fd++ )
504    {
505        process->fd_array.array[fd] = XPTR_NULL;
506    }
507}
508
509//////////////////////////////
510bool_t process_fd_array_full()
511{
512    // get extended pointer on reference process
513    xptr_t ref_xp = CURRENT_THREAD->process->ref_xp;
514
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 );
518
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
522        return ( current >= CONFIG_PROCESS_FILE_MAX_NR );
523}
524
525/////////////////////////////////////////////////
526error_t process_fd_register( process_t * process,
527                             xptr_t      file_xp,
528                             uint32_t  * fdid )
529{
530    bool_t    found;
531    uint32_t  id;
532    xptr_t    xp;
533
534    // get reference process cluster and local pointer
535    xptr_t ref_xp = process->ref_xp;
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
542    found   = false;
543
544    for ( id = 0; id < CONFIG_PROCESS_FILE_MAX_NR ; id++ )
545    {
546        xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->fd_array.array[id] ) );
547        if ( xp == XPTR_NULL )
548        {
549            found = true;
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 );
552                        *fdid = id;
553            break;
554        }
555    }
556
557    // release lock protecting reference fd_array
558        remote_spinlock_unlock( XPTR( ref_cxy , &ref_ptr->fd_array.lock ) );
559
560    if ( !found ) return EMFILE;
561    else          return 0;
562}
563
564////////////////////////////////////////////////
565xptr_t process_fd_get_xptr( process_t * process,
566                            uint32_t    fdid )
567{
568    xptr_t  file_xp;
569
570    // access local copy of process descriptor
571    file_xp = process->fd_array.array[fdid];
572
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 );
579
580        // access reference process descriptor
581        file_xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->fd_array.array[fdid] ) );
582
583        // update local fd_array if found
584        if( file_xp != XPTR_NULL )
585        {
586            process->fd_array.array[fdid] = file_xp;
587        }
588    }
589
590    return file_xp;
591
592}  // end process_fd_get_xptr()
593
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
612    // loop on all entries in source process fd_array
613    for( fd = 0 ; fd < CONFIG_PROCESS_FILE_MAX_NR ; fd++ )
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
630}  // end process_fd_remote_copy()
631
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
644    assert( (process != NULL) , __FUNCTION__ , "process argument is NULL" );
645
646    assert( (thread != NULL) , __FUNCTION__ , "thread argument is NULL" );
647
648    // search a free slot in th_tbl[]
649    // 0 is not a valid ltid value
650    found = false;
651    for( ltid = 1 ; ltid < CONFIG_THREAD_MAX_PER_CLUSTER ; ltid++ )
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;
671
672}  // end process_register_thread()
673
674///////////////////////////////////////////////
675void process_remove_thread( thread_t * thread )
676{
677    assert( (thread != NULL) , __FUNCTION__ , "thread argument is NULL" );
678
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
688}  // process_remove_thread()
689
690/////////////////////////////////////////////////////
691error_t process_make_exec( exec_info_t  * exec_info )
692{
693    char           * path;                            // pathname to .elf file
694    bool_t           keep_pid;                        // new process keep parent PID if true
695    process_t      * process;                         // local pointer on new process
696    pid_t            pid;                             // new process pid
697    xptr_t           parent_xp;                       // extended pointer on parent process
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
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
705        error_t          error;
706
707        // get .elf pathname, parent_xp, and keep_pid flag from exec_info
708        path      = exec_info->path;
709    parent_xp = exec_info->parent_xp;
710    keep_pid  = exec_info->keep_pid;
711
712process_dmsg("\n[DBG] %s : core[%x,%d] enters for path = %s\n",
713__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, path );
714
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 ) );
719
720    // allocates memory for process descriptor
721        process = process_alloc(); 
722        if( process == NULL ) return -1;
723
724    // get PID
725    if( keep_pid )    // keep parent PID
726    {
727        pid = parent_pid;
728    }
729    else              // get new PID from local cluster
730    {
731        error = cluster_pid_alloc( XPTR( local_cxy , process ) , &pid );
732        if( error ) return -1;
733    }
734
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
738    // initialize the process descriptor as the reference
739    process_reference_init( process , pid , parent_xp );
740
741process_dmsg("\n[DBG] %s : core[%x,%d] initialized process %x / path = %s\n",
742__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, pid, path );
743
744    // initialize vfs_root and vfs_cwd from parent process
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;
748
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
754    process_fd_remote_copy( XPTR( local_cxy  , &process->fd_array ),
755                            XPTR( parent_cxy , &parent_ptr->fd_array) );
756
757process_dmsg("\n[DBG] %s :  core[%x,%d] copied fd_array for process %x\n",
758__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, pid );
759
760    // register "code" and "data" vsegs as well as the process entry-point in VMM,
761    // using information contained in the elf file.
762        error = elf_load_process( path , process );
763
764        if( error )
765        {
766                printk("\n[ERROR] in %s : failed to access .elf file for process %x / path = %s\n",
767                       __FUNCTION__, pid , path );
768        process_destroy( process );
769        return error;
770        }
771
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 );
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
780    attr.attributes = PT_ATTR_DETACH | PT_ATTR_CLUSTER_DEFINED | PT_ATTR_CORE_DEFINED;
781    attr.cxy        = local_cxy;
782    attr.lid        = lid;
783
784    // create and initialize thread descriptor
785        error = thread_user_create( pid,
786                                (void *)process->vmm.entry_point,
787                                exec_info->args_pointers,
788                                &attr,
789                                &thread );
790        if( error )
791        {
792                printk("\n[ERROR] in %s : cannot create thread for process %x / path = %s\n",
793                       __FUNCTION__, pid , path );
794        process_destroy( process );
795        return error;
796        }
797
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  );
800
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
806    // activate new thread
807        thread_unblock( XPTR( local_cxy , thread ) , THREAD_BLOCKED_GLOBAL );
808
809process_dmsg("\n[DBG] %s : core[%x,%d] exit for path = %s\n",
810__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, path  );
811
812        return 0;
813
814}  // end process_make_exec()
815
816//////////////////////////
817void process_init_create()
818{
819    exec_info_t   exec_info;     // structure to be passed to process_make_exec()
820    xptr_t        parent_xp;     // extended pointer on parent process.
821    error_t       error;
822
823process_dmsg("\n[DBG] %s : enters in cluster %x\n", 
824__FUNCTION__ , local_cxy );
825
826    // parent process is local kernel process
827    parent_xp = XPTR( local_cxy , &process_zero );
828
829    // initialize the exec_info structure
830    exec_info.keep_pid     = false;
831    exec_info.parent_xp    = parent_xp;
832    strcpy( exec_info.path , CONFIG_PROCESS_INIT_PATH );
833    exec_info.args_nr      = 0;
834    exec_info.envs_nr      = 0;
835
836    // initialize process_init and create thread_init
837        error = process_make_exec( &exec_info );
838
839        if( error ) panic("cannot initialize process_init in cluster %x", local_cxy );
840
841process_dmsg("\n[DBG] %s : exit in cluster %x\n", 
842__FUNCTION__ , local_cxy );
843               
844    hal_fence();
845
846}  // end process_init_create()
847
Note: See TracBrowser for help on using the repository browser.