X-Git-Url: https://oss.titaniummirror.com/gitweb/?a=blobdiff_plain;f=tos%2Flib%2Ftosthreads%2Fsystem%2FTinyThreadSchedulerP.nc;h=097a7a9a9c550dd9676f0cae85b4c2fc6a85ec73;hb=e42551d53cc9fbff637eaffd64edb7db5572d678;hp=1ae67708558488bad103d2c6760a5a5d2dd75864;hpb=9720fb8250cecf3f696a9c844c1d37b594ce050a;p=tinyos-2.x.git diff --git a/tos/lib/tosthreads/system/TinyThreadSchedulerP.nc b/tos/lib/tosthreads/system/TinyThreadSchedulerP.nc index 1ae67708..097a7a9a 100644 --- a/tos/lib/tosthreads/system/TinyThreadSchedulerP.nc +++ b/tos/lib/tosthreads/system/TinyThreadSchedulerP.nc @@ -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 @@ -128,22 +138,44 @@ 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++) { + 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 +195,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 +210,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 +219,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; @@ -232,11 +269,29 @@ 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]()); + #ifdef TOSTHREADS_TIMER_OPTIMIZATION + atomic num_runnable_threads++; + post alarmTask(); + #endif return SUCCESS; } return FAIL; @@ -267,4 +322,3 @@ implementation { return NULL; } } -