duke@435: /* duke@435: * Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved. duke@435: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@435: * duke@435: * This code is free software; you can redistribute it and/or modify it duke@435: * under the terms of the GNU General Public License version 2 only, as duke@435: * published by the Free Software Foundation. duke@435: * duke@435: * This code is distributed in the hope that it will be useful, but WITHOUT duke@435: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@435: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@435: * version 2 for more details (a copy is included in the LICENSE file that duke@435: * accompanied this code). duke@435: * duke@435: * You should have received a copy of the GNU General Public License version duke@435: * 2 along with this work; if not, write to the Free Software Foundation, duke@435: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@435: * duke@435: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, duke@435: * CA 95054 USA or visit www.sun.com if you need additional information or duke@435: * have any questions. duke@435: * duke@435: */ duke@435: duke@435: // duke@435: // The GCTaskManager is a queue of GCTasks, and accessors duke@435: // to allow the queue to be accessed from many threads. duke@435: // duke@435: duke@435: // Forward declarations of types defined in this file. duke@435: class GCTask; duke@435: class GCTaskQueue; duke@435: class SynchronizedGCTaskQueue; duke@435: class GCTaskManager; duke@435: class NotifyDoneClosure; duke@435: // Some useful subclasses of GCTask. You can also make up your own. duke@435: class NoopGCTask; duke@435: class BarrierGCTask; duke@435: class ReleasingBarrierGCTask; duke@435: class NotifyingBarrierGCTask; duke@435: class WaitForBarrierGCTask; duke@435: // A free list of Monitor*'s. duke@435: class MonitorSupply; duke@435: duke@435: // Forward declarations of classes referenced in this file via pointer. duke@435: class GCTaskThread; duke@435: class Mutex; duke@435: class Monitor; duke@435: class ThreadClosure; duke@435: duke@435: // The abstract base GCTask. duke@435: class GCTask : public ResourceObj { duke@435: public: duke@435: // Known kinds of GCTasks, for predicates. duke@435: class Kind : AllStatic { duke@435: public: duke@435: enum kind { duke@435: unknown_task, duke@435: ordinary_task, duke@435: barrier_task, duke@435: noop_task duke@435: }; duke@435: static const char* to_string(kind value); duke@435: }; duke@435: private: duke@435: // Instance state. duke@435: const Kind::kind _kind; // For runtime type checking. duke@435: const uint _affinity; // Which worker should run task. duke@435: GCTask* _newer; // Tasks are on doubly-linked ... duke@435: GCTask* _older; // ... lists. duke@435: public: duke@435: virtual char* name() { return (char *)"task"; } duke@435: duke@435: // Abstract do_it method duke@435: virtual void do_it(GCTaskManager* manager, uint which) = 0; duke@435: // Accessors duke@435: Kind::kind kind() const { duke@435: return _kind; duke@435: } duke@435: uint affinity() const { duke@435: return _affinity; duke@435: } duke@435: GCTask* newer() const { duke@435: return _newer; duke@435: } duke@435: void set_newer(GCTask* n) { duke@435: _newer = n; duke@435: } duke@435: GCTask* older() const { duke@435: return _older; duke@435: } duke@435: void set_older(GCTask* p) { duke@435: _older = p; duke@435: } duke@435: // Predicates. duke@435: bool is_ordinary_task() const { duke@435: return kind()==Kind::ordinary_task; duke@435: } duke@435: bool is_barrier_task() const { duke@435: return kind()==Kind::barrier_task; duke@435: } duke@435: bool is_noop_task() const { duke@435: return kind()==Kind::noop_task; duke@435: } duke@435: void print(const char* message) const PRODUCT_RETURN; duke@435: protected: duke@435: // Constructors: Only create subclasses. duke@435: // An ordinary GCTask. duke@435: GCTask(); duke@435: // A GCTask of a particular kind, usually barrier or noop. duke@435: GCTask(Kind::kind kind); duke@435: // An ordinary GCTask with an affinity. duke@435: GCTask(uint affinity); duke@435: // A GCTask of a particular kind, with and affinity. duke@435: GCTask(Kind::kind kind, uint affinity); duke@435: // We want a virtual destructor because virtual methods, duke@435: // but since ResourceObj's don't have their destructors duke@435: // called, we don't have one at all. Instead we have duke@435: // this method, which gets called by subclasses to clean up. duke@435: virtual void destruct(); duke@435: // Methods. duke@435: void initialize(); duke@435: }; duke@435: duke@435: // A doubly-linked list of GCTasks. duke@435: // The list is not synchronized, because sometimes we want to duke@435: // build up a list and then make it available to other threads. duke@435: // See also: SynchronizedGCTaskQueue. duke@435: class GCTaskQueue : public ResourceObj { duke@435: private: duke@435: // Instance state. duke@435: GCTask* _insert_end; // Tasks are enqueued at this end. duke@435: GCTask* _remove_end; // Tasks are dequeued from this end. duke@435: uint _length; // The current length of the queue. duke@435: const bool _is_c_heap_obj; // Is this a CHeapObj? duke@435: public: duke@435: // Factory create and destroy methods. duke@435: // Create as ResourceObj. duke@435: static GCTaskQueue* create(); duke@435: // Create as CHeapObj. duke@435: static GCTaskQueue* create_on_c_heap(); duke@435: // Destroyer. duke@435: static void destroy(GCTaskQueue* that); duke@435: // Accessors. duke@435: // These just examine the state of the queue. duke@435: bool is_empty() const { duke@435: assert(((insert_end() == NULL && remove_end() == NULL) || duke@435: (insert_end() != NULL && remove_end() != NULL)), duke@435: "insert_end and remove_end don't match"); duke@435: return insert_end() == NULL; duke@435: } duke@435: uint length() const { duke@435: return _length; duke@435: } duke@435: // Methods. duke@435: // Enqueue one task. duke@435: void enqueue(GCTask* task); duke@435: // Enqueue a list of tasks. Empties the argument list. duke@435: void enqueue(GCTaskQueue* list); duke@435: // Dequeue one task. duke@435: GCTask* dequeue(); duke@435: // Dequeue one task, preferring one with affinity. duke@435: GCTask* dequeue(uint affinity); duke@435: protected: duke@435: // Constructor. Clients use factory, but there might be subclasses. duke@435: GCTaskQueue(bool on_c_heap); duke@435: // Destructor-like method. duke@435: // Because ResourceMark doesn't call destructors. duke@435: // This method cleans up like one. duke@435: virtual void destruct(); duke@435: // Accessors. duke@435: GCTask* insert_end() const { duke@435: return _insert_end; duke@435: } duke@435: void set_insert_end(GCTask* value) { duke@435: _insert_end = value; duke@435: } duke@435: GCTask* remove_end() const { duke@435: return _remove_end; duke@435: } duke@435: void set_remove_end(GCTask* value) { duke@435: _remove_end = value; duke@435: } duke@435: void increment_length() { duke@435: _length += 1; duke@435: } duke@435: void decrement_length() { duke@435: _length -= 1; duke@435: } duke@435: void set_length(uint value) { duke@435: _length = value; duke@435: } duke@435: bool is_c_heap_obj() const { duke@435: return _is_c_heap_obj; duke@435: } duke@435: // Methods. duke@435: void initialize(); duke@435: GCTask* remove(); // Remove from remove end. duke@435: GCTask* remove(GCTask* task); // Remove from the middle. duke@435: void print(const char* message) const PRODUCT_RETURN; duke@435: }; duke@435: duke@435: // A GCTaskQueue that can be synchronized. duke@435: // This "has-a" GCTaskQueue and a mutex to do the exclusion. duke@435: class SynchronizedGCTaskQueue : public CHeapObj { duke@435: private: duke@435: // Instance state. duke@435: GCTaskQueue* _unsynchronized_queue; // Has-a unsynchronized queue. duke@435: Monitor * _lock; // Lock to control access. duke@435: public: duke@435: // Factory create and destroy methods. duke@435: static SynchronizedGCTaskQueue* create(GCTaskQueue* queue, Monitor * lock) { duke@435: return new SynchronizedGCTaskQueue(queue, lock); duke@435: } duke@435: static void destroy(SynchronizedGCTaskQueue* that) { duke@435: if (that != NULL) { duke@435: delete that; duke@435: } duke@435: } duke@435: // Accessors duke@435: GCTaskQueue* unsynchronized_queue() const { duke@435: return _unsynchronized_queue; duke@435: } duke@435: Monitor * lock() const { duke@435: return _lock; duke@435: } duke@435: // GCTaskQueue wrapper methods. duke@435: // These check that you hold the lock duke@435: // and then call the method on the queue. duke@435: bool is_empty() const { duke@435: guarantee(own_lock(), "don't own the lock"); duke@435: return unsynchronized_queue()->is_empty(); duke@435: } duke@435: void enqueue(GCTask* task) { duke@435: guarantee(own_lock(), "don't own the lock"); duke@435: unsynchronized_queue()->enqueue(task); duke@435: } duke@435: void enqueue(GCTaskQueue* list) { duke@435: guarantee(own_lock(), "don't own the lock"); duke@435: unsynchronized_queue()->enqueue(list); duke@435: } duke@435: GCTask* dequeue() { duke@435: guarantee(own_lock(), "don't own the lock"); duke@435: return unsynchronized_queue()->dequeue(); duke@435: } duke@435: GCTask* dequeue(uint affinity) { duke@435: guarantee(own_lock(), "don't own the lock"); duke@435: return unsynchronized_queue()->dequeue(affinity); duke@435: } duke@435: uint length() const { duke@435: guarantee(own_lock(), "don't own the lock"); duke@435: return unsynchronized_queue()->length(); duke@435: } duke@435: // For guarantees. duke@435: bool own_lock() const { duke@435: return lock()->owned_by_self(); duke@435: } duke@435: protected: duke@435: // Constructor. Clients use factory, but there might be subclasses. duke@435: SynchronizedGCTaskQueue(GCTaskQueue* queue, Monitor * lock); duke@435: // Destructor. Not virtual because no virtuals. duke@435: ~SynchronizedGCTaskQueue(); duke@435: }; duke@435: duke@435: // This is an abstract base class for getting notifications duke@435: // when a GCTaskManager is done. duke@435: class NotifyDoneClosure : public CHeapObj { duke@435: public: duke@435: // The notification callback method. duke@435: virtual void notify(GCTaskManager* manager) = 0; duke@435: protected: duke@435: // Constructor. duke@435: NotifyDoneClosure() { duke@435: // Nothing to do. duke@435: } duke@435: // Virtual destructor because virtual methods. duke@435: virtual ~NotifyDoneClosure() { duke@435: // Nothing to do. duke@435: } duke@435: }; duke@435: duke@435: class GCTaskManager : public CHeapObj { duke@435: friend class ParCompactionManager; duke@435: friend class PSParallelCompact; duke@435: friend class PSScavenge; duke@435: friend class PSRefProcTaskExecutor; duke@435: friend class RefProcTaskExecutor; duke@435: private: duke@435: // Instance state. duke@435: NotifyDoneClosure* _ndc; // Notify on completion. duke@435: const uint _workers; // Number of workers. duke@435: Monitor* _monitor; // Notification of changes. duke@435: SynchronizedGCTaskQueue* _queue; // Queue of tasks. duke@435: GCTaskThread** _thread; // Array of worker threads. duke@435: uint _busy_workers; // Number of busy workers. duke@435: uint _blocking_worker; // The worker that's blocking. duke@435: bool* _resource_flag; // Array of flag per threads. duke@435: uint _delivered_tasks; // Count of delivered tasks. duke@435: uint _completed_tasks; // Count of completed tasks. duke@435: uint _barriers; // Count of barrier tasks. duke@435: uint _emptied_queue; // Times we emptied the queue. duke@435: NoopGCTask* _noop_task; // The NoopGCTask instance. duke@435: uint _noop_tasks; // Count of noop tasks. duke@435: public: duke@435: // Factory create and destroy methods. duke@435: static GCTaskManager* create(uint workers) { duke@435: return new GCTaskManager(workers); duke@435: } duke@435: static GCTaskManager* create(uint workers, NotifyDoneClosure* ndc) { duke@435: return new GCTaskManager(workers, ndc); duke@435: } duke@435: static void destroy(GCTaskManager* that) { duke@435: if (that != NULL) { duke@435: delete that; duke@435: } duke@435: } duke@435: // Accessors. duke@435: uint busy_workers() const { duke@435: return _busy_workers; duke@435: } duke@435: // Pun between Monitor* and Mutex* duke@435: Monitor* monitor() const { duke@435: return _monitor; duke@435: } duke@435: Monitor * lock() const { duke@435: return _monitor; duke@435: } duke@435: // Methods. duke@435: // Add the argument task to be run. duke@435: void add_task(GCTask* task); duke@435: // Add a list of tasks. Removes task from the argument list. duke@435: void add_list(GCTaskQueue* list); duke@435: // Claim a task for argument worker. duke@435: GCTask* get_task(uint which); duke@435: // Note the completion of a task by the argument worker. duke@435: void note_completion(uint which); duke@435: // Is the queue blocked from handing out new tasks? duke@435: bool is_blocked() const { duke@435: return (blocking_worker() != sentinel_worker()); duke@435: } duke@435: // Request that all workers release their resources. duke@435: void release_all_resources(); duke@435: // Ask if a particular worker should release its resources. duke@435: bool should_release_resources(uint which); // Predicate. duke@435: // Note the release of resources by the argument worker. duke@435: void note_release(uint which); duke@435: // Constants. duke@435: // A sentinel worker identifier. duke@435: static uint sentinel_worker() { duke@435: return (uint) -1; // Why isn't there a max_uint? duke@435: } duke@435: duke@435: // Execute the task queue and wait for the completion. duke@435: void execute_and_wait(GCTaskQueue* list); duke@435: duke@435: void print_task_time_stamps(); duke@435: void print_threads_on(outputStream* st); duke@435: void threads_do(ThreadClosure* tc); duke@435: duke@435: protected: duke@435: // Constructors. Clients use factory, but there might be subclasses. duke@435: // Create a GCTaskManager with the appropriate number of workers. duke@435: GCTaskManager(uint workers); duke@435: // Create a GCTaskManager that calls back when there's no more work. duke@435: GCTaskManager(uint workers, NotifyDoneClosure* ndc); duke@435: // Make virtual if necessary. duke@435: ~GCTaskManager(); duke@435: // Accessors. duke@435: uint workers() const { duke@435: return _workers; duke@435: } duke@435: NotifyDoneClosure* notify_done_closure() const { duke@435: return _ndc; duke@435: } duke@435: SynchronizedGCTaskQueue* queue() const { duke@435: return _queue; duke@435: } duke@435: NoopGCTask* noop_task() const { duke@435: return _noop_task; duke@435: } duke@435: // Bounds-checking per-thread data accessors. duke@435: GCTaskThread* thread(uint which); duke@435: void set_thread(uint which, GCTaskThread* value); duke@435: bool resource_flag(uint which); duke@435: void set_resource_flag(uint which, bool value); duke@435: // Modifier methods with some semantics. duke@435: // Is any worker blocking handing out new tasks? duke@435: uint blocking_worker() const { duke@435: return _blocking_worker; duke@435: } duke@435: void set_blocking_worker(uint value) { duke@435: _blocking_worker = value; duke@435: } duke@435: void set_unblocked() { duke@435: set_blocking_worker(sentinel_worker()); duke@435: } duke@435: // Count of busy workers. duke@435: void reset_busy_workers() { duke@435: _busy_workers = 0; duke@435: } duke@435: uint increment_busy_workers(); duke@435: uint decrement_busy_workers(); duke@435: // Count of tasks delivered to workers. duke@435: uint delivered_tasks() const { duke@435: return _delivered_tasks; duke@435: } duke@435: void increment_delivered_tasks() { duke@435: _delivered_tasks += 1; duke@435: } duke@435: void reset_delivered_tasks() { duke@435: _delivered_tasks = 0; duke@435: } duke@435: // Count of tasks completed by workers. duke@435: uint completed_tasks() const { duke@435: return _completed_tasks; duke@435: } duke@435: void increment_completed_tasks() { duke@435: _completed_tasks += 1; duke@435: } duke@435: void reset_completed_tasks() { duke@435: _completed_tasks = 0; duke@435: } duke@435: // Count of barrier tasks completed. duke@435: uint barriers() const { duke@435: return _barriers; duke@435: } duke@435: void increment_barriers() { duke@435: _barriers += 1; duke@435: } duke@435: void reset_barriers() { duke@435: _barriers = 0; duke@435: } duke@435: // Count of how many times the queue has emptied. duke@435: uint emptied_queue() const { duke@435: return _emptied_queue; duke@435: } duke@435: void increment_emptied_queue() { duke@435: _emptied_queue += 1; duke@435: } duke@435: void reset_emptied_queue() { duke@435: _emptied_queue = 0; duke@435: } duke@435: // Count of the number of noop tasks we've handed out, duke@435: // e.g., to handle resource release requests. duke@435: uint noop_tasks() const { duke@435: return _noop_tasks; duke@435: } duke@435: void increment_noop_tasks() { duke@435: _noop_tasks += 1; duke@435: } duke@435: void reset_noop_tasks() { duke@435: _noop_tasks = 0; duke@435: } duke@435: // Other methods. duke@435: void initialize(); duke@435: }; duke@435: duke@435: // duke@435: // Some exemplary GCTasks. duke@435: // duke@435: duke@435: // A noop task that does nothing, duke@435: // except take us around the GCTaskThread loop. duke@435: class NoopGCTask : public GCTask { duke@435: private: duke@435: const bool _is_c_heap_obj; // Is this a CHeapObj? duke@435: public: duke@435: // Factory create and destroy methods. duke@435: static NoopGCTask* create(); duke@435: static NoopGCTask* create_on_c_heap(); duke@435: static void destroy(NoopGCTask* that); duke@435: // Methods from GCTask. duke@435: void do_it(GCTaskManager* manager, uint which) { duke@435: // Nothing to do. duke@435: } duke@435: protected: duke@435: // Constructor. duke@435: NoopGCTask(bool on_c_heap) : duke@435: GCTask(GCTask::Kind::noop_task), duke@435: _is_c_heap_obj(on_c_heap) { duke@435: // Nothing to do. duke@435: } duke@435: // Destructor-like method. duke@435: void destruct(); duke@435: // Accessors. duke@435: bool is_c_heap_obj() const { duke@435: return _is_c_heap_obj; duke@435: } duke@435: }; duke@435: duke@435: // A BarrierGCTask blocks other tasks from starting, duke@435: // and waits until it is the only task running. duke@435: class BarrierGCTask : public GCTask { duke@435: public: duke@435: // Factory create and destroy methods. duke@435: static BarrierGCTask* create() { duke@435: return new BarrierGCTask(); duke@435: } duke@435: static void destroy(BarrierGCTask* that) { duke@435: if (that != NULL) { duke@435: that->destruct(); duke@435: delete that; duke@435: } duke@435: } duke@435: // Methods from GCTask. duke@435: void do_it(GCTaskManager* manager, uint which); duke@435: protected: duke@435: // Constructor. Clients use factory, but there might be subclasses. duke@435: BarrierGCTask() : duke@435: GCTask(GCTask::Kind::barrier_task) { duke@435: // Nothing to do. duke@435: } duke@435: // Destructor-like method. duke@435: void destruct(); duke@435: // Methods. duke@435: // Wait for this to be the only task running. duke@435: void do_it_internal(GCTaskManager* manager, uint which); duke@435: }; duke@435: duke@435: // A ReleasingBarrierGCTask is a BarrierGCTask duke@435: // that tells all the tasks to release their resource areas. duke@435: class ReleasingBarrierGCTask : public BarrierGCTask { duke@435: public: duke@435: // Factory create and destroy methods. duke@435: static ReleasingBarrierGCTask* create() { duke@435: return new ReleasingBarrierGCTask(); duke@435: } duke@435: static void destroy(ReleasingBarrierGCTask* that) { duke@435: if (that != NULL) { duke@435: that->destruct(); duke@435: delete that; duke@435: } duke@435: } duke@435: // Methods from GCTask. duke@435: void do_it(GCTaskManager* manager, uint which); duke@435: protected: duke@435: // Constructor. Clients use factory, but there might be subclasses. duke@435: ReleasingBarrierGCTask() : duke@435: BarrierGCTask() { duke@435: // Nothing to do. duke@435: } duke@435: // Destructor-like method. duke@435: void destruct(); duke@435: }; duke@435: duke@435: // A NotifyingBarrierGCTask is a BarrierGCTask duke@435: // that calls a notification method when it is the only task running. duke@435: class NotifyingBarrierGCTask : public BarrierGCTask { duke@435: private: duke@435: // Instance state. duke@435: NotifyDoneClosure* _ndc; // The callback object. duke@435: public: duke@435: // Factory create and destroy methods. duke@435: static NotifyingBarrierGCTask* create(NotifyDoneClosure* ndc) { duke@435: return new NotifyingBarrierGCTask(ndc); duke@435: } duke@435: static void destroy(NotifyingBarrierGCTask* that) { duke@435: if (that != NULL) { duke@435: that->destruct(); duke@435: delete that; duke@435: } duke@435: } duke@435: // Methods from GCTask. duke@435: void do_it(GCTaskManager* manager, uint which); duke@435: protected: duke@435: // Constructor. Clients use factory, but there might be subclasses. duke@435: NotifyingBarrierGCTask(NotifyDoneClosure* ndc) : duke@435: BarrierGCTask(), duke@435: _ndc(ndc) { duke@435: assert(notify_done_closure() != NULL, "can't notify on NULL"); duke@435: } duke@435: // Destructor-like method. duke@435: void destruct(); duke@435: // Accessor. duke@435: NotifyDoneClosure* notify_done_closure() const { return _ndc; } duke@435: }; duke@435: duke@435: // A WaitForBarrierGCTask is a BarrierGCTask duke@435: // with a method you can call to wait until duke@435: // the BarrierGCTask is done. duke@435: // This may cover many of the uses of NotifyingBarrierGCTasks. duke@435: class WaitForBarrierGCTask : public BarrierGCTask { duke@435: private: duke@435: // Instance state. duke@435: Monitor* _monitor; // Guard and notify changes. duke@435: bool _should_wait; // true=>wait, false=>proceed. duke@435: const bool _is_c_heap_obj; // Was allocated on the heap. duke@435: public: duke@435: virtual char* name() { return (char *) "waitfor-barrier-task"; } duke@435: duke@435: // Factory create and destroy methods. duke@435: static WaitForBarrierGCTask* create(); duke@435: static WaitForBarrierGCTask* create_on_c_heap(); duke@435: static void destroy(WaitForBarrierGCTask* that); duke@435: // Methods. duke@435: void do_it(GCTaskManager* manager, uint which); duke@435: void wait_for(); duke@435: protected: duke@435: // Constructor. Clients use factory, but there might be subclasses. duke@435: WaitForBarrierGCTask(bool on_c_heap); duke@435: // Destructor-like method. duke@435: void destruct(); duke@435: // Accessors. duke@435: Monitor* monitor() const { duke@435: return _monitor; duke@435: } duke@435: bool should_wait() const { duke@435: return _should_wait; duke@435: } duke@435: void set_should_wait(bool value) { duke@435: _should_wait = value; duke@435: } duke@435: bool is_c_heap_obj() { duke@435: return _is_c_heap_obj; duke@435: } duke@435: }; duke@435: duke@435: class MonitorSupply : public AllStatic { duke@435: private: duke@435: // State. duke@435: // Control multi-threaded access. duke@435: static Mutex* _lock; duke@435: // The list of available Monitor*'s. duke@435: static GrowableArray* _freelist; duke@435: public: duke@435: // Reserve a Monitor*. duke@435: static Monitor* reserve(); duke@435: // Release a Monitor*. duke@435: static void release(Monitor* instance); duke@435: private: duke@435: // Accessors. duke@435: static Mutex* lock() { duke@435: return _lock; duke@435: } duke@435: static GrowableArray* freelist() { duke@435: return _freelist; duke@435: } duke@435: };