Skip to content

Commit 99b5ace

Browse files
authored
Merge pull request #7 from wizard97/strict-priorities
Strict priorities
2 parents 6b269a5 + 92014a0 commit 99b5ace

7 files changed

Lines changed: 112 additions & 54 deletions

File tree

src/ProcessScheduler.h

100644100755
File mode changed.

src/ProcessScheduler/Config.h

100644100755
File mode changed.

src/ProcessScheduler/Includes.h

100644100755
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ typedef enum ProcessWarning
3535

3636
#define OVERSCHEDULED_NO_WARNING 0
3737

38-
// PICK INT VALUES PEOPLE UNLIKLEY TO USE
3938
#define LONGJMP_ISR_CODE -1000
4039
#define LONGJMP_YIELD_CODE -1001
4140

src/ProcessScheduler/Process.cpp

100644100755
Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,9 @@
5959

6060
bool Process::needsServicing(uint32_t start)
6161
{
62-
return (isEnabled() && (_force ||
63-
((getPeriod() == SERVICE_CONSTANTLY || start - getScheduledTS() >= getPeriod()) &&
62+
return (isEnabled() &&
63+
(_force ||
64+
((getPeriod() == SERVICE_CONSTANTLY || timeToNextRun(start) <= 0) &&
6465
(getIterations() == RUNTIME_FOREVER || getIterations() > 0))));
6566
}
6667

@@ -84,6 +85,21 @@
8485
}
8586

8687

88+
// both must need servicing
89+
Process *Process::runWhich(Process *p1, Process *p2)
90+
{
91+
// All things being equal pick yes
92+
93+
// Compare forces
94+
if (p1->forceSet() || p2->forceSet())
95+
return p1->forceSet() ? p1 : p2;
96+
97+
// whichever one is more behind goes first
98+
return (p1->timeToNextRun() <= p2->timeToNextRun()) ? p1 : p2;
99+
100+
}
101+
102+
87103

88104
/*********** PROTECTED *************/
89105

src/ProcessScheduler/Process.h

100644100755
Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,15 @@ class Process
3131
bool destroy();
3232
bool restart();
3333

34+
35+
/*
36+
* Give both processes that need to run p1 and p2
37+
* return the process that should run first
38+
*
39+
* @return: p1 or p2
40+
*/
41+
static Process *runWhich(Process *p1, Process *p2);
42+
3443
///////////////////// GETTERS /////////////////////////
3544

3645
// These methods are also the same as calling calling scheduler.method(process)
@@ -75,7 +84,9 @@ class Process
7584
*
7685
* @return: int32_t time offset
7786
*/
78-
inline int32_t timeToNextRun() { return (_scheduledTS + _period) - _scheduler.getCurrTS(); }
87+
inline int32_t timeToNextRun() { return timeToNextRun(_scheduler.getCurrTS()); }
88+
89+
inline int32_t timeToNextRun(uint32_t curr) { return (int32_t)((_scheduledTS + _period) - curr); }
7990

8091

8192
/*

src/ProcessScheduler/Scheduler.cpp

100644100755
Lines changed: 78 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -133,86 +133,109 @@ uint8_t Scheduler::countProcesses(int priority, bool enabledOnly)
133133
return count;
134134
}
135135

136+
136137
int Scheduler::run()
137138
{
138139
// Already running in another call frame
139140
if (_active) return 0;
140141

141142
uint8_t count = 0;
143+
uint32_t start = getCurrTS();
142144
for (uint8_t pLevel=0; pLevel < NUM_PRIORITY_LEVELS; pLevel++)
143145
{
144146
processQueue();
145147

146-
_active = _pLevels[pLevel].next;
147-
if (!_active)
148+
// Resume looking where we left off in the list
149+
Process *torun = getRunnable(start, _pLevels[pLevel].next, NULL);
150+
151+
if (!torun && _pLevels[pLevel].next != _pLevels[pLevel].head)
152+
torun = getRunnable(start, _pLevels[pLevel].head, _pLevels[pLevel].next);
153+
154+
// No ready process found at this priority level
155+
if (!torun)
148156
continue;
149157

150-
/////////// Run the correct process /////////
151-
uint32_t start = getCurrTS();
158+
_pLevels[pLevel].next = torun->hasNext() ? torun->getNext() : _pLevels[pLevel].head;
152159

153-
if (_active->needsServicing(start))
154-
{
155-
bool force = _active->forceSet(); // Store whether it was a forced iteraiton
156-
_active->willService(start);
160+
/////////// Run the correct process /////////
161+
_active = torun;
162+
start = getCurrTS(); //update
163+
bool force = _active->forceSet(); // Store whether it was a forced iteraiton
164+
_active->willService(start);
157165

158166
#ifdef _PROCESS_EXCEPTION_HANDLING
159-
int ret = setjmp(_env);
167+
int ret = setjmp(_env);
160168

161-
#ifdef _PROCESS_TIMEOUT_INTERRUPTS
162-
ENABLE_SCHEDULER_ISR();
163-
#endif
164-
if (!ret) {
165-
_active->service();
166-
} else {
167-
jmpHandler(ret);
168-
}
169-
#else
169+
// Enable the interrupts
170+
#ifdef _PROCESS_TIMEOUT_INTERRUPTS
171+
ENABLE_SCHEDULER_ISR();
172+
#endif
173+
174+
if (!ret) {
170175
_active->service();
176+
} else {
177+
jmpHandler(ret);
178+
}
179+
#else
180+
_active->service();
171181
#endif
172182

183+
// Disable the interrupts after the process returned
173184
#ifdef _PROCESS_TIMEOUT_INTERRUPTS
174185
DISABLE_SCHEDULER_ISR();
175186
#endif
187+
//////////////////////END PROCESS SERVICING//////////////////////
176188

177189
#ifdef _PROCESS_STATISTICS
178-
uint32_t runTime = getCurrTS() - start;
179-
// Make sure no overflow happens
180-
if (_active->statsWillOverflow(1, runTime))
181-
handleHistOverFlow(HISTORY_DIV_FACTOR);
190+
uint32_t runTime = getCurrTS() - start;
191+
// Make sure no overflow happens
192+
if (_active->statsWillOverflow(1, runTime))
193+
handleHistOverFlow(HISTORY_DIV_FACTOR);
182194

183-
_active->setHistIterations(_active->getHistIterations()+1);
184-
_active->setHistRuntime(_active->getHistRunTime()+runTime);
195+
_active->setHistIterations(_active->getHistIterations()+1);
196+
_active->setHistRuntime(_active->getHistRunTime()+runTime);
185197

186198
#endif
187-
// Is it time to disable?
188-
if (_active->wasServiced(force)) {
189-
disable(*_active);
190-
}
191-
192-
count++; // incr counter
199+
// Is it time to disable?
200+
if (_active->wasServiced(force)) {
201+
disable(*_active);
193202
}
194-
//////////////////////END PROCESS SERVICING//////////////////////
203+
_active = NULL; //done!
204+
205+
count++; // incr counter
206+
processQueue();
195207
delay(0); // For esp8266
208+
break; // We found the process and serviced it, so were done
209+
}
210+
delay(0); // For esp8266
211+
212+
return count;
213+
}
214+
215+
216+
// end is exclusive, end=NULL means go to entire end of list
217+
Process *Scheduler::getRunnable(uint32_t start, Process *begin, Process *end)
218+
{
219+
if (!start)
220+
return NULL;
221+
222+
Process *torun = NULL;
223+
Process *tmp = begin;
196224

197-
// Determine what to do next ///
198-
if (!_active->hasNext()) {
199-
#ifdef _PROCESS_REORDERING
200-
if(++_pLevels[pLevel].passes >= _PROCESS_REORDERING_AGGRESSIVENESS) {
201-
reOrderProcs((ProcPriority)pLevel);
202-
++_pLevels[pLevel].passes = 0;
225+
// Search for the best process
226+
while(tmp != end) {
227+
if (tmp->needsServicing(start)) {
228+
if (torun) { //Compare which one needs to run more
229+
torun = Process::runWhich(torun, tmp);
230+
} else { //torun is NULL so this is the best one to run
231+
torun = tmp;
203232
}
204-
#endif
205-
_pLevels[pLevel].next = _pLevels[pLevel].head; // Set next to first
206-
} else {
207-
_pLevels[pLevel].next = _active->getNext(); // Set next and break
208-
_active = NULL;
209-
break;
210233
}
211234

212-
_active = NULL;
235+
tmp = tmp->getNext();
213236
}
214-
processQueue();
215-
return count;
237+
238+
return torun;
216239
}
217240

218241

@@ -434,9 +457,15 @@ void Scheduler::handleHistOverFlow(uint8_t div)
434457
longjmp(_env, e);
435458
}
436459

437-
void Scheduler::handleException(Process &process, int e)
460+
void Scheduler::handleException(Process *process, int e)
438461
{
439-
process.restart();
462+
// Exception came from process
463+
if (process) {
464+
process.restart();
465+
} else {
466+
// Exception came from scheduler
467+
468+
}
440469
}
441470

442471

@@ -457,7 +486,7 @@ void Scheduler::handleHistOverFlow(uint8_t div)
457486

458487
default:
459488
if (!_active->handleException(e))
460-
handleException(*_active, e);
489+
handleException(_active, e);
461490
break;
462491

463492
}

src/ProcessScheduler/Scheduler.h

100644100755
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ class Scheduler
191191
* Handle uncaught Process exceptions from Process process with Exception code e
192192
* By default just restart it
193193
*/
194-
virtual void handleException(Process &process, int e);
194+
virtual void handleException(Process *process, int e);
195195
#endif
196196
// Inner queue object class to queue scheduler jobs
197197
class QueableOperation
@@ -245,6 +245,9 @@ class Scheduler
245245
void procRestart(Process &process);
246246
void procHalt();
247247

248+
// Get runnable process in process linked list chain
249+
Process *getRunnable(uint32_t start, Process *begin, Process *end=NULL);
250+
248251
// Process the scheduler job queue
249252
void processQueue();
250253

0 commit comments

Comments
 (0)