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

Last change on this file since 1 was 1, checked in by alain, 7 years ago

First import

File size: 7.3 KB
Line 
1/*
2 * signal.c - signal-management related operations implementation
3 *
4 * Author  Ghassan Almaless (2008,2009,2010,2011,2012)
5 *         Mohamed Lamine Karaoui (2015)
6 *         Alain Greiner    (2016)
7 *
8 * Copyright (c) UPMC Sorbonne Universites
9 *
10 * This file is part of ALMOS-MKH.
11 *
12 * ALMOS-MKH is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; version 2.0 of the License.
15 *
16 * ALMOS-MKH is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
23 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 */
25
26#include <hal_types.h>
27#include <errno.h>
28#include <thread.h>
29#include <process.h>
30#include <core.h>
31#include <signal.h>
32
33SIGNAL_HANDLER(kill_sigaction)
34{
35        struct thread_s *this;
36 
37        this = CURRENT_THREAD;
38        this->state = S_KERNEL;
39
40        printk(INFO, "INFO: Recieved signal %d, pid %d, tid %x, core %d  [ KILLED ]\n",
41               sig,
42               this->process->pid,
43               this,
44               cpu_get_id());
45
46        sys_thread_exit((void*)EINTR);
47}
48
49//////////////////////////////////////////////////
50void signal_manager_init( process_t * process )
51{
52        memset(&process->sig_mgr, 0, sizeof(process->sig_mgr));
53        process->sig_mgr.sigactions[SIGCHLD] = SIG_IGNORE;
54        process->sig_mgr.sigactions[SIGURG]  = SIG_IGNORE;
55}
56
57////////////////////////////////////////
58error_t signal_init( thread_t * thread )
59{
60        thread->info.sig_state = 0;
61        thread->info.sig_mask  = CURRENT_THREAD->info.sig_mask;
62        return 0;
63}
64
65////////////////////////////////////////////////////
66static error_t signal_rise_all( process_t * process, 
67                                uint32_t    sig )
68{
69        thread_t     * thread;
70        uint32_t       i;
71
72        spinlock_lock( &process->th_lock );
73
74        for( i = 0 ; i < process->th_nr ; i++ )
75        {
76                thread = process->th_tbl[i];
77                hal_atomic_or( &thread->signals , (1 << sig) );
78        }
79
80        spinlock_unlock( &process->th_lock );
81
82        sig_dmsg("\n[INFO] %s : %d threads have been signaled for process %d\n",
83                        __FUNCTION__, process->th_nr , process->pid );
84
85        return 0;
86}
87
88////////////////////////////////////////////////////
89static error_t signal_rise_one( process_t * process,
90                                uint32_t    sig )
91{
92        thread_t * thread;
93
94        spinlock_lock( &process->th_lock );
95
96//mdify to current_thread, not the one pointed by the sig_mgr ?
97        if(process->sig_mgr.handler == NULL)
98                thread = list_first(&process->th_root, struct thread_s, rope);
99        else
100                thread = process->sig_mgr.handler;
101
102        spinlock_lock( &thread->lock );
103        thread->info.sig_state |= (1 << sig);
104        spinlock_unlock( &thread->lock );
105
106        spinlock_unlock( &process->th_lock );
107
108    sig_dmsg("\n[INFO] %s : Thread %u of process %u has received signal %u. sig_state = %x\n",        \
109                        __FUNCTION__, thread_current_cpu(thread)->gid,                          \
110                        process->pid, sig, thread->info.sig_state);
111
112        return 0;
113}
114
115RPC_DECLARE( __signal_rise,                             \
116                RPC_RET( RPC_RET_PTR(error_t, err)),    \
117                RPC_ARG( RPC_ARG_VAL(pid_t,   pid),     \
118                         RPC_ARG_VAL(uint32_t,  sig))     \
119           )
120{
121         process_t   * process;
122        struct hnode_s  *hnode;
123
124        /* Avoid killing process0 and init */
125        /* FIXME: Zero should not be hard-coded but obtains with something like MAIN_KERN */
126        if( ((pid == PID_MIN_GLOBAL) || (pid == PID_MIN_GLOBAL+1))
127                        && (current_cid == 0) )
128        {
129                *err = EPERM;
130                sig_dmsg(1, "%s: can't kill process %u on cluster %u\n",           \
131                                __FUNCTION__, PID_GET_LOCAL(pid), current_cid);
132                goto SYS_RISE_ERR_PID;
133        }
134
135        /* Step 1 : lock the process manager */
136        processs_manager_lock();
137
138        /* Step 2 : Get the process' address */
139        /* Case 1 : current cluster is the anchor and the owner. */
140        if ( PID_GET_CLUSTER(pid) == current_cid )
141        {
142                sig_dmsg(1, "%s: process %u is in the processs manager array of cluster  %u\n",       \
143                                __FUNCTION__, pid, current_cid);
144                process = process_lookup(pid)->process;
145
146        }
147        else /* Case 2 : current cluster is not the anchor, so the struct
148              * process_s is in its hash table.
149              */
150        {
151                sig_dmsg(1, "%s: process %u is in the processs manager hash table of cluster  %u\n",  \
152                                __FUNCTION__, pid, current_cid);
153                hnode = hfind(processs_manager_get_htable(), (void*)pid);
154                process    = ( process_t*) container_of(hnode,          \
155                                 process_t, t_hnode);
156        }
157
158        /* Step 4 : check process' address */
159        if ( process == NULL )
160        {
161                *err = ESRCH;
162                goto SYS_RISE_ERR;
163        }
164
165        /* Step 5 : deliver signal */
166        if((sig == SIGTERM) || (sig == SIGKILL))
167                *err = signal_rise_all(process, sig);
168        else
169                *err = signal_rise_one(process, sig);
170
171        /* Step 6 : unlock processs manager */
172        processs_manager_unlock();
173
174        return;
175
176SYS_RISE_ERR:
177        processs_manager_unlock();
178SYS_RISE_ERR_PID:
179        sig_dmsg(1, "%s: Cluster %u has not deliver signal %u to process %u (err %u)\n",  \
180                        __FUNCTION__, current_cid, sig, err );
181
182        return;
183}
184
185//////////////////////////////////
186error_t signal_rise( pid_t    pid, 
187                     cxy_t    location, 
188                     uint32_t sig)
189{
190        error_t err;
191
192        /* Check location error */
193        if ( location == CID_NULL )
194        {
195                err = ESRCH;
196                printk(WARNING, "%s: there is no process with pid %u\n", \
197                                __FUNCTION__, pid);
198                return err;
199        }
200
201        err = EAGAIN;
202        RCPC( location, RPC_PRIO_SIG_RISE, __signal_rise,       \
203                        RPC_RECV( RPC_RECV_OBJ(err) ),          \
204                        RPC_SEND( RPC_SEND_OBJ(pid),            \
205                                  RPC_SEND_OBJ(sig))            \
206            );
207
208        return err;
209}
210
211////////////////////////////////////
212void signal_notify( thread_s * this)
213{
214        register uint32_t sig_state;
215        register uint32_t sig;
216        register struct sig_mgr_s *sig_mgr;
217        uint32_t irq_state;
218
219        sig_state = this->info.sig_state & this->info.sig_mask;
220        sig       = 0;
221 
222        while((sig_state != 0) && ((sig_state & 0x1) == 0) && (sig < SIG_NR))
223        {
224                sig ++; 
225                sig_state >>= 1;
226        }
227 
228        if(sig)
229        {
230                cpu_disable_all_irq(&irq_state);
231
232                if(thread_isSignaled(this))
233                {
234                        cpu_restore_irq(irq_state);
235                        return;
236                }
237
238                thread_set_signaled(this);
239                cpu_restore_irq(irq_state);
240
241                spinlock_lock(&this->lock);
242                this->info.sig_state &= ~(1 << sig);
243                spinlock_unlock(&this->lock);
244
245                sig_mgr = &this->process->sig_mgr;
246
247                if(sig_mgr->sigactions[sig] == SIG_IGNORE)
248                        return;
249
250                if(sig_mgr->sigactions[sig] == SIG_DEFAULT)
251                        kill_sigaction(sig);
252
253                cpu_signal_notify(this, sig_mgr->sigactions[sig], sig);
254        }
255}
Note: See TracBrowser for help on using the repository browser.