1 /*! \addtogroup Scheduler
3 Se incluyen todas las funciones relacionadas con la creación y estado de las tareas y el manejo del TSS.
6 #include "routix/system.h"
7 #include "routix/task.h"
8 #include "routix/paging.h"
9 #include "routix/kalloc.h"
11 #include "routix/file.h"
19 void inicializarTss(tss_t
*tss
, word cs
, word ds
, dword eip
, dword esp
, dword eflags
)
33 tss
->cr3
=POSICION_DIR_PAGINAS
;
37 //Agregado de ebp para facilitar el fork
38 dword
*inicializar_task(dword
*stack
, word cs
, word ds
, dword eip
, dword esp
, dword eflags
)
41 /* Recordemos como se pushean los datos al stack
55 o sea, tenemos en el siguiente orden:
56 Interrupción : ss, esp, eflags, cs, eip
57 Push manuales: eax, ebx, .... , edi
59 debemos cargar el stack del kernel de la misma manera
85 dword *inicializar_fork(dword *stack,word cs,word ds,dword eip,dword esp,dword eflags,dword ebp, dword eax, dword ebx, \
86 dword ecx, dword edx, dword edi, dword esi)
102 *stack-- = ebp; //ebp
103 *stack-- = esi; //esi
111 inline pid_t
get_new_pid(void)
120 // Contador de tareas activas ( estado == TASK_RUNNING )
121 volatile int tareas_activas
=0;
123 void inc_tareas_activas()
128 inline void dormir_task(task_struct_t
*tarea
)
130 // No puede ser interrumpida por el TimerTick (Atomicidad)
133 // Cambiamos su estado y le sacamos el resto de tiempo de cpu que le faltaba
134 tarea
->estado
= TASK_INTERRUMPIBLE
;
135 tarea
->cuenta
=tarea
->prioridad
;
139 if ( tareas_activas < 1 && init_task->estado!=TASK_RUNNING) {
140 init_task->estado=TASK_RUNNING;
147 inline void despertar_task(task_struct_t
*tarea
)
149 // No puede ser interrumpida por el TimerTick (Atomicidad)
152 tarea
->estado
= TASK_RUNNING
;
155 if ( tareas_activas > 1 && init_task->estado==TASK_RUNNING ) {
156 init_task->estado=TASK_STOPPED;
164 inline void sleep_init()
167 //if ( tareas_activas > 1 && init_task->estado==TASK_RUNNING ) {
168 if ( init_task
->estado
==TASK_RUNNING
) {
169 init_task
->estado
=TASK_STOPPED
;
175 inline void wakeup_init()
178 if (init_task
->estado
!=TASK_RUNNING
) {
179 init_task
->estado
=TASK_RUNNING
;
186 task_struct_t
* init_new_task(word cs
, word ds
, dword eip
, dword esp
, dword eflags
, char *descripcion
, word prioridad
)
188 task_struct_t
*nueva
;
191 // Alocamos una página completa (para el descriptor de tarea y el stack en modo kernel).
192 if ( (nueva
= (task_struct_t
*) kmalloc_page()) == NULL
) {
196 //Provisorio, debe ser más performante !!!
197 memset(nueva
, 0, PAGINA_SIZE
);
199 // Selector de Datos (DPL=0) y esp0 al final de la página
200 esp0
= (dword
) nueva
+ 4092;
202 // Crear un directorio de paginas y alojar su dir en cr3
203 if ( (nueva
->cr3
= (addr_t
) make_pdt()) == NULL
) {
204 kfree_page((addr_t
)nueva
);
208 nueva
->cr3_backup
= nueva
->cr3
;
210 // Esto debe hacerse sólo en la llamada a fork (o en exec si el que llama es init)
211 // nueva->pid = get_new_pid();
212 strcpy( nueva
->descripcion
, descripcion
);
214 // Ponemos la tarea a correr
215 //nueva->estado = TASK_RUNNING;
216 // Stoppeada hasta no terminar todo el proceso de creacion, la debe despertar otra funcion
217 // como por ejemplo sys_exec()
218 nueva
->estado
= TASK_STOPPED
;
220 nueva
->prioridad
= prioridad
;
224 // Cantidad de ticks que tiene permitido usar la cpu en forma continua
225 nueva
->cuenta
= prioridad
;
226 nueva
->tiempo_cpu
= 0;
228 // Inicializamos la estructura que contiene el contexto de hardware de la tarea
229 nueva
->esp0
= (dword
) inicializar_task((dword
*)esp0
,cs
,ds
,eip
,esp
,eflags
); //el ultimo 0 es ebp (provisorio)
232 for (j
=0 ; j
<MAX_FILES_POR_TAREA
; j
++)
233 nueva
->open_files
[j
] = NULL
;
235 // Inicializo todos los handlers de señal a SIG_DFL
238 for (init_signo=0 ; init_signo<SIGMAX ; init_signo++)
239 (TASK_SIGNAL_HANDLER(actual, init_signo)) = SIG_DFL;
243 // Insertamos la tarea en la lista
244 if ( ! insertar_tarea(nueva
) ) {
247 // No pudimos insertarla !! liberamos la memoria
248 kfree_page((addr_t
)nueva
);
252 BITMAP_INIT(nueva
->thread_bitmap
, MAX_THREADS_PER_PROCESS
);
253 LIST_INIT(nueva
->threads
);
254 // Si hay más de una tarea activa ponemos a dormir al idle task
255 //if ( ++tareas_activas > 1 ) {
256 // dormir_task( tareas_inicio );
266 int insertar_tarea(task_struct_t
*nueva
)
270 if ( nueva
== NULL
) { return 0; }
274 // Nos paramos al ppio de la lista
277 if ( tareas_inicio
== NULL
) { tareas_inicio
= nueva
; }
281 // Buscamos la última tarea
282 for ( tmp
= tareas_inicio
; tmp
->proxima
!= NULL
; tmp
= tmp
->proxima
);
284 // Nos colgamos de ella
285 tmp
->proxima
= nueva
;
288 // La nueva tarea queda apuntando a NULL
289 nueva
->proxima
= NULL
;
297 task_struct_t
*encontrar_proceso_por_pid(pid_t pid
)
301 for( tmp
= tareas_inicio
; tmp
&& (tmp
->pid
!= pid
); tmp
= tmp
->proxima
) ;
307 /* Esta funcion toma un path de archivo, y coloca en nuevo solo el nombre del archivo.
308 * Ej: viejo[]="/files/rotor.bin" ---> nuevo[]="rotor.bin"
309 * (usado por ejemplo en el "ps")
312 void tomar_nombre_tarea (const char *viejo
, char *nuevo
)
314 char *aux
= (char *) (viejo
+ strlen(viejo
));
315 int i
=12; //Cantidad maxima de caracteres de un archivo (11 ya que estamos en FAT)
316 for ( ; (aux
> viejo
) && (*aux
!='/') && i
>0 ; aux
--);
319 nuevo
= str_to_lower (nuevo
);
322 /*! Saca a un proceso de la lista de procesos del scheduler
324 int remover_task (task_struct_t
*tarea
)
328 for ( aux
= tareas_inicio
; aux
!=NULL
; aux
=aux
->proxima
) {
329 if (aux
->proxima
== tarea
) { //La encontre
330 aux
->proxima
= tarea
->proxima
;
338 thread_struct_t
* init_new_thread(word cs
, word ds
, dword eip
, dword esp
, dword eflags
, char *descripcion
, word prioridad
)
340 task_struct_t
*nueva
;
343 // Alocamos una página completa (para el descriptor de tarea y el stack en modo kernel).
344 if ( (nueva
= (task_struct_t
*) kmalloc_page()) == NULL
) {
348 //Provisorio, debe ser más performante !!!
349 memset(nueva
, 0, PAGINA_SIZE
);
351 // Selector de Datos (DPL=0) y esp0 al final de la página
352 esp0
= (dword
) nueva
+ 4092;
355 // Esto debe hacerse sólo en la llamada a fork (o en exec si el que llama es init)
356 // nueva->pid = get_new_pid();
357 strcpy( nueva
->descripcion
, descripcion
);
359 // Ponemos la tarea a correr
360 //nueva->estado = TASK_RUNNING;
361 // Stoppeada hasta no terminar todo el proceso de creacion, la debe despertar otra funcion
362 // como por ejemplo sys_exec()
363 nueva
->estado
= TASK_STOPPED
;
365 nueva
->prioridad
= prioridad
;
369 // Cantidad de ticks que tiene permitido usar la cpu en forma continua
370 nueva
->cuenta
= prioridad
;
371 nueva
->tiempo_cpu
= 0;
373 // Inicializamos la estructura que contiene el contexto de hardware de la tarea
374 nueva
->esp0
= (dword
) inicializar_task((dword
*)esp0
,cs
,ds
,eip
,esp
,eflags
); //el ultimo 0 es ebp (provisorio)
377 for (j
=0 ; j
<MAX_FILES_POR_TAREA
; j
++)
378 nueva
->open_files
[j
] = NULL
;
380 // Inicializo todos los handlers de señal a SIG_DFL
383 for (init_signo=0 ; init_signo<SIGMAX ; init_signo++)
384 (TASK_SIGNAL_HANDLER(actual, init_signo)) = SIG_DFL;
388 // La idea es que los threads se scheduleen de otra forma
390 // Insertamos la tarea en la lista
391 if ( ! insertar_tarea(nueva) ) {
394 // No pudimos insertarla !! liberamos la memoria
395 kfree_page((addr_t)nueva);