Functions | |||||||||||||
task_t * | create_kthread (void *address, char *pname) | ||||||||||||
Create a new kernel thread.
| |||||||||||||
task_t * | create_process (void *address, void *buffer, size_t size, char *pname, int privilege) | ||||||||||||
Create a new process.
| |||||||||||||
size_t | new_vspace () | ||||||||||||
Create a new virtual space.
| |||||||||||||
uint32_t * | task_setup_stack (int argc, char **argv, addr_t stack_start, size_t stack_size, int privilege) | ||||||||||||
Initialize the stack for a new process.
| |||||||||||||
task_t * | new_task (char *filename, int argc, char **argv, int privilege) | ||||||||||||
Execute a file creating a new task.
| |||||||||||||
bool | kill (pid_t pid) | ||||||||||||
Kill a task by the pid.
| |||||||||||||
void | auto_kill (int n) | ||||||||||||
Kill the current running task.
| |||||||||||||
pid_t | waitpid (pid_t pid, int *status, int options) | ||||||||||||
Wait for the exit of a child.
| |||||||||||||
void | sleep_task (task_t *p) | ||||||||||||
Sleep a process if it is awake.
| |||||||||||||
void | wakeup_task (task_t *p) | ||||||||||||
Wakeup a process if it is sleeping.
|
|
Kill the current running task.
This routine move the current task from the ready queue to the zombie queue. Then the kpager() daemon should provide to free the memory and resources owned by this task. Definition at line 949 of file task.c.
|
|
Create a new kernel thread.
This routine initialize a new kernel thread structure and add this thread to the ready queue. Definition at line 234 of file task.c.
00235 { 00236 task_t *new_task; 00237 byte *pl0_stack; 00238 00239 sched_enter_critical_region(); 00240 00241 // --- Create the task structure -------------------------------// 00242 //! 00243 //! IA-32 Intel(R) Architecture Software Developer's Manual 00244 //! Volume 3: System Programming Guide - Chapter 6 - reports: 00245 //! 00246 //! "If paging is used, care should be taken to avoid placing a 00247 //! page boundary within the part of the TSS that the processor 00248 //! reads during a task switch (the first 104 bytes). If a page 00249 //! boundary is placed within this part of the TSS, the pages on 00250 //! either side of the boundary must be present at the same time 00251 //! and contiguous in physical memory. 00252 //! 00253 //! The reason for this restriction is that when accessing a TSS 00254 //! during a task switch, the processor reads and writes into 00255 //! the first 104 bytes of each TSS from contiguous physical 00256 //! addresses beginning with the physical address of the first 00257 //! byte of the TSS. It may not perform address translation at a 00258 //! page boundary if one occurs within this area. So, after the 00259 //! TSS access begins, if a part of the 104 bytes is not both 00260 //! present and physically contiguous, the processor will access 00261 //! incorrect TSS information, without generating a page-fault 00262 //! exception. The reading of this incorrect information will 00263 //! generally lead to an unrecoverable exception later in the 00264 //! task switch process..." 00265 new_task = kmemalign(PAGE_SIZE, sizeof(task_t)); 00266 if (new_task == NULL) 00267 { 00268 // Out of virtual memory!!! // 00269 set_color(LIGHT_RED); 00270 kprintf("\n\rOut of virtual memory!!! Cannot create task [%s]\n\r", pname); 00271 set_color(DEFAULT_COLOR); 00272 00273 sched_leave_critical_region(); 00274 return(NULL); 00275 } 00276 memset(new_task, 0, sizeof(task_t)); 00277 00278 // --- Create the pl0-stack --- // 00279 pl0_stack = kmalloc(STACK_SIZE); 00280 if (pl0_stack == NULL) 00281 { 00282 // Out of virtual memory!!! // 00283 set_color(LIGHT_RED); 00284 kprintf("\n\rOut of virtual memory!!! Cannot create task [%s]\n\r", pname); 00285 set_color(DEFAULT_COLOR); 00286 // Free the previous allocated space // 00287 kfree((void *)new_task); 00288 00289 sched_leave_critical_region(); 00290 return(NULL); 00291 } 00292 // Null the stack to enforce the page mapping // 00293 memset(pl0_stack, 0, STACK_SIZE); 00294 // Setup the pl0-stack // 00295 new_task->tss.ss0 = new_task->tss.ss = KERNEL_STACK; 00296 new_task->tss.esp0 = new_task->tss.esp = new_task->pl0_stack = (dword)(pl0_stack+STACK_SIZE-sizeof(uint32_t)); 00297 00298 // --- Setup the TSS --- // 00299 new_task->tss_sel = setup_GDT_entry(sizeof(tss_IO_t), (dword)&(new_task->tss), TSS_SEG, 0); 00300 00301 // Setup the task PDBR => get the kernel PDBR // 00302 new_task->tss.cr3 = GET_PDBR(); 00303 00304 // Setup the IO port mapping // 00305 new_task->tss.io_map_addr = sizeof(tss_t); 00306 00307 // Setup general registers // 00308 new_task->tss.ds = new_task->tss.es = KERNEL_DATA; 00309 new_task->tss.fs = new_task->tss.gs = KERNEL_DATA; 00310 new_task->tss.eflags = EFLAGS_IF | 0x02; 00311 00312 // Initialize general purpose registers // 00313 new_task->tss.eax = new_task->tss.ebx = 00314 new_task->tss.ecx = new_task->tss.edx = 00315 new_task->tss.esi = new_task->tss.edi = 0; 00316 00317 // Initialize LDTR (Local Descriptor Table Register) // 00318 // No LDTs for now... 00319 new_task->tss.ldtr = 0; 00320 00321 // Initialize debug trap // 00322 // If set to 1 the processor generate a debug exception when a task switch to this task occurs... 00323 new_task->tss.trace = 0; 00324 00325 // Setup starting address // 00326 new_task->tss.cs = KERNEL_CODE; 00327 new_task->tss.eip = (dword)address; 00328 00329 // --- Get a pid --- // 00330 new_task->pid = new_pid(); 00331 00332 // --- Store the name --- // 00333 // The last character must be ever '\0' (end of string) // 00334 strncpy(new_task->name, pname, sizeof(new_task->name)-2); 00335 00336 // --- Set the type --- // 00337 new_task->type = KTHREAD_T; 00338 00339 // --- Set the parent process --- // 00340 new_task->father = curr_task; 00341 00342 // --- Set the console --- // 00343 new_task->console = curr_task->console; 00344 00345 // --- Insert the task into the ready queue --- // 00346 new_task->state = READY; 00347 add_queue(&ready_queue, new_task); 00348 00349 sched_leave_critical_region(); 00350 00351 return (new_task); 00352 } |
|
Create a new process.
This routine initializes the new task structure, copies the content of the buffer to the entry point address and then add the new task to the ready queue. Definition at line 374 of file task.c.
00375 { 00376 task_t *new_task; 00377 byte *pl0_stack; 00378 dword *PDBR; 00379 dword PDBR_frame, i; 00380 register dword cr3; 00381 00382 sched_enter_critical_region(); 00383 00384 // --- Create the task structure -------------------------------// 00385 //! 00386 //! IA-32 Intel(R) Architecture Software Developer's Manual 00387 //! Volume 3: System Programming Guide - Chapter 6 - reports: 00388 //! 00389 //! "If paging is used, care should be taken to avoid placing a 00390 //! page boundary within the part of the TSS that the processor 00391 //! reads during a task switch (the first 104 bytes). If a page 00392 //! boundary is placed within this part of the TSS, the pages on 00393 //! either side of the boundary must be present at the same time 00394 //! and contiguous in physical memory. 00395 //! 00396 //! The reason for this restriction is that when accessing a TSS 00397 //! during a task switch, the processor reads and writes into 00398 //! the first 104 bytes of each TSS from contiguous physical 00399 //! addresses beginning with the physical address of the first 00400 //! byte of the TSS. It may not perform address translation at a 00401 //! page boundary if one occurs within this area. So, after the 00402 //! TSS access begins, if a part of the 104 bytes is not both 00403 //! present and physically contiguous, the processor will access 00404 //! incorrect TSS information, without generating a page-fault 00405 //! exception. The reading of this incorrect information will 00406 //! generally lead to an unrecoverable exception later in the 00407 //! task switch process..." 00408 new_task = kmemalign(PAGE_SIZE, sizeof(task_t)); 00409 if (new_task == NULL) 00410 { 00411 // Out of virtual memory!!! // 00412 set_color(LIGHT_RED); 00413 kprintf("\n\rOut of virtual memory!!! Cannot create task [%s]\n\r", pname); 00414 set_color(DEFAULT_COLOR); 00415 00416 sched_leave_critical_region(); 00417 return(NULL); 00418 } 00419 memset(new_task, 0, sizeof(task_t)); 00420 00421 // --- Create the pl0-stack --- // 00422 pl0_stack = kmalloc(STACK_SIZE); 00423 if (pl0_stack == NULL) 00424 { 00425 // Out of virtual memory!!! // 00426 set_color(LIGHT_RED); 00427 kprintf("\n\rOut of virtual memory!!! Cannot create task [%s]\n\r", pname); 00428 set_color(DEFAULT_COLOR); 00429 // Free the previous allocated space // 00430 kfree((void *)new_task); 00431 00432 sched_leave_critical_region(); 00433 return(NULL); 00434 } 00435 // Null the stack to enforce the page mapping // 00436 memset(pl0_stack, 0, STACK_SIZE); 00437 // Setup the pl0-stack // 00438 new_task->tss.ss0 = KERNEL_STACK; 00439 new_task->tss.esp0 = new_task->pl0_stack = (dword)(pl0_stack+STACK_SIZE-sizeof(uint32_t)); 00440 00441 // --- Setup the TSS --- // 00442 new_task->tss_sel = setup_GDT_entry(sizeof(tss_IO_t), (dword)&(new_task->tss), TSS_SEG, 0); 00443 00444 // --- Create the virtual space of the task ------------------- // 00445 PDBR = (dword *)get_temp_page(); 00446 if ( PDBR == NULL ) 00447 { 00448 // Out of memory!!! Free the previous allocated memory. // 00449 set_color(LIGHT_RED); 00450 kprintf("\n\rOut memory!!! Cannot create task [%s]\n\r", pname); 00451 set_color(DEFAULT_COLOR); 00452 // Free the previous allocated space // 00453 kfree((void *)(pl0_stack)); 00454 kfree((void *)new_task); 00455 // Destroy the TSS // 00456 remove_GDT_entry(new_task->tss_sel); 00457 // Free the 00458 00459 sched_leave_critical_region(); 00460 return(NULL); 00461 } 00462 PDBR_frame = vir_to_phys( (dword)PDBR ); 00463 00464 // Initialize PDBR // 00465 memset(PDBR, 0, PAGE_SIZE); 00466 for (i=K_VIR_START/(PAGE_SIZE*1024); i<1024; i++) 00467 PDBR[i] = K_PDBR[i]; 00468 00469 // Map page directory into itself // 00470 PDBR[1023] = PDBR_frame | P_PRESENT | P_WRITE; 00471 00472 // Unmap the temporary page, without free the physical frame // 00473 free_temp_page(PDBR, FALSE); 00474 00475 // Temporary switch to the new address space // 00476 // // 00477 // QUESTION: cr3 is in the stack... if I switch into the new // 00478 // address space can I ever see the old cr3 value??? // 00479 // // 00480 // RE: Yes, but only if cr3 is stored into a register... // 00481 // And if the value should be stored into the stack, here we // 00482 // are at CPL0, so we're using the 0-privileged stack, so, // 00483 // since the 0-privileged stack space is shared between every // 00484 // task and also the kernel, we're ever able to see the stored // 00485 // cr3 value... // 00486 __asm__ __volatile__ ("movl %%cr3, %0" : "=r"(cr3) : ); 00487 __asm__ __volatile__ ("movl %0, %%cr3" : : "r"(PDBR_frame)); 00488 00489 // --- Create the user space --- // 00490 00491 // Create the task stack // 00492 new_task->tss.ss = (privilege == KERNEL_PRIVILEGE) ? KERNEL_STACK : USER_STACK | 3; 00493 if ( privilege == KERNEL_PRIVILEGE ) 00494 new_task->tss.esp = new_task->pl0_stack; 00495 else 00496 new_task->tss.esp = (dword)(TASK_STACK_START-sizeof(size_t)); 00497 00498 // Map the user code and data space. // 00499 // ("address" is the virtual task space, "buffer" is the // 00500 // kernel space where the task-code is located). // 00501 if (address != buffer) 00502 { 00503 memcpy(address, buffer, size); 00504 } 00505 00506 // Restore the old address space // 00507 __asm__ __volatile__ ("movl %0, %%cr3" : : "r"(cr3)); 00508 00509 // Setup the task PDBR // 00510 new_task->tss.cr3 = PDBR_frame; 00511 00512 // Setup the IO port mapping // 00513 new_task->tss.io_map_addr = sizeof(tss_t); 00514 00515 // Setup general registers // 00516 if ( privilege == KERNEL_PRIVILEGE ) 00517 new_task->tss.ds = new_task->tss.es = 00518 new_task->tss.fs = new_task->tss.gs = KERNEL_DATA; 00519 else 00520 new_task->tss.ds = new_task->tss.es = 00521 new_task->tss.fs = new_task->tss.gs = USER_DATA | 3; 00522 00523 new_task->tss.eflags = EFLAGS_IF | 0x02; 00524 if ( privilege == USER_PRIVILEGE ) 00525 // User tasks must have the I/O privilege level // 00526 // at the lower level // 00527 new_task->tss.eflags |= EFLAGS_IOPL3; 00528 00529 // Initialize general purpose registers // 00530 new_task->tss.eax = new_task->tss.ebx = 00531 new_task->tss.ecx = new_task->tss.edx = 00532 new_task->tss.esi = new_task->tss.edi = 0; 00533 00534 // Initialize LDTR (Local Descriptor Table Register) // 00535 // No LDTs for now... 00536 new_task->tss.ldtr = 0; 00537 00538 // Initialize debug trap // 00539 // If set to 1 the processor generates a debug exception when a // 00540 // task switch to this task occurs... // 00541 new_task->tss.trace = 0; 00542 00543 // Setup starting address // 00544 new_task->tss.cs = (privilege == KERNEL_PRIVILEGE) ? KERNEL_CODE : USER_CODE | 3; 00545 new_task->tss.eip = (dword)address; 00546 00547 // --- Get a pid --- // 00548 new_task->pid = new_pid(); 00549 00550 // --- Store the name --- // 00551 // The last character must be ever '\0' (end of string) // 00552 strncpy(new_task->name, pname, sizeof(new_task->name)-2); 00553 00554 // --- Set the type --- // 00555 new_task->type = PROCESS_T; 00556 00557 // --- Set the parent process --- // 00558 new_task->father = curr_task; 00559 00560 // --- Set the console --- // 00561 if( curr_task ) 00562 new_task->console = curr_task->console; 00563 00564 // --- Insert the task into the ready queue --- // 00565 new_task->state = READY; 00566 add_queue(&ready_queue, new_task); 00567 00568 sched_leave_critical_region(); 00569 return (new_task); 00570 } |
|
Kill a task by the pid.
This routine move the task having the pid from the ready queue to the zombie queue. Then the kpager() daemon should provide to free the memory and resources owned by this task. Definition at line 881 of file task.c.
00882 { 00883 // Queues where to search the processes // 00884 static queue_t **q[] = { &ready_queue, &wait_queue }; 00885 task_t *p = curr_task; 00886 bool retval = FALSE; 00887 register int i, j, n; 00888 00889 // No running processes(???) => quit! // 00890 if ( p==NULL ) 00891 return(FALSE); 00892 00893 sched_enter_critical_region(); 00894 00895 // Explore every task queue // 00896 for ( i=0; i<_countof(q); i++) 00897 for ( j=0, n=count_queue(q[i]); j<n; j++ ) 00898 { 00899 // Get the next task in the queue // 00900 p = pick_queue( q[i] ); 00901 00902 if ( p->pid == pid ) 00903 { 00904 // Move the task from the queue to the // 00905 // zombie queue // 00906 if ( rem_queue(q[i], p) ) 00907 { 00908 add_queue(&zombie_queue, p); 00909 p->state = ZOMBIE; 00910 // Wake-up the kpager daemon // 00911 wakeup_task( kpagd ); 00912 // Wake-up the father // 00913 if ( p->father != NULL ) 00914 wakeup_task( p->father ); 00915 // Task killed! // 00916 retval = TRUE; 00917 } 00918 } 00919 else 00920 { 00921 // If the process p is a child of the // 00922 // process to kill we have to set its // 00923 // father to NULL // 00924 if ( p->father != NULL ) 00925 if ( (p->father)->pid == pid ) 00926 p->father = NULL; 00927 } 00928 } 00929 00930 // Check if the task has killed itself // 00931 if (curr_task->pid == pid) 00932 { 00933 sched_leave_critical_region(); 00934 // Wait for the dispatcher // 00935 do_idle(); 00936 } 00937 00938 sched_leave_critical_region(); 00939 return( retval ); 00940 } |
|
Execute a file creating a new task.
This routine can execute only ELF32 files. The file is loaded in a temporary buffer, then the sections are copied into memory and the task structure is initialized. At the end of this the new task is putted into the ready queue. Definition at line 697 of file task.c.
00698 { 00699 uint32_t temp_PDBR; 00700 task_t *task; 00701 byte *pl0_stack; 00702 size_t PDBR, entry; 00703 void *filebuffer; 00704 int filesize = get_file_size(filename); 00705 00706 if ( filesize < 0 ) 00707 return(NULL); 00708 00709 // Load the ELF32 file into the buffer // 00710 filebuffer = kmalloc(filesize); 00711 if ( elf32_load_file(filename, filebuffer)<0 ) 00712 { 00713 kfree(filebuffer); 00714 return(NULL); 00715 } 00716 00717 sched_enter_critical_region(); 00718 00719 // Create the task structure // 00720 task = kmemalign(PAGE_SIZE, sizeof(task_t)); 00721 if ( task == NULL ) 00722 { 00723 sched_leave_critical_region(); 00724 kfree(filebuffer); 00725 return(NULL); 00726 } 00727 memset(task, 0, sizeof(task_t)); 00728 00729 // Create the PL0-stack // 00730 pl0_stack = kmalloc(STACK_SIZE); 00731 if (pl0_stack == NULL) 00732 { 00733 // Out of virtual memory!!! // 00734 // Free the previous allocated space // 00735 kfree((void *)task); 00736 kfree(filebuffer); 00737 00738 sched_leave_critical_region(); 00739 return(NULL); 00740 } 00741 // Null the stack to enforce the page mapping // 00742 memset(pl0_stack, 0, STACK_SIZE); 00743 00744 // Setup the PL0-stack // 00745 task->tss.ss0 = KERNEL_STACK; 00746 task->tss.esp0 = task->pl0_stack = (dword)(pl0_stack+STACK_SIZE-sizeof(uint32_t)); 00747 00748 // Setup the TSS // 00749 task->tss_sel = setup_GDT_entry(sizeof(tss_IO_t), (dword)&(task->tss), TSS_SEG, 0); 00750 00751 // Create the new virtual space // 00752 PDBR = new_vspace(); 00753 if ( PDBR == NULL ) 00754 { 00755 // Out of memory !!! // 00756 00757 // Destroy the TSS // 00758 remove_GDT_entry(task->tss_sel); 00759 // Free the previous allocated space // 00760 kfree((void *)(pl0_stack)); 00761 kfree((void *)task); 00762 kfree(filebuffer); 00763 00764 sched_leave_critical_region(); 00765 return(NULL); 00766 } 00767 00768 // Temporary switch to the new address space // 00769 __asm__ __volatile__ ("movl %%cr3, %0" : "=r"(temp_PDBR) : ); 00770 __asm__ __volatile__ ("movl %0, %%cr3" : : "r"(PDBR)); 00771 00772 // Copy the file sections into memory // 00773 entry = elf32_copy_sections(filebuffer); 00774 if ( entry == NULL ) 00775 { 00776 // Restore the old address space // 00777 __asm__ __volatile__ ("movl %0, %%cr3" : : "r"(temp_PDBR)); 00778 00779 // Free the PDBR frame // 00780 push_frame(PDBR/PAGE_SIZE); 00781 // Destroy the TSS // 00782 remove_GDT_entry(task->tss_sel); 00783 // Free the previous allocated space // 00784 kfree((void *)(pl0_stack)); 00785 kfree((void *)task); 00786 kfree(filebuffer); 00787 00788 sched_leave_critical_region(); 00789 return(NULL); 00790 } 00791 00792 // Create the task stack. 00793 task->tss.ss = (privilege == KERNEL_PRIVILEGE) ? KERNEL_STACK : USER_STACK | 3; 00794 if ( privilege == KERNEL_PRIVILEGE ) 00795 task->tss.esp = (uint32_t)task_setup_stack(argc, argv, task->pl0_stack, STACK_SIZE, privilege); 00796 else 00797 task->tss.esp = (uint32_t)task_setup_stack(argc, argv, TASK_STACK_START, STACK_SIZE, privilege); 00798 00799 // Initialize the user heap. 00800 umalloc_init( TASK_HEAP_START, TASK_HEAP_DEFAULT_SIZE ); 00801 00802 // Restore the old address space // 00803 __asm__ __volatile__ ("movl %0, %%cr3" : : "r"(temp_PDBR)); 00804 00805 // Setup the task PDBR // 00806 task->tss.cr3 = PDBR; 00807 00808 // Setup the IO port mapping // 00809 task->tss.io_map_addr = sizeof(tss_t); 00810 00811 // Setup general registers // 00812 if ( privilege == KERNEL_PRIVILEGE ) 00813 task->tss.ds = task->tss.es = 00814 task->tss.fs = task->tss.gs = KERNEL_DATA; 00815 else 00816 task->tss.ds = task->tss.es = 00817 task->tss.fs = task->tss.gs = USER_DATA | 3; 00818 00819 task->tss.eflags = EFLAGS_IF | 0x02; 00820 if ( privilege == USER_PRIVILEGE ) 00821 // User privilege must be the I/O privilege set to the // 00822 // lower level // 00823 task->tss.eflags |= EFLAGS_IOPL3; 00824 00825 // Initialize general purpose registers // 00826 task->tss.eax = task->tss.ebx = 00827 task->tss.ecx = task->tss.edx = 00828 task->tss.esi = task->tss.edi = 0; 00829 00830 // Initialize LDTR (Local Descriptor Table Register) // 00831 // No LDTs for now... 00832 task->tss.ldtr = 0; 00833 00834 // Initialize debug trap // 00835 // If set to 1 the processor generate a debug exception when a task switch to this task occurs... 00836 task->tss.trace = 0; 00837 00838 // Setup starting address // 00839 task->tss.cs = (privilege == KERNEL_PRIVILEGE) ? KERNEL_CODE : USER_CODE | 3; 00840 task->tss.eip = entry; 00841 00842 // Get a pid // 00843 task->pid = new_pid(); 00844 00845 // Store the name // 00846 // The last character must be ever '\0' (end of string) // 00847 strncpy(task->name, filename, sizeof(task->name)-2); 00848 00849 // Set the type // 00850 task->type = PROCESS_T; 00851 00852 // Set the parent process // 00853 task->father = curr_task; 00854 00855 // Set the console // 00856 task->console = curr_task->console; 00857 00858 // Insert the task into the ready queue // 00859 task->state = READY; 00860 add_queue(&ready_queue, task); 00861 00862 // Well done! // 00863 kfree(filebuffer); 00864 sched_leave_critical_region(); 00865 00866 return( task ); 00867 } |
|
Create a new virtual space.
Definition at line 579 of file task.c.
00580 { 00581 size_t PDBR_frame; 00582 uint32_t *PDBR; 00583 int i; 00584 00585 // Create the virtual space of the task // 00586 PDBR = (uint32_t *)get_temp_page(); 00587 if (PDBR == NULL) 00588 { 00589 // Out of memory!!! // 00590 return( NULL ); 00591 } 00592 PDBR_frame = vir_to_phys( (dword)PDBR ); 00593 00594 // Initialize PDBR // 00595 memset(PDBR, 0, PAGE_SIZE); 00596 for (i=K_VIR_START/(PAGE_SIZE*1024); i<1024; i++) 00597 PDBR[i] = K_PDBR[i]; 00598 // Map page directory into itself // 00599 PDBR[1023] = PDBR_frame | P_PRESENT | P_WRITE; 00600 00601 // Free the page, but doesn't destroy the physical frame // 00602 free_temp_page( PDBR, FALSE ); 00603 00604 return( PDBR_frame ); 00605 } |
|
Sleep a process if it is awake.
Definition at line 1024 of file task.c.
|
|
Initialize the stack for a new process.
Definition at line 620 of file task.c.
00621 { 00622 static uint8_t __i386_quit[] = { 00623 0xb8, 0x00, 0x00, 0x00, 0x00, // mov $0x0, %eax 00624 0x89, 0xe5, // mov %esp, %ebp 00625 0xcd, 0x80, // int $0x80 00626 }; 00627 size_t *stack = (uint32_t *)( (stack_start - sizeof(size_t)) - 00628 ALIGN_UP(sizeof(size_t), sizeof(__i386_quit)) - 00629 sizeof(size_t) ); 00630 size_t *exit_point = stack; 00631 size_t *user_argv; 00632 int i; 00633 00634 // We have not to null the stack to enforce page mapping for a // 00635 // user-mode task, because a stack fault is managed like a // 00636 // normal page fault. // 00637 // But In kernel mode a stack fault can cause a system reboot // 00638 // so we must enforce the page mapping in this case. // 00639 if ( privilege == KERNEL_PRIVILEGE ) 00640 memset((void *)(stack_start-stack_size), 0, stack_size/sizeof(size_t)); 00641 00642 // Copy the exit code into the stack, because if we are in // 00643 // user-mode we cannot access to the kernel space without // 00644 // causing a page level protection fault. // 00645 memcpy((void *)stack, __i386_quit, sizeof(__i386_quit)); 00646 00647 // Copy external parameters strings // 00648 for( i=0; i<argc; i++ ) 00649 { 00650 stack = (size_t *)((size_t)stack - strlen(argv[i]) - 1); 00651 strcpy((char *)stack, argv[i]); 00652 argv[i] = (char *)stack; 00653 } 00654 00655 // Round down the stack pointer to the stack boundaries // 00656 stack = (size_t *)( TRUNC((size_t)stack, sizeof(size_t)) ); 00657 00658 // Copy parameter string pointers // 00659 for( i=0; i<argc; i++ ) 00660 { 00661 *(--stack) = (size_t)(argv[argc-i-1]); 00662 } 00663 00664 // Set the process argv pointer // 00665 user_argv = stack; 00666 *(--stack) = (size_t)user_argv; 00667 // Copy number of parameters value // 00668 *(--stack) = argc; 00669 // Copy the exit point address // 00670 *(--stack) = (size_t)(exit_point); 00671 00672 // Return the initial stack pointer // 00673 return( stack ); 00674 } |
|
Wait for the exit of a child.
Definition at line 966 of file task.c.
00967 { 00968 // Queues where to search the processes // 00969 static queue_t **q[] = { &ready_queue, &wait_queue }; 00970 task_t *p; 00971 int i, j, n; 00972 bool found = FALSE; 00973 dword IF = GET_IF(); 00974 00975 // A task can't wait for yourself! // 00976 if (curr_task->pid == pid) return(0); 00977 00978 repeat: 00979 sched_enter_critical_region(); 00980 // Search into every task queue // 00981 for( i=0; i<_countof(q); i++ ) 00982 { 00983 for( j=0, n = count_queue( q[i] ); j<n; j++ ) 00984 { 00985 p = pick_queue( q[i] ); 00986 if ( (p->father == curr_task) && ((pid==-1) || (p->pid==pid)) ) 00987 { 00988 // Found! // 00989 found = TRUE; 00990 00991 // Update the pid of the child that we // 00992 // are waiting (when pid is -1). // 00993 pid = p->pid; 00994 00995 // Move the current task (father) into // 00996 // the wait queue and wait // 00997 if ( rem_queue(&ready_queue, curr_task) ) 00998 { 00999 add_queue(&wait_queue, curr_task); 01000 curr_task->state = WAIT; 01001 } 01002 sched_leave_critical_region(); 01003 01004 // Sleeped! // 01005 // Now wait for the dispatcher // 01006 enable(); 01007 idle(); 01008 // Task waked-up! Check if the child // 01009 // that we are waiting is dead // 01010 goto repeat; 01011 } 01012 } 01013 01014 } 01015 sched_leave_critical_region(); 01016 SET_IF(IF); 01017 01018 // Return the child pid or -1 if the process has not been found // 01019 return( (found) ? pid : -1 ); 01020 } |
|
Wakeup a process if it is sleeping.
Definition at line 1031 of file task.c.
|