00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "src/common/shared.hpp"
00019 #include "src/common/blist.hpp"
00020 #include "src/common/blistsort.hpp"
00021 #include "src/common/string.hpp"
00022 #include "src/mboot.hpp"
00023 #include "src/module/elf.hpp"
00024 #include "src/module/mangle.hpp"
00025 #include "src/module/coresyms.hpp"
00026 #include "src/memory/memset.hpp"
00027 #include "src/memory/mmap.hpp"
00028 #include "src/memory/alloc4k.hpp"
00029 #include "src/memory/shmem.hpp"
00030 #include "src/ipc/msg.hpp"
00031 #include "src/ipc/sem.hpp"
00032 #include "src/arch/x86/gdt.hpp"
00033 #include "src/arch/x86/context.hpp"
00034 #include "src/arch/x86/interr.hpp"
00035 #include "src/arch/x86/except_c.hpp"
00036 #include "src/arch/x86/irq.hpp"
00037 #include "src/arch/x86/rtc.hpp"
00038 #include "src/thread/process.hpp"
00039 #include "src/thread/scheduler.hpp"
00040
00041 volatile struct Thread::thread_t *current_thread;
00042
00043 namespace Thread {
00044
00045
00046 struct thread_t *MemsetThreadHandle=NULL,*IdleThreadHandle=NULL;
00047
00048
00049 void count_prior(thread_t *thread, uint32 i, bool move)
00050 {
00051 uint32 new_prior;
00052
00053 new_prior=MIN(thread->worst_priority,
00054 ( (THREAD_QUEUES) * thread_load(thread) / 10000 ));
00055 new_prior=MAX(thread->best_priority, new_prior);
00056
00057 if (thread->priority > new_prior)
00058 thread->prior_diff--;
00059 if (thread->priority < new_prior)
00060 thread->prior_diff++;
00061
00062 if (ABS(thread->prior_diff)>=PRIOR_THREAD_DELTA)
00063 {
00064
00065 if (thread->prior_diff < 0)
00066 new_prior=MAX(thread->priority-1, 2);
00067 if (thread->prior_diff > 0)
00068 new_prior=MIN(THREAD_QUEUES-1, thread->priority+1);
00069
00070 thread->prior_diff=0;
00071 thread->priority=new_prior;
00072
00073 if (move)
00074 {
00075 lock_system.lock();
00076 lock_queues.ulock();
00077 unqueue_thread(thread, &threads_queue[i]);
00078 enqueue_thread(thread, &threads_queue[new_prior]);
00079 lock_queues.lock();
00080 lock_system.ulock();
00081 }
00082 }
00083 }
00084
00085
00086 void prior_thread()
00087 {
00088 uint32 i,n;
00089
00090 for (i=0; i<CRT_STACK_SIZE; i+= PAGE_SIZE)
00091 {
00092 n= Memory::Pager::kmem.pte_val(0xfffff000&(i+(uint32)&CRT_STACK));
00093 if (n & PTE_PRESENT)
00094 disalloc4k ( n&0xfffff000 );
00095 }
00096
00097 blist_s *item,*next;
00098
00099 while (true)
00100 {
00101 Thread::sleep(PRIOR_THREAD_SLEEP);
00102 lock_queues.lock();
00103
00104 for (i=0;i<THREAD_QUEUES;i++)
00105 for (item=threads_queue[i].head;item;item=next)
00106 { next=item->next;
00107 count_prior(bli_dt(item,thread_t*), i, true);
00108 }
00109
00110 for (item=threads_sleep.head;item;item=next)
00111 { next=item->next;
00112 count_prior(bli_dt(item,thread_t*), 0, false);
00113 }
00114 lock_queues.ulock();
00115 }
00116 }
00117
00118
00119 int ThreadFinishOff(thread_t *thread)
00120 {
00121
00122
00123 blist_s *item,*next;
00124 process_t *proc= thread->proc;
00125 mmap_s *node;
00126 thread->state|=TH_BLOCKED;
00127
00128 if (thread->env.cd!= NULL)
00129 {
00130 Arch::x86::Interr::stackVac--;
00131 Arch::x86::Interr::stackPtr[Arch::x86::Interr::stackVac]=thread->env.cd->stack;
00132 }
00133
00134
00135 thread->inbox.done();
00136
00137 thread->env.cd= NULL;
00138
00139 for (item=proc->mem->memory_map.map.head;item;item=next)
00140 {
00141 next= item->next;
00142 node= bli_dt(item,struct mmap_s*);
00143 if (node->thread==thread->no)
00144 {
00145 if (node->destroy)
00146 node->destroy(&proc->mem->memory_map,node);
00147 proc->mem->memory_map.mdel(item);
00148 }
00149 }
00150
00151 threads_dead.del(threads_dead.find(thread));
00152 proc->thread_list.del(proc->thread_list.find(thread));
00153
00154 return ESUCCESS;
00155 }
00156
00157
00158 int ProcFinishOff(process_t *proc)
00159 {
00160
00161
00162
00163 lock_queues.lock();
00164 bool b= (proc->thread_list.head!=NULL);
00165 lock_queues.ulock();
00166 if (b)
00167 return EINVAL;
00168
00169 proc->env.api=0;
00170
00171 proc->heap.destruct();
00172
00173 proc->mem->memory_map.done();
00174
00175 proc->mem->done();
00176
00177 Processes.del(Processes.find(proc));
00178
00179 return ESUCCESS;
00180 }
00181
00182
00184 void ZombieSlayerThread()
00185 {
00186 blist_s *item,*next;
00187 thread_t *thread;
00188 process_t *proc;
00189
00190 while(true) {
00191 (*(uint64*)(0xb8030))++;
00192
00193 #if DISABLE_FAST_MOVING_CHARS
00194 Thread::sleep(1);
00195 #endif
00196
00197
00198
00199
00200 item=threads_dead.head;
00201
00202 for ( ; item; item=next)
00203 {
00204 next= item->next;
00205
00206 thread= bli_dt(item,thread_t*);
00207 proc= thread->proc;
00208
00209 ThreadFinishOff(thread);
00210 if (proc->thread_list.head==NULL)
00211 ProcFinishOff(proc);
00212 }
00213 }
00214 }
00215
00216
00218 void MemsetThread()
00219 {
00220 uint32 addr;
00221 int i;
00222 while(true) {
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232 sleep(1);
00233
00234
00235
00236
00237
00238
00239 while (Memory::Physical::zero_pages_high.length() < Memory::Physical::PAGESCLEANMAX)
00240 {
00241 addr= Memory::Physical::alloc4kDirty_high(1);
00242 if (addr==NULL)
00243 break;
00244 i= Memory::Physical::zero_pages_high.free(addr);
00245 if (i!=ESUCCESS) say(const_cast<char*>("high- %x"), addr);
00246 }
00247 while (Memory::Physical::zero_pages_low.length() < Memory::Physical::PAGESCLEANMAX)
00248 {
00249 addr= Memory::Physical::alloc4kDirty_low(1);
00250 if (addr==NULL)
00251 break;
00252 i= Memory::Physical::zero_pages_low.free(addr);
00253 if (i!=ESUCCESS) say(const_cast<char*>("low- %x"), addr);
00254 }
00255 }
00256 }
00257
00258
00259 void IdleThread()
00260 {
00261 while (true)
00262 {
00263 asm volatile("sti\nhlt");
00264 }
00265 }
00266
00267 thread_t volatile *t1=NULL,*t2=NULL;
00268
00269 int volatile i=0;
00270 void ABCThread()
00271 {
00272 while(1) Thread::sleep(1);
00273
00274 switch (current_thread->proc->no)
00275 {
00276 case 1:
00277 i=1;
00278
00279 i=2;
00280
00281
00282
00283
00284
00285
00286
00287
00288 break;
00289 case 2:
00290 while (i!=2) ;
00291
00292
00293
00294
00295
00296
00297
00298 i=3;
00299 break;
00300 case 3:
00301 while (i!=3) ;
00302
00303
00304
00305
00306 i=4;
00307 break;
00308 }
00309 for(;;);
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357 }
00358
00359 void MatkaTeresaThread()
00360 {
00361 while(1) Thread::sleep(1);
00362 t2=current_thread;
00363 while (t1==NULL);
00364
00365
00366 while(1)
00367 {
00368
00369
00370 sleep(1);
00371
00372
00373 }
00374 }
00375
00376 void BaonKilinski()
00377 {
00378 while(1) Thread::sleep(1);
00379
00380 while (t1==NULL);
00381 while (t2==NULL);
00382 while (1)
00383 {
00384 (*(char*)(0xb8004))++;
00385 if (t1->state&TH_ASLEEP)
00386 (*(char*)(0xb8000))='-'; else
00387 (*(char*)(0xb8000))='x';
00388
00389
00390 if (t2->state&TH_ASLEEP)
00391
00392
00393 (*(char*)(0xb8002))='-'; else
00394 (*(char*)(0xb8002))='x';
00395
00396
00397
00398 }
00399 }
00400 class process_t proc2, proc3;
00401 class Memory::Pager::memtree m2,m3;
00402
00403 void init()
00404 {
00405 uint32 i;
00406
00407 Processes.init("proclist", &Memory::Heap::heap0);
00408
00409 for (i=0;i<Thread::THREAD_QUEUES;i++)
00410 Thread::threads_queue[i].init(FAC_THREAD|FAC_THRLIST, &Thread::heap);
00411 Thread::threads_sleep.init(FAC_THREAD|FAC_THRSLEEP, &Thread::heap);
00412 Thread::threads_dead.init("threads dead blist", &Thread::heap);
00413 Thread::lock_queues.ulock();
00414 Thread::Scheduler::lock_scheduler.ulock();
00415
00416 if (allocate_heapbox(&Thread::heap, const_cast<char*>("scheduler")) != ESUCCESS)
00417 sysfail("heapbox not allocated");
00418
00419 allocate_memtree(&m2,true,&Memory::Heap::heap0);
00420 allocate_memtree(&m3,true,&Memory::Heap::heap0);
00421 kernel_process.init(const_cast<char*>("proc_kern0"), &Memory::Pager::kmem);
00422 Thread::ProcessRegister(&kernel_process);
00423 proc2.init(const_cast<char*>("proc2"), &m2);
00424 Thread::ProcessRegister(&proc2);
00425 proc3.init(const_cast<char*>("proc3"), &m3);
00426 Thread::ProcessRegister(&proc3);
00427
00428
00429
00430 kernel_process.create_thread(true, (uint32)&prior_thread, 0, 0, const_cast<char*>("thread_prior"));
00431 kernel_process.create_thread(true, (uint32)&ABCThread,20,0,const_cast<char*>("YO1"));
00432
00433 proc2.create_thread(true, (uint32)&ABCThread,20,0,const_cast<char*>("YO2"));
00434 proc3.create_thread(true, (uint32)&ABCThread,20,0,const_cast<char*>("YO3"));
00435
00436
00437 kernel_process.create_thread(true, (uint32)&ZombieSlayerThread, 15, 3, const_cast<char*>("zombie slayer"));
00438 IdleThreadHandle=kernel_process.create_thread(true, (uint32)&IdleThread, THREAD_QUEUES-1, THREAD_QUEUES-1, const_cast<char*>("idle"));
00439 MemsetThreadHandle= kernel_process.create_thread(true, (uint32)&MemsetThread, 15, 3, const_cast<char*>("memset"));
00440
00441
00442
00443 IdleThreadHandle->state|=TH_IDLE;
00444 current_thread=MemsetThreadHandle;
00445 current_thread->work_time=Arch::x86::RTC::up_time;
00446 }
00447
00448
00449 namespace Scheduler {
00450
00451
00452 bool volatile multitasking_running=false;
00453 class IPC::Lock::lock_t lock_scheduler("scheduler");
00454
00455
00456 int choose_high()
00457 {
00458 uint32 i;
00459 thread_t *dt;
00460 for (i=0;i<THREAD_QUEUES;i++)
00461 {
00462 if (threads_queue[i].head == NULL)
00463 continue;
00464 dt=bli_dt(threads_queue[i].head,thread_t*);
00465
00466
00467 unqueue_thread(dt, &threads_queue[i]);
00468
00469 current_thread=dt;
00470
00471 return ESUCCESS;
00472 }
00473
00474 return EFAIL;
00475 }
00476
00484 volatile uint32 time_slices=0;
00485
00486
00488 int choose_next_thread()
00489 {
00490 multitasking_running=true;
00491
00492 if (lock_system.locked())
00493 return EFAIL;
00494 if (lock_scheduler.locked())
00495 return EFAIL;
00496 if (lock_queues.locked())
00497 return EFAIL;
00498
00499 time_slices ++ ;
00500
00501 current_thread->state &= (0xFFFFFFFF-TH_BUSY);
00502 current_thread->running_time+=Arch::x86::RTC::up_time - current_thread->work_time;
00503 if (current_thread->state & TH_ACTIVE)
00504 if ((current_thread->state & TH_IDLE)==0)
00505 enqueue_thread((Thread::thread_t*)current_thread, &threads_queue[current_thread->priority]);
00506
00507
00508 if (choose_high() != ESUCCESS)
00509 {
00510 unqueue_thread(IdleThreadHandle,&threads_queue[IdleThreadHandle->priority]);
00511 current_thread=IdleThreadHandle; }
00512
00513 asm volatile("mov %%eax, %%cr3"::"a"( current_thread->proc->mem->cr3 ));
00514
00515 current_thread->state|=TH_BUSY;
00516 current_thread->work_time=Arch::x86::RTC::up_time;
00517
00518 return ESUCCESS;
00519 }
00520
00521
00522
00523 };
00524
00525
00526 };
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558