From 1d9def9edae0011eeee8f83dc32fb3797ca2f46b Mon Sep 17 00:00:00 2001 From: Pixel Date: Fri, 7 Oct 2011 15:36:12 -0700 Subject: More work in the Task manager. Also fixing a few bugs linked with the printer and TLS. Removed flto from compilation flags: this actually creates bad code (!) --- Makefile | 11 +++++++---- includes/Local.h | 4 ++-- includes/Printer.h | 8 +++++--- includes/Task.h | 4 ++-- includes/TaskMan.h | 13 ++++++++++++- src/Printer.cc | 19 ++++++++++++++++--- src/Task.cc | 9 ++++++++- src/TaskMan.cc | 48 +++++++++++++++++++++++++++++++++++++++++++++++- tests/test-Tasks.cc | 20 ++++++++++++++++++++ 9 files changed, 119 insertions(+), 17 deletions(-) diff --git a/Makefile b/Makefile index 79ed4c7..62c0920 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,12 @@ LD = g++ AS = gcc -c AR = ar rcs -CPPFLAGS = -O3 +ifeq ($(DEBUG),) +CPPFLAGS += -O3 +else +CPPFLAGS += -g +LDFLAGS += -g +endif ifeq ($(SYSTEM),Darwin) LIBCORO_CFLAGS = -DCORO_SJLJ @@ -32,13 +37,11 @@ else ARCH_FLAGS = -march=i686 -m32 ASFLAGS = -march=i686 --32 STRIP = strip --strip-unneeded - CPPFLAGS += -flto - LDFLAGS += -flto -O3 endif INCLUDES = -Iincludes -Ilibcoro -CPPFLAGS_NO_ARCH += $(INCLUDES) -g -DSTDC_HEADERS -fexceptions -DWORDS_LITTLEENDIAN $(HAVES) $(LIBCORO_CFLAGS) +CPPFLAGS_NO_ARCH += $(INCLUDES) -DSTDC_HEADERS -fexceptions -DWORDS_LITTLEENDIAN $(HAVES) $(LIBCORO_CFLAGS) -Wno-deprecated CPPFLAGS += $(CPPFLAGS_NO_ARCH) $(ARCH_FLAGS) LDFLAGS += $(ARCH_FLAGS) $(LIBS) diff --git a/includes/Local.h b/includes/Local.h index a3405ca..e3d08a4 100644 --- a/includes/Local.h +++ b/includes/Local.h @@ -23,10 +23,10 @@ class Local : public AtStart { void * get() { if (getTLS()) { void * l = getLocal(); return l ? l : getGlobal(); } else return getGlobal(); } void setGlobal(void * obj) { m_globals[m_idx] = obj; } void setLocal(void * obj) { void * r = getTLS(); reinterpret_cast(r)[m_idx] = obj; } - void set(void * obj) { void * r = getTLS(); if (r) setGlobal(obj); else setLocal(obj); } + void set(void * obj) { void * r = getTLS(); if (r) setLocal(obj); else setGlobal(obj); } int getIndex() { return m_idx; } private: - static void * create() { void * r = malloc(s_size * sizeof(void *)); setTLS(r); return r; } + static void * create() { void * r = malloc(s_size * sizeof(void *)); return r; } static void * getTLS() { return tlsManager->getTLS(); } static void * setTLS(void * val) { return tlsManager->setTLS(val); } virtual void doStart(); diff --git a/includes/Printer.h b/includes/Printer.h index b55df22..20b3b6c 100644 --- a/includes/Printer.h +++ b/includes/Printer.h @@ -1,5 +1,6 @@ #pragma once +#include #include namespace Balau { @@ -21,14 +22,15 @@ class Printer { virtual void _print(const char * fmt, va_list ap); private: + void _print(const char * fmt, ...); void _log(uint32_t level, const char * fmt, va_list ap); - static Printer * getPrinter(); public: Printer(); void setLocal(); + static Printer * getPrinter(); static void log(uint32_t level, const String & fmt, ...) { va_list ap; va_start(ap, fmt); log(level, fmt.to_charp(), ap); va_end(ap); } static void log(uint32_t level, const char * fmt, ...) { va_list ap; va_start(ap, fmt); log(level, fmt, ap); va_end(ap); } static void log(uint32_t level, const char * fmt, va_list ap) { getPrinter()->_log(level, fmt, ap); } @@ -36,8 +38,8 @@ class Printer { static void print(const char * fmt, ...) { va_list ap; va_start(ap, fmt); print(fmt, ap); va_end(ap); } static void print(const char * fmt, va_list ap) { getPrinter()->_print(fmt, ap); } - void enable(uint32_t levels = M_ALL) { m_verbosity |= levels; } - void disable(uint32_t levels = M_ALL) { m_verbosity &= ~levels; } + static void enable(uint32_t levels = M_ALL) { getPrinter()->m_verbosity |= levels; } + static void disable(uint32_t levels = M_ALL) { getPrinter()->m_verbosity &= ~levels; } uint32_t m_verbosity; }; diff --git a/includes/Task.h b/includes/Task.h index 314532b..fb210a2 100644 --- a/includes/Task.h +++ b/includes/Task.h @@ -17,12 +17,12 @@ class Task { FAULTED, }; Task(); - ~Task() { free(stack); free(tls); } - virtual void Do() = 0; + virtual ~Task(); virtual const char * getName() = 0; Status getStatus() { return status; } protected: void suspend(); + virtual void Do() = 0; private: size_t stackSize() { return 128 * 1024; } void switchTo(); diff --git a/includes/TaskMan.h b/includes/TaskMan.h index 05e5fa8..ac95f71 100644 --- a/includes/TaskMan.h +++ b/includes/TaskMan.h @@ -1,6 +1,10 @@ #pragma once #include +#include +#include + +namespace gnu = __gnu_cxx; namespace Balau { @@ -11,11 +15,18 @@ class TaskMan { TaskMan(); ~TaskMan(); void mainLoop(); + void stop() { stopped = true; } + static TaskMan * getTaskMan(); private: - static TaskMan * getTaskMan(); + void registerTask(Task * t); + void unregisterTask(Task * t); coro_context returnContext; friend class Task; + struct taskHash { size_t operator()(const Task * t) const { return reinterpret_cast(t); } }; + typedef gnu::hash_set taskList; + taskList tasks, pendingAdd; + volatile bool stopped; }; }; diff --git a/src/Printer.cc b/src/Printer.cc index cb94084..ef0cbf5 100644 --- a/src/Printer.cc +++ b/src/Printer.cc @@ -19,6 +19,10 @@ Balau::Printer::Printer() : m_verbosity(M_STATUS | M_WARNING | M_ERROR) { localPrinter.setGlobal(this); } +void Balau::Printer::setLocal() { + localPrinter.set(this); +} + Balau::Printer * Balau::Printer::getPrinter() { return localPrinter.get(); } void Balau::Printer::_log(uint32_t level, const char * fmt, va_list ap) { @@ -31,11 +35,20 @@ void Balau::Printer::_log(uint32_t level, const char * fmt, va_list ap) { if (l & level) break; - print(prefixes[i]); - print(fmt, ap); - print("\n"); + Printer * printer = getPrinter(); + + printer->_print(prefixes[i]); + printer->_print(fmt, ap); + printer->_print("\n"); } void Balau::Printer::_print(const char * fmt, va_list ap) { vfprintf(stderr, fmt, ap); } + +void Balau::Printer::_print(const char * fmt, ...) { + va_list ap; + va_start(ap, fmt); + _print(fmt, ap); + va_end(ap); +} diff --git a/src/Task.cc b/src/Task.cc index d41f088..9bdad0c 100644 --- a/src/Task.cc +++ b/src/Task.cc @@ -9,10 +9,16 @@ Balau::Task::Task() { stack = malloc(size); coro_create(&ctx, coroutine, this, stack, size); taskMan = TaskMan::getTaskMan(); + taskMan->registerTask(this); tls = tlsManager->createTLS(); status = STARTING; } +Balau::Task::~Task() { + free(stack); + free(tls); +} + void Balau::Task::coroutine(void * arg) { Task * task = reinterpret_cast(arg); Assert(task); @@ -38,7 +44,8 @@ void Balau::Task::switchTo() { tlsManager->setTLS(tls); coro_transfer(&taskMan->returnContext, &ctx); tlsManager->setTLS(oldTLS); - status = IDLE; + if (status == RUNNING) + status = IDLE; } void Balau::Task::suspend() { diff --git a/src/TaskMan.cc b/src/TaskMan.cc index 783c683..bbaf35c 100644 --- a/src/TaskMan.cc +++ b/src/TaskMan.cc @@ -1,11 +1,12 @@ #include "TaskMan.h" +#include "Task.h" #include "Main.h" #include "Local.h" static Balau::DefaultTmpl defaultTaskMan(50); static Balau::LocalTmpl localTaskMan; -Balau::TaskMan::TaskMan() { +Balau::TaskMan::TaskMan() : stopped(false) { coro_create(&returnContext, 0, 0, 0, 0); if (!localTaskMan.getGlobal()) localTaskMan.setGlobal(this); @@ -18,4 +19,49 @@ Balau::TaskMan::~TaskMan() { } void Balau::TaskMan::mainLoop() { + // We need at least one round before bailing :) + do { + taskList::iterator i; + Task * t; + + // lock pending + // Adding tasks that were added, maybe from other threads + for (i = pendingAdd.begin(); i != pendingAdd.end(); i++) { + Assert(tasks.find(*i) == tasks.end()); + tasks.insert(*i); + } + pendingAdd.clear(); + // unlock pending + + // checking "STARTING" tasks, and running them once + for (i = tasks.begin(); i != tasks.end(); i++) { + t = *i; + if (t->getStatus() == Task::STARTING) { + t->switchTo(); + } + } + + // That's probably where we poll for events + + // checking "STOPPED" tasks, and destroying them + bool didDelete; + do { + didDelete = false; + for (i = tasks.begin(); i != tasks.end(); i++) { + t = *i; + if ((t->getStatus() == Task::STOPPED) || (t->getStatus() == Task::FAULTED)) { + delete t; + tasks.erase(i); + didDelete = true; + break; + } + } + } while (didDelete); + } while (!stopped && tasks.size() != 0); +} + +void Balau::TaskMan::registerTask(Balau::Task * t) { + // lock pending + pendingAdd.insert(t); + // unlock pending } diff --git a/tests/test-Tasks.cc b/tests/test-Tasks.cc index bb7c795..2eedb47 100644 --- a/tests/test-Tasks.cc +++ b/tests/test-Tasks.cc @@ -6,8 +6,28 @@ BALAU_STARTUP; using namespace Balau; +class CustomPrinter : public Printer { +}; + +static CustomPrinter * customPrinter = NULL; + +class MainTask : public Task { + public: + virtual const char * getName() { return "MainTask"; } + private: + virtual void Do() { + customPrinter->setLocal(); + Printer::enable(M_ALL); + Printer::log(M_DEBUG, "In MainTask::Do()"); + } +}; + int Application::startup() throw (Balau::GeneralException) { + customPrinter = new CustomPrinter(); Printer::log(M_STATUS, "Test::Tasks running."); + Task * mainTask = new MainTask(); + TaskMan::getTaskMan()->mainLoop(); Printer::log(M_STATUS, "Test::Tasks passed."); + Printer::log(M_DEBUG, "You shouldn't see that message."); return 0; } -- cgit v1.2.3