Skip to content

Commit fff5b4d

Browse files
committed
Fixed bug with multiple priorities
1 parent 603b006 commit fff5b4d

3 files changed

Lines changed: 124 additions & 30 deletions

File tree

src/ProcessScheduler/Config.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,18 @@
77
//#define _PROCESS_EXCEPTION_HANDLING
88

99
/* Uncomment this to allow Process timing statistics functionality */
10-
//#define _PROCESS_STATISTICS
10+
#define _PROCESS_STATISTICS
1111

1212
/* Uncomment this to use microseconds instead of milliseconds for timestamp unit (more precise) */
1313
//#define _MICROS_PRECISION
1414

1515
/* The size of the scheduler job queue, */
1616
//increase if add(), destroy(), enable(), disable(), or updateStats() is returning false*/
17+
18+
//#define _PROCESS_REORDERING
19+
20+
#define _PROCESS_REORDERING_AGGRESSIVENESS 50000
21+
1722
#define SCHEDULER_JOB_QUEUE_SIZE 20
1823

1924
typedef enum ProcPriority

src/ProcessScheduler/Scheduler.cpp

Lines changed: 104 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44

55
Scheduler::Scheduler()
6-
: _head{}, _nextProc{}
6+
: _pLevels{}
77
{
88
_lastID = 0;
99
// Create queue
@@ -35,7 +35,7 @@ Process *Scheduler::findProcById(uint8_t id)
3535
{
3636
for (uint8_t i=0; i < NUM_PRIORITY_LEVELS; i++)
3737
{
38-
for (Process *serv = _head[i]; serv != NULL; serv = serv->getNext())
38+
for (Process *serv = _pLevels[i].head; serv != NULL; serv = serv->getNext())
3939
{
4040
if (serv->getID() == id)
4141
return serv;
@@ -99,7 +99,7 @@ uint8_t Scheduler::countProcesses(int priority, bool enabledOnly)
9999
uint8_t count=0;
100100
for (uint8_t i = (priority == ALL_PRIORITY_LEVELS) ? 0 : (uint8_t)priority; i < NUM_PRIORITY_LEVELS; i++)
101101
{
102-
for (Process *curr = _head[i]; curr != NULL; curr = curr->getNext())
102+
for (Process *curr = _pLevels[i].head; curr != NULL; curr = curr->getNext())
103103
{
104104
count += enabledOnly ? curr->isEnabled() : 1;
105105
}
@@ -120,7 +120,7 @@ int Scheduler::run()
120120
{
121121
processQueue();
122122

123-
_active = _nextProc[pLevel];
123+
_active = _pLevels[pLevel].next;
124124
if (!_active)
125125
continue;
126126

@@ -166,17 +166,22 @@ int Scheduler::run()
166166

167167
// Determine what to do next ///
168168
if (!_active->hasNext()) {
169-
_nextProc[pLevel] = _head[pLevel]; // Set next to first
169+
#ifdef _PROCESS_REORDERING
170+
if(++_pLevels[pLevel].passes >= _PROCESS_REORDERING_AGGRESSIVENESS) {
171+
reOrderProcs((ProcPriority)pLevel);
172+
++_pLevels[pLevel].passes = 0;
173+
}
174+
#endif
175+
_pLevels[pLevel].next = _pLevels[pLevel].head; // Set next to first
170176
} else {
171-
_nextProc[pLevel] = _active->getNext(); // Set next and break
177+
_pLevels[pLevel].next = _active->getNext(); // Set next and break
172178
_active = NULL;
173179
break;
174180
}
175181

182+
_active = NULL;
176183
}
177-
178184
processQueue();
179-
180185
return count;
181186
}
182187

@@ -230,7 +235,7 @@ void Scheduler::procHalt()
230235
{
231236
for (uint8_t i = 0; i < NUM_PRIORITY_LEVELS; i++)
232237
{
233-
for (Process *curr = _head[i]; curr != NULL; curr = curr->getNext())
238+
for (Process *curr = _pLevels[i].head; curr != NULL; curr = curr->getNext())
234239
{
235240
procDestroy(*curr);
236241
}
@@ -310,7 +315,6 @@ void Scheduler::processQueue()
310315
}
311316

312317
#ifdef _PROCESS_STATISTICS
313-
314318
bool Scheduler::updateStats()
315319
{
316320
QueableOperation op(QueableOperation::UPDATE_STATS);
@@ -331,7 +335,7 @@ void Scheduler::procUpdateStats()
331335

332336
for (uint8_t l = 0; l < NUM_PRIORITY_LEVELS; l++)
333337
{
334-
for (i = 0, p = _head[l]; p != NULL && i < count; p = p->getNext(), i++)
338+
for (i = 0, p = _pLevels[l].head; p != NULL && i < count; p = p->getNext(), i++)
335339
{
336340
// to ensure no overflows
337341
sTime[i] = (p->getHistRunTime() + count/2) / count;
@@ -341,7 +345,7 @@ void Scheduler::procUpdateStats()
341345

342346
for (uint8_t l = 0; l < NUM_PRIORITY_LEVELS; l++)
343347
{
344-
for (i = 0, p = _head[l]; p != NULL && i < count; p = p->getNext(), i++)
348+
for (i = 0, p = _pLevels[l].head; p != NULL && i < count; p = p->getNext(), i++)
345349
{
346350
// to ensure no overflows have to use double
347351
if (!totalTime) {
@@ -361,7 +365,7 @@ void Scheduler::handleHistOverFlow(uint8_t div)
361365
{
362366
for (uint8_t i = 0; i < NUM_PRIORITY_LEVELS; i++)
363367
{
364-
for (Process *p = _head[i]; p != NULL; p = p->getNext())
368+
for (Process *p = _pLevels[i].head; p != NULL; p = p->getNext())
365369
{
366370
p->divStats(div);
367371
}
@@ -400,11 +404,11 @@ bool Scheduler::appendNode(Process &node)
400404

401405
ProcPriority p = node.getPriority();
402406

403-
if (!_head[p]) {
404-
_head[p] = &node;
405-
_nextProc[p] = &node;
407+
if (!_pLevels[p].head) { // adding to head
408+
_pLevels[p].head = &node;
409+
_pLevels[p].next = &node;
406410
} else {
407-
Process *next = _head[p];
411+
Process *next = _pLevels[p].head; // adding not to head
408412
for(; next->hasNext(); next = next->getNext()); //run through list
409413
// Update pointers
410414
next->setNext(&node);
@@ -416,31 +420,105 @@ bool Scheduler::removeNode(Process &node)
416420
{
417421
ProcPriority p = node.getPriority();
418422

419-
if (&node == _head[p]) { // node is head
420-
_head[p] = node.getNext();
423+
if (&node == _pLevels[p].head) { // node is head
424+
_pLevels[p].head = node.getNext();
421425
} else {
422426
// Find the previous node
423-
Process *prev = _head[p];
424-
for (; prev != NULL && prev->getNext() != &node; prev = prev->getNext());
427+
Process *prev = findPrevNode(node);
425428

426-
if (!prev) return false; // previous node does not exist
429+
if (!prev)
430+
return false; // previous node does not exist
427431

428432
prev->setNext(node.getNext());
429433
}
430434

431-
if (_nextProc[p] == &node)
432-
_nextProc[p] = node.hasNext() ? node.getNext() : _head[p];
435+
if (_pLevels[p].next == &node)
436+
_pLevels[p].next = node.hasNext() ? node.getNext() : _pLevels[p].head;
433437

434438
return true;
435439
}
436440

437-
438441
bool Scheduler::findNode(Process &node)
439442
{
440-
for (Process *p = _head[node.getPriority()]; p != NULL; p = p->getNext())
443+
for (Process *p = _pLevels[node.getPriority()].head; p != NULL; p = p->getNext())
441444
{
442445
if (p == &node)
443446
return true;
444447
}
445448
return false;
446449
}
450+
451+
Process *Scheduler::findPrevNode(Process &node)
452+
{
453+
Process *prev = _pLevels[node.getPriority()].head;
454+
for (; prev != NULL && prev->getNext() != &node; prev = prev->getNext());
455+
return prev;
456+
}
457+
458+
/*
459+
void Scheduler::reOrderProcs(ProcPriority level)
460+
{
461+
for(Process *p = _pLevels[level].head; p != NULL && p->hasNext(); p = p->getNext())
462+
{
463+
Process *next = p->getNext();
464+
465+
if (p->getAvgRunTime() > next->getAvgRunTime())
466+
{
467+
Serial.println("Swapping");
468+
if(!swapNode(*p, *next)) //this should never fail, but to be safe
469+
break;
470+
471+
p = next;
472+
}
473+
}
474+
}
475+
476+
bool Scheduler::swapNode(Process &n1, Process &n2)
477+
{
478+
if (&n1 == &n2 || n1.getPriority() != n2.getPriority())
479+
return false;
480+
481+
482+
Process *n1_prev = findPrevNode(n1);
483+
Process *n2_prev = findPrevNode(n2);
484+
485+
if (!n1_prev) { //n1 was head
486+
_pLevels[n1.getPriority()].head = &n2;
487+
} else { //n1 was not head
488+
n1_prev->setNext(&n2);
489+
}
490+
491+
if (!n2_prev) { //n2 was head
492+
_pLevels[n1.getPriority()].head = &n1;
493+
} else { //n2 was not head
494+
n2_prev->setNext(&n1);
495+
}
496+
497+
Process *tmp = n2.getNext();
498+
n2.setNext(n1.getNext());
499+
n1.setNext(tmp);
500+
return true;
501+
}
502+
503+
bool Scheduler::removeNodeAfter(Process &prev)
504+
{
505+
Process *toRemove = prev.getNext();
506+
507+
if (!toRemove)
508+
return false;
509+
510+
prev.setNext(toRemove->getNext());
511+
512+
return true;
513+
}
514+
515+
bool Scheduler::insertNodeAfter(Process &prev, Process &toAdd)
516+
{
517+
Process *next = prev.getNext();
518+
519+
prev.setNext(&toAdd);
520+
toAdd.setNext(&prev);
521+
522+
return true;
523+
}
524+
*/

src/ProcessScheduler/Scheduler.h

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,15 +80,26 @@ class Scheduler
8080
bool appendNode(Process &node); // true on success
8181
bool removeNode(Process &node); // true on success
8282
bool findNode(Process &node); // True if node exists in list
83+
Process *findPrevNode(Process &node);
8384

84-
Process *volatile _head[NUM_PRIORITY_LEVELS];
85-
Process *volatile _nextProc[NUM_PRIORITY_LEVELS];
8685

8786
Process *_active;
8887
uint8_t _lastID;
8988
RingBuf *_queue;
9089

91-
private:
90+
struct SchedulerPriorityLevel
91+
{
92+
Process *head;
93+
Process *next;
94+
};
95+
struct SchedulerPriorityLevel _pLevels[NUM_PRIORITY_LEVELS];
96+
97+
98+
/* CUSTOM COMPILE OPTIONS*/
99+
/*
100+
bool swapNode(Process &n1, Process &n2);
101+
void reOrderProcs(ProcPriority level);
102+
*/
92103

93104
#ifdef _PROCESS_STATISTICS
94105
public:

0 commit comments

Comments
 (0)