source: trunk/kernel/kern/signal.c @ 8

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

Introduce the chdev_t structure in place of the device_t structure.

File size: 7.2 KB
Line 
1/*
2 * signal.c - signal-management related operations implementation
3 *
4 * Author  Alain Greiner    (2016,2017)
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_types.h>
25#include <errno.h>
26#include <thread.h>
27#include <process.h>
28#include <core.h>
29#include <signal.h>
30
31SIGNAL_HANDLER(kill_sigaction)
32{
33        struct thread_s *this;
34 
35        this = CURRENT_THREAD;
36        this->state = S_KERNEL;
37
38        printk(INFO, "INFO: Recieved signal %d, pid %d, tid %x, core %d  [ KILLED ]\n",
39               sig,
40               this->process->pid,
41               this,
42               cpu_get_id());
43
44        sys_thread_exit((void*)EINTR);
45}
46
47//////////////////////////////////////////////////
48void signal_manager_init( process_t * process )
49{
50        memset(&process->sig_mgr, 0, sizeof(process->sig_mgr));
51        process->sig_mgr.sigactions[SIGCHLD] = SIG_IGNORE;
52        process->sig_mgr.sigactions[SIGURG]  = SIG_IGNORE;
53}
54
55//////////////////////////////////////
56void signal_rise( process_t * process, 
57                  uint32_t    sig )
58{
59        thread_t     * thread;
60        uint32_t       i;
61
62        spinlock_lock( &process->th_lock );
63
64        for( i = 0 ; i < process->th_nr ; i++ )
65        {
66                thread = process->th_tbl[i];
67                hal_atomic_or( &thread->signals , (1 << sig) );
68        }
69
70        spinlock_unlock( &process->th_lock );
71
72        sig_dmsg("\n[INFO] %s : %d threads have been signaled for process %d\n",
73                        __FUNCTION__, process->th_nr , process->pid );
74
75}  // end signal_rise()
76
77///////////////////////////////////////////
78RPC_DECLARE( __signal_rise,                             \
79                RPC_RET( RPC_RET_PTR(error_t, err)),    \
80                RPC_ARG( RPC_ARG_VAL(pid_t,   pid),     \
81                         RPC_ARG_VAL(uint32_t,  sig))     \
82           )
83{
84         process_t   * process;
85        struct hnode_s  *hnode;
86
87        /* Avoid killing process0 and init */
88        /* FIXME: Zero should not be hard-coded but obtains with something like MAIN_KERN */
89        if( ((pid == PID_MIN_GLOBAL) || (pid == PID_MIN_GLOBAL+1))
90                        && (current_cid == 0) )
91        {
92                *err = EPERM;
93                sig_dmsg(1, "%s: can't kill process %u on cluster %u\n",           \
94                                __FUNCTION__, PID_GET_LOCAL(pid), current_cid);
95                goto SYS_RISE_ERR_PID;
96        }
97
98        /* Step 1 : lock the process manager */
99        processs_manager_lock();
100
101        /* Step 2 : Get the process' address */
102        /* Case 1 : current cluster is the anchor and the owner. */
103        if ( PID_GET_CLUSTER(pid) == current_cid )
104        {
105                sig_dmsg(1, "%s: process %u is in the processs manager array of cluster  %u\n",       \
106                                __FUNCTION__, pid, current_cid);
107                process = process_lookup(pid)->process;
108
109        }
110        else /* Case 2 : current cluster is not the anchor, so the struct
111              * process_s is in its hash table.
112              */
113        {
114                sig_dmsg(1, "%s: process %u is in the processs manager hash table of cluster  %u\n",  \
115                                __FUNCTION__, pid, current_cid);
116                hnode = hfind(processs_manager_get_htable(), (void*)pid);
117                process    = ( process_t*) container_of(hnode,          \
118                                 process_t, t_hnode);
119        }
120
121        /* Step 4 : check process' address */
122        if ( process == NULL )
123        {
124                *err = ESRCH;
125                goto SYS_RISE_ERR;
126        }
127
128        /* Step 5 : deliver signal */
129        if((sig == SIGTERM) || (sig == SIGKILL))
130                *err = signal_rise_all(process, sig);
131        else
132                *err = signal_rise_one(process, sig);
133
134        /* Step 6 : unlock processs manager */
135        processs_manager_unlock();
136
137        return;
138
139SYS_RISE_ERR:
140        processs_manager_unlock();
141SYS_RISE_ERR_PID:
142        sig_dmsg(1, "%s: Cluster %u has not deliver signal %u to process %u (err %u)\n",  \
143                        __FUNCTION__, current_cid, sig, err );
144
145        return;
146}
147
148///////////////////////////////
149error_t sys_kill( pid_t    pid, 
150                  uint32_t sig)
151{
152    cxy_t       owner_cxy;    // process owner cluster
153    lpid_t      owner_lpid;   // local process identifier
154    xptr_t      root_xp;      // extended pointer on root of xlist of process copies
155    xptr_t      lock_xp;      // extended pointer on remote_spinlock protecting this list
156    xptr_t      iter_xp;      // iterator for process copies list
157    xptr_t      process_xp;   // local pointer on process copy
158    cxy_t       process_cxy;  // cluster of process copy
159    process_t * process_ptr;  // local pointer on process copy
160        error_t     error;
161
162    // get local pointer on local cluster manager
163    cluster_t * cluster = LOCAL_CLUSTER;
164
165    // get owner process cluster and lpid
166    owner_cxy  = CXY_FROM_PID( pid );
167    owner_lpid = LPID_FROM_PID( pid );
168
169    // get extended pointers on copies root and lock
170    root_xp = XPTR( owner_cxy , &cluster->copies_root[lpid] );
171    lock_xp = XPTR( owner_cxy , &cluster->copies_lock[lpid] );
172
173    // take the lock protecting the copies
174    remote_spinlock_lock( lock_xp );
175
176    // TODO the loop below sequencialize the RPCs
177    // they could be pipelined...
178 
179    // traverse the list of copies
180    XLIST_FOREACH( root_xp , iter_xp )
181    {
182        process_xp  = XLIST_ELEMENT( iter_xp , process_t , copies_list );
183        process_cxy = GET_CXY( process_xp );
184        process_ptr = (process_t *)GET_PTR( process_xp );
185
186        if( process_xy == local_cxy )   // process copy is local
187        {
188            error = signal_rise( process_ptr , sig );
189        }
190        else                           // process copy is remote
191        {
192            rpc_signal_rise_client( process_cxy , process_ptr , sig );
193        }
194    }
195
196        return 0;
197}
198
199////////////////////////////////////
200void signal_notify( thread_s * this)
201{
202        register uint32_t sig_state;
203        register uint32_t sig;
204        register struct sig_mgr_s *sig_mgr;
205        uint32_t irq_state;
206
207        sig_state = this->info.sig_state & this->info.sig_mask;
208        sig       = 0;
209 
210        while((sig_state != 0) && ((sig_state & 0x1) == 0) && (sig < SIG_NR))
211        {
212                sig ++; 
213                sig_state >>= 1;
214        }
215 
216        if(sig)
217        {
218                cpu_disable_all_irq(&irq_state);
219
220                if(thread_isSignaled(this))
221                {
222                        cpu_restore_irq(irq_state);
223                        return;
224                }
225
226                thread_set_signaled(this);
227                cpu_restore_irq(irq_state);
228
229                spinlock_lock(&this->lock);
230                this->info.sig_state &= ~(1 << sig);
231                spinlock_unlock(&this->lock);
232
233                sig_mgr = &this->process->sig_mgr;
234
235                if(sig_mgr->sigactions[sig] == SIG_IGNORE)
236                        return;
237
238                if(sig_mgr->sigactions[sig] == SIG_DEFAULT)
239                        kill_sigaction(sig);
240
241                cpu_signal_notify(this, sig_mgr->sigactions[sig], sig);
242        }
243}
Note: See TracBrowser for help on using the repository browser.