[dia] New development-only plug-in: stress



commit 79161756e1a909d33bbab016570f011f133799ee
Author: Hans Breuer <hans breuer org>
Date:   Sun Mar 27 22:46:58 2011 +0200

    New development-only plug-in: stress
    
    This should not be installed anywhere, it's development only!
    The only implemented function is 'eating' memory, to test
    Dia under low memory conditions.
    BEWARE: consecutive calls try to eat 9/10 of the available
    memory. This will finally lead to hard program exit when
    the next call to g_malloc() fails.
    It is still useful to reproduce bugs like bug 643285 without
    swapping, because the memory is just 'eaten' from the address
    space, not from real memory. Win32 only for the moment.

 plug-ins/makefile.msc           |    8 ++-
 plug-ins/stress/stress-memory.c |  131 +++++++++++++++++++++++++++++++++++++++
 plug-ins/stress/stress-memory.h |    7 ++
 plug-ins/stress/stress.c        |   93 +++++++++++++++++++++++++++
 4 files changed, 238 insertions(+), 1 deletions(-)
---
diff --git a/plug-ins/makefile.msc b/plug-ins/makefile.msc
index 64a4cef..82fe3da 100644
--- a/plug-ins/makefile.msc
+++ b/plug-ins/makefile.msc
@@ -3,7 +3,7 @@
 # dummy sissi
 PLUGINS = cairo cgm dxf hpgl libart metapost pgf pixbuf \
 	postscript pstricks shape svg vdx wmf wpg xfig xslt \
-	drs
+	drs stress
 
 # The main target
 all : sub-all
@@ -137,6 +137,12 @@ OBJECTS = \
   shape-export.obj
 !ENDIF
 
+!IFDEF OBJ_stress
+OBJECTS = \
+  stress.obj \
+  stress-memory.obj
+!ENDIF
+
 !IFDEF OBJ_svg
 OBJECTS = \
   svg.obj \
diff --git a/plug-ins/stress/stress-memory.c b/plug-ins/stress/stress-memory.c
new file mode 100644
index 0000000..5d74573
--- /dev/null
+++ b/plug-ins/stress/stress-memory.c
@@ -0,0 +1,131 @@
+/*
+ * stress-memory.c -- functions to play around with virtual memory
+ *
+ * Copyright (C) 2011, Hans Breuer <hans breuer org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* NOTHING Dia specific HERE */
+#include "stress-memory.h"
+
+#ifdef G_OS_WIN32
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#endif
+
+gboolean
+vmem_avail (guint64 *size)
+{
+  guint64 avail = 0;
+  gpointer p = NULL;
+#ifdef G_OS_WIN32
+  MEMORY_BASIC_INFORMATION mbi;
+
+  while (VirtualQuery (p, &mbi, sizeof(mbi))) {
+    if (MEM_FREE == mbi.State)
+      avail += mbi.RegionSize;
+    p = ((char*)mbi.BaseAddress + mbi.RegionSize);
+  }
+#else
+  return FALSE;
+#endif
+  if (size)
+    *size = avail;
+  return (avail > 0);
+}
+
+static GHashTable *virtual_reserved = NULL;
+
+gboolean
+vmem_reserve (guint64 size)
+{
+  if (!virtual_reserved)
+    virtual_reserved = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+#ifdef G_OS_WIN32
+  {
+    /* scan entire process for contiguous blocks of memory */
+    gpointer p = NULL;
+    gsize maxbs = 0, bs; /* maximum block size */ 
+    guint64 size_to_eat = size;
+    guint64 page_size;
+    MEMORY_BASIC_INFORMATION mbi;
+    SYSTEM_INFO si;
+    
+    GetSystemInfo (&si);
+    page_size = si.dwPageSize;
+
+    while (VirtualQuery (p, &mbi, sizeof(mbi))) {
+      if (MEM_FREE == mbi.State)
+        if (mbi.RegionSize > maxbs)
+          maxbs = mbi.RegionSize;
+      p = ((char*)mbi.BaseAddress + mbi.RegionSize);
+    }
+    if (maxbs < page_size)
+      return TRUE;
+    bs = maxbs;
+    while (size_to_eat >= page_size) {
+      /* start with the largest free block */
+      if (size_to_eat > bs) { /* reserve but MEM_COMMIT */
+        p = VirtualAlloc(NULL, bs, MEM_RESERVE, PAGE_READWRITE);
+	if (p) {
+	  g_hash_table_insert (virtual_reserved, p, (gpointer)bs);
+	  size_to_eat -= bs;
+	} else {
+	  /* reduce block size to request as a whole */
+	  if (bs <= page_size)
+	    break;
+	  bs -= page_size;
+	}
+      } else {
+        /* find a convenient bs to start reserving */
+	while (size_to_eat < bs && bs > page_size)
+	  bs = bs >> 1;
+	if (bs < page_size)
+	  break;
+      }
+      /* the while loop is ignoring extra memory used for the hash */
+    }
+    /* done anything */
+    return (size_to_eat < size);
+  }
+#else
+  return FALSE;
+#endif
+}
+
+static void
+_release_one (gpointer key,
+              gpointer value,
+              gpointer user_data)
+{
+#ifdef G_OS_WIN32
+  if (key)
+    VirtualFree(key, 0, MEM_RELEASE);
+#else
+  g_print ("release_one?");
+#endif
+}
+
+void
+vmem_release (void)
+{
+  if (virtual_reserved) {
+    g_hash_table_foreach (virtual_reserved, _release_one, NULL);
+    g_hash_table_destroy (virtual_reserved);
+    virtual_reserved = NULL;
+  }
+}
diff --git a/plug-ins/stress/stress-memory.h b/plug-ins/stress/stress-memory.h
new file mode 100644
index 0000000..bc37d19
--- /dev/null
+++ b/plug-ins/stress/stress-memory.h
@@ -0,0 +1,7 @@
+#include <glib.h>
+
+gboolean vmem_avail (guint64 *size);
+gboolean vmem_reserve (guint64 size);
+void vmem_release (void);
+
+
diff --git a/plug-ins/stress/stress.c b/plug-ins/stress/stress.c
new file mode 100644
index 0000000..f746a96
--- /dev/null
+++ b/plug-ins/stress/stress.c
@@ -0,0 +1,93 @@
+/* Dia -- an diagram creation/manipulation program
+ * Copyright (C) 1998 Alexander Larsson
+ *
+ * autolayout-register.c -  registeration of auto-layout algoritms as plug-in
+ * Copyright (c) 2008 Hans Breuer <hans breuer org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include <config.h>
+
+#include "intl.h"
+#include "message.h"
+#include "filter.h"
+#include "plug-ins.h"
+
+#include "stress-memory.h"
+
+static void
+stress_memory_callback (DiagramData *data,
+                       const gchar *filename,
+                       guint flags, /* further additions */
+                       void *user_data)
+{
+  guint64 avail;
+
+  if (vmem_avail (&avail)) {
+    guint64 eat = (avail * 9) / 10;
+    
+    if (vmem_reserve (eat)) {
+      guint64 still_avail;
+      vmem_avail (&still_avail);
+
+      message_warning ("%d MB of memory reserved,\n%d MB still available.\n",
+                       (guint)((avail - still_avail)>>20),
+		       (guint)(still_avail >> 20));
+    } else {
+      message_error ("Failed to reserve memory.");
+    }
+  } else {
+    message_error ("Failed to calculate available memory.");
+  }
+}
+
+static DiaCallbackFilter cb_stress_memory = {
+    "StressMemory",
+    N_("Stress memory"),
+    "/ToolboxMenu/Debug/StressMemory",
+    stress_memory_callback,
+    NULL
+};
+
+static gboolean
+_plugin_can_unload (PluginInfo *info)
+{
+  /* there is no filter_unregister_callback yet */
+  return TRUE;
+}
+
+static void
+_plugin_unload (PluginInfo *info)
+{
+  vmem_release ();
+}
+
+/* --- dia plug-in interface --- */
+
+DIA_PLUGIN_CHECK_INIT
+
+PluginInitResult
+dia_plugin_init(PluginInfo *info)
+{
+  if (!dia_plugin_info_init(info, "Stress",
+                            _("Stress memory (development tool)"),
+                            _plugin_can_unload,
+                            _plugin_unload))
+    return DIA_PLUGIN_INIT_ERROR;
+
+  filter_register_callback (&cb_stress_memory);
+
+  return DIA_PLUGIN_INIT_OK;
+}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]