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

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

Fix various bugs

File size: 69.3 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,2018)
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 <chdev.h>
42#include <list.h>
43#include <string.h>
44#include <scheduler.h>
45#include <remote_spinlock.h>
46#include <dqdt.h>
47#include <cluster.h>
48#include <ppm.h>
49#include <boot_info.h>
50#include <process.h>
51#include <elf.h>
52#include <syscalls.h>
53#include <shared_syscalls.h>
54
55//////////////////////////////////////////////////////////////////////////////////////////
56// Extern global variables
57//////////////////////////////////////////////////////////////////////////////////////////
58
59extern process_t process_zero; // allocated in kernel_init.c
60extern chdev_directory_t chdev_dir; // allocated in kernel_init.c
61
62//////////////////////////////////////////////////////////////////////////////////////////
63// Process initialisation related functions
64//////////////////////////////////////////////////////////////////////////////////////////
65
66///////////////////////////
67process_t * process_alloc()
68{
69 kmem_req_t req;
70
71 req.type = KMEM_PROCESS;
72 req.size = sizeof(process_t);
73 req.flags = AF_KERNEL;
74
75 return (process_t *)kmem_alloc( &req );
76}
77
78////////////////////////////////////////
79void process_free( process_t * process )
80{
81 kmem_req_t req;
82
83 req.type = KMEM_PROCESS;
84 req.ptr = process;
85 kmem_free( &req );
86}
87
88/////////////////////////////////////////////////
89void process_reference_init( process_t * process,
90 pid_t pid,
91 xptr_t parent_xp,
92 xptr_t model_xp )
93{
94 cxy_t parent_cxy;
95 process_t * parent_ptr;
96 cxy_t model_cxy;
97 process_t * model_ptr;
98 xptr_t stdin_xp;
99 xptr_t stdout_xp;
100 xptr_t stderr_xp;
101 uint32_t stdin_id;
102 uint32_t stdout_id;
103 uint32_t stderr_id;
104 error_t error;
105 uint32_t txt_id;
106 char rx_path[40];
107 char tx_path[40];
108 xptr_t chdev_xp;
109 chdev_t * chdev_ptr;
110 cxy_t chdev_cxy;
111 pid_t model_pid;
112 pid_t parent_pid;
113
114 // get model process cluster and local pointer
115 model_cxy = GET_CXY( model_xp );
116 model_ptr = GET_PTR( model_xp );
117
118 // get parent process cluster and local pointer
119 parent_cxy = GET_CXY( parent_xp );
120 parent_ptr = GET_PTR( parent_xp );
121
122 // get model_pid and parent_pid
123 parent_pid = hal_remote_lw( XPTR( parent_cxy , &parent_ptr->pid ) );
124 model_pid = hal_remote_lw( XPTR( model_cxy , &model_ptr->pid ) );
125
126#if CONFIG_DEBUG_PROCESS_REFERENCE_INIT
127uint32_t cycle = (uint32_t)hal_get_cycles();
128if( CONFIG_DEBUG_PROCESS_REFERENCE_INIT )
129printk("\n[DBG] %s : thread %x enter / pid = %x / ppid = %x / model_pid = %x / cycle %d\n",
130__FUNCTION__ , CURRENT_THREAD , pid , parent_pid , model_pid , cycle );
131#endif
132
133 // initialize PID, REF_XP, PARENT_XP, and STATE
134 process->pid = pid;
135 process->ref_xp = XPTR( local_cxy , process );
136 process->parent_xp = parent_xp;
137 process->term_state = 0;
138
139 // initialize vmm as empty
140 error = vmm_init( process );
141 assert( (error == 0) , __FUNCTION__ , "cannot initialize VMM\n" );
142
143#if (CONFIG_DEBUG_PROCESS_REFERENCE_INIT & 1)
144cycle = (uint32_t)hal_get_cycles();
145if( CONFIG_DEBUG_PROCESS_REFERENCE_INIT )
146printk("\n[DBG] %s : thread %x / vmm empty for process %x / cycle %d\n",
147__FUNCTION__ , CURRENT_THREAD , pid , cycle );
148#endif
149
150 // initialize fd_array as empty
151 process_fd_init( process );
152
153 // define the stdin/stdout/stderr pseudo files <=> select a TXT terminal.
154 // - if INIT (pid == 1) => link to kernel TXT[0]
155 // - if KSH[i] (model_pid == 1) => allocate a free TXT[i]
156 // - if USER process => same terminal as model
157
158 if( (pid == 1) || (model_pid == 1)) // INIT or KSH process
159 {
160 if (pid == 1 ) txt_id = 0; // INIT
161 else txt_id = process_txt_alloc(); // KSH[i]
162
163 // attach process to TXT[txt_id]
164 process_txt_attach( process , txt_id );
165
166 // build path to TXT_RX[i] and TXT_TX[i] chdevs
167 snprintf( rx_path , 40 , "/dev/external/txt%d_rx", txt_id );
168 snprintf( tx_path , 40 , "/dev/external/txt%d_tx", txt_id );
169
170 // create stdin pseudo file
171 error = vfs_open( process,
172 rx_path,
173 O_RDONLY,
174 0, // FIXME chmod
175 &stdin_xp,
176 &stdin_id );
177
178 assert( (error == 0) , __FUNCTION__ , "cannot open stdin pseudo file" );
179 assert( (stdin_id == 0) , __FUNCTION__ , "stdin index must be 0" );
180
181 // create stdout pseudo file
182 error = vfs_open( process,
183 tx_path,
184 O_WRONLY,
185 0, // FIXME chmod
186 &stdout_xp,
187 &stdout_id );
188
189 assert( (error == 0) , __FUNCTION__ , "cannot open stdout pseudo file" );
190 assert( (stdout_id == 1) , __FUNCTION__ , "stdout index must be 1" );
191
192 // create stderr pseudo file
193 error = vfs_open( process,
194 tx_path,
195 O_WRONLY,
196 0, // FIXME chmod
197 &stderr_xp,
198 &stderr_id );
199
200 assert( (error == 0) , __FUNCTION__ , "cannot open stderr pseudo file" );
201 assert( (stderr_id == 2) , __FUNCTION__ , "stderr index must be 2" );
202
203 }
204 else // normal user process
205 {
206 // get extended pointer on model process TXT chdev
207 chdev_xp = chdev_from_file( model_ptr->fd_array.array[0] );
208
209 // get cluster and local pointer on chdev
210 chdev_cxy = GET_CXY( chdev_xp );
211 chdev_ptr = GET_PTR( chdev_xp );
212
213 // get TXT terminal index
214 txt_id = hal_remote_lw( XPTR( chdev_cxy , &chdev_ptr->channel ) );
215
216 // attach process to TXT[txt_id]
217 process_txt_attach( process , txt_id );
218
219 // copy all open files from model process fd_array to this process
220 process_fd_remote_copy( XPTR( local_cxy , &process->fd_array ),
221 XPTR( model_cxy , &model_ptr->fd_array ) );
222 }
223
224 // initialize specific inodes root and cwd
225 process->vfs_root_xp = (xptr_t)hal_remote_lwd( XPTR( model_cxy,
226 &model_ptr->vfs_root_xp ) );
227 process->vfs_cwd_xp = (xptr_t)hal_remote_lwd( XPTR( model_cxy,
228 &model_ptr->vfs_cwd_xp ) );
229 vfs_inode_remote_up( process->vfs_root_xp );
230 vfs_inode_remote_up( process->vfs_cwd_xp );
231
232 remote_rwlock_init( XPTR( local_cxy , &process->cwd_lock ) );
233
234#if (CONFIG_DEBUG_PROCESS_REFERENCE_INIT & 1)
235cycle = (uint32_t)hal_get_cycles();
236if( CONFIG_DEBUG_PROCESS_REFERENCE_INIT )
237printk("\n[DBG] %s : thread %x / fd_array for process %x / cycle %d\n",
238__FUNCTION__ , CURRENT_THREAD , pid , cycle );
239#endif
240
241 // reset children list root
242 xlist_root_init( XPTR( local_cxy , &process->children_root ) );
243 process->children_nr = 0;
244 remote_spinlock_init( XPTR( local_cxy , &process->children_lock ) );
245
246 // reset semaphore / mutex / barrier / condvar list roots
247 xlist_root_init( XPTR( local_cxy , &process->sem_root ) );
248 xlist_root_init( XPTR( local_cxy , &process->mutex_root ) );
249 xlist_root_init( XPTR( local_cxy , &process->barrier_root ) );
250 xlist_root_init( XPTR( local_cxy , &process->condvar_root ) );
251 remote_spinlock_init( XPTR( local_cxy , &process->sync_lock ) );
252
253 // register new process in the local cluster manager pref_tbl[]
254 lpid_t lpid = LPID_FROM_PID( pid );
255 LOCAL_CLUSTER->pmgr.pref_tbl[lpid] = XPTR( local_cxy , process );
256
257 // register new process descriptor in local cluster manager local_list
258 cluster_process_local_link( process );
259
260 // register new process descriptor in local cluster manager copies_list
261 cluster_process_copies_link( process );
262
263 // reset th_tbl[] array as empty in process descriptor
264 uint32_t i;
265 for( i = 0 ; i < CONFIG_THREAD_MAX_PER_CLUSTER ; i++ )
266 {
267 process->th_tbl[i] = NULL;
268 }
269 process->th_nr = 0;
270 spinlock_init( &process->th_lock );
271
272 hal_fence();
273
274#if (CONFIG_DEBUG_PROCESS_REFERENCE_INIT & 1)
275cycle = (uint32_t)hal_get_cycles();
276if( CONFIG_DEBUG_PROCESS_REFERENCE_INIT )
277printk("\n[DBG] %s : thread %x exit / process %x / cycle %d\n",
278__FUNCTION__ , CURRENT_THREAD , pid , cycle );
279#endif
280
281} // process_reference_init()
282
283/////////////////////////////////////////////////////
284error_t process_copy_init( process_t * local_process,
285 xptr_t reference_process_xp )
286{
287 error_t error;
288
289 // get reference process cluster and local pointer
290 cxy_t ref_cxy = GET_CXY( reference_process_xp );
291 process_t * ref_ptr = GET_PTR( reference_process_xp );
292
293 // initialize PID, REF_XP, PARENT_XP, and STATE
294 local_process->pid = hal_remote_lw( XPTR( ref_cxy , &ref_ptr->pid ) );
295 local_process->parent_xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->parent_xp ) );
296 local_process->ref_xp = reference_process_xp;
297 local_process->term_state = 0;
298
299#if CONFIG_DEBUG_PROCESS_COPY_INIT
300uint32_t cycle = (uint32_t)hal_get_cycles();
301if( CONFIG_DEBUG_PROCESS_COPY_INIT )
302printk("\n[DBG] %s : thread %x enter for process %x\n",
303__FUNCTION__ , CURRENT_THREAD , local_process->pid );
304#endif
305
306 // reset local process vmm
307 error = vmm_init( local_process );
308 assert( (error == 0) , __FUNCTION__ , "cannot initialize VMM\n");
309
310 // reset process file descriptors array
311 process_fd_init( local_process );
312
313 // reset vfs_root_xp / vfs_bin_xp / vfs_cwd_xp fields
314 local_process->vfs_root_xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->vfs_root_xp ) );
315 local_process->vfs_bin_xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->vfs_bin_xp ) );
316 local_process->vfs_cwd_xp = XPTR_NULL;
317
318 // reset children list root (not used in a process descriptor copy)
319 xlist_root_init( XPTR( local_cxy , &local_process->children_root ) );
320 local_process->children_nr = 0;
321 remote_spinlock_init( XPTR( local_cxy , &local_process->children_lock ) );
322
323 // reset children_list (not used in a process descriptor copy)
324 xlist_entry_init( XPTR( local_cxy , &local_process->children_list ) );
325
326 // reset semaphores list root (not used in a process descriptor copy)
327 xlist_root_init( XPTR( local_cxy , &local_process->sem_root ) );
328 xlist_root_init( XPTR( local_cxy , &local_process->mutex_root ) );
329 xlist_root_init( XPTR( local_cxy , &local_process->barrier_root ) );
330 xlist_root_init( XPTR( local_cxy , &local_process->condvar_root ) );
331
332 // reset th_tbl[] array as empty
333 uint32_t i;
334 for( i = 0 ; i < CONFIG_THREAD_MAX_PER_CLUSTER ; i++ )
335 {
336 local_process->th_tbl[i] = NULL;
337 }
338 local_process->th_nr = 0;
339 spinlock_init( &local_process->th_lock );
340
341 // register new process descriptor in local cluster manager local_list
342 cluster_process_local_link( local_process );
343
344 // register new process descriptor in owner cluster manager copies_list
345 cluster_process_copies_link( local_process );
346
347 hal_fence();
348
349#if CONFIG_DEBUG_PROCESS_COPY_INIT
350cycle = (uint32_t)hal_get_cycles();
351if( CONFIG_DEBUG_PROCESS_COPY_INIT )
352printk("\n[DBG] %s : thread %x exit for process %x\n",
353__FUNCTION__ , CURRENT_THREAD , local_process->pid );
354#endif
355
356 return 0;
357
358} // end process_copy_init()
359
360///////////////////////////////////////////
361void process_destroy( process_t * process )
362{
363 xptr_t parent_xp;
364 process_t * parent_ptr;
365 cxy_t parent_cxy;
366 xptr_t children_lock_xp;
367
368 pid_t pid = process->pid;
369
370 assert( (process->th_nr == 0) , __FUNCTION__ ,
371 "process %x in cluster %x has still active threads", pid , local_cxy );
372
373#if CONFIG_DEBUG_PROCESS_DESTROY
374uint32_t cycle = (uint32_t)hal_get_cycles();
375if( CONFIG_DEBUG_PROCESS_DESTROY )
376printk("\n[DBG] %s : thread %x enter to destroy process %x (pid = %x) / cycle %d\n",
377__FUNCTION__ , CURRENT_THREAD , process, pid , cycle );
378#endif
379
380#if CONFIG_DEBUG_PROCESS_DESTROY
381if( CONFIG_DEBUG_PROCESS_DESTROY & 1 )
382cluster_processes_display( CXY_FROM_PID( pid ) );
383#endif
384
385 // remove process from local_list in local cluster manager
386 cluster_process_local_unlink( process );
387
388 // remove process from copies_list in owner cluster manager
389 cluster_process_copies_unlink( process );
390
391 // remove process from children_list if process is in owner cluster
392 if( CXY_FROM_PID( pid ) == local_cxy )
393 {
394 // get pointers on parent process
395 parent_xp = process->parent_xp;
396 parent_cxy = GET_CXY( parent_xp );
397 parent_ptr = GET_PTR( parent_xp );
398
399 // get extended pointer on children_lock in parent process
400 children_lock_xp = XPTR( parent_cxy , &parent_ptr->children_lock );
401
402 // remove process from children_list
403 remote_spinlock_lock( children_lock_xp );
404 xlist_unlink( XPTR( local_cxy , &process->children_list ) );
405 remote_spinlock_unlock( children_lock_xp );
406 }
407
408 // release the process PID to cluster manager
409 cluster_pid_release( pid );
410
411 // FIXME close all open files and update dirty [AG]
412
413 // decrease refcount for bin file, root file and cwd file
414 if( process->vfs_bin_xp != XPTR_NULL ) vfs_file_count_down( process->vfs_bin_xp );
415 if( process->vfs_root_xp != XPTR_NULL ) vfs_file_count_down( process->vfs_root_xp );
416 if( process->vfs_cwd_xp != XPTR_NULL ) vfs_file_count_down( process->vfs_cwd_xp );
417
418 // Destroy VMM
419 vmm_destroy( process );
420
421 // release memory allocated to process descriptor
422 process_free( process );
423
424#if CONFIG_DEBUG_PROCESS_DESTROY
425cycle = (uint32_t)hal_get_cycles();
426if( CONFIG_DEBUG_PROCESS_DESTROY )
427printk("\n[DBG] %s : thread %x exit / destroyed process %x (pid = %x) / cycle %d\n",
428__FUNCTION__ , CURRENT_THREAD , process, pid, cycle );
429#endif
430
431} // end process_destroy()
432
433/////////////////////////////////////////////////
434char * process_action_str( uint32_t action_type )
435{
436 if ( action_type == BLOCK_ALL_THREADS ) return "BLOCK";
437 else if( action_type == UNBLOCK_ALL_THREADS ) return "UNBLOCK";
438 else if( action_type == DELETE_ALL_THREADS ) return "DELETE";
439 else return "undefined";
440}
441
442////////////////////////////////////////
443void process_sigaction( pid_t pid,
444 uint32_t action_type )
445{
446 cxy_t owner_cxy; // owner cluster identifier
447 lpid_t lpid; // process index in owner cluster
448 cluster_t * cluster; // pointer on cluster manager
449 xptr_t root_xp; // extended pointer on root of copies
450 xptr_t lock_xp; // extended pointer on lock protecting copies
451 xptr_t iter_xp; // iterator on copies list
452 xptr_t process_xp; // extended pointer on process copy
453 cxy_t process_cxy; // process copy cluster identifier
454 reg_t save_sr; // for critical section
455 rpc_desc_t rpc; // shared RPC descriptor
456
457 thread_t * client = CURRENT_THREAD;
458
459#if CONFIG_DEBUG_PROCESS_SIGACTION
460uint32_t cycle = (uint32_t)hal_get_cycles();
461if( CONFIG_DEBUG_PROCESS_SIGACTION < cycle )
462printk("\n[DBG] %s : thread %x enter to %s process %x / cycle %d\n",
463__FUNCTION__ , client, process_action_str( action_type ) , pid , cycle );
464#endif
465
466 // get pointer on local cluster manager
467 cluster = LOCAL_CLUSTER;
468
469 // get owner cluster identifier and process lpid
470 owner_cxy = CXY_FROM_PID( pid );
471 lpid = LPID_FROM_PID( pid );
472
473 // get root of list of copies, lock, and number of copies from owner cluster
474 root_xp = XPTR( owner_cxy , &cluster->pmgr.copies_root[lpid] );
475 lock_xp = XPTR( owner_cxy , &cluster->pmgr.copies_lock[lpid] );
476
477 // check action type
478 assert( ((action_type == DELETE_ALL_THREADS ) ||
479 (action_type == BLOCK_ALL_THREADS ) ||
480 (action_type == UNBLOCK_ALL_THREADS )), __FUNCTION__ , "illegal action type" );
481
482 // allocate a - shared - RPC descriptor in client thread stack
483 // it can be shared because all parallel, non-blocking, server threads
484 // use the same input arguments, and use the shared RPC response field
485 // but use
486
487 // the client thread makes the following sequence:
488 // 1. mask interrupts
489 // 2. block itself
490 // 3. send RPC requests to all copies
491 // 4. unmask interrupts
492 // 5. deschedule
493
494 // mask IRQs
495 hal_disable_irq( &save_sr);
496
497 // client register blocking condition for itself
498 thread_block( XPTR( local_cxy , client ) , THREAD_BLOCKED_RPC );
499
500 // take the lock protecting the copies
501 remote_spinlock_lock( lock_xp );
502
503 // initialize shared RPC descriptor
504 rpc.response = 0;
505 rpc.blocking = false;
506 rpc.index = RPC_PROCESS_SIGACTION;
507 rpc.thread = client;
508 rpc.lid = client->core->lid;
509 rpc.args[0] = action_type;
510 rpc.args[1] = pid;
511
512 // send RPCs to all clusters containing process copiess
513 XLIST_FOREACH( root_xp , iter_xp )
514 {
515
516#if CONFIG_DEBUG_PROCESS_SIGACTION
517if( CONFIG_DEBUG_PROCESS_SIGACTION < cycle )
518printk("\n[DBG] %s : send RPC to %s process %x in cluster %x\n",
519__FUNCTION__ , process_action_str( action_type ) , pid , process_cxy );
520#endif
521 // atomically increment responses counter
522 hal_atomic_add( (void *)&rpc.response , 1 );
523
524 process_xp = XLIST_ELEMENT( iter_xp , process_t , copies_list );
525 process_cxy = GET_CXY( process_xp );
526
527 // call RPC in target cluster
528 rpc_process_sigaction_client( process_cxy , &rpc );
529 }
530
531 // release the lock protecting process copies
532 remote_spinlock_unlock( lock_xp );
533
534 // restore IRQs
535 hal_restore_irq( save_sr);
536
537 // client deschedule : will be unblocked by the last RPC server thread
538 sched_yield("blocked on rpc_process_sigaction");
539
540#if CONFIG_DEBUG_PROCESS_SIGACTION
541cycle = (uint32_t)hal_get_cycles();
542if( CONFIG_DEBUG_PROCESS_SIGACTION < cycle )
543printk("\n[DBG] %s : thread %x exit after %s process %x in cluster %x / cycle %d\n",
544__FUNCTION__ , client, process_action_str( action_type ) , pid , local_cxy , cycle );
545#endif
546
547} // end process_sigaction()
548
549/////////////////////////////////////////////////
550void process_block_threads( process_t * process )
551{
552 thread_t * target; // pointer on target thread
553 thread_t * this; // pointer on calling thread
554 uint32_t ltid; // index in process th_tbl
555 cxy_t owner_cxy; // target process owner cluster
556 uint32_t count; // requests counter
557 volatile uint32_t ack_count; // scheduler acknowledge counter
558
559 // get calling thread pointer
560 this = CURRENT_THREAD;
561
562 // get target process owner cluster
563 owner_cxy = CXY_FROM_PID( process->pid );
564
565#if CONFIG_DEBUG_PROCESS_SIGACTION
566uint32_t cycle = (uint32_t)hal_get_cycles();
567if( CONFIG_DEBUG_PROCESS_SIGACTION < cycle )
568printk("\n[DBG] %s : thread %x enter for process %x in cluster %x / cycle %d\n",
569__FUNCTION__ , this , process->pid , local_cxy , cycle );
570#endif
571
572 // get lock protecting process th_tbl[]
573 spinlock_lock( &process->th_lock );
574
575 // loop to block all threads but the main thread
576 // we use both "ltid" and "count" because it can exist "holes" in th_tbl
577 for( ltid = 0 , count = 0 , ack_count = 0 ; count < process->th_nr ; ltid++ )
578 {
579 target = process->th_tbl[ltid];
580
581 if( target != NULL ) // thread exist
582 {
583 count++;
584
585 // main thread should not be deleted
586 if( (ltid != 0) || (owner_cxy != local_cxy) )
587 {
588 // set the global blocked bit in target thread descriptor.
589 thread_block( XPTR( local_cxy , target ) , THREAD_BLOCKED_GLOBAL );
590
591 // - if the calling thread and the target thread are on the same core,
592 // we don't need confirmation from scheduler,
593 // - if the calling thread and the target thread are not running on the same
594 // core, we ask the target scheduler to acknowlege the blocking
595 // to be sure that the target thread is not running.
596
597 if( this->core->lid != target->core->lid )
598 {
599 // increment responses counter
600 hal_atomic_add( (void*)&ack_count , 1 );
601
602 // set FLAG_REQ_ACK and &ack_rsp_count in target descriptor
603 thread_set_req_ack( target , (uint32_t *)&ack_count );
604
605 // force scheduling on target thread
606 dev_pic_send_ipi( local_cxy , target->core->lid );
607 }
608 }
609 }
610 }
611
612 // release lock protecting process th_tbl[]
613 spinlock_unlock( &process->th_lock );
614
615 // wait acknowledges
616 while( 1 )
617 {
618 // exit when all scheduler acknoledges received
619 if ( ack_count == 0 ) break;
620
621 // wait 1000 cycles before retry
622 hal_fixed_delay( 1000 );
623 }
624
625#if CONFIG_DEBUG_PROCESS_SIGACTION
626cycle = (uint32_t)hal_get_cycles();
627if( CONFIG_DEBUG_PROCESS_SIGACTION < cycle )
628printk("\n[DBG] %s : thread %x exit for process %x in cluster %x / cycle %d\n",
629__FUNCTION__ , this , process->pid , local_cxy , cycle );
630#endif
631
632} // end process_block_threads()
633
634///////////////////////////////////////////////////
635void process_unblock_threads( process_t * process )
636{
637 thread_t * target; // pointer on target thead
638 thread_t * this; // pointer on calling thread
639 uint32_t ltid; // index in process th_tbl
640 uint32_t count; // requests counter
641
642 // get calling thread pointer
643 this = CURRENT_THREAD;
644
645#if CONFIG_DEBUG_PROCESS_SIGACTION
646uint32_t cycle = (uint32_t)hal_get_cycles();
647if( CONFIG_DEBUG_PROCESS_SIGACTION < cycle )
648printk("\n[DBG] %s : thread %x enter for process %x in cluster %x / cycle %d\n",
649__FUNCTION__ , this , process->pid , local_cxy , cycle );
650#endif
651
652 // get lock protecting process th_tbl[]
653 spinlock_lock( &process->th_lock );
654
655 // loop on process threads to unblock all threads
656 // we use both "ltid" and "count" because it can exist "holes" in th_tbl
657 for( ltid = 0 , count = 0 ; count < process->th_nr ; ltid++ )
658 {
659 target = process->th_tbl[ltid];
660
661 if( target != NULL ) // thread found
662 {
663 count++;
664
665 // reset the global blocked bit in target thread descriptor.
666 thread_unblock( XPTR( local_cxy , target ) , THREAD_BLOCKED_GLOBAL );
667 }
668 }
669
670 // release lock protecting process th_tbl[]
671 spinlock_unlock( &process->th_lock );
672
673#if CONFIG_DEBUG_PROCESS_SIGACTION
674cycle = (uint32_t)hal_get_cycles();
675if( CONFIG_DEBUG_PROCESS_SIGACTION < cycle )
676printk("\n[DBG] %s : thread %x exit for process %x in cluster %x / cycle %d\n",
677__FUNCTION__ , this , process->pid , local_cxy , cycle );
678#endif
679
680} // end process_unblock_threads()
681
682//////////////////////////////////////////////////
683void process_delete_threads( process_t * process )
684{
685 thread_t * target; // pointer on target thread
686 uint32_t ltid; // index in process th_tbl
687 uint32_t count; // threads counter
688
689#if CONFIG_DEBUG_PROCESS_SIGACTION
690uint32_t cycle = (uint32_t)hal_get_cycles();
691if( CONFIG_DEBUG_PROCESS_SIGACTION < cycle )
692printk("\n[DBG] %s : thread %x enter for process %x in cluster %x / cycle %d\n",
693__FUNCTION__ , CURRENT_THREAD , process->pid , local_cxy , cycle );
694#endif
695
696 // get lock protecting process th_tbl[]
697 spinlock_lock( &process->th_lock );
698
699 // loop to set the REQ_DELETE flag on all threads but the main
700 // we use both "ltid" and "count" because it can exist "holes" in th_tbl
701 for( ltid = 0 , count = 0 ; count < process->th_nr ; ltid++ )
702 {
703 target = process->th_tbl[ltid];
704
705 if( target != NULL )
706 {
707 count++;
708
709 thread_kill( XPTR( local_cxy , target ),
710 false, // is_exit
711 true ); // is_forced
712 }
713 }
714
715 // release lock protecting process th_tbl[]
716 spinlock_unlock( &process->th_lock );
717
718#if CONFIG_DEBUG_PROCESS_SIGACTION
719cycle = (uint32_t)hal_get_cycles();
720if( CONFIG_DEBUG_PROCESS_SIGACTION < cycle )
721printk("\n[DBG] %s : thread %x exit for process %x in cluster %x / cycle %d\n",
722__FUNCTION__ , CURRENT_THREAD , process->pid , local_cxy , cycle );
723#endif
724
725} // end process_delete_threads()
726
727///////////////////////////////////////////////
728process_t * process_get_local_copy( pid_t pid )
729{
730 error_t error;
731 process_t * process_ptr; // local pointer on process
732 xptr_t process_xp; // extended pointer on process
733
734 cluster_t * cluster = LOCAL_CLUSTER;
735
736 // get lock protecting local list of processes
737 remote_spinlock_lock( XPTR( local_cxy , &cluster->pmgr.local_lock ) );
738
739 // scan the local list of process descriptors to find the process
740 xptr_t iter;
741 bool_t found = false;
742 XLIST_FOREACH( XPTR( local_cxy , &cluster->pmgr.local_root ) , iter )
743 {
744 process_xp = XLIST_ELEMENT( iter , process_t , local_list );
745 process_ptr = GET_PTR( process_xp );
746 if( process_ptr->pid == pid )
747 {
748 found = true;
749 break;
750 }
751 }
752
753 // release lock protecting local list of processes
754 remote_spinlock_unlock( XPTR( local_cxy , &cluster->pmgr.local_lock ) );
755
756 // allocate memory for a new local process descriptor
757 // and initialise it from reference cluster if required
758 if( !found )
759 {
760 // get extended pointer on reference process descriptor
761 xptr_t ref_xp = cluster_get_reference_process_from_pid( pid );
762
763 assert( (ref_xp != XPTR_NULL) , __FUNCTION__ , "illegal pid\n" );
764
765 // allocate memory for local process descriptor
766 process_ptr = process_alloc();
767 if( process_ptr == NULL ) return NULL;
768
769 // initialize local process descriptor copy
770 error = process_copy_init( process_ptr , ref_xp );
771 if( error ) return NULL;
772 }
773
774 return process_ptr;
775
776} // end process_get_local_copy()
777
778////////////////////////////////////////////
779pid_t process_get_ppid( xptr_t process_xp )
780{
781 cxy_t process_cxy;
782 process_t * process_ptr;
783 xptr_t parent_xp;
784 cxy_t parent_cxy;
785 process_t * parent_ptr;
786
787 // get process cluster and local pointer
788 process_cxy = GET_CXY( process_xp );
789 process_ptr = GET_PTR( process_xp );
790
791 // get pointers on parent process
792 parent_xp = (xptr_t)hal_remote_lwd( XPTR( process_cxy , &process_ptr->parent_xp ) );
793 parent_cxy = GET_CXY( parent_xp );
794 parent_ptr = GET_PTR( parent_xp );
795
796 return hal_remote_lw( XPTR( parent_cxy , &parent_ptr->pid ) );
797}
798
799//////////////////////////////////////////////////////////////////////////////////////////
800// File descriptor array related functions
801//////////////////////////////////////////////////////////////////////////////////////////
802
803///////////////////////////////////////////
804void process_fd_init( process_t * process )
805{
806 uint32_t fd;
807
808 remote_spinlock_init( XPTR( local_cxy , &process->fd_array.lock ) );
809
810 process->fd_array.current = 0;
811
812 // initialize array
813 for ( fd = 0 ; fd < CONFIG_PROCESS_FILE_MAX_NR ; fd++ )
814 {
815 process->fd_array.array[fd] = XPTR_NULL;
816 }
817}
818
819//////////////////////////////
820bool_t process_fd_array_full()
821{
822 // get extended pointer on reference process
823 xptr_t ref_xp = CURRENT_THREAD->process->ref_xp;
824
825 // get reference process cluster and local pointer
826 process_t * ref_ptr = GET_PTR( ref_xp );
827 cxy_t ref_cxy = GET_CXY( ref_xp );
828
829 // get number of open file descriptors from reference fd_array
830 uint32_t current = hal_remote_lw( XPTR( ref_cxy , &ref_ptr->fd_array.current ) );
831
832 return ( current >= CONFIG_PROCESS_FILE_MAX_NR );
833}
834
835/////////////////////////////////////////////////
836error_t process_fd_register( process_t * process,
837 xptr_t file_xp,
838 uint32_t * fdid )
839{
840 bool_t found;
841 uint32_t id;
842 xptr_t xp;
843
844 // get reference process cluster and local pointer
845 xptr_t ref_xp = process->ref_xp;
846 process_t * ref_ptr = GET_PTR( ref_xp );
847 cxy_t ref_cxy = GET_CXY( ref_xp );
848
849 // take lock protecting reference fd_array
850 remote_spinlock_lock( XPTR( ref_cxy , &ref_ptr->fd_array.lock ) );
851
852 found = false;
853
854 for ( id = 0; id < CONFIG_PROCESS_FILE_MAX_NR ; id++ )
855 {
856 xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->fd_array.array[id] ) );
857 if ( xp == XPTR_NULL )
858 {
859 found = true;
860 hal_remote_swd( XPTR( ref_cxy , &ref_ptr->fd_array.array[id] ) , file_xp );
861 hal_remote_atomic_add( XPTR( ref_cxy , &ref_ptr->fd_array.current ) , 1 );
862 *fdid = id;
863 break;
864 }
865 }
866
867 // release lock protecting reference fd_array
868 remote_spinlock_unlock( XPTR( ref_cxy , &ref_ptr->fd_array.lock ) );
869
870 if ( !found ) return -1;
871 else return 0;
872}
873
874////////////////////////////////////////////////
875xptr_t process_fd_get_xptr( process_t * process,
876 uint32_t fdid )
877{
878 xptr_t file_xp;
879
880 // access local copy of process descriptor
881 file_xp = process->fd_array.array[fdid];
882
883 if( file_xp == XPTR_NULL )
884 {
885 // get reference process cluster and local pointer
886 xptr_t ref_xp = process->ref_xp;
887 cxy_t ref_cxy = GET_CXY( ref_xp );
888 process_t * ref_ptr = GET_PTR( ref_xp );
889
890 // access reference process descriptor
891 file_xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->fd_array.array[fdid] ) );
892
893 // update local fd_array if found
894 if( file_xp != XPTR_NULL )
895 {
896 process->fd_array.array[fdid] = file_xp;
897 }
898 }
899
900 return file_xp;
901
902} // end process_fd_get_xptr()
903
904///////////////////////////////////////////
905void process_fd_remote_copy( xptr_t dst_xp,
906 xptr_t src_xp )
907{
908 uint32_t fd;
909 xptr_t entry;
910
911 // get cluster and local pointer for src fd_array
912 cxy_t src_cxy = GET_CXY( src_xp );
913 fd_array_t * src_ptr = GET_PTR( src_xp );
914
915 // get cluster and local pointer for dst fd_array
916 cxy_t dst_cxy = GET_CXY( dst_xp );
917 fd_array_t * dst_ptr = GET_PTR( dst_xp );
918
919 // get the remote lock protecting the src fd_array
920 remote_spinlock_lock( XPTR( src_cxy , &src_ptr->lock ) );
921
922 // loop on all fd_array entries
923 for( fd = 0 ; fd < CONFIG_PROCESS_FILE_MAX_NR ; fd++ )
924 {
925 entry = (xptr_t)hal_remote_lwd( XPTR( src_cxy , &src_ptr->array[fd] ) );
926
927 if( entry != XPTR_NULL )
928 {
929 // increment file descriptor ref count
930 vfs_file_count_up( entry );
931
932 // copy entry in destination process fd_array
933 hal_remote_swd( XPTR( dst_cxy , &dst_ptr->array[fd] ) , entry );
934 }
935 }
936
937 // release lock on source process fd_array
938 remote_spinlock_unlock( XPTR( src_cxy , &src_ptr->lock ) );
939
940} // end process_fd_remote_copy()
941
942////////////////////////////////////////////////////////////////////////////////////
943// Thread related functions
944////////////////////////////////////////////////////////////////////////////////////
945
946/////////////////////////////////////////////////////
947error_t process_register_thread( process_t * process,
948 thread_t * thread,
949 trdid_t * trdid )
950{
951 ltid_t ltid;
952 bool_t found = false;
953
954 assert( (process != NULL) , __FUNCTION__ , "process argument is NULL" );
955
956 assert( (thread != NULL) , __FUNCTION__ , "thread argument is NULL" );
957
958 // take lock protecting th_tbl
959 spinlock_lock( &process->th_lock );
960
961 // search a free slot in th_tbl[]
962 for( ltid = 0 ; ltid < CONFIG_THREAD_MAX_PER_CLUSTER ; ltid++ )
963 {
964 if( process->th_tbl[ltid] == NULL )
965 {
966 found = true;
967 break;
968 }
969 }
970
971 if( found )
972 {
973 // register thread in th_tbl[]
974 process->th_tbl[ltid] = thread;
975 process->th_nr++;
976
977 // returns trdid
978 *trdid = TRDID( local_cxy , ltid );
979 }
980
981
982 // release lock protecting th_tbl
983 hal_fence();
984 spinlock_unlock( &process->th_lock );
985
986 return (found) ? 0 : ENOMEM;
987
988} // end process_register_thread()
989
990///////////////////////////////////////////////
991void process_remove_thread( thread_t * thread )
992{
993 assert( (thread != NULL) , __FUNCTION__ , "thread argument is NULL" );
994
995 process_t * process = thread->process;
996
997 // get thread local index
998 ltid_t ltid = LTID_FROM_TRDID( thread->trdid );
999
1000 // take lock protecting th_tbl
1001 spinlock_lock( &process->th_lock );
1002
1003 assert( (process->th_nr) , __FUNCTION__ , "process th_nr cannot be 0\n" );
1004
1005 // remove thread from th_tbl[]
1006 process->th_tbl[ltid] = NULL;
1007 process->th_nr--;
1008
1009 hal_fence();
1010
1011 // release lock protecting th_tbl
1012 spinlock_unlock( &process->th_lock );
1013
1014} // process_remove_thread()
1015
1016/////////////////////////////////////////////////////////
1017error_t process_make_fork( xptr_t parent_process_xp,
1018 xptr_t parent_thread_xp,
1019 pid_t * child_pid,
1020 thread_t ** child_thread )
1021{
1022 process_t * process; // local pointer on child process descriptor
1023 thread_t * thread; // local pointer on child thread descriptor
1024 pid_t new_pid; // process identifier for child process
1025 pid_t parent_pid; // process identifier for parent process
1026 xptr_t ref_xp; // extended pointer on reference process
1027 xptr_t vfs_bin_xp; // extended pointer on .elf file
1028 error_t error;
1029
1030 // get cluster and local pointer for parent process
1031 cxy_t parent_process_cxy = GET_CXY( parent_process_xp );
1032 process_t * parent_process_ptr = GET_PTR( parent_process_xp );
1033
1034 // get parent process PID and extended pointer on .elf file
1035 parent_pid = hal_remote_lw (XPTR( parent_process_cxy , &parent_process_ptr->pid));
1036 vfs_bin_xp = hal_remote_lwd(XPTR( parent_process_cxy , &parent_process_ptr->vfs_bin_xp));
1037
1038 // check parent process is the reference
1039 ref_xp = hal_remote_lwd( XPTR( parent_process_cxy , &parent_process_ptr->ref_xp ) );
1040 assert( (parent_process_xp == ref_xp ) , __FUNCTION__ ,
1041 "parent process must be the reference process\n" );
1042
1043#if CONFIG_DEBUG_PROCESS_MAKE_FORK
1044uint32_t cycle = (uint32_t)hal_get_cycles();
1045if( CONFIG_DEBUG_PROCESS_MAKE_FORK < cycle )
1046printk("\n[DBG] %s : thread %x enter for process %x / cycle %d\n",
1047__FUNCTION__, CURRENT_THREAD, parent_pid, cycle );
1048#endif
1049
1050 // allocate a process descriptor
1051 process = process_alloc();
1052 if( process == NULL )
1053 {
1054 printk("\n[ERROR] in %s : cannot get process in cluster %x\n",
1055 __FUNCTION__, local_cxy );
1056 return -1;
1057 }
1058
1059 // allocate a child PID from local cluster
1060 error = cluster_pid_alloc( process , &new_pid );
1061 if( error )
1062 {
1063 printk("\n[ERROR] in %s : cannot get PID in cluster %x\n",
1064 __FUNCTION__, local_cxy );
1065 process_free( process );
1066 return -1;
1067 }
1068
1069 // initializes child process descriptor from parent process descriptor
1070 process_reference_init( process,
1071 new_pid,
1072 parent_process_xp,
1073 parent_process_xp );
1074
1075#if( CONFIG_DEBUG_PROCESS_MAKE_FORK & 1 )
1076cycle = (uint32_t)hal_get_cycles();
1077if( CONFIG_DEBUG_PROCESS_MAKE_FORK < cycle )
1078printk("\n[DBG] %s : thread %x created child_process %x / child_pid %x / cycle %d\n",
1079__FUNCTION__, CURRENT_THREAD, process, new_pid, cycle );
1080#endif
1081
1082 // copy VMM from parent descriptor to child descriptor
1083 error = vmm_fork_copy( process,
1084 parent_process_xp );
1085 if( error )
1086 {
1087 printk("\n[ERROR] in %s : cannot copy VMM in cluster %x\n",
1088 __FUNCTION__, local_cxy );
1089 process_free( process );
1090 cluster_pid_release( new_pid );
1091 return -1;
1092 }
1093
1094#if( CONFIG_DEBUG_PROCESS_MAKE_FORK & 1 )
1095cycle = (uint32_t)hal_get_cycles();
1096if( CONFIG_DEBUG_PROCESS_MAKE_FORK < cycle )
1097printk("\n[DBG] %s : thread %x copied VMM from parent %x to child %x / cycle %d\n",
1098__FUNCTION__ , CURRENT_THREAD , parent_pid, new_pid, cycle );
1099#endif
1100
1101 // update extended pointer on .elf file
1102 process->vfs_bin_xp = vfs_bin_xp;
1103
1104 // create child thread descriptor from parent thread descriptor
1105 error = thread_user_fork( parent_thread_xp,
1106 process,
1107 &thread );
1108 if( error )
1109 {
1110 printk("\n[ERROR] in %s : cannot create thread in cluster %x\n",
1111 __FUNCTION__, local_cxy );
1112 process_free( process );
1113 cluster_pid_release( new_pid );
1114 return -1;
1115 }
1116
1117 // check main thread index
1118 assert( (thread->trdid == 0) , __FUNCTION__ , "main thread must have index 0\n" );
1119
1120#if( CONFIG_DEBUG_PROCESS_MAKE_FORK & 1 )
1121cycle = (uint32_t)hal_get_cycles();
1122if( CONFIG_DEBUG_PROCESS_MAKE_FORK < cycle )
1123printk("\n[DBG] %s : thread %x created child thread %x / cycle %d\n",
1124__FUNCTION__ , CURRENT_THREAD, thread, cycle );
1125#endif
1126
1127 // set Copy_On_Write flag in parent process GPT
1128 // this includes all replicated GPT copies
1129 if( parent_process_cxy == local_cxy ) // reference is local
1130 {
1131 vmm_set_cow( parent_process_ptr );
1132 }
1133 else // reference is remote
1134 {
1135 rpc_vmm_set_cow_client( parent_process_cxy,
1136 parent_process_ptr );
1137 }
1138
1139 // set Copy_On_Write flag in child process GPT
1140 vmm_set_cow( process );
1141
1142#if( CONFIG_DEBUG_PROCESS_MAKE_FORK & 1 )
1143cycle = (uint32_t)hal_get_cycles();
1144if( CONFIG_DEBUG_PROCESS_MAKE_FORK < cycle )
1145printk("\n[DBG] %s : thread %x set COW in parent and child / cycle %d\n",
1146__FUNCTION__ , CURRENT_THREAD, cycle );
1147#endif
1148
1149 // get extended pointers on parent children_root, children_lock and children_nr
1150 xptr_t children_root_xp = XPTR( parent_process_cxy , &parent_process_ptr->children_root );
1151 xptr_t children_lock_xp = XPTR( parent_process_cxy , &parent_process_ptr->children_lock );
1152 xptr_t children_nr_xp = XPTR( parent_process_cxy , &parent_process_ptr->children_nr );
1153
1154 // register process in parent children list
1155 remote_spinlock_lock( children_lock_xp );
1156 xlist_add_last( children_root_xp , XPTR( local_cxy , &process->children_list ) );
1157 hal_remote_atomic_add( children_nr_xp , 1 );
1158 remote_spinlock_unlock( children_lock_xp );
1159
1160 // return success
1161 *child_thread = thread;
1162 *child_pid = new_pid;
1163
1164#if CONFIG_DEBUG_PROCESS_MAKE_FORK
1165cycle = (uint32_t)hal_get_cycles();
1166if( CONFIG_DEBUG_PROCESS_MAKE_FORK < cycle )
1167printk("\n[DBG] %s : thread %x exit / cycle %d\n",
1168__FUNCTION__, CURRENT_THREAD, cycle );
1169#endif
1170
1171 return 0;
1172
1173} // end process_make_fork()
1174
1175
1176/////////////////////////////////////////////////////
1177error_t process_make_exec( exec_info_t * exec_info )
1178{
1179 char * path; // pathname to .elf file
1180 pid_t pid; // old_process PID / given to new_process
1181 pid_t temp_pid; // temporary PID / given to old_process
1182 process_t * old_process; // local pointer on old process
1183 thread_t * old_thread; // local pointer on old thread
1184 process_t * new_process; // local pointer on new process
1185 thread_t * new_thread; // local pointer on new thread
1186 xptr_t parent_xp; // extended pointer on parent process
1187 pthread_attr_t attr; // new thread attributes
1188 lid_t lid; // selected core local index
1189 error_t error;
1190
1191 // get old_thread / old_process / PID / parent_xp
1192 old_thread = CURRENT_THREAD;
1193 old_process = old_thread->process;
1194 pid = old_process->pid;
1195 parent_xp = old_process->parent_xp;
1196
1197 // get .elf pathname from exec_info
1198 path = exec_info->path;
1199
1200 // this function must be executed by a thread running in owner cluster
1201 assert( (CXY_FROM_PID( pid ) == local_cxy), __FUNCTION__,
1202 "local_cluster must be owner_cluster\n" );
1203
1204 assert( (LTID_FROM_TRDID( old_thread->trdid ) == 0) , __FUNCTION__,
1205 "must be called by the main thread\n" );
1206
1207#if CONFIG_DEBUG_PROCESS_MAKE_EXEC
1208uint32_t cycle = (uint32_t)hal_get_cycles();
1209if( CONFIG_DEBUG_PROCESS_MAKE_EXEC < cycle )
1210printk("\n[DBG] %s : thread %x enters for process %x / %s / cycle %d\n",
1211__FUNCTION__, old_thread, pid, path, cycle );
1212#endif
1213
1214 // allocate memory for new_process descriptor
1215 new_process = process_alloc();
1216
1217 if( new_process == NULL )
1218 {
1219 printk("\n[ERROR] in %s : cannot allocate process descriptor in cluster %x\n",
1220 __FUNCTION__ , local_cxy );
1221 return -1;
1222 }
1223
1224 // get a temporary PID for old_process
1225 error = cluster_pid_alloc( old_process , &temp_pid );
1226 if( error )
1227 {
1228 printk("\n[ERROR] in %s : cannot get PID in cluster %x\n",
1229 __FUNCTION__ , local_cxy );
1230 process_free( new_process );
1231 return -1;
1232 }
1233
1234 // set temporary PID to old_process
1235 old_process->pid = temp_pid;
1236
1237 // initialize new process descriptor
1238 process_reference_init( new_process,
1239 pid,
1240 parent_xp, // parent_process_xp
1241 XPTR(local_cxy , old_process) ); // model_process
1242
1243 // give TXT ownership to new_process
1244 process_txt_set_ownership( XPTR( local_cxy , new_process) );
1245
1246#if( CONFIG_DEBUG_PROCESS_MAKE_EXEC & 1 )
1247cycle = (uint32_t)hal_get_cycles();
1248if( CONFIG_DEBUG_PROCESS_MAKE_EXEC < cycle )
1249printk("\n[DBG] %s : thread %x created new process %x / cycle %d \n",
1250__FUNCTION__ , old_thread , new_process , cycle );
1251#endif
1252
1253 // register code & data vsegs as well as entry-point in new process VMM,
1254 // and register extended pointer on .elf file in process descriptor
1255 if( elf_load_process( path , new_process ) )
1256 {
1257 printk("\n[ERROR] in %s : failed to access .elf file for path %s\n",
1258 __FUNCTION__ , path );
1259 process_destroy( new_process );
1260 return -1;
1261 }
1262
1263#if( CONFIG_DEBUG_PROCESS_MAKE_EXEC & 1 )
1264cycle = (uint32_t)hal_get_cycles();
1265if( CONFIG_DEBUG_PROCESS_MAKE_EXEC < cycle )
1266printk("\n[DBG] %s : thread %x registered code/data vsegs in new process %x / cycle %d\n",
1267__FUNCTION__, old_thread , new_process->pid , cycle );
1268#endif
1269
1270 // select a core in local cluster to execute the main thread
1271 lid = cluster_select_local_core();
1272
1273 // initialize pthread attributes for main thread
1274 attr.attributes = PT_ATTR_DETACH | PT_ATTR_CLUSTER_DEFINED | PT_ATTR_CORE_DEFINED;
1275 attr.cxy = local_cxy;
1276 attr.lid = lid;
1277
1278 // create and initialize main thread in local cluster
1279 error = thread_user_create( pid,
1280 (void *)new_process->vmm.entry_point,
1281 exec_info->args_pointers,
1282 &attr,
1283 &new_thread );
1284 if( error )
1285 {
1286 printk("\n[ERROR] in %s : cannot create thread for process %x\n",
1287 __FUNCTION__ , new_process );
1288 process_destroy( new_process );
1289 return -1;
1290 }
1291
1292 // check main thread index
1293 assert( (new_thread->trdid == 0) , __FUNCTION__ , "main thread must have index 0\n" );
1294
1295#if( CONFIG_DEBUG_PROCESS_MAKE_EXEC & 1 )
1296cycle = (uint32_t)hal_get_cycles();
1297if( CONFIG_DEBUG_PROCESS_MAKE_EXEC < cycle )
1298printk("\n[DBG] %s : thread %x created new_process main thread %x / cycle %d\n",
1299__FUNCTION__ , old_thread , new_thread , cycle );
1300#endif
1301
1302 // get cluster and local pointer on parent process
1303 process_t * parent_ptr = GET_PTR( parent_xp );
1304 cxy_t parent_cxy = GET_CXY( parent_xp );
1305
1306 // get extended pointers on parent children_root, children_lock and children_nr
1307 xptr_t root_xp = XPTR( parent_cxy , &parent_ptr->children_root );
1308 xptr_t lock_xp = XPTR( parent_cxy , &parent_ptr->children_lock );
1309 xptr_t nr_xp = XPTR( parent_cxy , &parent_ptr->children_nr );
1310
1311 // register new_process in parent children list
1312 remote_spinlock_lock( lock_xp );
1313 xlist_add_last( root_xp , XPTR( local_cxy , &new_process->children_list ) );
1314 hal_remote_atomic_add( nr_xp , 1 );
1315 remote_spinlock_unlock( lock_xp );
1316
1317 // activate new thread
1318 thread_unblock( XPTR( local_cxy , new_thread ) , THREAD_BLOCKED_GLOBAL );
1319
1320 // detach old_process from TXT
1321 process_txt_detach( XPTR( local_cxy , old_process ) );
1322
1323 // request old_thread destruction => old_process destruction
1324 thread_block( XPTR( local_cxy , old_thread ) , THREAD_BLOCKED_GLOBAL );
1325 hal_atomic_or( &old_thread->flags , THREAD_FLAG_REQ_DELETE );
1326
1327 hal_fence();
1328
1329#if CONFIG_DEBUG_PROCESS_MAKE_EXEC
1330cycle = (uint32_t)hal_get_cycles();
1331if( CONFIG_DEBUG_PROCESS_MAKE_EXEC < cycle )
1332printk("\n[DBG] %s : old_thread %x blocked / new_thread %x activated / cycle %d\n",
1333__FUNCTION__ , old_thread , new_thread , cycle );
1334#endif
1335
1336 return 0;
1337
1338} // end process_make_exec()
1339
1340///////////////////////////////////////////////
1341void process_zero_create( process_t * process )
1342{
1343
1344#if CONFIG_DEBUG_PROCESS_ZERO_CREATE
1345uint32_t cycle = (uint32_t)hal_get_cycles();
1346if( CONFIG_DEBUG_PROCESS_ZERO_CREATE < cycle )
1347printk("\n[DBG] %s : thread %x enter / cycle %d\n", __FUNCTION__, CURRENT_THREAD, cycle );
1348#endif
1349
1350 // initialize PID, REF_XP, PARENT_XP, and STATE
1351 process->pid = 0;
1352 process->ref_xp = XPTR( local_cxy , process );
1353 process->parent_xp = XPTR_NULL;
1354 process->term_state = 0;
1355
1356 // reset th_tbl[] array as empty
1357 uint32_t i;
1358 for( i = 0 ; i < CONFIG_THREAD_MAX_PER_CLUSTER ; i++ )
1359 {
1360 process->th_tbl[i] = NULL;
1361 }
1362 process->th_nr = 0;
1363 spinlock_init( &process->th_lock );
1364
1365 // reset children list as empty
1366 xlist_root_init( XPTR( local_cxy , &process->children_root ) );
1367 remote_spinlock_init( XPTR( local_cxy , &process->children_lock ) );
1368 process->children_nr = 0;
1369
1370 hal_fence();
1371
1372#if CONFIG_DEBUG_PROCESS_ZERO_CREATE
1373cycle = (uint32_t)hal_get_cycles();
1374if( CONFIG_DEBUG_PROCESS_ZERO_CREATE < cycle )
1375printk("\n[DBG] %s : thread %x exit / cycle %d\n", __FUNCTION__, CURRENT_THREAD, cycle );
1376#endif
1377
1378} // end process_zero_init()
1379
1380//////////////////////////
1381void process_init_create()
1382{
1383 process_t * process; // local pointer on process descriptor
1384 pid_t pid; // process_init identifier
1385 thread_t * thread; // local pointer on main thread
1386 pthread_attr_t attr; // main thread attributes
1387 lid_t lid; // selected core local index for main thread
1388 error_t error;
1389
1390#if CONFIG_DEBUG_PROCESS_INIT_CREATE
1391uint32_t cycle = (uint32_t)hal_get_cycles();
1392if( CONFIG_DEBUG_PROCESS_INIT_CREATE < cycle )
1393printk("\n[DBG] %s : thread %x enter / cycle %d\n", __FUNCTION__, CURRENT_THREAD, cycle );
1394#endif
1395
1396 // allocates memory for process descriptor from local cluster
1397 process = process_alloc();
1398 if( process == NULL )
1399 {
1400 printk("\n[PANIC] in %s : no memory for process descriptor in cluster %x\n",
1401 __FUNCTION__, local_cxy );
1402 }
1403
1404 // get PID from local cluster
1405 error = cluster_pid_alloc( process , &pid );
1406 if( error )
1407 {
1408 printk("\n[PANIC] in %s : cannot allocate PID in cluster %x\n",
1409 __FUNCTION__, local_cxy );
1410 process_free( process );
1411 }
1412
1413 // check allocated PID
1414 assert( (pid == 1) , __FUNCTION__ , "process INIT must be first process in cluster 0\n" );
1415
1416 // initialize process descriptor / parent is local process_zero
1417 process_reference_init( process,
1418 pid,
1419 XPTR( local_cxy , &process_zero ), // parent
1420 XPTR( local_cxy , &process_zero ) ); // model
1421
1422 // register "code" and "data" vsegs as well as entry-point
1423 // in process VMM, using information contained in the elf file.
1424 if( elf_load_process( CONFIG_PROCESS_INIT_PATH , process ) )
1425 {
1426 printk("\n[PANIC] in %s : cannot access .elf file / path = %s\n",
1427 __FUNCTION__, CONFIG_PROCESS_INIT_PATH );
1428 process_destroy( process );
1429 }
1430
1431 // get extended pointers on process_zero children_root, children_lock
1432 xptr_t children_root_xp = XPTR( local_cxy , &process_zero.children_root );
1433 xptr_t children_lock_xp = XPTR( local_cxy , &process_zero.children_lock );
1434
1435 // register process INIT in parent local process_zero
1436 remote_spinlock_lock( children_lock_xp );
1437 xlist_add_last( children_root_xp , XPTR( local_cxy , &process->children_list ) );
1438 hal_atomic_add( &process_zero.children_nr , 1 );
1439 remote_spinlock_unlock( children_lock_xp );
1440
1441 // select a core in local cluster to execute the main thread
1442 lid = cluster_select_local_core();
1443
1444 // initialize pthread attributes for main thread
1445 attr.attributes = PT_ATTR_DETACH | PT_ATTR_CLUSTER_DEFINED | PT_ATTR_CORE_DEFINED;
1446 attr.cxy = local_cxy;
1447 attr.lid = lid;
1448
1449 // create and initialize thread descriptor
1450 error = thread_user_create( pid,
1451 (void *)process->vmm.entry_point,
1452 NULL,
1453 &attr,
1454 &thread );
1455 if( error )
1456 {
1457 printk("\n[PANIC] in %s : cannot create main thread / path = %s\n",
1458 __FUNCTION__, CONFIG_PROCESS_INIT_PATH );
1459 process_destroy( process );
1460 }
1461
1462 // check main thread index
1463 assert( (thread->trdid == 0) , __FUNCTION__ , "main thread must have index 0\n" );
1464
1465 // activate thread
1466 thread_unblock( XPTR( local_cxy , thread ) , THREAD_BLOCKED_GLOBAL );
1467
1468 hal_fence();
1469
1470#if CONFIG_DEBUG_PROCESS_INIT_CREATE
1471cycle = (uint32_t)hal_get_cycles();
1472if( CONFIG_DEBUG_PROCESS_INIT_CREATE < cycle )
1473printk("\n[DBG] %s : thread %x exit / cycle %d\n", __FUNCTION__, CURRENT_THREAD, cycle );
1474#endif
1475
1476} // end process_init_create()
1477
1478/////////////////////////////////////////
1479void process_display( xptr_t process_xp )
1480{
1481 process_t * process_ptr;
1482 cxy_t process_cxy;
1483 xptr_t parent_xp; // extended pointer on parent process
1484 process_t * parent_ptr;
1485 cxy_t parent_cxy;
1486
1487 pid_t pid;
1488 pid_t ppid;
1489 uint32_t state;
1490 xptr_t ref_xp;
1491 uint32_t th_nr;
1492
1493 xptr_t txt_file_xp; // extended pointer on TXT_RX pseudo file
1494 xptr_t chdev_xp; // extended pointer on TXT_RX chdev
1495 chdev_t * chdev_ptr;
1496 cxy_t chdev_cxy;
1497 xptr_t owner_xp; // extended pointer on TXT owner process
1498
1499 xptr_t elf_file_xp; // extended pointer on .elf file
1500 cxy_t elf_file_cxy;
1501 vfs_file_t * elf_file_ptr;
1502 vfs_inode_t * elf_inode_ptr; // local pointer on .elf inode
1503
1504 char txt_name[CONFIG_VFS_MAX_NAME_LENGTH];
1505 char elf_name[CONFIG_VFS_MAX_NAME_LENGTH];
1506
1507 // get cluster and local pointer on process
1508 process_ptr = GET_PTR( process_xp );
1509 process_cxy = GET_CXY( process_xp );
1510
1511 // check reference process
1512 ref_xp = hal_remote_lwd( XPTR( process_cxy , &process_ptr->ref_xp ) );
1513 assert( (process_xp == ref_xp) , __FUNCTION__ , "process is not the reference\n");
1514
1515 // get PID and state
1516 pid = hal_remote_lw( XPTR( process_cxy , &process_ptr->pid ) );
1517 state = hal_remote_lw( XPTR( process_cxy , &process_ptr->term_state ) );
1518
1519 // get PPID
1520 parent_xp = hal_remote_lwd( XPTR( process_cxy , &process_ptr->parent_xp ) );
1521 parent_cxy = GET_CXY( parent_xp );
1522 parent_ptr = GET_PTR( parent_xp );
1523 ppid = hal_remote_lw( XPTR( parent_cxy , &parent_ptr->pid ) );
1524
1525 // get number of threads
1526 th_nr = hal_remote_lw( XPTR( process_cxy , &process_ptr->th_nr ) );
1527
1528 // get TXT name and process owner
1529 txt_file_xp = hal_remote_lwd( XPTR( process_cxy , &process_ptr->fd_array.array[0] ) );
1530
1531 assert( (txt_file_xp != XPTR_NULL) , __FUNCTION__ ,
1532 "process must be attached to one TXT terminal\n" );
1533
1534 chdev_xp = chdev_from_file( txt_file_xp );
1535 chdev_cxy = GET_CXY( chdev_xp );
1536 chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
1537 hal_remote_strcpy( XPTR( local_cxy , txt_name ) ,
1538 XPTR( chdev_cxy , chdev_ptr->name ) );
1539 owner_xp = (xptr_t)hal_remote_lwd( XPTR( chdev_cxy , &chdev_ptr->ext.txt.owner_xp ) );
1540
1541 // get process .elf name
1542 elf_file_xp = hal_remote_lwd( XPTR( process_cxy , &process_ptr->vfs_bin_xp ) );
1543
1544 elf_file_cxy = GET_CXY( elf_file_xp );
1545 elf_file_ptr = (vfs_file_t *)GET_PTR( elf_file_xp );
1546 elf_inode_ptr = (vfs_inode_t *)hal_remote_lpt( XPTR( elf_file_cxy , &elf_file_ptr->inode ) );
1547 vfs_inode_get_name( XPTR( elf_file_cxy , elf_inode_ptr ) , elf_name );
1548
1549 // display process info
1550 if( owner_xp == process_xp )
1551 {
1552 printk("PID %X | PPID %X | STS %X | %s (FG) | %X | %d | %s\n",
1553 pid, ppid, state, txt_name, process_ptr, th_nr, elf_name );
1554 }
1555 else
1556 {
1557 printk("PID %X | PPID %X | STS %X | %s (BG) | %X | %d | %s\n",
1558 pid, ppid, state, txt_name, process_ptr, th_nr, elf_name );
1559 }
1560} // end process_display()
1561
1562
1563////////////////////////////////////////////////////////////////////////////////////////
1564// Terminals related functions
1565////////////////////////////////////////////////////////////////////////////////////////
1566
1567////////////////////////////
1568uint32_t process_txt_alloc()
1569{
1570 uint32_t index; // TXT terminal index
1571 xptr_t chdev_xp; // extended pointer on TXT_RX chdev
1572 chdev_t * chdev_ptr; // local pointer on TXT_RX chdev
1573 cxy_t chdev_cxy; // TXT_RX chdev cluster
1574 xptr_t root_xp; // extended pointer on owner field in chdev
1575
1576 // scan the user TXT_RX chdevs (TXT0 is reserved for kernel)
1577 for( index = 1 ; index < LOCAL_CLUSTER->nb_txt_channels ; index ++ )
1578 {
1579 // get pointers on TXT_RX[index]
1580 chdev_xp = chdev_dir.txt_rx[index];
1581 chdev_cxy = GET_CXY( chdev_xp );
1582 chdev_ptr = GET_PTR( chdev_xp );
1583
1584 // get extended pointer on root of attached process
1585 root_xp = XPTR( chdev_cxy , &chdev_ptr->ext.txt.root );
1586
1587 // return free TXT index if found
1588 if( xlist_is_empty( root_xp ) ) return index;
1589 }
1590
1591 assert( false , __FUNCTION__ , "no free TXT terminal found" );
1592
1593 return -1;
1594
1595} // end process_txt_alloc()
1596
1597/////////////////////////////////////////////
1598void process_txt_attach( process_t * process,
1599 uint32_t txt_id )
1600{
1601 xptr_t chdev_xp; // extended pointer on TXT_RX chdev
1602 cxy_t chdev_cxy; // TXT_RX chdev cluster
1603 chdev_t * chdev_ptr; // local pointer on TXT_RX chdev
1604 xptr_t root_xp; // extended pointer on list root in chdev
1605 xptr_t lock_xp; // extended pointer on list lock in chdev
1606
1607#if CONFIG_DEBUG_PROCESS_TXT_ATTACH
1608uint32_t cycle = (uint32_t)hal_get_cycles();
1609if( CONFIG_DEBUG_PROCESS_TXT_ATTACH < cycle )
1610printk("\n[DBG] %s : thread %x enter for process %x / txt_id = %d / cycle %d\n",
1611__FUNCTION__, CURRENT_THREAD, process->pid, txt_id, cycle );
1612#endif
1613
1614 // check process is in owner cluster
1615 assert( (CXY_FROM_PID( process->pid ) == local_cxy) , __FUNCTION__ ,
1616 "process descriptor not in owner cluster" );
1617
1618 // check terminal index
1619 assert( (txt_id < LOCAL_CLUSTER->nb_txt_channels) ,
1620 __FUNCTION__ , "illegal TXT terminal index" );
1621
1622 // get pointers on TXT_RX[txt_id] chdev
1623 chdev_xp = chdev_dir.txt_rx[txt_id];
1624 chdev_cxy = GET_CXY( chdev_xp );
1625 chdev_ptr = GET_PTR( chdev_xp );
1626
1627 // get extended pointer on root & lock of attached process list
1628 root_xp = XPTR( chdev_cxy , &chdev_ptr->ext.txt.root );
1629 lock_xp = XPTR( chdev_cxy , &chdev_ptr->ext.txt.lock );
1630
1631 // insert process in attached process list
1632 remote_spinlock_lock( lock_xp );
1633 xlist_add_last( root_xp , XPTR( local_cxy , &process->txt_list ) );
1634 remote_spinlock_unlock( lock_xp );
1635
1636#if CONFIG_DEBUG_PROCESS_TXT_ATTACH
1637cycle = (uint32_t)hal_get_cycles();
1638if( CONFIG_DEBUG_PROCESS_TXT_ATTACH < cycle )
1639printk("\n[DBG] %s : thread %x exit for process %x / txt_id = %d / cycle %d\n",
1640__FUNCTION__, CURRENT_THREAD, process->pid, txt_id , cycle );
1641#endif
1642
1643} // end process_txt_attach()
1644
1645/////////////////////////////////////////////
1646void process_txt_detach( xptr_t process_xp )
1647{
1648 process_t * process_ptr; // local pointer on process in owner cluster
1649 cxy_t process_cxy; // process owner cluster
1650 pid_t process_pid; // process identifier
1651 xptr_t file_xp; // extended pointer on stdin file
1652 xptr_t chdev_xp; // extended pointer on TXT_RX chdev
1653 cxy_t chdev_cxy; // TXT_RX chdev cluster
1654 chdev_t * chdev_ptr; // local pointer on TXT_RX chdev
1655 xptr_t lock_xp; // extended pointer on list lock in chdev
1656
1657 // get process cluster, local pointer, and PID
1658 process_cxy = GET_CXY( process_xp );
1659 process_ptr = GET_PTR( process_xp );
1660 process_pid = hal_remote_lw( XPTR( process_cxy , &process_ptr->pid ) );
1661
1662 // check process descriptor in owner cluster
1663 assert( (CXY_FROM_PID( process_pid ) == process_cxy ) , __FUNCTION__ ,
1664 "process descriptor not in owner cluster" );
1665
1666#if CONFIG_DEBUG_PROCESS_TXT_ATTACH
1667uint32_t cycle = (uint32_t)hal_get_cycles();
1668if( CONFIG_DEBUG_PROCESS_TXT_ATTACH < cycle )
1669printk("\n[DBG] %s : thread %x enter for process %x / cycle %d\n",
1670__FUNCTION__, CURRENT_THREAD, process_pid, cycle );
1671#endif
1672
1673 // release TXT ownership (does nothing if not TXT owner)
1674 process_txt_transfer_ownership( process_xp );
1675
1676 // get extended pointer on process stdin file
1677 file_xp = (xptr_t)hal_remote_lwd( XPTR( process_cxy , &process_ptr->fd_array.array[0] ) );
1678
1679 // get pointers on TXT_RX chdev
1680 chdev_xp = chdev_from_file( file_xp );
1681 chdev_cxy = GET_CXY( chdev_xp );
1682 chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
1683
1684 // get extended pointer on lock protecting attached process list
1685 lock_xp = XPTR( chdev_cxy , &chdev_ptr->ext.txt.lock );
1686
1687 // unlink process from attached process list
1688 remote_spinlock_lock( lock_xp );
1689 xlist_unlink( XPTR( process_cxy , &process_ptr->txt_list ) );
1690 remote_spinlock_unlock( lock_xp );
1691
1692#if( CONFIG_DEBUG_PROCESS_TXT_ATTACH & 1 )
1693if( CONFIG_DEBUG_PROCESS_TXT_ATTACH < cycle )
1694{
1695 xptr_t root_xp = XPTR( chdev_cxy , &chdev_ptr->ext.txt.root );
1696 xptr_t iter_xp;
1697 XLIST_FOREACH( root_xp , iter_xp )
1698 {
1699 xptr_t current_xp = XLIST_ELEMENT( iter_xp , process_t , txt_list );
1700 process_t * current_ptr = GET_PTR( current_xp );
1701
1702 printk("\n[DBG] %s : attached_process %x (pid = %x)\n",
1703 __FUNCTION__, current_ptr, current_ptr->pid );
1704 }
1705}
1706#endif
1707
1708#if CONFIG_DEBUG_PROCESS_TXT_ATTACH
1709cycle = (uint32_t)hal_get_cycles();
1710if( CONFIG_DEBUG_PROCESS_TXT_ATTACH < cycle )
1711printk("\n[DBG] %s : thread %x exit / process %x detached from TXT / cycle %d\n",
1712__FUNCTION__, CURRENT_THREAD, process->pid, cycle );
1713#endif
1714
1715} // end process_txt_detach()
1716
1717///////////////////////////////////////////////////
1718void process_txt_set_ownership( xptr_t process_xp )
1719{
1720 process_t * process_ptr;
1721 cxy_t process_cxy;
1722 pid_t process_pid;
1723 xptr_t file_xp;
1724 xptr_t txt_xp;
1725 chdev_t * txt_ptr;
1726 cxy_t txt_cxy;
1727
1728 // get pointers on process in owner cluster
1729 process_cxy = GET_CXY( process_xp );
1730 process_ptr = GET_PTR( process_xp );
1731
1732 // get process PID
1733 process_pid = hal_remote_lw( XPTR( process_cxy , &process_ptr->pid ) );
1734
1735 // check owner cluster
1736 assert( (process_cxy == CXY_FROM_PID( process_pid )) , __FUNCTION__,
1737 "process descriptor not in owner cluster\n" );
1738
1739#if CONFIG_DEBUG_PROCESS_TXT_ATTACH
1740uint32_t cycle = (uint32_t)hal_get_cycles();
1741if( CONFIG_DEBUG_PROCESS_TXT_ATTACH < cycle )
1742printk("\n[DBG] %s : thread %x enter for process %x / cycle %d\n",
1743__FUNCTION__, CURRENT_THREAD, process_pid, cycle );
1744#endif
1745
1746 // get extended pointer on stdin pseudo file
1747 file_xp = hal_remote_lwd( XPTR( process_cxy , &process_ptr->fd_array.array[0] ) );
1748
1749 // get pointers on TXT chdev
1750 txt_xp = chdev_from_file( file_xp );
1751 txt_cxy = GET_CXY( txt_xp );
1752 txt_ptr = GET_PTR( txt_xp );
1753
1754 // set owner field in TXT chdev
1755 hal_remote_swd( XPTR( txt_cxy , &txt_ptr->ext.txt.owner_xp ) , process_xp );
1756
1757#if CONFIG_DEBUG_PROCESS_TXT_ATTACH
1758cycle = (uint32_t)hal_get_cycles();
1759if( CONFIG_DEBUG_PROCESS_TXT_ATTACH < cycle )
1760printk("\n[DBG] %s : thread %x exit for process %x / cycle %d\n",
1761__FUNCTION__, CURRENT_THREAD, process_pid, cycle );
1762#endif
1763
1764} // end process_txt_set ownership()
1765
1766////////////////////////////////////////////////////////
1767void process_txt_transfer_ownership( xptr_t process_xp )
1768{
1769 process_t * process_ptr; // local pointer on process releasing ownership
1770 cxy_t process_cxy; // process cluster
1771 pid_t process_pid; // process identifier
1772 xptr_t file_xp; // extended pointer on TXT_RX pseudo file
1773 xptr_t txt_xp; // extended pointer on TXT_RX chdev
1774 chdev_t * txt_ptr; // local pointer on TXT_RX chdev
1775 cxy_t txt_cxy; // cluster of TXT_RX chdev
1776 uint32_t txt_id; // TXT_RX channel
1777 xptr_t owner_xp; // extended pointer on current TXT_RX owner
1778 xptr_t root_xp; // extended pointer on root of attached process list
1779 xptr_t lock_xp; // extended pointer on lock protecting attached process list
1780 xptr_t iter_xp; // iterator for xlist
1781 xptr_t current_xp; // extended pointer on current process
1782 process_t * current_ptr; // local pointer on current process
1783 cxy_t current_cxy; // cluster for current process
1784
1785 // get pointers on process in owner cluster
1786 process_cxy = GET_CXY( process_xp );
1787 process_ptr = GET_PTR( process_xp );
1788
1789 // get process PID
1790 process_pid = hal_remote_lw( XPTR( process_cxy , &process_ptr->pid ) );
1791
1792 // check owner cluster
1793 assert( (process_cxy == CXY_FROM_PID( process_pid )) , __FUNCTION__,
1794 "process descriptor not in owner cluster\n" );
1795
1796#if CONFIG_DEBUG_PROCESS_TXT_ATTACH
1797uint32_t cycle = (uint32_t)hal_get_cycles();
1798if( CONFIG_DEBUG_PROCESS_TXT_ATTACH < cycle )
1799printk("\n[DBG] %s : thread %x enter / process %x / pid %x / cycle %d\n",
1800__FUNCTION__, CURRENT_THREAD, process_ptr, process_pid, cycle );
1801#endif
1802
1803 // get extended pointer on stdin pseudo file
1804 file_xp = hal_remote_lwd( XPTR( process_cxy , &process_ptr->fd_array.array[0] ) );
1805
1806 // get pointers on TXT chdev
1807 txt_xp = chdev_from_file( file_xp );
1808 txt_cxy = GET_CXY( txt_xp );
1809 txt_ptr = GET_PTR( txt_xp );
1810
1811 // get extended pointer on TXT_RX owner and TXT channel
1812 owner_xp = hal_remote_lwd( XPTR( txt_cxy , &txt_ptr->ext.txt.owner_xp ) );
1813 txt_id = hal_remote_lw ( XPTR( txt_cxy , &txt_ptr->channel ) );
1814
1815#if( CONFIG_DEBUG_PROCESS_TXT_ATTACH & 1 )
1816if( CONFIG_DEBUG_PROCESS_TXT_ATTACH < cycle )
1817printk("\n[DBG] %s : file_ptr %x / txt_ptr %x / txt_id %d / owner_ptr = %x\n",
1818__FUNCTION__, GET_PTR(file_xp), txt_ptr, txt_id, GET_PTR(owner_xp) );
1819#endif
1820
1821 // transfer ownership only if process is the TXT owner
1822 if( (owner_xp == process_xp) && (txt_id > 0) )
1823 {
1824 // get extended pointers on root and lock of attached processes list
1825 root_xp = XPTR( txt_cxy , &txt_ptr->ext.txt.root );
1826 lock_xp = XPTR( txt_cxy , &txt_ptr->ext.txt.lock );
1827
1828 // get lock
1829 remote_spinlock_lock( lock_xp );
1830
1831 if( process_get_ppid( process_xp ) != 1 ) // process is not KSH
1832 {
1833
1834#if( CONFIG_DEBUG_PROCESS_TXT_ATTACH & 1 )
1835if( CONFIG_DEBUG_PROCESS_TXT_ATTACH < cycle )
1836printk("\n[DBG] %s : process is not the KSH process => search the KSH\n", __FUNCTION__ );
1837#endif
1838 // scan attached process list to find KSH process
1839 XLIST_FOREACH( root_xp , iter_xp )
1840 {
1841 current_xp = XLIST_ELEMENT( iter_xp , process_t , txt_list );
1842 current_cxy = GET_CXY( current_xp );
1843 current_ptr = GET_PTR( current_xp );
1844
1845 if( process_get_ppid( current_xp ) == 1 ) // current is KSH
1846 {
1847 // release lock
1848 remote_spinlock_unlock( lock_xp );
1849
1850 // set owner field in TXT chdev
1851 hal_remote_swd( XPTR( txt_cxy , &txt_ptr->ext.txt.owner_xp ) , current_xp );
1852
1853#if CONFIG_DEBUG_PROCESS_TXT_ATTACH
1854cycle = (uint32_t)hal_get_cycles();
1855if( CONFIG_DEBUG_PROCESS_TXT_ATTACH < cycle )
1856printk("\n[DBG] %s : thread %x exit / process %x to KSH process %x / cycle %d\n",
1857__FUNCTION__, CURRENT_THREAD, process_pid,
1858hal_remote_lw( XPTR( current_cxy , &current_ptr->pid ) ), cycle );
1859#endif
1860 return;
1861 }
1862 }
1863
1864 // release lock
1865 remote_spinlock_unlock( lock_xp );
1866
1867 // PANIC if KSH not found
1868 assert( false , __FUNCTION__ , "KSH process not found for TXT %d" );
1869
1870 return;
1871 }
1872 else // process is KSH
1873 {
1874
1875#if( CONFIG_DEBUG_PROCESS_TXT_ATTACH & 1 )
1876if( CONFIG_DEBUG_PROCESS_TXT_ATTACH < cycle )
1877printk("\n[DBG] %s : process is the KSH process => search another\n", __FUNCTION__ );
1878#endif
1879
1880 // scan attached process list to find another process
1881 XLIST_FOREACH( root_xp , iter_xp )
1882 {
1883 current_xp = XLIST_ELEMENT( iter_xp , process_t , txt_list );
1884 current_cxy = GET_CXY( current_xp );
1885 current_ptr = GET_PTR( current_xp );
1886
1887 if( current_xp != process_xp ) // current is not KSH
1888 {
1889 // release lock
1890 remote_spinlock_unlock( lock_xp );
1891
1892 // set owner field in TXT chdev
1893 hal_remote_swd( XPTR( txt_cxy , &txt_ptr->ext.txt.owner_xp ) , current_xp );
1894
1895#if CONFIG_DEBUG_PROCESS_TXT_ATTACH
1896cycle = (uint32_t)hal_get_cycles();
1897if( CONFIG_DEBUG_PROCESS_TXT_ATTACH < cycle )
1898printk("\n[DBG] %s : thread %x exit / KSH process %x to process %x / cycle %d\n",
1899__FUNCTION__, CURRENT_THREAD, process_pid,
1900hal_remote_lw( XPTR( current_cxy , &current_ptr->pid ) ), cycle );
1901#endif
1902 return;
1903 }
1904 }
1905
1906 // release lock
1907 remote_spinlock_unlock( lock_xp );
1908
1909 // no more owner for TXT if no other process found
1910 hal_remote_swd( XPTR( txt_cxy , &txt_ptr->ext.txt.owner_xp ) , XPTR_NULL );
1911
1912#if CONFIG_DEBUG_PROCESS_TXT_ATTACH
1913cycle = (uint32_t)hal_get_cycles();
1914if( CONFIG_DEBUG_PROCESS_TXT_ATTACH < cycle )
1915printk("\n[DBG] %s : thread %x exit / KSH process %x to nobody / cycle %d\n",
1916__FUNCTION__, CURRENT_THREAD, process_pid, cycle );
1917#endif
1918 return;
1919 }
1920 }
1921 else
1922 {
1923
1924#if CONFIG_DEBUG_PROCESS_TXT_ATTACH
1925cycle = (uint32_t)hal_get_cycles();
1926if( CONFIG_DEBUG_PROCESS_TXT_ATTACH < cycle )
1927printk("\n[DBG] %s : thread %x exit / process %x is not TXT owner / cycle %d\n",
1928__FUNCTION__, CURRENT_THREAD, process_pid, cycle );
1929#endif
1930
1931 }
1932} // end process_txt_transfer_ownership()
1933
1934
1935////////////////////////////////////////////////
1936xptr_t process_txt_get_owner( uint32_t channel )
1937{
1938 xptr_t txt_rx_xp = chdev_dir.txt_rx[channel];
1939 cxy_t txt_rx_cxy = GET_CXY( txt_rx_xp );
1940 chdev_t * txt_rx_ptr = GET_PTR( txt_rx_xp );
1941
1942 return (xptr_t)hal_remote_lwd( XPTR( txt_rx_cxy , &txt_rx_ptr->ext.txt.owner_xp ) );
1943}
1944
1945///////////////////////////////////////////
1946void process_txt_display( uint32_t txt_id )
1947{
1948 xptr_t chdev_xp;
1949 cxy_t chdev_cxy;
1950 chdev_t * chdev_ptr;
1951 xptr_t root_xp;
1952 xptr_t lock_xp;
1953 xptr_t current_xp;
1954 xptr_t iter_xp;
1955
1956 // check terminal index
1957 assert( (txt_id < LOCAL_CLUSTER->nb_txt_channels) ,
1958 __FUNCTION__ , "illegal TXT terminal index" );
1959
1960 // get pointers on TXT_RX[txt_id] chdev
1961 chdev_xp = chdev_dir.txt_rx[txt_id];
1962 chdev_cxy = GET_CXY( chdev_xp );
1963 chdev_ptr = GET_PTR( chdev_xp );
1964
1965 // get extended pointer on root & lock of attached process list
1966 root_xp = XPTR( chdev_cxy , &chdev_ptr->ext.txt.root );
1967 lock_xp = XPTR( chdev_cxy , &chdev_ptr->ext.txt.lock );
1968
1969 // display header
1970 printk("\n***** processes attached to TXT_%d\n", txt_id );
1971
1972 // get lock
1973 remote_spinlock_lock( lock_xp );
1974
1975 // scan attached process list
1976 XLIST_FOREACH( root_xp , iter_xp )
1977 {
1978 current_xp = XLIST_ELEMENT( iter_xp , process_t , txt_list );
1979 process_display( current_xp );
1980 }
1981
1982 // release lock
1983 remote_spinlock_unlock( lock_xp );
1984
1985} // end process_txt_display
Note: See TracBrowser for help on using the repository browser.