00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "src/common/shared.hpp"
00018 #include "src/common/blist.hpp"
00019 #include "src/common/blistsort.hpp"
00020 #include "src/arch/x86/interr.hpp"
00021 #include "src/arch/x86/except_c.hpp"
00022 #include "src/arch/x86/rtc.hpp"
00023 #include "src/thread/scheduler.hpp"
00024 #include "src/thread/thread.hpp"
00025 #include "src/thread/process.hpp"
00026
00034 namespace Thread {
00035
00036
00037 class IPC::Lock::lock_t lock_queues("queues");
00038 class IPC::Lock::lock_t lock_sleep("sleep");
00039 class Memory::Heap::heapbox heap;
00040 class blist_t threads_queue[THREAD_QUEUES];
00041
00042 class blist_t threads_sleep;
00043 class blist_t threads_dead;
00044
00045
00046 int wake_threads()
00047 { _PF;
00048 blist_s *item, *next;
00049 thread_t *thread;
00050
00051 if (!Thread::Scheduler::multitasking_running)
00052 Preturn(EFAIL);
00053
00054 if (lock_system.locked())
00055 Preturn(EFAIL);
00056 if (lock_queues.locked())
00057 Preturn(EFAIL);
00058 if (lock_sleep.locked())
00059 Preturn(EFAIL);
00060
00061 for (item=threads_sleep.head;item;item=next)
00062 {
00063 next=item->next;
00064 thread=bli_dt(item,thread_t*);
00065
00066 if (thread->awake_time > Arch::x86::RTC::up_time)
00067 break;
00068 awake(thread);
00069 }
00070
00071 Preturn(ESUCCESS);
00072 }
00073
00074
00075 int enqueue_thread(thread_t *thread, blist_t *queue)
00076 {
00077 int i;
00078 lock_queues.lock();
00079 i= (queue->ptr(thread, NULL)==NULL? EFAIL : ESUCCESS);
00080 lock_queues.ulock();
00081 return i;
00082 }
00083
00084
00085 int unqueue_thread(thread_t *thread, blist_t *queue)
00086 { _Pf("T'::unqueue_thread");
00087 blist_s *item;
00088 lock_queues.lock();
00089 for (item=queue->head;item;item=item->next)
00090 {
00091 if (bli_dt(item,thread_t*) != thread)
00092 continue;
00093 queue->del(item);
00094 lock_queues.ulock();
00095 preturn( ESUCCESS );
00096 }
00097
00098 lock_queues.ulock();
00099 preturn( EFAIL );
00100 }
00101
00102
00103 uint32 thread_load(thread_t *thread) { _Pf("Thread::thread_load");
00104 uint32 i;
00105 if (Arch::x86::RTC::up_time - thread->save1_time > 29)
00106 {
00107 thread->save1_time=thread->save2_time;
00108 thread->run1_time=thread->run2_time;
00109 thread->save2_time=Arch::x86::RTC::up_time;
00110 thread->run2_time=thread->running_time;
00111 }
00112
00113 i= 2000 * (thread->running_time) /
00114 ( Arch::x86::RTC::up_time-thread->creation_time);
00115 if (thread->run1_time != 0) {
00116
00117
00118
00119 if (thread->save1_time >= Arch::x86::RTC::up_time)
00120 i+= 8000 * (thread->running_time) /
00121 ( Arch::x86::RTC::up_time-thread->creation_time);
00122 else
00123 i+= 8000 * (thread->running_time-thread->run1_time) /
00124 ( Arch::x86::RTC::up_time-thread->save1_time);
00125 }
00126
00127
00128
00129
00130
00131
00132 thread->load=i;
00133 preturn( thread->load );
00134
00135 }
00136
00137
00138 int sleepcompar(const void *a, const void *b)
00139 { _Pf("T'::sleepcompar");
00140 uint64 A, B;
00141 A= bli_dt(a,thread_t*)->awake_time;
00142 B= bli_dt(b,thread_t*)->awake_time;
00143
00144 if (A > B)
00145 preturn( 1);
00146 if (B > A)
00147 preturn( -1);
00148 preturn( 0);
00149 }
00150
00151
00152 int sleep(thread_t *thread, uint64 time)
00153 { _Pf("Thread::sleep");
00154 int i;
00155
00156
00157 uint32 fl;
00158 asm volatile("pushf\npopl %0\ncli":"=g"(fl));
00159 Scheduler::lock_scheduler.lock();
00160 lock_sleep.lock();
00161 lock_system.lock();
00162 if (time != 0)
00163 thread->awake_time=Arch::x86::RTC::up_time+time;
00164 else
00165 thread->awake_time=0xffffffffffffffffll;
00166
00167
00168 i=unqueue_thread(thread, &threads_queue[thread->priority]);
00169 if (i!= ESUCCESS)
00170 if (current_thread==thread) i=ESUCCESS;
00171
00172 if (i!= ESUCCESS) {
00173 lock_system.ulock();
00174 lock_sleep.ulock();
00175 Scheduler::lock_scheduler.ulock();
00176 asm volatile("pushl %0\npopf"::"g"(fl));
00177 preturn( i ); }
00178
00179
00180 if ((thread->state & TH_DYING) == 0) {
00181 lock_queues.lock();
00182 i= (blistsort_ptr(&threads_sleep, thread, NULL, &sleepcompar)==NULL? EFAIL:ESUCCESS);
00183 lock_queues.ulock(); }
00184
00185
00186
00187 thread->state&=(0xFFFFFFFF- TH_ACTIVE-TH_BUSY);
00188 thread->state|=TH_ASLEEP;
00189
00190
00191
00192
00193 lock_system.ulock();
00194 lock_sleep.ulock();
00195 Scheduler::lock_scheduler.ulock();
00196 asm volatile("pushl %0\npopf"::"g"(fl));
00197
00198
00199 if (thread==current_thread) {
00200 asm volatile ("int $0x20":::"memory");
00201 do {} while (thread->state & TH_ASLEEP);
00202 }
00203
00204 preturn( i );
00205 }
00206
00207
00208 int sleep(uint64 time) {
00209 return sleep((Thread::thread_t*)current_thread, time);
00210 }
00211
00212
00213 int awake(thread_t *thread)
00214 { _Pf("Thread::awake");
00215 int i;
00216 uint32 fl;
00217 asm volatile("pushf\npopl %0\ncli":"=g"(fl));
00218 if (Thread::Scheduler::multitasking_running==false)
00219 { asm volatile ("pushl %0\npopf"::"g"(fl)); preturn( EINVAL ); }
00220
00221 if ((thread->state&TH_ASLEEP)==0)
00222 { asm volatile ("pushl %0\npopf"::"g"(fl)); preturn( EINVAL ); }
00223
00224 Scheduler::lock_scheduler.lock();
00225 lock_sleep.lock();
00226 lock_system.lock();
00227
00228 i=unqueue_thread(thread, &threads_sleep);
00229 if (i!= ESUCCESS) {
00230 lock_system.ulock();
00231 Scheduler::lock_scheduler.ulock();
00232 lock_sleep.ulock();
00233 asm volatile ("pushl %0\npopf"::"g"(fl));
00234 preturn( i ); }
00235
00236 thread->state&=(0xffffffff-TH_ASLEEP);
00237 thread->state|=TH_ACTIVE;
00238
00239
00240 enqueue_thread(thread, &threads_queue[thread->priority]);
00241
00242 lock_system.ulock();
00243 lock_sleep.ulock();
00244 Scheduler::lock_scheduler.ulock();
00245
00246 asm volatile ("pushl %0\npopf"::"g"(fl));
00247 preturn( ESUCCESS );
00248 }
00249
00250
00251 int sem_sleep(thread_t *thread, struct sem_t *sem_id, uint64 sem_dt)
00252 {
00253 thread->sem_id=sem_id;
00254 thread->sem_dt=sem_dt;
00255 return sleep(thread,0);
00256 }
00257
00258
00259 int sem_sleep(struct sem_t *sem_id, uint64 sem_dt) {
00260 return sem_sleep((Thread::thread_t*)current_thread, sem_id, sem_dt);
00261 }
00262
00263
00264 int sem_awake(thread_t *thread)
00265 {
00266 thread->sem_id=NULL;
00267 thread->sem_dt=0;
00268 return awake(thread);
00269 }
00270
00271 thread_t *ThreadGet(int procno, int threadno)
00272 {
00273 process_t *proc;
00274 proc= ProcessGet(procno);
00275 if (proc==NULL) return NULL;
00276
00277 blist_s *item;
00278 for(item=proc->thread_list.head;item&&(bli_dt(item,thread_t*)->no<=threadno);item=item->next)
00279 if (bli_dt(item,thread_t*)->no==threadno)
00280 return bli_dt(item,thread_t*);
00281
00282 return NULL;
00283 }
00284
00285 int ThreadKill(thread_t *thread)
00286 {
00287 uint32 fl;
00288 asm volatile("pushf\npopl %0\ncli":"=g"(fl));
00289
00290 thread->state|=TH_DYING;
00291 threads_dead.ptr(thread, NULL);
00292 asm volatile("pushl %0\npopf"::"g"(fl));
00293
00294 return sleep(thread, 0);
00295 }
00296
00297 int ThreadKill(int procno, int threadno) {
00298 return ThreadKill(ThreadGet(procno, threadno));
00299 }
00300
00301 };
00302
00303
00304
00305
00306
00307