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

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

Fix several bugs in the fork() syscall.

File size: 32.8 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_zero_init( process_t * process )
86{
87    // initialize PID, PPID anf PREF
88    process->pid    = 0;
89    process->ppid   = 0;
90    process->ref_xp = XPTR( local_cxy , process );
91
92    // reset th_tbl[] array as empty
93    uint32_t i;
94    for( i = 0 ; i < CONFIG_THREAD_MAX_PER_CLUSTER ; i++ )
95        {
96        process->th_tbl[i] = NULL;
97    }
98    process->th_nr  = 0;
99    spinlock_init( &process->th_lock );
100
101        hal_fence();
102
103process_dmsg("\n[DBG] %s : core[%x,%d] exit for process %x\n",
104__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , process->pid );
105
106}  // end process_zero_init()
107
108/////////////////////////////////////////////////
109void process_reference_init( process_t * process,
110                             pid_t       pid,
111                             pid_t       ppid,
112                             xptr_t      model_xp )
113{
114    cxy_t       model_cxy;
115    process_t * model_ptr;
116        error_t     error1;
117        error_t     error2;
118        error_t     error3;
119    xptr_t      stdin_xp;
120    xptr_t      stdout_xp;
121    xptr_t      stderr_xp;
122    uint32_t    stdin_id;
123    uint32_t    stdout_id;
124    uint32_t    stderr_id;
125
126process_dmsg("\n[DBG] %s : core[%x,%d] enters for process %x\n",
127__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , pid );
128
129    // get model process cluster and local pointer
130    model_cxy = GET_CXY( model_xp );
131    model_ptr = (process_t *)GET_PTR( model_xp );
132
133    // initialize PID, PPID, and REF
134        process->pid    = pid;
135    process->ppid   = ppid;
136    process->ref_xp = XPTR( local_cxy , process );
137
138    // initialize vmm
139    vmm_init( process );
140
141process_dmsg("\n[DBG] %s : core[%x,%d] / vmm empty for process %x\n", 
142__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , pid );
143
144    // initialize fd_array (not for kernel)
145    process_fd_init( process );
146
147    // create stdin / stdout / stderr pseudo-files
148    if( ppid == 0 )                                        // process_init
149    {
150        error1 = vfs_open( process,
151                           CONFIG_INIT_STDIN,
152                           O_RDONLY, 
153                           0,                // FIXME chmod
154                           &stdin_xp, 
155                           &stdin_id );
156
157        error2 = vfs_open( process,
158                           CONFIG_INIT_STDOUT,
159                           O_WRONLY, 
160                           0,                // FIXME chmod
161                           &stdout_xp, 
162                           &stdout_id );
163
164        error3 = vfs_open( process,
165                           CONFIG_INIT_STDERR,
166                           O_WRONLY, 
167                           0,                // FIXME chmod
168                           &stderr_xp, 
169                           &stderr_id );
170    }
171    else                                                  // other user process
172    {
173        error1 = vfs_open( process,
174                           CONFIG_USER_STDIN,
175                           O_RDONLY, 
176                           0,                // FIXME chmod
177                           &stdin_xp, 
178                           &stdin_id );
179
180        error2 = vfs_open( process,
181                           CONFIG_USER_STDOUT,
182                           O_WRONLY, 
183                           0,                // FIXME chmod
184                           &stdout_xp, 
185                           &stdout_id );
186
187        error3 = vfs_open( process,
188                           CONFIG_USER_STDERR,
189                           O_WRONLY, 
190                           0,                // FIXME chmod
191                           &stderr_xp, 
192                           &stderr_id );
193    }
194
195    assert( ((error1 == 0) && (error2 == 0) && (error3 == 0)) , __FUNCTION__ ,
196    "cannot open stdin/stdout/stderr pseudo files\n");
197
198    assert( ((stdin_id == 0) && (stdout_id == 1) && (stderr_id == 2)) , __FUNCTION__ ,
199    "bad indexes : stdin %d / stdout %d / stderr %d \n", stdin_id , stdout_id , stderr_id );
200
201    // initialize specific files, cwd_lock, and fd_array
202    process->vfs_root_xp = (xptr_t)hal_remote_lwd( XPTR( model_cxy,
203                                                         &model_ptr->vfs_root_xp ) );
204    process->vfs_cwd_xp  = (xptr_t)hal_remote_lwd( XPTR( model_cxy,
205                                                         &model_ptr->vfs_cwd_xp ) );
206    process->vfs_bin_xp  = (xptr_t)hal_remote_lwd( XPTR( model_cxy,
207                                                         &model_ptr->vfs_bin_xp ) );
208    vfs_file_count_up( process->vfs_root_xp );
209    vfs_file_count_up( process->vfs_cwd_xp );
210    vfs_file_count_up( process->vfs_bin_xp );
211
212    process_fd_remote_copy( XPTR( local_cxy , &process->fd_array ),
213                            XPTR( model_cxy , &model_ptr->fd_array ) );
214
215    remote_rwlock_init( XPTR( local_cxy , &process->cwd_lock ) );
216
217process_dmsg("\n[DBG] %s : core[%x,%d] / fd array initialised for process %x\n", 
218__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , pid );
219
220    // reset children list root
221    xlist_root_init( XPTR( local_cxy , &process->children_root ) );
222    process->children_nr     = 0;
223
224    // reset semaphore / mutex / barrier / condvar list roots
225    xlist_root_init( XPTR( local_cxy , &process->sem_root ) );
226    xlist_root_init( XPTR( local_cxy , &process->mutex_root ) );
227    xlist_root_init( XPTR( local_cxy , &process->barrier_root ) );
228    xlist_root_init( XPTR( local_cxy , &process->condvar_root ) );
229    remote_spinlock_init( XPTR( local_cxy , &process->sync_lock ) );
230
231    // register new process in the local cluster manager pref_tbl[]
232    lpid_t lpid = LPID_FROM_PID( pid );
233    LOCAL_CLUSTER->pmgr.pref_tbl[lpid] = XPTR( local_cxy , process );
234
235    // register new process descriptor in local cluster manager local_list
236    cluster_process_local_link( process );
237
238    // register new process descriptor in local cluster manager copies_list
239    cluster_process_copies_link( process );
240
241    // reset th_tbl[] array as empty in process descriptor
242    uint32_t i;
243    for( i = 0 ; i < CONFIG_THREAD_MAX_PER_CLUSTER ; i++ )
244        {
245        process->th_tbl[i] = NULL;
246    }
247    process->th_nr  = 0;
248    spinlock_init( &process->th_lock );
249
250        hal_fence();
251
252process_dmsg("\n[DBG] %s : core[%x,%d] exit for process %x\n",
253__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , pid );
254
255}  // process_reference init()
256
257/////////////////////////////////////////////////////
258error_t process_copy_init( process_t * local_process,
259                           xptr_t      reference_process_xp )
260{
261    // get reference process cluster and local pointer
262    cxy_t       ref_cxy = GET_CXY( reference_process_xp );
263    process_t * ref_ptr = (process_t *)GET_PTR( reference_process_xp );
264
265    // set the pid, ppid, ref_xp fields in local process
266    local_process->pid    = hal_remote_lw( XPTR( ref_cxy , &ref_ptr->pid ) );
267    local_process->ppid   = hal_remote_lw( XPTR( ref_cxy , &ref_ptr->ppid ) );
268    local_process->ref_xp = reference_process_xp;
269
270process_dmsg("\n[DBG] %s : core[%x,%d] enters for process %x in cluster %x\n",
271__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , local_process->pid );
272
273    // reset local process vmm
274    vmm_init( local_process );
275
276    // reset process file descriptors array
277        process_fd_init( local_process );
278
279    // reset vfs_root_xp / vfs_bin_xp / vfs_cwd_xp fields
280    local_process->vfs_root_xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->vfs_root_xp ) );
281    local_process->vfs_bin_xp  = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->vfs_bin_xp ) );
282    local_process->vfs_cwd_xp  = XPTR_NULL;
283
284    // reset children list root (not used in a process descriptor copy)
285    xlist_root_init( XPTR( local_cxy , &local_process->children_root ) );
286    local_process->children_nr   = 0;
287
288    // reset brothers list (not used in a process descriptor copy)
289    xlist_entry_init( XPTR( local_cxy , &local_process->brothers_list ) );
290
291    // reset semaphores list root (not used in a process descriptor copy)
292    xlist_root_init( XPTR( local_cxy , &local_process->sem_root ) );
293    xlist_root_init( XPTR( local_cxy , &local_process->mutex_root ) );
294    xlist_root_init( XPTR( local_cxy , &local_process->barrier_root ) );
295    xlist_root_init( XPTR( local_cxy , &local_process->condvar_root ) );
296
297    // reset th_tbl[] array as empty
298    uint32_t i;
299    for( i = 0 ; i < CONFIG_THREAD_MAX_PER_CLUSTER ; i++ )
300        {
301        local_process->th_tbl[i] = NULL;
302    }
303    local_process->th_nr  = 0;
304    spinlock_init( &local_process->th_lock );
305
306    // register new process descriptor in local cluster manager local_list
307    cluster_process_local_link( local_process );
308
309    // register new process descriptor in owner cluster manager copies_list
310    cluster_process_copies_link( local_process );
311
312    // initialize signal manager TODO [AG]
313
314        hal_fence();
315
316process_dmsg("\n[DBG] %s : core[%x,%d] exit for process %x in cluster %x\n",
317__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , local_process->pid );
318
319    return 0;
320
321} // end process_copy_init()
322
323///////////////////////////////////////////
324void process_destroy( process_t * process )
325{
326        if( process->th_nr != 0 )
327    {
328        panic("process %x in cluster %x has still active threads",
329              process->pid , local_cxy );
330    }
331
332    // get local process manager pointer
333    pmgr_t * pmgr = &LOCAL_CLUSTER->pmgr;
334
335    // get the lock protecting the list of local process descriptors
336    remote_spinlock_lock( XPTR( local_cxy , &pmgr->local_lock ) );
337
338    // remove the process descriptor from local_list in local cluster manager
339    xlist_unlink( XPTR( local_cxy , &process->local_list ) );
340
341    // release the lock protecting the list of local process descriptors
342    remote_spinlock_unlock( XPTR( local_cxy , &pmgr->local_lock ) );
343
344    // get extended pointer on copies_lock in owner cluster manager
345    cxy_t  owner_cxy    = CXY_FROM_PID( process->pid );
346        lpid_t lpid         = LPID_FROM_PID( process->pid );
347    xptr_t copies_lock  = XPTR( owner_cxy , &pmgr->copies_lock[lpid] );
348
349    // remove the local process descriptor from copies_list
350    remote_spinlock_lock( copies_lock );
351    xlist_unlink( XPTR( local_cxy , &process->copies_list ) );
352    remote_spinlock_unlock( copies_lock );
353
354    // synchronize memory
355        hal_fence();
356
357    // From this point, the process descriptor is unreachable
358
359    // close all open files and update dirty TODO [AG]
360
361    // release signal manager TODO [AG]
362
363    // Decrease refcount for bin file, root file and cwd file
364        if( process->vfs_bin_xp  != XPTR_NULL ) vfs_file_count_down( process->vfs_bin_xp );
365        if( process->vfs_root_xp != XPTR_NULL ) vfs_file_count_down( process->vfs_root_xp );
366        if( process->vfs_cwd_xp  != XPTR_NULL ) vfs_file_count_down( process->vfs_cwd_xp );
367
368    // Destroy VMM
369    vmm_destroy( process );
370
371        process_dmsg("\n[DBG] %s for pid %d / page_faults = %d\n",
372                 __FUNCTION__ , process->pid, process->vmm.pgfault_nr );
373
374}  // end process_destroy()
375
376////////////////////////////////////////
377void process_kill( process_t * process )
378{
379    thread_t     * thread;    // pointer on current thead descriptor
380    uint32_t       ltid;      // index in process th_tbl
381    uint32_t       count;     // thread counter
382
383printk("\n[@@@] %s enter\n", __FUNCTION__ );
384
385    // get lock protecting th_tbl[]
386    spinlock_lock( &process->th_lock );
387
388    // first loop on threads to send the THREAD_SIG_KILL signal to all process threads
389    // we use both "ltid" and "count" indexes, because it can exist "holes" in th_tbl
390    for( ltid = 0 , count = 0  ;
391         (ltid < CONFIG_THREAD_MAX_PER_CLUSTER) && (count < process->th_nr) ;
392         ltid++ )
393    {
394        thread = process->th_tbl[ltid];
395
396        if( thread != NULL )
397        {
398            thread_kill( thread );
399            count++;
400        }
401    }
402
403printk("\n[@@@] %s : %d signal(s) sent\n", __FUNCTION__, count );
404
405    // second loop on threads to wait acknowledge from scheduler,
406    // unlink thread from process and parent thread, and release thread descriptor
407    for( ltid = 0 , count = 0  ;
408         (ltid < CONFIG_THREAD_MAX_PER_CLUSTER) && (count < process->th_nr) ;
409         ltid++ )
410    {
411        thread = process->th_tbl[ltid];
412
413        if( thread != NULL )
414        {
415
416printk("\n[@@@] %s start polling at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
417
418            // poll the THREAD_SIG_KILL bit until reset
419            while( thread->signals & THREAD_SIG_KILL ) asm volatile( "nop" );
420
421printk("\n[@@@] %s exit polling\n", __FUNCTION__ );
422
423            // detach target thread from parent if attached
424            if( (thread->flags & THREAD_FLAG_DETACHED) != 0 ) 
425            thread_child_parent_unlink( thread->parent , XPTR( local_cxy , thread ) );
426
427            // unlink thread from process
428            process_remove_thread( thread );
429
430            // release memory for thread descriptor
431            thread_destroy( thread );
432
433            count++;
434        }
435    }
436
437printk("\n[@@@] %s : %d ack(s) received\n", __FUNCTION__, count );
438
439    // release lock protecting th_tbl[]
440    spinlock_unlock( &process->th_lock );
441
442    // release memory allocated for process descriptor
443    process_destroy( process );
444
445printk("\n[DBG] %s : core[%x,%d] exit\n",
446__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid );
447
448}  // end process_kill()
449
450///////////////////////////////////////////////
451process_t * process_get_local_copy( pid_t pid )
452{
453    error_t        error;
454    process_t    * process_ptr;   // local pointer on process
455    xptr_t         process_xp;    // extended pointer on process
456
457    cluster_t * cluster = LOCAL_CLUSTER;
458
459    // get lock protecting local list of processes
460    remote_spinlock_lock( XPTR( local_cxy , &cluster->pmgr.local_lock ) );
461
462    // scan the local list of process descriptors to find the process
463    xptr_t  iter;
464    bool_t  found = false;
465    XLIST_FOREACH( XPTR( local_cxy , &cluster->pmgr.local_root ) , iter )
466    {
467        process_xp  = XLIST_ELEMENT( iter , process_t , local_list );
468        process_ptr = (process_t *)GET_PTR( process_xp );
469        if( process_ptr->pid == pid )
470        {
471            found = true;
472            break;
473        }
474    }
475
476    // release lock protecting local list of processes
477    remote_spinlock_unlock( XPTR( local_cxy , &cluster->pmgr.local_lock ) );
478
479    // allocate memory for a new local process descriptor
480    // and initialise it from reference cluster if required
481    if( !found )
482    {
483        // get extended pointer on reference process descriptor
484        xptr_t ref_xp = cluster_get_reference_process_from_pid( pid );
485
486        assert( (ref_xp != XPTR_NULL) , __FUNCTION__ , "illegal pid\n" );
487
488        // allocate memory for local process descriptor
489        process_ptr = process_alloc();
490        if( process_ptr == NULL )  return NULL;
491
492        // initialize local process descriptor copy
493        error = process_copy_init( process_ptr , ref_xp );
494        if( error ) return NULL;
495    }
496
497    return process_ptr;
498}
499
500//////////////////////////////////////////////////////////////////////////////////////////
501// File descriptor array related functions
502//////////////////////////////////////////////////////////////////////////////////////////
503
504///////////////////////////////////////////
505void process_fd_init( process_t * process )
506{
507    uint32_t fd;
508
509    remote_spinlock_init( XPTR( local_cxy , &process->fd_array.lock ) );
510
511    process->fd_array.current = 0;
512
513    // initialize array
514    for ( fd = 0 ; fd < CONFIG_PROCESS_FILE_MAX_NR ; fd++ )
515    {
516        process->fd_array.array[fd] = XPTR_NULL;
517    }
518}
519
520//////////////////////////////
521bool_t process_fd_array_full()
522{
523    // get extended pointer on reference process
524    xptr_t ref_xp = CURRENT_THREAD->process->ref_xp;
525
526    // get reference process cluster and local pointer
527    process_t * ref_ptr = (process_t *)GET_PTR( ref_xp );
528    cxy_t       ref_cxy = GET_CXY( ref_xp );
529
530    // get number of open file descriptors from reference fd_array
531    uint32_t current = hal_remote_lw( XPTR( ref_cxy , &ref_ptr->fd_array.current ) );
532
533        return ( current >= CONFIG_PROCESS_FILE_MAX_NR );
534}
535
536/////////////////////////////////////////////////
537error_t process_fd_register( process_t * process,
538                             xptr_t      file_xp,
539                             uint32_t  * fdid )
540{
541    bool_t    found;
542    uint32_t  id;
543    xptr_t    xp;
544
545    // get reference process cluster and local pointer
546    xptr_t ref_xp = process->ref_xp;
547    process_t * ref_ptr = (process_t *)GET_PTR( ref_xp );
548    cxy_t       ref_cxy = GET_CXY( ref_xp );
549
550    // take lock protecting reference fd_array
551        remote_spinlock_lock( XPTR( ref_cxy , &ref_ptr->fd_array.lock ) );
552
553    found   = false;
554
555    for ( id = 0; id < CONFIG_PROCESS_FILE_MAX_NR ; id++ )
556    {
557        xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->fd_array.array[id] ) );
558        if ( xp == XPTR_NULL )
559        {
560            found = true;
561            hal_remote_swd( XPTR( ref_cxy , &ref_ptr->fd_array.array[id] ) , file_xp );
562                hal_remote_atomic_add( XPTR( ref_cxy , &ref_ptr->fd_array.current ) , 1 );
563                        *fdid = id;
564            break;
565        }
566    }
567
568    // release lock protecting reference fd_array
569        remote_spinlock_unlock( XPTR( ref_cxy , &ref_ptr->fd_array.lock ) );
570
571    if ( !found ) return EMFILE;
572    else          return 0;
573}
574
575////////////////////////////////////////////////
576xptr_t process_fd_get_xptr( process_t * process,
577                            uint32_t    fdid )
578{
579    xptr_t  file_xp;
580
581    // access local copy of process descriptor
582    file_xp = process->fd_array.array[fdid];
583
584    if( file_xp == XPTR_NULL )
585    {
586        // get reference process cluster and local pointer
587        xptr_t      ref_xp  = process->ref_xp;
588        cxy_t       ref_cxy = GET_CXY( ref_xp );
589        process_t * ref_ptr = (process_t *)GET_PTR( ref_xp );
590
591        // access reference process descriptor
592        file_xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->fd_array.array[fdid] ) );
593
594        // update local fd_array if found
595        if( file_xp != XPTR_NULL )
596        {
597            process->fd_array.array[fdid] = file_xp;
598        }
599    }
600
601    return file_xp;
602
603}  // end process_fd_get_xptr()
604
605///////////////////////////////////////////
606void process_fd_remote_copy( xptr_t dst_xp,
607                             xptr_t src_xp )
608{
609    uint32_t fd;
610    xptr_t   entry;
611
612    // get cluster and local pointer for src fd_array
613    cxy_t        src_cxy = GET_CXY( src_xp );
614    fd_array_t * src_ptr = (fd_array_t *)GET_PTR( src_xp );
615
616    // get cluster and local pointer for dst fd_array
617    cxy_t        dst_cxy = GET_CXY( dst_xp );
618    fd_array_t * dst_ptr = (fd_array_t *)GET_PTR( dst_xp );
619
620    // get the remote lock protecting the src fd_array
621        remote_spinlock_lock( XPTR( src_cxy , &src_ptr->lock ) );
622
623    // loop on all entries in source process fd_array
624    for( fd = 0 ; fd < CONFIG_PROCESS_FILE_MAX_NR ; fd++ )
625        {
626                entry = (xptr_t)hal_remote_lwd( XPTR( src_cxy , &src_ptr->array[fd] ) );
627
628                if( entry != XPTR_NULL )
629                {
630            // increment file descriptor ref count
631            vfs_file_count_up( entry );
632
633                        // copy entry in destination process fd_array
634                        hal_remote_swd( XPTR( dst_cxy , &dst_ptr->array[fd] ) , entry );
635                }
636        }
637
638    // release lock on source process fd_array
639        remote_spinlock_unlock( XPTR( src_cxy , &src_ptr->lock ) );
640
641}  // end process_fd_remote_copy()
642
643////////////////////////////////////////////////////////////////////////////////////
644//  Thread related functions
645////////////////////////////////////////////////////////////////////////////////////
646
647/////////////////////////////////////////////////////
648error_t process_register_thread( process_t * process,
649                                 thread_t  * thread,
650                                 trdid_t   * trdid )
651{
652    ltid_t   ltid;
653    bool_t   found;
654
655    assert( (process != NULL) , __FUNCTION__ , "process argument is NULL" );
656
657    assert( (thread != NULL) , __FUNCTION__ , "thread argument is NULL" );
658
659    // search a free slot in th_tbl[]
660    // 0 is not a valid ltid value
661    found = false;
662    for( ltid = 1 ; ltid < CONFIG_THREAD_MAX_PER_CLUSTER ; ltid++ )
663    {
664        if( process->th_tbl[ltid] == NULL )
665        {
666            found = true;
667            break;
668        }
669    }
670
671    if( found )
672    {
673        // register thread in th_tbl[]
674        process->th_tbl[ltid] = thread;
675        process->th_nr++;
676
677        // returns trdid
678        *trdid = TRDID( local_cxy , ltid );
679    }
680
681    return (found) ? 0 : ENOMEM;
682
683}  // end process_register_thread()
684
685///////////////////////////////////////////////
686void process_remove_thread( thread_t * thread )
687{
688    assert( (thread != NULL) , __FUNCTION__ , "thread argument is NULL" );
689
690    process_t * process = thread->process;
691
692    // get thread local index
693    ltid_t  ltid = LTID_FROM_TRDID( thread->trdid );
694
695    // remove thread from th_tbl[]
696    process->th_tbl[ltid] = NULL;
697    process->th_nr--;
698
699}  // process_remove_thread()
700
701/////////////////////////////////////////////////////////
702error_t process_make_fork( xptr_t      parent_process_xp,
703                           xptr_t      parent_thread_xp,
704                           pid_t     * child_pid,
705                           thread_t ** child_thread )
706{
707    process_t * process;         // local pointer on child process descriptor
708    thread_t  * thread;          // local pointer on child thread descriptor
709    pid_t       new_pid;         // process identifier for child process
710    pid_t       parent_pid;      // process identifier for parent process
711    xptr_t      ref_xp;          // extended pointer on reference process
712    error_t     error;
713
714    // get cluster and local pointer for parent process
715    cxy_t       parent_process_cxy = GET_CXY( parent_process_xp );
716    process_t * parent_process_ptr = (process_t *)GET_PTR( parent_process_xp );
717
718    // get parent process PID
719    parent_pid = hal_remote_lw( XPTR( parent_process_cxy , &parent_process_ptr->pid ) );
720   
721    // check parent process is the reference
722    ref_xp = hal_remote_lwd( XPTR( parent_process_cxy , &parent_process_ptr->ref_xp ) );
723    assert( (parent_process_xp == ref_xp ) , __FUNCTION__ ,
724    "parent process must be the reference process\n" );
725
726process_dmsg("\n[DBG] %s : core[%x,%d] enter at cycle %d\n",
727__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid , hal_get_cycles() );
728
729    // allocate a process descriptor
730    process = process_alloc();
731    if( process == NULL )
732    {
733        printk("\n[ERROR] in %s : cannot get process in cluster %x\n", 
734        __FUNCTION__, local_cxy ); 
735        return -1;
736    }
737
738process_dmsg("\n[DBG] %s : core[%x,%d] child process descriptor allocated at cycle %d\n",
739 __FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, hal_get_cycles() );
740
741    // allocate a child PID from local cluster
742    error = cluster_pid_alloc( XPTR( local_cxy , process ) , &new_pid );
743    if( (error != 0) || (new_pid == 0) )
744    {
745        printk("\n[ERROR] in %s : cannot get PID in cluster %x\n", 
746        __FUNCTION__, local_cxy ); 
747        process_free( process );
748        return -1;
749    }
750
751process_dmsg("\n[DBG] %s : core[%x, %d] child process PID allocated = %x at cycle %d\n",
752 __FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, new_pid , hal_get_cycles() );
753
754    // initializes child process descriptor from parent process descriptor
755    process_reference_init( process,
756                            new_pid,
757                            parent_pid,
758                            parent_process_xp );
759
760process_dmsg("\n[DBG] %s : core[%x, %d] child process initialised at cycle %d\n",
761__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, hal_get_cycles() );
762
763    // copy VMM from parent descriptor to child descriptor
764    error = vmm_fork_copy( process,
765                           parent_process_xp );
766    if( error )
767    {
768        printk("\n[ERROR] in %s : cannot copy VMM in cluster %x\n", 
769        __FUNCTION__, local_cxy ); 
770        process_free( process );
771        cluster_pid_release( new_pid );
772        return -1;
773    }
774
775process_dmsg("\n[DBG] %s : core[%x, %d] child process VMM copied at cycle %d\n",
776__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, hal_get_cycles() );
777
778    // create child thread descriptor from parent thread descriptor
779    error = thread_user_fork( parent_thread_xp,
780                              process,
781                              &thread );
782    if( error )
783    {
784        printk("\n[ERROR] in %s : cannot create thread in cluster %x\n",
785        __FUNCTION__, local_cxy ); 
786        process_free( process );
787        cluster_pid_release( new_pid );
788        return -1;
789    }
790
791process_dmsg("\n[DBG] %s : core[%x,%d] child thread created at cycle %d\n", 
792__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, hal_get_cycles() );
793
794    // update parent process GPT to set Copy_On_Write for shared data vsegs
795    // this includes all replicated GPT copies
796    if( parent_process_cxy == local_cxy )   // reference is local
797    {
798        vmm_set_cow( parent_process_ptr );
799    }
800    else                                    // reference is remote
801    {
802        rpc_vmm_set_cow_client( parent_process_cxy,
803                                parent_process_ptr );
804    }
805
806process_dmsg("\n[DBG] %s : core[%x,%d] COW set in parent_process at cycle %d\n",
807__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, hal_get_cycles() );
808
809    // update children list in parent process
810        xlist_add_last( XPTR( parent_process_cxy , &parent_process_ptr->children_root ),
811                    XPTR( local_cxy , &process->brothers_list ) );
812        hal_remote_atomic_add( XPTR( parent_process_cxy,
813                                 &parent_process_ptr->children_nr), 1 );
814
815// vmm_display( process , true );
816// vmm_display( parent_process_ptr , true );
817// sched_display( 0 );
818
819    // return success
820    *child_thread = thread;
821    *child_pid    = new_pid;
822
823    return 0;
824
825}  // end process_make_fork()
826
827/////////////////////////////////////////////////////
828error_t process_make_exec( exec_info_t  * exec_info )
829{
830    char           * path;                    // pathname to .elf file
831    process_t      * old;                     // local pointer on old process
832    process_t      * new;                     // local pointer on new process
833    pid_t            pid;                     // old process identifier
834    thread_t       * thread;                  // pointer on new thread
835    pthread_attr_t   attr;                    // main thread attributes
836    lid_t            lid;                     // selected core local index
837        error_t          error;
838
839        // get .elf pathname and PID from exec_info
840        path = exec_info->path;
841    pid  = exec_info->pid;
842
843    // check local cluster is old process owner
844    assert( (CXY_FROM_PID( pid ) == local_cxy), __FUNCTION__,
845    "local cluster %x is not owner for process %x\n", local_cxy, pid );
846
847exec_dmsg("\n[DBG] %s : core[%x,%d] enters for process %x / path = %s\n",
848__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, pid , path );
849
850    // get old process local pointer
851    old = (process_t *)cluster_get_local_process_from_pid( pid );
852   
853    assert( (old != NULL ) , __FUNCTION__ , 
854    "process %x not found in cluster %x\n", pid , local_cxy ); 
855
856    // allocate memory for new process descriptor
857    new = process_alloc();
858
859    // initialize new process descriptor
860    process_reference_init( new,
861                            old->pid,                   // same as old
862                            old->ppid,                  // same as old
863                            XPTR( local_cxy , old ) );
864
865exec_dmsg("\n[DBG] %s : core[%x,%d] created new process %x / path = %s\n",
866__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, pid, path );
867
868    // register "code" and "data" vsegs as well as entry-point
869    // in new process VMM, using information contained in the elf file.
870        if( elf_load_process( path , new ) )
871        {
872                printk("\n[ERROR] in %s : failed to access .elf file for process %x / path = %s\n",
873                __FUNCTION__, pid , path );
874        process_destroy( new );
875        return -1;
876        }
877
878exec_dmsg("\n[DBG] %s : core[%x,%d] registered code/data vsegs / process %x / path = %s\n",
879__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, pid, path );
880
881    // select a core in local cluster to execute the main thread
882    lid  = cluster_select_local_core();
883
884    // initialize pthread attributes for main thread
885    attr.attributes = PT_ATTR_DETACH | PT_ATTR_CLUSTER_DEFINED | PT_ATTR_CORE_DEFINED;
886    attr.cxy        = local_cxy;
887    attr.lid        = lid;
888
889    // create and initialize thread descriptor
890        error = thread_user_create( pid,
891                                (void *)new->vmm.entry_point,
892                                exec_info->args_pointers,
893                                &attr,
894                                &thread );
895        if( error )
896        {
897                printk("\n[ERROR] in %s : cannot create thread for process %x / path = %s\n",
898                       __FUNCTION__, pid , path );
899        process_destroy( new );
900        return -1;
901        }
902
903exec_dmsg("\n[DBG] %s : core[%x,%d] created main thread %x for new process %x\n",
904__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, thread->trdid, pid );
905
906    // update children list (rooted in parent process)
907        xlist_replace( XPTR( local_cxy , &old->brothers_list ) ,
908                   XPTR( local_cxy , &new->brothers_list ) );
909
910    // FIXME request destruction of old process copies and threads in all clusters
911
912    // activate new thread
913        thread_unblock( XPTR( local_cxy , thread ) , THREAD_BLOCKED_GLOBAL );
914
915exec_dmsg("\n[DBG] %s : core[%x,%d] exit for path = %s\n",
916__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, path  );
917
918        return 0;
919
920}  // end process_make_exec()
921
922//////////////////////////
923void process_init_create()
924{
925    exec_info_t   exec_info;     // structure to be passed to process_make_exec()
926    process_t   * process;       // local pointer on process_init descriptor
927    pid_t         pid;           // process_init identifier
928    error_t       error;
929
930process_dmsg("\n[DBG] %s : enters in cluster %x\n", 
931__FUNCTION__ , local_cxy );
932
933    // allocates memory for process descriptor from local cluster
934        process = process_alloc(); 
935        if( process == NULL )
936    {
937                printk("\n[PANIC] in %s : no memory for process descriptor in cluster %x\n",
938                __FUNCTION__, local_cxy );
939    }
940
941    // get new PID from local cluster
942    error = cluster_pid_alloc( XPTR( local_cxy , process ) , &pid );
943    if( error )
944    {
945                printk("\n[PANIC] in %s : cannot allocate PID in cluster %x\n",
946                __FUNCTION__, local_cxy );
947    }
948
949    // initialise the process desciptor (parent is local kernel process)
950    process_reference_init( process, 
951                            pid,
952                            process_zero.pid, 
953                            XPTR( local_cxy , &process_zero ) );
954
955    // initialize the exec_info structure
956    exec_info.pid          = pid;
957    exec_info.args_nr      = 0;
958    exec_info.envs_nr      = 0;
959    strcpy( exec_info.path , CONFIG_PROCESS_INIT_PATH );
960
961    // update process descriptor and create thread descriptor
962        error = process_make_exec( &exec_info );
963
964        if( error )
965    { 
966                printk("\n[PANIC] in %s : cannot exec %s in cluster %x\n",
967                __FUNCTION__, CONFIG_PROCESS_INIT_PATH , local_cxy );
968    }
969
970process_dmsg("\n[DBG] %s : exit in cluster %x\n", 
971__FUNCTION__ , local_cxy );
972               
973    hal_fence();
974
975}  // end process_init_create()
976
Note: See TracBrowser for help on using the repository browser.