| 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 |  | 
|---|
| 33 | SIGNAL_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 | ////////////////////////////////////////////////// | 
|---|
| 50 | void 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 | //////////////////////////////////////// | 
|---|
| 58 | error_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 | //////////////////////////////////////////////////// | 
|---|
| 66 | static 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 | //////////////////////////////////////////////////// | 
|---|
| 89 | static 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 |  | 
|---|
| 115 | RPC_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 |  | 
|---|
| 176 | SYS_RISE_ERR: | 
|---|
| 177 |         processs_manager_unlock(); | 
|---|
| 178 | SYS_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 | ////////////////////////////////// | 
|---|
| 186 | error_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 | //////////////////////////////////// | 
|---|
| 212 | void 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 | } | 
|---|