00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <const.h>
00015 #include <stdlib.h>
00016 #include <string.h>
00017
00018 #include <arch/i386.h>
00019 #include <arch/interrupt.h>
00020 #include <arch/mem.h>
00021 #include <arch/paging.h>
00022 #include <arch/v86.h>
00023
00024 #include <kernel/console.h>
00025 #include <kernel/clock.h>
00026 #include <kernel/elf32.h>
00027 #include <kernel/fat.h>
00028 #include <kernel/kmalloc.h>
00029 #include <kernel/queue.h>
00030 #include <kernel/semaphore.h>
00031 #include <kernel/shell.h>
00032 #include <kernel/umalloc.h>
00033
00034 #include <kernel/task.h>
00035
00036 extern size_t K_PDBR[PAGE_SIZE/sizeof(size_t)];
00037
00038
00039
00040
00041
00042
00043
00044
00045 queue_t *ready_queue = NULL;
00046
00047 queue_t *wait_queue = NULL;
00048
00049 queue_t *zombie_queue = NULL;
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062 task_t *curr_task = NULL;
00063
00064 task_t *idle_task = NULL;
00065
00066 task_t *kpagd = NULL;
00067
00068
00069
00070
00071
00072
00073 void do_idle()
00074 {
00075 while(TRUE)
00076 {
00077 enable();
00078 idle();
00079 }
00080 }
00081
00082
00083
00084
00085 void kpager()
00086 {
00087 task_t *t;
00088 dword addr, PDBR;
00089
00090 while( TRUE )
00091 {
00092 sched_enter_critical_region();
00093
00094
00095 t = pick_queue(&zombie_queue);
00096 if ( t==NULL )
00097 {
00098
00099 sched_leave_critical_region();
00100
00101 sleep_task( curr_task );
00102 enable();
00103 idle();
00104 continue;
00105 }
00106
00107
00108 if ( t->type==KTHREAD_T )
00109 {
00110
00111 if( t->pl0_stack!=NULL )
00112 kfree((void *)((dword)(t->pl0_stack)+sizeof(uint32_t)-STACK_SIZE));
00113
00114
00115 remove_GDT_entry(t->tss_sel);
00116
00117
00118 rem_queue(&zombie_queue, t);
00119
00120
00121 kfree((void *)t);
00122 }
00123 else
00124 {
00125 PDBR = t->tss.cr3;
00126
00127
00128 __asm__ __volatile__ ("movl %0, %%cr3" : : "r"(t->tss.cr3));
00129
00130
00131 for(addr=0; addr<K_VIR_START; addr+=PAGE_SIZE)
00132 {
00133 if (*ADDR_TO_PDE(addr) != NULL)
00134 delete_page(addr);
00135 else
00136 addr=PAGE_DIR_ALIGN_UP(addr);
00137 }
00138
00139
00140 __asm__ __volatile__ ("movl %0, %%cr3" : : "r"(curr_task->tss.cr3));
00141
00142
00143 kfree((void *)((dword)(t->pl0_stack)+sizeof(uint32_t)-STACK_SIZE));
00144
00145
00146 remove_GDT_entry(t->tss_sel);
00147
00148
00149 rem_queue(&zombie_queue, t);
00150
00151
00152 kfree((void *)t);
00153
00154
00155 push_frame(PDBR/PAGE_SIZE);
00156 }
00157 sched_leave_critical_region();
00158 }
00159 }
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171 atomic_t last_pid;
00172
00173
00174
00175
00176
00177
00178 pid_t new_pid()
00179 {
00180 atomic_inc(&last_pid);
00181 return(atomic_read(&last_pid));
00182 }
00183
00184
00185
00186 pid_t get_pid()
00187 {
00188 if ( !curr_task ) return( NULL );
00189 return( curr_task->pid );
00190 }
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203 task_t *get_curr_task()
00204 {
00205 return( curr_task );
00206 }
00207
00208
00209
00210 char *get_pname()
00211 {
00212 if ( !curr_task ) return( NULL );
00213 return( curr_task->name );
00214 }
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234 task_t *create_kthread(void *address, char *pname)
00235 {
00236 task_t *new_task;
00237 byte *pl0_stack;
00238
00239 sched_enter_critical_region();
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265 new_task = kmemalign(PAGE_SIZE, sizeof(task_t));
00266 if (new_task == NULL)
00267 {
00268
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
00279 pl0_stack = kmalloc(STACK_SIZE);
00280 if (pl0_stack == NULL)
00281 {
00282
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
00287 kfree((void *)new_task);
00288
00289 sched_leave_critical_region();
00290 return(NULL);
00291 }
00292
00293 memset(pl0_stack, 0, STACK_SIZE);
00294
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
00299 new_task->tss_sel = setup_GDT_entry(sizeof(tss_IO_t), (dword)&(new_task->tss), TSS_SEG, 0);
00300
00301
00302 new_task->tss.cr3 = GET_PDBR();
00303
00304
00305 new_task->tss.io_map_addr = sizeof(tss_t);
00306
00307
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
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
00318
00319 new_task->tss.ldtr = 0;
00320
00321
00322
00323 new_task->tss.trace = 0;
00324
00325
00326 new_task->tss.cs = KERNEL_CODE;
00327 new_task->tss.eip = (dword)address;
00328
00329
00330 new_task->pid = new_pid();
00331
00332
00333
00334 strncpy(new_task->name, pname, sizeof(new_task->name)-2);
00335
00336
00337 new_task->type = KTHREAD_T;
00338
00339
00340 new_task->father = curr_task;
00341
00342
00343 new_task->console = curr_task->console;
00344
00345
00346 new_task->state = READY;
00347 add_queue(&ready_queue, new_task);
00348
00349 sched_leave_critical_region();
00350
00351 return (new_task);
00352 }
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374 task_t *create_process(void *address, void *buffer, size_t size, char *pname, int privilege)
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
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408 new_task = kmemalign(PAGE_SIZE, sizeof(task_t));
00409 if (new_task == NULL)
00410 {
00411
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
00422 pl0_stack = kmalloc(STACK_SIZE);
00423 if (pl0_stack == NULL)
00424 {
00425
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
00430 kfree((void *)new_task);
00431
00432 sched_leave_critical_region();
00433 return(NULL);
00434 }
00435
00436 memset(pl0_stack, 0, STACK_SIZE);
00437
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
00442 new_task->tss_sel = setup_GDT_entry(sizeof(tss_IO_t), (dword)&(new_task->tss), TSS_SEG, 0);
00443
00444
00445 PDBR = (dword *)get_temp_page();
00446 if ( PDBR == NULL )
00447 {
00448
00449 set_color(LIGHT_RED);
00450 kprintf("\n\rOut memory!!! Cannot create task [%s]\n\r", pname);
00451 set_color(DEFAULT_COLOR);
00452
00453 kfree((void *)(pl0_stack));
00454 kfree((void *)new_task);
00455
00456 remove_GDT_entry(new_task->tss_sel);
00457
00458
00459 sched_leave_critical_region();
00460 return(NULL);
00461 }
00462 PDBR_frame = vir_to_phys( (dword)PDBR );
00463
00464
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
00470 PDBR[1023] = PDBR_frame | P_PRESENT | P_WRITE;
00471
00472
00473 free_temp_page(PDBR, FALSE);
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486 __asm__ __volatile__ ("movl %%cr3, %0" : "=r"(cr3) : );
00487 __asm__ __volatile__ ("movl %0, %%cr3" : : "r"(PDBR_frame));
00488
00489
00490
00491
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
00499
00500
00501 if (address != buffer)
00502 {
00503 memcpy(address, buffer, size);
00504 }
00505
00506
00507 __asm__ __volatile__ ("movl %0, %%cr3" : : "r"(cr3));
00508
00509
00510 new_task->tss.cr3 = PDBR_frame;
00511
00512
00513 new_task->tss.io_map_addr = sizeof(tss_t);
00514
00515
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
00526
00527 new_task->tss.eflags |= EFLAGS_IOPL3;
00528
00529
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
00535
00536 new_task->tss.ldtr = 0;
00537
00538
00539
00540
00541 new_task->tss.trace = 0;
00542
00543
00544 new_task->tss.cs = (privilege == KERNEL_PRIVILEGE) ? KERNEL_CODE : USER_CODE | 3;
00545 new_task->tss.eip = (dword)address;
00546
00547
00548 new_task->pid = new_pid();
00549
00550
00551
00552 strncpy(new_task->name, pname, sizeof(new_task->name)-2);
00553
00554
00555 new_task->type = PROCESS_T;
00556
00557
00558 new_task->father = curr_task;
00559
00560
00561 if( curr_task )
00562 new_task->console = curr_task->console;
00563
00564
00565 new_task->state = READY;
00566 add_queue(&ready_queue, new_task);
00567
00568 sched_leave_critical_region();
00569 return (new_task);
00570 }
00571
00572
00573
00574
00575
00576
00577
00578
00579 size_t new_vspace()
00580 {
00581 size_t PDBR_frame;
00582 uint32_t *PDBR;
00583 int i;
00584
00585
00586 PDBR = (uint32_t *)get_temp_page();
00587 if (PDBR == NULL)
00588 {
00589
00590 return( NULL );
00591 }
00592 PDBR_frame = vir_to_phys( (dword)PDBR );
00593
00594
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
00599 PDBR[1023] = PDBR_frame | P_PRESENT | P_WRITE;
00600
00601
00602 free_temp_page( PDBR, FALSE );
00603
00604 return( PDBR_frame );
00605 }
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620 uint32_t *task_setup_stack(int argc, char **argv, addr_t stack_start, size_t stack_size, int privilege)
00621 {
00622 static uint8_t __i386_quit[] = {
00623 0xb8, 0x00, 0x00, 0x00, 0x00,
00624 0x89, 0xe5,
00625 0xcd, 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
00635
00636
00637
00638
00639 if ( privilege == KERNEL_PRIVILEGE )
00640 memset((void *)(stack_start-stack_size), 0, stack_size/sizeof(size_t));
00641
00642
00643
00644
00645 memcpy((void *)stack, __i386_quit, sizeof(__i386_quit));
00646
00647
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
00656 stack = (size_t *)( TRUNC((size_t)stack, sizeof(size_t)) );
00657
00658
00659 for( i=0; i<argc; i++ )
00660 {
00661 *(--stack) = (size_t)(argv[argc-i-1]);
00662 }
00663
00664
00665 user_argv = stack;
00666 *(--stack) = (size_t)user_argv;
00667
00668 *(--stack) = argc;
00669
00670 *(--stack) = (size_t)(exit_point);
00671
00672
00673 return( stack );
00674 }
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697 task_t *new_task(char *filename, int argc, char **argv, int privilege)
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
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
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
00730 pl0_stack = kmalloc(STACK_SIZE);
00731 if (pl0_stack == NULL)
00732 {
00733
00734
00735 kfree((void *)task);
00736 kfree(filebuffer);
00737
00738 sched_leave_critical_region();
00739 return(NULL);
00740 }
00741
00742 memset(pl0_stack, 0, STACK_SIZE);
00743
00744
00745 task->tss.ss0 = KERNEL_STACK;
00746 task->tss.esp0 = task->pl0_stack = (dword)(pl0_stack+STACK_SIZE-sizeof(uint32_t));
00747
00748
00749 task->tss_sel = setup_GDT_entry(sizeof(tss_IO_t), (dword)&(task->tss), TSS_SEG, 0);
00750
00751
00752 PDBR = new_vspace();
00753 if ( PDBR == NULL )
00754 {
00755
00756
00757
00758 remove_GDT_entry(task->tss_sel);
00759
00760 kfree((void *)(pl0_stack));
00761 kfree((void *)task);
00762 kfree(filebuffer);
00763
00764 sched_leave_critical_region();
00765 return(NULL);
00766 }
00767
00768
00769 __asm__ __volatile__ ("movl %%cr3, %0" : "=r"(temp_PDBR) : );
00770 __asm__ __volatile__ ("movl %0, %%cr3" : : "r"(PDBR));
00771
00772
00773 entry = elf32_copy_sections(filebuffer);
00774 if ( entry == NULL )
00775 {
00776
00777 __asm__ __volatile__ ("movl %0, %%cr3" : : "r"(temp_PDBR));
00778
00779
00780 push_frame(PDBR/PAGE_SIZE);
00781
00782 remove_GDT_entry(task->tss_sel);
00783
00784 kfree((void *)(pl0_stack));
00785 kfree((void *)task);
00786 kfree(filebuffer);
00787
00788 sched_leave_critical_region();
00789 return(NULL);
00790 }
00791
00792
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
00800 umalloc_init( TASK_HEAP_START, TASK_HEAP_DEFAULT_SIZE );
00801
00802
00803 __asm__ __volatile__ ("movl %0, %%cr3" : : "r"(temp_PDBR));
00804
00805
00806 task->tss.cr3 = PDBR;
00807
00808
00809 task->tss.io_map_addr = sizeof(tss_t);
00810
00811
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
00822
00823 task->tss.eflags |= EFLAGS_IOPL3;
00824
00825
00826 task->tss.eax = task->tss.ebx =
00827 task->tss.ecx = task->tss.edx =
00828 task->tss.esi = task->tss.edi = 0;
00829
00830
00831
00832 task->tss.ldtr = 0;
00833
00834
00835
00836 task->tss.trace = 0;
00837
00838
00839 task->tss.cs = (privilege == KERNEL_PRIVILEGE) ? KERNEL_CODE : USER_CODE | 3;
00840 task->tss.eip = entry;
00841
00842
00843 task->pid = new_pid();
00844
00845
00846
00847 strncpy(task->name, filename, sizeof(task->name)-2);
00848
00849
00850 task->type = PROCESS_T;
00851
00852
00853 task->father = curr_task;
00854
00855
00856 task->console = curr_task->console;
00857
00858
00859 task->state = READY;
00860 add_queue(&ready_queue, task);
00861
00862
00863 kfree(filebuffer);
00864 sched_leave_critical_region();
00865
00866 return( task );
00867 }
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881 bool kill(pid_t pid)
00882 {
00883
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
00890 if ( p==NULL )
00891 return(FALSE);
00892
00893 sched_enter_critical_region();
00894
00895
00896 for ( i=0; i<_countof(q); i++)
00897 for ( j=0, n=count_queue(q[i]); j<n; j++ )
00898 {
00899
00900 p = pick_queue( q[i] );
00901
00902 if ( p->pid == pid )
00903 {
00904
00905
00906 if ( rem_queue(q[i], p) )
00907 {
00908 add_queue(&zombie_queue, p);
00909 p->state = ZOMBIE;
00910
00911 wakeup_task( kpagd );
00912
00913 if ( p->father != NULL )
00914 wakeup_task( p->father );
00915
00916 retval = TRUE;
00917 }
00918 }
00919 else
00920 {
00921
00922
00923
00924 if ( p->father != NULL )
00925 if ( (p->father)->pid == pid )
00926 p->father = NULL;
00927 }
00928 }
00929
00930
00931 if (curr_task->pid == pid)
00932 {
00933 sched_leave_critical_region();
00934
00935 do_idle();
00936 }
00937
00938 sched_leave_critical_region();
00939 return( retval );
00940 }
00941
00942
00943
00944
00945
00946
00947
00948
00949 void auto_kill(int n)
00950 {
00951 kill( curr_task->pid );
00952 }
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966 pid_t waitpid(pid_t pid, int *status, int options)
00967 {
00968
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
00976 if (curr_task->pid == pid) return(0);
00977
00978 repeat:
00979 sched_enter_critical_region();
00980
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
00989 found = TRUE;
00990
00991
00992
00993 pid = p->pid;
00994
00995
00996
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
01005
01006 enable();
01007 idle();
01008
01009
01010 goto repeat;
01011 }
01012 }
01013
01014 }
01015 sched_leave_critical_region();
01016 SET_IF(IF);
01017
01018
01019 return( (found) ? pid : -1 );
01020 }
01021
01022
01023
01024 void sleep_task(task_t *p)
01025 {
01026 p->state = WAIT;
01027 }
01028
01029
01030
01031 void wakeup_task(task_t *p)
01032 {
01033 p->state = READY;
01034 }
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047 semaphore_t sched_enabled;
01048
01049
01050
01051
01052
01053
01054
01055 void sched_enter_critical_region()
01056 {
01057 DOWN( &sched_enabled );
01058 }
01059
01060
01061 void sched_leave_critical_region()
01062 {
01063 UP( &sched_enabled );
01064 }
01065
01066
01067
01068
01069
01070 bool is_sched_enabled()
01071 {
01072 if( atomic_read(&sched_enabled) )
01073 return( TRUE );
01074 else
01075 return( FALSE );
01076 }
01077
01078
01079
01080
01081
01082
01083 static __inline__ void scheduler()
01084 {
01085 task_t *p=NULL;
01086 int count;
01087
01088
01089 count = count_queue( &ready_queue );
01090 for ( ; count; --count )
01091 {
01092 p = pick_queue( &ready_queue );
01093 if ( p->state==WAIT )
01094 {
01095 rem_queue( &ready_queue, p );
01096 add_queue( &wait_queue, p );
01097 }
01098 }
01099
01100
01101 count = count_queue( &wait_queue );
01102 for ( ; count; --count )
01103 {
01104 p = pick_queue( &wait_queue );
01105 if ( p->state==READY )
01106 {
01107 rem_queue( &wait_queue, p );
01108 add_queue( &ready_queue, p );
01109 }
01110 }
01111
01112
01113 curr_task = pick_queue( &ready_queue );
01114 if (curr_task == NULL) curr_task=idle_task;
01115 }
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131 void dispatcher()
01132 {
01133 task_t *prev_task;
01134
01135
01136 clock_thread();
01137
01138
01139 if ( atomic_read(&sched_enabled) )
01140 {
01141
01142 prev_task = curr_task;
01143
01144 scheduler();
01145
01146 if ( prev_task != curr_task )
01147 {
01148 if ( prev_task->tss.cr3 != curr_task->tss.cr3 )
01149 {
01150
01151
01152
01153 __asm__ __volatile__ (
01154 "movl %%eax, %%cr3\n"
01155 "cld\n"
01156 "rep movsl\n"
01157 "movl %%ebx, %%cr3" : :
01158 "a"(curr_task->tss.cr3),
01159 "b"(prev_task->tss.cr3),
01160 "D"((dword *)PAGE_DIR_MAP+(K_VIR_START/(PAGE_SIZE*1024))),
01161 "S"((dword *)K_PDBR+(K_VIR_START/(PAGE_SIZE*1024))),
01162 "c"((PAGE_DIR_MAP/(PAGE_SIZE*1024)) - (K_VIR_START/(PAGE_SIZE*1024)))
01163 );
01164 __asm__("" : : : "%eax", "%ebx", "%ecx", "%edi", "%esi");
01165 }
01166
01167
01168 outportb(PORT_8259_M, EOI);
01169
01170 jmp_to_tss(curr_task->tss_sel);
01171 }
01172 }
01173 }
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185 void init_multitasking()
01186 {
01187
01188 atomic_set(&last_pid, 0);
01189
01190
01191 INIT_MUTEX( &sched_enabled );
01192
01193
01194 curr_task = create_process(NULL, NULL, 0, "init", KERNEL_PRIVILEGE);
01195
01196 curr_task->console=1;
01197
01198 curr_task->type = KTHREAD_T;
01199
01200
01201 __asm__ __volatile__ ("ltr %%ax" : : "a" (curr_task->tss_sel));
01202 __asm__ __volatile__ ("" : : : "ax");
01203
01204
01205 __asm__ __volatile__ ("movl %0, %%cr3" : : "r"(curr_task->tss.cr3));
01206
01207
01208
01209
01210 idle_task = create_kthread(&do_idle, "idle");
01211 idle_task->console=0;
01212 rem_queue(&ready_queue, idle_task);
01213
01214
01215 kpagd = create_kthread(&kpager, "kpagerd");
01216 kpagd->console = 0;
01217
01218
01219 install_irq_handler( TIMER_IRQ, (void *)&dispatcher );
01220 }
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234 void ps()
01235 {
01236 task_t *p;
01237 int count, i;
01238
01239 if ((p = curr_task)==NULL) return;
01240
01241
01242 kprintf("\n\rPID STATE CONSOLE CMD");
01243
01244 sched_enter_critical_region();
01245
01246
01247 for(i=0, count=count_queue(&ready_queue); i<count; i++)
01248 {
01249
01250 p = pick_queue(&ready_queue);
01251
01252
01253 kprintf("\n\r%u", p->pid);
01254 gotoxy(12, -1);
01255 kputchar('R');
01256 gotoxy(22, -1);
01257 if (p->console)
01258 kprintf("tty%u", p->console);
01259 else
01260 kputchar('?');
01261 gotoxy(34, -1);
01262 kprintf("%s", p->name);
01263 }
01264
01265
01266 for(i=0, count=count_queue(&wait_queue); i<count; i++)
01267 {
01268
01269 p = pick_queue(&wait_queue);
01270
01271
01272 kprintf("\n\r%u", p->pid);
01273 gotoxy(12, -1);
01274 kputchar('W');
01275 gotoxy(22, -1);
01276 if (p->console)
01277 kprintf("tty%u", p->console);
01278 else
01279 kputchar('?');
01280 gotoxy(34, -1);
01281 kprintf("%s", p->name);
01282 }
01283
01284
01285 for(i=0, count=count_queue(&zombie_queue); i<count; i++)
01286 {
01287
01288 p = pick_queue(&zombie_queue);
01289
01290
01291 kprintf("\n\r%u", p->pid);
01292 gotoxy(12, -1);
01293 kputchar('Z');
01294 gotoxy(22, -1);
01295 if (p->console)
01296 kprintf("tty%u", p->console);
01297 else
01298 kputchar('?');
01299 gotoxy(34, -1);
01300 kprintf("%s", p->name);
01301 }
01302
01303 sched_leave_critical_region();
01304
01305 kprintf("\n\r");
01306 }
01307