--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/agent/src/os/win32/Reaper.cpp Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2000 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+#include <iostream>
+#include "Reaper.hpp"
+
+using namespace std;
+
+Reaper::Reaper(ReaperCB* cb) {
+ InitializeCriticalSection(&crit);
+ event = CreateEvent(NULL, TRUE, FALSE, NULL);
+ this->cb = cb;
+
+ active = false;
+ shouldShutDown = false;
+}
+
+bool
+Reaper::start() {
+ bool result = false;
+
+ EnterCriticalSection(&crit);
+
+ if (!active) {
+ DWORD id;
+ HANDLE reaper = CreateThread(NULL, 0, &Reaper::reaperThreadEntry,
+ this, 0, &id);
+ if (reaper != NULL) {
+ result = true;
+ }
+ }
+
+ LeaveCriticalSection(&crit);
+
+ return result;
+}
+
+bool
+Reaper::stop() {
+ bool result = false;
+
+ EnterCriticalSection(&crit);
+
+ if (active) {
+ shouldShutDown = true;
+ SetEvent(event);
+ while (active) {
+ Sleep(1);
+ }
+ shouldShutDown = false;
+ result = true;
+ }
+
+ LeaveCriticalSection(&crit);
+
+ return result;
+}
+
+void
+Reaper::registerProcess(HANDLE processHandle, void* userData) {
+ ProcessInfo info;
+
+ info.handle = processHandle;
+ info.userData = userData;
+
+ EnterCriticalSection(&crit);
+
+ procInfo.push_back(info);
+ SetEvent(event);
+
+ LeaveCriticalSection(&crit);
+}
+
+void
+Reaper::reaperThread() {
+ while (!shouldShutDown) {
+ // Take atomic snapshot of the current process list and user data
+ EnterCriticalSection(&crit);
+
+ int num = procInfo.size();
+ HANDLE* handleList = new HANDLE[1 + num];
+ void** dataList = new void*[num];
+ for (int i = 0; i < num; i++) {
+ handleList[i] = procInfo[i].handle;
+ dataList[i] = procInfo[i].userData;
+ }
+
+ LeaveCriticalSection(&crit);
+
+ // Topmost handle becomes the event object, so other threads can
+ // signal this one to notice differences in the above list (or
+ // shut down)
+ handleList[num] = event;
+
+ // Wait for these objects
+ DWORD idx = WaitForMultipleObjects(1 + num, handleList,
+ FALSE, INFINITE);
+ if ((idx >= WAIT_OBJECT_0) && (idx <= WAIT_OBJECT_0 + num)) {
+ idx -= WAIT_OBJECT_0;
+ if (idx < num) {
+ // A process exited (i.e., it wasn't that we were woken up
+ // just because the event went off)
+ (*cb)(dataList[idx]);
+ // Remove this process from the list (NOTE: requires that
+ // ordering does not change, i.e., that all additions are to
+ // the back of the process list)
+ EnterCriticalSection(&crit);
+
+ std::vector<ProcessInfo>::iterator iter = procInfo.begin();
+ iter += idx;
+ procInfo.erase(iter);
+
+ LeaveCriticalSection(&crit);
+ } else {
+ // Notification from other thread
+ ResetEvent(event);
+ }
+ } else {
+ // Unexpected return value. For now, warn.
+ cerr << "Reaper::reaperThread(): unexpected return value "
+ << idx << " from WaitForMultipleObjects" << endl;
+ }
+
+ // Clean up these lists
+ delete[] handleList;
+ delete[] dataList;
+ }
+
+ // Time to shut down
+ active = false;
+}
+
+DWORD WINAPI
+Reaper::reaperThreadEntry(LPVOID data) {
+ Reaper* reaper = (Reaper*) data;
+ reaper->reaperThread();
+ return 0;
+}