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

Last change on this file since 46 was 23, checked in by alain, 8 years ago

Introduce syscalls.

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