diff --git a/miosix/doc/textdoc/Changelog.txt b/miosix/doc/textdoc/Changelog.txt index 0677ae2a088ad576cf3689adf3b53f75fec5cf0f..91f9438331ee23fb5468e74f6f27e51d7b32ac67 100644 --- a/miosix/doc/textdoc/Changelog.txt +++ b/miosix/doc/textdoc/Changelog.txt @@ -1,5 +1,9 @@ Changelog for Miosix np embedded OS +v1.58 +- Bumped to version 1.58 because from now on the new compiler gcc-4.5.2, and + especially the new newlib patches become necessary + v1.57 - Added memory barriers to miosix_private::doDisableInterrupts() and doEnableInterrupts(), and made fastDisableInterrupts() and diff --git a/miosix/kernel/sync.cpp b/miosix/kernel/sync.cpp index 927e52d2f032fb0e40ec10c3bfb5065faca84b22..831e78e8af634068be53ebbcb6c3bec1467c3458 100644 --- a/miosix/kernel/sync.cpp +++ b/miosix/kernel/sync.cpp @@ -38,21 +38,13 @@ namespace miosix { // FIXME : begin -void fixmeInit(MutexImpl *mutex, bool recursive) +/** + * Implementation code to lock a mutex. Must be called with interrupts disabled + * \param mutex mutexto be locked + * \param d The instance of FastInterruptDisableLock used to disable interrupts + */ +static inline void IRQdoMutexLock(MutexImpl *mutex, FastInterruptDisableLock& d) { - mutex->owner=0; - mutex->head=0; - mutex->recursive= recursive ? 0 : -1; -} - -void fixmeDestroy(MutexImpl *mutex) -{ - //Do nothing -} - -void fixmeLock(MutexImpl *mutex) -{ - FastInterruptDisableLock dLock; void *p=reinterpret_cast<void*>(Thread::IRQgetCurrentThread()); if(mutex->owner==0) { @@ -72,15 +64,17 @@ void fixmeLock(MutexImpl *mutex) } else errorHandler(MUTEX_DEADLOCK); //Bad, deadlock } - MutexWaitingList waiting; //Element of a linked list on stack + WaitingList waiting; //Element of a linked list on stack waiting.thread=p; waiting.next=0; //Putting this thread last on the list (lifo policy) - if(mutex->head!=0) + if(mutex->first==0) { - MutexWaitingList *walk; - for(walk=mutex->head;walk->next!=0;walk=walk->next); - walk->next=&waiting; - } else mutex->head=&waiting; + mutex->first=&waiting; + mutex->last=&waiting; + } else { + mutex->last->next=&waiting; + mutex->last=&waiting; + } //The while is necessary because some other thread might call wakeup() //on this thread. So the thread can wakeup also for other reasons not @@ -89,13 +83,69 @@ void fixmeLock(MutexImpl *mutex) { Thread::IRQwait();//Returns immediately { - FastInterruptEnableLock eLock(dLock); + FastInterruptEnableLock eLock(d); Thread::yield(); //Now the IRQwait becomes effective } } } -bool fixmeTryLock(MutexImpl *mutex) +/** + * Implementation code to unlock a mutex. + * Must be called with interrupts disabled + * \param mutex mutex to unlock + * \return true if a higher priority thread was woken, + * only if EDF scheduler is selected, otherwise it always returns false + */ +static inline bool IRQdoMutexUnlock(MutexImpl *mutex) +{ +// Safety check removed for speed reasons +// if(mutex->owner!=reinterpret_cast<void*>(Thread::IRQgetCurrentThread())) +// { +// errorHandler(MUTEX_UNLOCK_NOT_OWNER); +// return false; +// } + if(mutex->recursive>0) + { + mutex->recursive--; + return false; + } + if(mutex->first!=0) + { + Thread *t=reinterpret_cast<Thread*>(mutex->first->thread); + t->IRQwakeup(); + mutex->owner=mutex->first->thread; + mutex->first=mutex->first->next; + + #ifndef SCHED_TYPE_EDF + if(t->IRQgetPriority() >Thread::IRQgetCurrentThread()->IRQgetPriority()) + return true; + #endif //SCHED_TYPE_EDF + return false; + } + mutex->owner=0; + return false; +} + +void fixmeMutexInit(MutexImpl *mutex, bool recursive) +{ + mutex->owner=0; + mutex->first=0; + //No need to initialize mutex->last + mutex->recursive= recursive ? 0 : -1; +} + +void fixmeMutexDestroy(MutexImpl *mutex) +{ + //Do nothing +} + +void fixmeMutexLock(MutexImpl *mutex) +{ + FastInterruptDisableLock dLock; + IRQdoMutexLock(mutex,dLock); +} + +bool fixmeMutexTryLock(MutexImpl *mutex) { FastInterruptDisableLock dLock; void *p=reinterpret_cast<void*>(Thread::IRQgetCurrentThread()); @@ -112,26 +162,105 @@ bool fixmeTryLock(MutexImpl *mutex) return false; } -void fixmeUnlock(MutexImpl *mutex) +void fixmeMutexUnlock(MutexImpl *mutex) { + #ifndef SCHED_TYPE_EDF FastInterruptDisableLock dLock; -// Safety check removed for speed reasons -// if(mutex->owner!=reinterpret_cast<void*>(Thread::IRQgetCurrentThread())) -// { -// errorHandler(MUTEX_UNLOCK_NOT_OWNER); -// return; -// } - if(mutex->recursive>0) + IRQdoMutexUnlock(mutex); + #else //SCHED_TYPE_EDF + bool hppw; { - mutex->recursive--; - return; + FastInterruptDisableLock dLock; + hppw=IRQdoMutexUnlock(mutex); } - if(mutex->head!=0) - { - mutex->owner=mutex->head->thread; - reinterpret_cast<Thread*>(mutex->head->thread)->IRQwakeup(); - mutex->head=mutex->head->next; - } else mutex->owner=0; + //If the woken thread has higher priority, yield + if(hppw) Thread::yield(); + #endif //SCHED_TYPE_EDF +} + +void fixmeCondInit(CondvarImpl *cond) +{ + cond->first=0; + //No need to initialize cond->last +} + +void fixmeCondDestroy(CondvarImpl *cond) +{ + //Do nothing +} + +void fixmeCondWait(CondvarImpl *cond, MutexImpl *mutex) +{ +// FastInterruptDisableLock dLock; +// Thread *p=Thread::IRQgetCurrentThread(); +// WaitingList waiting; //Element of a linked list on stack +// waiting.thread=reinterpret_cast<void*>(p); +// waiting.next=0; //Putting this thread last on the list (lifo policy) +// if(cond->first==0) +// { +// cond->first=&waiting; +// cond->last=&waiting; +// } else { +// cond->last->next=&waiting; +// cond->last=&waiting; +// } +// p->flags.IRQsetCondWait(true); +// +// IRQdoMutexUnlock(mutex); +// { +// FastInterruptEnableLock eLock(dLock); +// Thread::yield(); //Here the wait becomes effective +// } +// IRQdoMutexLock(mutex,dLock); +} + +void fixmeCondSignal(CondvarImpl *cond) +{ +// #ifdef SCHED_TYPE_EDF +// bool hppw=false; +// #endif //SCHED_TYPE_EDF +// { +// FastInterruptDisableLock dLock; +// if(cond->first==0) return; +// +// Thread *t=reinterpret_cast<Thread*>(cond->first->thread); +// t->flags.IRQsetCondWait(false); +// cond->first=cond->first->next; +// +// #ifdef SCHED_TYPE_EDF +// if(t->IRQgetPriority() >Thread::IRQgetCurrentThread()->IRQgetPriority()) +// hppw=true; +// #endif //SCHED_TYPE_EDF +// } +// #ifdef SCHED_TYPE_EDF +// //If the woken thread has higher priority, yield +// if(hppw) Thread::yield(); +// #endif //SCHED_TYPE_EDF +} + +void fixmeCondBroadcast(CondvarImpl *cond) +{ +// #ifdef SCHED_TYPE_EDF +// bool hppw=false; +// #endif //SCHED_TYPE_EDF +// { +// FastInterruptDisableLock lock; +// while(cond->first!=0) +// { +// Thread *t=reinterpret_cast<Thread*>(cond->first->thread); +// t->flags.IRQsetCondWait(false); +// cond->first=cond->first->next; +// +// #ifdef SCHED_TYPE_EDF +// if(t->IRQgetPriority() > +// Thread::IRQgetCurrentThread()->IRQgetPriority()) hppw=true; +// #endif //SCHED_TYPE_EDF +// } +// } +// #ifdef SCHED_TYPE_EDF +// //If at least one of the woken thread has higher, yield +// if(hppw) Thread::yield(); +// #endif //SCHED_TYPE_EDF } // FIXME : end diff --git a/miosix/kernel/sync.h b/miosix/kernel/sync.h index 1e00baa08fd17c6d8a88617222d8e216142e8ad7..a25f07f8f0be9af90767c3ec99a79df73f1e75e5 100644 --- a/miosix/kernel/sync.h +++ b/miosix/kernel/sync.h @@ -43,27 +43,41 @@ namespace miosix { // FIXME: begin -#define FIXME_MUTEX_INITIALIZER {0,0,-1} -#define FIXME_MUTEX_INITIALIZER_RECURSIVE {0,0,0} +#define FIXME_MUTEX_INITIALIZER {0,0,0,-1} +#define FIXME_MUTEX_INITIALIZER_RECURSIVE {0,0,0,0} +#define FIXME_COND_INITIALIZER {0,0} -struct MutexWaitingList +struct WaitingList { void *thread; //Actually, a Thread * but C doesn't know about C++ classes - MutexWaitingList *next; + WaitingList *next; }; struct MutexImpl { void *owner; //Actually, a Thread * but C doesn't know about C++ classes - MutexWaitingList *head; + WaitingList *first; + WaitingList *last; int recursive; // -1 = special value for non recursive }; -void fixmeInit(MutexImpl *mutex, bool recursive); -void fixmeDestroy(MutexImpl *mutex); -void fixmeLock(MutexImpl *mutex); -bool fixmeTryLock(MutexImpl *mutex); -void fixmeUnlock(MutexImpl *mutex); +struct CondvarImpl +{ + WaitingList *first; + WaitingList *last; +}; + +void fixmeMutexInit(MutexImpl *mutex, bool recursive); +void fixmeMutexDestroy(MutexImpl *mutex); +void fixmeMutexLock(MutexImpl *mutex); +bool fixmeMutexTryLock(MutexImpl *mutex); +void fixmeMutexUnlock(MutexImpl *mutex); + +void fixmeCondInit(CondvarImpl *cond); +void fixmeCondDestroy(CondvarImpl *cond); +void fixmeCondWait(CondvarImpl *cond, MutexImpl *mutex); +void fixmeCondSignal(CondvarImpl *cond); +void fixmeCondBroadcast(CondvarImpl *cond); /** * Fast mutex without support for priority inheritance @@ -86,8 +100,8 @@ public: */ FastMutex(Options opt=DEFAULT) { - if(opt==DEFAULT) fixmeInit(&impl,false); - else fixmeInit(&impl,true); + if(opt==DEFAULT) fixmeMutexInit(&impl,false); + else fixmeMutexInit(&impl,true); } /** @@ -96,7 +110,7 @@ public: */ void lock() { - fixmeLock(&impl); + fixmeMutexLock(&impl); } /** @@ -107,7 +121,7 @@ public: */ bool tryLock() { - return fixmeTryLock(&impl); + return fixmeMutexTryLock(&impl); } /** @@ -115,7 +129,7 @@ public: */ void unlock() { - fixmeUnlock(&impl); + fixmeMutexUnlock(&impl); } /** @@ -123,7 +137,7 @@ public: */ ~FastMutex() { - fixmeDestroy(&impl); + fixmeMutexDestroy(&impl); } private: diff --git a/miosix/util/version.cpp b/miosix/util/version.cpp index 08b8f8b94272ecd3c58f85c5451eebc795a754e1..d9b4aeffcfabe2933b5b09ecf867d0a1419abc00 100644 --- a/miosix/util/version.cpp +++ b/miosix/util/version.cpp @@ -4,7 +4,7 @@ namespace miosix { /** * Kernel verision is stored in this string. */ -const char *const versionString="Miosix v1.57"; +const char *const versionString="Miosix v1.58"; const char *getMiosixVersion() { diff --git a/testsuite.cpp b/testsuite.cpp index a57376e60fd503134ad2c17c5b27ab51d18af37e..40ce5547749cf93e6ef829bf4edb955776488757 100644 --- a/testsuite.cpp +++ b/testsuite.cpp @@ -2538,8 +2538,8 @@ static void benchmark_4() i=0; while(b4_end==false) { - fixmeLock(&mm); - fixmeUnlock(&mm); + fixmeMutexLock(&mm); + fixmeMutexUnlock(&mm); i++; } iprintf("%d FastMutexlock/unlock pairs per second\n",i);