summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPixel <pixel@nobis-crew.org>2011-10-07 15:36:12 -0700
committerPixel <pixel@nobis-crew.org>2011-10-07 15:36:12 -0700
commit1d9def9edae0011eeee8f83dc32fb3797ca2f46b (patch)
tree29077945287dd4b0c13269b9f3e5dc97936551f9
parent5a283e5b2b523d53e3504292c386b534dc74386a (diff)
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 (!)
-rw-r--r--Makefile11
-rw-r--r--includes/Local.h4
-rw-r--r--includes/Printer.h8
-rw-r--r--includes/Task.h4
-rw-r--r--includes/TaskMan.h13
-rw-r--r--src/Printer.cc19
-rw-r--r--src/Task.cc9
-rw-r--r--src/TaskMan.cc48
-rw-r--r--tests/test-Tasks.cc20
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<void **>(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 <stdarg.h>
#include <BString.h>
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 <coro.h>
+#include <ext/hash_set>
+#include <stdint.h>
+
+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<uintptr_t>(t); } };
+ typedef gnu::hash_set<Task *, taskHash> 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<Task *>(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<Balau::TaskMan> defaultTaskMan(50);
static Balau::LocalTmpl<Balau::TaskMan> 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;
}