task.h File Reference

#include "routix/system.h"
#include <routix/paging.h>
#include "sys/list.h"
#include <sys/types.h>
#include <signal.h>
#include "routix/file.h"

Go to the source code of this file.

Classes

Defines

Typedefs

Enumerations

Functions

Variables


Define Documentation

 
#define _reschedule  )     __asm__ __volatile__("int $0x51")
 

Definition at line 266 of file task.h.

Referenced by cache_read(), sys_exec(), sys_execve(), sys_usleep(), sys_waitpid(), and tarea_init().

#define EXIT_TASK   (TASK_TEXT - PAGINA_SIZE)
 

Definition at line 277 of file task.h.

#define GET_CONTEXT task   )     ((struct int_regs_ext *) ((task->esp0 & 0xfffff000) + PAGINA_SIZE - sizeof(struct int_regs_ext)))
 

Definition at line 288 of file task.h.

Referenced by exec_sigpending(), sys_fork(), sys_signal_check(), and sys_signal_correct().

#define ltr selector   )     __asm__ __volatile__("ltr %w0" : : "a" (selector));
 

Definition at line 127 of file task.h.

Referenced by init_MM_base().

#define MAX_DESCRIPTION   64
 

Definition at line 132 of file task.h.

#define MAX_PAGINAS_POR_TAREA   16
 

Definition at line 131 of file task.h.

Referenced by sys_malloc_page().

#define MAX_TASKS   7
 

Definition at line 25 of file task.h.

#define PAGINA_ALLOC   2
 

Definition at line 238 of file task.h.

Referenced by sys_malloc_page().

#define PAGINA_CODE   1
 

Definition at line 236 of file task.h.

Referenced by sys_exec(), and sys_execve().

#define PAGINA_DATA   0
 

Definition at line 235 of file task.h.

Referenced by sys_exec(), and sys_execve().

#define PAGINA_STACK   0
 

Definition at line 237 of file task.h.

Referenced by sys_exec(), and sys_execve().

#define TASK_CODEPAGES  )     (t->num_code)
 

Definition at line 221 of file task.h.

#define TASK_COUNT  )     (t->cuenta)
 

Definition at line 219 of file task.h.

#define TASK_CPUTIME  )     (t->tiempo_cpu)
 

Definition at line 220 of file task.h.

#define TASK_CR3  )     (t->cr3)
 

Definition at line 213 of file task.h.

#define TASK_CR3_BACKUP  )     (t->cr3_backup)
 

Definition at line 214 of file task.h.

#define TASK_DATA   0x88000000
 

Definition at line 271 of file task.h.

Referenced by sys_exec(), sys_execve(), and sys_malloc_page().

#define TASK_DATAPAGES  )     (t->num_data)
 

Definition at line 222 of file task.h.

#define TASK_DESCRIPTION  )     (t->descripcion)
 

Definition at line 216 of file task.h.

#define TASK_ERRNO  )     (t->err_no)
 

Definition at line 224 of file task.h.

#define TASK_PARENT  )     (t->padre)
 

Definition at line 226 of file task.h.

Referenced by sys_exec(), sys_execve(), and sys_fork().

#define TASK_PID  )     (t->pid)
 

Definition at line 215 of file task.h.

Referenced by sys_proc_dump_v(), sys_waitpid(), and timer_dump().

#define TASK_PPID  )     (t->padre->pid)
 

Definition at line 225 of file task.h.

Referenced by sys_get_ppid(), and sys_waitpid().

#define TASK_PRIORITY  )     (t->prioridad)
 

Definition at line 218 of file task.h.

#define TASK_SIGADDR task   )     (TASK_SIGNALS(task)->sigcheck_addr)
 

Definition at line 153 of file task.h.

Referenced by exec_sigpending(), sys_exec(), and sys_execve().

#define TASK_SIGMASK task   )     (TASK_SIGNALS(task)->sigmask)
 

Definition at line 152 of file task.h.

Referenced by exec_sigpending(), sys_proc_dump(), sys_signal_check(), and sys_sigprocmask().

#define TASK_SIGNAL task,
signo   )     (TASK_SIGNALS(task)->signal[signo])
 

Definition at line 154 of file task.h.

Referenced by sys_sigaction().

#define TASK_SIGNAL_COUNT task,
signo   )     ((TASK_SIGNALS(task)->sigcount)[signo])
 

Definition at line 166 of file task.h.

Referenced by _sys_kill(), and check_sigpending().

#define TASK_SIGNAL_FLAGS task,
signo   )     (TASK_SIGNAL(task,signo).sa_flags)
 

Definition at line 157 of file task.h.

#define TASK_SIGNAL_HANDLER task,
signo   )     (TASK_SIGNAL(task,signo).sa_handler)
 

Definition at line 155 of file task.h.

Referenced by _sys_kill(), exec_sigpending(), and sys_signal().

#define TASK_SIGNAL_MASK task,
signo   )     (TASK_SIGNAL(task,signo).sa_mask)
 

Definition at line 156 of file task.h.

Referenced by exec_sigpending().

#define TASK_SIGNALS task   )     (task->_signals)
 

Definition at line 150 of file task.h.

Referenced by sys_exec(), sys_execve(), and sys_fork().

#define TASK_SIGNALS_ALLOC task   ) 
 

Value:

TASK_SIGNALS(task) = (struct task_signals *)                            \
                                                                                                                         malloc(sizeof(struct task_signals));   \
                                                                                                                         task_signals_alloc++;

Definition at line 159 of file task.h.

Referenced by sys_exec(), sys_execve(), and sys_fork().

#define TASK_SIGNALS_FREE task   ) 
 

Value:

Definition at line 162 of file task.h.

Referenced by sys_exit_mm().

#define TASK_SIGNALS_INIT task   )     memset(TASK_SIGNALS(task), 0, sizeof(struct task_signals))
 

Definition at line 164 of file task.h.

#define TASK_SIGPENDING task   )     (TASK_SIGNALS(task)->sigpending)
 

Definition at line 151 of file task.h.

Referenced by _sys_kill(), check_sigpending(), and sys_proc_dump().

#define TASK_STACK   0x90000000
 

Definition at line 272 of file task.h.

Referenced by sys_exec(), and sys_execve().

#define TASK_STACK_USER  )     (t->esp0)
 

Definition at line 212 of file task.h.

#define TASK_STACKPAGES  )     (t->num_stack)
 

Definition at line 223 of file task.h.

#define TASK_STATE  )     (t->estado)
 

Definition at line 217 of file task.h.

Referenced by sys_waitpid().

#define TASK_TEXT   0x80000000
 

Definition at line 270 of file task.h.

Referenced by sys_exec(), sys_execve(), and sys_exit_mm().


Typedef Documentation

typedef struct task_struct_t task_struct_t
 

typedef struct task_t task_t
 

typedef struct tss_t tss_t
 


Enumeration Type Documentation

enum estado
 

Enumeration values:
TASK_RUNNING 
TASK_STOPPED 
TASK_INTERRUMPIBLE 
TASK_ININTERRUMPIBLE 
TASK_ZOMBIE 
TASK_CLEAN 

Definition at line 228 of file task.h.


Function Documentation

void despertar_task task_struct_t tarea  )  [inline]
 

Definition at line 147 of file task.c.

Referenced by actualizar_eventos(), cache_read(), despertar(), endrequest(), start_scheduler(), sys_exec(), sys_execve(), and sys_fork().

void dormir_task task_struct_t tarea  )  [inline]
 

Definition at line 128 of file task.c.

Referenced by cache_read(), sys_renice(), and sys_usleep().

task_struct_t* encontrar_proceso_por_pid pid_t  pid  ) 
 

Definition at line 298 of file task.c.

Referenced by sys_kill(), sys_proc_dump_v(), sys_renice(), and tarea_init().

pid_t get_new_pid void   )  [inline]
 

Definition at line 111 of file task.c.

Referenced by sys_exec(), sys_execve(), and sys_fork().

void inicializarTss tss_t tss,
word  cs,
word  ds,
dword  eip,
dword  esp,
dword  eflags
 

Definition at line 19 of file task.c.

Referenced by start_scheduler().

task_struct_t* init_new_task word  cs,
word  ds,
dword  eip,
dword  esp,
dword  eflags,
char *  descripcion,
word  prioridad
 

Definition at line 186 of file task.c.

Referenced by start_scheduler(), sys_exec(), sys_execve(), and sys_fork().

int insertar_tarea task_struct_t nueva  ) 
 

Definition at line 267 of file task.c.

Referenced by init_new_task().

int remover_task task_struct_t tarea  ) 
 

Saca a un proceso de la lista de procesos del scheduler

Definition at line 325 of file task.c.

Referenced by sys_exec(), sys_execve(), and sys_waitpid().

void sleep_init  )  [inline]
 

Definition at line 164 of file task.c.

void tomar_nombre_tarea const char *  viejo,
char *  nuevo
 

Definition at line 313 of file task.c.

Referenced by sys_exec(), and sys_execve().

void wakeup_init  )  [inline]
 

Definition at line 175 of file task.c.

Referenced by sys_exit_notify().


Variable Documentation

task_struct_t* actual
 

Definition at line 253 of file task.h.

Referenced by _sys_kill(), cache_read(), check_sigpending(), close(), exec_sig_default(), exec_sigpending(), LIST_NEW(), lseek(), open(), open_FAT12(), perror(), ps(), read(), scheduler(), start_scheduler(), sys_exec(), sys_execve(), sys_exit_fs(), sys_exit_mm(), sys_exit_notify(), sys_fork(), sys_get_pid(), sys_get_ppid(), sys_gets(), sys_getvar(), sys_kill(), sys_malloc_page(), sys_no_existe(), sys_perror(), sys_print(), sys_proc_dump_v(), sys_renice(), sys_setvar(), sys_sigaction(), sys_signal(), sys_signal_check(), sys_signal_correct(), sys_sigprocmask(), sys_usleep(), sys_void(), sys_waitpid(), and umalloc_page().

unsigned int file_alloc
 

Definition at line 147 of file task.h.

Referenced by open(), and sys_show().

unsigned int file_free
 

Definition at line 147 of file task.h.

Referenced by close(), sys_exit_fs(), and sys_show().

task_struct_t* init_task
 

Definition at line 230 of file task.h.

Referenced by _sys_kill(), sleep_init(), start_scheduler(), sys_exit_notify(), tarea_init(), and wakeup_init().

int num_alloc_signals
 

Definition at line 293 of file task.h.

int num_free_signals
 

Definition at line 293 of file task.h.

int num_frees
 

Cantidad de frees desde la última llamada a "clear alloc".

Definition at line 292 of file task.h.

Referenced by fat_file_find(), free(), open_FAT12(), and sys_show().

int num_mallocs
 

Cantidad de mallocs realizados desde la última llamada a "clear alloc".

Definition at line 292 of file task.h.

Referenced by fat_file_find(), malloc(), open_FAT12(), and sys_show().

task_struct_t * pre_init_task
 

Definition at line 230 of file task.h.

Referenced by check_sigpending(), start_scheduler(), sys_exec(), and sys_execve().

task_t tarea[]
 

Definition at line 122 of file task.h.

Referenced by despertar_task(), dormir_task(), exec(), execve(), and remover_task().

task_struct_t* tareas_inicio
 

Definition at line 252 of file task.h.

Referenced by encontrar_proceso_por_pid(), insertar_tarea(), ps(), remover_task(), scheduler(), start_scheduler(), sys_proc_dump(), and tarea_init().

unsigned int task_signals_alloc
 

Note:
Notas sobre señales: 3-May-2004 antes de schedulear la tarea, debo verificar si tengo señales pendientes. (en caso de haber, debo ejecutar el handle correspondiente. Como hago para que cuando termino de ejecutar el handle, la tarea siga ejecutandose donde se encontraba ? Para ser más claro, supongamos que la tarea está esperando en un while la llegada de una señal de tipo SIGUSR1, con un código como el que sigue while (flag_siguser1==0); continuar_ejecucion.... luego de ejecutado el handler, la tarea debería hacer la verificación de condición del while, y seguir... En este momento se me ocurrió (momentaneamente) que si la función check_sigpending encuentra una señal pendiente, pushee el IP de la tarea al stack, y ejecute el handler utilizando ese mismo stack de usuario, para que cuando el handler finalize, la ejecución siga "armonicamente". Para recuperar el valor del IP, creo, debería utilizar una estructura llamada "int_regs_ext" creada para el uso de la llamada fork. Con la siguiente linea, conseguiría cargar el contexto de una tarea con esa estructura new_ext = (struct int_regs_ext *) \ ((new_task->esp0 & 0xfffff000) + PAGINA_SIZE - sizeof(struct int_regs_ext)); Sería bueno implementar una macro GET_CONTEXT(task) para obtener facilmente el contexto y asi modularizar bien el código. Yo pensaba en saltar desde check_sigpending a la función apuntada por sa_handler, el tema es que aquí estoy en modo kernel y no me convece la idea de switchear el stack. Me parece sería mejor apuntar con el eip del contexto al handler, y colocar al tope del stack la dirección ip que se encuentra en el contexto.
Que pasa en caso de que se termine de ejecutar un handler y la tarea tenga más señales pendientes ? Debería ejecutar los handlers y no seguir con la ejecución normal de la tarea, cosa que no sucede con esta simple aproximación que planteamos. Algo que se me ocurrió que si resolvería el tema, sería lo siguiente: ademas de poner como IP de contexto la dirección del handler, pongo al fondo del stack un salto a un pedazo de código que llame a una syscall (signal_check), que lo que haga es seguir el proceso de verificación de señales pendientes, y ejecución de los handlers correspondientes.

8-May-2004 Giro de 90º en la implementación base de señales. Por cuestiones de concurrencia, y un análisis "profundo" del impacto que tienen recibir una señal mientras se procesa un handler de otra, decidí sobre la marcha cambiar la implementación. Lo que haré será lo siguiente: El check_sigpending irá verificando si hay señales pendientes. Suponiendo que haya más de una, lo que se hará será lo siguiente. Para el primer handler se pondrá su dirección en el EIP del contexto de la tarea, y se pusheará al fondo del stack la dirección de un wrapper (creado por execve) el cuál me restaura los registros usados por la tarea, y luego hará un ret (para lo cual tuve que haber puesto el EIP del contexto al fondo del stack). Para las demás señales pendientes que haya detectado check_sigpending, se pusheará su dirección en el stack, con lo que primero se ejecutará la primera señal pendiente detectada, al finalizar está se iran sacando sistemáticamente del stack las direcciones de los handlers de la última a hacia la segunda pendiente. Es decir, si al momento de schedulear tengo pendientes las señales 1,2,3 y 10 primero se ejecutará la 1, luego la 10, la 3 y finalmente la 2.

9-May-2004 La gata flora se apodera de mi :-) Luego de haber implementado el sistema comentado anteriormente, me he dado cuenta que no funciona (al menos no como lo implementé). Cuál es el problema ? Todos los handlers logran ejecutarse con continuidad sin que el kernel se entere. Si bien esto es altamente performante :-), no me permite ir variando la máscara de señales ( task->sigmask ) la cual me dice que señales debo ignorar mientras estoy en el handler actual. Asi que, anulo esta implementación y vuelvo a algo muy cercano a la implementación original. En primer lugar: la función check_sigpending recibe como parámetro un flag, el cuál indica si debe o no guardar el contexto de la tarea. Esto creo lo explique en reiteradas oportunidades, pero en pos de aumentar la posibilidad de comprensión, lo volveré a explicar. Sólo debo guardar el contexto de la tarea en dos ocasiones: 1) Si tengo que interrumpir la ejecución de la tarea para ejecutar un handler. 2) Si debo interrumpir la interrupción de un handler para ejecutar otro handler (siempre y cuando task->sigmask me lo permita). En que caso no debo guardar el contexto ? Supongamos que estaba ejecutando la tarea, y recibo dos señales: guardo el contexto y ejecuto un handler. Cuando retorno de ejecutar ese handler (vía INT sys_signal_check) puedo ejecutar el otro handler sin necesidad de guardar el contexto, lo cuál hice unos instantes antes. A continuación se detalla el wrapper que se ejcuta una vez terminado el handler (el cuál se carga en la llamada execve): *(ptr_exit+12) = 0xb8; // Codigo de operacion: "mov eax, " *(unsigned long *)(ptr_exit+13) = SYS_SIGNALS | SYS_SIGNAL_CHECK; *(ptr_exit+17) = 0xcd; // int *(ptr_exit+18) = 0x50; // 0x50 *(ptr_exit+19) = 0x5e; // pop esi // Con estos popeos recupero los registros de propósito general *(ptr_exit+20) = 0x5f; // pop edi // que fueron pusheados antes de ejecutar un handler de señal *(ptr_exit+21) = 0x5a; // pop edx *(ptr_exit+22) = 0x59; // pop ecx *(ptr_exit+23) = 0x5b; // pop ebx *(ptr_exit+24) = 0x58; // pop eax *(ptr_exit+25) = 0xc3; // retn new_task->sigcheck_addr = GET_OFFSET(ptr_exit + 12) + mem->vdir;

Este wrapper se ubica en el segmento de datos de la tarea, y se guarda su dirección en task->sigcheck_addr. Esa dirección se pone en el stack de la tarea, como dirección de retorno del handler :-)

12-May-2004 Ya tenemos la base del sistema de posteo y entrega (post & deliver) de señales. Es el momento de hablar de la implementación de las máscaras de señal. Vamos a tener dos tipos de máscaras: la primera seteada mediante la llamada al sistema sigprocmask, la cuál indica a que señales debemos inhibir mientras ejecutamos código de la tarea; mientras que el segundo tipo será la máscara definida mediante la llamada sigaction la cuál nos dice que señales debo "ignorar" mientras ejecuto el handler de una señal en particular. Vale aclarar que el término "ignorar" no es del todo correcto, ya que según POSIX, cuando se IGNORA una señal, se la descarta (definiendo como handler de la señal a SIG_IGN). Que pasa entonces cuando yo pongo una máscara de señal que inhiba a la señal SIGCHLD, por ejemplo ? Cuando se reciba esa señal, se la va a marcar como pendiente (post), pero su handler se ejecutará (deliver) recién cuando se "desinhiba" de la máscara.

A continuación voy a intentar dar una idea de como será la implementación. La forma real de entenderla es estudiando el código (y sí, no hay otra). Se ejecuta check_sigpending, para ver si hay señales pendientes, cuando se encuentra alguna, antes de preparar todo para ejecutar el handler, verifico si esa señal está inhibida mediante la máscara sigmask (que se encuentra en el task_struct de la tarea), usando la macro IS_MASKED. Obviamente la señal no se ejecuta mientras se encuentre inhibida. Ese valor sigmask, de donde sale ? Como ya aclaré anteriormente, puede ser seteado con la llamada sigprocmask o bien, es el valor sa_mask de la estructura sigaction, la cual se se define mediante la llamada sigaction. En esta primera aproximación, haremos lo siguiente. Cuando vamos a ejecutar un handler, pondremos como máscara (es decir en sigmask) al sa_mask de ese handler, y resguardaremos el valor que poseía sigmask en el mismo stack que vinimos manipulando (Si si, otra vez a meter mando en el stack...). Cuando se termine de ejecutar el handler, popearemos el valor del stack y lo regresaremos a sigmask. Para lograr esto tuvimos que modificar el código de sys_signal_check (sys_signal.c) y el de exec_sigpending (signal.c). Sencillamente pusheamos el valor de la máscara actual antes de pushear "signo" (el cuál es el parámetro que recibe el handler de señal). Luego, al retornar de la ejecución del handler, simplemente se popea la máscara.

Realmente no mire como implementaron esto otros desarrolladores, pero me imagino que debe ser de una manera terriblemente similar. Me imagino esto ya que, al realizar testeos, encuentro que si utilizo sigprocmask desde un handler de señal, al salir del handler, esa nueva máscara que coloque la pierdo, es decir, se sobreescribe con la que se recupera del stack. Al ir a POSIX (particularmente sigprocmask) encuentro algo como esto: "When a thread's signal mask is changed in a signal-catching function that is installed by sigaction() the restoration of the signal mask on return from the signal-catching function overrides that change (see sigaction()).", lo que me indica que probablemente hallan almacenado las máscaras dentro de una pila.

22-May-2004 Es realmente problematico que no se encolen las señales, ya que si un proceso crea 10 hijos, y todos ellos terminan simultaneamente, varios quedarán en Zombies, ya que hay solo 1 bit disponible en task->sigpending. Se me ocurrió como forma fácil de solucionar esto, colocar en la estructura task_signal un entero por cada señal, en el cuál podemos almacenar la cantidad de señales de un tipo que hay. Cada vez que ejecutamos un handler, decrementamos ese valor. De este modo, no perdemos señales.

Definition at line 144 of file task.h.

Referenced by sys_show().

unsigned int task_signals_free
 

Definition at line 144 of file task.h.

Referenced by sys_show().

tss_t tss
 

Definition at line 121 of file task.h.

Referenced by inicializarTss(), init_MM_base(), and start_scheduler().

unsigned int umalloc_alloc
 

Definition at line 146 of file task.h.

Referenced by sys_show(), and umalloc_page().

unsigned int umalloc_free
 

Definition at line 146 of file task.h.

Referenced by sys_show(), and ufree_page().


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