28 #include "memory/allocation.hpp"
29 #include "memory/padded.hpp"
30 #include "runtime/mutex.hpp"
31
32 class TaskQueueSetSuper;
33 class TerminatorTerminator;
34 class Thread;
35
36 /*
37 * Provides a task termination protocol.
38 *
39 * This is an enhanced implementation of Google's OWST work stealing task termination
40 * protocol (OWST stands for Optimized Work Stealing Threads).
41 *
42 * It is described in the paper:
43 * "Wessam Hassanein. 2016. Understanding and improving JVM GC work
44 * stealing at the data center scale. In Proceedings of the 2016 ACM
45 * SIGPLAN International Symposium on Memory Management (ISMM 2016). ACM,
46 * New York, NY, USA, 46-54. DOI: https://doi.org/10.1145/2926697.2926706"
47 *
48 * Instead of a dedicated spin-master, our implementation will let spin-master relinquish
49 * the role before it goes to sleep/wait, allowing newly arrived threads to compete for the role.
50 * The intention of above enhancement is to reduce spin-master's latency on detecting new tasks
51 * for stealing and termination condition.
52 */
53 class TaskTerminator : public CHeapObj<mtGC> {
54 struct DelayContext {
55 uint _yield_count;
56 // Number of hard spin loops done since last yield
57 uint _hard_spin_count;
58 // Number of iterations in the hard spin loop.
59 uint _hard_spin_limit;
60
61 DelayContext();
62 };
63
64 uint _n_threads;
65 TaskQueueSetSuper* _queue_set;
66
67 DEFINE_PAD_MINUS_SIZE(0, DEFAULT_CACHE_LINE_SIZE, 0);
68 volatile uint _offered_termination;
69 DEFINE_PAD_MINUS_SIZE(1, DEFAULT_CACHE_LINE_SIZE, sizeof(volatile uint));
70
71 void assert_queue_set_empty() const NOT_DEBUG_RETURN;
72
73 Monitor _blocker;
74 Thread* _spin_master;
75
76 // Prepare for return from offer_termination. Gives up the spin master token
77 // and wakes up up to tasks threads waiting on _blocker (the default value
78 // means to wake up everyone).
79 void prepare_for_return(Thread* this_thread, size_t tasks = SIZE_MAX);
80
81 // If we should exit current termination protocol
82 bool exit_termination(size_t tasks, TerminatorTerminator* terminator);
83
84 size_t tasks_in_queue_set() const;
85
86 // Perform one iteration of spin-master work.
87 bool do_delay_step(DelayContext& delay_context);
88
89 NONCOPYABLE(TaskTerminator);
90
91 public:
92 TaskTerminator(uint n_threads, TaskQueueSetSuper* queue_set);
93 ~TaskTerminator();
94
95 // The current thread has no work, and is ready to terminate if everyone
96 // else is. If returns "true", all threads are terminated. If returns
97 // "false", available work has been observed in one of the task queues,
98 // so the global task is not complete.
99 bool offer_termination() {
100 return offer_termination(NULL);
101 }
102
103 // As above, but it also terminates if the should_exit_termination()
104 // method of the terminator parameter returns true. If terminator is
105 // NULL, then it is ignored.
106 bool offer_termination(TerminatorTerminator* terminator);
107
|
28 #include "memory/allocation.hpp"
29 #include "memory/padded.hpp"
30 #include "runtime/mutex.hpp"
31
32 class TaskQueueSetSuper;
33 class TerminatorTerminator;
34 class Thread;
35
36 /*
37 * Provides a task termination protocol.
38 *
39 * This is an enhanced implementation of Google's OWST work stealing task termination
40 * protocol (OWST stands for Optimized Work Stealing Threads).
41 *
42 * It is described in the paper:
43 * "Wessam Hassanein. 2016. Understanding and improving JVM GC work
44 * stealing at the data center scale. In Proceedings of the 2016 ACM
45 * SIGPLAN International Symposium on Memory Management (ISMM 2016). ACM,
46 * New York, NY, USA, 46-54. DOI: https://doi.org/10.1145/2926697.2926706"
47 *
48 * Instead of a dedicated spin-master, our implementation will let spin-master
49 * relinquish the role before it goes to sleep/wait, allowing newly arrived
50 * threads to compete for the role.
51 * The intention of above enhancement is to reduce spin-master's latency on
52 * detecting new tasks for stealing and termination condition.
53 */
54 class TaskTerminator : public CHeapObj<mtGC> {
55 class DelayContext {
56 uint _yield_count;
57 // Number of hard spin loops done since last yield
58 uint _hard_spin_count;
59 // Number of iterations in the current hard spin loop.
60 uint _hard_spin_limit;
61
62 void reset_hard_spin_information();
63 public:
64 DelayContext();
65
66 // Should the caller sleep (wait) or perform a spin step?
67 bool needs_sleep() const;
68 // Perform one delay iteration.
69 void do_step();
70 };
71
72 uint _n_threads;
73 TaskQueueSetSuper* _queue_set;
74
75 DEFINE_PAD_MINUS_SIZE(0, DEFAULT_CACHE_LINE_SIZE, 0);
76 volatile uint _offered_termination;
77 DEFINE_PAD_MINUS_SIZE(1, DEFAULT_CACHE_LINE_SIZE, sizeof(volatile uint));
78
79 Monitor _blocker;
80 Thread* _spin_master;
81
82 void assert_queue_set_empty() const NOT_DEBUG_RETURN;
83
84 // Prepare for return from offer_termination. Gives up the spin master token
85 // and wakes up up to tasks threads waiting on _blocker (the default value
86 // means to wake up everyone).
87 void prepare_for_return(Thread* this_thread, size_t tasks = SIZE_MAX);
88
89 // If we should exit current termination protocol
90 bool exit_termination(size_t tasks, TerminatorTerminator* terminator);
91
92 size_t tasks_in_queue_set() const;
93
94 // Perform one iteration of spin-master work.
95 void do_delay_step(DelayContext& delay_context);
96
97 NONCOPYABLE(TaskTerminator);
98
99 public:
100 TaskTerminator(uint n_threads, TaskQueueSetSuper* queue_set);
101 ~TaskTerminator();
102
103 // The current thread has no work, and is ready to terminate if everyone
104 // else is. If returns "true", all threads are terminated. If returns
105 // "false", available work has been observed in one of the task queues,
106 // so the global task is not complete.
107 bool offer_termination() {
108 return offer_termination(NULL);
109 }
110
111 // As above, but it also terminates if the should_exit_termination()
112 // method of the terminator parameter returns true. If terminator is
113 // NULL, then it is ignored.
114 bool offer_termination(TerminatorTerminator* terminator);
115
|