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

Last change on this file since 625 was 625, checked in by alain, 5 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
RevLine 
[421]1/*
2 * sys_wait.c - wait termination or blocking of a child process.
3 *
[625]4 * Author    Alain Greiner (2016,2017,2018,2019)
[421]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
[457]24#include <hal_kernel_types.h>
[421]25#include <hal_uspace.h>
[435]26#include <hal_irqmask.h>
[624]27#include <hal_vmm.h>
[566]28#include <remote_queuelock.h>
[421]29#include <core.h>
30#include <thread.h>
31#include <process.h>
32#include <vmm.h>
33#include <printk.h>
34
[506]35#include <syscalls.h>
36
[421]37/////////////////////////////////
38int sys_wait( uint32_t * status )
39{
40        error_t     error;
[440]41    vseg_t    * vseg;
[421]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;
[446]47    uint32_t    child_state;
[433]48    thread_t  * child_thread;
[435]49    reg_t       save_sr;
[421]50
51    thread_t  * this    = CURRENT_THREAD;
52    process_t * process = this->process;
[433]53    pid_t       pid     = process->pid;
[421]54
[438]55#if DEBUG_SYS_WAIT
[446]56uint64_t    cycle = hal_get_cycles();
57if( DEBUG_SYS_WAIT < cycle )
[625]58printk("\n[%s] thread[%x,%x] enter / cycle %d\n",
59__FUNCTION__, pid, this->trdid, (uint32_t)cycle );
[421]60#endif
61
62    // check status in user space
[440]63    error = vmm_get_vseg( process, (intptr_t)status , &vseg );
[421]64
65        if( error )
66        {
[435]67
[438]68#if DEBUG_SYSCALLS_ERROR
[625]69printk("\n[ERROR] in %s : status buffer %x unmapped for thread[%x,%x]\n",
70__FUNCTION__ , (intptr_t)status, pid, this->trdid );
[624]71hal_vmm_display( process , false );
[435]72#endif
[436]73        this->errno = EINVAL;
[421]74                return -1;
75        }
76
[443]77    // get calling process owner cluster
[436]78    cxy_t   owner_cxy = CXY_FROM_PID( pid );
[421]79
[443]80    // get calling thread trdid
81    trdid_t trdid = this->trdid;
82
83    // this function must be executed by the process main thread
[436]84    if( (owner_cxy != local_cxy) || (LTID_FROM_TRDID(trdid) != 0) )
85    {
[421]86
[446]87#if DEBUG_SYSCALLS_ERROR
[625]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 );
[436]90#endif
91        this->errno = EINVAL;
92                return -1;
93        }
94
[433]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 );
[421]98
[566]99    // exit this loop only when a child processes change state
[421]100    while( 1 )
101    {
[435]102        // enable IRQS
103        hal_enable_irq( &save_sr );
104 
[433]105        // get lock protecting children list
[566]106        remote_queuelock_acquire( children_lock_xp );
[421]107
[436]108        // scan the list of child process
[433]109        XLIST_FOREACH( children_root_xp , iter_xp )
[421]110        {
[433]111            // get child process owner cluster and local pointer
[421]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
[446]116            // get PID, term_state, and main thread from child process
[566]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 ) );
[446]119            child_thread = hal_remote_lpt(XPTR( child_cxy , &child_ptr->th_tbl[0] ));
[421]120
[443]121            // test if this child process is terminated,
[433]122            // but termination not yet reported to parent process
[435]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) )
[421]127            {
[566]128                // set the PROCESS_TERM_WAIT in child process descriptor
[433]129                hal_remote_atomic_or( XPTR( child_cxy , &child_ptr->term_state ),
[435]130                                      PROCESS_TERM_WAIT );
[433]131
[446]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))
[433]134                hal_remote_atomic_or( XPTR( child_cxy , &child_thread->flags ) ,
135                                            THREAD_FLAG_REQ_DELETE );
136
[435]137                // release lock protecting children list
[566]138                remote_queuelock_release( children_lock_xp );
[435]139
[438]140#if DEBUG_SYS_WAIT
[446]141cycle = hal_get_cycles();
142if( DEBUG_SYS_WAIT < cycle )
143{
[625]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 );
[446]147    if( child_state & PROCESS_TERM_KILL )
[625]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 );
[446]150    if( child_state & PROCESS_TERM_STOP )
[625]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 );
[446]153}
[421]154#endif
[436]155                 // return child termination state  to parent process
[433]156                 hal_copy_to_uspace( status , &child_state , sizeof(int) );
157                 return child_pid;
[421]158            }
[436]159        }  // end loop on children
[421]160       
[625]161        // we execute this code when no child change detected
[566]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
[446]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 )
[625]175printk("\n[%s] thread[%x,%x] block & deschedule / cycle %d\n",
176__FUNCTION__, pid, this->trdid, (uint32_t)cycle );
[446]177#endif
[421]178
[446]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 )
[625]185printk("\n[%s] thread[%x,%x] resume / cycle %d\n",
186__FUNCTION__, pid, this->trdid, (uint32_t)cycle );
[446]187#endif
188
[435]189    }  // end while
190
[421]191    // never executed
192        return -1; 
193
194}  // end sys_wait()
Note: See TracBrowser for help on using the repository browser.