initial commit
[pfinal.git] / Routix / src / sched / task.c
blob05f503e8829ae1009b6e31949ae280bdab80c745
1 /*! \addtogroup Scheduler
2 \page task.c
3 Se incluyen todas las funciones relacionadas con la creación y estado de las tareas y el manejo del TSS.
4 */
6 #include "routix/system.h"
7 #include "routix/task.h"
8 #include "routix/paging.h"
9 #include "routix/kalloc.h"
10 #include "error.h"
11 #include "routix/file.h"
12 #include "string.h"
14 #include "sys/list.h"
16 // Un solo tss
17 tss_t tss;
19 void inicializarTss(tss_t *tss, word cs, word ds, dword eip, dword esp, dword eflags)
21 tss->ss0 = DESC_DATA;
22 tss->cs=cs;
23 tss->ds=ds;
24 tss->es=ds;
25 tss->fs=ds;
26 tss->gs=ds;
27 tss->ss=ds;
28 tss->eip=eip;
29 tss->esp=esp;
30 tss->eflags=eflags;
31 tss->ldt=0;
32 tss->t=0;
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
42 interrupcion
43 push eax
44 push ebx
45 push ecx
46 push edx
47 push ds
48 push es
49 push fs
50 push gs
51 push ebp
52 push esi
53 push edi
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
63 stack--;
64 *stack-- = ds; //ss
65 *stack-- = esp;
66 *stack-- = eflags;
67 *stack-- = cs;
68 *stack-- = eip;
69 *stack-- = 0; //ebp
70 *stack-- = 0; //esi
71 *stack-- = 0; //edi
72 *stack-- = 0; //edx
73 *stack-- = 0; //ecx
74 *stack-- = 0; //ebx
75 *stack-- = 0; //eax
76 *stack-- = ds; //ds
77 *stack-- = ds; //es
78 *stack-- = ds; //fs
79 *stack = ds; //gs
81 return stack;
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)
88 stack--;
89 *stack-- = ds; //ss
90 *stack-- = esp;
91 *stack-- = eflags;
92 *stack-- = cs;
93 *stack-- = eip;
94 *stack-- = eax; //eax
95 *stack-- = ebx; //ebx
96 *stack-- = ecx; //ecx
97 *stack-- = edx; //edx
98 *stack-- = ds; //ds
99 *stack-- = ds; //es
100 *stack-- = ds; //fs
101 *stack-- = ds; //gs
102 *stack-- = ebp; //ebp
103 *stack-- = esi; //esi
104 *stack = edi; //edi
106 return stack;
111 inline pid_t get_new_pid(void)
113 static pid_t pid=2;
115 return(pid++);
120 // Contador de tareas activas ( estado == TASK_RUNNING )
121 volatile int tareas_activas=0;
123 void inc_tareas_activas()
125 ++tareas_activas;
128 inline void dormir_task(task_struct_t *tarea)
130 // No puede ser interrumpida por el TimerTick (Atomicidad)
131 cli();
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;
137 --tareas_activas;
139 if ( tareas_activas < 1 && init_task->estado!=TASK_RUNNING) {
140 init_task->estado=TASK_RUNNING;
141 tareas_activas++;
144 sti();
147 inline void despertar_task(task_struct_t *tarea)
149 // No puede ser interrumpida por el TimerTick (Atomicidad)
150 cli();
152 tarea->estado = TASK_RUNNING;
153 tareas_activas++;
155 if ( tareas_activas > 1 && init_task->estado==TASK_RUNNING ) {
156 init_task->estado=TASK_STOPPED;
157 tareas_activas--;
160 sti();
164 inline void sleep_init()
166 cli();
167 //if ( tareas_activas > 1 && init_task->estado==TASK_RUNNING ) {
168 if ( init_task->estado==TASK_RUNNING ) {
169 init_task->estado=TASK_STOPPED;
170 tareas_activas--;
172 sti();
175 inline void wakeup_init()
177 cli();
178 if (init_task->estado!=TASK_RUNNING) {
179 init_task->estado=TASK_RUNNING;
180 tareas_activas++;
182 sti();
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;
189 dword esp0;
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 ) {
193 return 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);
205 return NULL;
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;
222 nueva->err_no = 0;
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)
231 word j;
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
237 int init_signo;
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) ) {
245 kpanic("aca");
247 // No pudimos insertarla !! liberamos la memoria
248 kfree_page((addr_t)nueva);
249 return NULL;
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 );
259 return nueva;
266 int insertar_tarea(task_struct_t *nueva)
268 task_struct_t *tmp;
270 if ( nueva == NULL ) { return 0; }
272 cli();
274 // Nos paramos al ppio de la lista
275 tmp = tareas_inicio;
277 if ( tareas_inicio == NULL ) { tareas_inicio = nueva; }
279 else {
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;
291 sti();
292 return 1;
297 task_struct_t *encontrar_proceso_por_pid(pid_t pid)
299 task_struct_t *tmp;
301 for( tmp = tareas_inicio; tmp && (tmp->pid != pid); tmp = tmp->proxima) ;
303 return tmp;
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--);
318 strcpy(nuevo, 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)
326 task_struct_t *aux;
328 for ( aux = tareas_inicio ; aux!=NULL ; aux=aux->proxima) {
329 if (aux->proxima == tarea) { //La encontre
330 aux->proxima = tarea->proxima;
331 return 0;
334 return -1;
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;
341 dword esp0;
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 ) {
345 return 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;
367 nueva->err_no = 0;
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)
376 word j;
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
382 int init_signo;
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) ) {
392 kpanic("aca");
394 // No pudimos insertarla !! liberamos la memoria
395 kfree_page((addr_t)nueva);
396 return NULL;
400 return nueva;