00001
00007 #include <routix/system.h>
00008 #include <routix/paging.h>
00009 #include <routix/segm.h>
00010 #include <routix/debug.h>
00011 #include <routix/syscalls.h>
00012 #include <sys/syscalls.h>
00013 #include <routix/elf.h>
00014 #include <routix/file.h>
00015 #include <error.h>
00016 #include <routix/timer.h>
00017 #include <routix/kalloc.h>
00018 #include <routix/kstdio.h>
00019 #include <string.h>
00020 #include <routix/task.h>
00021 #include <sys/list.h>
00022 #include <sys/types.h>
00023 #include <routix/signal.h>
00024
00025 #define RUNSTATS 1
00026
00028 #define START_PRIORITY 1
00029
00030
00032 extern task_struct_t *actual;
00034 extern task_struct_t *init_task;
00035
00036 int sys_execve (char *nombre, char **arg_p, char **env_p);
00037 inline int count_elements (char **vector);
00038
00039
00040 int sys_exit_mm(void);
00041 int sys_exit_notify(void);
00042 int sys_exit_fs (void);
00043
00044
00046 int (*syscall_process[MAX_SYSCALLS]) (void) = {
00047 (int (*) (void)) sys_exec,
00048 (int (*) (void)) sys_void,
00049 (int (*) (void)) sys_fork,
00050 (int (*) (void)) sys_perror,
00051 (int (*) (void)) sys_renice,
00052 (int (*) (void)) sys_get_pid,
00053 (int (*) (void)) sys_get_ppid,
00054 (int (*) (void)) sys_exit,
00055 (int (*) (void)) sys_show,
00056 (int (*) (void)) sys_waitpid,
00057 (int (*) (void)) sys_execve
00058 };
00059
00060
00062 int sys_void (void)
00063 {
00064 kprintf("\nLlamada a SYS Void\n");
00065 unsigned long *_esp;
00066 __asm__ __volatile__ ("movl %%esp, %0" : "=m" (_esp));
00067 kprintf("VOIDO: valor de ESP: 0x%x\n", *(_esp));
00068 kprintf("VOIDO: valor de ESP+1: 0x%x\n", *(_esp+1));
00069 kprintf("VOIDO: valor de ESP+2: 0x%x\n", *(_esp+2));
00070 kprintf("VOIDO: valor de ESP+3: 0x%x\n", *(_esp+3));
00071 kprintf("VOIDO: valor de ESP+4: 0x%x\n", *(_esp+4));
00072 kprintf("VOIDO: valor de ESP+5: 0x%x\n", *(_esp+5));
00073 kprintf("VOIDO: valor de ESP+6: 0x%x\n", *(_esp+6));
00074 kprintf("VOIDO: valor de ESP+7: 0x%x\n", *(_esp+7));
00075 kprintf("VOIDO: valor de ESP+8: 0x%x\n", *(_esp+8));
00076 kprintf("VOIDO: valor de ESP+9: 0x%x\n", *(_esp+9));
00077 kprintf("VOIDO: valor de ESP+10: 0x%x\n", *(_esp+10));
00078 kprintf("VOIDO: valor de ESP+11: 0x%x\n", *(_esp+11));
00079 kprintf("VOIDO: valor de ESP+12: 0x%x\n", *(_esp+12));
00080 kprintf("VOIDO: valor de ESP+13: 0x%x\n", *(_esp+13));
00081 kprintf("VOIDO: valor de ESP+14: 0x%x\n", *(_esp+14));
00082 kprintf("VOIDO: valor de ESP+15: 0x%x\n", *(_esp+15));
00083 kprintf("VOIDO: valor de ESP+16: 0x%x\n", *(_esp+16));
00084 kprintf("VOIDO: valor de ESP+17: 0x%x\n", *(_esp+17));
00085
00086 unsigned long *p = (unsigned long *) *(_esp+9);
00087 p = convertir_direccion (p, actual->cr3_backup);
00088
00089
00090 return OK;
00091 }
00092
00095 struct int_regs
00096 {
00097 dword ebx;
00098 dword ecx;
00099 dword edx;
00100 dword edi;
00101 dword esi;
00102 dword ebp;
00103 dword eip;
00104 dword cs;
00105 dword eflags;
00106 dword esp;
00107 dword ss;
00108 };
00109
00110
00112 int sys_fork (void)
00113 {
00114 cli();
00115
00116 struct task_struct_t *new_task;
00117
00118 struct int_regs *new, *current;
00119 struct int_regs_ext *new_ext;
00120 word i;
00121
00122
00123 new_task = init_new_task (0,0,0,0,0, actual->descripcion, actual->prioridad);
00124
00125 current = (struct int_regs *) ((actual->esp0 & 0xfffff000) + PAGINA_SIZE - sizeof(struct int_regs));
00126 new = (struct int_regs *) ((new_task->esp0 & 0xfffff000) + PAGINA_SIZE - sizeof(struct int_regs));
00127
00128 new_ext = (struct int_regs_ext *) ((new_task->esp0 & 0xfffff000) + PAGINA_SIZE - sizeof(struct int_regs_ext));
00129 new_ext = GET_CONTEXT(new_task);
00130
00131 new_ext->ds = DESC_DATA_USUARIO;
00132 new_ext->es = DESC_DATA_USUARIO;
00133 new_ext->fs = DESC_DATA_USUARIO;
00134 new_ext->gs = DESC_DATA_USUARIO;
00135
00136 new_task->esp0 = (new_task->esp0 & 0xfffff000) + PAGINA_SIZE - 64;
00137
00138
00139 memcpy(new, current, sizeof (struct int_regs) );
00140
00141
00142 new_task->num_code = actual->num_code;
00143 new_task->num_data = actual->num_data;
00144 new_task->num_stack = actual->num_stack;
00145
00146 struct user_page *mem;
00147 mem = new_task->mcode = actual->mcode;
00148
00149
00150 for ( i=0 ; i < new_task->num_code ; i++,mem=mem->next ) {
00151 if ( kmapmem( mem->dir , mem->vdir , new_task->cr3 ,PAGE_PRES|PAGE_USER|PAGE_RW)!=OK ){
00152 kprintf("Kmapmem TASK_TEXT error\n");
00153 return -1;
00154 }
00155 mem->count++;
00156 }
00157
00158 struct user_page *src = actual->mdata;
00159 struct user_page *dest;
00160
00161
00162 for( i=0 ; i < new_task->num_data ; i++) {
00163 if (i==0)
00164 dest = umalloc_page ( src->flags, src->vdir, new_task->cr3 );
00165 else {
00166 dest->next = umalloc_page ( src->flags, src->vdir, new_task->cr3 );
00167 dest = dest->next;
00168 }
00169 if (!dest) {
00170 actual->err_no = ENOMEM;
00171 return -1;
00172 }
00173 if (i==0)
00174 new_task->mdata = dest;
00175
00176
00177 copy_page ( (void *)dest->dir, (void *)src->dir);
00178 src = src->next;
00179 }
00180
00181
00182 src = actual->mstack;
00183 for( i=0 ; i < new_task->num_stack ; i++) {
00184 if (i==0)
00185 dest = umalloc_page ( src->flags, src->vdir, new_task->cr3 );
00186 else {
00187 dest->next = umalloc_page ( src->flags, src->vdir, new_task->cr3 );
00188 dest = dest->next;
00189 }
00190 if (!dest) {
00191 actual->err_no = ENOMEM;
00192 return -1;
00193 }
00194 if (i==0)
00195 new_task->mstack = dest;
00196
00197 copy_page ( (void *)dest->dir, (void *)src->dir);
00198 src = src->next;
00199 }
00200
00201 TASK_SIGNALS_ALLOC(new_task);
00202 memcpy(TASK_SIGNALS(new_task), TASK_SIGNALS(actual), sizeof(struct task_signals));
00203
00204 new_task->pid = get_new_pid();
00205 TASK_PARENT(new_task) = actual;
00206 new_task->padre = actual;
00207
00208
00209
00210 LIST_INIT (new_task->childs);
00211
00212 LIST_ADD_TAIL(actual->childs, brothers, new_task);
00213
00214
00215
00216
00217
00218 new_ext->eax = 0;
00219
00220
00221 despertar_task( new_task );
00222 sti();
00223
00224 return (new_task->pid);
00225 }
00226
00227
00234 int sys_exec (char *nombre)
00235 {
00236
00237
00238
00239 #ifdef RUNSTATS
00240 long long counter;
00241
00242 if ( getvar("debugexec") == 2 ) {
00243 rdtscl(counter);
00244 }
00245 #endif
00246
00247
00248 nombre = convertir_direccion( nombre , actual->cr3_backup);
00249
00250 int fd;
00251 byte buff_aux[100];
00252 word i;
00253
00254 struct coff_header *p;
00255 struct coff_sections sec_text, sec_data, sec_bss;
00256
00257 int bytes_leidos;
00258
00259 fd = open(nombre);
00260 if (fd < 0) {
00261 actual->err_no = ENOENT;
00262 return -1;
00263 }
00264
00265
00266 read(fd, buff_aux, sizeof(struct coff_header));
00267 p = (struct coff_header *) buff_aux;
00268
00269 if (p->f_magic != COFF32_TYPE) {
00270 actual->err_no = ENOEXEC;
00271 close(fd);
00272 return -1;
00273 }
00274 byte num_secciones;
00275 if ( (num_secciones = p->f_nscns)!= 3) {
00276 actual->err_no = ENOEXEC;
00277 close(fd);
00278 return -1;
00279 }
00280
00281 lseek (fd, sizeof(struct coff_header) + p->f_opthdr , SEEK_SET);
00282
00283 word verificacion = 0;
00284
00285 struct coff_sections *q;
00286
00287 while (num_secciones--) {
00288 read(fd, buff_aux, sizeof(struct coff_sections));
00289 q = (struct coff_sections *) buff_aux;
00290
00291 if ( q->s_flags == COFF32_TEXT ) {
00292 memcpy ( &sec_text , q , sizeof(struct coff_sections) );
00293 verificacion = verificacion | COFF32_TEXT;
00294 }
00295 else if ( q->s_flags == COFF32_DATA ) {
00296 memcpy ( &sec_data , q , sizeof(struct coff_sections) );
00297 verificacion = verificacion | COFF32_DATA;
00298 }
00299 else if ( q->s_flags == COFF32_BSS ) {
00300 memcpy ( &sec_bss , q , sizeof(struct coff_sections) );
00301 verificacion = verificacion | COFF32_BSS;
00302 }
00303 else {
00304 close(fd);
00305 actual->err_no = ENOEXEC;
00306 return -1;
00307 }
00308 }
00309
00310
00311 if (verificacion != (COFF32_TEXT | COFF32_DATA | COFF32_BSS) ) {
00312 close(fd);
00313 actual->err_no = ENOEXEC;
00314 return -1;
00315 }
00316
00317
00318 if (kmem_free() < ((actual->open_files[fd]->size / PAGINA_SIZE)+8) ) {
00319 actual->err_no = ENOMEM;
00320 close(fd);
00321 return -1;
00322 }
00323
00324
00325 word paginas_texto, paginas_datos;
00326
00327 paginas_texto = sec_text.s_size / PAGINA_SIZE;
00328 if ( sec_text.s_size % PAGINA_SIZE ) {
00329 paginas_texto++;
00330 }
00331
00332 int size_datos = sec_data.s_size + sec_bss.s_size;
00333
00334
00335 paginas_datos = size_datos / PAGINA_SIZE;
00336 if ( size_datos % PAGINA_SIZE )
00337 paginas_datos++;
00338
00339 paginas_datos++;
00340
00341
00342 int paginas_data = sec_data.s_size / PAGINA_SIZE;
00343 if ( sec_data.s_size % PAGINA_SIZE )
00344 paginas_data++;
00345
00346
00347 task_struct_t *new_task;
00348 struct user_page *mem;
00349
00350
00351 char nuevo_nombre[13];
00352 tomar_nombre_tarea(nombre, nuevo_nombre);
00353
00354
00355 new_task = init_new_task(DESC_CODE_USUARIO, DESC_DATA_USUARIO, TASK_TEXT, TASK_STACK + 4096 - 16, 0x202,\
00356 nuevo_nombre, START_PRIORITY);
00357
00358 if (!new_task) {
00359 return -1;
00360 }
00361
00362 new_task->mstack = umalloc_page (PAGINA_STACK, TASK_STACK, new_task->cr3);
00363 if (!new_task->mstack)
00364 return -1;
00365
00366 new_task->num_code = paginas_texto;
00367 new_task->num_data = paginas_datos;
00368 new_task->num_stack = 1;
00369
00370
00371 lseek(fd, sec_text.s_scnptr,SEEK_SET);
00372 new_task->mcode = umalloc_page (PAGINA_CODE,TASK_TEXT, new_task->cr3);
00373 if (!new_task->mcode)
00374 return -1;
00375 mem = new_task->mcode;
00376 bytes_leidos = read( fd, (void *)mem->dir, PAGINA_SIZE);
00377
00378 for( i=1 ; i < paginas_texto ; i++) {
00379 mem->next = umalloc_page (PAGINA_CODE, TASK_TEXT + (i*PAGINA_SIZE) , new_task->cr3);
00380 mem = mem->next;
00381 bytes_leidos = read(fd, (void *)mem->dir , PAGINA_SIZE);
00382 if (bytes_leidos < 0) {
00383 actual->err_no = EIO;
00384 close(fd);
00385 return -1;
00386 }
00387 }
00388
00389
00390 new_task->mdata = umalloc_page (PAGINA_DATA, TASK_DATA, new_task->cr3);
00391 if (!new_task->mdata)
00392 return -1;
00393 for ( mem=new_task->mdata,i=1 ; i<paginas_datos ; i++, mem=mem->next ) {
00394 mem->next = umalloc_page (PAGINA_DATA, TASK_DATA + (i*PAGINA_SIZE) , new_task->cr3);
00395 if (!mem->next)
00396 return -1;
00397 }
00398
00399
00400 lseek(fd, sec_data.s_scnptr,SEEK_SET);
00401 for( i=0, mem=new_task->mdata ; i < paginas_data ; i++, mem=mem->next ) {
00402 bytes_leidos = read(fd, (void *)mem->dir, PAGINA_SIZE);
00403 if (bytes_leidos < 0) {
00404 actual->err_no = EIO;
00405 close(fd);
00406 return -1;
00407 }
00408 };
00409
00410
00411
00412
00413
00414 for( mem=new_task->mdata ; mem->next ; mem=mem->next);
00415
00416 unsigned char *ptr_exit = (unsigned char *) mem->dir;
00417
00418
00419 *ptr_exit = 0xb8;
00420 *(unsigned long *)(ptr_exit+1) = SYS_PROCESS | SYS_EXIT;
00421 *(ptr_exit+5) = 0xbb;
00422 *(unsigned long *)(ptr_exit+6) = 0;
00423 *(ptr_exit+10) = 0xcd;
00424 *(ptr_exit+11) = 0x50;
00425
00426
00427 *(ptr_exit+12) = 0xb8;
00428 *(unsigned long *)(ptr_exit+13) = SYS_SIGNALS | SYS_SIGNAL_CHECK;
00429 *(ptr_exit+17) = 0xcd;
00430 *(ptr_exit+18) = 0x50;
00431 *(ptr_exit+19) = 0x5e;
00432 *(ptr_exit+20) = 0x5f;
00433 *(ptr_exit+21) = 0x5a;
00434 *(ptr_exit+22) = 0x59;
00435 *(ptr_exit+23) = 0x5b;
00436 *(ptr_exit+24) = 0x58;
00437 *(ptr_exit+25) = 0xc3;
00438
00439
00440 TASK_SIGNALS_ALLOC(new_task);
00441 memset (TASK_SIGNALS(new_task), 0, sizeof(struct task_signals));
00442 TASK_SIGADDR(new_task) = GET_OFFSET(ptr_exit + 12) + mem->vdir;
00443
00444
00445
00446
00447 unsigned int argc = 0;
00448 char **argv, **envp;
00449
00450 argv = NULL;
00451 envp = NULL;
00452
00453
00454 unsigned long *qwe = (unsigned long *) (new_task->mstack->dir + 4096 - 4);
00455 *(qwe--) = (unsigned long) envp;
00456 *(qwe--) = (unsigned long) argv;
00457 *(qwe--) = (unsigned long) argc;
00458 *qwe = (unsigned long) mem->vdir;
00459
00460 if (actual==pre_init_task) {
00461 TASK_PARENT(new_task) = actual;
00462 new_task->pid = get_new_pid();
00463 new_task->padre = pre_init_task;
00464
00465
00466 LIST_INIT (new_task->childs);
00467
00468 LIST_ADD (actual->childs, brothers, new_task);
00469 }
00470 else {
00471 TASK_PARENT(new_task) = TASK_PARENT(actual);
00472 new_task->pid = actual->pid;
00473 new_task->padre = actual->padre;
00474
00475
00476
00477
00478 LIST_DEL(actual->padre->childs, brothers, actual);
00479 LIST_ADD_TAIL(actual->padre->childs, brothers, new_task);
00480
00481
00482 }
00483
00484 close(fd);
00485
00486
00487 despertar_task( new_task );
00488
00489 #ifdef RUNSTATS
00490 if ( getvar("debugexec") == 2 ) {
00491 long long int counterfinal;
00492 rdtscl(counterfinal);
00493 kprintf("0x%llx ",counterfinal-counter);
00494 }
00495 #endif
00496
00497
00498 if (actual->pid!=1) {
00499
00500 cli();
00501 sys_exit_mm();
00502 remover_task (actual);
00503 kfree_page ((addr_t)actual);
00504 sti();
00505 _reschedule();
00506 }
00507
00508
00509 return OK;
00510 }
00511
00512
00513
00514
00516 void sys_perror (char *str)
00517 {
00518 str = convertir_direccion( str , actual->cr3_backup);
00519 perror(str);
00520 }
00521
00526 int sys_renice (word pid, word prioridad)
00527 {
00528
00529 task_struct_t *tmp;
00530 if ( (tmp = encontrar_proceso_por_pid(pid))==NULL ) {
00531 actual->err_no = ESRCH;
00532 return -1;
00533 }
00534
00535 if (prioridad < 1)
00536 dormir_task(tmp);
00537 tmp->prioridad = prioridad;
00538 return OK;
00539 }
00540
00542 inline pid_t sys_get_pid (void)
00543 {
00544 return actual->pid;
00545 }
00546
00548 inline pid_t sys_get_ppid (void)
00549 {
00550 return TASK_PPID(actual);
00551 }
00552
00554
00555
00557
00559 int zombie_queue_len = 0;
00560
00561
00567
00568
00569
00570
00571
00572 void sys_exit (int valor)
00573 {
00574 cli();
00575 actual->retorno = valor;
00576
00577 sys_exit_mm();
00578 sys_exit_notify();
00579 sys_exit_fs();
00580 dormir_task(actual);
00581 actual->estado = TASK_ZOMBIE;
00582 sti();
00583 _reschedule();
00584 }
00585
00588 int sys_exit_mm(void)
00589 {
00590
00591
00592 TASK_SIGNALS_FREE(actual);
00593
00594
00595 struct user_page *aux, *tmp;
00596
00597 for (aux=tmp=actual->mcode ; aux && tmp ; aux=tmp) {
00598 tmp=aux->next;
00599
00600 kunmapmem(aux->vdir, actual->cr3_backup);
00601
00602 if (getvar("__exit")==1)
00603 kprintf("Liberando Codigo dir: 0x%x\tvdir: 0x%x\n", aux->dir,aux->vdir);
00604 ufree_page(aux);
00605 }
00606
00607 for (aux=tmp=actual->mdata ; aux && tmp ; aux=tmp) {
00608 tmp=aux->next;
00609 kunmapmem(aux->vdir, actual->cr3_backup);
00610 if (getvar("__exit")==1)
00611 kprintf("Liberando Datos dir: 0x%x\tvdir: 0x%x\n", aux->dir,aux->vdir);
00612 ufree_page(aux);
00613 }
00614
00615 for (aux=tmp=actual->mstack ; aux && tmp ; aux=tmp) {
00616 tmp=aux->next;
00617 kunmapmem(aux->vdir, actual->cr3_backup);
00618 if (getvar("__exit")==1)
00619 kprintf("Liberando Stack dir: 0x%x\tvdir: 0x%x\n", aux->dir,aux->vdir);
00620 ufree_page(aux);
00621 }
00622
00623 kunmapmem (TASK_TEXT - PAGINA_SIZE, actual->cr3_backup);
00624
00625
00626
00627 kfree_page (actual->cr3_backup);
00628 return 0;
00629 }
00630
00635 int sys_exit_notify (void)
00636 {
00637
00638 zombie_queue_len++;
00639
00640 int value;
00641 pid_t pid;
00642 task_struct_t *child, *aux;
00643
00644 _LIST_FOREACH(child, actual->childs, brothers) {
00645 aux = LIST_NEXT(brothers, child);
00646
00647
00648 if (child->estado == TASK_ZOMBIE) {
00649 if (getvar("exit")==1)
00650 kprintf("Esperando al hijo: %d\n", child->pid);
00651
00652 pid = sys_waitpid(-1,&value,WNOHANG);
00653
00654 if (getvar("exit")==1)
00655 kprintf("EXIT_NOTIFY: termino hijo %d con: %d\n", pid, value);
00656 }
00657
00658 else {
00659 LIST_DEL(actual->childs, brothers, child);
00660 LIST_ADD_TAIL(init_task->childs, brothers, child);
00661 child->padre = init_task;
00662 }
00663
00664 child = aux;
00665 }
00666
00667 _sys_kill(actual->padre, SIGCHLD);
00668
00669
00670 wakeup_init();
00671 return 0;
00672 }
00673
00676 int sys_exit_fs ()
00677 {
00678 int i;
00679 for (i=0 ; i < MAX_FILES_POR_TAREA ; i++)
00680 if (actual->open_files[i]) {
00681 free(actual->open_files[i]);
00682 file_free++;
00683 }
00684
00685 return 0;
00686 }
00687
00688
00694 pid_t sys_waitpid (pid_t pid, int *status, int options)
00695 {
00696 _cli();
00697 status = convertir_direccion( status , actual->cr3_backup);
00698
00699 struct task_struct_t *child;
00700
00701 int zombie_found = 0;
00702
00703 while (1) {
00704
00705 LIST_FOREACH (child, actual->childs, brothers) {
00706
00707 if (TASK_STATE(child)!=TASK_ZOMBIE)
00708 continue;
00709
00710 if (pid>1 && pid!=TASK_PPID(child))
00711 break;
00712 zombie_found = 1;
00713 break;
00714 }
00715 if (zombie_found==1)
00716 break;
00717 if (getvar("__wait")==1)
00718 kprintf("SYS_WAIT: Mi PID es: %d\tNo encontre hijo zombie\n", actual->pid);
00719
00720
00721 if (options==WNOHANG) {
00722 if (getvar("__wait")==1)
00723 kprintf("SYS_WAIT: Me voy por el WNOHANG....\n");
00724 actual->err_no = ECHILD;
00725 _sti();
00726 return -1;
00727 }
00728 _sti();
00729 _reschedule();
00730 _cli();
00731 }
00732
00733
00734 pid_t child_pid = TASK_PID(child);
00735 if (getvar("__wait")==1)
00736 kprintf("SYS_WAIT:Mi hijo zombie es: %d\n", child->pid);
00737
00738
00739 *status = child->retorno;
00740 remover_task (child);
00741
00742
00743 LIST_DEL (actual->childs,brothers, child);
00744
00745
00746 kfree_page ((addr_t)child);
00747
00748 zombie_queue_len--;
00749
00750 _sti();
00751 return child_pid;
00752 }
00753
00754
00755
00756
00757 extern word morecores;
00758 extern struct floppy_cache *header_floppy_cache;
00759
00760 void *punteros[1000];
00761
00765 void sys_show (int valor)
00766 {
00767 int xx;
00768 int mem_before = kmem_free();
00769 int veces;
00770 int i;
00771 switch (valor) {
00772 case 1:
00773 kprintf ("Cantidad de paginas asignadas via Morecores: %d\n", morecores);
00774 break;
00775 case 2:
00776 kprintf("Sectores en cache: ");
00777 struct floppy_cache *aux;
00778 for (aux = header_floppy_cache, i=0 ; aux ; aux=aux->next, i++)
00779 kprintf("%d ", aux->sector);
00780 kprintf("\nSizeof floppy_cache: %d\n", sizeof(struct floppy_cache));
00781 kprintf("Sectores cacheados: %d\tPaginas usadas: %d\n", i, sizeof(struct floppy_cache) * i / 4096 + 1);
00782 break;
00783 case 3:
00784 kprintf ("Cantidad de procesos zombies: %d\n", zombie_queue_len);
00785 break;
00786 case 4:
00787 if ((veces=getvar("veces"))==-1)
00788 veces = 10;
00789
00790 for (xx=0 ; xx<veces ; xx++) {
00791 if ((punteros[xx]=malloc(300))==NULL) {
00792 kprintf("MALLOC ERROR\n");
00793 return;
00794 }
00795 }
00796
00797 for (xx=0 ; xx<veces ; xx++) {
00798 free(punteros[xx]);
00799 }
00800
00801 kprintf("Veces: %d\tMemoria antes: %d\tdespues: %d\n", veces, mem_before, kmem_free());
00802 break;
00803
00804 case 5:
00805 num_mallocs = num_frees = 0;
00806 task_signals_alloc = task_signals_free = 0;
00807 umalloc_alloc = umalloc_free = 0;
00808 file_alloc = file_free = 0;
00809 break;
00810 case 6:
00811 kprintf("Cantidad de Mallocs: %d\tFrees: %d\n", num_mallocs, num_frees);
00812 kprintf("Allocs de task_Signals: %d\tFrees: %d\n", task_signals_alloc, task_signals_free);
00813 kprintf("Allocs de User_page: %d\tFrees: %d\n", umalloc_alloc, umalloc_free);
00814 kprintf("Allocs de File: %d\tFrees: %d\n", file_alloc, file_free);
00815 break;
00816 case 7:
00817 task_signals_alloc = task_signals_free = 0;
00818 break;
00819 case 8:
00820 kprintf("Cantidad de Mallocs de task_Signals: %d\tFrees: %d\n", task_signals_alloc, task_signals_free);
00821 break;
00822 default:
00823
00824 break;
00825 }
00826
00827 }
00828
00829
00830
00831
00840 int sys_execve (char *nombre, char **arg_p, char **env_p)
00841 {
00842 nombre = convertir_direccion( nombre , actual->cr3_backup);
00843
00844 int fd;
00845 byte buff_aux[100];
00846 word i;
00847
00848 struct coff_header *p;
00849 struct coff_sections sec_text, sec_data, sec_bss;
00850
00851 int bytes_leidos;
00852
00853 fd = open(nombre);
00854 if (fd < 0) {
00855 actual->err_no = ENOENT;
00856 return -1;
00857 }
00858
00859
00860 read(fd, buff_aux, sizeof(struct coff_header));
00861 p = (struct coff_header *) buff_aux;
00862
00863 if (p->f_magic != COFF32_TYPE) {
00864 actual->err_no = ENOEXEC;
00865 close(fd);
00866 return -1;
00867 }
00868 byte num_secciones;
00869 if ( (num_secciones = p->f_nscns)!= 3) {
00870 actual->err_no = ENOEXEC;
00871 close(fd);
00872 return -1;
00873 }
00874
00875 lseek (fd, sizeof(struct coff_header) + p->f_opthdr , SEEK_SET);
00876
00877 word verificacion = 0;
00878
00879 struct coff_sections *q;
00880
00881 while (num_secciones--) {
00882 read(fd, buff_aux, sizeof(struct coff_sections));
00883 q = (struct coff_sections *) buff_aux;
00884
00885 if ( q->s_flags == COFF32_TEXT ) {
00886 memcpy ( &sec_text , q , sizeof(struct coff_sections) );
00887 verificacion = verificacion | COFF32_TEXT;
00888 }
00889 else if ( q->s_flags == COFF32_DATA ) {
00890 memcpy ( &sec_data , q , sizeof(struct coff_sections) );
00891 verificacion = verificacion | COFF32_DATA;
00892 }
00893 else if ( q->s_flags == COFF32_BSS ) {
00894 memcpy ( &sec_bss , q , sizeof(struct coff_sections) );
00895 verificacion = verificacion | COFF32_BSS;
00896 }
00897 else {
00898 close(fd);
00899 actual->err_no = ENOEXEC;
00900 return -1;
00901 }
00902 }
00903
00904
00905 if (verificacion != (COFF32_TEXT | COFF32_DATA | COFF32_BSS) ) {
00906 close(fd);
00907 actual->err_no = ENOEXEC;
00908 return -1;
00909 }
00910
00911
00912 if (kmem_free() < ((actual->open_files[fd]->size / PAGINA_SIZE)+8) ) {
00913 actual->err_no = ENOMEM;
00914 close(fd);
00915 return -1;
00916 }
00917
00918
00919 word paginas_texto, paginas_datos;
00920
00921 paginas_texto = sec_text.s_size / PAGINA_SIZE;
00922 if ( sec_text.s_size % PAGINA_SIZE ) {
00923 paginas_texto++;
00924 }
00925
00926 int size_datos = sec_data.s_size + sec_bss.s_size;
00927
00928
00929 paginas_datos = size_datos / PAGINA_SIZE;
00930 if ( size_datos % PAGINA_SIZE )
00931 paginas_datos++;
00932
00933 paginas_datos++;
00934
00935
00936 int paginas_data = sec_data.s_size / PAGINA_SIZE;
00937 if ( sec_data.s_size % PAGINA_SIZE )
00938 paginas_data++;
00939
00940 task_struct_t *new_task;
00941 struct user_page *mem;
00942
00943
00944 char nuevo_nombre[13];
00945 tomar_nombre_tarea(nombre, nuevo_nombre);
00946
00947
00948 new_task = init_new_task(DESC_CODE_USUARIO, DESC_DATA_USUARIO, TASK_TEXT, TASK_STACK + 4096 - 16, 0x202,\
00949 nuevo_nombre, START_PRIORITY);
00950
00951 if (!new_task) {
00952 return -1;
00953 }
00954
00955 new_task->mstack = umalloc_page (PAGINA_STACK, TASK_STACK, new_task->cr3);
00956 if (!new_task->mstack)
00957 return -1;
00958
00959 new_task->num_code = paginas_texto;
00960 new_task->num_data = paginas_datos;
00961 new_task->num_stack = 1;
00962
00963
00964 lseek(fd, sec_text.s_scnptr,SEEK_SET);
00965 new_task->mcode = umalloc_page (PAGINA_CODE,TASK_TEXT, new_task->cr3);
00966 if (!new_task->mcode)
00967 return -1;
00968 mem = new_task->mcode;
00969 bytes_leidos = read( fd, (void *)mem->dir, PAGINA_SIZE);
00970
00971 for( i=1 ; i < paginas_texto ; i++) {
00972 mem->next = umalloc_page (PAGINA_CODE, TASK_TEXT + (i*PAGINA_SIZE) , new_task->cr3);
00973 mem = mem->next;
00974 bytes_leidos = read(fd, (void *)mem->dir , PAGINA_SIZE);
00975 if (bytes_leidos < 0) {
00976 actual->err_no = EIO;
00977 close(fd);
00978 return -1;
00979 }
00980 }
00981
00982
00983 new_task->mdata = umalloc_page (PAGINA_DATA, TASK_DATA, new_task->cr3);
00984 if (!new_task->mdata)
00985 return -1;
00986 for ( mem=new_task->mdata,i=1 ; i<paginas_datos ; i++, mem=mem->next ) {
00987 mem->next = umalloc_page (PAGINA_DATA, TASK_DATA + (i*PAGINA_SIZE) , new_task->cr3);
00988 if (!mem->next)
00989 return -1;
00990 }
00991
00992
00993 lseek(fd, sec_data.s_scnptr,SEEK_SET);
00994 for( i=0, mem=new_task->mdata ; i < paginas_data ; i++, mem=mem->next ) {
00995 bytes_leidos = read(fd, (void *)mem->dir, PAGINA_SIZE);
00996 if (bytes_leidos < 0) {
00997 actual->err_no = EIO;
00998 close(fd);
00999 return -1;
01000 }
01001 };
01002
01003
01004
01005
01006 for( mem=new_task->mdata ; mem->next ; mem=mem->next);
01007
01008 unsigned char *ptr_exit = (unsigned char *) mem->dir;
01009
01010
01011 *ptr_exit = 0xb8;
01012 *(unsigned long *)(ptr_exit+1) = SYS_PROCESS | SYS_EXIT;
01013 *(ptr_exit+5) = 0xbb;
01014 *(unsigned long *)(ptr_exit+6) = 0;
01015 *(ptr_exit+10) = 0xcd;
01016 *(ptr_exit+11) = 0x50;
01017
01018
01019 *(ptr_exit+12) = 0xb8;
01020 *(unsigned long *)(ptr_exit+13) = SYS_SIGNALS | SYS_SIGNAL_CHECK;
01021 *(ptr_exit+17) = 0xcd;
01022 *(ptr_exit+18) = 0x50;
01023 *(ptr_exit+19) = 0x5e;
01024 *(ptr_exit+20) = 0x5f;
01025 *(ptr_exit+21) = 0x5a;
01026 *(ptr_exit+22) = 0x59;
01027 *(ptr_exit+23) = 0x5b;
01028 *(ptr_exit+24) = 0x58;
01029 *(ptr_exit+25) = 0xc3;
01030
01031 TASK_SIGNALS_ALLOC(new_task);
01032 memset (TASK_SIGNALS(new_task), 0, sizeof(struct task_signals));
01033 TASK_SIGADDR(new_task) = GET_OFFSET(ptr_exit + 12) + mem->vdir;
01034
01035 #define EXIT_CALL_LEN 12
01036 #define SIGNAL_CHECK_LEN 14
01037
01038
01039 arg_p = convertir_direccion(arg_p, actual->cr3_backup);
01040 env_p = convertir_direccion(env_p, actual->cr3_backup);
01041
01042 char **argv, **envp;
01043
01044 int argc = count_elements (arg_p) + 1;
01045
01046 int envc = count_elements (env_p);
01047
01048 char *aux_dest;
01049 argv = (char **) ptr_exit + EXIT_CALL_LEN + SIGNAL_CHECK_LEN;
01050 aux_dest = (char *)(argv + argc + 1);
01051 strcpy(aux_dest, nuevo_nombre);
01052 int z;
01053
01054 for (z=0 ; z<argc ; z++) {
01055 argv[z] = GET_OFFSET(aux_dest) + (char *) mem->vdir;
01056 aux_dest += strlen(aux_dest) + 1;
01057 strcpy(aux_dest, convertir_direccion(arg_p[z], actual->cr3_backup));
01058 }
01059
01060 argv[z+2] = NULL;
01061
01062
01063 envp = (char **) ALINEAR_4(aux_dest + strlen(aux_dest) + 4);
01064
01065 aux_dest = (char *) (envp + envc + 2);
01066 for (z=0 ; z<envc ; z++) {
01067 strcpy(aux_dest, convertir_direccion(env_p[z], actual->cr3_backup));
01068 envp[z] = GET_OFFSET(aux_dest) + (char *) mem->vdir;
01069 aux_dest += strlen(aux_dest) + 1;
01070 }
01071
01072 envp[z+1] = NULL;
01073
01074 argv = (char **)(GET_OFFSET(argv) + (char *) mem->vdir);
01075 envp = (char **)(GET_OFFSET(envp) + (char *) mem->vdir);
01076
01077
01078 unsigned long *qwe = (unsigned long *) (new_task->mstack->dir + 4096 - 4);
01079 *(qwe--) = (unsigned long) envp;
01080 *(qwe--) = (unsigned long) argv;
01081 *(qwe--) = (unsigned long) argc;
01082 *qwe = (unsigned long) mem->vdir;
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097 if (actual==pre_init_task) {
01098 TASK_PARENT(new_task) = actual;
01099 new_task->pid = get_new_pid();
01100 new_task->padre = pre_init_task;
01101
01102
01103 LIST_INIT (new_task->childs);
01104
01105 LIST_ADD (actual->childs, brothers, new_task);
01106 }
01107 else {
01108 TASK_PARENT(new_task) = TASK_PARENT(actual);
01109 new_task->pid = actual->pid;
01110 new_task->padre = actual->padre;
01111
01112
01113
01114
01115 LIST_DEL(actual->padre->childs, brothers, actual);
01116 LIST_ADD_TAIL(actual->padre->childs, brothers, new_task);
01117
01118
01119 }
01120
01121
01122 close(fd);
01123
01124
01125 despertar_task( new_task );
01126
01127
01128 if (actual->pid!=1) {
01129 cli();
01130 sys_exit_mm();
01131 remover_task (actual);
01132 kfree_page ((addr_t)actual);
01133 sti();
01134 _reschedule();
01135 }
01136 return OK;
01137 }
01138
01140 inline int count_elements (char **vector)
01141 {
01142 int i;
01143 for ( i=0 ; vector[i]!=NULL && i<10 && vector; i++);
01144 return i;
01145 }