task.c

Go to the documentation of this file.
00001 
00006 #include "routix/system.h"
00007 #include "routix/task.h"
00008 #include "routix/paging.h"
00009 #include "routix/kalloc.h"
00010 #include "error.h"
00011 #include "routix/file.h"
00012 #include "string.h"
00013 
00014 #include "sys/list.h"
00015 
00016 // Un solo tss
00017 tss_t   tss; 
00018 
00019 void inicializarTss(tss_t *tss, word cs, word ds, dword eip, dword esp, dword eflags)
00020 {
00021  tss->ss0 = DESC_DATA;
00022  tss->cs=cs;
00023  tss->ds=ds;
00024  tss->es=ds;
00025  tss->fs=ds;
00026  tss->gs=ds;
00027  tss->ss=ds;
00028  tss->eip=eip;
00029  tss->esp=esp;
00030  tss->eflags=eflags;
00031  tss->ldt=0;
00032  tss->t=0;
00033  tss->cr3=POSICION_DIR_PAGINAS;
00034 }
00035 
00036 
00037 //Agregado de ebp para facilitar el fork
00038 dword *inicializar_task(dword *stack, word cs, word ds, dword eip, dword esp, dword eflags)
00039 {
00040         
00041  /* Recordemos como se pushean los datos al stack
00042         interrupcion
00043         push eax
00044         push ebx
00045         push ecx
00046         push edx
00047         push ds
00048         push es
00049         push fs
00050         push gs
00051         push ebp
00052         push esi
00053         push edi
00054 
00055         o sea, tenemos en el siguiente orden:
00056         Interrupción :  ss, esp, eflags, cs, eip
00057         Push manuales:  eax, ebx, .... , edi
00058 
00059         debemos cargar el stack del kernel de la misma manera
00060  */
00061 
00062 
00063  stack--;
00064  *stack-- = ds;     //ss
00065  *stack-- = esp;
00066  *stack-- = eflags;
00067  *stack-- = cs;
00068  *stack-- = eip;
00069  *stack-- = 0;      //ebp
00070  *stack-- = 0;      //esi
00071  *stack-- = 0;      //edi
00072  *stack-- = 0;      //edx
00073  *stack-- = 0;      //ecx
00074  *stack-- = 0;      //ebx   
00075  *stack-- = 0;      //eax
00076  *stack-- = ds;     //ds
00077  *stack-- = ds;     //es
00078  *stack-- = ds;     //fs
00079  *stack = ds;       //gs
00080  
00081  return stack;
00082 }
00083 
00084 /*
00085 dword *inicializar_fork(dword *stack,word cs,word ds,dword eip,dword esp,dword eflags,dword ebp, dword eax, dword ebx, \
00086                 dword ecx, dword edx, dword edi, dword esi)
00087 {
00088  stack--;
00089  *stack-- = ds;     //ss
00090  *stack-- = esp;
00091  *stack-- = eflags;
00092  *stack-- = cs;
00093  *stack-- = eip;
00094  *stack-- = eax;    //eax
00095  *stack-- = ebx;    //ebx   
00096  *stack-- = ecx;    //ecx
00097  *stack-- = edx;    //edx
00098  *stack-- = ds;     //ds
00099  *stack-- = ds;     //es
00100  *stack-- = ds;     //fs
00101  *stack-- = ds;     //gs
00102  *stack-- = ebp;    //ebp
00103  *stack-- = esi;    //esi
00104  *stack = edi;      //edi
00105  
00106  return stack;
00107 }
00108 */      
00109 
00110 
00111 inline pid_t get_new_pid(void)
00112 {
00113  static pid_t pid=2;
00114  
00115  return(pid++);
00116 }
00117 
00118 
00119 
00120 // Contador de tareas activas ( estado == TASK_RUNNING )
00121 volatile int tareas_activas=0;
00122 
00123 void inc_tareas_activas()
00124 {
00125  ++tareas_activas;
00126 }
00127 
00128 inline void dormir_task(task_struct_t *tarea)
00129 {
00130         // No puede ser interrumpida por el TimerTick (Atomicidad)
00131         cli();
00132 
00133         // Cambiamos su estado y le sacamos el resto de tiempo de cpu que le faltaba
00134         tarea->estado  = TASK_INTERRUMPIBLE;
00135         tarea->cuenta=tarea->prioridad;
00136 
00137         --tareas_activas;
00138 /*
00139         if ( tareas_activas < 1 && init_task->estado!=TASK_RUNNING) {
00140                 init_task->estado=TASK_RUNNING;
00141                 tareas_activas++;
00142         }
00143 */
00144         sti();
00145 }
00146 
00147 inline void despertar_task(task_struct_t *tarea)
00148 {
00149         // No puede ser interrumpida por el TimerTick (Atomicidad)
00150         cli();
00151   
00152         tarea->estado = TASK_RUNNING;
00153         tareas_activas++;
00154 /*
00155  if ( tareas_activas > 1 && init_task->estado==TASK_RUNNING ) {
00156    init_task->estado=TASK_STOPPED;
00157    tareas_activas--;   
00158  }
00159 */
00160         sti();
00161 }
00162 
00163 
00164 inline void sleep_init()
00165 {
00166         cli();
00167         //if ( tareas_activas > 1 && init_task->estado==TASK_RUNNING ) {
00168         if ( init_task->estado==TASK_RUNNING ) {
00169                 init_task->estado=TASK_STOPPED;
00170             tareas_activas--;   
00171         }
00172         sti();
00173 }
00174 
00175 inline void wakeup_init()
00176 {
00177         cli();
00178         if (init_task->estado!=TASK_RUNNING) {
00179            init_task->estado=TASK_RUNNING;
00180            tareas_activas++;
00181         }
00182         sti();
00183 }
00184 
00185 
00186 task_struct_t *init_new_task(word cs, word ds, dword eip, dword esp, dword eflags, char *descripcion, word prioridad)
00187 {
00188  task_struct_t *nueva;
00189  dword esp0;
00190  
00191   // Alocamos una página completa (para el descriptor de tarea y el stack en modo kernel).
00192  if ( (nueva = (task_struct_t *) kmalloc_page()) == NULL ) {
00193   return NULL;
00194  }
00195 
00196         //Provisorio, debe ser más performante !!!
00197         memset(nueva, 0, PAGINA_SIZE);
00198 
00199   // Selector de Datos (DPL=0) y esp0 al final de la página
00200  esp0 = (dword) nueva + 4092;
00201 
00202  // Crear un directorio de paginas y alojar su dir en cr3
00203  if ( (nueva->cr3 = (addr_t) make_pdt()) == NULL ) {
00204     kfree_page((addr_t)nueva);
00205     return NULL;
00206  } 
00207 
00208  nueva->cr3_backup = nueva->cr3;
00209 
00210 // Esto debe hacerse sólo en la llamada a fork (o en exec si el que llama es init)
00211 // nueva->pid = get_new_pid();
00212  strcpy( nueva->descripcion, descripcion);
00213 
00214  // Ponemos la tarea a correr
00215  //nueva->estado = TASK_RUNNING;
00216  // Stoppeada hasta no terminar todo el proceso de creacion, la debe despertar otra funcion
00217  // como por ejemplo sys_exec()
00218  nueva->estado = TASK_STOPPED;
00219 
00220  nueva->prioridad = prioridad;
00221 
00222  nueva->err_no = 0;
00223 
00224  // Cantidad de ticks que tiene permitido usar la cpu en forma continua
00225  nueva->cuenta     = prioridad;
00226  nueva->tiempo_cpu = 0;
00227 
00228  // Inicializamos la estructura que contiene el contexto de hardware de la tarea
00229  nueva->esp0 = (dword) inicializar_task((dword *)esp0,cs,ds,eip,esp,eflags);    //el ultimo 0 es ebp (provisorio)
00230 
00231     word j;
00232     for (j=0 ; j<MAX_FILES_POR_TAREA; j++)
00233         nueva->open_files[j] = NULL;
00234 
00235         // Inicializo todos los handlers de señal a SIG_DFL
00236 /*
00237         int init_signo;
00238         for (init_signo=0 ; init_signo<SIGMAX ; init_signo++)
00239                 (TASK_SIGNAL_HANDLER(actual, init_signo)) = SIG_DFL;
00240 */
00241         
00242 
00243  // Insertamos la tarea en la lista
00244  if ( ! insertar_tarea(nueva) ) {
00245  
00246         kpanic("aca");
00247 
00248 
00249   // No pudimos insertarla !! liberamos la memoria
00250   kfree_page((addr_t)nueva);
00251 
00252   return NULL;
00253  }
00254 
00255  // Si hay más de una tarea activa ponemos a dormir al idle task
00256  //if ( ++tareas_activas > 1 ) {
00257  // dormir_task( tareas_inicio );
00258  //}
00259 
00260  return nueva;
00261 }
00262 
00263 
00264 
00265 
00266 
00267 int insertar_tarea(task_struct_t *nueva)
00268 {
00269  task_struct_t *tmp;
00270         
00271  if ( nueva == NULL ) { return 0; }
00272 
00273  cli();
00274 
00275  // Nos paramos al ppio de la lista
00276  tmp = tareas_inicio;
00277 
00278  if ( tareas_inicio == NULL ) { tareas_inicio = nueva; }
00279 
00280  else {
00281  
00282    // Buscamos la última tarea
00283    for ( tmp = tareas_inicio; tmp->proxima != NULL ; tmp = tmp->proxima );
00284         
00285    // Nos colgamos de ella
00286    tmp->proxima = nueva;
00287  }
00288 
00289  // La nueva tarea queda apuntando a NULL
00290  nueva->proxima = NULL;
00291 
00292  sti();
00293  return 1;
00294 }
00295 
00296 
00297 
00298 task_struct_t *encontrar_proceso_por_pid(pid_t pid)
00299 {
00300  task_struct_t *tmp;
00301 
00302  for( tmp = tareas_inicio; tmp  && (tmp->pid != pid); tmp = tmp->proxima) ;
00303 
00304  return tmp;
00305 }
00306 
00307 
00308 /* Esta funcion toma un path de archivo, y coloca en nuevo solo el nombre del archivo.
00309  * Ej: viejo[]="/files/rotor.bin"  --->   nuevo[]="rotor.bin"
00310  * (usado por ejemplo en el "ps")
00311  */ 
00312 
00313 void tomar_nombre_tarea (const char *viejo, char *nuevo)
00314 {
00315     char *aux = (char *) (viejo + strlen(viejo));
00316     int i=12;   //Cantidad maxima de caracteres de un archivo (11 ya que estamos en FAT)
00317     for ( ; (aux > viejo) && (*aux!='/') && i>0 ; aux--);
00318 
00319     strcpy(nuevo, aux);
00320     nuevo = str_to_lower (nuevo);
00321 }       
00322 
00325 int remover_task (task_struct_t *tarea)
00326 {
00327         task_struct_t *aux;
00328 
00329         for ( aux = tareas_inicio ; aux!=NULL ; aux=aux->proxima) {
00330                 if (aux->proxima == tarea)      {       //La encontre
00331                         aux->proxima = tarea->proxima;
00332                         return 0;
00333                 }
00334         }
00335         return -1;
00336 }

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