signal.c

Go to the documentation of this file.
00001 
00006 #include <routix/system.h>
00007 #include <routix/task.h>
00008 #include <signal.h>
00009 #include <routix/signal.h>
00010 #include <sys/types.h>
00011 #include <routix/kstdio.h>
00012 #include <error.h>
00013 #include <routix/debug.h>
00014 #include <routix/syscalls.h> 
00015  
00016 void exec_sig_default (task_struct_t *task, int signo);
00017 void sig_kill(task_struct_t *task);
00018 
00151 // Variables que contienen cuantos malloc y cuantos frees realizó el kernel para alocar estructuras de
00152 // señales (sólo con propósitos de debug)
00153 unsigned int task_signals_alloc = 0;
00154 unsigned int task_signals_free = 0;
00155 
00156 
00157 
00163 int check_sigpending(task_struct_t *task, int save_context)
00164 {
00165         // No verificar ningún tipo de señales para init (al menos por ahora)
00166         if (actual==pre_init_task)
00167                 return -1;
00168 
00169         if (getvar("pepe")==1)
00170                 return 0;
00171 
00172         // Si no hay señales pendientes... me voy
00173         if (TASK_SIGPENDING(task)==0)   {
00174                 return 0;
00175         }
00176 
00177         int signo = 0;
00178         unsigned long sig = TASK_SIGPENDING(task);
00179 
00180         while (signo < SIGMAX) {
00181                 // Si la señal está pendiente y no está inhibida (o enmascarada) ...
00182                 if ( (sig & 1) && !IS_MASKED(task,signo)) {
00183                         exec_sigpending(task, signo, save_context);
00184                         TASK_SIGNAL_COUNT(task, signo)--;
00185                         if (TASK_SIGNAL_COUNT(task, signo)<1)
00186                                 // Borro el bit que indica que la señal está pendiente
00187                                 TASK_SIGPENDING(task) = TASK_SIGPENDING(task) ^ (1<<signo);
00188                         // Me voy avisando que encontre al menos una señal pendiente
00189                         return 1;
00190                 }
00191                 // No importa la máscara para SIGKILL
00192                 else if ( (sig & 1) && ((signo==SIGKILL) || (signo==SIGSTOP)) )
00193                         sig_kill(actual);
00194                 sig = sig >> 1;
00195                 signo++;
00196         }
00197 
00198         return 0;
00199 
00200 /*
00201         // Barrer todas las posibles señales
00202         for (signo=0 ; (sig & 1)==0 ; signo++)
00203                 sig = sig >> 1;
00204 
00205         exec_sigpending(task, signo, save_context);
00206         task->sigpending = task->sigpending ^ (1<<signo);
00207 
00208         // Si llegué al final y no hay más pendientes
00209         if (signo > SIGMAX) {
00210                 kprintf("No hay más pendientes ???\n");
00211                 return 0;
00212         }
00213 
00214 
00215         // Retorno al scheduler, diciendo que había la menos una señal pendiente
00216         return 1;
00217 */
00218 }
00219 
00220 
00221 
00229 void exec_sigpending(task_struct_t *task, int signo, int save_context)
00230 {
00231         if (TASK_SIGNAL_HANDLER(task, signo) == SIG_DFL) {
00232                 exec_sig_default(task, signo);
00233                 return;
00234         }
00235         
00236         // Debo inhibir la posibilidad que me conmute la tarea, ya que si lo hace con el stack desbalanceado
00237         // puede pasar cualquier cosa
00238         cli();
00239         
00240         // Obtener el contexto de la tarea
00241         struct int_regs_ext *context = GET_CONTEXT(task);
00242 
00243         unsigned long *user_ptr = (unsigned long *) context->esp;
00244         // Obtener la dirección física del stack de la tarea
00245         user_ptr = convertir_direccion( user_ptr, actual->cr3_backup);
00246 
00247         // Sólo debo "pushear" el EIP de la tarea y los registros para la primer señal pendiente
00248         // verificando con first_signal
00249         if (save_context == 1) {
00250 //              kprintf("EXEC: signo first: %d\n", signo);
00251                 *(--user_ptr) = context->eip;
00252 //              kprintf("Pusheando al stack el EIP: 0x%x\n", context->eip);
00253                 context->esp -= 4;
00254                 *(--user_ptr) = context->eax;
00255                 *(--user_ptr) = context->ebx;
00256                 *(--user_ptr) = context->ecx;
00257                 *(--user_ptr) = context->edx;
00258                 *(--user_ptr) = context->edi;
00259                 *(--user_ptr) = context->esi;
00260                 context->esp -= (6 * sizeof(dword));
00261                 
00262                 *(--user_ptr) = TASK_SIGMASK(task);
00263                 context->esp -= 4;
00264 //              kprintf("Pusheando MASCARA: 0x%x\n", task->sigmask);
00265                 
00266                 
00267                 // Paso como argumento el número de señal
00268                 *(--user_ptr) = signo;
00269                 // Y como dirección de retorno el wrapper "sigcheck" que popea los registros (EAX - ESI)
00270                 *(--user_ptr) = TASK_SIGADDR(task);
00271                 context->esp -= 8;
00272                 context->eip = (dword) TASK_SIGNAL_HANDLER(task, signo);
00273         }
00274         else {
00275                 // Paso como argumento el número de señal (no muevo el stack porque quedo 4 bytes desplazado)
00276                 *(user_ptr) = TASK_SIGMASK(task);
00277 //              kprintf("Pusheando MASCARA: 0x%x\n", task->sigmask);
00278                 context->esp -= 4;
00279                 *(--user_ptr) = signo;
00280                 *(--user_ptr) = TASK_SIGADDR(task);
00281                 // Y pusheo en el stack la dirección del handler (cuando termine el otro handler, se ejecutará este)
00282                 context->eip = (dword) TASK_SIGNAL_HANDLER(task, signo);
00283                 context->esp -= 4;
00284                 //kprintf("EXEC: signo no first: %d\n", signo);
00285         }
00286         
00287         // Coloco como máscara, la máscara del proceso (seteada con sigaction)
00288         TASK_SIGMASK(task) = TASK_SIGNAL_MASK(task, signo);
00289         sti();
00290 
00291 }
00292 
00297 void exec_sig_default (task_struct_t *task, int signo)
00298 {
00299         if (signo==9)
00300                 sig_kill(actual);
00301         else kprintf("Proceso PID: %d\tSIG_DFL para la senal: %d no implementado \n", task->pid, signo);
00302 }
00303 
00304 
00305 void sig_kill(task_struct_t *task)
00306 {
00307         sys_exit(0);
00308 }
00309 

Generated on Sun May 30 18:38:35 2004 for Routix OS by doxygen 1.3.6