1.1 --- a/src/share/vm/gc_implementation/parallelScavenge/gcTaskManager.hpp Tue Nov 22 04:47:10 2011 -0500 1.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/gcTaskManager.hpp Tue Aug 09 10:16:01 2011 -0700 1.3 @@ -45,6 +45,7 @@ 1.4 class ReleasingBarrierGCTask; 1.5 class NotifyingBarrierGCTask; 1.6 class WaitForBarrierGCTask; 1.7 +class IdleGCTask; 1.8 // A free list of Monitor*'s. 1.9 class MonitorSupply; 1.10 1.11 @@ -64,7 +65,8 @@ 1.12 unknown_task, 1.13 ordinary_task, 1.14 barrier_task, 1.15 - noop_task 1.16 + noop_task, 1.17 + idle_task 1.18 }; 1.19 static const char* to_string(kind value); 1.20 }; 1.21 @@ -108,6 +110,9 @@ 1.22 bool is_noop_task() const { 1.23 return kind()==Kind::noop_task; 1.24 } 1.25 + bool is_idle_task() const { 1.26 + return kind()==Kind::idle_task; 1.27 + } 1.28 void print(const char* message) const PRODUCT_RETURN; 1.29 protected: 1.30 // Constructors: Only create subclasses. 1.31 @@ -153,6 +158,7 @@ 1.32 assert(((insert_end() == NULL && remove_end() == NULL) || 1.33 (insert_end() != NULL && remove_end() != NULL)), 1.34 "insert_end and remove_end don't match"); 1.35 + assert((insert_end() != NULL) || (_length == 0), "Not empty"); 1.36 return insert_end() == NULL; 1.37 } 1.38 uint length() const { 1.39 @@ -204,6 +210,8 @@ 1.40 GCTask* remove(); // Remove from remove end. 1.41 GCTask* remove(GCTask* task); // Remove from the middle. 1.42 void print(const char* message) const PRODUCT_RETURN; 1.43 + // Debug support 1.44 + void verify_length() const PRODUCT_RETURN; 1.45 }; 1.46 1.47 // A GCTaskQueue that can be synchronized. 1.48 @@ -285,12 +293,76 @@ 1.49 } 1.50 }; 1.51 1.52 +// Dynamic number of GC threads 1.53 +// 1.54 +// GC threads wait in get_task() for work (i.e., a task) to perform. 1.55 +// When the number of GC threads was static, the number of tasks 1.56 +// created to do a job was equal to or greater than the maximum 1.57 +// number of GC threads (ParallelGCThreads). The job might be divided 1.58 +// into a number of tasks greater than the number of GC threads for 1.59 +// load balancing (i.e., over partitioning). The last task to be 1.60 +// executed by a GC thread in a job is a work stealing task. A 1.61 +// GC thread that gets a work stealing task continues to execute 1.62 +// that task until the job is done. In the static number of GC theads 1.63 +// case, tasks are added to a queue (FIFO). The work stealing tasks are 1.64 +// the last to be added. Once the tasks are added, the GC threads grab 1.65 +// a task and go. A single thread can do all the non-work stealing tasks 1.66 +// and then execute a work stealing and wait for all the other GC threads 1.67 +// to execute their work stealing task. 1.68 +// In the dynamic number of GC threads implementation, idle-tasks are 1.69 +// created to occupy the non-participating or "inactive" threads. An 1.70 +// idle-task makes the GC thread wait on a barrier that is part of the 1.71 +// GCTaskManager. The GC threads that have been "idled" in a IdleGCTask 1.72 +// are released once all the active GC threads have finished their work 1.73 +// stealing tasks. The GCTaskManager does not wait for all the "idled" 1.74 +// GC threads to resume execution. When those GC threads do resume 1.75 +// execution in the course of the thread scheduling, they call get_tasks() 1.76 +// as all the other GC threads do. Because all the "idled" threads are 1.77 +// not required to execute in order to finish a job, it is possible for 1.78 +// a GC thread to still be "idled" when the next job is started. Such 1.79 +// a thread stays "idled" for the next job. This can result in a new 1.80 +// job not having all the expected active workers. For example if on 1.81 +// job requests 4 active workers out of a total of 10 workers so the 1.82 +// remaining 6 are "idled", if the next job requests 6 active workers 1.83 +// but all 6 of the "idled" workers are still idle, then the next job 1.84 +// will only get 4 active workers. 1.85 +// The implementation for the parallel old compaction phase has an 1.86 +// added complication. In the static case parold partitions the chunks 1.87 +// ready to be filled into stacks, one for each GC thread. A GC thread 1.88 +// executing a draining task (drains the stack of ready chunks) 1.89 +// claims a stack according to it's id (the unique ordinal value assigned 1.90 +// to each GC thread). In the dynamic case not all GC threads will 1.91 +// actively participate so stacks with ready to fill chunks can only be 1.92 +// given to the active threads. An initial implementation chose stacks 1.93 +// number 1-n to get the ready chunks and required that GC threads 1.94 +// 1-n be the active workers. This was undesirable because it required 1.95 +// certain threads to participate. In the final implementation a 1.96 +// list of stacks equal in number to the active workers are filled 1.97 +// with ready chunks. GC threads that participate get a stack from 1.98 +// the task (DrainStacksCompactionTask), empty the stack, and then add it to a 1.99 +// recycling list at the end of the task. If the same GC thread gets 1.100 +// a second task, it gets a second stack to drain and returns it. The 1.101 +// stacks are added to a recycling list so that later stealing tasks 1.102 +// for this tasks can get a stack from the recycling list. Stealing tasks 1.103 +// use the stacks in its work in a way similar to the draining tasks. 1.104 +// A thread is not guaranteed to get anything but a stealing task and 1.105 +// a thread that only gets a stealing task has to get a stack. A failed 1.106 +// implementation tried to have the GC threads keep the stack they used 1.107 +// during a draining task for later use in the stealing task but that didn't 1.108 +// work because as noted a thread is not guaranteed to get a draining task. 1.109 +// 1.110 +// For PSScavenge and ParCompactionManager the GC threads are 1.111 +// held in the GCTaskThread** _thread array in GCTaskManager. 1.112 + 1.113 + 1.114 class GCTaskManager : public CHeapObj { 1.115 friend class ParCompactionManager; 1.116 friend class PSParallelCompact; 1.117 friend class PSScavenge; 1.118 friend class PSRefProcTaskExecutor; 1.119 friend class RefProcTaskExecutor; 1.120 + friend class GCTaskThread; 1.121 + friend class IdleGCTask; 1.122 private: 1.123 // Instance state. 1.124 NotifyDoneClosure* _ndc; // Notify on completion. 1.125 @@ -298,6 +370,7 @@ 1.126 Monitor* _monitor; // Notification of changes. 1.127 SynchronizedGCTaskQueue* _queue; // Queue of tasks. 1.128 GCTaskThread** _thread; // Array of worker threads. 1.129 + uint _active_workers; // Number of active workers. 1.130 uint _busy_workers; // Number of busy workers. 1.131 uint _blocking_worker; // The worker that's blocking. 1.132 bool* _resource_flag; // Array of flag per threads. 1.133 @@ -307,6 +380,8 @@ 1.134 uint _emptied_queue; // Times we emptied the queue. 1.135 NoopGCTask* _noop_task; // The NoopGCTask instance. 1.136 uint _noop_tasks; // Count of noop tasks. 1.137 + WaitForBarrierGCTask* _idle_inactive_task;// Task for inactive workers 1.138 + volatile uint _idle_workers; // Number of idled workers 1.139 public: 1.140 // Factory create and destroy methods. 1.141 static GCTaskManager* create(uint workers) { 1.142 @@ -324,6 +399,9 @@ 1.143 uint busy_workers() const { 1.144 return _busy_workers; 1.145 } 1.146 + volatile uint idle_workers() const { 1.147 + return _idle_workers; 1.148 + } 1.149 // Pun between Monitor* and Mutex* 1.150 Monitor* monitor() const { 1.151 return _monitor; 1.152 @@ -331,6 +409,9 @@ 1.153 Monitor * lock() const { 1.154 return _monitor; 1.155 } 1.156 + WaitForBarrierGCTask* idle_inactive_task() { 1.157 + return _idle_inactive_task; 1.158 + } 1.159 // Methods. 1.160 // Add the argument task to be run. 1.161 void add_task(GCTask* task); 1.162 @@ -350,6 +431,10 @@ 1.163 bool should_release_resources(uint which); // Predicate. 1.164 // Note the release of resources by the argument worker. 1.165 void note_release(uint which); 1.166 + // Create IdleGCTasks for inactive workers and start workers 1.167 + void task_idle_workers(); 1.168 + // Release the workers in IdleGCTasks 1.169 + void release_idle_workers(); 1.170 // Constants. 1.171 // A sentinel worker identifier. 1.172 static uint sentinel_worker() { 1.173 @@ -375,6 +460,15 @@ 1.174 uint workers() const { 1.175 return _workers; 1.176 } 1.177 + void set_active_workers(uint v) { 1.178 + assert(v <= _workers, "Trying to set more workers active than there are"); 1.179 + _active_workers = MIN2(v, _workers); 1.180 + assert(v != 0, "Trying to set active workers to 0"); 1.181 + _active_workers = MAX2(1U, _active_workers); 1.182 + } 1.183 + // Sets the number of threads that will be used in a collection 1.184 + void set_active_gang(); 1.185 + 1.186 NotifyDoneClosure* notify_done_closure() const { 1.187 return _ndc; 1.188 } 1.189 @@ -457,8 +551,21 @@ 1.190 void reset_noop_tasks() { 1.191 _noop_tasks = 0; 1.192 } 1.193 + void increment_idle_workers() { 1.194 + _idle_workers++; 1.195 + } 1.196 + void decrement_idle_workers() { 1.197 + _idle_workers--; 1.198 + } 1.199 // Other methods. 1.200 void initialize(); 1.201 + 1.202 + public: 1.203 + // Return true if all workers are currently active. 1.204 + bool all_workers_active() { return workers() == active_workers(); } 1.205 + uint active_workers() const { 1.206 + return _active_workers; 1.207 + } 1.208 }; 1.209 1.210 // 1.211 @@ -475,6 +582,8 @@ 1.212 static NoopGCTask* create(); 1.213 static NoopGCTask* create_on_c_heap(); 1.214 static void destroy(NoopGCTask* that); 1.215 + 1.216 + virtual char* name() { return (char *)"noop task"; } 1.217 // Methods from GCTask. 1.218 void do_it(GCTaskManager* manager, uint which) { 1.219 // Nothing to do. 1.220 @@ -518,6 +627,8 @@ 1.221 } 1.222 // Destructor-like method. 1.223 void destruct(); 1.224 + 1.225 + virtual char* name() { return (char *)"barrier task"; } 1.226 // Methods. 1.227 // Wait for this to be the only task running. 1.228 void do_it_internal(GCTaskManager* manager, uint which); 1.229 @@ -586,11 +697,13 @@ 1.230 // the BarrierGCTask is done. 1.231 // This may cover many of the uses of NotifyingBarrierGCTasks. 1.232 class WaitForBarrierGCTask : public BarrierGCTask { 1.233 + friend class GCTaskManager; 1.234 + friend class IdleGCTask; 1.235 private: 1.236 // Instance state. 1.237 - Monitor* _monitor; // Guard and notify changes. 1.238 - bool _should_wait; // true=>wait, false=>proceed. 1.239 - const bool _is_c_heap_obj; // Was allocated on the heap. 1.240 + Monitor* _monitor; // Guard and notify changes. 1.241 + volatile bool _should_wait; // true=>wait, false=>proceed. 1.242 + const bool _is_c_heap_obj; // Was allocated on the heap. 1.243 public: 1.244 virtual char* name() { return (char *) "waitfor-barrier-task"; } 1.245 1.246 @@ -600,7 +713,10 @@ 1.247 static void destroy(WaitForBarrierGCTask* that); 1.248 // Methods. 1.249 void do_it(GCTaskManager* manager, uint which); 1.250 - void wait_for(); 1.251 + void wait_for(bool reset); 1.252 + void set_should_wait(bool value) { 1.253 + _should_wait = value; 1.254 + } 1.255 protected: 1.256 // Constructor. Clients use factory, but there might be subclasses. 1.257 WaitForBarrierGCTask(bool on_c_heap); 1.258 @@ -613,14 +729,38 @@ 1.259 bool should_wait() const { 1.260 return _should_wait; 1.261 } 1.262 - void set_should_wait(bool value) { 1.263 - _should_wait = value; 1.264 - } 1.265 bool is_c_heap_obj() { 1.266 return _is_c_heap_obj; 1.267 } 1.268 }; 1.269 1.270 +// Task that is used to idle a GC task when fewer than 1.271 +// the maximum workers are wanted. 1.272 +class IdleGCTask : public GCTask { 1.273 + const bool _is_c_heap_obj; // Was allocated on the heap. 1.274 + public: 1.275 + bool is_c_heap_obj() { 1.276 + return _is_c_heap_obj; 1.277 + } 1.278 + // Factory create and destroy methods. 1.279 + static IdleGCTask* create(); 1.280 + static IdleGCTask* create_on_c_heap(); 1.281 + static void destroy(IdleGCTask* that); 1.282 + 1.283 + virtual char* name() { return (char *)"idle task"; } 1.284 + // Methods from GCTask. 1.285 + virtual void do_it(GCTaskManager* manager, uint which); 1.286 +protected: 1.287 + // Constructor. 1.288 + IdleGCTask(bool on_c_heap) : 1.289 + GCTask(GCTask::Kind::idle_task), 1.290 + _is_c_heap_obj(on_c_heap) { 1.291 + // Nothing to do. 1.292 + } 1.293 + // Destructor-like method. 1.294 + void destruct(); 1.295 +}; 1.296 + 1.297 class MonitorSupply : public AllStatic { 1.298 private: 1.299 // State.