< prev index next >

src/share/vm/gc/shared/workgroup.cpp

Print this page

        

@@ -252,13 +252,14 @@
 }
 
 WorkGang::WorkGang(const char* name,
                    uint  workers,
                    bool  are_GC_task_threads,
-                   bool  are_ConcurrentGC_threads) :
+                   bool  are_ConcurrentGC_threads,
+                   GangTaskDispatcher* dispatcher) :
     AbstractWorkGang(name, workers, are_GC_task_threads, are_ConcurrentGC_threads),
-    _dispatcher(create_dispatcher(workers))
+    _dispatcher(dispatcher != NULL ? dispatcher: create_dispatcher(workers))
 { }
 
 AbstractGangWorker* WorkGang::allocate_worker(uint worker_id) {
   return new GangWorker(this, worker_id);
 }

@@ -621,5 +622,78 @@
 #endif
   if (_waiters > 0)
     // Notify all would be safer, but this is OK, right?
     _mon->notify_all();
 }
+
+/////////////// Unit tests ///////////////
+
+#ifndef PRODUCT
+
+class CountTask : public AbstractGangTask {
+  volatile jint _count;
+  bool _sleep;
+ public:
+  CountTask(bool sleep) : AbstractGangTask("CountTask"), _sleep(sleep), _count(0) {}
+  virtual void work(uint worker_id) {
+    if (_sleep) {
+      // Sleep a while, to delay the task to allow the coordinator to run.
+      os::sleep(Thread::current(), 100, false);
+    }
+
+    // Count number of times executed.
+    Atomic::inc(&_count);
+  }
+  uint count() { return _count; }
+};
+
+
+static void test_workgang_dispatch(bool use_semaphore,
+                                   uint total_workers,
+                                   uint active_workers,
+                                   bool sleep) {
+
+  GangTaskDispatcher* dispatcher = use_semaphore
+      ? (GangTaskDispatcher*) new SemGangTaskDispatcher(total_workers)
+      : (GangTaskDispatcher*) new MutexGangTaskDispatcher();
+
+  // Intentionally leaking WorkGang, since there's no support to delete WorkGangs.
+  WorkGang* gang = new WorkGang("Test WorkGang", total_workers, false, false, dispatcher);
+  gang->initialize_workers();
+
+  gang->set_active_workers(active_workers);
+
+  CountTask task(sleep);
+
+  gang->run_task(&task);
+
+  uint task_count = task.count();
+
+  assert(task_count == active_workers, err_msg("Expected count: %u got: %u", active_workers, task_count));
+}
+
+static void test_workgang_dispatch(bool use_semaphore) {
+  const bool sleep = true;
+  const uint total_workers = 8;
+  for (uint active_workers = 1; active_workers <= 4; active_workers++) {
+    test_workgang_dispatch(use_semaphore, total_workers, active_workers, sleep);
+    test_workgang_dispatch(use_semaphore, total_workers, active_workers, !sleep);
+  }
+}
+
+static void test_workgang_dispatch_mutex() {
+  test_workgang_dispatch(false);
+}
+
+static void test_workgang_dispatch_semaphore() {
+  test_workgang_dispatch(true);
+}
+
+void test_workgang() {
+  // Needed to use dynamic number of active workers.
+  FlagSetting fs(UseDynamicNumberOfGCThreads, true);
+
+  test_workgang_dispatch_semaphore();
+  test_workgang_dispatch_mutex();
+}
+
+#endif // PRODUCT
< prev index next >