00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 #include "src/common/shared.hpp"
00011 #include "src/collection/avltree.hpp"
00012 #include "src/memory/memset.hpp"
00013 #include "src/memory/align.hpp"
00014 #include "src/memory/heap.hpp"
00015 #include "src/thread/timer.hpp"
00016 #include "src/thread/process.hpp"
00017 #include "src/arch/x86/rtc.hpp"
00018 #include "src/ipc/lock.hpp"
00019 
00020 namespace Thread {
00034    namespace Timer {
00035 
00036 
00037    struct Memory::Heap::heapbox timer_thread_heapbox;
00038 
00039       struct timer_struct {
00040          timer_proc proc;
00041          int arg1, arg2;
00042          uint32 nextExec;     
00043          uint32 interval;     
00044       };
00045 
00049 
00050    #define lnDb3 do {} while(0)
00051 
00052    #define MAX_TIMERS_CNT   1000
00053 
00056    
00057    
00058       int timer_struct_cmp(struct timer_struct *a, struct timer_struct *b) {
00059          if (a->nextExec   >   b->nextExec)
00060             return 1;
00061          if (a->nextExec   <   b->nextExec)
00062             return -1;
00063 
00064          uint32 A= reinterpret_cast<uint32>(a);
00065          uint32 B= reinterpret_cast<uint32>(b);
00066          if (A>B)
00067             return 1;
00068          if (A<B)
00069             return 1;
00070 
00071          
00072          return 0;
00073       }
00074 
00075       using namespace Collection;
00076 
00077       class AvlTree<struct timer_struct*, timer_struct_cmp> *tmrs;
00078       class AvlTree<struct timer_struct*, timer_struct_cmp> *tmrs_pom; 
00079 
00080       volatile uint32 timers_cnt=0;
00081 
00082       class IPC::Lock::lock_t tmrs_lock(const_cast<char*>("timers"));
00083 
00084 
00085       void TimerThread () {
00086          struct Option<struct timer_struct*> item;
00087          struct timer_struct *ts;
00088          while(1) {
00089             uint32 fl;
00090             ENTER_CRITICAL(fl);
00091             lnDb3 ;
00092             tmrs_lock.lock();
00093             lnDb3 ;
00094             for (item= tmrs->findMin();
00095                                        !item.isNone();
00096                                        item=tmrs->findMin()) {
00097                ts= item.get();
00098 
00099                if (ts->nextExec > Arch::x86::RTC::up_time)
00100                   break;
00101                tmrs->remove(ts);
00102                timers_cnt--;
00103                
00104                tmrs_pom->insert(ts);
00109                (*(uint32*)0xb8024)++;
00110             }
00111 
00112             tmrs_lock.ulock();
00113             LEAVE_CRITICAL(fl);
00114             lnDb3 ;
00115 
00116             
00117             for (item= tmrs_pom->findMin();
00118                                           !item.isNone();
00119                                           item= tmrs_pom->findMin()) {
00120                ts= item.get();
00121                tmrs_pom->remove(ts);
00122                
00123                if (ts->proc(ts->arg1,ts->arg2) == 1) { 
00124                   ts->nextExec += ts->interval; 
00125 
00126                   ENTER_CRITICAL(fl);
00127                   lnDb3 ;
00128                   tmrs_lock.lock();
00129                   lnDb3 ;
00130                   tmrs->insert(ts); 
00131                   tmrs_lock.ulock();
00132                   LEAVE_CRITICAL(fl);
00133                   lnDb3 ;
00134                } else {
00135                   
00136                   timer_thread_heapbox.free(ts);
00137                }
00138 
00139             }
00140 
00141 
00142 
00143 
00144 
00145 
00146 
00147 
00148 
00149 
00150 
00151 
00152 
00153             Thread::sleep(1);
00154          }
00155       }
00156 
00161       struct timer_handle add(timer_proc proc, uint32 interval, int arg1, int arg2) {
00162          struct timer_struct *ts;
00163             ts= static_cast<struct timer_struct*>(timer_thread_heapbox.malloc(sizeof(struct timer_struct),1,"timer struct",null));
00164             ts->proc=proc;
00165             ts->arg1=arg1;
00166             ts->arg2=arg2;
00167             ts->interval=interval;
00168             ts->nextExec= Arch::x86::RTC::up_time+ interval;
00169             uint32 fl; ENTER_CRITICAL(fl);
00170             lnDb3 ;
00171             tmrs_lock.lock();
00172             lnDb3 ;
00173             if (timers_cnt > MAX_TIMERS_CNT) {
00174 
00175                sysfail("too many timers");
00176                tmrs_lock.ulock();
00177                LEAVE_CRITICAL(fl);
00178                timer_thread_heapbox.free(ts);
00179                
00180                return timer_handle();
00181             }
00182             tmrs->insert(ts);
00183             timers_cnt ++;
00184             tmrs_lock.ulock();
00185             LEAVE_CRITICAL(fl);
00186             lnDb3 ;
00187             return timer_handle(reinterpret_cast<uint32>(ts));
00188       }
00189 
00190       bool remove(struct timer_handle &hndl) {
00191          uint32 fl;
00192          ENTER_CRITICAL(fl);
00193          lnDb3 ;
00194          tmrs_lock.lock();
00195          lnDb3 ;
00196          bool x= tmrs->remove(reinterpret_cast<struct timer_struct*>(hndl.d));
00197          timers_cnt --;
00198          tmrs_lock.ulock();
00199          LEAVE_CRITICAL(fl);
00200          timer_thread_heapbox.free(reinterpret_cast<struct timer_struct*>(hndl.d));
00201          lnDb3 ;
00202          hndl=0;
00203          return x;
00204       }
00205 
00206       void initTimerThread() {
00207          Memory::Heap::allocate_heapbox(&timer_thread_heapbox, "timer thread");
00208          
00209 
00210 
00211          tmrs = new class Collection::AvlTree<struct timer_struct*, timer_struct_cmp>;
00212          tmrs_pom = new class Collection::AvlTree<struct timer_struct*, timer_struct_cmp>;
00213          Thread::kernel_process.create_thread(true, (uint32)&TimerThread, 2, 2, const_cast<char*>("timers"));
00214       }
00215 
00216 
00217   }
00218 }
00219 
00220