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

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

blip

File size: 65.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,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 <signal.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 = (process_t *)GET_PTR( model_xp );
117
118 // get parent process cluster and local pointer
119 parent_cxy = GET_CXY( parent_xp );
120 parent_ptr = (process_t *)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 = (chdev_t *)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 = (process_t *)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 parent_thread_xp;
367 xptr_t children_lock_xp;
368 xptr_t copies_lock_xp;
369
370 assert( (process->th_nr == 0) , __FUNCTION__ ,
371 "process %x in cluster %x has still active threads", process->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, process->pid , cycle );
378#endif
379
380 // get local process manager pointer
381 pmgr_t * pmgr = &LOCAL_CLUSTER->pmgr;
382
383 // remove process from local_list in cluster manager
384 remote_spinlock_lock( XPTR( local_cxy , &pmgr->local_lock ) );
385 xlist_unlink( XPTR( local_cxy , &process->local_list ) );
386 remote_spinlock_unlock( XPTR( local_cxy , &pmgr->local_lock ) );
387
388 // get extended pointer on copies_lock in owner cluster manager
389 cxy_t owner_cxy = CXY_FROM_PID( process->pid );
390 lpid_t lpid = LPID_FROM_PID( process->pid );
391 copies_lock_xp = XPTR( owner_cxy , &pmgr->copies_lock[lpid] );
392
393 // remove local process from copies_list
394 remote_spinlock_lock( copies_lock_xp );
395 xlist_unlink( XPTR( local_cxy , &process->copies_list ) );
396 remote_spinlock_unlock( copies_lock_xp );
397
398 // for reference process only
399 if( XPTR( local_cxy , process ) == process->ref_xp )
400 {
401 // remove reference process from txt_list
402 process_txt_detach( process );
403
404 // get pointers on parent process
405 parent_xp = process->parent_xp;
406 parent_cxy = GET_CXY( parent_xp );
407 parent_ptr = GET_PTR( parent_xp );
408
409 // get extended pointer on children_lock in parent process
410 children_lock_xp = XPTR( parent_cxy , &parent_ptr->children_lock );
411
412 // remove process from children_list
413 remote_spinlock_lock( children_lock_xp );
414 xlist_unlink( XPTR( local_cxy , &process->children_list ) );
415 remote_spinlock_unlock( children_lock_xp );
416 }
417
418 // release the process PID to cluster manager
419 cluster_pid_release( process->pid );
420
421 // FIXME close all open files and update dirty [AG]
422
423 // decrease refcount for bin file, root file and cwd file
424 if( process->vfs_bin_xp != XPTR_NULL ) vfs_file_count_down( process->vfs_bin_xp );
425 if( process->vfs_root_xp != XPTR_NULL ) vfs_file_count_down( process->vfs_root_xp );
426 if( process->vfs_cwd_xp != XPTR_NULL ) vfs_file_count_down( process->vfs_cwd_xp );
427
428 // Destroy VMM
429 vmm_destroy( process );
430
431 // release memory allocated to process descriptor
432 process_free( process );
433
434#if CONFIG_DEBUG_PROCESS_DESTROY
435cycle = (uint32_t)hal_get_cycles();
436if( CONFIG_DEBUG_PROCESS_DESTROY )
437printk("\n[DBG] %s : thread %x exit / destroyed process %x (pid = %x) / cycle %d\n",
438__FUNCTION__ , CURRENT_THREAD , process, process->pid, cycle );
439#endif
440
441} // end process_destroy()
442
443/////////////////////////////////////////////////
444char * process_action_str( uint32_t action_type )
445{
446 if ( action_type == BLOCK_ALL_THREADS ) return "BLOCK";
447 else if( action_type == UNBLOCK_ALL_THREADS ) return "UNBLOCK";
448 else if( action_type == DELETE_ALL_THREADS ) return "DELETE";
449 else return "undefined";
450}
451
452////////////////////////////////////////////
453void process_sigaction( process_t * process,
454 uint32_t action_type )
455{
456 cxy_t owner_cxy; // owner cluster identifier
457 lpid_t lpid; // process index in owner cluster
458 cluster_t * cluster; // pointer on cluster manager
459 xptr_t root_xp; // extended pointer on root of copies
460 xptr_t lock_xp; // extended pointer on lock protecting copies
461 xptr_t iter_xp; // iterator on copies list
462 xptr_t process_xp; // extended pointer on process copy
463 cxy_t process_cxy; // process copy cluster identifier
464 process_t * process_ptr; // local pointer on process copy
465 uint32_t responses; // number of remote process copies
466 uint32_t rsp_count; // used to assert number of copies
467 rpc_desc_t rpc; // rpc descriptor allocated in stack
468
469#if CONFIG_DEBUG_PROCESS_SIGACTION
470uint32_t cycle = (uint32_t)hal_get_cycles();
471if( CONFIG_DEBUG_PROCESS_SIGACTION < cycle )
472printk("\n[DBG] %s : thread %x enter to %s process %x in cluster %x / cycle %d\n",
473__FUNCTION__ , CURRENT_THREAD, process_action_str( action_type ) ,
474process->pid , local_cxy , cycle );
475#endif
476
477 thread_t * client = CURRENT_THREAD;
478
479 // get local pointer on local cluster manager
480 cluster = LOCAL_CLUSTER;
481
482 // get owner cluster identifier and process lpid
483 owner_cxy = CXY_FROM_PID( process->pid );
484 lpid = LPID_FROM_PID( process->pid );
485
486 // check owner cluster
487 assert( (owner_cxy == local_cxy) , __FUNCTION__ , "must be executed in owner cluster\n" );
488
489 // get number of remote copies
490 responses = cluster->pmgr.copies_nr[lpid] - 1;
491 rsp_count = 0;
492
493 // check action type
494 assert( ((action_type == DELETE_ALL_THREADS ) ||
495 (action_type == BLOCK_ALL_THREADS ) ||
496 (action_type == UNBLOCK_ALL_THREADS )), __FUNCTION__ , "illegal action type" );
497
498 // initialise rpc descriptor
499 rpc.index = RPC_PROCESS_SIGACTION;
500 rpc.response = responses;
501 rpc.blocking = false;
502 rpc.thread = client;
503
504 // get extended pointers on copies root and lock
505 root_xp = XPTR( local_cxy , &cluster->pmgr.copies_root[lpid] );
506 lock_xp = XPTR( local_cxy , &cluster->pmgr.copies_lock[lpid] );
507
508 // take the lock protecting the copies
509 remote_spinlock_lock( lock_xp );
510
511 // send RPCs to remote clusters
512 XLIST_FOREACH( root_xp , iter_xp )
513 {
514 process_xp = XLIST_ELEMENT( iter_xp , process_t , copies_list );
515 process_cxy = GET_CXY( process_xp );
516 process_ptr = (process_t *)GET_PTR( process_xp );
517
518 // send RPC to remote clusters
519 if( process_cxy != local_cxy )
520 {
521
522#if CONFIG_DEBUG_PROCESS_SIGACTION
523if( CONFIG_DEBUG_PROCESS_SIGACTION < cycle )
524printk("\n[DBG] %s : send RPC to remote cluster %x\n", __FUNCTION__ , process_cxy );
525#endif
526
527 rpc.args[0] = (uint64_t)action_type;
528 rpc.args[1] = (uint64_t)(intptr_t)process_ptr;
529 rpc_process_sigaction_client( process_cxy , &rpc );
530 rsp_count++;
531 }
532 }
533
534 // release the lock protecting process copies
535 remote_spinlock_unlock( lock_xp );
536
537 // check number of copies...
538 assert( (rsp_count == responses) , __FUNCTION__ ,
539 "unconsistent number of process copies : rsp_count = %d / responses = %d",
540 rsp_count , responses );
541
542 // block and deschedule to wait RPC responses if required
543 if( responses )
544 {
545 thread_block( CURRENT_THREAD , THREAD_BLOCKED_RPC );
546 sched_yield("BLOCKED on RPC_PROCESS_SIGACTION");
547 }
548
549#if CONFIG_DEBUG_PROCESS_SIGACTION
550if( CONFIG_DEBUG_PROCESS_SIGACTION < cycle )
551printk("\n[DBG] %s : make action in owner cluster %x\n", __FUNCTION__ , local_cxy );
552#endif
553
554 // call directly the relevant function in local owner cluster
555 if (action_type == DELETE_ALL_THREADS ) process_delete_threads ( process );
556 else if (action_type == BLOCK_ALL_THREADS ) process_block_threads ( process );
557 else if (action_type == UNBLOCK_ALL_THREADS ) process_unblock_threads( process );
558
559#if CONFIG_DEBUG_PROCESS_SIGACTION
560cycle = (uint32_t)hal_get_cycles();
561if( CONFIG_DEBUG_PROCESS_SIGACTION < cycle )
562printk("\n[DBG] %s : thread %x exit after %s process %x in cluster %x / cycle %d\n",
563__FUNCTION__ , CURRENT_THREAD, process_action_str( action_type ) ,
564process->pid , local_cxy , cycle );
565#endif
566
567} // end process_sigaction()
568
569/////////////////////////////////////////////////
570void process_block_threads( process_t * process )
571{
572 thread_t * target; // pointer on target thread
573 thread_t * this; // pointer on calling thread
574 uint32_t ltid; // index in process th_tbl
575 uint32_t count; // requests counter
576 volatile uint32_t rsp_count; // responses counter
577
578 // get calling thread pointer
579 this = CURRENT_THREAD;
580
581#if CONFIG_DEBUG_PROCESS_SIGACTION
582uint32_t cycle = (uint32_t)hal_get_cycles();
583if( CONFIG_DEBUG_PROCESS_SIGACTION < cycle )
584printk("\n[DBG] %s : thread %x enter for process %x in cluster %x / cycle %d\n",
585__FUNCTION__ , this , process->pid , local_cxy , cycle );
586#endif
587
588 // get lock protecting process th_tbl[]
589 spinlock_lock( &process->th_lock );
590
591 // initialize local responses counter
592 rsp_count = process->th_nr;
593
594 // loop on process threads to block and deschedule all threads in cluster
595 // we use both "ltid" and "count" because it can exist "holes" in th_tbl
596 for( ltid = 0 , count = 0 ; count < process->th_nr ; ltid++ )
597 {
598 target = process->th_tbl[ltid];
599
600 assert( (target != this) , __FUNCTION__ , "calling thread cannot be a target\n" );
601
602 if( target != NULL ) // thread found
603 {
604 count++;
605
606 // - if the calling thread and the target thread are on the same core,
607 // we block the target thread, we don't need confirmation from scheduler,
608 // and we simply decrement the responses counter.
609 // - if the calling thread and the target thread are not running on the same
610 // core, we ask the target scheduler to acknowlege the blocking
611 // to be sure that the target thread is not running.
612
613 if( this->core->lid == target->core->lid )
614 {
615 // set the global blocked bit in target thread descriptor.
616 thread_block( target , THREAD_BLOCKED_GLOBAL );
617
618 // decrement responses counter
619 hal_atomic_add( (void *)&rsp_count , -1 );
620 }
621 else
622 {
623 // set the global blocked bit in target thread descriptor.
624 thread_block( target , THREAD_BLOCKED_GLOBAL );
625
626 // set FLAG_REQ_ACK and &ack_rsp_count in target descriptor
627 thread_set_req_ack( target , (void *)&rsp_count );
628
629 // force scheduling on target thread
630 dev_pic_send_ipi( local_cxy , target->core->lid );
631 }
632 }
633 }
634
635 // release lock protecting process th_tbl[]
636 spinlock_unlock( &process->th_lock );
637
638 // wait all responses from schedulers
639 while( 1 )
640 {
641 // exit loop when all local responses received
642 if ( rsp_count == 0 ) break;
643
644 // wait 1000 cycles before retry
645 hal_fixed_delay( 1000 );
646 }
647
648#if CONFIG_DEBUG_PROCESS_SIGACTION
649cycle = (uint32_t)hal_get_cycles();
650if( CONFIG_DEBUG_PROCESS_SIGACTION < cycle )
651printk("\n[DBG] %s : thread %x exit for process %x in cluster %x / cycle %d\n",
652__FUNCTION__ , this , process->pid , local_cxy , cycle );
653#endif
654
655} // end process_block_threads()
656
657///////////////////////////////////////////////////
658void process_unblock_threads( process_t * process )
659{
660 thread_t * target; // pointer on target thead
661 thread_t * this; // pointer on calling thread
662 uint32_t ltid; // index in process th_tbl
663 uint32_t count; // requests counter
664
665 // get calling thread pointer
666 this = CURRENT_THREAD;
667
668#if CONFIG_DEBUG_PROCESS_SIGACTION
669uint32_t cycle = (uint32_t)hal_get_cycles();
670if( CONFIG_DEBUG_PROCESS_SIGACTION < cycle )
671printk("\n[DBG] %s : thread %x enter for process %x in cluster %x / cycle %d\n",
672__FUNCTION__ , this , process->pid , local_cxy , cycle );
673#endif
674
675 // get lock protecting process th_tbl[]
676 spinlock_lock( &process->th_lock );
677
678 // loop on process threads to unblock all threads in cluster
679 // we use both "ltid" and "count" because it can exist "holes" in th_tbl
680 for( ltid = 0 , count = 0 ; count < process->th_nr ; ltid++ )
681 {
682 target = process->th_tbl[ltid];
683
684 assert( (target != this) , __FUNCTION__ , "calling thread cannot be a target\n" );
685
686 if( target != NULL ) // thread found
687 {
688 count++;
689
690 // reset the global blocked bit in target thread descriptor.
691 thread_unblock( XPTR( local_cxy , target ) , THREAD_BLOCKED_GLOBAL );
692 }
693 }
694
695 // release lock protecting process th_tbl[]
696 spinlock_unlock( &process->th_lock );
697
698#if CONFIG_DEBUG_PROCESS_SIGACTION
699cycle = (uint32_t)hal_get_cycles();
700if( CONFIG_DEBUG_PROCESS_SIGACTION < cycle )
701printk("\n[DBG] %s : thread %x exit for process %x in cluster %x / cycle %d\n",
702__FUNCTION__ , this , process->pid , local_cxy , cycle );
703#endif
704
705} // end process_unblock_threads()
706
707//////////////////////////////////////////////////
708void process_delete_threads( process_t * process )
709{
710 thread_t * target; // pointer on target thread
711 thread_t * this; // pointer on calling thread
712 uint32_t ltid; // index in process th_tbl
713 uint32_t count; // request counter
714 cxy_t owner_cxy; // owner cluster identifier
715
716 // get calling thread pointer
717 this = CURRENT_THREAD;
718 owner_cxy = CXY_FROM_PID( process->pid );
719
720#if CONFIG_DEBUG_PROCESS_SIGACTION
721uint32_t cycle = (uint32_t)hal_get_cycles();
722if( CONFIG_DEBUG_PROCESS_SIGACTION < cycle )
723printk("\n[DBG] %s : thread %x enter for process %x in cluster %x / cycle %d\n",
724__FUNCTION__ , this , process->pid , local_cxy , cycle );
725#endif
726
727 // get lock protecting process th_tbl[]
728 spinlock_lock( &process->th_lock );
729
730 // loop on threads to set the REQ_DELETE flag
731 // we use both "ltid" and "count" because it can exist "holes" in th_tbl
732 for( ltid = 0 , count = 0 ; count < process->th_nr ; ltid++ )
733 {
734 target = process->th_tbl[ltid];
735
736 assert( (target != this) , __FUNCTION__ , "calling thread cannot be a target\n" );
737
738 if( target != NULL ) // thread found
739 {
740 count++;
741
742 // the main thread should not be deleted
743 if( (owner_cxy != local_cxy) || (ltid != 0) )
744 {
745 hal_atomic_or( &target->flags , THREAD_FLAG_REQ_DELETE );
746 }
747 }
748 }
749
750 // release lock protecting process th_tbl[]
751 spinlock_unlock( &process->th_lock );
752
753#if CONFIG_DEBUG_PROCESS_SIGACTION
754cycle = (uint32_t)hal_get_cycles();
755if( CONFIG_DEBUG_PROCESS_SIGACTION < cycle )
756printk("\n[DBG] %s : thread %x exit for process %x in cluster %x / cycle %d\n",
757__FUNCTION__ , this , process->pid , local_cxy , cycle );
758#endif
759
760} // end process_delete_threads()
761
762///////////////////////////////////////////////
763process_t * process_get_local_copy( pid_t pid )
764{
765 error_t error;
766 process_t * process_ptr; // local pointer on process
767 xptr_t process_xp; // extended pointer on process
768
769 cluster_t * cluster = LOCAL_CLUSTER;
770
771 // get lock protecting local list of processes
772 remote_spinlock_lock( XPTR( local_cxy , &cluster->pmgr.local_lock ) );
773
774 // scan the local list of process descriptors to find the process
775 xptr_t iter;
776 bool_t found = false;
777 XLIST_FOREACH( XPTR( local_cxy , &cluster->pmgr.local_root ) , iter )
778 {
779 process_xp = XLIST_ELEMENT( iter , process_t , local_list );
780 process_ptr = (process_t *)GET_PTR( process_xp );
781 if( process_ptr->pid == pid )
782 {
783 found = true;
784 break;
785 }
786 }
787
788 // release lock protecting local list of processes
789 remote_spinlock_unlock( XPTR( local_cxy , &cluster->pmgr.local_lock ) );
790
791 // allocate memory for a new local process descriptor
792 // and initialise it from reference cluster if required
793 if( !found )
794 {
795 // get extended pointer on reference process descriptor
796 xptr_t ref_xp = cluster_get_reference_process_from_pid( pid );
797
798 assert( (ref_xp != XPTR_NULL) , __FUNCTION__ , "illegal pid\n" );
799
800 // allocate memory for local process descriptor
801 process_ptr = process_alloc();
802 if( process_ptr == NULL ) return NULL;
803
804 // initialize local process descriptor copy
805 error = process_copy_init( process_ptr , ref_xp );
806 if( error ) return NULL;
807 }
808
809 return process_ptr;
810
811} // end process_get_local_copy()
812
813//////////////////////////////////////////////////////////////////////////////////////////
814// File descriptor array related functions
815//////////////////////////////////////////////////////////////////////////////////////////
816
817///////////////////////////////////////////
818void process_fd_init( process_t * process )
819{
820 uint32_t fd;
821
822 remote_spinlock_init( XPTR( local_cxy , &process->fd_array.lock ) );
823
824 process->fd_array.current = 0;
825
826 // initialize array
827 for ( fd = 0 ; fd < CONFIG_PROCESS_FILE_MAX_NR ; fd++ )
828 {
829 process->fd_array.array[fd] = XPTR_NULL;
830 }
831}
832
833//////////////////////////////
834bool_t process_fd_array_full()
835{
836 // get extended pointer on reference process
837 xptr_t ref_xp = CURRENT_THREAD->process->ref_xp;
838
839 // get reference process cluster and local pointer
840 process_t * ref_ptr = (process_t *)GET_PTR( ref_xp );
841 cxy_t ref_cxy = GET_CXY( ref_xp );
842
843 // get number of open file descriptors from reference fd_array
844 uint32_t current = hal_remote_lw( XPTR( ref_cxy , &ref_ptr->fd_array.current ) );
845
846 return ( current >= CONFIG_PROCESS_FILE_MAX_NR );
847}
848
849/////////////////////////////////////////////////
850error_t process_fd_register( process_t * process,
851 xptr_t file_xp,
852 uint32_t * fdid )
853{
854 bool_t found;
855 uint32_t id;
856 xptr_t xp;
857
858 // get reference process cluster and local pointer
859 xptr_t ref_xp = process->ref_xp;
860 process_t * ref_ptr = (process_t *)GET_PTR( ref_xp );
861 cxy_t ref_cxy = GET_CXY( ref_xp );
862
863 // take lock protecting reference fd_array
864 remote_spinlock_lock( XPTR( ref_cxy , &ref_ptr->fd_array.lock ) );
865
866 found = false;
867
868 for ( id = 0; id < CONFIG_PROCESS_FILE_MAX_NR ; id++ )
869 {
870 xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->fd_array.array[id] ) );
871 if ( xp == XPTR_NULL )
872 {
873 found = true;
874 hal_remote_swd( XPTR( ref_cxy , &ref_ptr->fd_array.array[id] ) , file_xp );
875 hal_remote_atomic_add( XPTR( ref_cxy , &ref_ptr->fd_array.current ) , 1 );
876 *fdid = id;
877 break;
878 }
879 }
880
881 // release lock protecting reference fd_array
882 remote_spinlock_unlock( XPTR( ref_cxy , &ref_ptr->fd_array.lock ) );
883
884 if ( !found ) return -1;
885 else return 0;
886}
887
888////////////////////////////////////////////////
889xptr_t process_fd_get_xptr( process_t * process,
890 uint32_t fdid )
891{
892 xptr_t file_xp;
893
894 // access local copy of process descriptor
895 file_xp = process->fd_array.array[fdid];
896
897 if( file_xp == XPTR_NULL )
898 {
899 // get reference process cluster and local pointer
900 xptr_t ref_xp = process->ref_xp;
901 cxy_t ref_cxy = GET_CXY( ref_xp );
902 process_t * ref_ptr = (process_t *)GET_PTR( ref_xp );
903
904 // access reference process descriptor
905 file_xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->fd_array.array[fdid] ) );
906
907 // update local fd_array if found
908 if( file_xp != XPTR_NULL )
909 {
910 process->fd_array.array[fdid] = file_xp;
911 }
912 }
913
914 return file_xp;
915
916} // end process_fd_get_xptr()
917
918///////////////////////////////////////////
919void process_fd_remote_copy( xptr_t dst_xp,
920 xptr_t src_xp )
921{
922 uint32_t fd;
923 xptr_t entry;
924
925 // get cluster and local pointer for src fd_array
926 cxy_t src_cxy = GET_CXY( src_xp );
927 fd_array_t * src_ptr = (fd_array_t *)GET_PTR( src_xp );
928
929 // get cluster and local pointer for dst fd_array
930 cxy_t dst_cxy = GET_CXY( dst_xp );
931 fd_array_t * dst_ptr = (fd_array_t *)GET_PTR( dst_xp );
932
933 // get the remote lock protecting the src fd_array
934 remote_spinlock_lock( XPTR( src_cxy , &src_ptr->lock ) );
935
936 // loop on all fd_array entries
937 for( fd = 0 ; fd < CONFIG_PROCESS_FILE_MAX_NR ; fd++ )
938 {
939 entry = (xptr_t)hal_remote_lwd( XPTR( src_cxy , &src_ptr->array[fd] ) );
940
941 if( entry != XPTR_NULL )
942 {
943 // increment file descriptor ref count
944 vfs_file_count_up( entry );
945
946 // copy entry in destination process fd_array
947 hal_remote_swd( XPTR( dst_cxy , &dst_ptr->array[fd] ) , entry );
948 }
949 }
950
951 // release lock on source process fd_array
952 remote_spinlock_unlock( XPTR( src_cxy , &src_ptr->lock ) );
953
954} // end process_fd_remote_copy()
955
956////////////////////////////////////////////////////////////////////////////////////
957// Thread related functions
958////////////////////////////////////////////////////////////////////////////////////
959
960/////////////////////////////////////////////////////
961error_t process_register_thread( process_t * process,
962 thread_t * thread,
963 trdid_t * trdid )
964{
965 ltid_t ltid;
966 bool_t found = false;
967
968 assert( (process != NULL) , __FUNCTION__ , "process argument is NULL" );
969
970 assert( (thread != NULL) , __FUNCTION__ , "thread argument is NULL" );
971
972 // take lock protecting th_tbl
973 spinlock_lock( &process->th_lock );
974
975 // search a free slot in th_tbl[]
976 for( ltid = 0 ; ltid < CONFIG_THREAD_MAX_PER_CLUSTER ; ltid++ )
977 {
978 if( process->th_tbl[ltid] == NULL )
979 {
980 found = true;
981 break;
982 }
983 }
984
985 if( found )
986 {
987 // register thread in th_tbl[]
988 process->th_tbl[ltid] = thread;
989 process->th_nr++;
990
991 // returns trdid
992 *trdid = TRDID( local_cxy , ltid );
993 }
994
995
996 // release lock protecting th_tbl
997 hal_fence();
998 spinlock_unlock( &process->th_lock );
999
1000 return (found) ? 0 : ENOMEM;
1001
1002} // end process_register_thread()
1003
1004///////////////////////////////////////////////
1005void process_remove_thread( thread_t * thread )
1006{
1007 assert( (thread != NULL) , __FUNCTION__ , "thread argument is NULL" );
1008
1009 process_t * process = thread->process;
1010
1011 // get thread local index
1012 ltid_t ltid = LTID_FROM_TRDID( thread->trdid );
1013
1014 // take lock protecting th_tbl
1015 spinlock_lock( &process->th_lock );
1016
1017 assert( (process->th_nr) , __FUNCTION__ , "process th_nr cannot be 0\n" );
1018
1019 // remove thread from th_tbl[]
1020 process->th_tbl[ltid] = NULL;
1021 process->th_nr--;
1022
1023 hal_fence();
1024
1025 // release lock protecting th_tbl
1026 spinlock_unlock( &process->th_lock );
1027
1028} // process_remove_thread()
1029
1030/////////////////////////////////////////////////////////
1031error_t process_make_fork( xptr_t parent_process_xp,
1032 xptr_t parent_thread_xp,
1033 pid_t * child_pid,
1034 thread_t ** child_thread )
1035{
1036 process_t * process; // local pointer on child process descriptor
1037 thread_t * thread; // local pointer on child thread descriptor
1038 pid_t new_pid; // process identifier for child process
1039 pid_t parent_pid; // process identifier for parent process
1040 xptr_t ref_xp; // extended pointer on reference process
1041 xptr_t vfs_bin_xp; // extended pointer on .elf file
1042 error_t error;
1043
1044 // get cluster and local pointer for parent process
1045 cxy_t parent_process_cxy = GET_CXY( parent_process_xp );
1046 process_t * parent_process_ptr = (process_t *)GET_PTR( parent_process_xp );
1047
1048 // get parent process PID and extended pointer on .elf file
1049 parent_pid = hal_remote_lw (XPTR( parent_process_cxy , &parent_process_ptr->pid));
1050 vfs_bin_xp = hal_remote_lwd(XPTR( parent_process_cxy , &parent_process_ptr->vfs_bin_xp));
1051
1052 // check parent process is the reference
1053 ref_xp = hal_remote_lwd( XPTR( parent_process_cxy , &parent_process_ptr->ref_xp ) );
1054 assert( (parent_process_xp == ref_xp ) , __FUNCTION__ ,
1055 "parent process must be the reference process\n" );
1056
1057#if CONFIG_DEBUG_PROCESS_MAKE_FORK
1058uint32_t cycle = (uint32_t)hal_get_cycles();
1059if( CONFIG_DEBUG_PROCESS_MAKE_FORK < cycle )
1060printk("\n[DBG] %s : thread %x enter for process %x / cycle %d\n",
1061__FUNCTION__, CURRENT_THREAD, parent_pid, cycle );
1062#endif
1063
1064 // allocate a process descriptor
1065 process = process_alloc();
1066 if( process == NULL )
1067 {
1068 printk("\n[ERROR] in %s : cannot get process in cluster %x\n",
1069 __FUNCTION__, local_cxy );
1070 return -1;
1071 }
1072
1073 // allocate a child PID from local cluster
1074 error = cluster_pid_alloc( process , &new_pid );
1075 if( error )
1076 {
1077 printk("\n[ERROR] in %s : cannot get PID in cluster %x\n",
1078 __FUNCTION__, local_cxy );
1079 process_free( process );
1080 return -1;
1081 }
1082
1083 // initializes child process descriptor from parent process descriptor
1084 process_reference_init( process,
1085 new_pid,
1086 parent_process_xp,
1087 parent_process_xp );
1088
1089#if CONFIG_DEBUG_PROCESS_MAKE_FORK
1090cycle = (uint32_t)hal_get_cycles();
1091if( CONFIG_DEBUG_PROCESS_MAKE_FORK < cycle )
1092printk("\n[DBG] %s : thread %x created child_process %x / child_pid %x / cycle %d\n",
1093__FUNCTION__, CURRENT_THREAD, process, new_pid, cycle );
1094#endif
1095
1096 // copy VMM from parent descriptor to child descriptor
1097 error = vmm_fork_copy( process,
1098 parent_process_xp );
1099 if( error )
1100 {
1101 printk("\n[ERROR] in %s : cannot copy VMM in cluster %x\n",
1102 __FUNCTION__, local_cxy );
1103 process_free( process );
1104 cluster_pid_release( new_pid );
1105 return -1;
1106 }
1107
1108#if CONFIG_DEBUG_PROCESS_MAKE_FORK
1109cycle = (uint32_t)hal_get_cycles();
1110if( CONFIG_DEBUG_PROCESS_MAKE_FORK < cycle )
1111printk("\n[DBG] %s : thread %x copied VMM from parent %x to child %x / cycle %d\n",
1112__FUNCTION__ , CURRENT_THREAD , parent_pid, new_pid, cycle );
1113#endif
1114
1115 // update extended pointer on .elf file
1116 process->vfs_bin_xp = vfs_bin_xp;
1117
1118 // create child thread descriptor from parent thread descriptor
1119 error = thread_user_fork( parent_thread_xp,
1120 process,
1121 &thread );
1122 if( error )
1123 {
1124 printk("\n[ERROR] in %s : cannot create thread in cluster %x\n",
1125 __FUNCTION__, local_cxy );
1126 process_free( process );
1127 cluster_pid_release( new_pid );
1128 return -1;
1129 }
1130
1131 // check main thread index
1132 assert( (thread->trdid == 0) , __FUNCTION__ , "main thread must have index 0\n" );
1133
1134#if CONFIG_DEBUG_PROCESS_MAKE_FORK
1135cycle = (uint32_t)hal_get_cycles();
1136if( CONFIG_DEBUG_PROCESS_MAKE_FORK < cycle )
1137printk("\n[DBG] %s : thread %x created child thread %x / cycle %d\n",
1138__FUNCTION__ , CURRENT_THREAD, thread, cycle );
1139#endif
1140
1141 // set Copy_On_Write flag in parent process GPT
1142 // this includes all replicated GPT copies
1143 if( parent_process_cxy == local_cxy ) // reference is local
1144 {
1145 vmm_set_cow( parent_process_ptr );
1146 }
1147 else // reference is remote
1148 {
1149 rpc_vmm_set_cow_client( parent_process_cxy,
1150 parent_process_ptr );
1151 }
1152
1153 // set Copy_On_Write flag in child process GPT
1154 vmm_set_cow( process );
1155
1156#if CONFIG_DEBUG_PROCESS_MAKE_FORK
1157cycle = (uint32_t)hal_get_cycles();
1158if( CONFIG_DEBUG_PROCESS_MAKE_FORK < cycle )
1159printk("\n[DBG] %s : thread %x set COW in parent and child / cycle %d\n",
1160__FUNCTION__ , CURRENT_THREAD, cycle );
1161#endif
1162
1163 // get extended pointers on parent children_root, children_lock and children_nr
1164 xptr_t children_root_xp = XPTR( parent_process_cxy , &parent_process_ptr->children_root );
1165 xptr_t children_lock_xp = XPTR( parent_process_cxy , &parent_process_ptr->children_lock );
1166 xptr_t children_nr_xp = XPTR( parent_process_cxy , &parent_process_ptr->children_nr );
1167
1168 // register process in parent children list
1169 remote_spinlock_lock( children_lock_xp );
1170 xlist_add_last( children_root_xp , XPTR( local_cxy , &process->children_list ) );
1171 hal_remote_atomic_add( children_nr_xp , 1 );
1172 remote_spinlock_unlock( children_lock_xp );
1173
1174 // return success
1175 *child_thread = thread;
1176 *child_pid = new_pid;
1177
1178#if CONFIG_DEBUG_PROCESS_MAKE_FORK
1179cycle = (uint32_t)hal_get_cycles();
1180if( CONFIG_DEBUG_PROCESS_MAKE_FORK < cycle )
1181printk("\n[DBG] %s : thread %x exit / cycle %d\n",
1182__FUNCTION__, CURRENT_THREAD, cycle );
1183#endif
1184
1185 return 0;
1186
1187} // end process_make_fork()
1188
1189
1190/////////////////////////////////////////////////////
1191error_t process_make_exec( exec_info_t * exec_info )
1192{
1193 char * path; // pathname to .elf file
1194 pid_t pid; // old_process PID / given to new_process
1195 pid_t temp_pid; // temporary PID / given to old_process
1196 process_t * old_process; // local pointer on old process
1197 thread_t * old_thread; // local pointer on old thread
1198 process_t * new_process; // local pointer on new process
1199 thread_t * new_thread; // local pointer on new thread
1200 xptr_t parent_xp; // extended pointer on parent process
1201 pthread_attr_t attr; // new thread attributes
1202 lid_t lid; // selected core local index
1203 error_t error;
1204
1205 // get old_thread / old_process / PID / parent_xp
1206 old_thread = CURRENT_THREAD;
1207 old_process = old_thread->process;
1208 pid = old_process->pid;
1209 parent_xp = old_process->parent_xp;
1210
1211 // get .elf pathname from exec_info
1212 path = exec_info->path;
1213
1214 // this function must be executed by a thread running in owner cluster
1215 assert( (CXY_FROM_PID( pid ) == local_cxy), __FUNCTION__,
1216 "local_cluster must be owner_cluster\n" );
1217
1218 assert( (LTID_FROM_TRDID( old_thread->trdid ) == 0) , __FUNCTION__,
1219 "must be called by the main thread\n" );
1220
1221#if CONFIG_DEBUG_PROCESS_MAKE_EXEC
1222uint32_t cycle = (uint32_t)hal_get_cycles();
1223if( CONFIG_DEBUG_PROCESS_MAKE_EXEC < cycle )
1224printk("\n[DBG] %s : thread %x enters for process %x / %s / cycle %d\n",
1225__FUNCTION__, old_thread, pid, path, cycle );
1226#endif
1227
1228 // allocate memory for new_process descriptor
1229 new_process = process_alloc();
1230
1231 if( new_process == NULL )
1232 {
1233 printk("\n[ERROR] in %s : cannot allocate process descriptor in cluster %x\n",
1234 __FUNCTION__ , local_cxy );
1235 return -1;
1236 }
1237
1238 // get a temporary PID for old_process
1239 error = cluster_pid_alloc( old_process , &temp_pid );
1240 if( error )
1241 {
1242 printk("\n[ERROR] in %s : cannot get PID in cluster %x\n",
1243 __FUNCTION__ , local_cxy );
1244 process_free( new_process );
1245 return -1;
1246 }
1247
1248 // set temporary PID to old_process
1249 old_process->pid = temp_pid;
1250
1251 // initialize new process descriptor
1252 process_reference_init( new_process,
1253 pid,
1254 parent_xp, // parent_process_xp
1255 XPTR(local_cxy , old_process) ); // model_process
1256
1257 // give TXT ownership to new_process
1258 process_txt_set_ownership( XPTR( local_cxy , new_process ) );
1259
1260#if CONFIG_DEBUG_PROCESS_MAKE_EXEC
1261cycle = (uint32_t)hal_get_cycles();
1262if( CONFIG_DEBUG_PROCESS_MAKE_EXEC < cycle )
1263printk("\n[DBG] %s : thread %x created new process %x / cycle %d \n",
1264__FUNCTION__ , old_thread , new_process , cycle );
1265#endif
1266
1267 // register code & data vsegs as well as entry-point in new process VMM,
1268 // and register extended pointer on .elf file in process descriptor
1269 if( elf_load_process( path , new_process ) )
1270 {
1271 printk("\n[ERROR] in %s : failed to access .elf file for path %s\n",
1272 __FUNCTION__ , path );
1273 process_destroy( new_process );
1274 return -1;
1275 }
1276
1277#if CONFIG_DEBUG_PROCESS_MAKE_EXEC
1278cycle = (uint32_t)hal_get_cycles();
1279if( CONFIG_DEBUG_PROCESS_MAKE_EXEC < cycle )
1280printk("\n[DBG] %s : thread %x registered code/data vsegs in new process %x / cycle %d\n",
1281__FUNCTION__, old_thread , new_process->pid , cycle );
1282#endif
1283
1284 // select a core in local cluster to execute the main thread
1285 lid = cluster_select_local_core();
1286
1287 // initialize pthread attributes for main thread
1288 attr.attributes = PT_ATTR_DETACH | PT_ATTR_CLUSTER_DEFINED | PT_ATTR_CORE_DEFINED;
1289 attr.cxy = local_cxy;
1290 attr.lid = lid;
1291
1292 // create and initialize main thread in local cluster
1293 error = thread_user_create( pid,
1294 (void *)new_process->vmm.entry_point,
1295 exec_info->args_pointers,
1296 &attr,
1297 &new_thread );
1298 if( error )
1299 {
1300 printk("\n[ERROR] in %s : cannot create thread for process %x\n",
1301 __FUNCTION__ , new_process );
1302 process_destroy( new_process );
1303 return -1;
1304 }
1305
1306 // check main thread index
1307 assert( (new_thread->trdid == 0) , __FUNCTION__ , "main thread must have index 0\n" );
1308
1309#if CONFIG_DEBUG_PROCESS_MAKE_EXEC
1310cycle = (uint32_t)hal_get_cycles();
1311if( CONFIG_DEBUG_PROCESS_MAKE_EXEC < cycle )
1312printk("\n[DBG] %s : thread %x created new_process main thread %x / cycle %d\n",
1313__FUNCTION__ , old_thread , new_thread , cycle );
1314#endif
1315
1316 // get cluster and local pointer on parent process
1317 process_t * parent_ptr = GET_PTR( parent_xp );
1318 cxy_t parent_cxy = GET_CXY( parent_xp );
1319
1320 // get extended pointers on parent children_root, children_lock and children_nr
1321 xptr_t root_xp = XPTR( parent_cxy , &parent_ptr->children_root );
1322 xptr_t lock_xp = XPTR( parent_cxy , &parent_ptr->children_lock );
1323 xptr_t nr_xp = XPTR( parent_cxy , &parent_ptr->children_nr );
1324
1325 // register new_process in parent children list
1326 remote_spinlock_lock( lock_xp );
1327 xlist_add_last( root_xp , XPTR( local_cxy , &new_process->children_list ) );
1328 hal_remote_atomic_add( nr_xp , 1 );
1329 remote_spinlock_unlock( lock_xp );
1330
1331 // activate new thread
1332 thread_unblock( XPTR( local_cxy , new_thread ) , THREAD_BLOCKED_GLOBAL );
1333
1334 // request old_thread destruction => old_process destruction
1335 thread_block( old_thread , THREAD_BLOCKED_GLOBAL );
1336 hal_atomic_or( &old_thread->flags , THREAD_FLAG_REQ_DELETE );
1337
1338 hal_fence();
1339
1340#if CONFIG_DEBUG_PROCESS_MAKE_EXEC
1341cycle = (uint32_t)hal_get_cycles();
1342if( CONFIG_DEBUG_PROCESS_MAKE_EXEC < cycle )
1343printk("\n[DBG] %s : old_thread %x blocked / new_thread %x activated / cycle %d\n",
1344__FUNCTION__ , old_thread , new_thread , cycle );
1345#endif
1346
1347 return 0;
1348
1349} // end process_make_exec()
1350
1351////////////////////////////////////////////
1352void process_make_kill( process_t * process,
1353 bool_t is_exit,
1354 uint32_t exit_status )
1355{
1356 thread_t * this = CURRENT_THREAD;
1357
1358 assert( (CXY_FROM_PID( process->pid ) == local_cxy) , __FUNCTION__ ,
1359 "must be executed in process owner cluster\n" );
1360
1361 assert( ( this->type == THREAD_RPC ) , __FUNCTION__ ,
1362 "must be executed by an RPC thread\n" );
1363
1364#if CONFIG_DEBUG_PROCESS_MAKE_KILL
1365uint32_t cycle = (uint32_t)hal_get_cycles();
1366if( CONFIG_DEBUG_PROCESS_MAKE_KILL < cycle )
1367printk("\n[DBG] %s : thread %x enter for process %x / cycle %d\n",
1368__FUNCTION__, this , process->pid , cycle );
1369#endif
1370
1371 // register exit_status in owner process descriptor
1372 if( is_exit ) process->term_state = exit_status;
1373
1374 // atomically update owner process descriptor flags
1375 if( is_exit ) hal_atomic_or( &process->term_state , PROCESS_FLAG_EXIT );
1376 else hal_atomic_or( &process->term_state , PROCESS_FLAG_KILL );
1377
1378 // remove TXT ownership from owner process descriptor
1379 process_txt_reset_ownership( XPTR( local_cxy , process ) );
1380
1381 // block all process threads in all clusters
1382 process_sigaction( process , BLOCK_ALL_THREADS );
1383
1384 // mark all process threads in all clusters for delete
1385 process_sigaction( process , DELETE_ALL_THREADS );
1386
1387/* unused if sys_wait deschedules without blocking [AG]
1388
1389 // get cluster and pointers on reference parent process
1390 xptr_t parent_xp = process->parent_xp;
1391 process_t * parent_ptr = GET_PTR( parent_xp );
1392 cxy_t parent_cxy = GET_CXY( parent_xp );
1393
1394 // get loal pointer on parent main thread
1395 thread_t * main_ptr = hal_remote_lpt( XPTR( parent_cxy , &parent_ptr->th_tbl[0] ) );
1396
1397 // reset THREAD_BLOCKED_WAIT bit in parent process main thread
1398 thread_unblock( XPTR( parent_cxy , main_ptr ) , THREAD_BLOCKED_WAIT );
1399*/
1400
1401#if CONFIG_DEBUG_PROCESS_MAKE_KILL
1402cycle = (uint32_t)hal_get_cycles();
1403if( CONFIG_DEBUG_PROCESS_MAKE_KILL < cycle )
1404printk("\n[DBG] %s : thread %x exit for process %x / cycle %d\n",
1405__FUNCTION__, this, process->pid , cycle );
1406#endif
1407
1408} // end process_make_kill()
1409
1410///////////////////////////////////////////////
1411void process_zero_create( process_t * process )
1412{
1413
1414#if CONFIG_DEBUG_PROCESS_ZERO_CREATE
1415uint32_t cycle = (uint32_t)hal_get_cycles();
1416if( CONFIG_DEBUG_PROCESS_ZERO_CREATE < cycle )
1417printk("\n[DBG] %s : thread %x enter / cycle %d\n", __FUNCTION__, CURRENT_THREAD, cycle );
1418#endif
1419
1420 // initialize PID, REF_XP, PARENT_XP, and STATE
1421 process->pid = 0;
1422 process->ref_xp = XPTR( local_cxy , process );
1423 process->parent_xp = XPTR_NULL;
1424 process->term_state = 0;
1425
1426 // reset th_tbl[] array as empty
1427 uint32_t i;
1428 for( i = 0 ; i < CONFIG_THREAD_MAX_PER_CLUSTER ; i++ )
1429 {
1430 process->th_tbl[i] = NULL;
1431 }
1432 process->th_nr = 0;
1433 spinlock_init( &process->th_lock );
1434
1435 // reset children list as empty
1436 xlist_root_init( XPTR( local_cxy , &process->children_root ) );
1437 remote_spinlock_init( XPTR( local_cxy , &process->children_lock ) );
1438 process->children_nr = 0;
1439
1440 hal_fence();
1441
1442#if CONFIG_DEBUG_PROCESS_ZERO_CREATE
1443cycle = (uint32_t)hal_get_cycles();
1444if( CONFIG_DEBUG_PROCESS_ZERO_CREATE < cycle )
1445printk("\n[DBG] %s : thread %x exit / cycle %d\n", __FUNCTION__, CURRENT_THREAD, cycle );
1446#endif
1447
1448} // end process_zero_init()
1449
1450//////////////////////////
1451void process_init_create()
1452{
1453 process_t * process; // local pointer on process descriptor
1454 pid_t pid; // process_init identifier
1455 thread_t * thread; // local pointer on main thread
1456 pthread_attr_t attr; // main thread attributes
1457 lid_t lid; // selected core local index for main thread
1458 error_t error;
1459
1460#if CONFIG_DEBUG_PROCESS_INIT_CREATE
1461uint32_t cycle = (uint32_t)hal_get_cycles();
1462if( CONFIG_DEBUG_PROCESS_INIT_CREATE < cycle )
1463printk("\n[DBG] %s : thread %x enter / cycle %d\n", __FUNCTION__, CURRENT_THREAD, cycle );
1464#endif
1465
1466 // allocates memory for process descriptor from local cluster
1467 process = process_alloc();
1468 if( process == NULL )
1469 {
1470 printk("\n[PANIC] in %s : no memory for process descriptor in cluster %x\n",
1471 __FUNCTION__, local_cxy );
1472 }
1473
1474 // get PID from local cluster
1475 error = cluster_pid_alloc( process , &pid );
1476 if( error )
1477 {
1478 printk("\n[PANIC] in %s : cannot allocate PID in cluster %x\n",
1479 __FUNCTION__, local_cxy );
1480 process_free( process );
1481 }
1482
1483 // check allocated PID
1484 assert( (pid == 1) , __FUNCTION__ , "process INIT must be first process in cluster 0\n" );
1485
1486 // initialize process descriptor / parent is local process_zero
1487 process_reference_init( process,
1488 pid,
1489 XPTR( local_cxy , &process_zero ), // parent
1490 XPTR( local_cxy , &process_zero ) ); // model
1491
1492 // register "code" and "data" vsegs as well as entry-point
1493 // in process VMM, using information contained in the elf file.
1494 if( elf_load_process( CONFIG_PROCESS_INIT_PATH , process ) )
1495 {
1496 printk("\n[PANIC] in %s : cannot access .elf file / path = %s\n",
1497 __FUNCTION__, CONFIG_PROCESS_INIT_PATH );
1498 process_destroy( process );
1499 }
1500
1501 // get extended pointers on process_zero children_root, children_lock
1502 xptr_t children_root_xp = XPTR( local_cxy , &process_zero.children_root );
1503 xptr_t children_lock_xp = XPTR( local_cxy , &process_zero.children_lock );
1504
1505 // register process INIT in parent local process_zero
1506 remote_spinlock_lock( children_lock_xp );
1507 xlist_add_last( children_root_xp , XPTR( local_cxy , &process->children_list ) );
1508 hal_atomic_add( &process_zero.children_nr , 1 );
1509 remote_spinlock_unlock( children_lock_xp );
1510
1511 // select a core in local cluster to execute the main thread
1512 lid = cluster_select_local_core();
1513
1514 // initialize pthread attributes for main thread
1515 attr.attributes = PT_ATTR_DETACH | PT_ATTR_CLUSTER_DEFINED | PT_ATTR_CORE_DEFINED;
1516 attr.cxy = local_cxy;
1517 attr.lid = lid;
1518
1519 // create and initialize thread descriptor
1520 error = thread_user_create( pid,
1521 (void *)process->vmm.entry_point,
1522 NULL,
1523 &attr,
1524 &thread );
1525 if( error )
1526 {
1527 printk("\n[PANIC] in %s : cannot create main thread / path = %s\n",
1528 __FUNCTION__, CONFIG_PROCESS_INIT_PATH );
1529 process_destroy( process );
1530 }
1531
1532 // check main thread index
1533 assert( (thread->trdid == 0) , __FUNCTION__ , "main thread must have index 0\n" );
1534
1535 // activate thread
1536 thread_unblock( XPTR( local_cxy , thread ) , THREAD_BLOCKED_GLOBAL );
1537
1538 hal_fence();
1539
1540#if CONFIG_DEBUG_PROCESS_INIT_CREATE
1541cycle = (uint32_t)hal_get_cycles();
1542if( CONFIG_DEBUG_PROCESS_INIT_CREATE < cycle )
1543printk("\n[DBG] %s : thread %x exit / cycle %d\n", __FUNCTION__, CURRENT_THREAD, cycle );
1544#endif
1545
1546} // end process_init_create()
1547
1548/////////////////////////////////////////
1549void process_display( xptr_t process_xp )
1550{
1551 process_t * process_ptr;
1552 cxy_t process_cxy;
1553 xptr_t parent_xp; // extended pointer on parent process
1554 process_t * parent_ptr;
1555 cxy_t parent_cxy;
1556
1557 pid_t pid;
1558 pid_t ppid;
1559 uint32_t state;
1560 xptr_t ref_xp;
1561 uint32_t th_nr;
1562
1563 xptr_t txt_file_xp; // extended pointer on TXT_RX pseudo file
1564 xptr_t chdev_xp; // extended pointer on TXT_RX chdev
1565 chdev_t * chdev_ptr;
1566 cxy_t chdev_cxy;
1567 xptr_t owner_xp; // extended pointer on TXT owner process
1568
1569 xptr_t elf_file_xp; // extended pointer on .elf file
1570 cxy_t elf_file_cxy;
1571 vfs_file_t * elf_file_ptr;
1572 vfs_inode_t * elf_inode_ptr; // local pointer on .elf inode
1573
1574 char txt_name[CONFIG_VFS_MAX_NAME_LENGTH];
1575 char elf_name[CONFIG_VFS_MAX_NAME_LENGTH];
1576
1577 // get cluster and local pointer on process
1578 process_ptr = GET_PTR( process_xp );
1579 process_cxy = GET_CXY( process_xp );
1580
1581 // check reference process
1582 ref_xp = hal_remote_lwd( XPTR( process_cxy , &process_ptr->ref_xp ) );
1583 assert( (process_xp == ref_xp) , __FUNCTION__ , "process is not the reference\n");
1584
1585 // get PID and state
1586 pid = hal_remote_lw( XPTR( process_cxy , &process_ptr->pid ) );
1587 state = hal_remote_lw( XPTR( process_cxy , &process_ptr->term_state ) );
1588
1589 // get PPID
1590 parent_xp = hal_remote_lwd( XPTR( process_cxy , &process_ptr->parent_xp ) );
1591 parent_cxy = GET_CXY( parent_xp );
1592 parent_ptr = GET_PTR( parent_xp );
1593 ppid = hal_remote_lw( XPTR( parent_cxy , &parent_ptr->pid ) );
1594
1595 // get number of threads
1596 th_nr = hal_remote_lw( XPTR( process_cxy , &process_ptr->th_nr ) );
1597
1598 // get TXT name and process owner
1599 txt_file_xp = hal_remote_lwd( XPTR( process_cxy , &process_ptr->fd_array.array[0] ) );
1600
1601 assert( (txt_file_xp != XPTR_NULL) , __FUNCTION__ ,
1602 "process must be attached to one TXT terminal\n" );
1603
1604 chdev_xp = chdev_from_file( txt_file_xp );
1605 chdev_cxy = GET_CXY( chdev_xp );
1606 chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
1607 hal_remote_strcpy( XPTR( local_cxy , txt_name ) ,
1608 XPTR( chdev_cxy , chdev_ptr->name ) );
1609 owner_xp = (xptr_t)hal_remote_lwd( XPTR( chdev_cxy , &chdev_ptr->ext.txt.owner_xp ) );
1610
1611 // get process .elf name
1612 elf_file_xp = hal_remote_lwd( XPTR( process_cxy , &process_ptr->vfs_bin_xp ) );
1613
1614 elf_file_cxy = GET_CXY( elf_file_xp );
1615 elf_file_ptr = (vfs_file_t *)GET_PTR( elf_file_xp );
1616 elf_inode_ptr = (vfs_inode_t *)hal_remote_lpt( XPTR( elf_file_cxy , &elf_file_ptr->inode ) );
1617 vfs_inode_get_name( XPTR( elf_file_cxy , elf_inode_ptr ) , elf_name );
1618
1619 // display process info
1620 if( owner_xp == process_xp )
1621 {
1622 printk("PID %X | PPID %X | STS %X | %s (FG) | %X | %d | %s\n",
1623 pid, ppid, state, txt_name, process_ptr, th_nr, elf_name );
1624 }
1625 else
1626 {
1627 printk("PID %X | PPID %X | STS %X | %s (BG) | %X | %d | %s\n",
1628 pid, ppid, state, txt_name, process_ptr, th_nr, elf_name );
1629 }
1630} // end process_display()
1631
1632
1633////////////////////////////////////////////////////////////////////////////////////////
1634// Terminals related functions
1635////////////////////////////////////////////////////////////////////////////////////////
1636
1637////////////////////////////
1638uint32_t process_txt_alloc()
1639{
1640 uint32_t index; // TXT terminal index
1641 xptr_t chdev_xp; // extended pointer on TXT_RX chdev
1642 chdev_t * chdev_ptr; // local pointer on TXT_RX chdev
1643 cxy_t chdev_cxy; // TXT_RX chdev cluster
1644 xptr_t root_xp; // extended pointer on owner field in chdev
1645
1646 // scan the user TXT_RX chdevs (TXT0 is reserved for kernel)
1647 for( index = 1 ; index < LOCAL_CLUSTER->nb_txt_channels ; index ++ )
1648 {
1649 // get pointers on TXT_RX[index]
1650 chdev_xp = chdev_dir.txt_rx[index];
1651 chdev_cxy = GET_CXY( chdev_xp );
1652 chdev_ptr = GET_PTR( chdev_xp );
1653
1654 // get extended pointer on root of attached process
1655 root_xp = XPTR( chdev_cxy , &chdev_ptr->ext.txt.root );
1656
1657 // return free TXT index if found
1658 if( xlist_is_empty( root_xp ) ) return index;
1659 }
1660
1661 assert( false , __FUNCTION__ , "no free TXT terminal found" );
1662
1663 return -1;
1664
1665} // end process_txt_alloc()
1666
1667/////////////////////////////////////////////
1668void process_txt_attach( process_t * process,
1669 uint32_t txt_id )
1670{
1671 xptr_t chdev_xp; // extended pointer on TXT_RX chdev
1672 cxy_t chdev_cxy; // TXT_RX chdev cluster
1673 chdev_t * chdev_ptr; // local pointer on TXT_RX chdev
1674 xptr_t root_xp; // extended pointer on list root in chdev
1675 xptr_t lock_xp; // extended pointer on list lock in chdev
1676
1677#if CONFIG_DEBUG_PROCESS_TXT_ATTACH
1678uint32_t cycle = (uint32_t)hal_get_cycles();
1679if( CONFIG_DEBUG_PROCESS_TXT_ATTACH < cycle )
1680printk("\n[DBG] %s : thread %x enter for process %x / txt_id = %d / cycle %d\n",
1681__FUNCTION__, CURRENT_THREAD, process->pid, txt_id, cycle );
1682#endif
1683
1684 // check process is reference
1685 assert( (process->ref_xp == XPTR( local_cxy , process )) , __FUNCTION__ ,
1686 "process is not the reference descriptor" );
1687
1688 // check terminal index
1689 assert( (txt_id < LOCAL_CLUSTER->nb_txt_channels) ,
1690 __FUNCTION__ , "illegal TXT terminal index" );
1691
1692 // get pointers on TXT_RX[txt_id] chdev
1693 chdev_xp = chdev_dir.txt_rx[txt_id];
1694 chdev_cxy = GET_CXY( chdev_xp );
1695 chdev_ptr = GET_PTR( chdev_xp );
1696
1697 // get extended pointer on root & lock of attached process list
1698 root_xp = XPTR( chdev_cxy , &chdev_ptr->ext.txt.root );
1699 lock_xp = XPTR( chdev_cxy , &chdev_ptr->ext.txt.lock );
1700
1701 // insert process in attached process list
1702 remote_spinlock_lock( lock_xp );
1703 xlist_add_last( root_xp , XPTR( local_cxy , &process->txt_list ) );
1704 remote_spinlock_unlock( lock_xp );
1705
1706#if CONFIG_DEBUG_PROCESS_TXT_ATTACH
1707cycle = (uint32_t)hal_get_cycles();
1708if( CONFIG_DEBUG_PROCESS_TXT_ATTACH < cycle )
1709printk("\n[DBG] %s : thread %x exit for process %x / txt_id = %d / cycle %d\n",
1710__FUNCTION__, CURRENT_THREAD, process->pid, txt_id , cycle );
1711#endif
1712
1713} // end process_txt_attach()
1714
1715//////////////////////////////////////////////
1716void process_txt_detach( process_t * process )
1717{
1718 xptr_t chdev_xp; // extended pointer on TXT_RX chdev
1719 cxy_t chdev_cxy; // TXT_RX chdev cluster
1720 chdev_t * chdev_ptr; // local pointer on TXT_RX chdev
1721 xptr_t lock_xp; // extended pointer on list lock in chdev
1722
1723#if CONFIG_DEBUG_PROCESS_TXT_DETACH
1724uint32_t cycle = (uint32_t)hal_get_cycles();
1725if( CONFIG_DEBUG_PROCESS_TXT_DETACH < cycle )
1726printk("\n[DBG] %s : thread %x enter for process %x / cycle %d\n",
1727__FUNCTION__, CURRENT_THREAD, process->pid , cycle );
1728#endif
1729
1730 // check process is reference
1731 assert( (process->ref_xp == XPTR( local_cxy , process )) , __FUNCTION__ ,
1732 "process is not the reference descriptor" );
1733
1734 // get extended pointer on TXT_RX chdev
1735 chdev_xp = chdev_from_file( process->fd_array.array[0] );
1736 chdev_cxy = GET_CXY( chdev_xp );
1737 chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
1738
1739 // get extended pointer on lock of attached process list
1740 lock_xp = XPTR( chdev_cxy , &chdev_ptr->ext.txt.lock );
1741
1742 // unlink process from attached process list
1743 remote_spinlock_lock( lock_xp );
1744 xlist_unlink( XPTR( local_cxy , &process->txt_list ) );
1745 remote_spinlock_unlock( lock_xp );
1746
1747#if CONFIG_DEBUG_PROCESS_TXT_DETACH
1748cycle = (uint32_t)hal_get_cycles();
1749if( CONFIG_DEBUG_PROCESS_TXT_DETACH < cycle )
1750printk("\n[DBG] %s : thread %x exit for process %x / cycle %d\n",
1751__FUNCTION__, CURRENT_THREAD, process->pid, cycle );
1752#endif
1753
1754} // end process_txt_detach()
1755
1756///////////////////////////////////////////////////
1757void process_txt_set_ownership( xptr_t process_xp )
1758{
1759 process_t * process_ptr;
1760 cxy_t process_cxy;
1761 xptr_t file_xp;
1762 xptr_t txt_xp;
1763 chdev_t * txt_ptr;
1764 cxy_t txt_cxy;
1765
1766 // get cluster and local pointer on process
1767 process_cxy = GET_CXY( process_xp );
1768 process_ptr = (process_t *)GET_PTR( process_xp );
1769
1770 // get extended pointer on stdin pseudo file
1771 file_xp = hal_remote_lwd( XPTR( process_cxy , &process_ptr->fd_array.array[0] ) );
1772
1773 // get pointers on TXT chdev
1774 txt_xp = chdev_from_file( file_xp );
1775 txt_cxy = GET_CXY( txt_xp );
1776 txt_ptr = (chdev_t *)GET_PTR( txt_xp );
1777
1778 // set owner field in TXT chdev
1779 hal_remote_swd( XPTR( txt_cxy , &txt_ptr->ext.txt.owner_xp ) , process_xp );
1780
1781} // end process_txt_set ownership()
1782
1783/////////////////////////////////////////////////////
1784void process_txt_reset_ownership( xptr_t process_xp )
1785{
1786 process_t * process_ptr;
1787 cxy_t process_cxy;
1788 xptr_t parent_xp; // extended pointer on parent process
1789 process_t * parent_ptr;
1790 cxy_t parent_cxy;
1791 xptr_t file_xp; // extended pointer on TXT_RX pseudo file
1792 xptr_t txt_xp; // extended pointer on TXT_RX chdev
1793 chdev_t * txt_ptr; // local pointer on TXT_RX chdev
1794 cxy_t txt_cxy; // cluster of TXT_RX chdev
1795 uint32_t txt_id; // TXT_RX channel
1796 xptr_t owner_xp; // extended pointer on current TXT_RX owner
1797 xptr_t root_xp; // extended pointer on root of attached process list
1798 xptr_t iter_xp; // iterator for xlist
1799 xptr_t current_xp; // extended pointer on current process
1800 process_t * current_ptr; // local pointer on current process
1801 cxy_t current_cxy; // cluster for current process
1802 pid_t ppid; // parent process identifier for current process
1803
1804 // get cluster and local pointer on process
1805 process_cxy = GET_CXY( process_xp );
1806 process_ptr = (process_t *)GET_PTR( process_xp );
1807
1808 // get extended pointer on stdin pseudo file
1809 file_xp = hal_remote_lwd( XPTR( process_cxy , &process_ptr->fd_array.array[0] ) );
1810
1811 // get pointers on TXT chdev
1812 txt_xp = chdev_from_file( file_xp );
1813 txt_cxy = GET_CXY( txt_xp );
1814 txt_ptr = GET_PTR( txt_xp );
1815
1816 // get extended pointer on TXT_RX owner and TXT channel
1817 owner_xp = hal_remote_lwd( XPTR( txt_cxy , &txt_ptr->ext.txt.owner_xp ) );
1818 txt_id = hal_remote_lw ( XPTR( txt_cxy , &txt_ptr->channel ) );
1819
1820 // transfer ownership to KSH if required
1821 if( (owner_xp == process_xp) && (txt_id > 0) )
1822 {
1823 // get extended pointer on root of list of attached processes
1824 root_xp = hal_remote_lwd( XPTR( txt_cxy , &txt_ptr->ext.txt.root ) );
1825
1826 // scan attached process list to find KSH process
1827 XLIST_FOREACH( root_xp , iter_xp )
1828 {
1829 current_xp = XLIST_ELEMENT( iter_xp , process_t , txt_list );
1830 current_cxy = GET_CXY( current_xp );
1831 current_ptr = GET_PTR( current_xp );
1832 parent_xp = hal_remote_lwd( XPTR( current_cxy , &current_ptr->parent_xp ) );
1833
1834 parent_cxy = GET_CXY( parent_xp );
1835 parent_ptr = GET_PTR( parent_xp );
1836 ppid = hal_remote_lw( XPTR( parent_cxy , &parent_ptr->pid ) );
1837
1838 if( ppid == 1 ) // current is KSH
1839 {
1840 // set owner field in TXT chdev
1841 hal_remote_swd( XPTR( txt_cxy , &txt_ptr->ext.txt.owner_xp ) , current_xp );
1842 return;
1843 }
1844 }
1845
1846 assert( false , __FUNCTION__ , "KSH process not found" );
1847 }
1848} // end process_txt_reset_ownership()
1849
1850
1851
Note: See TracBrowser for help on using the repository browser.