From: Vasileios Karakasis <bkk@cslab.ece.ntua.gr>
To: linux-numa@vger.kernel.org
Cc: 'Kornilios Kourtis' <kkourt@cslab.ece.ntua.gr>
Subject: realloc function
Date: Sun, 02 Jan 2011 19:37:42 +0200 [thread overview]
Message-ID: <4D20B7E6.9020207@cslab.ece.ntua.gr> (raw)
[-- Attachment #1.1: Type: text/plain, Size: 718 bytes --]
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
[-- Attachment #1.2: numactl-2.0.6-rc4-realloc-patch --]
[-- Type: text/plain, Size: 5795 bytes --]
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;
[-- Attachment #1.3: 0x17A67A9C.asc --]
[-- Type: application/pgp-keys, Size: 2858 bytes --]
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 197 bytes --]
next reply other threads:[~2011-01-02 17:37 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-01-02 17:37 Vasileios Karakasis [this message]
2011-01-02 23:42 ` realloc function Andi Kleen
2011-01-03 21:56 ` Vasileios Karakasis
2011-01-03 22:44 ` Cliff Wickman
2011-01-04 22:20 ` Andi Kleen
2011-01-05 12:11 ` Vasileios Karakasis
2011-01-05 15:00 ` Vasileios Karakasis
2011-01-05 19:25 ` Andi Kleen
2011-01-10 22:12 ` Vasileios Karakasis
2011-01-10 22:17 ` Andi Kleen
2011-01-11 16:29 ` Cliff Wickman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4D20B7E6.9020207@cslab.ece.ntua.gr \
--to=bkk@cslab.ece.ntua.gr \
--cc=kkourt@cslab.ece.ntua.gr \
--cc=linux-numa@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).