about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <e@yhbt.net>2011-02-06 08:04:42 +0000
committerEric Wong <normalperson@yhbt.net>2011-02-06 08:51:00 +0000
commit415296ba1d398983a0ea047134b8ee7d58ac93bc (patch)
tree96fd3781a65037cf7d232949866d859826e162b8
parentab9d3237f622e9db0be25f09bfb5c123318f3974 (diff)
downloadmall-415296ba1d398983a0ea047134b8ee7d58ac93bc.tar.gz
malloc_info() support from glibc as Mall.xml
XML FOR ENTERPRISE!
-rw-r--r--ext/mall/extconf.rb1
-rw-r--r--ext/mall/mall.c.erb51
-rw-r--r--test/test_mall.rb14
3 files changed, 66 insertions, 0 deletions
diff --git a/ext/mall/extconf.rb b/ext/mall/extconf.rb
index a180c71..8fc6cbd 100644
--- a/ext/mall/extconf.rb
+++ b/ext/mall/extconf.rb
@@ -4,5 +4,6 @@ have_header('malloc.h') or abort "malloc.h header missing"
 have_type('struct mallinfo', 'malloc.h') or abort 'struct mallinfo missing'
 have_func('malloc_trim', 'malloc.h')
 have_func('malloc_stats', 'malloc.h')
+have_func('malloc_info', 'malloc.h')
 dir_config('mall')
 create_makefile('mall')
diff --git a/ext/mall/mall.c.erb b/ext/mall/mall.c.erb
index 66c1973..1e15662 100644
--- a/ext/mall/mall.c.erb
+++ b/ext/mall/mall.c.erb
@@ -90,6 +90,52 @@ static VALUE dump_stats(VALUE klass)
 }
 #endif /* HAVE_MALLOC_STATS */
 
+#ifdef HAVE_MALLOC_INFO
+static ID id_ltlt;
+#include <stdio.h>
+#include <errno.h>
+static void xmlerr(FILE *fp, int err, const char *msg)
+{
+        fclose(fp);
+        errno = err ? err : EIO; /* gotta have something */
+        rb_sys_fail(msg);
+}
+
+static VALUE xml(int argc, VALUE *argv, VALUE self)
+{
+        int err;
+        long len;
+        VALUE options, out, buf;
+        int xoptions;
+        FILE *fp;
+
+        rb_scan_args(argc, argv, "02", &options, &out);
+        xoptions = NIL_P(options) ? 0 : NUM2INT(options);
+
+        fp = tmpfile();
+        if (fp == NULL)
+                rb_sys_fail("tmpfile");
+
+        err = malloc_info(xoptions, fp);
+        if (err != 0)
+                xmlerr(fp, err, "malloc_info");
+
+        len = ftell(fp);
+        if (len < 0)
+                xmlerr(fp, errno, "ftell");
+
+        rewind(fp);
+        buf = rb_str_new(0, len);
+        if (fread(RSTRING_PTR(buf), 1, len, fp) != len)
+                xmlerr(fp, ferror(fp), "fread");
+        fclose(fp);
+
+        if (NIL_P(out))
+                return buf;
+        return rb_funcall(out, id_ltlt, 1, buf);
+}
+#endif /* HAVE_MALLOC_INFO */
+
 void Init_mall(void)
 {
         mMall = rb_define_module("Mall");
@@ -101,6 +147,11 @@ void Init_mall(void)
 #ifdef HAVE_MALLOC_STATS
         rb_define_singleton_method(mMall, "dump_stats", dump_stats, 0);
 #endif /* HAVE_MALLOC_STATS */
+#ifdef HAVE_MALLOC_INFO
+        id_ltlt = rb_intern("<<");
+        rb_define_singleton_method(mMall, "xml", xml, -1);
+#endif /* HAVE_MALLOC_INFO*/
+
 <% mallinfo_keys.each { |x| %>
         sym_<%= x %> = ID2SYM(rb_intern("<%= x %>"));
 <% } %>
diff --git a/test/test_mall.rb b/test/test_mall.rb
index 1bbff85..5472acb 100644
--- a/test/test_mall.rb
+++ b/test/test_mall.rb
@@ -32,6 +32,20 @@ class TestMall < Test::Unit::TestCase
     end
   end
 
+  def test_xml
+    if Mall.respond_to?(:xml)
+      str = Mall.xml
+      assert_match /<malloc version=/, str
+
+      tmp = []
+      assert_equal tmp, Mall.xml(0, tmp)
+      assert_match /<malloc version=/, tmp[0]
+      assert_equal 1, tmp.size
+    else
+      warn "Mall.xml not supported"
+    end
+  end
+
   def test_dump_stats
     if Mall.respond_to?(:dump_stats)
       olderr = $stderr.dup