diff options
Diffstat (limited to 'ndb/src/kernel/vm/ThreadConfig.cpp')
-rw-r--r-- | ndb/src/kernel/vm/ThreadConfig.cpp | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/ndb/src/kernel/vm/ThreadConfig.cpp b/ndb/src/kernel/vm/ThreadConfig.cpp new file mode 100644 index 00000000000..d18b20a5bb5 --- /dev/null +++ b/ndb/src/kernel/vm/ThreadConfig.cpp @@ -0,0 +1,207 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include "ThreadConfig.hpp" +#include "Emulator.hpp" +#include "GlobalData.hpp" +#include "TimeQueue.hpp" +#include "TransporterRegistry.hpp" +#include "FastScheduler.hpp" +#include "pc.hpp" + +#include <GlobalSignalNumbers.h> +#include <BlockNumbers.h> + +#include <NdbSleep.h> +#include <NdbTick.h> +#include <NdbOut.hpp> + +#include <signaldata/StartOrd.hpp> + +ThreadConfig::ThreadConfig() +{ +} + +ThreadConfig::~ThreadConfig() +{ +} + +/** + * For each millisecond that has passed since this function was last called: + * Scan the job buffer and increment the internalMillisecCounter + * with 1 to keep track of where we are + */ +inline +void +ThreadConfig::scanTimeQueue() +{ + unsigned int maxCounter; + Uint64 currMilliSecond; + maxCounter = 0; + currMilliSecond = NdbTick_CurrentMillisecond(); + if (currMilliSecond < globalData.internalMillisecCounter) { +//-------------------------------------------------------------------- +// This could occur around 2036 or if the operator decides to change +// time backwards. We cannot know how long time has past since last +// time and we make a best try with 0 milliseconds. +//-------------------------------------------------------------------- +#ifdef VM_TRACE + ndbout << "Time moved backwards with "; + ndbout << (globalData.internalMillisecCounter - currMilliSecond); + ndbout << " milliseconds" << endl; +#endif + globalData.internalMillisecCounter = currMilliSecond; + }//if + if (currMilliSecond > (globalData.internalMillisecCounter + 1500)) { +//-------------------------------------------------------------------- +// Time has moved forward more than a second. Either it could happen +// if operator changed the time or if the OS has misbehaved badly. +// We set the new time to one second from the past. +//-------------------------------------------------------------------- +#ifdef VM_TRACE + ndbout << "Time moved forward with "; + ndbout << (currMilliSecond - globalData.internalMillisecCounter); + ndbout << " milliseconds" << endl; +#endif + globalData.internalMillisecCounter = currMilliSecond - 1000; + }//if + while (((currMilliSecond - globalData.internalMillisecCounter) > 0) && + (maxCounter < 20)){ + globalData.internalMillisecCounter++; + maxCounter++; + globalTimeQueue.scanTable(); + }//while +}//ThreadConfig::scanTimeQueue() + + +//-------------------------------------------------------------------- +// ipControlLoop -- The main loop of ndb. +// Handles the scheduling of signal execution and input/output +// One lap in the loop should take approximately 10 milli seconds +// If the jobbuffer is empty and the laptime is less than 10 milliseconds +// at the end of the loop +// the TransporterRegistry is called in order to sleep on the IO ports +// waiting for another incoming signal to wake us up. +// The timeout value in this call is calculated as (10 ms - laptime) +// This would make ndb use less cpu while improving response time. +//-------------------------------------------------------------------- +void ThreadConfig::ipControlLoop() +{ + +#if defined NDB_OSE || defined NDB_SOFTOSE +//-------------------------------------------------------------------- +// To let the Cello Watchdog do it's work NDB must sleep a short +// period every 10 minutes. If this is not done, the watchdog will +// reboot the board NDB is running on when the load is high. +//-------------------------------------------------------------------- + int loopCounter = 0; +#endif + +//-------------------------------------------------------------------- +// initialise the counter that keeps track of the current millisecond +//-------------------------------------------------------------------- + globalData.internalMillisecCounter = NdbTick_CurrentMillisecond(); + Uint32 i = 0; + while (globalData.theRestartFlag != perform_stop) { + +#if defined NDB_OSE || defined NDB_SOFTOSE + loopCounter++; + if(loopCounter > 1000){ +//-------------------------------------------------------------------- +// This is done to allow OSE do a context switch to let the watchdog +// do it's stuff. +//-------------------------------------------------------------------- + NdbSleep_MilliSleep(1); + loopCounter = 0; + } +#endif + + Uint32 timeOutMillis = 0; + if (LEVEL_IDLE == globalData.highestAvailablePrio) { +//-------------------------------------------------------------------- +// The buffers are empty, we need to wait for a while until we continue. +// We cannot wait forever since we can also have timed events. +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +// Set the time we will sleep on the sockets before waking up +// unconditionally to 10 ms. Will never sleep more than 10 milliseconds +// on a socket. +//-------------------------------------------------------------------- + timeOutMillis = 10; + }//if +//-------------------------------------------------------------------- +// Now it is time to check all interfaces. We will send all buffers +// plus checking for any received messages. +//-------------------------------------------------------------------- + if (i++ >= 20) { + globalData.incrementWatchDogCounter(5); + globalTransporterRegistry.checkConnections(); + i = 0; + }//if + + globalData.incrementWatchDogCounter(6); + globalTransporterRegistry.performSend(); + + globalData.incrementWatchDogCounter(7); + if (globalTransporterRegistry.pollReceive(timeOutMillis)) { + globalData.incrementWatchDogCounter(8); + globalTransporterRegistry.performReceive(); + } + +//-------------------------------------------------------------------- +// We scan the time queue to see if there are any timed signals that +// is now ready to be executed. +//-------------------------------------------------------------------- + globalData.incrementWatchDogCounter(2); + scanTimeQueue(); + +//-------------------------------------------------------------------- +// This is where the actual execution of signals occur. We execute +// until all buffers are empty or until we have executed 2048 signals. +//-------------------------------------------------------------------- + globalScheduler.doJob(); + + globalScheduler.sendPacked(); + + }//while + + globalData.incrementWatchDogCounter(6); + globalTransporterRegistry.performSend(); + +}//ThreadConfig::ipControlLoop() + +int +ThreadConfig::doStart(NodeState::StartLevel startLevel){ + + SignalHeader sh; + memset(&sh, 0, sizeof(SignalHeader)); + + sh.theVerId_signalNumber = GSN_START_ORD; + sh.theReceiversBlockNumber = CMVMI; + sh.theSendersBlockRef = 0; + sh.theTrace = 0; + sh.theSignalId = 0; + sh.theLength = StartOrd::SignalLength; + + Uint32 theData[25]; + StartOrd * const startOrd = (StartOrd *)&theData[0]; + startOrd->restartInfo = 0; + + Uint32 secPtrI[3]; + globalScheduler.execute(&sh, JBA, theData, secPtrI); + return 0; +} + |