source: trunk/kernel/syscalls/sys_kill.c @ 638

Last change on this file since 638 was 624, checked in by alain, 6 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: 7.7 KB
Line 
1/*
2 * sys_kill.c - Kernel function implementing the "kill" system call.
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 <kernel_config.h>
25#include <hal_kernel_types.h>
26#include <hal_irqmask.h>
27#include <errno.h>
28#include <thread.h>
29#include <printk.h>
30#include <process.h>
31#include <shared_syscalls.h>
32#include <cluster.h>
33#include <rpc.h>
34
35#include <syscalls.h>
36
37
38#if DEBUG_SYS_KILL
39////////////////////////////////////////////
40static char* sig_type_str( uint32_t sig_id )
41{
42    switch( sig_id )
43    {
44        case SIGKILL: return "SIGKILL";
45        case SIGSTOP: return "SIGSTOP";
46        case SIGCONT: return "SIGCONT";
47        default:      return "undefined";
48    }
49}
50#endif
51
52
53///////////////////////////
54int sys_kill( pid_t    pid,
55              uint32_t sig_id )
56{
57    xptr_t      owner_xp;          // extended pointer on process in owner cluster
58    cxy_t       owner_cxy;         // process owner cluster
59    process_t * owner_ptr;         // local pointer on process in owner cluster
60    xptr_t      parent_xp;         // extended pointer on parent process
61    cxy_t       parent_cxy;        // parent process cluster
62    process_t * parent_ptr;        // local pointer on parent process
63    thread_t  * parent_main_ptr;   // local pointer on parent main thread
64    xptr_t      parent_main_xp;    // extended pointer on parent main thread
65
66    thread_t  * this    = CURRENT_THREAD;
67    process_t * process = this->process;
68
69#if (DEBUG_SYS_KILL || CONFIG_INSTRUMENTATION_SYSCALLS)
70uint64_t     tm_start = hal_get_cycles();
71#endif
72
73#if DEBUG_SYS_KILL
74tm_start = hal_get_cycles();
75if( DEBUG_SYS_KILL < tm_start )
76printk("\n[%s] thread[%x,%x] enter : %s to process %x / cycle %d\n",
77__FUNCTION__, this->process->pid, this->trdid,
78sig_type_str(sig_id), pid, (uint32_t)tm_start );
79#endif
80
81    // get pointers on process descriptor in owner cluster
82    owner_xp  = cluster_get_owner_process_from_pid( pid );
83    owner_cxy = GET_CXY( owner_xp );
84    owner_ptr = GET_PTR( owner_xp );
85   
86#if (DEBUG_SYS_KILL & 1)
87if( DEBUG_SYS_KILL < tm_start )
88printk("\n[%s] thread[%x,%x] get target process descriptor %x in owner cluster %x\n",
89__FUNCTION__ , this->process->pid, this->trdid, owner_ptr, owner_cxy );
90#endif
91
92    // check process found
93    if( owner_xp == XPTR_NULL)
94    {
95
96#if DEBUG_SYSCALLS_ERROR
97printk("\n[ERROR] in %s : process %x not found\n", __FUNCTION__, pid );
98#endif
99        this->errno = EINVAL;
100        return -1;
101    }
102
103    // get parent process descriptor pointers
104    parent_xp  = (xptr_t)hal_remote_l64( XPTR( owner_cxy , &owner_ptr->parent_xp ) );
105    parent_cxy = GET_CXY( parent_xp );
106    parent_ptr = GET_PTR( parent_xp );
107
108#if (DEBUG_SYS_KILL & 1)
109if( DEBUG_SYS_KILL < tm_start )
110printk("\n[%s] thread[%x,%x] get parent process descriptor %x in cluster %x\n",
111__FUNCTION__ , this->process->pid, this->trdid, parent_ptr, parent_cxy );
112#endif
113
114    // get pointers on the parent process main thread
115    parent_main_ptr = hal_remote_lpt( XPTR( parent_cxy , &parent_ptr->th_tbl[0] ) ); 
116    parent_main_xp  = XPTR( parent_cxy , parent_main_ptr );
117
118    // analyse signal type / supported values are : 0, SIGSTOP, SIGCONT, SIGKILL
119    switch( sig_id )
120    {
121        case 0 :          // does nothing
122        {
123            break;
124        }
125        case SIGSTOP:     // block all target process threads
126        {
127            // block all threads in all clusters
128            process_sigaction( pid , BLOCK_ALL_THREADS );
129
130#if (DEBUG_SYS_KILL & 1)
131if( DEBUG_SYS_KILL < tm_start )
132printk("\n[%s] thread[%x,%x] blocked all threads of process %x\n",
133__FUNCTION__ , this->process->pid, this->trdid, pid );
134#endif
135            // atomically update owner process termination state
136            hal_remote_atomic_or( XPTR( owner_cxy , &owner_ptr->term_state ) ,
137                                  PROCESS_TERM_STOP );
138
139            // unblock the parent process main thread
140            thread_unblock( parent_main_xp , THREAD_BLOCKED_WAIT );
141
142            // calling thread deschedules when it is itself a target thread
143            if( this->process->pid == pid )
144            {
145
146#if (DEBUG_SYS_KILL & 1)
147if( DEBUG_SYS_KILL < tm_start )
148printk("\n[%s] thread[%x,%x] is a target thread => deschedule\n",
149__FUNCTION__ , this->process->pid, this->trdid );
150#endif
151                sched_yield("block itself");
152            }
153
154            break;
155        }
156        case SIGCONT:     // unblock all target process threads
157        {
158            // unblock all threads in all clusters
159            process_sigaction( pid , UNBLOCK_ALL_THREADS );
160
161            // atomically update owner process termination state
162            hal_remote_atomic_and( XPTR( owner_cxy , &owner_ptr->term_state ) ,
163                                   ~PROCESS_TERM_STOP );
164
165            // unblock the parent process main thread
166            thread_unblock( parent_main_xp , THREAD_BLOCKED_WAIT );
167
168            break;
169        }
170        case SIGKILL:
171        {
172            // a process cannot kill itself
173            if( (pid == process->pid) ) 
174            {
175
176#if DEBUG_SYSCALLS_ERROR
177printk("\n[ERROR] in %s : process %x cannot kill itself\n", __FUNCTION__, pid );
178#endif
179                this->errno = EINVAL;
180                return -1;
181            }
182
183            // processe INIT cannot be killed
184            if( pid == 1 )
185            {
186
187#if DEBUG_SYSCALLS_ERROR
188printk("\n[ERROR] in %s : process_init cannot be killed\n", __FUNCTION__ );
189#endif
190                        this->errno = EINVAL;
191                return -1;
192            }
193
194            // remove process from TXT list
195            process_txt_detach( owner_xp );
196
197            // mark for delete all threads in all clusters, but the main
198            process_sigaction( pid , DELETE_ALL_THREADS );
199
200            // block main thread
201            xptr_t main_xp = XPTR( owner_cxy , &owner_ptr->th_tbl[0] );
202            thread_block( main_xp , THREAD_BLOCKED_GLOBAL );
203
204            // atomically update owner process descriptor term_state to ask
205            // the parent process sys_wait() function to delete this main thread
206            hal_remote_atomic_or( XPTR( owner_cxy , &owner_ptr->term_state ) ,
207                                  PROCESS_TERM_KILL );
208
209            // unblock the parent process main thread
210            thread_unblock( parent_main_xp , THREAD_BLOCKED_WAIT );
211
212            break;
213        }
214        default:
215        {
216
217#if DEBUG_SYSCALLS_ERROR
218printk("\n[ERROR] in %s : illegal signal %d / process %x\n", __FUNCTION__, sig_id, pid );
219#endif
220            this->errno = EINVAL;
221            return -1;
222        }
223    }
224   
225    hal_fence();
226
227#if (DEBUG_SYS_KILL || CONFIG_INSTRUMENTATION_SYSCALLS)
228uint64_t     tm_end = hal_get_cycles();
229#endif
230
231#if DEBUG_SYS_KILL
232if( DEBUG_SYS_KILL < tm_end )
233printk("\n[%s] thread[%x,%x] exit / process %x / %s / cost = %d / cycle %d\n",
234__FUNCTION__ , this->process->pid, this->trdid, pid,
235sig_type_str(sig_id), (uint32_t)(tm_end - tm_start), (uint32_t)tm_end );
236#endif
237
238#if CONFIG_INSTRUMENTATION_SYSCALLS
239hal_atomic_add( &syscalls_cumul_cost[SYS_KILL] , tm_end - tm_start );
240hal_atomic_add( &syscalls_occurences[SYS_KILL] , 1 );
241#endif
242
243        return 0;
244
245}  // end sys_kill()
246
Note: See TracBrowser for help on using the repository browser.