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

Last change on this file since 625 was 625, checked in by alain, 2 years ago

Fix a bug in the vmm_remove_vseg() function: the physical pages
associated to an user DATA vseg were released to the kernel when
the target process descriptor was in the reference cluster.
This physical pages release should be done only when the page
forks counter value is zero.
All other modifications are cosmetic.

File size: 6.5 KB
Line 
1/*
2 * sys_wait.c - wait termination or blocking of a child process.
3 *
4 * Author    Alain Greiner (2016,2017,2018,2019)
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[%s] thread[%x,%x] enter / cycle %d\n",
59__FUNCTION__, pid, this->trdid, (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,%x]\n",
70__FUNCTION__ , (intptr_t)status, pid, this->trdid );
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,%x] is not thread 0 in owner cluster %x\n",
89__FUNCTION__ , pid, this->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            // test if this child process is terminated,
122            // but termination not yet reported to parent process
123            if( ((child_state & PROCESS_TERM_EXIT)  || 
124                 (child_state & PROCESS_TERM_KILL)  ||
125                 (child_state & PROCESS_TERM_STOP)) &&
126                 ((child_state & PROCESS_TERM_WAIT) == 0) )
127            {
128                // set the PROCESS_TERM_WAIT in child process descriptor
129                hal_remote_atomic_or( XPTR( child_cxy , &child_ptr->term_state ),
130                                      PROCESS_TERM_WAIT );
131
132                // set the THREAD_FLAG_REQ_DELETE in main thread if kill or exit
133                if((child_state & PROCESS_TERM_EXIT) || (child_state & PROCESS_TERM_KILL))
134                hal_remote_atomic_or( XPTR( child_cxy , &child_thread->flags ) ,
135                                            THREAD_FLAG_REQ_DELETE );
136
137                // release lock protecting children list
138                remote_queuelock_release( children_lock_xp );
139
140#if DEBUG_SYS_WAIT
141cycle = hal_get_cycles();
142if( DEBUG_SYS_WAIT < cycle )
143{
144    if( child_state & PROCESS_TERM_EXIT )
145        printk("\n[%s] thread[%x,%x] exit : child process %x terminated / cycle %d\n",
146        __FUNCTION__, pid, this->trdid, child_pid, (uint32_t)cycle );
147    if( child_state & PROCESS_TERM_KILL )
148        printk("\n[%s] thread[%x,%x] exit : child process %x killed / cycle %d\n",
149        __FUNCTION__, pid, this->trdid, child_pid, (uint32_t)cycle );
150    if( child_state & PROCESS_TERM_STOP )
151        printk("\n[%s] thread[%x,%x] exit : child process %x stopped / cycle %d\n",
152        __FUNCTION__, pid, this->trdid, child_pid, (uint32_t)cycle );
153}
154#endif
155                 // return child termination state  to parent process
156                 hal_copy_to_uspace( status , &child_state , sizeof(int) );
157                 return child_pid;
158            }
159        }  // end loop on children
160       
161        // we execute this code when no child change detected
162        // - release the lock protecting children list,
163        // - block on the WAIT condition
164        // - deschedule to keep waiting in the while loop
165
166        // release lock protecting children list
167        remote_queuelock_release( children_lock_xp );
168
169        // block on WAIT condition
170        thread_block( XPTR( local_cxy , this ) , THREAD_BLOCKED_WAIT );
171
172#if (DEBUG_SYS_WAIT & 1)
173cycle = hal_get_cycles();
174if( DEBUG_SYS_WAIT < cycle )
175printk("\n[%s] thread[%x,%x] block & deschedule / cycle %d\n",
176__FUNCTION__, pid, this->trdid, (uint32_t)cycle );
177#endif
178
179        // deschedule
180        sched_yield( "parent process wait children processes termination" );
181
182#if (DEBUG_SYS_WAIT & 1)
183cycle = hal_get_cycles();
184if( DEBUG_SYS_WAIT < cycle )
185printk("\n[%s] thread[%x,%x] resume / cycle %d\n",
186__FUNCTION__, pid, this->trdid, (uint32_t)cycle );
187#endif
188
189    }  // end while
190
191    // never executed
192        return -1; 
193
194}  // end sys_wait()
Note: See TracBrowser for help on using the repository browser.