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.
|
1.2.18