Rewrite critical search inner loop in C for speed.
[virt-mem.git] / lib / virt_mem_mmap_c.c
diff --git a/lib/virt_mem_mmap_c.c b/lib/virt_mem_mmap_c.c
new file mode 100644 (file)
index 0000000..29dca72
--- /dev/null
@@ -0,0 +1,77 @@
+/* Memory info command for virtual domains.
+   (C) Copyright 2008 Richard W.M. Jones, Red Hat Inc.
+   http://libvirt.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+   This contains hand-coded C functions written for speed.
+*/
+
+#include <config.h>
+
+#include <string.h>
+
+#include <caml/config.h>
+#include <caml/alloc.h>
+#include <caml/memory.h>
+#include <caml/mlvalues.h>
+#include <caml/bigarray.h>
+
+CAMLprim value
+virt_mem_mmap_find_in (value startv, value alignv, value strv, value arrv)
+{
+  CAMLparam4 (startv, alignv, strv, arrv);
+  CAMLlocal2 (rv, vv);
+  long start = Long_val (startv); /* Start offset for search. */
+  long align = Long_val (alignv); /* Alignment for search. */
+  char *str = String_val (strv);  /* String to search for. */
+  int strlen = caml_string_length (strv);
+  void *data = Data_bigarray_val (arrv); /* Data in bigarray. */
+  int datalen = Bigarray_val(arrv)->dim[0]; /* Total length of bigarray. */
+  long i, r = -1;
+  void *p;
+
+  /* memmem is a GNU extension.  Note that we cannot use strstr because
+   * OCaml strings may contain NULs, and in this case it is very likely
+   * that it does contain NULs.
+   */
+#ifdef HAVE_MEMMEM
+  if (align == 1) {
+    p = memmem (data+start, datalen-start, str, strlen);
+    r = p ? p-data : -1;
+    goto ret;
+  }
+#endif
+
+  p = data+start;
+  for (i = start; i < datalen-strlen; i += align) {
+    if (memcmp (p, str, strlen) == 0) {
+      r = p-data;
+      goto ret;
+    }
+    p += align;
+  }
+
+ ret:
+  if (r == -1)
+    rv = Val_int (0);          /* None */
+  else {
+    vv = Val_long (r);         /* Some r */
+    rv = caml_alloc (1, 0);
+    Store_field (rv, 0, vv);
+  }
+
+  CAMLreturn (rv);
+}