aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/drivers/unix/mem_drv.c
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/drivers/unix/mem_drv.c')
-rw-r--r--erts/emulator/drivers/unix/mem_drv.c145
1 files changed, 145 insertions, 0 deletions
diff --git a/erts/emulator/drivers/unix/mem_drv.c b/erts/emulator/drivers/unix/mem_drv.c
new file mode 100644
index 0000000000..1417ca1121
--- /dev/null
+++ b/erts/emulator/drivers/unix/mem_drv.c
@@ -0,0 +1,145 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 1996-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+/* Purpose: Access to elib memory statistics */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "sys.h"
+#include "erl_driver.h"
+#include "elib_stat.h"
+
+#define MAP_BUF_SIZE 1000 /* Max map size */
+#define HISTO_BUF_SIZE 100 /* Max histogram buckets */
+
+static ErlDrvData mem_start(ErlDrvPort);
+static int mem_init(void);
+static void mem_stop(ErlDrvData);
+static void mem_command(ErlDrvData, char*, int);
+
+const struct driver_entry mem_driver_entry = {
+ mem_init,
+ mem_start,
+ mem_stop,
+ mem_command,
+ NULL,
+ NULL,
+ "mem_drv"
+};
+
+static int mem_init(void)
+{
+ return 0;
+}
+
+static ErlDrvData mem_start(ErlDrvPort port, char* buf)
+{
+ return (ErlDrvData)port;
+}
+
+static void mem_stop(ErlDrvData port)
+{
+}
+
+void putint32(p, v)
+byte* p; int v;
+{
+ p[0] = (v >> 24) & 0xff;
+ p[1] = (v >> 16) & 0xff;
+ p[2] = (v >> 8) & 0xff;
+ p[3] = (v) & 0xff;
+}
+
+int getint16(p)
+byte* p;
+{
+ return (p[0] << 8) | p[1];
+}
+
+/*
+** Command:
+** m L1 L0 -> a heap map of length L1*256 + L0 is returned
+** s -> X3 X2 X1 X0 Y3 Y2 Y1 Y0 Z3 Z2 Z1 Z0
+** X == Total heap size bytes
+** Y == Total free bytes
+** Z == Size of largest free block in bytes
+**
+** h L1 L0 B0 -> Generate a logarithm historgram base B with L buckets
+** l L1 L0 S0 -> Generate a linear histogram with step S with L buckets
+*/
+unsigned char outbuf[HISTO_BUF_SIZE*2*4];
+
+static void mem_command(ErlDrvData port, char* buf, int count)
+{
+ if ((count == 1) && buf[0] == 's') {
+ struct elib_stat info;
+ char v[3*4];
+
+ elib_stat(&info);
+
+ putint32(v, info.mem_total*4);
+ putint32(v+4, info.mem_free*4);
+ putint32(v+8, info.max_free*4);
+ driver_output((ErlDrvPort)port, v, 12);
+ return;
+ }
+ else if ((count == 3) && buf[0] == 'm') {
+ char w[MAP_BUF_SIZE];
+ int n = getint16(buf+1);
+
+ if (n > MAP_BUF_SIZE)
+ n = MAP_BUF_SIZE;
+ elib_heap_map(w, n);
+ driver_output((ErlDrvPort)port, w, n);
+ return;
+ }
+ else if ((count == 4) && (buf[0] == 'h' || buf[0] == 'l')) {
+ unsigned long vf[HISTO_BUF_SIZE];
+ unsigned long va[HISTO_BUF_SIZE];
+ int n = getint16(buf+1);
+ int base = (unsigned char) buf[3];
+
+ if (n >= HISTO_BUF_SIZE)
+ n = HISTO_BUF_SIZE;
+ if (buf[0] == 'l')
+ base = -base;
+ if (elib_histo(vf, va, n, base) < 0) {
+ driver_failure((ErlDrvPort)port, -1);
+ return;
+ }
+ else {
+ char* p = outbuf;
+ int i;
+
+ for (i = 0; i < n; i++) {
+ putint32(p, vf[i]);
+ p += 4;
+ }
+ for (i = 0; i < n; i++) {
+ putint32(p, va[i]);
+ p += 4;
+ }
+ driver_output((ErlDrvPort)port, outbuf, n*8);
+ }
+ return;
+ }
+ driver_failure((ErlDrvPort)port, -1);
+}