//-------------------------------------------------------------------------------- void LogStream::write() const { if (lssPerm.getMessageType() < lssTemp.getMessageType()) { std::string msg = ": " + mBuf.str(); locked_write(msg); } else if (lssPerm.getMessageType() == lssTemp.getMessageType() && lssPerm.getSeverity () <= lssTemp.getSeverity ()) { std::string msg = ": " + mBuf.str(); locked_write(msg); } }
//-------------------------------------------------------------------------------- void LogStream::end_write() { if(!myMaskEnabled()) return; std::string msg; msg = "- [" + getSource() + "]"; locked_write(msg); }
//-------------------------------------------------------------------------------- void LogStream::end_write() const { if(lssPerm.getMessageType() <= LT_DEBUG && lssPerm.getSeverity () <= LS_LOW) { std::string msg = "- [" + getSource() + "]"; locked_write(msg); } }
void critical_section_init(CriticalSection* cs) { locked_write(&cs->lock, 0); #ifdef RECURSIVE cs->owner = NULL; cs->counter = 0; #endif cs->waiter_chain = NULL; }
void critical_section_enter(CriticalSection* cs) { while (EXPECT_FALSE(!critical_section_try_enter(cs))) { //cs ist gelockt, versuchen, waiter zu werden uint val = locked_read(&cs->lock); //0 und 3 wären auch noch möglich if (EXPECT_TRUE(val == 1 || val == 2)) { if (locked_cas(&cs->lock, val, 3)) { //geklappt; sind im spin-lock zustand //als warter einqueuen, und... warten /*volatile*/ struct Waiter puh; puh.thread = thread_get_current_handle(); //cast entfernt warnung puh.next = (struct Waiter*)cs->waiter_chain; cs->waiter_chain = &puh; #ifdef TACTICAL_YIELD thread_yield(); #endif assert(locked_read(&cs->lock) == 3); locked_write(&cs->lock, 2); //zwischen hier und jetzt könnten wir unterbrochen werden // nicht schlimm, wenn der aufwecker einen blockierenden // ipc call benutzt LipcMessage msg; msg.flags = LIPC_RECEIVE; bool res = sys_lipc(&msg); //"sparodische" msg ausschliessen assert(res && msg.word0 == SOME_MAGIC); if (msg.word1 == MSG_CRITICAL_SECTION_DESTROY) { //sonderfall zur zerstörung eines mutex #ifdef PRINT_DEBUG printf("ÄRGS! TOT ZERSTÖRUNG!, thread %p by %p\n", thread_get_current_handle(), msg.send_receive_handle); #endif //was soll ich machen? assert(false); return; } assert(msg.word1 == MSG_CRITICAL_SECTION_WAKEUP); #ifdef PRINT_DEBUG printf("woken up, thread %p by %p\n", thread_get_current_handle(), msg.send_receive_handle); #endif //der aufwecker hat uns aus waiter queue entfernt //jetzt versuchen, lock wieder zu bekommen (yield überspringen) continue; } } else { assert(val == 0 || val == 3); } #ifdef PRINT_DEBUG printf("thread %p: SPIN lock\n", thread_get_current_handle()); #endif thread_yield(); } }
//-------------------------------------------------------------------------------- void LogStream::write() { if(!myMaskEnabled()) return; std::string msg; msg = ": " + mBuf.str(); locked_write(msg); lssTemp.reset(); }
bool critical_section_try_enter(CriticalSection* cs) { #ifdef RECURSIVE if (EXPECT_FALSE(cs->owner == thread_get_current_handle())) { cs->counter++; return true; } #endif if (EXPECT_TRUE(locked_cas(&cs->lock, 0, 3))) { //mit 3 wird race condition verhindert: #ifdef RECURSIVE cs->owner = thread_get_current_handle(); cs->counter = 1; //<- eig. keine synchr. notwendig #endif #ifdef TACTICAL_YIELD thread_yield(); #endif assert(locked_read(&cs->lock) == 3); locked_write(&cs->lock, 1); return true; } else return false; }
void critical_section_leave(CriticalSection* cs) { #ifdef RECURSIVE //annahme: wir besitzen die CS cs->counter--; if (EXPECT_FALSE(cs->counter != 0)) //(und wir besitzen immer noch) return; //owner invalidieren (wird verwendet, um in _enter schnell zu erkennen, ob // der lock besessen wird...) assert(cs->owner == thread_get_current_handle()); cs->owner = NULL; #endif //schneller fall: 1->0 //wenn wir owner sind, ist nur noch 1->2/3 möglich, ohne rückkehr zu 1... // d.h. es reicht, wenn das der erste und letzte versuch für 1->0 ist. if (EXPECT_TRUE(locked_cas(&cs->lock, 1, 0))) return; //wir müssen andere thread aufwecken //einzige zustandsübergänge: 2->3 und 3->2 (nur wir können noch 3->0) while (EXPECT_FALSE(!locked_cas(&cs->lock, 2, 3))) { //zustand 3 ist eine art spinlock //etwas blöde, da es passieren kann, das der scheduler schon // zurückschaltet, obwohl der andere thread noch nicht fertig ist // mögliche lösung: spinlocker gibt seine thread id an... #ifdef PRINT_DEBUG printf("thread %p: SPIN release\n", thread_get_current_handle()); #endif thread_yield(); } #ifdef TACTICAL_YIELD thread_yield(); #endif //wir sind im zustand 3, eine art spinlock zustand //waiter lesen und section komplett freigeben volatile struct Waiter* waiter = cs->waiter_chain; //auch wichtig #ifdef TACTICAL_YIELD thread_yield(); #endif cs->waiter_chain = NULL; assert(locked_read(&cs->lock) == 3); locked_write(&cs->lock, 0); //waiter aufwecken //wir wecken alle auf; der scheduler entscheidet wer den zuschlag bekommt while (waiter) { #ifdef TACTICAL_YIELD thread_yield(); #endif LipcMessage msg; #ifdef PRINT_DEBUG printf("thread %p: wake up %p\n", thread_get_current_handle(), waiter->thread); #endif volatile struct Waiter* next = waiter->next; msg.send_receive_handle = waiter->thread; msg.flags = LIPC_SEND; msg.word0 = SOME_MAGIC; msg.word1 = MSG_CRITICAL_SECTION_WAKEUP; bool res = sys_lipc(&msg); assert(res); waiter = next; } //erfolg; fertig return; }