X-Git-Url: https://oss.titaniummirror.com/gitweb/?p=tinyos-2.x.git;a=blobdiff_plain;f=tos%2Flib%2Ftosthreads%2Fsystem%2FTinyThreadSchedulerP.nc;h=8466a9821513ef86e4987f450682b956b9b1322d;hp=1ae67708558488bad103d2c6760a5a5d2dd75864;hb=e9bfab607e051bae6afb47b44892ce37541d1b44;hpb=adf1de6c009d13b7b52e68535c63b28f59c97400 diff --git a/tos/lib/tosthreads/system/TinyThreadSchedulerP.nc b/tos/lib/tosthreads/system/TinyThreadSchedulerP.nc index 1ae67708..8466a982 100644 --- a/tos/lib/tosthreads/system/TinyThreadSchedulerP.nc +++ b/tos/lib/tosthreads/system/TinyThreadSchedulerP.nc @@ -32,7 +32,7 @@ /** * @author Kevin Klues */ - + module TinyThreadSchedulerP { provides { interface ThreadScheduler; @@ -43,6 +43,7 @@ module TinyThreadSchedulerP { interface Boot as ThreadSchedulerBoot; interface ThreadInfo[uint8_t id]; interface ThreadQueue; + interface BitArrayUtils; interface McuSleep; interface Leds; interface Timer as PreemptionAlarm; @@ -56,10 +57,19 @@ implementation { //Pointer to yielding thread thread_t* yielding_thread; //Number of threads started, and currently capable of running if given the chance - uint8_t num_started_threads; + uint8_t num_runnable_threads; //Thread queue for keeping track of threads waiting to run thread_queue_t ready_queue; + void task alarmTask() { + uint8_t temp; + atomic temp = num_runnable_threads; + if(temp <= 1) + call PreemptionAlarm.stop(); + else if(temp > 1) + call PreemptionAlarm.startOneShot(TOSTHREAD_PREEMPTION_PERIOD); + } + /* switch_threads() * This routine swaps the stack and allows a thread to run. * Needs to be in a separate function like this so that the @@ -88,7 +98,7 @@ implementation { while(TRUE) { bool mt; atomic mt = (call ThreadQueue.isEmpty(&ready_queue) == TRUE); - if(!mt) break; + if(!mt || tos_thread->state == TOSTHREAD_STATE_READY) break; call McuSleep.sleep(); } } @@ -100,7 +110,7 @@ implementation { */ void scheduleNextThread() { if(tos_thread->state == TOSTHREAD_STATE_READY) - current_thread = call ThreadQueue.remove(&ready_queue, tos_thread); + current_thread = tos_thread; else current_thread = call ThreadQueue.dequeue(&ready_queue); @@ -128,22 +138,48 @@ implementation { void suspend(thread_t* thread) { //if there are no active threads, put the MCU to sleep //Then wakeup the TinyOS thread whenever the MCU wakes up again + #ifdef TOSTHREADS_TIMER_OPTIMIZATION + num_runnable_threads--; + post alarmTask(); + #endif sleepWhileIdle(); interrupt(thread); } + void wakeupJoined(thread_t* t) { + int i,j,k; + k = 0; + for(i=0; ijoinedOnMe); i++) { + if(t->joinedOnMe[i] == 0) { + k+=8; + continue; + } + for(j=0; j<8; j++) { + if(t->joinedOnMe[i] & 0x1) + call ThreadScheduler.wakeupThread(k); + t->joinedOnMe[i] >>= 1; + k++; + } + } + } + /* stop * This routine stops a thread by putting it into the inactive state * and decrementing any necessary variables used to keep track of * threads by the thread scheduler. */ - void stop(thread_t* t) { - t->state = TOSTHREAD_STATE_INACTIVE; - num_started_threads--; - if(num_started_threads == 1) - call PreemptionAlarm.stop(); - signal ThreadCleanup.cleanup[t->id](); - } + void stop(thread_t* t) { + t->state = TOSTHREAD_STATE_INACTIVE; + num_runnable_threads--; + wakeupJoined(t); + #ifdef TOSTHREADS_TIMER_OPTIMIZATION + post alarmTask(); + #else + if(num_runnable_threads == 1) + call PreemptionAlarm.stop(); + #endif + signal ThreadCleanup.cleanup[t->id](); + } /* This executes and cleans up a thread */ @@ -163,7 +199,7 @@ implementation { } event void ThreadSchedulerBoot.booted() { - num_started_threads = 0; + num_runnable_threads = 0; tos_thread = call ThreadInfo.get[TOSTHREAD_TOS_THREAD_ID](); tos_thread->id = TOSTHREAD_TOS_THREAD_ID; call ThreadQueue.init(&ready_queue); @@ -178,6 +214,7 @@ implementation { thread_t* t = (call ThreadInfo.get[id]()); t->state = TOSTHREAD_STATE_INACTIVE; t->init_block = current_thread->init_block; + call BitArrayUtils.clrArray(t->joinedOnMe, sizeof(t->joinedOnMe)); PREPARE_THREAD(t, threadWrapper); return SUCCESS; } @@ -186,9 +223,13 @@ implementation { atomic { thread_t* t = (call ThreadInfo.get[id]()); if(t->state == TOSTHREAD_STATE_INACTIVE) { - num_started_threads++; - if(num_started_threads == 2) - call PreemptionAlarm.startOneShot(TOSTHREAD_PREEMPTION_PERIOD); + num_runnable_threads++; + #ifdef TOSTHREADS_TIMER_OPTIMIZATION + post alarmTask(); + #else + if(num_runnable_threads == 2) + call PreemptionAlarm.startOneShot(TOSTHREAD_PREEMPTION_PERIOD); + #endif t->state = TOSTHREAD_STATE_READY; call ThreadQueue.enqueue(&ready_queue, t); return SUCCESS; @@ -224,7 +265,8 @@ implementation { atomic { if(current_thread->state == TOSTHREAD_STATE_ACTIVE) { current_thread->state = TOSTHREAD_STATE_READY; - call ThreadQueue.enqueue(&ready_queue, current_thread); + if(current_thread != tos_thread) + call ThreadQueue.enqueue(&ready_queue, current_thread); interrupt(current_thread); return SUCCESS; } @@ -232,11 +274,31 @@ implementation { } } + async command error_t ThreadScheduler.joinThread(thread_id_t id) { + thread_t* t = call ThreadInfo.get[id](); + atomic { + if(current_thread == tos_thread) + return FAIL; + if (t->state != TOSTHREAD_STATE_INACTIVE) { + call BitArrayUtils.setBit(t->joinedOnMe, current_thread->id); + call ThreadScheduler.suspendCurrentThread(); + return SUCCESS; + } + } + return EALREADY; + } + async command error_t ThreadScheduler.wakeupThread(uint8_t id) { thread_t* t = call ThreadInfo.get[id](); if((t->state) == TOSTHREAD_STATE_SUSPENDED) { t->state = TOSTHREAD_STATE_READY; - call ThreadQueue.enqueue(&ready_queue, call ThreadInfo.get[id]()); + if(t != tos_thread) { + call ThreadQueue.enqueue(&ready_queue, call ThreadInfo.get[id]()); + #ifdef TOSTHREADS_TIMER_OPTIMIZATION + atomic num_runnable_threads++; + post alarmTask(); + #endif + } return SUCCESS; } return FAIL; @@ -267,4 +329,3 @@ implementation { return NULL; } } -