task.h 2.09 KB
Newer Older
1 2
#ifndef PLS_TASK_H
#define PLS_TASK_H
3

4
#include <utility>
5
#include <atomic>
6

7 8 9 10
#include "context_switcher/continuation.h"
#include "context_switcher/context_switcher.h"

#include "pls/internal/base/system_details.h"
11
#include "pls/internal/data_structures/stamped_integer.h"
12 13
#include "pls/internal/scheduling/traded_cas_field.h"

14 15 16 17
namespace pls {
namespace internal {
namespace scheduling {

18
/**
19 20 21 22 23
 * A task is the smallest unit of execution seen by the runtime system.
 *
 * Tasks represent a action dispatched by a potentially parallel call.
 * Tasks have their own execution context (stack and register state), making them stackefull coroutines.
 * Tasks can be suspended and resumed (stealing happens by resuming a task).
24
 *
25 26 27 28
 * Being coroutines tasks go through a very deliberate state machine:
 * - initialized (no execution state)
 * - running (currently executing user code)
 * - suspended (suspended by switching to a different task).
29
 */
30 31 32 33 34 35 36
struct alignas(base::system_details::CACHE_LINE_SIZE) task {
  void init(char *stack_memory, size_t stack_size, unsigned depth, unsigned thread_id) {
    stack_memory_ = stack_memory;
    stack_size_ = stack_size;

    depth_ = depth;
    thread_id_ = thread_id;
37 38

    is_synchronized_ = false;
39
  }
40

41 42 43
  template<typename F>
  context_switcher::continuation run_as_task(F &&lambda) {
    return context_switcher::enter_context(stack_memory_, stack_size_, std::forward<F>(lambda));
44 45
  }

46
  // TODO: Proper access control and split it up into responsibilities
47 48
  // Stack/Continuation Management
  char *stack_memory_;
49
  size_t stack_size_; // TODO: maybe remove it, not needed in here
50
  context_switcher::continuation continuation_;
51
  bool is_synchronized_;
52

53
  // TODO: Clean up responsibilities
54
  // Work-Stealing
55
  std::atomic<traded_cas_field> external_trading_deque_cas_{};
56
  std::atomic<task *> resource_stack_next_{};
57
  std::atomic<data_structures::stamped_integer> resource_stack_root_{{0, 0}};
58

59 60 61
  // Task Tree (we have a parent that we want to continue when we finish)
  unsigned depth_;
  unsigned thread_id_;
62

63 64 65
  // Memory Linked List
  task *prev_;
  task *next_;
66 67 68 69 70 71
};

}
}
}

72
#endif //PLS_TASK_H