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

Last change on this file since 415 was 415, checked in by alain, 9 years ago

Few bugs.

File size: 48.4 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 <hal_irqmask.h>
31#include <errno.h>
32#include <printk.h>
33#include <memcpy.h>
34#include <bits.h>
35#include <kmem.h>
36#include <page.h>
37#include <vmm.h>
38#include <vfs.h>
39#include <core.h>
40#include <thread.h>
41#include <list.h>
42#include <string.h>
43#include <scheduler.h>
44#include <remote_spinlock.h>
45#include <dqdt.h>
46#include <cluster.h>
47#include <ppm.h>
48#include <boot_info.h>
49#include <process.h>
50#include <elf.h>
51#include <syscalls.h>
52#include <signal.h>
53
54//////////////////////////////////////////////////////////////////////////////////////////
55// Extern global variables
56//////////////////////////////////////////////////////////////////////////////////////////
57
58extern process_t process_zero;
59
60//////////////////////////////////////////////////////////////////////////////////////////
61// Process initialisation related functions
62//////////////////////////////////////////////////////////////////////////////////////////
63
64///////////////////////////
65process_t * process_alloc()
66{
67 kmem_req_t req;
68
69 req.type = KMEM_PROCESS;
70 req.size = sizeof(process_t);
71 req.flags = AF_KERNEL;
72
73 return (process_t *)kmem_alloc( &req );
74}
75
76////////////////////////////////////////
77void process_free( process_t * process )
78{
79 kmem_req_t req;
80
81 req.type = KMEM_PROCESS;
82 req.ptr = process;
83 kmem_free( &req );
84}
85
86/////////////////////////////////////////////
87void process_zero_init( process_t * process )
88{
89 // initialize PID, PPID anf PREF
90 process->pid = 0;
91 process->ppid = 0;
92 process->ref_xp = XPTR( local_cxy , process );
93
94 // reset th_tbl[] array as empty
95 uint32_t i;
96 for( i = 0 ; i < CONFIG_THREAD_MAX_PER_CLUSTER ; i++ )
97 {
98 process->th_tbl[i] = NULL;
99 }
100 process->th_nr = 0;
101 spinlock_init( &process->th_lock );
102
103 hal_fence();
104
105process_dmsg("\n[DBG] %s : core[%x,%d] exit for process %x\n",
106__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , process->pid );
107
108} // end process_zero_init()
109
110/////////////////////////////////////////////////
111void process_reference_init( process_t * process,
112 pid_t pid,
113 pid_t ppid,
114 xptr_t model_xp )
115{
116 cxy_t model_cxy;
117 process_t * model_ptr;
118 error_t error1;
119 error_t error2;
120 error_t error3;
121 xptr_t stdin_xp;
122 xptr_t stdout_xp;
123 xptr_t stderr_xp;
124 uint32_t stdin_id;
125 uint32_t stdout_id;
126 uint32_t stderr_id;
127 error_t error;
128
129process_dmsg("\n[DBG] %s : core[%x,%d] enters for process %x / ppid = %x\n",
130__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , pid , ppid );
131
132 // get model process cluster and local pointer
133 model_cxy = GET_CXY( model_xp );
134 model_ptr = (process_t *)GET_PTR( model_xp );
135
136 // initialize PID, PPID, and REF
137 process->pid = pid;
138 process->ppid = ppid;
139 process->ref_xp = XPTR( local_cxy , process );
140
141 // initialize vmm as empty
142 error = vmm_init( process );
143 assert( (error == 0) , __FUNCTION__ , "cannot initialize VMM\n" );
144
145
146process_dmsg("\n[DBG] %s : core[%x,%d] / vmm empty for process %x\n",
147__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , pid );
148
149 // initialize fd_array as empty
150 process_fd_init( process );
151
152 // create stdin / stdout / stderr pseudo-files
153 if( ppid == 0 ) // process_init
154 {
155 error1 = vfs_open( process,
156 CONFIG_INIT_STDIN,
157 O_RDONLY,
158 0, // FIXME chmod
159 &stdin_xp,
160 &stdin_id );
161
162 error2 = vfs_open( process,
163 CONFIG_INIT_STDOUT,
164 O_WRONLY,
165 0, // FIXME chmod
166 &stdout_xp,
167 &stdout_id );
168
169 error3 = vfs_open( process,
170 CONFIG_INIT_STDERR,
171 O_WRONLY,
172 0, // FIXME chmod
173 &stderr_xp,
174 &stderr_id );
175 }
176 else // any other process
177 {
178 error1 = vfs_open( process,
179 CONFIG_USER_STDIN,
180 O_RDONLY,
181 0, // FIXME chmod
182 &stdin_xp,
183 &stdin_id );
184
185 error2 = vfs_open( process,
186 CONFIG_USER_STDOUT,
187 O_WRONLY,
188 0, // FIXME chmod
189 &stdout_xp,
190 &stdout_id );
191
192 error3 = vfs_open( process,
193 CONFIG_USER_STDERR,
194 O_WRONLY,
195 0, // FIXME chmod
196 &stderr_xp,
197 &stderr_id );
198 }
199
200 assert( ((error1 == 0) && (error2 == 0) && (error3 == 0)) , __FUNCTION__ ,
201 "cannot open stdin/stdout/stderr pseudo files\n");
202
203 assert( ((stdin_id == 0) && (stdout_id == 1) && (stderr_id == 2)) , __FUNCTION__ ,
204 "bad indexes : stdin %d / stdout %d / stderr %d \n", stdin_id , stdout_id , stderr_id );
205
206 // initialize specific inodes root and cwd
207 process->vfs_root_xp = (xptr_t)hal_remote_lwd( XPTR( model_cxy,
208 &model_ptr->vfs_root_xp ) );
209 process->vfs_cwd_xp = (xptr_t)hal_remote_lwd( XPTR( model_cxy,
210 &model_ptr->vfs_cwd_xp ) );
211 vfs_inode_remote_up( process->vfs_root_xp );
212 vfs_inode_remote_up( process->vfs_cwd_xp );
213
214 remote_rwlock_init( XPTR( local_cxy , &process->cwd_lock ) );
215
216 // copy all open file descriptors (other than stdin / stdout / stderr)
217 process_fd_remote_copy( XPTR( local_cxy , &process->fd_array ),
218 XPTR( model_cxy , &model_ptr->fd_array ) );
219
220process_dmsg("\n[DBG] %s : core[%x,%d] / fd array for process %x\n",
221__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , pid );
222
223 // reset children list root
224 xlist_root_init( XPTR( local_cxy , &process->children_root ) );
225 process->children_nr = 0;
226
227 // reset semaphore / mutex / barrier / condvar list roots
228 xlist_root_init( XPTR( local_cxy , &process->sem_root ) );
229 xlist_root_init( XPTR( local_cxy , &process->mutex_root ) );
230 xlist_root_init( XPTR( local_cxy , &process->barrier_root ) );
231 xlist_root_init( XPTR( local_cxy , &process->condvar_root ) );
232 remote_spinlock_init( XPTR( local_cxy , &process->sync_lock ) );
233
234 // register new process in the local cluster manager pref_tbl[]
235 lpid_t lpid = LPID_FROM_PID( pid );
236 LOCAL_CLUSTER->pmgr.pref_tbl[lpid] = XPTR( local_cxy , process );
237
238 // register new process descriptor in local cluster manager local_list
239 cluster_process_local_link( process );
240
241 // register new process descriptor in local cluster manager copies_list
242 cluster_process_copies_link( process );
243
244 // reset th_tbl[] array as empty in process descriptor
245 uint32_t i;
246 for( i = 0 ; i < CONFIG_THREAD_MAX_PER_CLUSTER ; i++ )
247 {
248 process->th_tbl[i] = NULL;
249 }
250 process->th_nr = 0;
251 spinlock_init( &process->th_lock );
252
253 hal_fence();
254
255process_dmsg("\n[DBG] %s : core[%x,%d] exit for process %x\n",
256__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , pid );
257
258} // process_reference init()
259
260/////////////////////////////////////////////////////
261error_t process_copy_init( process_t * local_process,
262 xptr_t reference_process_xp )
263{
264 error_t error;
265
266 // get reference process cluster and local pointer
267 cxy_t ref_cxy = GET_CXY( reference_process_xp );
268 process_t * ref_ptr = (process_t *)GET_PTR( reference_process_xp );
269
270 // set the pid, ppid, ref_xp fields in local process
271 local_process->pid = hal_remote_lw( XPTR( ref_cxy , &ref_ptr->pid ) );
272 local_process->ppid = hal_remote_lw( XPTR( ref_cxy , &ref_ptr->ppid ) );
273 local_process->ref_xp = reference_process_xp;
274
275process_dmsg("\n[DBG] %s : core[%x,%d] enters for process %x in cluster %x\n",
276__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , local_process->pid );
277
278 // reset local process vmm
279 error = vmm_init( local_process );
280 assert( (error == 0) , __FUNCTION__ , "cannot initialize VMM\n");
281
282 // reset process file descriptors array
283 process_fd_init( local_process );
284
285 // reset vfs_root_xp / vfs_bin_xp / vfs_cwd_xp fields
286 local_process->vfs_root_xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->vfs_root_xp ) );
287 local_process->vfs_bin_xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->vfs_bin_xp ) );
288 local_process->vfs_cwd_xp = XPTR_NULL;
289
290 // reset children list root (not used in a process descriptor copy)
291 xlist_root_init( XPTR( local_cxy , &local_process->children_root ) );
292 local_process->children_nr = 0;
293
294 // reset brothers list (not used in a process descriptor copy)
295 xlist_entry_init( XPTR( local_cxy , &local_process->brothers_list ) );
296
297 // reset semaphores list root (not used in a process descriptor copy)
298 xlist_root_init( XPTR( local_cxy , &local_process->sem_root ) );
299 xlist_root_init( XPTR( local_cxy , &local_process->mutex_root ) );
300 xlist_root_init( XPTR( local_cxy , &local_process->barrier_root ) );
301 xlist_root_init( XPTR( local_cxy , &local_process->condvar_root ) );
302
303 // reset th_tbl[] array as empty
304 uint32_t i;
305 for( i = 0 ; i < CONFIG_THREAD_MAX_PER_CLUSTER ; i++ )
306 {
307 local_process->th_tbl[i] = NULL;
308 }
309 local_process->th_nr = 0;
310 spinlock_init( &local_process->th_lock );
311
312 // register new process descriptor in local cluster manager local_list
313 cluster_process_local_link( local_process );
314
315 // register new process descriptor in owner cluster manager copies_list
316 cluster_process_copies_link( local_process );
317
318 hal_fence();
319
320process_dmsg("\n[DBG] %s : core[%x,%d] exit for process %x in cluster %x\n",
321__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , local_process->pid );
322
323 return 0;
324
325} // end process_copy_init()
326
327///////////////////////////////////////////
328void process_destroy( process_t * process )
329{
330 if( process->th_nr != 0 )
331 {
332 panic("process %x in cluster %x has still active threads",
333 process->pid , local_cxy );
334 }
335
336 // get local process manager pointer
337 pmgr_t * pmgr = &LOCAL_CLUSTER->pmgr;
338
339 // get the lock protecting the list of local process descriptors
340 remote_spinlock_lock( XPTR( local_cxy , &pmgr->local_lock ) );
341
342 // remove the process descriptor from local_list in local cluster manager
343 xlist_unlink( XPTR( local_cxy , &process->local_list ) );
344
345 // release the lock protecting the list of local process descriptors
346 remote_spinlock_unlock( XPTR( local_cxy , &pmgr->local_lock ) );
347
348 // get extended pointer on copies_lock in owner cluster manager
349 cxy_t owner_cxy = CXY_FROM_PID( process->pid );
350 lpid_t lpid = LPID_FROM_PID( process->pid );
351 xptr_t copies_lock = XPTR( owner_cxy , &pmgr->copies_lock[lpid] );
352
353 // remove the local process descriptor from copies_list
354 remote_spinlock_lock( copies_lock );
355 xlist_unlink( XPTR( local_cxy , &process->copies_list ) );
356 remote_spinlock_unlock( copies_lock );
357
358 hal_fence();
359
360 // From this point, the process descriptor is unreachable
361
362 // FIXME close all open files and update dirty [AG]
363
364 // Decrease refcount for bin file, root file and cwd file
365 if( process->vfs_bin_xp != XPTR_NULL ) vfs_file_count_down( process->vfs_bin_xp );
366 if( process->vfs_root_xp != XPTR_NULL ) vfs_file_count_down( process->vfs_root_xp );
367 if( process->vfs_cwd_xp != XPTR_NULL ) vfs_file_count_down( process->vfs_cwd_xp );
368
369 // Destroy VMM
370 vmm_destroy( process );
371
372 process_dmsg("\n[DBG] %s for pid %d / page_faults = %d\n",
373 __FUNCTION__ , process->pid, process->vmm.pgfault_nr );
374
375} // end process_destroy()
376
377/////////////////////////////////////////////////
378char * process_action_str( uint32_t action_type )
379{
380 if ( action_type == BLOCK_ALL_THREADS ) return "BLOCK";
381 else if( action_type == UNBLOCK_ALL_THREADS ) return "UNBLOCK";
382 else if( action_type == DELETE_ALL_THREADS ) return "DELETE";
383 else return "undefined";
384}
385
386////////////////////////////////////////////
387void process_sigaction( process_t * process,
388 uint32_t action_type )
389{
390 cxy_t owner_cxy; // owner cluster identifier
391 lpid_t lpid; // process index in owner cluster
392 cluster_t * cluster; // pointer on cluster manager
393 xptr_t root_xp; // extended pointer on root of copies
394 xptr_t lock_xp; // extended pointer on lock protecting copies
395 xptr_t client_xp; // extended pointer on client thread
396 uint32_t rsp_count; // number of expected responses
397 xptr_t rsp_xp; // extended pointer on responses counter
398 xptr_t iter_xp; // iterator on copies list
399 xptr_t process_xp; // extended pointer on process copy
400 cxy_t process_cxy; // process copy cluster identifier
401 process_t * process_ptr; // local pointer on process copy
402
403sigaction_dmsg("\n[DBG] %s : enter for signal %s to process %x in cluster %x\n",
404__FUNCTION__ , process_action_str( action_type ) , process , local_cxy );
405
406 thread_t * this = CURRENT_THREAD;
407
408 // get extended pointer on client thread and response counter
409 client_xp = XPTR( local_cxy , this );
410 rsp_xp = XPTR( local_cxy , &rsp_count );
411
412 // get owner cluster identifier and process lpid
413 owner_cxy = CXY_FROM_PID( process->pid );
414 lpid = LPID_FROM_PID( process->pid );
415
416 assert( (owner_cxy == local_cxy) , __FUNCTION__ , "illegal cluster\n" );
417
418 // get local pointer on local cluster manager
419 cluster = LOCAL_CLUSTER;
420
421 // get extended pointers on copies root, copies lock, and number of copies
422 root_xp = XPTR( local_cxy , &cluster->pmgr.copies_root[lpid] );
423 lock_xp = XPTR( local_cxy , &cluster->pmgr.copies_lock[lpid] );
424
425 // initialize responses number
426 rsp_count = cluster->pmgr.copies_nr[lpid];
427
428 // take the lock protecting the copies
429 remote_spinlock_lock( lock_xp );
430
431 // send RPCs to all process copies
432 XLIST_FOREACH( root_xp , iter_xp )
433 {
434 process_xp = XLIST_ELEMENT( iter_xp , process_t , copies_list );
435 process_cxy = GET_CXY( process_xp );
436 process_ptr = (process_t *)GET_PTR( process_xp );
437
438sigaction_dmsg("\n[DBG] %s : process = %x / pid = %x / ppid = %x\n",
439__FUNCTION__ , process_ptr , process_ptr->pid , process_ptr->ppid );
440
441 rpc_process_sigaction_client( process_cxy,
442 process_ptr,
443 action_type,
444 rsp_xp,
445 client_xp );
446 }
447
448 // release the lock protecting process copies
449 remote_spinlock_unlock( lock_xp );
450
451 // block and deschedule to wait response
452 thread_block( CURRENT_THREAD , THREAD_BLOCKED_RPC );
453 sched_yield("BLOCKED on RPC");
454
455sigaction_dmsg("\n[DBG] %s : exit for signal %s to process %x in cluster %x\n",
456__FUNCTION__ , process_action_str( action_type ) , process , local_cxy );
457
458} // end process_sigaction()
459
460////////////////////////////////////////
461void process_block( process_t * process,
462 xptr_t rsp_xp,
463 xptr_t client_xp )
464{
465 thread_t * target; // pointer on target thread
466 uint32_t ltid; // index in process th_tbl
467 thread_t * killer; // killer thread pointer
468 uint32_t count; // requests counter
469 volatile uint32_t sig_rsp_count; // responses counter
470 cxy_t client_cxy; // client thread cluster identifier
471 thread_t * client_ptr; // client thread pointer
472 core_t * client_core; // client thread core pointer
473
474 // get local killer thread pointer
475 killer = CURRENT_THREAD;
476
477sigaction_dmsg("\n[DBG] %s : enter for process %x in cluster %x\n",
478__FUNCTION__ , process->pid , local_cxy );
479
480 // get lock protecting process th_tbl[]
481 spinlock_lock( &process->th_lock );
482
483 // initialize local responses counter
484 sig_rsp_count = process->th_nr;
485
486 // loop on process threads to block and deschedule all threads in cluster
487 // we use both "ltid" and "count" because it can exist "holes" in th_tbl
488 for( ltid = 0 , count = 0 ; count < process->th_nr ; ltid++ )
489 {
490 target = process->th_tbl[ltid];
491
492 if( target != NULL ) // thread found
493 {
494 count++;
495
496 // set signal in target thread descriptor
497 thread_set_signal( target , (uint32_t *)sig_rsp_count );
498
499 // set the global blocked bit in target thread descriptor.
500 thread_block( target , THREAD_BLOCKED_GLOBAL );
501
502 // - if the killer thread and the target thread are not on the same core
503 // we want the scheduler of target thread to acknowlege the signal
504 // to be sure that the target thread is descheduled
505 // - if the killer thread and the target thread are on the same core
506 // we simply decrement the response counter.
507 if( killer->core->lid != target->core->lid )
508 {
509 dev_pic_send_ipi( local_cxy , target->core->lid );
510 }
511 else
512 {
513 hal_atomic_add( (void *)&sig_rsp_count , -1 );
514 }
515 }
516 }
517
518 // poll the reponses counter
519 while( 1 )
520 {
521 // exit loop when all responses received
522 if ( sig_rsp_count == 0 ) break;
523
524 // wait 1000 cycles before retry
525 hal_fixed_delay( 1000 );
526 }
527
528 // acknowledge client thread & unblock client thread if last response
529 client_cxy = GET_CXY( client_xp );
530 client_ptr = (thread_t *)GET_PTR( client_xp );
531 client_core = (core_t *)hal_remote_lpt( XPTR( client_cxy , &client_ptr->core ) );
532 if( hal_remote_atomic_add( rsp_xp , -1 ) == 1 )
533 {
534 thread_unblock( client_xp , THREAD_BLOCKED_RPC);
535 dev_pic_send_ipi( client_cxy , client_core->lid );
536 }
537
538sigaction_dmsg("\n[DBG] %s : exit for process %x in cluster %x / %d threads blocked\n",
539__FUNCTION__ , process->pid , local_cxy , count );
540
541} // end process_block()
542
543//////////////////////////////////////////
544void process_unblock( process_t * process,
545 xptr_t rsp_xp,
546 xptr_t client_xp )
547{
548 thread_t * target; // pointer on target thead
549 uint32_t ltid; // index in process th_tbl
550 thread_t * killer; // killer thread pointer
551 uint32_t req_count; // requests counter
552 cxy_t client_cxy; // client thread cluster identifier
553 thread_t * client_ptr; // client thread pointer
554 core_t * client_core; // client thread core pointer
555
556 // get local killer thread pointer
557 killer = CURRENT_THREAD;
558
559sigaction_dmsg("\n[DBG] %s : enter for process %x in cluster %x\n",
560__FUNCTION__ , process->pid , local_cxy );
561
562 // get lock protecting process th_tbl[]
563 spinlock_lock( &process->th_lock );
564
565 // loop on process threads to unblock all threads in cluster
566 // we use both "ltid" and "req_count" because it can exist "holes" in th_tbl
567 for( ltid = 0 , req_count = 0 ;
568 req_count < process->th_nr ;
569 ltid++ )
570 {
571 target = process->th_tbl[ltid];
572
573 if( target != NULL ) // thread found
574 {
575 req_count++;
576
577 // reset the global blocked bit in target thread descriptor.
578 thread_unblock( XPTR( local_cxy , target ) , THREAD_BLOCKED_GLOBAL );
579 }
580 }
581
582 // acknowledge client thread & unblock client thread if last response
583 client_cxy = GET_CXY( client_xp );
584 client_ptr = (thread_t *)GET_PTR( client_xp );
585 client_core = (core_t *)hal_remote_lpt( XPTR( client_cxy , &client_ptr->core ) );
586 if( hal_remote_atomic_add( rsp_xp , -1 ) == 1 )
587 {
588 thread_unblock( client_xp , THREAD_BLOCKED_RPC);
589 dev_pic_send_ipi( client_cxy , client_core->lid );
590 }
591
592sigaction_dmsg("\n[DBG] %s : exit for process %x in cluster %x / %d threads blocked\n",
593__FUNCTION__ , process->pid , local_cxy , req_count );
594
595} // end process_unblock()
596
597/////////////////////////////////////////
598void process_delete( process_t * process,
599 xptr_t rsp_xp,
600 xptr_t client_xp )
601{
602 thread_t * thread; // pointer on target thread
603 uint32_t ltid; // index in process th_tbl
604 uint32_t count; // request counter
605 pid_t pid; // process PID
606 cxy_t client_cxy; // client thread cluster identifier
607 thread_t * client_ptr; // client thread pointer
608 core_t * client_core; // client thread core pointer
609
610 // get process PID
611 pid = process->pid;
612
613sigaction_dmsg("\n[DBG] %s : enter for process %x in cluster %x at cycle %d\n",
614__FUNCTION__ , pid , local_cxy , (uint32_t)hal_get_cycles() );
615
616 // loop on threads to release memory allocated to threads
617 for( ltid = 0 , count = 0 ; count < process->th_nr ; ltid++ )
618 {
619 thread = process->th_tbl[ltid];
620
621 if( thread != NULL ) // thread found
622 {
623 count++;
624
625 // detach thread from parent if attached
626 if( (thread->flags & THREAD_FLAG_DETACHED) == 0 )
627 thread_child_parent_unlink( thread->parent , XPTR( local_cxy , thread ) );
628
629 // detach thread from process
630 process_remove_thread( thread );
631
632 // remove thread from scheduler
633 sched_remove_thread( thread );
634
635 // release memory allocated to thread
636 thread_destroy( thread );
637 }
638 }
639
640 // release memory allocated to process descriptors
641 // for all clusters other than the owner cluster
642 if( local_cxy != CXY_FROM_PID( process->pid ) ) process_destroy( process );
643
644 // acknowledge client thread & unblock client thread if last response
645 client_cxy = GET_CXY( client_xp );
646 client_ptr = (thread_t *)GET_PTR( client_xp );
647 client_core = (core_t *)hal_remote_lpt( XPTR( client_cxy , &client_ptr->core ) );
648 if( hal_remote_atomic_add( rsp_xp , -1 ) == 1 )
649 {
650 thread_unblock( client_xp , THREAD_BLOCKED_RPC);
651 dev_pic_send_ipi( client_cxy , client_core->lid );
652 }
653
654sigaction_dmsg("\n[DBG] %s : exit for process %x in cluster %x at cycle %d\n",
655__FUNCTION__ , pid , local_cxy , (uint32_t)hal_get_cycles() );
656
657} // end process_delete()
658
659///////////////////////////////////////////////
660process_t * process_get_local_copy( pid_t pid )
661{
662 error_t error;
663 process_t * process_ptr; // local pointer on process
664 xptr_t process_xp; // extended pointer on process
665
666 cluster_t * cluster = LOCAL_CLUSTER;
667
668 // get lock protecting local list of processes
669 remote_spinlock_lock( XPTR( local_cxy , &cluster->pmgr.local_lock ) );
670
671 // scan the local list of process descriptors to find the process
672 xptr_t iter;
673 bool_t found = false;
674 XLIST_FOREACH( XPTR( local_cxy , &cluster->pmgr.local_root ) , iter )
675 {
676 process_xp = XLIST_ELEMENT( iter , process_t , local_list );
677 process_ptr = (process_t *)GET_PTR( process_xp );
678 if( process_ptr->pid == pid )
679 {
680 found = true;
681 break;
682 }
683 }
684
685 // release lock protecting local list of processes
686 remote_spinlock_unlock( XPTR( local_cxy , &cluster->pmgr.local_lock ) );
687
688 // allocate memory for a new local process descriptor
689 // and initialise it from reference cluster if required
690 if( !found )
691 {
692 // get extended pointer on reference process descriptor
693 xptr_t ref_xp = cluster_get_reference_process_from_pid( pid );
694
695 assert( (ref_xp != XPTR_NULL) , __FUNCTION__ , "illegal pid\n" );
696
697 // allocate memory for local process descriptor
698 process_ptr = process_alloc();
699 if( process_ptr == NULL ) return NULL;
700
701 // initialize local process descriptor copy
702 error = process_copy_init( process_ptr , ref_xp );
703 if( error ) return NULL;
704 }
705
706 return process_ptr;
707
708} // end process_get_local_copy()
709
710//////////////////////////////////////////////////////////////////////////////////////////
711// File descriptor array related functions
712//////////////////////////////////////////////////////////////////////////////////////////
713
714///////////////////////////////////////////
715void process_fd_init( process_t * process )
716{
717 uint32_t fd;
718
719 remote_spinlock_init( XPTR( local_cxy , &process->fd_array.lock ) );
720
721 process->fd_array.current = 0;
722
723 // initialize array
724 for ( fd = 0 ; fd < CONFIG_PROCESS_FILE_MAX_NR ; fd++ )
725 {
726 process->fd_array.array[fd] = XPTR_NULL;
727 }
728}
729
730//////////////////////////////
731bool_t process_fd_array_full()
732{
733 // get extended pointer on reference process
734 xptr_t ref_xp = CURRENT_THREAD->process->ref_xp;
735
736 // get reference process cluster and local pointer
737 process_t * ref_ptr = (process_t *)GET_PTR( ref_xp );
738 cxy_t ref_cxy = GET_CXY( ref_xp );
739
740 // get number of open file descriptors from reference fd_array
741 uint32_t current = hal_remote_lw( XPTR( ref_cxy , &ref_ptr->fd_array.current ) );
742
743 return ( current >= CONFIG_PROCESS_FILE_MAX_NR );
744}
745
746/////////////////////////////////////////////////
747error_t process_fd_register( process_t * process,
748 xptr_t file_xp,
749 uint32_t * fdid )
750{
751 bool_t found;
752 uint32_t id;
753 xptr_t xp;
754
755 // get reference process cluster and local pointer
756 xptr_t ref_xp = process->ref_xp;
757 process_t * ref_ptr = (process_t *)GET_PTR( ref_xp );
758 cxy_t ref_cxy = GET_CXY( ref_xp );
759
760 // take lock protecting reference fd_array
761 remote_spinlock_lock( XPTR( ref_cxy , &ref_ptr->fd_array.lock ) );
762
763 found = false;
764
765 for ( id = 0; id < CONFIG_PROCESS_FILE_MAX_NR ; id++ )
766 {
767 xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->fd_array.array[id] ) );
768 if ( xp == XPTR_NULL )
769 {
770 found = true;
771 hal_remote_swd( XPTR( ref_cxy , &ref_ptr->fd_array.array[id] ) , file_xp );
772 hal_remote_atomic_add( XPTR( ref_cxy , &ref_ptr->fd_array.current ) , 1 );
773 *fdid = id;
774 break;
775 }
776 }
777
778 // release lock protecting reference fd_array
779 remote_spinlock_unlock( XPTR( ref_cxy , &ref_ptr->fd_array.lock ) );
780
781 if ( !found ) return EMFILE;
782 else return 0;
783}
784
785////////////////////////////////////////////////
786xptr_t process_fd_get_xptr( process_t * process,
787 uint32_t fdid )
788{
789 xptr_t file_xp;
790
791 // access local copy of process descriptor
792 file_xp = process->fd_array.array[fdid];
793
794 if( file_xp == XPTR_NULL )
795 {
796 // get reference process cluster and local pointer
797 xptr_t ref_xp = process->ref_xp;
798 cxy_t ref_cxy = GET_CXY( ref_xp );
799 process_t * ref_ptr = (process_t *)GET_PTR( ref_xp );
800
801 // access reference process descriptor
802 file_xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->fd_array.array[fdid] ) );
803
804 // update local fd_array if found
805 if( file_xp != XPTR_NULL )
806 {
807 process->fd_array.array[fdid] = file_xp;
808 }
809 }
810
811 return file_xp;
812
813} // end process_fd_get_xptr()
814
815///////////////////////////////////////////
816void process_fd_remote_copy( xptr_t dst_xp,
817 xptr_t src_xp )
818{
819 uint32_t fd;
820 xptr_t entry;
821
822 // get cluster and local pointer for src fd_array
823 cxy_t src_cxy = GET_CXY( src_xp );
824 fd_array_t * src_ptr = (fd_array_t *)GET_PTR( src_xp );
825
826 // get cluster and local pointer for dst fd_array
827 cxy_t dst_cxy = GET_CXY( dst_xp );
828 fd_array_t * dst_ptr = (fd_array_t *)GET_PTR( dst_xp );
829
830 // get the remote lock protecting the src fd_array
831 remote_spinlock_lock( XPTR( src_cxy , &src_ptr->lock ) );
832
833 // loop on all entries other than
834 // the three first entries: stdin/stdout/stderr
835 for( fd = 3 ; fd < CONFIG_PROCESS_FILE_MAX_NR ; fd++ )
836 {
837 entry = (xptr_t)hal_remote_lwd( XPTR( src_cxy , &src_ptr->array[fd] ) );
838
839 if( entry != XPTR_NULL )
840 {
841 // increment file descriptor ref count
842 vfs_file_count_up( entry );
843
844 // copy entry in destination process fd_array
845 hal_remote_swd( XPTR( dst_cxy , &dst_ptr->array[fd] ) , entry );
846 }
847 }
848
849 // release lock on source process fd_array
850 remote_spinlock_unlock( XPTR( src_cxy , &src_ptr->lock ) );
851
852} // end process_fd_remote_copy()
853
854////////////////////////////////////////////////////////////////////////////////////
855// Thread related functions
856////////////////////////////////////////////////////////////////////////////////////
857
858/////////////////////////////////////////////////////
859error_t process_register_thread( process_t * process,
860 thread_t * thread,
861 trdid_t * trdid )
862{
863 ltid_t ltid;
864 bool_t found;
865
866 assert( (process != NULL) , __FUNCTION__ , "process argument is NULL" );
867
868 assert( (thread != NULL) , __FUNCTION__ , "thread argument is NULL" );
869
870 // search a free slot in th_tbl[]
871 // 0 is not a valid ltid value
872 found = false;
873 for( ltid = 1 ; ltid < CONFIG_THREAD_MAX_PER_CLUSTER ; ltid++ )
874 {
875 if( process->th_tbl[ltid] == NULL )
876 {
877 found = true;
878 break;
879 }
880 }
881
882 if( found )
883 {
884 // register thread in th_tbl[]
885 process->th_tbl[ltid] = thread;
886 process->th_nr++;
887
888 // returns trdid
889 *trdid = TRDID( local_cxy , ltid );
890 }
891
892 return (found) ? 0 : ENOMEM;
893
894} // end process_register_thread()
895
896///////////////////////////////////////////////
897void process_remove_thread( thread_t * thread )
898{
899 assert( (thread != NULL) , __FUNCTION__ , "thread argument is NULL" );
900
901 process_t * process = thread->process;
902
903 // get thread local index
904 ltid_t ltid = LTID_FROM_TRDID( thread->trdid );
905
906 // remove thread from th_tbl[]
907 process->th_tbl[ltid] = NULL;
908 process->th_nr--;
909
910} // process_remove_thread()
911
912/////////////////////////////////////////////////////////
913error_t process_make_fork( xptr_t parent_process_xp,
914 xptr_t parent_thread_xp,
915 pid_t * child_pid,
916 thread_t ** child_thread )
917{
918 process_t * process; // local pointer on child process descriptor
919 thread_t * thread; // local pointer on child thread descriptor
920 pid_t new_pid; // process identifier for child process
921 pid_t parent_pid; // process identifier for parent process
922 xptr_t ref_xp; // extended pointer on reference process
923 error_t error;
924
925 // get cluster and local pointer for parent process
926 cxy_t parent_process_cxy = GET_CXY( parent_process_xp );
927 process_t * parent_process_ptr = (process_t *)GET_PTR( parent_process_xp );
928
929 // get parent process PID
930 parent_pid = hal_remote_lw( XPTR( parent_process_cxy , &parent_process_ptr->pid ) );
931
932 // check parent process is the reference
933 ref_xp = hal_remote_lwd( XPTR( parent_process_cxy , &parent_process_ptr->ref_xp ) );
934 assert( (parent_process_xp == ref_xp ) , __FUNCTION__ ,
935 "parent process must be the reference process\n" );
936
937fork_dmsg("\n[DBG] %s : core[%x,%d] enter at cycle %d\n",
938__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid , (uint32_t)hal_get_cycles() );
939
940 // allocate a process descriptor
941 process = process_alloc();
942 if( process == NULL )
943 {
944 printk("\n[ERROR] in %s : cannot get process in cluster %x\n",
945 __FUNCTION__, local_cxy );
946 return -1;
947 }
948
949fork_dmsg("\n[DBG] %s : core[%x,%d] child process descriptor allocated at cycle %d\n",
950 __FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, (uint32_t)hal_get_cycles() );
951
952 // allocate a child PID from local cluster
953 error = cluster_pid_alloc( XPTR( local_cxy , process ) , &new_pid );
954 if( (error != 0) || (new_pid == 0) )
955 {
956 printk("\n[ERROR] in %s : cannot get PID in cluster %x\n",
957 __FUNCTION__, local_cxy );
958 process_free( process );
959 return -1;
960 }
961
962fork_dmsg("\n[DBG] %s : core[%x, %d] child process PID allocated = %x at cycle %d\n",
963 __FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, new_pid , (uint32_t)hal_get_cycles() );
964
965 // initializes child process descriptor from parent process descriptor
966 process_reference_init( process,
967 new_pid,
968 parent_pid,
969 parent_process_xp );
970
971fork_dmsg("\n[DBG] %s : core[%x, %d] child process initialised at cycle %d\n",
972__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, hal_get_cycles() );
973
974 // copy VMM from parent descriptor to child descriptor
975 error = vmm_fork_copy( process,
976 parent_process_xp );
977 if( error )
978 {
979 printk("\n[ERROR] in %s : cannot copy VMM in cluster %x\n",
980 __FUNCTION__, local_cxy );
981 process_free( process );
982 cluster_pid_release( new_pid );
983 return -1;
984 }
985
986fork_dmsg("\n[DBG] %s : core[%x, %d] child process VMM copied at cycle %d\n",
987__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, (uint32_t)hal_get_cycles() );
988
989 // create child thread descriptor from parent thread descriptor
990 error = thread_user_fork( parent_thread_xp,
991 process,
992 &thread );
993 if( error )
994 {
995 printk("\n[ERROR] in %s : cannot create thread in cluster %x\n",
996 __FUNCTION__, local_cxy );
997 process_free( process );
998 cluster_pid_release( new_pid );
999 return -1;
1000 }
1001
1002fork_dmsg("\n[DBG] %s : core[%x,%d] child thread created at cycle %d\n",
1003__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, (uint32_t)hal_get_cycles() );
1004
1005 // update parent process GPT to set Copy_On_Write for shared data vsegs
1006 // this includes all replicated GPT copies
1007 if( parent_process_cxy == local_cxy ) // reference is local
1008 {
1009 vmm_set_cow( parent_process_ptr );
1010 }
1011 else // reference is remote
1012 {
1013 rpc_vmm_set_cow_client( parent_process_cxy,
1014 parent_process_ptr );
1015 }
1016
1017fork_dmsg("\n[DBG] %s : core[%x,%d] COW set in parent_process at cycle %d\n",
1018__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, (uint32_t)hal_get_cycles() );
1019
1020 // update children list in parent process
1021 xlist_add_last( XPTR( parent_process_cxy , &parent_process_ptr->children_root ),
1022 XPTR( local_cxy , &process->brothers_list ) );
1023 hal_remote_atomic_add( XPTR( parent_process_cxy,
1024 &parent_process_ptr->children_nr), 1 );
1025
1026// vmm_display( process , true );
1027// vmm_display( parent_process_ptr , true );
1028// sched_display( 0 );
1029
1030 // return success
1031 *child_thread = thread;
1032 *child_pid = new_pid;
1033
1034fork_dmsg("\n[DBG] %s : core[%x,%d] exit at cycle %d\n",
1035__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, (uint32_t)hal_get_cycles() );
1036
1037 return 0;
1038
1039} // end process_make_fork()
1040
1041/* deprecated because we don't wand to destroy the existing process descriptor
1042
1043/////////////////////////////////////////////////////
1044error_t process_make_exec( exec_info_t * exec_info )
1045{
1046 char * path; // pathname to .elf file
1047 process_t * old; // local pointer on old process
1048 process_t * new; // local pointer on new process
1049 pid_t pid; // old process identifier
1050 thread_t * thread; // pointer on new thread
1051 pthread_attr_t attr; // main thread attributes
1052 lid_t lid; // selected core local index
1053 error_t error;
1054
1055 // get .elf pathname and PID from exec_info
1056 path = exec_info->path;
1057 pid = exec_info->pid;
1058
1059 // check local cluster is process owner
1060 assert( (CXY_FROM_PID( pid ) == local_cxy), __FUNCTION__,
1061 "local cluster %x is not owner for process %x\n", local_cxy, pid );
1062
1063exec_dmsg("\n[DBG] %s : core[%x,%d] enters for process %x / path = %s\n",
1064__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, pid , path );
1065
1066 // get old process local pointer
1067 old = (process_t *)cluster_get_local_process_from_pid( pid );
1068
1069 assert( (old != NULL ) , __FUNCTION__ ,
1070 "process %x not found in cluster %x\n", pid , local_cxy );
1071
1072 // allocate memory for new process descriptor
1073 new = process_alloc();
1074
1075 // initialize new process descriptor
1076 process_reference_init( new,
1077 old->pid, // same as old
1078 old->ppid, // same as old
1079 XPTR( local_cxy , old ) );
1080
1081exec_dmsg("\n[DBG] %s : core[%x,%d] created new process %x / path = %s\n",
1082__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, pid, path );
1083
1084 // register "code" and "data" vsegs as well as entry-point
1085 // in new process VMM, using information contained in the elf file.
1086 if( elf_load_process( path , new ) )
1087 {
1088 printk("\n[ERROR] in %s : failed to access .elf file for process %x / path = %s\n",
1089 __FUNCTION__, pid , path );
1090 process_destroy( new );
1091 return -1;
1092 }
1093
1094exec_dmsg("\n[DBG] %s : core[%x,%d] vsegs registered / path = %s\n",
1095__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, path );
1096
1097 // select a core in local cluster to execute the main thread
1098 lid = cluster_select_local_core();
1099
1100 // initialize pthread attributes for main thread
1101 attr.attributes = PT_ATTR_DETACH | PT_ATTR_CLUSTER_DEFINED | PT_ATTR_CORE_DEFINED;
1102 attr.cxy = local_cxy;
1103 attr.lid = lid;
1104
1105 // create and initialize thread descriptor
1106 error = thread_user_create( pid,
1107 (void *)new->vmm.entry_point,
1108 exec_info->args_pointers,
1109 &attr,
1110 &thread );
1111 if( error )
1112 {
1113 printk("\n[ERROR] in %s : cannot create thread for process %x / path = %s\n",
1114 __FUNCTION__, pid , path );
1115 process_destroy( new );
1116 return -1;
1117 }
1118
1119exec_dmsg("\n[DBG] %s : core[%x,%d] created main thread %x for new process %x\n",
1120__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, thread->trdid, pid );
1121
1122 // update children list (rooted in parent process)
1123 xlist_replace( XPTR( local_cxy , &old->brothers_list ) ,
1124 XPTR( local_cxy , &new->brothers_list ) );
1125
1126 // request destruction of old process copies and threads in all clusters
1127 process_sigaction( old , SIGKILL );
1128
1129 // activate new thread
1130 thread_unblock( XPTR( local_cxy , thread ) , THREAD_BLOCKED_GLOBAL );
1131
1132exec_dmsg("\n[DBG] %s : core[%x,%d] exit for path = %s\n",
1133__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, path );
1134
1135 return 0;
1136
1137} // end process_make_exec()
1138
1139*/
1140
1141/////////////////////////////////////////////////////
1142error_t process_make_exec( exec_info_t * exec_info )
1143{
1144 char * path; // pathname to .elf file
1145 process_t * process; // local pointer on old process
1146 pid_t pid; // old process identifier
1147 thread_t * thread; // pointer on new main thread
1148 pthread_attr_t attr; // main thread attributes
1149 lid_t lid; // selected core local index
1150 error_t error;
1151
1152 // get .elf pathname and PID from exec_info
1153 path = exec_info->path;
1154 pid = exec_info->pid;
1155
1156 // check local cluster is process owner
1157 assert( (CXY_FROM_PID( pid ) == local_cxy), __FUNCTION__,
1158 "local cluster %x is not owner for process %x\n", local_cxy, pid );
1159
1160exec_dmsg("\n[DBG] %s : core[%x,%d] enters for process %x / path = %s\n",
1161__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, pid , path );
1162
1163 // get process local pointer
1164 process = (process_t *)cluster_get_local_process_from_pid( pid );
1165
1166 assert( (process != NULL ) , __FUNCTION__ ,
1167 "process %x not found in cluster %x\n", pid , local_cxy );
1168
1169 // reset the existing vmm
1170 vmm_destroy( process );
1171
1172exec_dmsg("\n[DBG] %s : core[%x,%d] VMM cleared\n",
1173__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid );
1174
1175 // block all existing process threads
1176 process_sigaction( process , BLOCK_ALL_THREADS );
1177
1178 // kill all existing threads and process descriptors (other than owner)
1179 process_sigaction( process , DELETE_ALL_THREADS );
1180
1181 // check no threads
1182 assert( (process->th_nr == 0) , __FUNCTION__ , "no threads at this point" );
1183
1184exec_dmsg("\n[DBG] %s : core[%x,%d] all threads deleted\n",
1185__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid );
1186
1187 // initialize VMM
1188 error = vmm_init( process );
1189 {
1190 printk("\n[ERROR] in %s : cannot initialize VMM for process %x / path = %s\n",
1191 __FUNCTION__, pid , path );
1192 process_destroy( process );
1193 return -1;
1194 }
1195
1196 if( error )
1197
1198 // register "code" and "data" vsegs as well as entry-point and vfs_bin_xp
1199 // in VMM, using information contained in the elf file.
1200 error = elf_load_process( path , process );
1201
1202 if( error )
1203 {
1204 printk("\n[ERROR] in %s : failed to access .elf file for process %x / path = %s\n",
1205 __FUNCTION__, pid , path );
1206 process_destroy( process );
1207 return -1;
1208 }
1209
1210exec_dmsg("\n[DBG] %s : core[%x,%d] new vsegs registered / path = %s\n",
1211__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, path );
1212
1213// @@@
1214vmm_display( process , true );
1215// @@@
1216
1217 // select a core in local cluster to execute the new main thread
1218 lid = cluster_select_local_core();
1219
1220 // initialize pthread attributes for new main thread
1221 attr.attributes = PT_ATTR_DETACH | PT_ATTR_CLUSTER_DEFINED | PT_ATTR_CORE_DEFINED;
1222 attr.cxy = local_cxy;
1223 attr.lid = lid;
1224
1225 // create and initialize thread descriptor
1226 error = thread_user_create( pid,
1227 (void *)process->vmm.entry_point,
1228 exec_info->args_pointers,
1229 &attr,
1230 &thread );
1231 if( error )
1232 {
1233 printk("\n[ERROR] in %s : cannot create thread for process %x / path = %s\n",
1234 __FUNCTION__, pid , path );
1235 process_destroy( process );
1236 return -1;
1237 }
1238
1239exec_dmsg("\n[DBG] %s : core[%x,%d] created main thread %x for new process %x\n",
1240__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, thread->trdid, pid );
1241
1242 // activate new thread
1243 thread_unblock( XPTR( local_cxy , thread ) , THREAD_BLOCKED_GLOBAL );
1244
1245exec_dmsg("\n[DBG] %s : core[%x,%d] exit for path = %s\n",
1246__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, path );
1247
1248 return 0;
1249
1250} // end process_make_exec()
1251
1252////////////////////////////////////////////
1253void process_make_kill( process_t * process,
1254 uint32_t sig_id )
1255{
1256 // this function must be executed by a thread running in owner cluster
1257 assert( (CXY_FROM_PID( process->pid ) == local_cxy) , __FUNCTION__ ,
1258 "must execute in owner cluster" );
1259
1260 // analyse signal type
1261 switch( sig_id )
1262 {
1263 case SIGSTOP: // block all threads
1264 {
1265 process_sigaction( process , BLOCK_ALL_THREADS );
1266 }
1267 break;
1268 case SIGCONT: // unblock all threads
1269 {
1270 process_sigaction( process , UNBLOCK_ALL_THREADS );
1271 }
1272 break;
1273 case SIGKILL: // block all threads, then delete all threads
1274 {
1275 process_sigaction( process , BLOCK_ALL_THREADS );
1276 process_sigaction( process , DELETE_ALL_THREADS );
1277 process_destroy( process );
1278 }
1279 break;
1280 }
1281} // end process_make_kill()
1282
1283////////////////////////////////////////////
1284void process_make_exit( process_t * process,
1285 uint32_t status )
1286{
1287 // this function must be executed by a thread running in owner cluster
1288 assert( (CXY_FROM_PID( process->pid ) == local_cxy) , __FUNCTION__ ,
1289 "must execute in owner cluster" );
1290
1291 // block all threads in all clusters
1292 process_sigaction( process , BLOCK_ALL_THREADS );
1293
1294 // delete all threads in all clusters
1295 process_sigaction( process , DELETE_ALL_THREADS );
1296
1297 // delete local process descriptor
1298 process_destroy( process );
1299
1300} // end process_make_exit()
1301
1302//////////////////////////
1303void process_init_create()
1304{
1305 process_t * process; // local pointer on process_init descriptor
1306 pid_t pid; // process_init identifier
1307 thread_t * thread; // local pointer on main thread
1308 pthread_attr_t attr; // main thread attributes
1309 lid_t lid; // selected core local index for main thread
1310 error_t error;
1311
1312kinit_dmsg("\n[DBG] %s : core[%x,%d] enters\n",
1313__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid );
1314
1315 // allocates memory for process descriptor from local cluster
1316 process = process_alloc();
1317 if( process == NULL )
1318 {
1319 printk("\n[PANIC] in %s : no memory for process descriptor in cluster %x\n",
1320 __FUNCTION__, local_cxy );
1321 }
1322
1323 // get PID from local cluster
1324 error = cluster_pid_alloc( XPTR( local_cxy , process ) , &pid );
1325 if( error )
1326 {
1327 printk("\n[PANIC] in %s : cannot allocate PID in cluster %x\n",
1328 __FUNCTION__, local_cxy );
1329 process_destroy( process );
1330 }
1331
1332 assert( (LPID_FROM_PID(pid) == 1) , __FUNCTION__ , "LPID must be 1 for process_init" );
1333
1334 // initialize process descriptor / parent is local process_zero
1335 process_reference_init( process,
1336 pid,
1337 0,
1338 XPTR( local_cxy , &process_zero ) );
1339
1340kinit_dmsg("\n[DBG] %s : core[%x,%d] / process initialised\n",
1341__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid );
1342
1343 // register "code" and "data" vsegs as well as entry-point
1344 // in process VMM, using information contained in the elf file.
1345 if( elf_load_process( CONFIG_PROCESS_INIT_PATH , process ) )
1346 {
1347 printk("\n[PANIC] in %s : cannot access .elf file / path = %s\n",
1348 __FUNCTION__, CONFIG_PROCESS_INIT_PATH );
1349 process_destroy( process );
1350 }
1351
1352kinit_dmsg("\n[DBG] %s : core[%x,%d] vsegs registered / path = %s\n",
1353__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, CONFIG_PROCESS_INIT_PATH );
1354
1355 // select a core in local cluster to execute the main thread
1356 lid = cluster_select_local_core();
1357
1358 // initialize pthread attributes for main thread
1359 attr.attributes = PT_ATTR_DETACH | PT_ATTR_CLUSTER_DEFINED | PT_ATTR_CORE_DEFINED;
1360 attr.cxy = local_cxy;
1361 attr.lid = lid;
1362
1363 // create and initialize thread descriptor
1364 error = thread_user_create( pid,
1365 (void *)process->vmm.entry_point,
1366 NULL,
1367 &attr,
1368 &thread );
1369 if( error )
1370 {
1371 printk("\n[PANIC] in %s : cannot create main thread / path = %s\n",
1372 __FUNCTION__, CONFIG_PROCESS_INIT_PATH );
1373 process_destroy( process );
1374 }
1375
1376 // activate thread
1377 thread_unblock( XPTR( local_cxy , thread ) , THREAD_BLOCKED_GLOBAL );
1378
1379 hal_fence();
1380
1381kinit_dmsg("\n[DBG] %s : core[%x,%d] exit / main thread = %x\n",
1382__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, thread );
1383
1384} // end process_init_create()
1385
Note: See TracBrowser for help on using the repository browser.