Skip to content

Commit

Permalink
IRAM attribute; small refactoring; runnableTasks array must be 1 elem…
Browse files Browse the repository at this point in the history
…ent larger than max task #
  • Loading branch information
dok-net committed Apr 22, 2021
1 parent 61cf7fe commit 318e5b5
Show file tree
Hide file tree
Showing 7 changed files with 35 additions and 26 deletions.
16 changes: 15 additions & 1 deletion examples/Callbacks/Callbacks.ino
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@
#include <CoopMutex.h>
#include <BasicCoopTask.h>

#if defined(ARDUINO_attiny)
#define LED_BUILTIN 1

struct DummySerial {
void print(const __FlashStringHelper* s = nullptr) {}
void println(const __FlashStringHelper* s = nullptr) {}
void println(long unsigned int) {}
void flush() {}
};
DummySerial Serial;
#endif

CoopTask<void>* blinkTask = nullptr;
CoopTask<void>* switchTask = nullptr;

Expand Down Expand Up @@ -53,11 +65,13 @@ bool sleepCb()

void setup()
{
#if !defined(ARDUINO_attiny)
Serial.begin(74800);
while (!Serial);
delay(100);
Serial.println();
Serial.println(F("runTasks callback test"));
#endif

runCoopTasks(nullptr, delayCb, sleepCb);
Serial.println(F("no tasks yet, sleepCb()?"));
Expand All @@ -78,7 +92,7 @@ void loop()
Serial.println(F("B - both tasks delayed, delayCb(100)?"));
yield();
runCoopTasks(nullptr, delayCb, sleepCb);
Serial.println(F("C - blink task delayed, buzzer task sleeping, delayCb(4900)?"));
Serial.println(F("C - blink task delayed, switch task sleeping, delayCb(4900)?"));
yield();
runCoopTasks(nullptr, delayCb, sleepCb);
Serial.println(F("D - both tasks sleeping, sleepCb()?"));
Expand Down
2 changes: 1 addition & 1 deletion library.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "CoopTask",
"version": "3.6.0",
"version": "3.6.1",
"keywords": [
"multitasking", "timing"
],
Expand Down
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name=CoopTask
version=3.6.0
version=3.6.1
author=Dirk O. Kaar
maintainer=Dirk O. Kaar <[email protected]>
sentence=Portable C++ library for cooperative multitasking like Arduino Scheduler on ESP8266/ESP32, AVR, Linux, Windows
Expand Down
4 changes: 2 additions & 2 deletions src/BasicCoopTask.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,10 @@ template<class StackAllocator = CoopTaskStackAllocator> class BasicCoopTask : pu
}
/// Every task is entered into this list by scheduleTask(). It is removed when it exits
/// or gets deleted.
static const std::array< std::atomic<BasicCoopTask* >, MAXNUMBERCOOPTASKS>& getRunnableTasks()
static const std::array< std::atomic<BasicCoopTask* >, MAXNUMBERCOOPTASKS + 1>& getRunnableTasks()
{
// this is safe to do because CoopTaskBase ctor is protected.
return reinterpret_cast<const std::array< std::atomic<BasicCoopTask* >, MAXNUMBERCOOPTASKS>&>(CoopTaskBase::getRunnableTasks());
return reinterpret_cast<const std::array< std::atomic<BasicCoopTask* >, MAXNUMBERCOOPTASKS + 1>&>(CoopTaskBase::getRunnableTasks());
}
protected:
StackAllocator stackAllocator;
Expand Down
16 changes: 5 additions & 11 deletions src/CoopSemaphore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,21 +127,18 @@ bool CoopSemaphore::_wait(const bool withDeadline, const uint32_t ms)
}
if (selfFirst)
{
if (!withDeadline) self->sleep(false);
selfFirst = false;
if (!withDeadline) self->sleep(false);
selfSuccess = true;
}
else if (pendingTask == self)
{
if (selfSuccess)
{
if (!stop) continue;
}
else
if (!selfSuccess)
{
if (!withDeadline) self->sleep(false);
return true;
}
if (!stop) continue;
}
else if (pendingTask)
{
Expand Down Expand Up @@ -213,11 +210,8 @@ bool IRAM_ATTR CoopSemaphore::post()
while (!value.compare_exchange_weak(val, val + 1)) {}
pendingTask = pendingTask0.exchange(nullptr);
#endif
if (pendingTask)
{
pendingTask->scheduleTask(true);
}
return true;
if (!pendingTask || !pendingTask->suspended()) return true;
return pendingTask->scheduleTask(true);
}

bool CoopSemaphore::setval(unsigned newVal)
Expand Down
14 changes: 7 additions & 7 deletions src/CoopTaskBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ extern "C" {
#endif // ESP32_FREERTOS
}

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

CoopTaskBase* CoopTaskBase::current = nullptr;
Expand Down Expand Up @@ -174,11 +174,11 @@ bool CoopTaskBase::rescheduleTask(uint32_t repeat_us)
}
#endif

bool CoopTaskBase::enrollRunnable()
bool IRAM_ATTR CoopTaskBase::enrollRunnable()
{
bool enrolled = false;
bool inserted = false;
for (size_t i = 0; i < CoopTaskBase::MAXNUMBERCOOPTASKS; ++i)
for (size_t i = 0; i < runnableTasks.size(); ++i)
{
#if !defined(ESP32) && defined(ARDUINO)
InterruptLock lock;
Expand Down Expand Up @@ -235,7 +235,7 @@ void CoopTaskBase::delistRunnable()
{
#if !defined(ESP32) && defined(ARDUINO)
InterruptLock lock;
for (size_t i = 0; i < CoopTaskBase::MAXNUMBERCOOPTASKS; ++i)
for (size_t i = 0; i < runnableTasks.size(); ++i)
{
if (runnableTasks[i].load() == this)
{
Expand All @@ -245,7 +245,7 @@ void CoopTaskBase::delistRunnable()
}
}
#else
for (size_t i = 0; i < CoopTaskBase::MAXNUMBERCOOPTASKS; ++i)
for (size_t i = 0; i < runnableTasks.size(); ++i)
{
CoopTaskBase* self = this;
if (runnableTasks[i].compare_exchange_strong(self, nullptr))
Expand Down Expand Up @@ -646,7 +646,7 @@ CoopTaskBase* CoopTaskBase::self() noexcept
const auto currentTaskHandle = xTaskGetCurrentTaskHandle();
auto cur = current;
if (cur && currentTaskHandle == cur->taskHandle) return cur;
for (size_t i = 0; i < CoopTaskBase::MAXNUMBERCOOPTASKS; ++i)
for (size_t i = 0; i < runnableTasks.size(); ++i)
{
cur = runnableTasks[i].load();
if (cur && currentTaskHandle == cur->taskHandle) return cur;
Expand Down Expand Up @@ -804,11 +804,11 @@ void CoopTaskBase::dumpStack() const
#endif
while (pos < (taskStackSize + (FULLFEATURES ? sizeof(STACKCOOKIE) : 0)) / sizeof(STACKCOOKIE))
{
#ifndef ARDUINO_attiny
auto* sp = &reinterpret_cast<unsigned*>(taskStackTop)[pos];

// rough indicator: stack frames usually have SP saved as the second word
bool looksLikeStackFrame = (sp[2] == reinterpret_cast<size_t>(&sp[4]));
#ifndef ARDUINO_attiny
::printf(PSTR("%08x: %08x %08x %08x %08x %c\n"),
reinterpret_cast<size_t>(sp), sp[0], sp[1], sp[2], sp[3], looksLikeStackFrame ? '<' : ' ');
#endif
Expand Down
7 changes: 4 additions & 3 deletions src/CoopTaskBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ class CoopTaskBase
jmp_buf env_yield;
#endif
static constexpr size_t MAXNUMBERCOOPTASKS = FULLFEATURES ? 32 : 8;
static std::array< std::atomic<CoopTaskBase* >, MAXNUMBERCOOPTASKS> runnableTasks;
// for lock-free insertion, must be one element larger than max task count
static std::array< std::atomic<CoopTaskBase* >, MAXNUMBERCOOPTASKS + 1> runnableTasks;
static std::atomic<size_t> runnableTasksCount;
static CoopTaskBase* current;
bool init = false;
Expand All @@ -117,7 +118,7 @@ class CoopTaskBase
static bool usingBuiltinScheduler;
bool rescheduleTask(uint32_t repeat_us);
#endif
bool enrollRunnable();
bool IRAM_ATTR enrollRunnable();
void delistRunnable();

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

0 comments on commit 318e5b5

Please sign in to comment.