Skip to content

Commit 318e5b5

Browse files
committed
IRAM attribute; small refactoring; runnableTasks array must be 1 element larger than max task #
1 parent 61cf7fe commit 318e5b5

File tree

7 files changed

+35
-26
lines changed

7 files changed

+35
-26
lines changed

examples/Callbacks/Callbacks.ino

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,18 @@
44
#include <CoopMutex.h>
55
#include <BasicCoopTask.h>
66

7+
#if defined(ARDUINO_attiny)
8+
#define LED_BUILTIN 1
9+
10+
struct DummySerial {
11+
void print(const __FlashStringHelper* s = nullptr) {}
12+
void println(const __FlashStringHelper* s = nullptr) {}
13+
void println(long unsigned int) {}
14+
void flush() {}
15+
};
16+
DummySerial Serial;
17+
#endif
18+
719
CoopTask<void>* blinkTask = nullptr;
820
CoopTask<void>* switchTask = nullptr;
921

@@ -53,11 +65,13 @@ bool sleepCb()
5365

5466
void setup()
5567
{
68+
#if !defined(ARDUINO_attiny)
5669
Serial.begin(74800);
5770
while (!Serial);
5871
delay(100);
5972
Serial.println();
6073
Serial.println(F("runTasks callback test"));
74+
#endif
6175

6276
runCoopTasks(nullptr, delayCb, sleepCb);
6377
Serial.println(F("no tasks yet, sleepCb()?"));
@@ -78,7 +92,7 @@ void loop()
7892
Serial.println(F("B - both tasks delayed, delayCb(100)?"));
7993
yield();
8094
runCoopTasks(nullptr, delayCb, sleepCb);
81-
Serial.println(F("C - blink task delayed, buzzer task sleeping, delayCb(4900)?"));
95+
Serial.println(F("C - blink task delayed, switch task sleeping, delayCb(4900)?"));
8296
yield();
8397
runCoopTasks(nullptr, delayCb, sleepCb);
8498
Serial.println(F("D - both tasks sleeping, sleepCb()?"));

library.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "CoopTask",
3-
"version": "3.6.0",
3+
"version": "3.6.1",
44
"keywords": [
55
"multitasking", "timing"
66
],

library.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name=CoopTask
2-
version=3.6.0
2+
version=3.6.1
33
author=Dirk O. Kaar
44
maintainer=Dirk O. Kaar <dok@dok-net.net>
55
sentence=Portable C++ library for cooperative multitasking like Arduino Scheduler on ESP8266/ESP32, AVR, Linux, Windows

src/BasicCoopTask.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,10 +101,10 @@ template<class StackAllocator = CoopTaskStackAllocator> class BasicCoopTask : pu
101101
}
102102
/// Every task is entered into this list by scheduleTask(). It is removed when it exits
103103
/// or gets deleted.
104-
static const std::array< std::atomic<BasicCoopTask* >, MAXNUMBERCOOPTASKS>& getRunnableTasks()
104+
static const std::array< std::atomic<BasicCoopTask* >, MAXNUMBERCOOPTASKS + 1>& getRunnableTasks()
105105
{
106106
// this is safe to do because CoopTaskBase ctor is protected.
107-
return reinterpret_cast<const std::array< std::atomic<BasicCoopTask* >, MAXNUMBERCOOPTASKS>&>(CoopTaskBase::getRunnableTasks());
107+
return reinterpret_cast<const std::array< std::atomic<BasicCoopTask* >, MAXNUMBERCOOPTASKS + 1>&>(CoopTaskBase::getRunnableTasks());
108108
}
109109
protected:
110110
StackAllocator stackAllocator;

src/CoopSemaphore.cpp

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -127,21 +127,18 @@ bool CoopSemaphore::_wait(const bool withDeadline, const uint32_t ms)
127127
}
128128
if (selfFirst)
129129
{
130-
if (!withDeadline) self->sleep(false);
131130
selfFirst = false;
131+
if (!withDeadline) self->sleep(false);
132132
selfSuccess = true;
133133
}
134134
else if (pendingTask == self)
135135
{
136-
if (selfSuccess)
137-
{
138-
if (!stop) continue;
139-
}
140-
else
136+
if (!selfSuccess)
141137
{
142138
if (!withDeadline) self->sleep(false);
143139
return true;
144140
}
141+
if (!stop) continue;
145142
}
146143
else if (pendingTask)
147144
{
@@ -213,11 +210,8 @@ bool IRAM_ATTR CoopSemaphore::post()
213210
while (!value.compare_exchange_weak(val, val + 1)) {}
214211
pendingTask = pendingTask0.exchange(nullptr);
215212
#endif
216-
if (pendingTask)
217-
{
218-
pendingTask->scheduleTask(true);
219-
}
220-
return true;
213+
if (!pendingTask || !pendingTask->suspended()) return true;
214+
return pendingTask->scheduleTask(true);
221215
}
222216

223217
bool CoopSemaphore::setval(unsigned newVal)

src/CoopTaskBase.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ extern "C" {
114114
#endif // ESP32_FREERTOS
115115
}
116116

117-
std::array< std::atomic<CoopTaskBase* >, CoopTaskBase::MAXNUMBERCOOPTASKS> CoopTaskBase::runnableTasks{};
117+
std::array< std::atomic<CoopTaskBase* >, CoopTaskBase::MAXNUMBERCOOPTASKS + 1> CoopTaskBase::runnableTasks {};
118118
std::atomic<size_t> CoopTaskBase::runnableTasksCount(0);
119119

120120
CoopTaskBase* CoopTaskBase::current = nullptr;
@@ -174,11 +174,11 @@ bool CoopTaskBase::rescheduleTask(uint32_t repeat_us)
174174
}
175175
#endif
176176

177-
bool CoopTaskBase::enrollRunnable()
177+
bool IRAM_ATTR CoopTaskBase::enrollRunnable()
178178
{
179179
bool enrolled = false;
180180
bool inserted = false;
181-
for (size_t i = 0; i < CoopTaskBase::MAXNUMBERCOOPTASKS; ++i)
181+
for (size_t i = 0; i < runnableTasks.size(); ++i)
182182
{
183183
#if !defined(ESP32) && defined(ARDUINO)
184184
InterruptLock lock;
@@ -235,7 +235,7 @@ void CoopTaskBase::delistRunnable()
235235
{
236236
#if !defined(ESP32) && defined(ARDUINO)
237237
InterruptLock lock;
238-
for (size_t i = 0; i < CoopTaskBase::MAXNUMBERCOOPTASKS; ++i)
238+
for (size_t i = 0; i < runnableTasks.size(); ++i)
239239
{
240240
if (runnableTasks[i].load() == this)
241241
{
@@ -245,7 +245,7 @@ void CoopTaskBase::delistRunnable()
245245
}
246246
}
247247
#else
248-
for (size_t i = 0; i < CoopTaskBase::MAXNUMBERCOOPTASKS; ++i)
248+
for (size_t i = 0; i < runnableTasks.size(); ++i)
249249
{
250250
CoopTaskBase* self = this;
251251
if (runnableTasks[i].compare_exchange_strong(self, nullptr))
@@ -646,7 +646,7 @@ CoopTaskBase* CoopTaskBase::self() noexcept
646646
const auto currentTaskHandle = xTaskGetCurrentTaskHandle();
647647
auto cur = current;
648648
if (cur && currentTaskHandle == cur->taskHandle) return cur;
649-
for (size_t i = 0; i < CoopTaskBase::MAXNUMBERCOOPTASKS; ++i)
649+
for (size_t i = 0; i < runnableTasks.size(); ++i)
650650
{
651651
cur = runnableTasks[i].load();
652652
if (cur && currentTaskHandle == cur->taskHandle) return cur;
@@ -804,11 +804,11 @@ void CoopTaskBase::dumpStack() const
804804
#endif
805805
while (pos < (taskStackSize + (FULLFEATURES ? sizeof(STACKCOOKIE) : 0)) / sizeof(STACKCOOKIE))
806806
{
807+
#ifndef ARDUINO_attiny
807808
auto* sp = &reinterpret_cast<unsigned*>(taskStackTop)[pos];
808809

809810
// rough indicator: stack frames usually have SP saved as the second word
810811
bool looksLikeStackFrame = (sp[2] == reinterpret_cast<size_t>(&sp[4]));
811-
#ifndef ARDUINO_attiny
812812
::printf(PSTR("%08x: %08x %08x %08x %08x %c\n"),
813813
reinterpret_cast<size_t>(sp), sp[0], sp[1], sp[2], sp[3], looksLikeStackFrame ? '<' : ' ');
814814
#endif

src/CoopTaskBase.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,8 @@ class CoopTaskBase
101101
jmp_buf env_yield;
102102
#endif
103103
static constexpr size_t MAXNUMBERCOOPTASKS = FULLFEATURES ? 32 : 8;
104-
static std::array< std::atomic<CoopTaskBase* >, MAXNUMBERCOOPTASKS> runnableTasks;
104+
// for lock-free insertion, must be one element larger than max task count
105+
static std::array< std::atomic<CoopTaskBase* >, MAXNUMBERCOOPTASKS + 1> runnableTasks;
105106
static std::atomic<size_t> runnableTasksCount;
106107
static CoopTaskBase* current;
107108
bool init = false;
@@ -117,7 +118,7 @@ class CoopTaskBase
117118
static bool usingBuiltinScheduler;
118119
bool rescheduleTask(uint32_t repeat_us);
119120
#endif
120-
bool enrollRunnable();
121+
bool IRAM_ATTR enrollRunnable();
121122
void delistRunnable();
122123

123124
void _exit() noexcept;
@@ -190,7 +191,7 @@ class CoopTaskBase
190191
#endif
191192
/// Every task is entered into this list by scheduleTask(). It is removed when it exits
192193
/// or gets deleted.
193-
static const std::array< std::atomic<CoopTaskBase* >, MAXNUMBERCOOPTASKS>& getRunnableTasks()
194+
static const decltype(runnableTasks)& getRunnableTasks()
194195
{
195196
return runnableTasks;
196197
}

0 commit comments

Comments
 (0)