summaryrefslogtreecommitdiff
path: root/thirdparty/embree-aarch64/common/tasking/taskschedulerinternal.h
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/embree-aarch64/common/tasking/taskschedulerinternal.h')
-rw-r--r--thirdparty/embree-aarch64/common/tasking/taskschedulerinternal.h386
1 files changed, 0 insertions, 386 deletions
diff --git a/thirdparty/embree-aarch64/common/tasking/taskschedulerinternal.h b/thirdparty/embree-aarch64/common/tasking/taskschedulerinternal.h
deleted file mode 100644
index 8bd70b2b8c..0000000000
--- a/thirdparty/embree-aarch64/common/tasking/taskschedulerinternal.h
+++ /dev/null
@@ -1,386 +0,0 @@
-// Copyright 2009-2020 Intel Corporation
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "../sys/platform.h"
-#include "../sys/alloc.h"
-#include "../sys/barrier.h"
-#include "../sys/thread.h"
-#include "../sys/mutex.h"
-#include "../sys/condition.h"
-#include "../sys/ref.h"
-#include "../sys/atomic.h"
-#include "../math/range.h"
-#include "../../include/embree3/rtcore.h"
-
-#include <list>
-
-namespace embree
-{
-
- /* The tasking system exports some symbols to be used by the tutorials. Thus we
- hide is also in the API namespace when requested. */
- RTC_NAMESPACE_BEGIN
-
- struct TaskScheduler : public RefCount
- {
- ALIGNED_STRUCT_(64);
- friend class Device;
-
- static const size_t TASK_STACK_SIZE = 4*1024; //!< task structure stack
- static const size_t CLOSURE_STACK_SIZE = 512*1024; //!< stack for task closures
-
- struct Thread;
-
- /*! virtual interface for all tasks */
- struct TaskFunction {
- virtual void execute() = 0;
- };
-
- /*! builds a task interface from a closure */
- template<typename Closure>
- struct ClosureTaskFunction : public TaskFunction
- {
- Closure closure;
- __forceinline ClosureTaskFunction (const Closure& closure) : closure(closure) {}
- void execute() { closure(); };
- };
-
- struct __aligned(64) Task
- {
- /*! states a task can be in */
- enum { DONE, INITIALIZED };
-
- /*! switch from one state to another */
- __forceinline void switch_state(int from, int to)
- {
- __memory_barrier();
- MAYBE_UNUSED bool success = state.compare_exchange_strong(from,to);
- assert(success);
- }
-
- /*! try to switch from one state to another */
- __forceinline bool try_switch_state(int from, int to) {
- __memory_barrier();
- return state.compare_exchange_strong(from,to);
- }
-
- /*! increment/decrement dependency counter */
- void add_dependencies(int n) {
- dependencies+=n;
- }
-
- /*! initialize all tasks to DONE state by default */
- __forceinline Task()
- : state(DONE) {}
-
- /*! construction of new task */
- __forceinline Task (TaskFunction* closure, Task* parent, size_t stackPtr, size_t N)
- : dependencies(1), stealable(true), closure(closure), parent(parent), stackPtr(stackPtr), N(N)
- {
- if (parent) parent->add_dependencies(+1);
- switch_state(DONE,INITIALIZED);
- }
-
- /*! construction of stolen task, stealing thread will decrement initial dependency */
- __forceinline Task (TaskFunction* closure, Task* parent)
- : dependencies(1), stealable(false), closure(closure), parent(parent), stackPtr(-1), N(1)
- {
- switch_state(DONE,INITIALIZED);
- }
-
- /*! try to steal this task */
- bool try_steal(Task& child)
- {
- if (!stealable) return false;
- if (!try_switch_state(INITIALIZED,DONE)) return false;
- new (&child) Task(closure, this);
- return true;
- }
-
- /*! run this task */
- dll_export void run(Thread& thread);
-
- void run_internal(Thread& thread);
-
- public:
- std::atomic<int> state; //!< state this task is in
- std::atomic<int> dependencies; //!< dependencies to wait for
- std::atomic<bool> stealable; //!< true if task can be stolen
- TaskFunction* closure; //!< the closure to execute
- Task* parent; //!< parent task to signal when we are finished
- size_t stackPtr; //!< stack location where closure is stored
- size_t N; //!< approximative size of task
- };
-
- struct TaskQueue
- {
- TaskQueue ()
- : left(0), right(0), stackPtr(0) {}
-
- __forceinline void* alloc(size_t bytes, size_t align = 64)
- {
- size_t ofs = bytes + ((align - stackPtr) & (align-1));
- if (stackPtr + ofs > CLOSURE_STACK_SIZE)
- // -- GODOT start --
- // throw std::runtime_error("closure stack overflow");
- abort();
- // -- GODOT end --
- stackPtr += ofs;
- return &stack[stackPtr-bytes];
- }
-
- template<typename Closure>
- __forceinline void push_right(Thread& thread, const size_t size, const Closure& closure)
- {
- if (right >= TASK_STACK_SIZE)
- // -- GODOT start --
- // throw std::runtime_error("task stack overflow");
- abort();
- // -- GODOT end --
-
- /* allocate new task on right side of stack */
- size_t oldStackPtr = stackPtr;
- TaskFunction* func = new (alloc(sizeof(ClosureTaskFunction<Closure>))) ClosureTaskFunction<Closure>(closure);
- /* gcc 8 or later fails to compile without explicit .load() */
- new (&(tasks[right.load()])) Task(func,thread.task,oldStackPtr,size);
- right++;
-
- /* also move left pointer */
- if (left >= right-1) left = right-1;
- }
-
- dll_export bool execute_local(Thread& thread, Task* parent);
- bool execute_local_internal(Thread& thread, Task* parent);
- bool steal(Thread& thread);
- size_t getTaskSizeAtLeft();
-
- bool empty() { return right == 0; }
-
- public:
-
- /* task stack */
- Task tasks[TASK_STACK_SIZE];
- __aligned(64) std::atomic<size_t> left; //!< threads steal from left
- __aligned(64) std::atomic<size_t> right; //!< new tasks are added to the right
-
- /* closure stack */
- __aligned(64) char stack[CLOSURE_STACK_SIZE];
- size_t stackPtr;
- };
-
- /*! thread local structure for each thread */
- struct Thread
- {
- ALIGNED_STRUCT_(64);
-
- Thread (size_t threadIndex, const Ref<TaskScheduler>& scheduler)
- : threadIndex(threadIndex), task(nullptr), scheduler(scheduler) {}
-
- __forceinline size_t threadCount() {
- return scheduler->threadCounter;
- }
-
- size_t threadIndex; //!< ID of this thread
- TaskQueue tasks; //!< local task queue
- Task* task; //!< current active task
- Ref<TaskScheduler> scheduler; //!< pointer to task scheduler
- };
-
- /*! pool of worker threads */
- struct ThreadPool
- {
- ThreadPool (bool set_affinity);
- ~ThreadPool ();
-
- /*! starts the threads */
- dll_export void startThreads();
-
- /*! sets number of threads to use */
- void setNumThreads(size_t numThreads, bool startThreads = false);
-
- /*! adds a task scheduler object for scheduling */
- dll_export void add(const Ref<TaskScheduler>& scheduler);
-
- /*! remove the task scheduler object again */
- dll_export void remove(const Ref<TaskScheduler>& scheduler);
-
- /*! returns number of threads of the thread pool */
- size_t size() const { return numThreads; }
-
- /*! main loop for all threads */
- void thread_loop(size_t threadIndex);
-
- private:
- std::atomic<size_t> numThreads;
- std::atomic<size_t> numThreadsRunning;
- bool set_affinity;
- std::atomic<bool> running;
- std::vector<thread_t> threads;
-
- private:
- MutexSys mutex;
- ConditionSys condition;
- std::list<Ref<TaskScheduler> > schedulers;
- };
-
- TaskScheduler ();
- ~TaskScheduler ();
-
- /*! initializes the task scheduler */
- static void create(size_t numThreads, bool set_affinity, bool start_threads);
-
- /*! destroys the task scheduler again */
- static void destroy();
-
- /*! lets new worker threads join the tasking system */
- void join();
- void reset();
-
- /*! let a worker thread allocate a thread index */
- dll_export ssize_t allocThreadIndex();
-
- /*! wait for some number of threads available (threadCount includes main thread) */
- void wait_for_threads(size_t threadCount);
-
- /*! thread loop for all worker threads */
- // -- GODOT start --
- // std::exception_ptr thread_loop(size_t threadIndex);
- void thread_loop(size_t threadIndex);
- // -- GODOT end --
-
- /*! steals a task from a different thread */
- bool steal_from_other_threads(Thread& thread);
-
- template<typename Predicate, typename Body>
- static void steal_loop(Thread& thread, const Predicate& pred, const Body& body);
-
- /* spawn a new task at the top of the threads task stack */
- template<typename Closure>
- void spawn_root(const Closure& closure, size_t size = 1, bool useThreadPool = true)
- {
- if (useThreadPool) startThreads();
-
- size_t threadIndex = allocThreadIndex();
- std::unique_ptr<Thread> mthread(new Thread(threadIndex,this)); // too large for stack allocation
- Thread& thread = *mthread;
- assert(threadLocal[threadIndex].load() == nullptr);
- threadLocal[threadIndex] = &thread;
- Thread* oldThread = swapThread(&thread);
- thread.tasks.push_right(thread,size,closure);
- {
- Lock<MutexSys> lock(mutex);
- anyTasksRunning++;
- hasRootTask = true;
- condition.notify_all();
- }
-
- if (useThreadPool) addScheduler(this);
-
- while (thread.tasks.execute_local(thread,nullptr));
- anyTasksRunning--;
- if (useThreadPool) removeScheduler(this);
-
- threadLocal[threadIndex] = nullptr;
- swapThread(oldThread);
-
- /* remember exception to throw */
- std::exception_ptr except = nullptr;
- if (cancellingException != nullptr) except = cancellingException;
-
- /* wait for all threads to terminate */
- threadCounter--;
- while (threadCounter > 0) yield();
- cancellingException = nullptr;
-
- /* re-throw proper exception */
- if (except != nullptr)
- std::rethrow_exception(except);
- }
-
- /* spawn a new task at the top of the threads task stack */
- template<typename Closure>
- static __forceinline void spawn(size_t size, const Closure& closure)
- {
- Thread* thread = TaskScheduler::thread();
- if (likely(thread != nullptr)) thread->tasks.push_right(*thread,size,closure);
- else instance()->spawn_root(closure,size);
- }
-
- /* spawn a new task at the top of the threads task stack */
- template<typename Closure>
- static __forceinline void spawn(const Closure& closure) {
- spawn(1,closure);
- }
-
- /* spawn a new task set */
- template<typename Index, typename Closure>
- static void spawn(const Index begin, const Index end, const Index blockSize, const Closure& closure)
- {
- spawn(end-begin, [=]()
- {
- if (end-begin <= blockSize) {
- return closure(range<Index>(begin,end));
- }
- const Index center = (begin+end)/2;
- spawn(begin,center,blockSize,closure);
- spawn(center,end ,blockSize,closure);
- wait();
- });
- }
-
- /* work on spawned subtasks and wait until all have finished */
- dll_export static bool wait();
-
- /* returns the ID of the current thread */
- dll_export static size_t threadID();
-
- /* returns the index (0..threadCount-1) of the current thread */
- dll_export static size_t threadIndex();
-
- /* returns the total number of threads */
- dll_export static size_t threadCount();
-
- private:
-
- /* returns the thread local task list of this worker thread */
- dll_export static Thread* thread();
-
- /* sets the thread local task list of this worker thread */
- dll_export static Thread* swapThread(Thread* thread);
-
- /*! returns the taskscheduler object to be used by the master thread */
- dll_export static TaskScheduler* instance();
-
- /*! starts the threads */
- dll_export static void startThreads();
-
- /*! adds a task scheduler object for scheduling */
- dll_export static void addScheduler(const Ref<TaskScheduler>& scheduler);
-
- /*! remove the task scheduler object again */
- dll_export static void removeScheduler(const Ref<TaskScheduler>& scheduler);
-
- private:
- std::vector<atomic<Thread*>> threadLocal;
- std::atomic<size_t> threadCounter;
- std::atomic<size_t> anyTasksRunning;
- std::atomic<bool> hasRootTask;
- std::exception_ptr cancellingException;
- MutexSys mutex;
- ConditionSys condition;
-
- private:
- static size_t g_numThreads;
- static __thread TaskScheduler* g_instance;
- static __thread Thread* thread_local_thread;
- static ThreadPool* threadPool;
- };
-
- RTC_NAMESPACE_END
-
-#if defined(RTC_NAMESPACE)
- using RTC_NAMESPACE::TaskScheduler;
-#endif
-}