source: trunk/kernel/syscalls/sys_wait.c @ 624

Last change on this file since 624 was 624, checked in by alain, 5 years ago

Fix several bugs to use the instruction MMU in kernel mode
in replacement of the instruction address extension register,
and remove the "kentry" segment.

This version is running on the tsar_generic_iob" platform.

One interesting bug: the cp0_ebase defining the kernel entry point
(for interrupts, exceptions and syscalls) must be initialized
early in kernel_init(), because the VFS initialisation done by
kernel_ini() uses RPCs, and RPCs uses Inter-Processor-Interrup.

File size: 6.8 KB
Line 
1/*
2 * sys_wait.c - wait termination or blocking of a child process.
3 *
4 * Author    Alain Greiner (2016,2017,2018)
5 * 
6 * Copyright (c) UPMC Sorbonne Universites
7 *
8 * This file is part of ALMOS-MKH.
9 *
10 * ALMOS-MKH is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; version 2.0 of the License.
13 *
14 * ALMOS-MKH is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24#include <hal_kernel_types.h>
25#include <hal_uspace.h>
26#include <hal_irqmask.h>
27#include <hal_vmm.h>
28#include <remote_queuelock.h>
29#include <core.h>
30#include <thread.h>
31#include <process.h>
32#include <vmm.h>
33#include <printk.h>
34
35#include <syscalls.h>
36
37/////////////////////////////////
38int sys_wait( uint32_t * status )
39{
40        error_t     error;
41    vseg_t    * vseg;
42    xptr_t      iter_xp;
43    xptr_t      child_xp;
44    process_t * child_ptr;
45    cxy_t       child_cxy;
46    pid_t       child_pid;
47    uint32_t    child_state;
48    thread_t  * child_thread;
49    reg_t       save_sr;
50
51    thread_t  * this    = CURRENT_THREAD;
52    process_t * process = this->process;
53    pid_t       pid     = process->pid;
54
55#if DEBUG_SYS_WAIT
56uint64_t    cycle = hal_get_cycles();
57if( DEBUG_SYS_WAIT < cycle )
58printk("\n[DBG] %s : thread %x in process %x enter / cycle %d\n",
59__FUNCTION__, this, process->pid, (uint32_t)cycle );
60#endif
61
62    // check status in user space
63    error = vmm_get_vseg( process, (intptr_t)status , &vseg );
64
65        if( error )
66        {
67
68#if DEBUG_SYSCALLS_ERROR
69printk("\n[ERROR] in %s : status buffer %x unmapped for thread %x in process %x\n",
70__FUNCTION__ , (intptr_t)status, this->trdid , process->pid );
71hal_vmm_display( process , false );
72#endif
73        this->errno = EINVAL;
74                return -1;
75        }
76
77    // get calling process owner cluster
78    cxy_t   owner_cxy = CXY_FROM_PID( pid );
79
80    // get calling thread trdid
81    trdid_t trdid = this->trdid;
82
83    // this function must be executed by the process main thread
84    if( (owner_cxy != local_cxy) || (LTID_FROM_TRDID(trdid) != 0) )
85    {
86
87#if DEBUG_SYSCALLS_ERROR
88printk("\n[ERROR] in %s : calling thread %x is not thread 0 in owner cluster %x\n",
89__FUNCTION__ , trdid , owner_cxy );
90#endif
91        this->errno = EINVAL;
92                return -1;
93        }
94
95    // get extended pointer on children list root and lock
96    xptr_t children_root_xp = XPTR( owner_cxy , &process->children_root );
97    xptr_t children_lock_xp = XPTR( owner_cxy , &process->children_lock );
98
99    // exit this loop only when a child processes change state
100    while( 1 )
101    {
102        // enable IRQS
103        hal_enable_irq( &save_sr );
104 
105        // get lock protecting children list
106        remote_queuelock_acquire( children_lock_xp );
107
108        // scan the list of child process
109        XLIST_FOREACH( children_root_xp , iter_xp )
110        {
111            // get child process owner cluster and local pointer
112            child_xp  = XLIST_ELEMENT( iter_xp , process_t , children_list );
113            child_ptr = GET_PTR( child_xp );
114            child_cxy = GET_CXY( child_xp );
115
116            // get PID, term_state, and main thread from child process
117            child_pid    = hal_remote_l32 (XPTR( child_cxy , &child_ptr->pid ));
118            child_state  = hal_remote_l32 ( XPTR(child_cxy , &child_ptr->term_state ) );
119            child_thread = hal_remote_lpt(XPTR( child_cxy , &child_ptr->th_tbl[0] ));
120
121#if (DEBUG_SYS_WAIT & 1)
122cycle = hal_get_cycles();
123if( DEBUG_SYS_WAIT < cycle )
124printk("\n[DBG] %s : thread %x in process %x check child %x / state %x\n",
125__FUNCTION__, this, process->pid, child_pid, child_state );
126#endif
127            // test if this child process is terminated,
128            // but termination not yet reported to parent process
129            if( ((child_state & PROCESS_TERM_EXIT)  || 
130                 (child_state & PROCESS_TERM_KILL)  ||
131                 (child_state & PROCESS_TERM_STOP)) &&
132                 ((child_state & PROCESS_TERM_WAIT) == 0) )
133            {
134                // set the PROCESS_TERM_WAIT in child process descriptor
135                hal_remote_atomic_or( XPTR( child_cxy , &child_ptr->term_state ),
136                                      PROCESS_TERM_WAIT );
137
138                // set the THREAD_FLAG_REQ_DELETE in main thread if kill or exit
139                if((child_state & PROCESS_TERM_EXIT) || (child_state & PROCESS_TERM_KILL))
140                hal_remote_atomic_or( XPTR( child_cxy , &child_thread->flags ) ,
141                                            THREAD_FLAG_REQ_DELETE );
142
143                // release lock protecting children list
144                remote_queuelock_release( children_lock_xp );
145
146#if DEBUG_SYS_WAIT
147cycle = hal_get_cycles();
148if( DEBUG_SYS_WAIT < cycle )
149{
150    if     ( child_state & PROCESS_TERM_EXIT )
151        printk("\n[DBG] %s : thread %x in process %x exit / child %x exit / cycle %d\n",
152        __FUNCTION__, this, process->pid, child_pid, (uint32_t)cycle );
153    if( child_state & PROCESS_TERM_KILL )
154        printk("\n[DBG] %s : thread %x in process %x exit / child %x killed / cycle %d\n",
155        __FUNCTION__, this, process->pid, child_pid, (uint32_t)cycle );
156    if( child_state & PROCESS_TERM_STOP )
157        printk("\n[DBG] %s : thread %x in process %x exit / child %x stopped / cycle %d\n",
158        __FUNCTION__, this, process->pid, child_pid, (uint32_t)cycle );
159}
160#endif
161                 // return child termination state  to parent process
162                 hal_copy_to_uspace( status , &child_state , sizeof(int) );
163                 return child_pid;
164            }
165        }  // end loop on children
166       
167        // we execute this code when no child terminated:
168        // - release the lock protecting children list,
169        // - block on the WAIT condition
170        // - deschedule to keep waiting in the while loop
171
172        // release lock protecting children list
173        remote_queuelock_release( children_lock_xp );
174
175        // block on WAIT condition
176        thread_block( XPTR( local_cxy , this ) , THREAD_BLOCKED_WAIT );
177
178#if (DEBUG_SYS_WAIT & 1)
179cycle = hal_get_cycles();
180if( DEBUG_SYS_WAIT < cycle )
181printk("\n[DBG] %s : thread %x in process %x block & deschedule / cycle %d\n",
182__FUNCTION__, this, process->pid, (uint32_t)cycle );
183#endif
184
185        // deschedule
186        sched_yield( "parent process wait children processes termination" );
187
188#if (DEBUG_SYS_WAIT & 1)
189cycle = hal_get_cycles();
190if( DEBUG_SYS_WAIT < cycle )
191printk("\n[DBG] %s : thread %x in process %x unblock & resume / cycle %d\n",
192__FUNCTION__, this, process->pid, (uint32_t)cycle );
193#endif
194
195    }  // end while
196
197    // never executed
198        return -1; 
199
200}  // end sys_wait()
Note: See TracBrowser for help on using the repository browser.