realloc function
Vasileios Karakasis <[email protected]> Sun, 02 Jan 2011 19:37:42 +0200
| Newsgroups | org.kernel.vger.linux-numa |
|---|---|
| Message-ID | <[email protected]> |
Hi, I am submitting a patch for a realloc function that might be useful. The proposed numa_realloc() is merely a wrapper to mremap(), which it calls with the flag MREMAP_MAYMOVE. The policy of the vm area is copied by the kernel in case of moving. I am also submitting a test program, that keeps expanding an initial allocation until a limit is reached and checks the mempolicy of the expanded area in every iteration. My use case is a dynamic array implementation which uses realloc() to dynamically expand the array and I want to convert it to a numa-aware implementation. PS: I could also submit a brief manpage entry for the new function, if you agree. Best regards, -- Vasileios Karakasis
numactl-2.0.6-rc4-realloc-patch
(text/plain, 5.7 KB)
diff -urN numactl-2.0.6-rc4-orig/libnuma.c numactl-2.0.6-rc4/libnuma.c
--- numactl-2.0.6-rc4-orig/libnuma.c 2011-01-02 16:01:07.000000000 +0200
+++ numactl-2.0.6-rc4/libnuma.c 2011-01-02 16:01:14.000000000 +0200
@@ -871,6 +871,16 @@
return mem;
}
+void *numa_realloc(void *old_addr, size_t old_size, size_t new_size)
+{
+ char *mem;
+ mem = mremap(old_addr, old_size, new_size, MREMAP_MAYMOVE);
+ if (mem == (char *)-1)
+ return NULL;
+ /* Policy and binding of the vm segment are preserved by the kernel */
+ return mem;
+}
+
void *numa_alloc_interleaved_subset_v1(size_t size, const nodemask_t *mask)
{
char *mem;
diff -urN numactl-2.0.6-rc4-orig/Makefile numactl-2.0.6-rc4/Makefile
--- numactl-2.0.6-rc4-orig/Makefile 2010-12-22 13:29:50.000000000 +0200
+++ numactl-2.0.6-rc4/Makefile 2011-01-02 13:32:36.000000000 +0200
@@ -31,7 +31,7 @@
test/after test/before threadtest test_move_pages \
test/mbind_mig_pages test/migrate_pages \
migratepages migspeed migspeed.o libnuma.a \
- test/move_pages
+ test/move_pages test/realloc_test
SOURCES := bitops.c libnuma.c distance.c memhog.c numactl.c numademo.c \
numamon.c shm.c stream_lib.c stream_main.c syscall.c util.c mt.c \
clearcache.c test/*.c
@@ -43,7 +43,7 @@
all: numactl migratepages migspeed libnuma.so numademo numamon memhog \
test/tshared stream test/mynode test/pagesize test/ftok test/prefered \
test/randmap test/nodemap test/distance test/tbitmap test/move_pages \
- test/mbind_mig_pages test/migrate_pages libnuma.a
+ test/mbind_mig_pages test/migrate_pages test/realloc_test libnuma.a
numactl: numactl.o util.o shm.o bitops.o libnuma.so
@@ -123,6 +123,8 @@
test/migrate_pages: test/migrate_pages.c libnuma.so
+test/realloc_test: test/realloc_test.c libnuma.so
+
.PHONY: install all clean html depend
MANPAGES := numa.3 numactl.8 numastat.8 migratepages.8 migspeed.8
diff -urN numactl-2.0.6-rc4-orig/numa.h numactl-2.0.6-rc4/numa.h
--- numactl-2.0.6-rc4-orig/numa.h 2010-12-22 13:29:50.000000000 +0200
+++ numactl-2.0.6-rc4/numa.h 2010-12-22 13:45:42.000000000 +0200
@@ -212,6 +212,8 @@
void *numa_alloc_local(size_t size);
/* Allocation with current policy */
void *numa_alloc(size_t size);
+/* Realloc memory, binding properties are preserved. */
+void *numa_realloc(void *old_addr, size_t old_size, size_t new_size);
/* Free memory allocated by the functions above */
void numa_free(void *mem, size_t size);
diff -urN numactl-2.0.6-rc4-orig/test/realloc_test.c numactl-2.0.6-rc4/test/realloc_test.c
--- numactl-2.0.6-rc4-orig/test/realloc_test.c 1970-01-01 02:00:00.000000000 +0200
+++ numactl-2.0.6-rc4/test/realloc_test.c 2011-01-02 13:25:13.000000000 +0200
@@ -0,0 +1,109 @@
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/mman.h>
+#include "numa.h"
+#include "numaif.h"
+
+#define DEFAULT_NR_PAGES 1024
+
+static int parse_int(const char *str)
+{
+ char *endptr;
+ long ret = strtol(str, &endptr, 0);
+ if (*endptr != '\0') {
+ fprintf(stderr, "[error] strtol() failed: parse error: %s\n", endptr);
+ exit(1);
+ }
+
+ if (errno == ERANGE)
+ fprintf(stderr, "[warning] strtol() out of range\n");
+
+ if (ret > INT_MAX || ret < INT_MIN) {
+ fprintf(stderr, "[warning] parse_int() out of range\n");
+ ret = (ret > 0) ? INT_MAX : INT_MIN;
+ }
+
+ return (int) ret;
+}
+
+int main(int argc, char **argv)
+{
+ char *mem;
+ int page_size = numa_pagesize();
+ int node = 0;
+ int nr_pages = DEFAULT_NR_PAGES;
+
+ if (numa_available() < 0) {
+ fprintf(stderr, "numa is not available");
+ exit(1);
+ }
+
+ if (argc > 1)
+ node = parse_int(argv[1]);
+ if (argc > 2)
+ nr_pages = parse_int(argv[2]);
+
+ mem = numa_alloc_onnode(page_size, node);
+
+ /* Store the policy of the newly allocated area */
+ unsigned long nodemask;
+ int mode;
+ int nr_nodes = numa_num_possible_nodes();
+ if (get_mempolicy(&mode, &nodemask, nr_nodes, mem,
+ MPOL_F_NODE | MPOL_F_ADDR) < 0) {
+ perror("get_mempolicy() failed");
+ exit(1);
+ }
+
+ /* Print some info */
+ printf("Page size: %d\n", page_size);
+ printf("Pages realloc'ed: %d\n", nr_pages);
+ printf("Allocate data in node: %d\n", node);
+
+ /* Request pages until a realloc moves the data */
+ int i;
+ int nr_inplace = 0;
+ int nr_moved = 0;
+ for (i = 0; i < nr_pages; i++) {
+ /* Enlarge mem with one more page */
+ char *new_mem = numa_realloc(mem, (i+1)*page_size, (i+2)*page_size);
+ if (!new_mem) {
+ perror("numa_realloc() failed");
+ exit(1);
+ }
+
+ if (new_mem == mem)
+ ++nr_inplace;
+ else
+ ++nr_moved;
+ mem = new_mem;
+
+ /* Check the policy of the realloc'ed area */
+ unsigned long realloc_nodemask;
+ int realloc_mode;
+ if (get_mempolicy(&realloc_mode, &realloc_nodemask,
+ nr_nodes, mem, MPOL_F_NODE | MPOL_F_ADDR) < 0) {
+ perror("get_mempolicy() failed");
+ exit(1);
+ }
+
+ assert(realloc_nodemask == nodemask &&
+ realloc_mode == mode && "policy changed");
+ }
+
+ /* Shrink to the original size */
+ mem = numa_realloc(mem, (nr_pages + 1)*page_size, page_size);
+ if (!mem) {
+ perror("numa_realloc() failed");
+ exit(1);
+ }
+
+ numa_free(mem, page_size);
+ printf("In-place reallocs: %d\n", nr_inplace);
+ printf("Moved reallocs: %d\n", nr_moved);
+ return 0;
+}
diff -urN numactl-2.0.6-rc4-orig/versions.ldscript numactl-2.0.6-rc4/versions.ldscript
--- numactl-2.0.6-rc4-orig/versions.ldscript 2010-12-22 13:29:50.000000000 +0200
+++ numactl-2.0.6-rc4/versions.ldscript 2010-12-22 20:41:22.000000000 +0200
@@ -87,6 +87,7 @@
numa_alloc_interleaved_subset;
numa_alloc_local;
numa_alloc_onnode;
+ numa_realloc;
numa_allocate_cpumask;
numa_allocate_nodemask;
numa_available;
0x17A67A9C.asc
(application/pgp-keys, 2.7 KB)
-----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v1.4.9 (GNU/Linux) mQGiBENcm2URBACj6CgSinpfmIwniRJJkWYgn1zrZdHZxW+ZFVp1GJxAE7zkd/NX z8C2ZcDW6dBgtCmNMgythflvIuTVJx/6fZJcVe5Y5YU9RxIoBHI2BhyxEKEbQ3oW rGWlXt9QIf0zc0RKGpTuE6XmRr8JUuI/JvBSzE6/SnRtmzqg/AMdyxRjvwCg8/lm VYqnIxX/0+L18U5WfgpOZGsD/0YS9ann3vCkRWgT4mQdGBA3oHHQQMlpxJeva409 UiYnlUTGySw8yNiC+a8Jeklv6TH1JM/l7nZzJJR49800oyw7TYgwbrXI6bp2F4PU 7bI2Fz5nmvX/z2Be/XP+rfYp6ItYBQ5QOXk7Yj6LY+sXS4s2BcP0IpSiqSGxT80c rbkaA/sH2MPry2d8EqVUbb+1zYs3RCQ6+0wtUbRHnSI8yhWKEw4GZcwsBfshNGhV e4t9F5xFpROCJe+uBeIl5lCzlywYDyjEnS4cfFkVKJ2MjXPqrF53T7k3Nw1/iA3u NfXRMzjjDQeJ8toYciu1i7+sL309m73oj+nqfJVvtX8LZWw+z7QuVmFzaWxlaW9z IEsuIEthcmFrYXNpcyA8YmtrQGNzbGFiLmVjZS5udHVhLmdyPohjBBMRAgAjBgsJ CAcDAgQVAggDBBYCAwECHgECF4AFAkxArL4FCRJKEtMACgkQHUHhfRemepxq9ACe KCjvjKwXxi1ma5a6tUKs55OadTYAoNZTi6i7UFPsPn4kkr7buA259qJjiGMEExEC ACMFAkNcm2UFCQWjmoAGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAKCRAdQeF9F6Z6 nKD3AKDCmqk62drTmkvYTE/JyQ25OsCN/ACfbye1hOZCEIKH2NYpk2p80alx8c2I YwQTEQIAIwYLCQgHAwIEFQIIAwQWAgMBAh4BAheABQJI7gUzBQkJU9DOAAoJEB1B 4X0XpnqcX3YAn3C+lRbO/s8G8p2vumlHFzKLu/VGAJkBbFj7hzUSKPZOd+SgeNJT UFGUkIhjBBMRAgAjBgsJCAcDAgQVAggDBBYCAwECHgECF4AFAkkIiBEFCQluU6wA CgkQHUHhfRemepzcaACfYM7cXDp5uYTOdgZXopewwDvTHLIAnA1E12YEbs1OyF+p wMxxVEiHwa9puQQNBENcnbwQEADsbm26j/NhEPJ1oksnw0oC1i8SkW5m0LIySa7E PuU7tI/RMMClxRmOztjthWB3BDbqIJF5ZIfGwwqlvDn6RWOMct2uTS/XtQPjJZcK vJaL1+YQnNoFUTpnzVJKOgnUcb52MV129etIlTM/Pav+U7241uds3m1IKjpvNI8S uG8wcQy1HxLBKxP32vPCUJOEcy4bLVMKlopBtqvGiweurNIvJaNAAHJuS6bbCyPl mzG/sHTVC1FvCR+TE4NQPxRCWom05AW4ZbpRLTZX1TghTJ4plvBBSovTTfHEo0if 7j0PNbFdSU+I7/okpDWB1AdP0RqK/bsRctA6ROg1hAJMmF/b3dYWMow5poHETIeM TgTecOsUc+nwteO9zSgy0UaI384pkqZ7CGfrocM2s5HepDlH3UQklsuw25EzgnCT Hrj8e+S5mW2gZM4bs2u+n0g0BeRrhWoxz+DNwxwgCovoHvs6yeRtibkQuCXemoxb ryamKwo+c/j52sURa2h0dPtvR/+tyg/Bs4ly9KJStCXiGPF+gMNgyfPM2pkhqE9Q rsVhZq+NWIGcQZIlCEGJlewantwy0VsiuCKQVQfOyz1si+50TSGPUp2WahNOrKBi S4TnlHcorfVnwy9gMV8BsAhy8Y8AGgYfJPGdYEPBbc8OjIx/3nIrZpIOHGpLFMtk deWi8wADBhAA5hkkXW1Ig61sQ5cIBBRjEsqbOvbF3oStWXXOIBo83ec4ebzclpRP mszndRgUupPs9/snMHDQHvHCFV2+LbA+y6mE7lXHT6zza0sPejUZrnz8bY4lUXI9 S6P38nJzbZAHiybGQMbaPI4YV+bCYLF4a8V4pJ/m+rEn5ZvQU48I8oH0nBPhS5Hd 8bWsza+Njr3V3hr22isW9/cz+w7nTXbFjLVpNtdTr2HlB/T143NgLFU2IyToi437 SxO5denkVDK66GxZ0a1EAHaaC1PImdTtYWjd/9t/MVFqtL4qrbun8bHldQnjFVIE m+MPiLmTbn53CChJ/3gNaYL+S0S4cxPLOBdEdZ62AnVtlvuE/S1aKGvhV5KvCafk qx0Pqv3FNyBhJqVVYfGA98MIJRHDWBO4uw8BVHh/5KpH+WIpn6zMyBx04DBGNvZP UinKsbKY7kIy0jB+9LE3vwqYPnQj79GAAxvnOqkwrhhbXIP+TqaeahPVe3MBIxDg 0nwsToRtd6f6WipDLOgYLA2rc4KdJ9kYTmyn1DJWx6N6WE20dwd6HVo+6Tp+hQTf ZZj+KjTsa/C47HbGpu2QZ+dtEOxHSiiBLqnNH7Bc7KozuoTCzNzIEGxUfjmvbYht SlfchiK/+MJFzpi6ot/7hIOoYwqoTVPzZTr3vzKfEgTylPLXpH2JJgaITAQYEQIA DAUCTECtBQUJEkoQxQAKCRAdQeF9F6Z6nNgbAKC+KGnNaTKJPx5VTurjEp9mW215 qgCdEHEBN5VcuGHZ5q/BfHeSXLcApFY= =MPxZ -----END PGP PUBLIC KEY BLOCK-----
signature.asc
(application/pgp-signature, 197 B)
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) iEYEARECAAYFAk0gt+YACgkQHUHhfRemepxFNgCgoM8SlyREpOlWK41+J7+kzfSn nAkAoOZr7naLFFksiDaBsum18gOO0aUB =ZwE2 -----END PGP SIGNATURE-----