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

Last change on this file since 199 was 188, checked in by alain, 7 years ago

Redefine the PIC device API.

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