diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000000000000000000000000000000000000..916369adbc0393fa6f00a0e341cbac565de1579b --- /dev/null +++ b/.travis.yml @@ -0,0 +1,9 @@ +language: c +compiler: + - clang + - gcc +before_install: + - sudo apt-get update -qq + - sudo apt-get install -y uuid-dev valgrind + - cp src/test/testconfig.sh.example src/test/testconfig.sh +script: make && make test && make check diff --git a/LICENSE b/LICENSE index 0c6a355680d69d2c2c5c88e3508ae0b5bbc68aba..18f3bf75c12a4b14f7280d6719ecd54cb6375b33 100644 --- a/LICENSE +++ b/LICENSE @@ -34,3 +34,5 @@ with the following exceptions: * src/jemalloc has its own (somewhat similar) license contained in src/jemalloc/COPYING. + +* utils/cstyle (used only during development) licensed under CDDL. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..8b613a3606b906e195ecd70080d35309cdd3bd03 --- /dev/null +++ b/Makefile @@ -0,0 +1,78 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# +# Makefile -- top-level Makefile for NVM Library +# +# Use "make" to build the library. +# +# Use "make test" to build unit tests. +# +# Use "make check" to run unit tests. +# +# Use "make clean" to delete all intermediate files (*.o, etc). +# +# Use "make clobber" to delete everything re-buildable (binaries, etc.). +# +# Use "make cstyle" to run cstyle on all C source files +# +# Use "make source DESTDIR=path_to_dir" to copy source files +# from HEAD to 'path_to_dir/nvml' directory. +# +# As root, use "make install" to install the library in the usual +# locations (/usr/lib, /usr/include, and /usr/share/man). +# You can provide custom directory prefix for installation using +# DESTDIR variable e.g.: "make install DESTDIR=/opt" + +all clean clobber: + $(MAKE) -C src $@ + $(MAKE) -C examples $@ + $(MAKE) -C doc $@ + +test check: + $(MAKE) -C src $@ + +cstyle: + $(MAKE) -C src $@ + $(MAKE) -C examples $@ + +source: + $(if $(shell git rev-parse 2>&1), $(error Not a git repository)) + $(if $(shell git status --porcelain), $(error Working directory is dirty)) + $(if $(DESTDIR), , $(error Please provide DESTDIR variable)) + mkdir -p $(DESTDIR)/nvml + git archive HEAD | tar -x -C $(DESTDIR)/nvml + +install: + $(MAKE) -C src $@ + $(MAKE) -C doc $@ + +.PHONY: all clean clobber test check cstyle install source $(SUBDIRS) diff --git a/README.md b/README.md index 9648da68163320fa948d0fe481b09fc58740565d..e6bce55501b7f6e6318ca21620feaff912952cbf 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,56 @@ -nvml -==== +nvml: Linux NVM Library +======================= -NVM Library +[](https://travis-ci.org/pmem/nvml) +This is the top-level README.md the Linux NVM Library. +For more information, see http://pmem.io. -**Coming Soon...** +Please see the file LICENSE for information on how this library is licensed. + +This tree contains libaries for using Non-Volatile Memory (NVM). +Here you'll find: + +* **doc** -- man pages describing each library contained here +* **examples** -- brief example programs using these libraries +* **src** -- the source for the libraries +* **utils** -- utilities used during build & test +* **CONTRIBUTING.md** -- instructions for people wishing to contribute + +To build this library, you may need to install some required packages on +the build system. See the **before_install:** rules in the +[.travis.yml](https://github.com/pmem/nvml/blob/master/.travis.yml) +file at the top level of the repository to get an idea what packages +were required to build on the _travis-ci_ (Ubuntu-based) systems. + +Once the build system is setup, the NVM Library is built using +this command at the top level: +``` + $ make +``` + +To build and run the unit tests: +``` + $ make check +``` + +To install this library into the standard locations +(/usr/lib, /usr/include, /usr/share/man), become root and: +``` + $ make install +``` + +To install this library into other locations, you can use +DESTDIR variable, e.g.: +``` + $ make install DESTDIR=/tmp +``` +This will install files to /tmp/lib, /tmp/include /tmp/usr/share/man. + +To install a complete copy of the source tree to $(DESTDIR)/nvml: +``` + $ make source DESTDIR=some_path +``` + +For more information on this library, +contact Andy Rudoff (andy.rudoff@intel.com). diff --git a/benchmarks/.gitignore b/benchmarks/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..f47cb2045f130d56b12a40b1ab207bd492281c17 --- /dev/null +++ b/benchmarks/.gitignore @@ -0,0 +1 @@ +*.out diff --git a/benchmarks/Makefile b/benchmarks/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..72fc6be84ec1f9cf65ffa80a2cccce5af9a458ac --- /dev/null +++ b/benchmarks/Makefile @@ -0,0 +1,48 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# Makefile -- build all benchmarks +# +BENCHMARK = mt + +all : TARGET = all +clean : TARGET = clean +clobber : TARGET = clobber +cstyle : TARGET = cstyle + +all clean clobber cstyle: $(BENCHMARK) + +$(BENCHMARK): + $(MAKE) -C $@ $(TARGET) + +.PHONY: all clean clobber cstyle $(BENCHMARK) diff --git a/benchmarks/Makefile.inc b/benchmarks/Makefile.inc new file mode 100644 index 0000000000000000000000000000000000000000..760341ba3472f3a34df9b8824b2fd220606ea692 --- /dev/null +++ b/benchmarks/Makefile.inc @@ -0,0 +1,59 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/Makefile.inc -- common Makefile defs for benchmarks +# + +LIBS = +INCS = +DEFS = +CFLAGS = -ggdb -Wall -Werror -std=gnu99 + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(CC) -o $@ $(OBJS) $(LIBS) + +%.o: %.c + $(CC) -c $(CFLAGS) $(INCS) $(DEFS) $< -o $@ + +clean: + $(RM) *.o */*.o *.out *.png + +clobber: clean + $(RM) $(TARGET) $(ADD_TARGETS) + +cstyle: + ../../utils/cstyle -pP *.c + +.PHONY: all clean clobber cstyle diff --git a/benchmarks/README b/benchmarks/README new file mode 100644 index 0000000000000000000000000000000000000000..07d733614a831e6c9a8786d03f22df649e3db7b2 --- /dev/null +++ b/benchmarks/README @@ -0,0 +1,12 @@ +Linux NVM Library + +This is benchmarks/README. + +This directory contains benchmarks for NVM Library. + +Benchmarks may be built and run from this directory using: + $ make + $ make run + +The subdirectories here contain benchmarks, which each subdirectory +containing one benchmark and corresponding scripts. diff --git a/benchmarks/mt/.gitignore b/benchmarks/mt/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..d0ff685ba0f093041501a210eb5da7a97fb4ca1f --- /dev/null +++ b/benchmarks/mt/.gitignore @@ -0,0 +1,3 @@ +benchmark_mt +benchmark_pool_mt +*.png diff --git a/benchmarks/mt/Makefile b/benchmarks/mt/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..f717084b5dcf237b5a6a62984ec5ff97777d144c --- /dev/null +++ b/benchmarks/mt/Makefile @@ -0,0 +1,47 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# benchmarks/mt/Makefile -- build multi-threading scaling benchmark +# +TARGET = benchmark_mt +VMEM_PATH=../../src/nondebug/ + +OBJS = mt.o tasks.o + +include ../Makefile.inc + +LIBS := -Wl,-rpath,$(VMEM_PATH) -L$(VMEM_PATH) -lvmem -lpthread +INCS := -I../../src/include/ -I. + +mt.o: mt.c +tasks.o: tasks.c tasks.h diff --git a/benchmarks/mt/README b/benchmarks/mt/README new file mode 100644 index 0000000000000000000000000000000000000000..00ae12e25db70dcc96549c0f3bfc042e7b3eef53 --- /dev/null +++ b/benchmarks/mt/README @@ -0,0 +1,40 @@ +Linux NVM Library + +This is benchmarks/mt/README. + +This directory contains the multithreaded allocations benchmark. + +mt benchmark serves as a comparison tool between any malloc library and libvmem, +it measures the number of malloc and free operations per second. + +Benchmark run can be configured to use certain number of threads to allocate +given amount of memory. + +By default, the makefile builds the application without linking to any +non-standard malloc libraries. + +The application itself requires two arguments: thread count and +operations count. First, the benchmark performs mallocs in threads, then frees +the allocated memory. Time spent doing these operations is measured separately. +By default libvmem is used, to choose different allocator use '-e' option. +For more informations about the application usage invoke --help ('-?'). + +In order to compare libvmem against other allocators, +set LD_PRELOAD environment variable before running the benchmark. + +For example, running this command before the benchmark: +export LD_PRELOAD=$LD_PRELOAD:/path/to/jemalloc/libjemalloc.so +will allow you to measure the performance of jemalloc. + +For convenience, there is a simple RUN.sh script provided that will compare +libvmem with provided library and generate results charts. To use it simply do: +./RUN.sh [malloc_library.so] + +The results of the benchmark are printed to standard output, use provided +gnuplot scripts (gnuplot_mt_free.p, gnuplot_mt_malloc.p) to visualize them. + +Output format: +total malloc operations time;malloc operations per second; +total free operations time;free operations per second; + +See the top-level README for instructions on building the entire library. diff --git a/benchmarks/mt/RUN.sh b/benchmarks/mt/RUN.sh new file mode 100755 index 0000000000000000000000000000000000000000..a94b2651431827adb332c8bb0bb4221d0bad77f8 --- /dev/null +++ b/benchmarks/mt/RUN.sh @@ -0,0 +1,22 @@ +#! /bin/bash + +LIB=$1 +MALLOCS_COUNT=10000000 +MAX_THREADS=32 +RUNS=`seq $MAX_THREADS` +SMALL=512 +VMEM_OUT=benchmark_mt_vmem.out +MALLOC_OUT=benchmark_mt.out + +rm $VMEM_OUT +for i in $RUNS ; do + ./benchmark_mt -e vmem -s $SMALL $i $MALLOCS_COUNT >> $VMEM_OUT; +done + +export LD_PRELOAD=$LD_PRELOAD:$LIB +rm $MALLOC_OUT +for i in $RUNS ; do + ./benchmark_mt -e malloc -s $SMALL $i $MALLOCS_COUNT >> $MALLOC_OUT; +done + +gnuplot *.p diff --git a/benchmarks/mt/gnuplot_mt_free.p b/benchmarks/mt/gnuplot_mt_free.p new file mode 100644 index 0000000000000000000000000000000000000000..690ccef074c0a7cadb2740e972246e2626facf6b --- /dev/null +++ b/benchmarks/mt/gnuplot_mt_free.p @@ -0,0 +1,16 @@ +set terminal png size 1000,500 +set output "benchmark_free.png" +set autoscale +set datafile separator ';' +unset log +unset label +set grid +set xtic auto +set size ratio 0.5 +set ytic auto +set title "jemalloc library thread scaling" +set xlabel "Threads" +set ylabel "Operations per second" +set key inside right bottom +plot "benchmark_mt_vmem.out" using ($0+1):4 title "vmem" with linespoints, \ +"benchmark_mt.out" using ($0+1):4 title "free" with linespoints diff --git a/benchmarks/mt/gnuplot_mt_malloc.p b/benchmarks/mt/gnuplot_mt_malloc.p new file mode 100644 index 0000000000000000000000000000000000000000..00c0a8265d792c80908f2a0aa31f3e478624661a --- /dev/null +++ b/benchmarks/mt/gnuplot_mt_malloc.p @@ -0,0 +1,16 @@ +set terminal png size 1000,500 +set output "benchmark_malloc.png" +set autoscale +set datafile separator ';' +unset log +unset label +set grid +set xtic auto +set size ratio 0.5 +set ytic auto +set title "jemalloc library thread scaling" +set xlabel "Threads" +set ylabel "Operations per second" +set key inside right bottom +plot "benchmark_mt_vmem.out" using ($0+1):2 title "vmem" with linespoints, \ +"benchmark_mt.out" using ($0+1):2 title "malloc" with linespoints diff --git a/benchmarks/mt/mt.c b/benchmarks/mt/mt.c new file mode 100644 index 0000000000000000000000000000000000000000..fff66a104ff3aed04a9af2345ef99460df4f9221 --- /dev/null +++ b/benchmarks/mt/mt.c @@ -0,0 +1,301 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY LOG OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * mt.c -- multi-threaded malloc benchmark + */ + +#include <stdio.h> +#include <stdint.h> +#include <ctype.h> +#include <string.h> +#include <argp.h> +#include "tasks.h" + +#define MAX_THREADS 8 +#define DEF_ALLOC 512 +#define KB 1024 +#define MB 1024 * KB + +void **allocated_mem; + +const char *argp_program_version = "mt_benchmark 1.2"; +static char doc[] = "Multithreaded allocator benchmark"; +static char args_doc[] = "THREAD_COUNT OPS_COUNT"; + +static struct argp_option options[] = { + {"pool-per-thread", 'p', 0, 0, + "Create a pool for each worker thread"}, + {"seed", 'r', "SEED", 0, + "Seed for random size allocator"}, + {"size", 's', "SIZE", 0, "Allocation size in bytes " + "(default: 512b); single number for static allocator;" + " comma separated min and max allocation size for ranged"}, + {"allocator", 'e', "NAME", 0, "Allocator to benchmark\n" + "Valid arguments: vmem (default), malloc"}, + { 0 } +}; + +#define ALLOCATOR_NAME_MAX_LEN 10 +static const char *allocator_names[] = {"vmem", "malloc"}; + +task_f tasks[MAX_TASK] = { + task_malloc, + task_free +}; + +/* + * parse_range -- parses allocation size provided by user and sets apropriate + * fields in arguments_t structure + * + * Syntax of input: + * - ALLOCATION_STATIC: <number> + * - ALLOCATION_RANGE: <number,number> + */ +int +parse_range(arguments_t *arguments, char *allocation_size) +{ + char *endptr; + + int size_param; + + char *size = strtok(allocation_size, ","); + if (size == NULL) + return FAILURE; + + size_param = strtol(size, &endptr, 10); + if (*endptr != 0) { + return FAILURE; + } + + size = strtok(NULL, ","); + if (size == NULL) { + arguments->allocation_size_max = size_param; + arguments->allocation_type = ALLOCATION_STATIC; + } else { + arguments->allocation_size = size_param; + arguments->allocation_type = ALLOCATION_RANGE; + + arguments->allocation_size_max = strtol(size, &endptr, 10); + size_param = strtol(size, &endptr, 10); + if (*endptr != 0) { + return FAILURE; + } + + if (size_param < arguments->allocation_size) { + fprintf(stderr, + "Range param: min > max!\n"); + return FAILURE; + } else { + arguments->allocation_size_max = size_param; + } + } + + return SUCCESS; +} + +char *allocation_size_str = NULL; + +/* + * parse_opt -- argp parsing function + */ +static error_t +parse_opt(int key, char *arg, struct argp_state *state) +{ + arguments_t *arguments = state->input; + char *endptr; + int i; + + switch (key) { + case 'p': + arguments->pool_per_thread = 1; + break; + case 's': + allocation_size_str = arg; + break; + case 'r': + arguments->seed = strtol(arg, &endptr, 10); + if (*endptr != 0) { + fprintf(stderr, + "Invalid seed count: %s\n", + endptr); + argp_usage(state); + return EXIT_FAILURE; + } + break; + case 'e': + for (i = 0; i < MAX_ALLOCATOR; ++i) { + if (strncmp(arg, allocator_names[i], + ALLOCATOR_NAME_MAX_LEN) == 0) { + arguments->allocator = i; + break; + } + } + allocator = arguments->allocator; + if (i == MAX_ALLOCATOR) { + fprintf(stderr, + "Unknown allocator %s, using default\n", + arg); + } + break; + case ARGP_KEY_ARG: + switch (state->arg_num) { + case 0: + arguments->thread_count = strtol(arg, &endptr, 10); + if (*endptr != 0) { + fprintf(stderr, + "Invalid thread count: %s\n", + endptr); + argp_usage(state); + return EXIT_FAILURE; + } + break; + case 1: + arguments->ops_count = strtol(arg, &endptr, 10); + if (*endptr != 0) { + fprintf(stderr, + "Invalid operation count: %s\n", + endptr); + argp_usage(state); + return EXIT_FAILURE; + } + break; + default: + argp_usage(state); + return ARGP_ERR_UNKNOWN; + } + break; + case ARGP_KEY_END: + if (state->arg_num < 2) + argp_usage(state); + + if (allocation_size_str == NULL || + parse_range(arguments, allocation_size_str) + == FAILURE) { + arguments->allocation_size_max = DEF_ALLOC; + arguments->allocation_type = ALLOCATION_STATIC; + } + break; + default: + return ARGP_ERR_UNKNOWN; + } + + return 0; +} + +static struct argp argp = { options, parse_opt, args_doc, doc }; + +/* + * main -- entry point, initializes allocated_mem and runs the tasks + */ +int +main(int argc, char *argv[]) +{ + int i, fails = 0; + double task_duration; + void **arg = NULL; + uint64_t pool_size; + arguments_t arguments; + int per_thread_args = 0; + arguments.pool_per_thread = 0; + arguments.allocator = ALLOCATOR_VMEM; + argp_parse(&argp, argc, argv, 0, 0, &arguments); + int pools_count = arguments.pool_per_thread ? + arguments.thread_count : 1; + VMEM *pools[pools_count]; + void *pools_data[pools_count]; + allocated_mem = calloc(arguments.ops_count, sizeof (void*)); + + if (arguments.allocator == ALLOCATOR_VMEM) { + if (arguments.pool_per_thread && + arguments.thread_count > MAX_THREADS) { + fprintf(stderr, "Maximum allowed thread count" + " with pool per thread option enabled is %u\n", + MAX_THREADS); + return EXIT_FAILURE; + } + + pools_count = arguments.pool_per_thread ? + arguments.thread_count : 1; + per_thread_args = arguments.pool_per_thread; + pool_size = arguments.ops_count * + arguments.allocation_size_max * 2u; + + pool_size /= pools_count; + + if (pool_size < 160 * MB) { + pool_size = 160 * MB; + } + + for (i = 0; i < pools_count; ++i) { + pools_data[i] = malloc(pool_size); + if (pools_data[i] == NULL) { + free(allocated_mem); + fprintf(stderr, + "Cannot allocate memory for pool\n"); + return EXIT_FAILURE; + } + pools[i] = vmem_pool_create_in_region(pools_data[i], + pool_size); + if (pools[i] == NULL) { + fprintf(stderr, "Cannot create vmem pool\n"); + } + } + arg = (void **)pools; + } + + /* Cache warmup. */ + for (i = 0; i < MAX_TASK; ++i) { + fails += run_threads(&arguments, tasks[i], + per_thread_args, arg, &task_duration); + } + + for (i = 0; i < MAX_TASK; ++i) { + fails += run_threads(&arguments, tasks[i], + per_thread_args, arg, &task_duration); + printf("%f;%f;", + task_duration, arguments.ops_count/task_duration); + } + + printf("\n"); + + if (arguments.allocator == ALLOCATOR_VMEM) { + for (i = 0; i < pools_count; ++i) { + vmem_pool_delete(pools[i]); + free(pools_data[i]); + } + } + + free(allocated_mem); + + return (fails == 0) ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/benchmarks/mt/tasks.c b/benchmarks/mt/tasks.c new file mode 100644 index 0000000000000000000000000000000000000000..c73846f899cf291a8d766cef01016e67cf6b42a5 --- /dev/null +++ b/benchmarks/mt/tasks.c @@ -0,0 +1,157 @@ +#include <tasks.h> +#include <pthread.h> +#include <sys/time.h> + +#define USEC_IN_SEC 1000000.0 + +struct task_def { + int start; + int end; + task_f task; + int result; + void *arg; + struct random_data *rand_state; +}; + +static allocation_type_t allocation_type; +static int allocation_min; +static int allocation_max; +allocator_t allocator; + +/* + * do_task -- thread start routine, + * performs task_f on values between start and end. + */ +void * +do_task(void *arg) +{ + struct task_def *t_def = arg; + int i; + + for (i = t_def->start; i < t_def->end; ++i) { + t_def->result = t_def->task(i, t_def->arg, t_def->rand_state); + } + + return NULL; +} + +/* + * run_threads -- performs runs number of tasks on threads + */ +int +run_threads(arguments_t *arguments, task_f task, int per_thread_arg, void **arg, + double *elapsed) +{ + int i, n, ret = 0; + pthread_t threads[arguments->thread_count]; + struct task_def t_def[arguments->thread_count]; + char *random_statebuf; + struct timeval task_start, task_stop; + + allocation_type = arguments->allocation_type; + allocation_min = arguments->allocation_size; + allocation_max = arguments->allocation_size_max; + + random_statebuf = (char *)calloc(arguments->thread_count, 32); + + n = arguments->ops_count / arguments->thread_count; + gettimeofday(&task_start, NULL); + + for (i = 0; i < arguments->thread_count; ++i) { + t_def[i].start = i * n; + t_def[i].end = n + i * n; + t_def[i].task = task; + t_def[i].rand_state = + (struct random_data *) + calloc(1, sizeof (struct random_data)); + + initstate_r(arguments->seed, + &random_statebuf[i], 32, t_def[i].rand_state); + + if (per_thread_arg) { + t_def[i].arg = arg == NULL ? NULL : arg[i]; + } else { + t_def[i].arg = arg == NULL ? NULL : arg[0]; + } + if (pthread_create(&threads[i], NULL, do_task, &t_def[i]) < 0) { + return FAILURE; + } + } + + for (i = 0; i < arguments->thread_count; ++i) { + pthread_join(threads[i], NULL); + if (t_def[i].result == FAILURE) { + ret++; + } + } + + gettimeofday(&task_stop, NULL); + + free(random_statebuf); + for (i = 0; i < arguments->thread_count; ++i) { + free(t_def[i].rand_state); + } + + if (elapsed != NULL) { + *elapsed = (task_stop.tv_sec - task_start.tv_sec) + + ((task_stop.tv_usec - task_start.tv_usec) / + USEC_IN_SEC); + } + + return ret; +} + +/* + * task_malloc -- allocates MALLOC_SIZE memory in allocated_mem array + */ +int +task_malloc(int i, void *arg, struct random_data *rand_state) +{ + int size_to_alloc; + int random_number; + + switch (allocation_type) { + case ALLOCATION_STATIC: + size_to_alloc = allocation_max; + break; + + case ALLOCATION_RANGE: + random_r(rand_state, &random_number); + size_to_alloc = random_number % + (allocation_max - allocation_min) + + allocation_min; + break; + + case ALLOCATION_UNKNOWN: + break; + } + + if (allocator == ALLOCATOR_VMEM) { + VMEM *pool = arg; + allocated_mem[i] = vmem_malloc(pool, size_to_alloc); + } else { + allocated_mem[i] = malloc(size_to_alloc); + } + + if (allocated_mem[i] == NULL) { + return FAILURE; + } + return SUCCESS; +} + +/* + * task_free -- frees memory located in allocated_mem + */ +int +task_free(int i, void *arg, struct random_data *rand_state) +{ + if (allocated_mem[i] != NULL) { + if (allocator == ALLOCATOR_VMEM) { + VMEM *pool = arg; + vmem_free(pool, allocated_mem[i]); + } else { + free(allocated_mem[i]); + } + } + return SUCCESS; +} diff --git a/benchmarks/mt/tasks.h b/benchmarks/mt/tasks.h new file mode 100644 index 0000000000000000000000000000000000000000..2ae3fe379394fbf4dfe9364c4a495c602045f25e --- /dev/null +++ b/benchmarks/mt/tasks.h @@ -0,0 +1,59 @@ +#ifndef TASKS_H +#define TASKS_H + +#include <stdlib.h> +#include <inttypes.h> +#include <libvmem.h> + +#define SUCCESS 0 +#define FAILURE -1 + +typedef enum allocator_e { + ALLOCATOR_VMEM, + ALLOCATOR_MALLOC, + MAX_ALLOCATOR +} allocator_t; + +typedef enum allocation_type_e { + ALLOCATION_UNKNOWN, + ALLOCATION_STATIC, + ALLOCATION_RANGE +} allocation_type_t; + +typedef struct arguments_s +{ + int thread_count; + int pool_per_thread; + uint64_t ops_count; + uint seed; + uint allocation_size; + uint allocation_size_max; + allocation_type_t allocation_type; + allocator_t allocator; +} arguments_t; + +typedef int (*task_f)(int, void *arg, struct random_data* rand_state); + +enum { + TASK_MALLOC, + TASK_FREE, + MAX_TASK +}; + +int task_malloc(int i, void *arg, struct random_data* rand_state); +int task_free(int i, void *arg, struct random_data* rand_state); + +extern task_f tasks[MAX_TASK]; + +extern int allocation_range_min; +extern int allocation_range_max; +extern allocator_t allocator; + +extern void **allocated_mem; + +extern const int allocation_sizes[]; + +int run_threads(arguments_t *arguments, task_f task, + int per_thread_arg, void **arg, double *elapsed); + +#endif // TASKS_H diff --git a/doc/.gitignore b/doc/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..76eaea317ef0b3778a09cb131de3bf9550b4f476 --- /dev/null +++ b/doc/.gitignore @@ -0,0 +1,3 @@ +*.txt +*.html +*.gz diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..39ecdd61514564c03e277393b919c3d8d4146647 --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,66 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# doc/Makefile -- Makefile for NVM library man pages +# +MANPAGES = libpmem.3 libvmem.3 +TXTFILES = $(MANPAGES:=.txt) +HTMLFILES = $(MANPAGES:=.html) +GZFILES = $(MANPAGES:=.gz) +MANPAGES_DESTDIR = $(DESTDIR)/usr/share/man/man3 + +all: $(TXTFILES) + +%.3.txt: %.3 + man ./$< > $@ + +html: $(HTMLFILES) + +%.3.html: %.3 + groff -mandoc -Thtml ./$< > $@ + +compress: $(GZFILES) + +%.3.gz: %.3 + gzip -c ./$< > $@ + +clean: + +clobber: clean + $(RM) -f $(TXTFILES) $(HTMLFILES) $(GZFILES) + +install: compress + install -d $(MANPAGES_DESTDIR) + install -p -m 0644 $(GZFILES) $(MANPAGES_DESTDIR) + +.PHONY: all html clean compress clobber cstyle install diff --git a/doc/README b/doc/README new file mode 100644 index 0000000000000000000000000000000000000000..b345c5ce72173068bb3303a25ccf4fc94bd1d0ad --- /dev/null +++ b/doc/README @@ -0,0 +1,20 @@ +Linux NVM Library + +This is doc/README. + +This directory contains the man pages for the NVM Library: + +libpmem.3 -- libpmem(3) - persistent memory library +libvmem.3 -- libvmem(3) - volatile memory allocation library + +These man pages provide the API specification for the corresponding +libraries in this source tree, so any updates to one should be tested, +reviewed, and committed with changes to the other. + +To create more readable text files from the source, use: + $ make +An even more convenient way to read these is to use the "man" +command to format them (includes bold, underline, etc. when +run in a terminal window): + $ man -l libpmem.3 + $ man -l libvmem.3 diff --git a/doc/libpmem.3 b/doc/libpmem.3 new file mode 100644 index 0000000000000000000000000000000000000000..667fd769af128db090fa264ba32cb9fdddaa5a67 --- /dev/null +++ b/doc/libpmem.3 @@ -0,0 +1,1216 @@ +.\" +.\" Copyright (c) 2014, Intel Corporation +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" * Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" * Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in +.\" the documentation and/or other materials provided with the +.\" distribution. +.\" +.\" * Neither the name of Intel Corporation nor the names of its +.\" contributors may be used to endorse or promote products derived +.\" from this software without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" +.\" libpmem.3 -- man page for libpmem +.\" +.\" Format this man page with: +.\" man -l libpmem.3 +.\" or +.\" groff -man -Tascii libpmem.3 +.\" +.TH libpmem 3 "pmem API version 0.48" "NVM Library" +.SH NAME +libpmem \- persistent memory library +.SH SYNOPSIS +.nf +.B #include <libpmem.h> +.sp +.B cc ... -lpmem +.sp +.B Flush-to-persistence support: +.sp +.BI "int pmem_is_pmem(void *" addr ", size_t " len ); +.BI "void pmem_persist(void *" addr ", size_t " len ", int " flags ); +.BI "void pmem_flush(void *" addr ", size_t " len ", int " flags ); +.BI "void pmem_fence(void);" +.BI "void pmem_drain(void);" +.sp +.B Support for Persistent Memory Transactions: +.sp +.BI "PMEMtrn *pmemtrn_map(int " fd ); +.BI "void pmemtrn_unmap(PMEMtrn *" ptp ); +.B XXX REST OF TRANSACTION SECTION NOT READY FOR REVIEW +.sp +.B Support for Atomic Arrays: +.sp +.BI "PMEMblk *pmemblk_map(int " fd ", size_t " bsize ); +.BI "void pmemblk_unmap(PMEMblk *" pbp ); +.BI "size_t pmemblk_nblock(PMEMblk *" pbp ); +.BI "int pmemblk_read(PMEMblk *" pbp ", void *" buf ", off_t " blockno ); +.BI "int pmemblk_write(PMEMblk *" pbp ", const void *" buf ", off_t " blockno ); +.BI "int pmemblk_set_zero(PMEMblk *" pbp ", off_t " blockno ); +.BI "int pmemblk_set_error(PMEMblk *" pbp ", off_t " blockno ); +.sp +.B Support for Persistent Memory Logs: +.sp +.BI "PMEMlog *pmemlog_map(int " fd ); +.BI "void pmemlog_unmap(PMEMlog *" plp ); +.BI "size_t pmemlog_nbyte(PMEMlog *" plp ); +.BI "int pmemlog_append(PMEMlog *" plp ", const void *" buf ", size_t " count ); +.BI "int pmemlog_appendv(PMEMlog *" plp ", const struct iovec *" iov ", int " iovcnt ); +.BI "off_t pmemlog_tell(PMEMlog *" plp ); +.BI "void pmemlog_rewind(PMEMlog *" plp ); +.BI "void pmemlog_walk(PMEMlog *" plp ", size_t " chunksize , +.BI " int (*" process_chunk ")(const void *" buf ", size_t " len ", void *" arg ), +.BI " void *" arg ); +.sp +.B Managing overall library behavior: +.sp +.BI "const char *pmem_check_version(" +.BI " unsigned " major_required , +.BI " unsigned " minor_required ); +.BI "void pmem_set_funcs(" +.BI " void *(*" malloc_func ")(size_t " size ), +.BI " void (*" free_func ")(void *" ptr ), +.BI " void *(*" realloc_func ")(void *" ptr ", size_t " size ), +.BI " char *(*" strdup_func ")(const char *" s ), +.BI " void (*" print_func ")(const char *" s ), +.BI " void (*" persist_func ")(void *" addr ", size_t " len" , int " flags )); +.BI "int pmemtrn_check(const char *" path ); +.BI "int pmemblk_check(const char *" path ); +.BI "int pmemlog_check(const char *" path ); +.fi +.sp +.SH DESCRIPTION +.PP +.B libpmem +provides several +interfaces to persistent memory pools built on memory-mapped files. +The interfaces are divided into categories, each described in a section +below. +All the interfaces may be used concurrently, however memory from +different memory pools must not be mixed. For example, memory allocated +from a transactional memory pool created with +.BR pmemtrn_map () +must not be freed to any other memory pool. +.PP +.B libpmem +uses the +.BR mmap (2) +system call to access memory pools. The library +is most useful when used with +.I Direct Access +storage (DAX), which is memory-addressable persistent storage +that supports load/store access without being paged via the system page cache. +A Persistent Memory-aware file system is typically used to provide this +type of access. Memory-mapping a file from a Persistent +Memory-aware file system provides the raw memory pools, and this library +supplies additional semantics like +.I transactions +on top of those pools. +.PP +Under normal usage, +.B libpmem +will never print messages or intentionally cause the process to exit. +The only exception to this is the debugging information, when enabled, as +described under +.B DEBUGGING +below. +The library uses +.BR pthreads (7) +to be fully MT-safe, but never creates or destroys threads itself. +The library does not make use of any signals, networking, and +never calls +.BR select () +or +.BR poll (). +The system memory allocation routines like +.BR malloc () +and +.BR free () +are used by +.B libpmem +for managing a small amount of run-time state, but applications +are allowed to override these calls if necessary (see the description +of +.BR pmem_set_funcs () +below). +.SH FLUSH-TO-PERSISTENCE +.PP +These interfaces are meant for fairly raw access to persistent +memory, where a persistent memory file has been memory mapped (see +.BR mmap (2)) +and the application takes on full responsibility to storing data to +the mapped area and flushing those stores to make them persistent. +Traditionally, forcing memory mapped changes to persistence is done +using +.BR msync (2), +and that will work as expected with Persistent Memory as well. +However, platforms may have more optimal ways to flush changes +in a range of memory. These functions are provided +for the case where a range is known to be true Persistent Memory +(not paged from storage). +.PP +.BI "int pmem_is_pmem(void *" addr ", size_t " len ); +.IP +The +.BR pmem_is_pmem () +function returns true only if the entire range +.IR "" [ addr ", " addr + len ) +consists entirely of Persistent Memory. A true return from +.BR pmem_is_pmem () +means it is safe to use +.BR pmem_persist () +and the related functions below to make changes durable for that +memory range. +.IP +The implementation of +.BR pmem_is_pmem () +requires a non-trivial amount of work to determine if the given range +is entirely Persistent Memory. For this reason, it is better to call +.BR pmem_is_pmem () +once when a range of memory is first encountered, save the result, and +use the saved result to determine whether +.BR pmem_persist () +or +.BR msync (2) +is called when flushing changes to persistence. Calling +.BR pmem_is_pmem () +each time changes are flushed to persistence will not perform well. +.IP +WARNING: Using +.BR pmem_persist () +on a range where +.BR pmem_is_pmem () +returns false may not do anything useful -- use +.BR msync (2) +instead. +.PP +.BI "void pmem_persist(void *" addr ", size_t " len ", int " flags ); +.IP +Force any changes in the range +.IR "" [ addr ", " addr + len ) +to be stored +durably in Persistent Memory. This is equivalent to calling +.BR msync (2) +as described above, but may be more optimal and will +avoid calling into the kernel if possible. +There are no alignment restrictions on +the range described by +.I addr +and +.IR len , +but +.BR pmem_persist () +may expand the range as necessary +to meet platform alignment requirements. +Zero should be passed in for +.I flags +since no flags have been defined for this call yet. +.IP +WARNING: Like +.BR msync (2), +there is nothing +atomic or transactional about this call. Any +unwritten stores in the given range will be written, +but some stores may have already been written by +virtue of normal cache eviction/replacement policies. +Correctly written code must not depend on stores +waiting until +.BR pmem_persist () +is called to become +persistent -- they can become persistent at any time +before +.BR pmem_persist () +is called. +.PP +.nf +.BI "void pmem_flush(void *" addr ", size_t " len ", int " flags ); +.BI "void pmem_fence(void);" +.BI "void pmem_drain(void);" +.fi +.IP +These three functions provide partial versions of the +.BR pmem_persist () +function described above. +.BR pmem_persist () +can be thought of as this: +.IP +.nf +void pmem_persist(void *addr, size_t len, int flags) +{ + /* flush the processor caches */ + pmem_flush(addr, len, flags); + + /* Persistent Memory store barrier */ + pmem_fence(); + + /* wait for any PM stores to drain from HW buffers */ + pmem_drain(); +} +.fi +.IP +These functions allow advanced programs to create their +own variations of +.BR pmem_persist (). +For example, a program +that needs to flush several discontiguous ranges can call +.BR pmem_flush () +for each range and then follow up by +calling the +.BR pmem_fence () +and +.BR pmem_drain () +once. +.SH PERSISTENT MEMORY TRANSACTIONS +.PP +To use the transactions supplied by +.BR libpmem , +a +.I memory pool +is first created. This is done with the +.BR pmemtrn_map () +function described in this section. +The other functions +described in this section then operate on the transaction-based +memory pool. +.PP +Once created, the memory pool is represented by an opaque handle, +of type +.IR "PMEMtrn *" , +which is passed to most of the other functions in this section. +Internally, +.B libpmem +will use either +.B pmem_persist () +or +.B msync (2) +when it needs to flush changes, depending on whether +the memory pool appears to be Persistent Memory or a regular file +(see +.BR pmem_is_pmem () +above for more information). +There is no need for applications to flush changes directly +when using the transactional memory API described in this section. +.PP +.BI "PMEMtrn *pmemtrn_map(int " fd ); +.IP +The +.BR pmemtrn_map () +function maps a transactional memory pool into memory, creating +a new pool in the file referenced by +.I fd +if an existing pool is not found. +.BR pmemtrn_map () +returns a memory +pool handle used with most of the functions in this section. +.I fd +must be a file descriptor for a file opened for both reading and writing, +and the file size must already be set appropriately +(for example, by calling +.BR posix_fallocate () +the first time the file is used). +.BR pmemtrn_map () +will map the file using +.BR mmap (2), +and detect if the file already contains a +.B libpmem +memory pool from an earlier use of the file with +.BR pmemtrn_map (). +If a memory pool is not found, a new pool is created, +overwriting any data contained in the file. +The minimum +file size allowed by the library for a transactional memory +pool is defined in +.B <libpmem.h> +as +.BR PMEMTRN_MIN_POOL . +After +.BR pmemtrn_map () +returns the memory pool handle, the file descriptor +.I fd +may be closed by the caller without impacting the use +of +.B libpmem +on the memory pool. +.BR pmemtrn_map () +returns NULL on error, setting errno appropriately. +It is an error to use +.BR pmemtrn_map () +on a file with a different type of memory pool in it. The library +will return EINVAL for this case. To switch the type of memory pool +in a file, it is best to delete the file and recreate it. +.IP +Each time a transactional memory pool is mapped using +.BR pmemtrn_map (), +a brief consistency check is performed, similar to the check done by +.BR pmemtrn_check () +described below, but less extensive. If a consistency issue is +discovered, the severity of the pool corruption is evaluated to +determine if read-only access is still viable. If so, +.BR pmemtrn_map () +succeeds but any subsequent calls to change the pool will +return the error EROFS. If the memory pool is not viable +for read-only access, +.BR pmemtrn_map () +will return the error EINVAL. In either case, see +.BR pmemtrn_check () +below for a description of how to determine the details of the +memory pool corruption. +.PP +.BI "void pmemtrn_unmap(PMEMtrn *" ptp ); +.IP +The +.BR pmemtrn_unmap () +function unmaps the memory pool indicated by +.I ptp +and deletes the memory pool handle. The transactional memory pool +itself lives on in the file that contains it and may be re-opened +at a later time using +.BR pmemtrn_map () +as described above. +Any in-progress (incomplete) transactions in outstanding at the time +.BR pmemtrn_unmap () +is called are discarded in the same manner as if the program had terminated +before completed those transactions. +.PP +.B XXX REST OF TRANSACTION SECTION NOT READY FOR REVIEW +.SH ATOMIC ARRAYS +.PP +To use the atomic block arrays supplied by +.BR libpmem , +a +.I memory pool +is first created. This is done with the +.BR pmemblk_map () +function described in this section. +The other functions +described in this section then operate on the resulting block +memory pool. +.PP +Once created, the memory pool is represented by an opaque handle, +of type +.IR "PMEMblk *" , +which is passed to most of the other functions in this section. +Internally, +.B libpmem +will use either +.B pmem_persist () +or +.B msync (2) +when it needs to flush changes, depending on whether +the memory pool appears to be Persistent Memory or a regular file +(see +.BR pmem_is_pmem () +above for more information). +There is no need for applications to flush changes directly +when using the block memory API described in this section. +.PP +.BI "PMEMblk *pmemblk_map(int " fd ", size_t " bsize ); +.IP +The +.B pmemblk_map () +function maps a block memory pool into memory (an array of +blocks that support atomic update at the block level), returning a memory +pool handle used with most of the functions in this section. +.I fd +must be a file descriptor for a file opened for both reading and writing, +and the file size must already be set appropriately +(for example, by calling +.BR posix_fallocate () +the first time the file is used). +.I bsize +is the block size of each element in the pool. +.B pmemblk_map () +will map the file using +.BR mmap (2), +and detect if the file already contains a +.B libpmem +memory pool from an earlier use of the file with +.BR pmemblk_map (). +If a memory pool is not found, a new pool is created, +overwriting any data contained in the file. +.BR pmemblk_map () +will fit as many blocks as possible in the given file, but some +space will be used by the library for metadata. See +.BR pmemblk_nblock () +below for a way to determine the resulting number of usable blocks. +The minimum +file size allowed by the library for a block pool is defined in +.B <libpmem.h> +as +.BR PMEMBLK_MIN_POOL . +There are no restrictions on the block size +.IR bsize , +however +.B libpmem +will silently round up the given size to +.BR PMEMBLK_MIN_BLK , +as defined in +.BR <libpmem.h> . +After +.BR pmemblk_map () +returns the memory pool handle, the file descriptor +.I fd +may be closed by the caller without impacting the use +of +.B libpmem +on the memory pool. +.BR pmemblk_map () +returns NULL on error, setting errno appropriately. +It is an error to use +.BR pmemblk_map () +on a file with a different type of memory pool in it. The library +will return EINVAL for this case. To switch the type of memory pool +in a file, it is best to delete the file and recreate it. +.IP +Each time a block memory pool is mapped using +.BR pmemblk_map (), +a brief consistency check is performed, similar to the check done by +.BR pmemblk_check () +described below, but less extensive. If a consistency issue is +discovered, the severity of the pool corruption is evaluated to +determine if read-only access is still viable. If so, +.BR pmemblk_map () +succeeds but any subsequent calls to change the pool will +return the error EROFS. If the memory pool is not viable +for read-only access, +.BR pmemblk_map () +will return the error EINVAL. In either case, see +.BR pmemblk_check () +below for a description of how to determine the details of the +memory pool corruption. +.PP +.BI "void pmemblk_unmap(PMEMblk *" pbp ); +.IP +The +.BR pmemblk_unmap () +function unmaps the memory pool indicated by +.I pbp +and deletes the memory pool handle. The block memory pool +itself lives on in the file that contains it and may be re-opened +at a later time using +.BR pmemblk_map () +as described above. +.PP +.BI "size_t pmemblk_nblock(PMEMblk *" pbp ); +.IP +The +.BR pmemblk_nblock () +function returns the usable space in the block memory pool, +expressed as the number of blocks available. +.I pbp +must be a block memory pool as returned by +.BR pmemblk_map (). +.PP +.BI "int pmemblk_read(PMEMblk *" pbp ", void *" buf ", off_t " blockno ); +.IP +The +.BR pmemblk_read () +function reads a block from memory pool +.IR pbp , +block number +.IR blockno , +into the buffer +.IR buf . +On success, zero is returned. On error, -1 is returned and errno is set. +Reading a block that has never been written by +.BR pmemblk_write () +since the creation of block memory pool will return a block of zeroes, as +that is the initial state of all blocks when the memory pool is created. +.PP +.BI "int pmemblk_write(PMEMblk *" pbp ", const void *" buf ", off_t " blockno ); +.IP +The +.BR pmemblk_write () +function writes a block from +.I buf +to block number +.I blockno +in the memory pool +.IR pbp . +The write is atomic with respect to other reads and writes. In addition, +the write cannot be torn by program failure or system crashes; on recovery +the block is guaranteed to contain either the old data or the new data, +never a mixture of both. +On success, zero is returned. On error, -1 is returned and errno is set. +.PP +.BI "int pmemblk_set_zero(PMEMblk *" pbp ", off_t " blockno ); +.IP +The +.BR pmemblk_set_zero () +function writes zeros to block number +.I blockno +in memory pool +.IR pbp . +Using this function is faster than actually writing a block of zeros +since +.B libpmem +uses metadata to indicate the block should read back as zero. +On success, zero is returned. On error, -1 is returned and errno is set. +.PP +.BI "int pmemblk_set_error(PMEMblk *" pbp ", off_t " blockno ); +.IP +The +.BR pmemblk_set_error () +function sets the error state for block number +.I blockno +in memory pool +.IR pbp . +A block in the error state returns errno EIO when read. Writing the +block clears the error state and returns the block to normal use. +On success, zero is returned. On error, -1 is returned and errno is set. +.SH PERSISTENT MEMORY LOGS +.PP +To use the persistent memory logs supplied by +.BR libpmem , +a +.I memory pool +is first created. This is done with the +.BR pmemlog_map () +function described in this section. +The other functions +described in this section then operate on the resulting log +memory pool. +.PP +Once created, the memory pool is represented by an opaque handle, +of type +.IR "PMEMlog *" , +which is passed to most of the other functions in this section. +Internally, +.B libpmem +will use either +.B pmem_persist () +or +.B msync (2) +when it needs to flush changes, depending on whether +the memory pool appears to be Persistent Memory or a regular file +(see +.BR pmem_is_pmem () +above for more information). +There is no need for applications to flush changes directly +when using the log memory API described in this section. +.PP +.BI "PMEMlog *pmemlog_map(int " fd ); +.IP +The +.B pmemlog_map () +function maps a log memory pool into memory (a persistent memory +resident log file), returning a memory +pool handle used with most of the functions in this section. +.I fd +must be a file descriptor for a file opened for both reading and writing, +and the file size must already be set appropriately +(for example, by calling +.BR posix_fallocate () +the first time the file is used). +.B pmemlog_map () +will map the file using +.BR mmap (2), +and detect if the file already contains a +.B libpmem +memory pool from an earlier use of the file with +.BR pmemlog_map (). +If a memory pool is not found, a new pool is created, +overwriting any data contained in the file. +.BR pmemlog_map () +will create as large a log as possible in the given file, but some +space will be used by the library for metadata. See +.BR pmemlog_nbyte () +below for a way to determine the resulting usable space. +The minimum +file size allowed by the library for a log memory pool is defined in +.B <libpmem.h> +as +.BR PMEMLOG_MIN_POOL . +After +.BR pmemlog_map () +returns the memory pool handle, the file descriptor +.I fd +may be closed by the caller without impacting the use +of +.B libpmem +on the memory pool. +.BR pmemlog_map () +returns NULL on error, setting errno appropriately. +It is an error to use +.BR pmemlog_map () +on a file with a different type of memory pool in it. The library +will return EINVAL for this case. To switch the type of memory pool +in a file, it is best to delete the file and recreate it. +.IP +Each time a log memory pool is mapped using +.BR pmemlog_map (), +a brief consistency check is performed, similar to the check done by +.BR pmemlog_check () +described below, but less extensive. If a consistency issue is +discovered, the severity of the pool corruption is evaluated to +determine if read-only access is still viable. If so, +.BR pmemlog_map () +succeeds but any subsequent calls to change the pool will +return the error EROFS. If the memory pool is not viable +for read-only access, +.BR pmemlog_map () +will return the error EINVAL. In either case, see +.BR pmemlog_check () +below for a description of how to determine the details of the +memory pool corruption. +.PP +.BI "void pmemlog_unmap(PMEMlog *" plp ); +.IP +The +.BR pmemlog_unmap () +function unmaps the memory pool indicated by +.I plp +and deletes the memory pool handle. The log memory pool +itself lives on in the file that contains it and may be re-opened +at a later time using +.BR pmemlog_map () +as described above. +.PP +.BI "size_t pmemlog_nbyte(PMEMlog *" plp ); +.IP +The +.BR pmemlog_nbyte () +function returns the +amount of usable space in the log +.IR plp . +This function may be used on a log to determine how much +usable space is available after +.B libpmem +has added its metadata to the memory pool. +.PP +.BI "int pmemlog_append(PMEMlog *" plp ", const void *" buf ", size_t " count ); +.IP +The +.BR pmemlog_append () +function appends +.I count +bytes from +.I buf +to the current write offset in the log memory pool +.IR plp . +Calling this function is analogous to appending to a file. The append +is atomic and cannot be torn by a program failure or system crash. +On success, zero is returned. On error, -1 is returned and errno is set. +.PP +.BI "int pmemlog_appendv(PMEMlog *" plp ", const struct iovec *" iov ", int " iovcnt ); +.IP +The +.BR pmemlog_appendv () +function appends to the log +.I plp +just like +.BR pmemlog_append () +above, but this function takes a scatter/gather list in a manner +similar to +.BR writev (2). +In this case, the entire list of buffers is appended atomically. +On success, zero is returned. On error, -1 is returned and errno is set. +.PP +.BI "off_t pmemlog_tell(PMEMlog *" plp ); +.IP +The +.BR pmemlog_tell () +function returns the current write point for the log, expressed as a byte +offset into the usable log space in the memory pool. This offset starts +off as zero on a newly-created log, and is incremented by each successful +append operation. This function can be used to determine how much data +is currently in the log. +.PP +.BI "void pmemlog_rewind(PMEMlog *" plp ); +.IP +The +.BR pmemlog_rewind () +function resets the current write point for the log to zero. After this +call, the next append adds to the beginning of the log. +.PP +.nf +.BI "void pmemlog_walk(PMEMlog *" plp ", size_t chunksize , +.BI " int (*" process_chunk ")(const void *" buf ", size_t " len ", void *" arg ), +.BI " void *" arg ); +.fi +.IP +The +.BR pmemlog_walk () +function walks through the log +.IR plp , +from beginning to end, calling the callback function +.I process_chunk +for each +.I chunksize +block of data found. +The argument +.I arg +is also passed to the callback to help avoid the need for global state. +The +.I chunksize +argument is useful for logs with fixed-length records and may be specified +as 0 to cause a single call to the callback with the entire log contents +passed as the +.I buf +argument. The +.I len +argument tells the +.I process_chunk +function how much data buf is holding. +The callback function should return true if +.BR pmemlog_walk () +should continue walking through the log, or false to +terminate the walk. +The callback function is called while holding +.B libpmem +internal locks that make calls atomic, so the callback function +must not try to append to the log itself or deadlock will occur. +.SH MANAGING LIBRARY BEHAVIOR +.PP +The library entry points described in this section are less +commonly used than the previous section. +These entry points expose library information or alter +the default library behavior. +.PP +.nf +.BI "const char *pmem_check_version(" +.BI " unsigned " major_required , +.BI " unsigned " minor_required ); +.fi +.IP +The +.BR pmem_check_version () +function is used to see if the installed +.B libpmem +supports the version of the library API required by an application. +The easiest way to do this is for the application to supply the +compile-time version information, supplied by defines in +.BR <libpmem.h> , +like this: +.IP +.nf +reason = pmem_check_version(PMEM_MAJOR_VERSION, + PMEM_MINOR_VERSION); +if (reason != NULL { + /* version check failed, reason string tells you why */ +} +.fi +.IP +Any mismatch in the major version number is considered a failure, +but a library with a newer minor version number will pass this +check since increasing minor versions imply backwards compatibility. +.IP +An application can also check specifically for the existence of +an interface by checking for the version where that interface was +introduced. These versions are documented in this man page as follows: +unless otherwise specified, all interfaces described here are available +in version 1.0 of the library. Interfaces added after version 1.0 +will contain the text +.I introduced in version x.y +in the section of this manual describing the feature. +.IP +When the version check performed by +.BR pmem_check_version () +is successful, the return value is NULL. Otherwise the return value +is a static string describing the reason for failing the version check. +The string returned by +.BR pmem_check_version () +must not be modified or freed. +.PP +.nf +.BI "void pmem_set_funcs(" +.BI " void *(*" malloc_func ")(size_t " size ), +.BI " void (*" free_func ")(void *" ptr ), +.BI " void *(*" realloc_func ")(void *" ptr ", size_t " size ), +.BI " char *(*" strdup_func ")(const char *" s ), +.BI " void (*" print_func ")(const char *" s ), +.BI " void (*" persist_func ")(void *" addr ", size_t " len ", int " flags )); +.fi +.IP +The +.BR pmem_set_funcs () +function allows an application to override some +interfaces used internally by +.BR libpmem . +Passing in NULL for any of the handlers will cause the +.B libpmem +default function to be used. +The library does not make heavy use of the system malloc functions, but +it does allocate approximately 4-8 kilobytes for each memory pool in use. +The only functions in the malloc family used by the library are represented +by the first four arguments to +.BR pmem_set_funcs (). +The +.I print_func +function is called by +.B libpmem +when additional tracing is enabled +in the debug version of the library as described in the +.B DEBUGGING +section below. +The default +.I print_func +used by the library prints to +the file specified by the +.B PMEM_LOG_FILE +environment variable, or to +.B stderr +if that variable is not set. +The +.I persist_func +is called by +.B libpmem +to make changes to Persistent Memory persistent. The default +.I persist_func +used by the library is +.BR pmem_persist (), +described in this manual. +.PP +.nf +.BI "int pmemtrn_check(const char *" path ); +.BI "int pmemblk_check(const char *" path ); +.BI "int pmemlog_check(const char *" path ); +.fi +.IP +These functions perform a consistency check of the file +indicated by +.IR path . +They return true if the memory pool is found to be consistent. In +the event of inconsistencies, continued use of the file +with +.B libpmem +will result in undefined behavior. The debug version of +.B libpmem +will provide additional details on inconsistencies when +.B PMEM_LOG_LEVEL +is at least 1, as described in the +.B DEBUGGING +section below. +These functions open the given +.I path +read-only so they never make any changes to the file. +Although these functions are mostly used during the development of +.B libpmem +itself, they are potentially useful for determining the type of +memory pool contained in a file (only the appropriate check function +will return true). +.SH DEBUGGING +.PP +Two versions of +.B libpmem +are typically available on a development system. +The normal version, accessed when a program is +linked using the +.B -lpmem +option, is optimized for performance. That version skips checks +that impact performance and never logs any trace information or performs +any run-time assertions. A second version, accessed when a program +uses the libraries under +.BR /usr/lib/nvml_debug , +contains run-time assertions and trace points. +The typical way to access the debug version is to set the environment variable +.B LD_LIBRARY_PATH +to +.BR /usr/lib/nvml_debug +or +.BR /usr/lib64/nvml_debug +depending on where the debug libraries are installed on the system. +The trace points in the debug version of the library +are enabled using the environment variable +.BR PMEM_LOG_LEVEL , +which can be set to the following values: +.IP 0 +This is the default level when +.B PMEM_LOG_LEVEL +is not set. No log messages are emitted at this level. +.IP 1 +Additional details on any errors detected are logged (in addition +to returning the errno-based errors as usual). +.IP 2 +A trace of basic operations including allocations and deallocations +is logged. +.IP 3 +This level enables a very verbose amount of function call tracing +in the library. +.IP 4 +This level enables voluminous and fairly obscure tracing information +that is likely only useful to the +.B libpmem +developers. +.PP +The environment variable +.B PMEM_LOG_FILE +specifies a file name where +all logging information should be written, and if +.B PMEM_LOG_FILE +is not set, output goes to stderr. +All prints are done using the +.I print_func +function in +.B libpmem +(see +.BR pmem_set_funcs () +above for details on how to override that function). +.PP +Setting the environment variable +.B PMEM_LOG_LEVEL +has no effect on the non-debug version of +.BR libpmem . +.SH BASIC PERSISTENT MEMORY EXAMPLE +.PP +The follow example uses +.B libpmem +to flush changes made to raw, memory-mapped persistent memory. +.IP +.\" run source through expand -4 before inserting... +.nf +#include <sys/mman.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <libpmem.h> + +int +main(int argc, char *argv[]) +{ + int fd; + char *pmaddr; + + /* memory map some persistent memory */ + if ((fd = open("/my/pmem-aware/fs/myfile", O_RDWR)) < 0) { + perror("open"); + exit(1); + } + + /* just map 4k for this example */ + if ((pmaddr = mmap(NULL, 4096, PROT_READ|PROT_WRITE, + MAP_SHARED, fd, 0)) == MAP_FAILED) { + perror("mmap"); + exit(1); + } + close(fd); + + /* store a string to the persistent memory */ + strcpy(pmaddr, "hello, persistent memory"); + + /* + * The above stores may or may not be sitting in cache at + * this point, depending on other system activity causing + * cache pressure. Now force the change to be durable + * (flushed all the say to the persistent memory). If + * unsure whether the file is really persistent memory, + * use pmem_is_pmem() to decide whether pmem_persist() can + * be used, or whether msync() must be used. + */ + if (pmem_is_pmem(pmaddr, 4096)) + pmem_persist(pmaddr, 4096, 0); + else + msync(pmaddr, 4096, MS_SYNC); +} +.fi +.SH ATOMIC ARRAYS EXAMPLE +.PP +The follow example shows how the +.I pmemblk +entry points to +.B libpmem +are used to provide atomic arrays. +.IP +.\" run source through expand -4 before inserting... +.nf +#include <stdio.h> +#include <fcntl.h> +#include <errno.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <libpmem.h> + +/* size of each element in the PMEM pool (bytes) */ +#define ELEMENT_SIZE ((size_t)1024) + +int +main(int argc, char *argv[]) +{ + int fd; + PMEMblk *pbp; + size_t nelements; + char buf[ELEMENT_SIZE]; + + /* create file on PMEM-aware file system */ + if ((fd = open("/my/pmem-aware/fs/myfile", + O_CREAT|O_RDWR, 0666)) < 0) { + perror("open"); + exit(1); + } + + /* pre-allocate 2GB of persistent memory */ + if ((errno = posix_fallocate(fd, (off_t)0, + (size_t)1024 * 1024 * 1024 * 2)) != 0) { + perror("posix_fallocate"); + exit(1); + } + + /* create an array of atomically writable elements */ + if ((pbp = pmemblk_map(fd, ELEMENT_SIZE)) == NULL) { + perror("pmemblk_map"); + exit(1); + } + + /* how many elements fit into the PMEM pool? */ + nelements = pmemblk_nblock(pbp); + printf("file holds %zu elements\n", nelements); + + /* store a block at index 5 */ + strcpy(buf, "hello, world"); + if (pmemblk_write(pbp, buf, 5) < 0) { + perror("pmemblk_write"); + exit(1); + } + + /* read the block at index 10 (reads as zeros initially) */ + if (pmemblk_read(pbp, buf, 10) < 0) { + perror("pmemblk_write"); + exit(1); + } + + /* zero out the block at index 5 */ + if (pmemblk_set_zero(pbp, 5) < 0) { + perror("pmemblk_set_zero"); + exit(1); + } + + /* ... */ + + pmemblk_unmap(pbp); + close(fd); +} +.fi +.SH PERSISTENT MEMORY LOG EXAMPLE +.PP +The follow example shows how the +.I pmemlog +entry points to +.B libpmem +are used to provide a persistent memory resident log file. +.IP +.\" run source through expand -4 before inserting... +.nf +#include <stdio.h> +#include <fcntl.h> +#include <errno.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <libpmem.h> + +/* log processing callback for use with pmemlog_walk() */ +int +printit(const void *buf, size_t len, void *arg) +{ + fwrite(buf, len, 1, stdout); + return 0; +} + +int +main(int argc, char *argv[]) +{ + int fd; + PMEMlog *plp; + size_t nbyte; + char *str; + + /* create file on PMEM-aware file system */ + if ((fd = open("/my/pmem-aware/fs/myfile", + O_CREAT|O_RDWR, 0666)) < 0) { + perror("open"); + exit(1); + } + + /* pre-allocate 2GB of persistent memory */ + if ((errno = posix_fallocate(fd, (off_t)0, + (size_t)1024 * 1024 * 1024 * 2)) != 0) { + perror("posix_fallocate"); + exit(1); + } + + /* create a persistent memory resident log */ + if ((plp = pmemlog_map(fd)) == NULL) { + perror("pmemlog_map"); + exit(1); + } + + /* how many bytes does the log hold? */ + nbyte = pmemlog_nbyte(plp); + printf("log holds %zu bytes\n", nbyte); + + /* append to the log... */ + str = "This is the first string appended\n"; + if (pmemlog_append(plp, str, strlen(str)) < 0) { + perror("pmemlog_append"); + exit(1); + } + str = "This is the second string appended\n"; + if (pmemlog_append(plp, str, strlen(str)) < 0) { + perror("pmemlog_append"); + exit(1); + } + + /* print the log contents */ + printf("log contains:\n"); + pmemlog_walk(plp, 0, printit, NULL); + + pmemlog_unmap(plp); + close(fd); +} +.fi +.SH BUGS +XXX +.SH ACKNOWLEDGEMENTS +.B libpmem +leverages persistent memory research from the +community and especially from these notable academic works: +.IP +J. Coburn, et al.: +.IR "NV-Heaps: Making Persistent Objects Fast and Safe with Next Generation, Non-Volatile Memories" , +The 16th ACM Conference +on Architectural Support for Programming Languages and Operating +Systems (ASPLOS 2011), March 2011, Newport Beach, Ca. +.IP +Haris Volos, Andres Jaan Tack, Michael M. Swift: +.IR "Mnemosyne: Lightweight Persistent Memory" , +The 16th ACM Conference on +Architectural Support for Programming Languages and Operating +Systems (ASPLOS 2011), March 2011, Newport Beach, California. +http://research.cs.wisc.edu/sonar/projects/mnemosyne/ +.PP +.B libpmem +builds on the persistent memory programming model +recommended by the SNIA NVM Programming Technical Work Group: +.IP +http://snia.org/nvmp +.SH "SEE ALSO" +.BR malloc (3), +.BR posix_memalign (3), +.BR strdup (3), +.BR mmap (2), +.BR msync (2), +.BR libvmem (3). diff --git a/doc/libvmem.3 b/doc/libvmem.3 new file mode 100644 index 0000000000000000000000000000000000000000..ad4e458fb129593e15cdbfb873e5a871c2242e02 --- /dev/null +++ b/doc/libvmem.3 @@ -0,0 +1,734 @@ +.\" +.\" Copyright (c) 2014, Intel Corporation +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" * Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" * Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in +.\" the documentation and/or other materials provided with the +.\" distribution. +.\" +.\" * Neither the name of Intel Corporation nor the names of its +.\" contributors may be used to endorse or promote products derived +.\" from this software without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" +.\" libvmem.3 -- man page for libvmem +.\" +.\" Format this man page with: +.\" man -l libvmem.3 +.\" or +.\" groff -man -Tascii libvmem.3 +.\" +.TH libvmem 3 "vmem API version 0.53" "NVM Library" +.SH NAME +libvmem \- volatile memory allocation library +.SH SYNOPSIS +.nf +.B #include <libvmem.h> +.sp +.B cc ... -lvmem +.sp +.B Memory pool management: +.sp +.BI "VMEM *vmem_pool_create(const char *" dir ", size_t " size ); +.BI "VMEM *vmem_pool_create_in_region(void *" addr ", size_t " size ); +.BI "void vmem_pool_delete(VMEM *" vmp ); +.BI "int vmem_pool_check(VMEM *" vmp ); +.BI "int vmem_pool_freespace(VMEM *" vmp ); +.BI "void vmem_pool_stats_print(VMEM *" vmp ", const char *" opts ); +.sp +.B Memory allocation related functions: +.sp +.BI "void *vmem_malloc(VMEM *" vmp ", size_t " size ); +.BI "void vmem_free(VMEM *" vmp ", void *" ptr ); +.BI "void *vmem_calloc(VMEM *" vmp ", size_t " nmemb ", size_t " size ); +.BI "void *vmem_realloc(VMEM *" vmp ", void *" ptr ", size_t " size ); +.BI "void *vmem_aligned_alloc(VMEM *" vmp ", size_t " alignment ", size_t " size ); +.BI "char *vmem_strdup(VMEM *" vmp ", const char *" s ); +.sp +.B Managing overall library behavior: +.sp +.BI "const char *vmem_check_version(" +.BI " unsigned " major_required , +.BI " unsigned " minor_required ); +.BI "void vmem_set_funcs(" +.BI " void *(*" malloc_func ")(size_t " size ), +.BI " void (*" free_func ")(void *" ptr ), +.BI " void *(*" realloc_func ")(void *" ptr ", size_t " size ), +.BI " char *(*" strdup_func ")(const char *" s ), +.BI " void (*" print_func ")(const char *" s )); +.fi +.sp +.SH DESCRIPTION +.PP +.B libvmem +provides common +.I malloc-like +interfaces to memory pools built on memory-mapped files. +These interfaces are for traditional +.B volatile +memory allocation but, unlike the functions described in +.BR malloc (3), +the memory managed by +.B libvmem +may have different attributes, depending on the file system +containing the memory-mapped files. In particular, +.B libvmem +is part of the +.I Non-Volatile Memory Library +because it is sometimes useful to use non-volatile memory as a volatile +memory pool, leveraging its capacity, cost, or performance characteristics. +.PP +.B libvmem +uses the +.BR mmap (2) +system call to create a pool of volatile memory. The library +is most useful when used with +.I Direct Access +storage (DAX), which is memory-addressable persistent storage +that supports load/store access without being paged via the system page cache. +A Persistent Memory-aware file system is typically used to provide this +type of access. Memory-mapping a file from a Persistent +Memory-aware file system provides the raw memory pools, and this library +supplies the more familiar +.I malloc-like +interfaces on top of those pools. +.PP +Under normal usage, +.B libvmem +will never print messages or intentionally cause the process to exit. +Exceptions to this are prints caused by calls to +.BR vmem_pool_stats_print (), +or by enabling debugging as described under +.B DEBUGGING +below. +The library uses +.BR pthreads (7) +to be fully MT-safe, but never creates or destroys threads itself. +The library does not make use of any signals, networking, and +never calls +.BR select () +or +.BR poll (). +The system memory allocation routines like +.BR malloc () +and +.BR free () +are used by +.B libvmem +for managing a small amount of run-time state, but applications +are allowed to override these calls if necessary (see the description +of +.BR vmem_set_funcs () +below). +.PP +.B libvmem +interfaces are grouped into three categories: those that manage +memory pools, those providing the basic +memory allocation functions, and those interfaces +less commonly used for managing +the overall library behavior. These groups of interfaces are +described in the following three sections. +.SH MANAGING MEMORY POOLS +.PP +To use +.BR libvmem , +a +.I memory pool +is first created. This is most commonly done with the +.BR vmem_pool_create () +function described in this section. +The other functions +described in this section are for less common cases, where +applications have special needs for creating pools or examining +library state. +.PP +Once created, a memory pool is represented by an opaque pool handle, +of type +.IR "VMEM *" , +which is passed to the functions for memory allocation described in +the next section. +.PP +.BI "VMEM *vmem_pool_create(const char *" dir ", size_t " size ); +.IP +The +.BR vmem_pool_create () +function creates a memory pool. The resulting pool is then used with +functions like +.BR vmem_malloc () +and +.BR vmem_free () +to provide the familiar +.I malloc-like +programming model for the memory pool. +.BR vmem_pool_create () +creates the pool by allocating a +temporary file in the given directory +.IR dir . +The file is created in a fashion similar to +.BR tmpfile (3), +so that the file name does not appear when the directory is listed and +the space is automatically freed when the program terminates. +.I size +bytes are allocated +and the resulting space is memory-mapped. +The minimum +.I size +value allowed by the library is defined in +.B <libvmem.h> +as +.BR VMEM_MIN_POOL . +Calling +.BR vmem_pool_create () +with a size smaller than that will return an error. +The maximum allowed size is not limited by +.BR libvmem , +but by the file system specified by the +.I dir +argument. +The +.I size +passed in is the raw size of the memory pool and +.B libvmem +will use some of that space for its own metadata. +.BR vmem_pool_create () +returns an opaque memory pool handle or NULL if an error occurred +(in which case +.I errno +is set appropriately). The opaque memory pool handle +is then used with the other functions +described in this man page that operate on a specific memory pool. +.PP +.BI "VMEM *vmem_pool_create_in_region(void *" addr ", size_t " size ); +.IP +The +.BR vmem_pool_create_in_region () +is an alternate +.B libvmem +entry point for creating a memory pool. +It is for the rare case where an application needs to create +a memory pool from an already memory-mapped region. +Instead of allocating space from a given file system, +.BR vmem_pool_create_in_region () +is given the memory region explicitly via the +.I addr +and +.I size +arguments. +Any data in the region is lost by calling +.BR vmem_pool_create_in_region (), +which will immediately store its own data structures for managing +the pool there. +Like +.BR vmem_pool_create () +above, the minimum +.I size +allowed is defined as +.BR VMEM_MIN_POOL . +.BR vmem_pool_create_in_region () +returns an opaque memory pool handle or NULL if an error occurred +(in which case +.I errno +is set appropriately). +.PP +.BI "void vmem_pool_delete(VMEM *" vmp ); +.IP +The +.BR vmem_pool_delete () +function releases the memory pool +.IR vmp . +If the memory pool was created using +.BR vmem_create_pool (), +deleting it allows the space to be reclaimed. +.PP +.BI "int vmem_pool_check(VMEM *" vmp ); +.IP +The +.BR vmem_pool_check () +function +performs an exhaustive consistency check of all +.B libvmem +internal data structures in memory pool +.IR vmp . +A return value of zero from +.BR vmem_pool_check () +means that no errors were found, otherwise -1 is returned and errno +is set to +.BR EINVAL . +Since an error return indicates memory pool corruption, applications +should not continue to use a pool in this state. +Additional details about errors found are logged when the log level +is at least 1 (see +.B DEBUGGING +below). +During the consistency check performed by +.BR vmem_pool_check (), +other operations on the same memory pool are locked out. +The checks are all read-only; +.BR vmem_pool_check () +never modifies the memory pool. +This function is mostly useful for +.B libvmem +developers during testing/debugging. +.PP +.BI "int vmem_pool_freespace(VMEM *" vmp ); +.IP +The +.BR vmem_pool_freespace () +function returns the amount of unallocated space available +in the memory pool +.IR vmp . +This return value is in bytes, and should be considered +an approximation since different allocation patterns will require +.B libvmem +to use up different amounts of space for internal metadata. +.PP +.BI "void vmem_pool_stats_print(VMEM *" vmp ", const char *" opts ); +.IP +The +.BR vmem_pool_stats_print () +function produces messages containing statistics about the +given memory pool. +The output is printed using +.BR libvmem 's +internal +.I print_func +function (see +.BR vmem_set_funcs () +below). That means the output typically appears on +.B stderr +unless the caller supplies a replacement +.I print_func +or sets the environment variable +.B VMEM_LOG_FILE +to direct output elsewhere. +The +.I opts +string can either be NULL or it can contain a list of options +that change the stats printed. +General information that never changes during execution can be +omitted by specifying "g" as a character within the opts string. +The characters “m†and “a†can be specified to omit merged arena +and per arena statistics, respectively; “b†and “l†can be specified +to omit per size class statistics for bins and large objects, respectively. +Unrecognized characters are silently ignored. +Note that thread caching may prevent some statistics from being +completely up to date. +See +.BR jemalloc (3) +for more detail (the description of the available +.I opts +above was taken from that man page). +.SH MEMORY ALLOCATION +.PP +This section describes the +.I malloc-like +API provided by +.BR libvmem . +These functions provide the same semantics as their libc namesakes, +but operate on the memory pools specified by their first arguments. +.PP +.BI "void *vmem_malloc(VMEM *" vmp ", size_t " size ); +.IP +The +.BR vmem_malloc () +function provides the same semantics as +.BR malloc (3), +but operates on the memory pool +.I vmp +instead of the process heap supplied by the system. +It allocates +.I size +bytes and returns a pointer to the allocated memory. +.IR "The memory is not initialized" . +If +.I size +is 0, then +.BR vmem_malloc () +returns either NULL, +or a unique pointer value that can later be successfully passed to +.BR vmem_free (). +If +.BR vmem_malloc () +is unable to satisfy the allocation request, a NULL pointer is +returned and errno is set appropriately. +.PP +.BI "void vmem_free(VMEM *" vmp ", void *" ptr ); +.IP +The +.BR vmem_free () +function provides the same semantics as +.BR free (3), +but operates on the memory pool +.I vmp +instead of the process heap supplied by the system. +It frees the memory space pointed to by +.IR ptr , +which must have been returned by a previous call to +.BR vmem_malloc (), +.BR vmem_calloc () +or +.BR vmem_realloc () +for +.IR "the same pool of memory" . +Undefined behavior occurs if frees do not correspond to allocated +memory from the same memory pool. +If +.I ptr +is NULL, no operation is performed. +.PP +.BI "void *vmem_calloc(VMEM *" vmp ", size_t " nmemb ", size_t " size ); +.IP +The +.BR vmem_calloc () +function provides the same semantics as +.BR calloc (3), +but operates on the memory pool +.I vmp +instead of the process heap supplied by the system. +It allocates memory for an array of +.I nmemb +elements of +.I size +bytes each and returns a pointer to the allocated memory. +The memory is set to zero. +If +.I nmemb +or +.I size +is 0, then +.BR vmem_calloc () +returns either NULL, +or a unique pointer value that can later be successfully passed to +.BR vmem_free (). +If +.BR vmem_calloc () +is unable to satisfy the allocation request, a NULL pointer is +returned and errno is set appropriately. +.PP +.BI "void *vmem_realloc(VMEM *" vmp ", void *" ptr ", size_t " size ); +.IP +The +.BR vmem_realloc () +function provides the same semantics as +.BR realloc (3), +but operates on the memory pool +.I vmp +instead of the process heap supplied by the system. +It changes the size of the memory block pointed to by +.I ptr +to +.I size +bytes. +The contents will be unchanged in the range from the start of the region +up to the minimum of the old and new sizes. +If the new size is larger than the old size, the added memory will +.I not +be initialized. +If +.I ptr +is NULL, then the call is equivalent to +.IR "vmem_malloc(vmp, size)" , +for all values of +.IR size ; +if +.I size +is equal to zero, +and +.I ptr +is not NULL, then the call is equivalent to +.IR "vmem_free(vmp, ptr)" . +Unless +.I ptr +is NULL, it must have been returned by an earlier call to +.BR vmem_malloc (), +.BR vmem_calloc () +or +.BR vmem_realloc (). +If the area pointed to was moved, a +.I vmem_free(vmp, ptr) +is done. +If +.BR vmem_realloc () +is unable to satisfy the allocation request, a NULL pointer is +returned and errno is set appropriately. +.PP +.BI "void *vmem_aligned_alloc(VMEM *" vmp ", size_t " alignment ", size_t " size ); +.IP +The +.BR vmem_aligned_alloc () +function provides the same semantics as +.BR aligned_alloc (3), +but operates on the memory pool +.I vmp +instead of the process heap supplied by the system. +It allocates +.I size +bytes from the memory pool and returns a pointer +to the allocated memory. +The memory address will be a multiple of +.IR alignment , +which must be a power of two. +If +.BR vmem_aligned_alloc () +is unable to satisfy the allocation request, a NULL pointer is +returned and errno is set appropriately. +.PP +.BI "char *vmem_strdup(VMEM *" vmp ", const char *" s ); +.IP +The +.BR vmem_strdup () +function provides the same semantics as +.BR strdup (3), +but operates on the memory pool +.I vmp +instead of the process heap supplied by the system. +It returns a pointer to a new string which is a +duplicate of the string +.IR s . +Memory for the new string is obtained +with +.BR vmem_malloc (), +on the given memory pool, and can be freed with +.BR vmem_free () +on the same memory pool. +If +.BR vmem_strdup () +is unable to satisfy the allocation request, a NULL pointer is +returned and errno is set appropriately. +.SH MANAGING LIBRARY BEHAVIOR +.PP +The library entry points described in this section are less +commonly used than the previous section. +These entry points expose library information or alter +the default library behavior. +.PP +.nf +.BI "const char *vmem_check_version(" +.BI " unsigned " major_required , +.BI " unsigned " minor_required ); +.fi +.IP +The +.BR vmem_check_version () +function is used to see if the installed +.B libvmem +supports the version of the library API required by an application. +The easiest way to do this is for the application to supply the +compile-time version information, supplied by defines in +.BR <libvmem.h> , +like this: +.IP +.nf +reason = vmem_check_version(VMEM_MAJOR_VERSION, + VMEM_MINOR_VERSION); +if (reason != NULL { + /* version check failed, reason string tells you why */ +} +.fi +.IP +Any mismatch in the major version number is considered a failure, +but a library with a newer minor version number will pass this +check since increasing minor versions imply backwards compatibility. +.IP +An application can also check specifically for the existence of +an interface by checking for the version where that interface was +introduced. These versions are documented in this man page as follows: +unless otherwise specified, all interfaces described here are available +in version 1.0 of the library. Interfaces added after version 1.0 +will contain the text +.I introduced in version x.y +in the section of this manual describing the feature. +.IP +When the version check performed by +.BR vmem_check_version () +is successful, the return value is NULL. Otherwise the return value +is a static string describing the reason for failing the version check. +The string returned by +.BR vmem_check_version () +must not be modified or freed. +.PP +.nf +.BI "void vmem_set_funcs(" +.BI " void *(*" malloc_func ")(size_t " size ), +.BI " void (*" free_func ")(void *" ptr ), +.BI " void *(*" realloc_func ")(void *" ptr ", size_t " size ), +.BI " char *(*" strdup_func ")(const char *" s ), +.BI " void (*" print_func ")(const char *" s )); +.fi +.IP +The +.BR vmem_set_funcs () +function allows an application to override some +interfaces used internally by +.BR libvmem . +Passing in NULL for any of the handlers will cause the +.B libvmem +default function to be used. +The library does not make heavy use of the system malloc functions, but +it does allocate approximately 4-8 kilobytes for each memory pool in use. +The only functions in the malloc family used by the library are represented +by the first four arguments to +.BR vmem_set_funcs (). +The +.I print_func +function is called by +.B libvmem +when the +.BR vmem_pool_stats_print () +entry point is used, or when additional tracing is enabled +in the debug version of the library as described in the +.B DEBUGGING +section below. +The default +.I print_func +used by the library prints to +the file specified by the +.B VMEM_LOG_FILE +environment variable, or to +.B stderr +if that variable is not set. +.SH DEBUGGING +.PP +Two versions of +.B libvmem +are typically available on a development system. +The normal version, accessed when a program is +linked using the +.B -lvmem +option, is optimized for performance. That version skips checks +that impact performance and never logs any trace information or performs +any run-time assertions. A second version, accessed when a program +uses the libraries under +.BR /usr/lib/nvml_debug , +contains run-time assertions and trace points. +The typical way to access the debug version is to set the environment variable +.B LD_LIBRARY_PATH +to +.BR /usr/lib/nvml_debug +or +.BR /usr/lib64/nvml_debug +depending on where the debug libraries are installed on the system. +The trace points in the debug version of the library +are enabled using the environment variable +.BR VMEM_LOG_LEVEL , +which can be set to the following values: +.IP 0 +This is the default level when +.B VMEM_LOG_LEVEL +is not set. +Only statistics are logged, and then only in response to a call to +.BR vmem_pool_stats_print (). +.IP 1 +Additional details on any errors detected are logged (in addition +to returning the errno-based errors as usual). +.IP 2 +A trace of basic operations including allocations and deallocations +is logged. +.IP 3 +This level enables a very verbose amount of function call tracing +in the library. +.IP 4 +This level enables voluminous and fairly obscure tracing information +that is likely only useful to the +.B libvmem +developers. +.PP +The environment variable +.B VMEM_LOG_FILE +specifies a file name where +all logging information should be written, and if +.B VMEM_LOG_FILE +is not set, output goes to stderr. +All prints are done using the +.I print_func +function in +.B libvmem +(see +.BR vmem_set_funcs () +above for details on how to override that function). +.PP +Setting the environment variable +.B VMEM_LOG_LEVEL +has no effect on the non-debug version of +.BR libvmem . +.SH EXAMPLE +.PP +The follow example creates a memory pool, allocates some memory to contain +the string "hello, world", and then frees that memory. +.IP +.nf +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <libvmem.h> + +main() +{ + VMEM *vmp; + char *ptr; + + /* create minimum size pool of memory */ + if ((vmp = vmem_pool_create("/my/pmem-aware/fs", + VMEM_MIN_POOL)) == NULL) { + perror("vmem_pool_create"); + exit(1); + } + + if ((ptr = vmem_malloc(vmp, 100)) == NULL) { + perror("vmem_malloc"); + exit(1); + } + + strcpy(ptr, "hello, world"); + + /* give the memory back */ + vmem_free(vmp, ptr); + + /* ... */ +} +.fi +.SH BUGS +Unlike the normal +.BR malloc (), +which asks the system for additional memory when it runs out, +.B libvmem +allocates the size it is told to and never attempts to grow or shrink +that memory pool. +.SH ACKNOWLEDGEMENTS +.B libvmem +depends on jemalloc, written by Jason Evans, to do the heavy lifting +of managing dynamic memory allocation. See: +.IP +http://www.canonware.com/jemalloc/ +.PP +.B libvmem +builds on the persistent memory programming model +recommended by the SNIA NVM Programming Technical Work Group: +.IP +http://snia.org/nvmp +.SH "SEE ALSO" +.BR malloc (3), +.BR posix_memalign (3), +.BR strdup (3), +.BR mmap (2), +.BR jemalloc (3), +.BR libpmem (3). diff --git a/examples/.gitignore b/examples/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..e85d8524c4a17e5029e19c983307277da586db9b --- /dev/null +++ b/examples/.gitignore @@ -0,0 +1,5 @@ +*.o +pmem_example +pmemblk_example +pmemlog_example +vmem_example diff --git a/examples/Makefile b/examples/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..b470a269cc0760743763680069e0bc40fc6a7010 --- /dev/null +++ b/examples/Makefile @@ -0,0 +1,77 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# examples/Makefile -- build the NVM Library examples +# +TARGETS = pmem_example pmemblk_example pmemlog_example vmem_example +INCS = -I../src/include +CFLAGS = -std=gnu99 -ggdb -Wall -Werror +LIBS = -L../src/debug -pthread + +vmem_example: LIBS += -lvmem +pmem_example pmemblk_example pmemlog_example: LIBS += -lpmem + +all: $(TARGETS) + $(MAKE) -C logfile $@ + $(MAKE) -C assetdb $@ + +clean: + $(RM) *.o core a.out + $(MAKE) -C logfile $@ + $(MAKE) -C assetdb $@ + +clobber: clean + $(RM) $(TARGETS) + $(MAKE) -C logfile $@ + $(MAKE) -C assetdb $@ + +cstyle: + ../utils/cstyle -pP *.[ch] + $(MAKE) -C logfile $@ + $(MAKE) -C assetdb $@ + +.c.o: + $(CC) -c -o $@ $(CFLAGS) $(INCS) $< + +$(TARGETS): + $(CC) -o $@ $< $(LIBS) + +pmem_example: pmem_example.o + +pmemblk_example: pmemblk_example.o + +pmemlog_example: pmemlog_example.o + +vmem_example: vmem_example.o + +.PHONY: all clean clobber cstyle diff --git a/examples/README b/examples/README new file mode 100644 index 0000000000000000000000000000000000000000..4f5755a446ebf98c692629a76bc9b63915b9f03e --- /dev/null +++ b/examples/README @@ -0,0 +1,8 @@ +Linux NVM Library + +This is examples/README. + +This directory contains brief educational examples illustrating the use +of the NVM libraries. For many of these examples, the Makefile rules +are here just to check that the example compiles, loads against the +appropriate library, and passes cstyle. diff --git a/examples/assetdb/.gitignore b/examples/assetdb/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..e17d8d8d4fc67f946de4a6803384971e601808b8 --- /dev/null +++ b/examples/assetdb/.gitignore @@ -0,0 +1,4 @@ +asset_load +asset_list +asset_checkout +asset_checkin diff --git a/examples/assetdb/Makefile b/examples/assetdb/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..844334df6c150b341e1305bd29418bb47881e726 --- /dev/null +++ b/examples/assetdb/Makefile @@ -0,0 +1,68 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# examples/asset/Makefile -- build the NVM Library examples +# +TARGETS = asset_load asset_list asset_checkout asset_checkin +INCS = -I../../src/include +CFLAGS = -std=gnu99 -ggdb -Wall -Werror +LIBS = -L../../src/debug -lpmem -pthread + +all: $(TARGETS) + +clean: + $(RM) *.o core a.out + +clobber: clean + $(RM) $(TARGETS) + +cstyle: + ../../utils/cstyle -pP *.[ch] + +.c.o: + $(CC) -c -o $@ $(CFLAGS) $(INCS) $< + +$(TARGETS): + $(CC) -o $@ $< $(LIBS) + +asset_load: asset_load.o + +asset_list: asset_list.o + +asset_checkout: asset_checkout.o + +asset_checkin: asset_checkin.o + +asset_load.o asset_list.o asset_checkout.o asset_checkin.o: asset.h + +.PHONY: all clean clobber cstyle diff --git a/examples/assetdb/README b/examples/assetdb/README new file mode 100644 index 0000000000000000000000000000000000000000..efe64c3baf33b4c3caa66cee43e0d923f8b8e3fc --- /dev/null +++ b/examples/assetdb/README @@ -0,0 +1,47 @@ +Linux NVM Library + +This is examples/asset/README. + +This example illustrates how a very simple database can be built using the +atomic arrays provided by libpmem (pmemblk). An array of records is created to +track a list of assets (like books or computers for example). Each asset is +represented by a fixed-length record in the asset database. Since updates to a +single record are atomic, the file remains consistent even if interrupted +during an update. To run this example, follow these steps: + +0. Build the example with "make". libpmem must be built first (i.e. + by running "make" in ../../src). To allow the example to find + libpmem, you can set the environment variable: + $ export LD_LIBRARY_PATH=../../src/debug + +1. Create the assetdb file. This can be anywhere but the point is it + will be a much faster database file if it is created on a PMEM-aware + file system. For example, if /pmem is the mount point for a + PMEM-aware file system: + + $ truncate -s 1G /pmem/assetdb + +2. Load up the assets from a list of assets, which is just a simple text + file containing asset description strings, one per line: + + $ asset_load /pmem/assetdb assetlist + +3. Print the assets any time using: + + $ asset_list /pmem/assetdb + +4. To mark an asset as checked out to someone: + + $ asset_checkout /pmem/assetdb asset-ID name + + The asset-ID is the ID printed by asset_list. The name may require + quotes if it contains any whitespace or special characters. + +5. To mark an asset as no longer checked out: + + $ asset_checkin /pmem/assetdb asset-ID + +As this is just an example to illustrate how pmemblk works, it may take +some trial-and-error to find the best size for the assetdb -- the file +must be large enough to hold about 512 bytes for each asset record, plus +about 1% overhead used by libpmem to provide the atomicity. diff --git a/examples/assetdb/asset.h b/examples/assetdb/asset.h new file mode 100644 index 0000000000000000000000000000000000000000..7c98533d6022a25345cfe605ef199c6c42221bee --- /dev/null +++ b/examples/assetdb/asset.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY LOG OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define ASSET_NAME_MAX 256 +#define ASSET_USER_NAME_MAX 64 +#define ASSET_CHECKED_OUT 2 +#define ASSET_FREE 1 + +struct asset { + char name[ASSET_NAME_MAX]; + char user[ASSET_USER_NAME_MAX]; + time_t time; + int state; +}; diff --git a/examples/assetdb/asset_checkin.c b/examples/assetdb/asset_checkin.c new file mode 100644 index 0000000000000000000000000000000000000000..214a0b29bc5073d8c3635a2e47ccdf97d23fa28e --- /dev/null +++ b/examples/assetdb/asset_checkin.c @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY LOG OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * asset_checkin -- mark an asset as no longer checked out + * + * Usage: + * asset_checkin /path/to/pm-aware/file asset-ID + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <string.h> +#include <time.h> +#include <libpmem.h> + +#include "asset.h" + +int +main(int argc, char *argv[]) +{ + int fd; + PMEMblk *pbp; + struct asset asset; + int assetid; + + if (argc < 3) { + fprintf(stderr, "usage: %s assetdb asset-ID\n", argv[0]); + exit(1); + } + + assetid = atoi(argv[2]); + + if ((fd = open(argv[1], O_RDWR)) == -1) { + perror(argv[1]); + exit(1); + } + + /* open an array of atomically writable elements */ + if ((pbp = pmemblk_map(fd, sizeof (struct asset))) == NULL) { + perror("pmemblk_map"); + exit(1); + } + + close(fd); + + /* read a required element in */ + if (pmemblk_read(pbp, &asset, (off_t)assetid) < 0) { + perror("pmemblk_read"); + exit(1); + } + + /* check if it contains any data */ + if ((asset.state != ASSET_FREE) && + (asset.state != ASSET_CHECKED_OUT)) { + fprintf(stderr, "Asset ID %d not found", assetid); + exit(1); + } + + /* change state to free, clear user name and timestamp */ + asset.state = ASSET_FREE; + asset.user[0] = '\0'; + asset.time = 0; + + if (pmemblk_write(pbp, &asset, (off_t)assetid) < 0) { + perror("pmemblk_write"); + exit(1); + } + + pmemblk_unmap(pbp); +} diff --git a/examples/assetdb/asset_checkout.c b/examples/assetdb/asset_checkout.c new file mode 100644 index 0000000000000000000000000000000000000000..cee3e834cfdc43ddca5f40973cca04072532b498 --- /dev/null +++ b/examples/assetdb/asset_checkout.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY LOG OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * asset_checkout -- mark an asset as checked out to someone + * + * Usage: + * asset_checkin /path/to/pm-aware/file asset-ID name + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <string.h> +#include <time.h> +#include <libpmem.h> + +#include "asset.h" + +int +main(int argc, char *argv[]) +{ + int fd; + PMEMblk *pbp; + struct asset asset; + int assetid; + + if (argc < 4) { + fprintf(stderr, "usage: %s assetdb asset-ID name\n", argv[0]); + exit(1); + } + + assetid = atoi(argv[2]); + + if ((fd = open(argv[1], O_RDWR)) == -1) { + perror(argv[1]); + exit(1); + } + + /* open an array of atomically writable elements */ + if ((pbp = pmemblk_map(fd, sizeof (struct asset))) == NULL) { + perror("pmemblk_map"); + exit(1); + } + + close(fd); + + /* read a required element in */ + if (pmemblk_read(pbp, &asset, (off_t)assetid) < 0) { + perror("pmemblk_read"); + exit(1); + } + + /* check if it contains any data */ + if ((asset.state != ASSET_FREE) && + (asset.state != ASSET_CHECKED_OUT)) { + fprintf(stderr, "Asset ID %d not found", assetid); + exit(1); + } + + if (asset.state == ASSET_CHECKED_OUT) { + fprintf(stderr, "Asset ID %d already checked out\n", assetid); + exit(1); + } + + /* update user name, set checked out state, and take timestamp */ + strncpy(asset.user, argv[3], ASSET_USER_NAME_MAX - 1); + asset.user[ASSET_USER_NAME_MAX - 1] = '\0'; + asset.state = ASSET_CHECKED_OUT; + time(&asset.time); + + /* put it back in the block */ + if (pmemblk_write(pbp, &asset, assetid) < 0) { + perror("pmemblk_write"); + exit(1); + } + + pmemblk_unmap(pbp); +} diff --git a/examples/assetdb/asset_list.c b/examples/assetdb/asset_list.c new file mode 100644 index 0000000000000000000000000000000000000000..13d7b3aba5946dd760245d1bb0657f1d0fd602de --- /dev/null +++ b/examples/assetdb/asset_list.c @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY LOG OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * asset_list -- list all assets in an assetdb file + * + * Usage: + * asset_list /path/to/pm-aware/file + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <string.h> +#include <time.h> +#include <libpmem.h> + +#include "asset.h" + +int +main(int argc, char *argv[]) +{ + int fd; + PMEMblk *pbp; + int assetid; + size_t nelements; + struct asset asset; + + if (argc < 2) { + fprintf(stderr, "usage: %s assetdb\n", argv[0]); + exit(1); + } + + if ((fd = open(argv[1], O_RDWR)) == -1) { + perror(argv[1]); + exit(1); + } + + /* open an array of atomically writable elements */ + if ((pbp = pmemblk_map(fd, sizeof (struct asset))) == NULL) { + perror("pmemblk_map"); + exit(1); + } + + close(fd); + + /* how many elements do we have? */ + nelements = pmemblk_nblock(pbp); + + /* print out all the elements that contain assets data */ + for (assetid = 0; assetid < nelements; ++assetid) { + if (pmemblk_read(pbp, &asset, (off_t)assetid) < 0) { + perror("pmemblk_read"); + exit(1); + } + + if ((asset.state != ASSET_FREE) && + (asset.state != ASSET_CHECKED_OUT)) { + break; + } + + printf("Asset ID: %d\n", (int)assetid); + if (asset.state == ASSET_FREE) + printf(" State: Free\n"); + else { + printf(" State: Checked out\n"); + printf(" User: %s\n", asset.user); + printf(" Time: %s", ctime(&asset.time)); + } + printf(" Name: %s\n", asset.name); + } + + pmemblk_unmap(pbp); +} diff --git a/examples/assetdb/asset_load.c b/examples/assetdb/asset_load.c new file mode 100644 index 0000000000000000000000000000000000000000..b4a205de87d0d8f1740a31111bb901ad56700989 --- /dev/null +++ b/examples/assetdb/asset_load.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY LOG OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * asset_load -- given an assetdb file, an asset list file, load up the assets + * + * Usage: + * truncate -s 1G /path/to/pm-aware/file # before first use + * + * asset_load /path/to/pm-aware/file assetlist + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <string.h> +#include <time.h> +#include <libpmem.h> + +#include "asset.h" + +int +main(int argc, char *argv[]) +{ + int fd; + FILE *fp; + size_t len; + PMEMblk *pbp; + int assetid = 0; + size_t nelements; + char *line = NULL; + + if (argc < 3) { + fprintf(stderr, "usage: %s assetdb assetlist\n", argv[0]); + exit(1); + } + + if ((fd = open(argv[1], O_RDWR)) < 0) { + perror(argv[1]); + exit(1); + } + + /* create an array of atomically writable elements */ + if ((pbp = pmemblk_map(fd, sizeof (struct asset))) == NULL) { + perror("pmemblk_map"); + exit(1); + } + close(fd); + + nelements = pmemblk_nblock(pbp); + + if ((fp = fopen(argv[2], "r")) == NULL) { + perror(argv[2]); + exit(1); + } + + /* + * Read in all the assets from the assetfile and put them in the + * array, if a name of the asset is longer than ASSET_NAME_SIZE_MAX, + * truncate it. + */ + while (getline(&line, &len, fp) != -1) { + struct asset asset; + + if (assetid >= nelements) { + fprintf(stderr, "%s: too many assets to fit in %s " + "(only %d assets loaded)\n", + argv[2], argv[1], assetid); + exit(1); + } + + memset(&asset, '\0', sizeof (asset)); + asset.state = ASSET_FREE; + strncpy(asset.name, line, ASSET_NAME_MAX - 1); + asset.name[ASSET_NAME_MAX - 1] = '\0'; + + if (pmemblk_write(pbp, &asset, (off_t)assetid) < 0) { + perror("pmemblk_write"); + exit(1); + } + + assetid++; + } + + free(line); + fclose(fp); + + pmemblk_unmap(pbp); +} diff --git a/examples/logfile/.gitignore b/examples/logfile/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..3b2f05823afb853d05ad3be91bbe2b7fce239db2 --- /dev/null +++ b/examples/logfile/.gitignore @@ -0,0 +1,2 @@ +addlog +printlog diff --git a/examples/logfile/Makefile b/examples/logfile/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..457640325506bfb088088197537d2de1667b9691 --- /dev/null +++ b/examples/logfile/Makefile @@ -0,0 +1,66 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# examples/logfile/Makefile -- build the NVM Library examples +# +TARGETS = addlog printlog +INCS = -I../../src/include +CFLAGS = -std=gnu99 -ggdb -Wall -Werror +LIBS = -L../../src/debug -pthread + +addlog printlog: LIBS += -lpmem + +all: $(TARGETS) + +clean: + $(RM) *.o core a.out + +clobber: clean + $(RM) $(TARGETS) + +cstyle: + ../../utils/cstyle -pP *.[ch] + +.c.o: + $(CC) -c -o $@ $(CFLAGS) $(INCS) $< + +$(TARGETS): + $(CC) -o $@ $< $(LIBS) + +addlog: addlog.o + +printlog: printlog.o + +addlog.o printlog.o: logentry.h + +.PHONY: all clean clobber cstyle diff --git a/examples/logfile/README b/examples/logfile/README new file mode 100644 index 0000000000000000000000000000000000000000..82024b8f18a87da084dcdaeb079828d81913b296 --- /dev/null +++ b/examples/logfile/README @@ -0,0 +1,34 @@ +Linux NVM Library + +This is examples/logfile/README. + +The example in this directory uses persistent memory to implement a +simple log file using the libpmem "pmemlog" functions. To run this +example, follow these steps: + +0. Build the example with "make". libpmem must be built first (i.e. + by running "make" in ../../src). To allow the example to find + libpmem, you can set the environment variable: + $ export LD_LIBRARY_PATH=../../src/debug + +1. Create the log file. This can be anywhere but the point is it + will be a much faster log file if it is created on a PMEM-aware + file system. For example, if /pmem is the mount point for a + PMEM-aware file system: + + $ truncate -s 1G /pmem/logfile + +2. Append to the log file as many times as you like: + + $ addlog /pmem/logfile "Hello there." + $ addlog /pmem/logfile "First line." "Second line." + ... + +3. Print the contents of the log any time using: + + $ printlog /pmem/logfile + +4. The printlog command will throw away the current log file contents + aftert printing it if given the -t argument: + + $ printlog -t /pmem/logfile diff --git a/examples/logfile/addlog.c b/examples/logfile/addlog.c new file mode 100644 index 0000000000000000000000000000000000000000..972cd0fcc12fd4ee3f4de3f3eca9026629b456c1 --- /dev/null +++ b/examples/logfile/addlog.c @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY LOG OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * addlog -- given a log file, append a log entry + * + * Usage: + * truncate -s 1G /path/to/pm-aware/file # before first use + * + * addlog /path/to/pm-aware/file "first line of entry" "second line" + * + * addlog ... # appends to the log + * + * addlog ... # appends to the log + */ + +#include <stdio.h> +#include <fcntl.h> +#include <time.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <libpmem.h> + +#include "logentry.h" + +int +main(int argc, char *argv[]) +{ + int fd; + PMEMlog *plp; + struct logentry header; + struct iovec *iovp; + struct iovec *next_iovp; + int iovcnt; + + if (argc < 3) { + fprintf(stderr, "usage: %s filename lines...\n", argv[0]); + exit(1); + } + + if ((fd = open(argv[1], O_RDWR)) < 0) { + perror(argv[1]); + exit(1); + } + + if ((plp = pmemlog_map(fd)) == NULL) { + perror("pmemlog_map"); + exit(1); + } + + /* fill in the header */ + time(&header.timestamp); + header.pid = getpid(); + + /* + * Create an iov for pmemlog_appendv(). For each argument given, + * allocate two entries (one for the string, one for the newline + * appended to the string). Allocate 1 additional entry for the + * header that gets prepended to the entry. + */ + iovcnt = (argc - 2) * 2 + 1; + if ((iovp = malloc(sizeof (*iovp) * iovcnt)) == NULL) { + perror("malloc"); + exit(1); + } + next_iovp = iovp; + + /* put the header into iov first */ + next_iovp->iov_base = &header; + next_iovp->iov_len = sizeof (header); + next_iovp++; + + /* + * Now put each arg in, following it with the string "\n". + * Calculate a total character count in header.len along the way. + */ + header.len = 0; + for (int arg = 2; arg < argc; arg++) { + /* add the string given */ + next_iovp->iov_base = argv[arg]; + next_iovp->iov_len = strlen(argv[arg]); + header.len += next_iovp->iov_len; + next_iovp++; + + /* add the newline */ + next_iovp->iov_base = "\n"; + next_iovp->iov_len = 1; + header.len += 1; + next_iovp++; + } + + /* atomically add it all to the log */ + if (pmemlog_appendv(plp, iovp, iovcnt) < 0) { + perror("pmemlog_appendv"); + exit(1); + } + + pmemlog_unmap(plp); + close(fd); +} diff --git a/examples/logfile/logentry.h b/examples/logfile/logentry.h new file mode 100644 index 0000000000000000000000000000000000000000..3403e8fc213960bd2b6e198e9d6b0c60ecae056d --- /dev/null +++ b/examples/logfile/logentry.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY LOG OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef LOGENTRY_H_ +#define LOGENTRY_H_ + +/* + * info prepended to each log entry... + */ +struct logentry { + size_t len; /* length of the rest of the log entry */ + time_t timestamp; + pid_t pid; +}; + +#endif /* LOGENTRY_H_ */ diff --git a/examples/logfile/printlog.c b/examples/logfile/printlog.c new file mode 100644 index 0000000000000000000000000000000000000000..12d22ddb02b3080a84404eb6a3a55fa66074e8c5 --- /dev/null +++ b/examples/logfile/printlog.c @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY LOG OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * printlog -- given a log file, print the entries + * + * Usage: + * printlog [-t] /path/to/pm-aware/file + * + * -t option means truncate the file after printing it. + */ + +#include <stdio.h> +#include <fcntl.h> +#include <time.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <libpmem.h> + +#include "logentry.h" + +/* + * printlog -- callback function called when walking the log + */ +int +printlog(const void *buf, size_t len, void *arg) +{ + const void *endp = buf + len; /* first byte after log contents */ + + /* for each entry in the log... */ + while (buf < endp) { + struct logentry *headerp = (struct logentry *)buf; + buf += sizeof (struct logentry); + + /* print the header */ + printf("Entry from pid: %ld\n", (long)headerp->pid); + printf(" Created: %s", ctime(&headerp->timestamp)); + printf(" Contents:\n"); + + /* print the log data itself */ + fwrite(buf, headerp->len, 1, stdout); + buf += headerp->len; + } + + return 0; +} + +int +main(int argc, char *argv[]) +{ + int opt; + int tflag = 0; + int fd; + PMEMlog *plp; + + while ((opt = getopt(argc, argv, "t")) != -1) + switch (opt) { + case 't': + tflag = 1; + break; + + default: + fprintf(stderr, "usage: %s [-t] file\n", argv[0]); + exit(1); + } + + if (optind >= argc) { + fprintf(stderr, "usage: %s [-t] file\n", argv[0]); + exit(1); + } + + if ((fd = open(argv[optind], O_RDWR)) < 0) { + perror(argv[optind]); + exit(1); + } + + if ((plp = pmemlog_map(fd)) == NULL) { + perror("pmemlog_map"); + exit(1); + } + + /* the rest of the work happens in printlog() above */ + pmemlog_walk(plp, 0, printlog, NULL); + + if (tflag) + pmemlog_rewind(plp); + + pmemlog_unmap(plp); + close(fd); +} diff --git a/examples/pmem_example.c b/examples/pmem_example.c new file mode 100644 index 0000000000000000000000000000000000000000..bbd2dd25036ffeca91b13f9e36bfad1868e70386 --- /dev/null +++ b/examples/pmem_example.c @@ -0,0 +1,45 @@ +#include <sys/mman.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <libpmem.h> + +int +main(int argc, char *argv[]) +{ + int fd; + char *pmaddr; + + /* memory map some persistent memory */ + if ((fd = open("/my/pmem-aware/fs/myfile", O_RDWR)) < 0) { + perror("open"); + exit(1); + } + + /* just map 4k for this example */ + if ((pmaddr = mmap(NULL, 4096, PROT_READ|PROT_WRITE, + MAP_SHARED, fd, 0)) == MAP_FAILED) { + perror("mmap"); + exit(1); + } + close(fd); + + /* store a string to the persistent memory */ + strcpy(pmaddr, "hello, persistent memory"); + + /* + * The above stores may or may not be sitting in cache at + * this point, depending on other system activity causing + * cache pressure. Now force the change to be durable + * (flushed all the say to the persistent memory). If + * unsure whether the file is really persistent memory, + * use pmem_is_pmem() to decide whether pmem_persist() can + * be used, or whether msync() must be used. + */ + if (pmem_is_pmem(pmaddr, 4096)) + pmem_persist(pmaddr, 4096, 0); + else + msync(pmaddr, 4096, MS_SYNC); +} diff --git a/examples/pmemblk_example.c b/examples/pmemblk_example.c new file mode 100644 index 0000000000000000000000000000000000000000..a937760bd29e045e78b102ba4f35843db136d42a --- /dev/null +++ b/examples/pmemblk_example.c @@ -0,0 +1,67 @@ +#include <stdio.h> +#include <fcntl.h> +#include <errno.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <libpmem.h> + +/* size of each element in the PMEM pool (bytes) */ +#define ELEMENT_SIZE ((size_t)1024) + +int +main(int argc, char *argv[]) +{ + int fd; + PMEMblk *pbp; + size_t nelements; + char buf[ELEMENT_SIZE]; + + /* create file on PMEM-aware file system */ + if ((fd = open("/my/pmem-aware/fs/myfile", + O_CREAT|O_RDWR, 0666)) < 0) { + perror("open"); + exit(1); + } + + /* pre-allocate 2GB of persistent memory */ + if ((errno = posix_fallocate(fd, (off_t)0, + (size_t)1024 * 1024 * 1024 * 2)) != 0) { + perror("posix_fallocate"); + exit(1); + } + + /* create an array of atomically writable elements */ + if ((pbp = pmemblk_map(fd, ELEMENT_SIZE)) == NULL) { + perror("pmemblk_map"); + exit(1); + } + + /* how many elements fit into the PMEM pool? */ + nelements = pmemblk_nblock(pbp); + printf("file holds %zu elements\n", nelements); + + /* store a block at index 5 */ + strcpy(buf, "hello, world"); + if (pmemblk_write(pbp, buf, 5) < 0) { + perror("pmemblk_write"); + exit(1); + } + + /* read the block at index 10 (reads as zeros initially) */ + if (pmemblk_read(pbp, buf, 10) < 0) { + perror("pmemblk_write"); + exit(1); + } + + /* zero out the block at index 5 */ + if (pmemblk_set_zero(pbp, 5) < 0) { + perror("pmemblk_set_zero"); + exit(1); + } + + /* ... */ + + pmemblk_unmap(pbp); + close(fd); +} diff --git a/examples/pmemlog_example.c b/examples/pmemlog_example.c new file mode 100644 index 0000000000000000000000000000000000000000..9ca08a0d224bdd8aef22caac671aa8c40f60086a --- /dev/null +++ b/examples/pmemlog_example.c @@ -0,0 +1,67 @@ +#include <stdio.h> +#include <fcntl.h> +#include <errno.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <libpmem.h> + +/* log processing callback for use with pmemlog_walk() */ +int +printit(const void *buf, size_t len, void *arg) +{ + fwrite(buf, len, 1, stdout); + return 0; +} + +int +main(int argc, char *argv[]) +{ + int fd; + PMEMlog *plp; + size_t nbyte; + char *str; + + /* create file on PMEM-aware file system */ + if ((fd = open("/my/pmem-aware/fs/myfile", + O_CREAT|O_RDWR, 0666)) < 0) { + perror("open"); + exit(1); + } + + /* pre-allocate 2GB of persistent memory */ + if ((errno = posix_fallocate(fd, (off_t)0, + (size_t)1024 * 1024 * 1024 * 2)) != 0) { + perror("posix_fallocate"); + exit(1); + } + + /* create a persistent memory resident log */ + if ((plp = pmemlog_map(fd)) == NULL) { + perror("pmemlog_map"); + exit(1); + } + + /* how many bytes does the log hold? */ + nbyte = pmemlog_nbyte(plp); + printf("log holds %zu bytes\n", nbyte); + + /* append to the log... */ + str = "This is the first string appended\n"; + if (pmemlog_append(plp, str, strlen(str)) < 0) { + perror("pmemlog_append"); + exit(1); + } + str = "This is the second string appended\n"; + if (pmemlog_append(plp, str, strlen(str)) < 0) { + perror("pmemlog_append"); + exit(1); + } + + /* print the log contents */ + printf("log contains:\n"); + pmemlog_walk(plp, 0, printit, NULL); + + pmemlog_unmap(plp); + close(fd); +} diff --git a/examples/vmem_example.c b/examples/vmem_example.c new file mode 100644 index 0000000000000000000000000000000000000000..a6e5f01f4693502b24b8a9e5cd3af7a1998454c3 --- /dev/null +++ b/examples/vmem_example.c @@ -0,0 +1,30 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <libvmem.h> + +int +main(int argc, char *argv[]) +{ + VMEM *vmp; + char *ptr; + + /* create minimum size pool of memory */ + if ((vmp = vmem_pool_create("/my/pmem-aware/fs", + VMEM_MIN_POOL)) == NULL) { + perror("vmem_pool_create"); + exit(1); + } + + if ((ptr = vmem_malloc(vmp, 100)) == NULL) { + perror("vmem_malloc"); + exit(1); + } + + strcpy(ptr, "hello, world"); + + /* give the memory back */ + vmem_free(vmp, ptr); + + /* ... */ +} diff --git a/src/.gitignore b/src/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..2e2c8c7deeff768b9d7894be565f7e4f806beb47 --- /dev/null +++ b/src/.gitignore @@ -0,0 +1,8 @@ +*.so +*.so.* +*.a +tags +TAGS +cscope.in.out +cscope.out +cscope.po.out diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..efc116970c0efcd1a372a5e521975ecc65452304 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,87 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/Makefile -- build the NVM Library +# +VARIANTS = debug nondebug + +JEMALLOC_DIR = $(CURDIR)/jemalloc +export JEMALLOC_DIR + +HEADERS_DESTDIR = $(DESTDIR)/usr/include +HEADERS_INSTALL = include/libpmem.h include/libvmem.h + +SCOPEFILES = *.[ch] include/*.[ch] jemalloc/src/*.[ch]\ + $(JEMALLOC_DIR)/include/jemalloc/*.h\ + $(JEMALLOC_DIR)/include/jemalloc/internal/*.h + +all : TARGET = all +clean : TARGET = clean +clobber : TARGET = clobber +jeconfig: TARGET = jeconfig +jemalloc: TARGET = jemalloc +install : TARGET = install + +all jeconfig jemalloc clean clobber install: $(VARIANTS) + +$(VARIANTS): + $(MAKE) -C $@ $(TARGET) + +clean: + $(MAKE) -C test clean + $(RM) tags cscope.in.out cscope.out cscope.po.out + +clobber: + $(MAKE) -C test clobber + +test: $(VARIANTS) + $(MAKE) -C test all + $(MAKE) -C $(JEMALLOC_DIR) tests + +check: test + cd test && ./RUNTESTS + $(MAKE) -C $(JEMALLOC_DIR) check + +cscope: + cscope -q -b $(SCOPEFILES) + ctags -e $(SCOPEFILES) + +cstyle: + ../utils/cstyle -pP *.[ch] include/*.[ch] + $(MAKE) -C test cstyle + +install: + install -d $(HEADERS_DESTDIR) + install -p -m 0644 $(HEADERS_INSTALL) $(HEADERS_DESTDIR) + +.PHONY: all jeconfig jemalloc clean clobber test check cscope cstyle install $(VARIANTS) diff --git a/src/Makefile.inc b/src/Makefile.inc new file mode 100644 index 0000000000000000000000000000000000000000..e27358fa1b93a7a352590529749849f0f9432812 --- /dev/null +++ b/src/Makefile.inc @@ -0,0 +1,155 @@ +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# +# src/Makefile.inc -- common Makefile rules for NVM library +# + +JEMALLOC_MAKE_NAME ?= Makefile +JEMALLOC_OBJROOT ?= +JEMALLOC_MAKE = $(JEMALLOC_DIR)/$(JEMALLOC_MAKE_NAME) +JEMALLOC_CFG = $(JEMALLOC_DIR)/configure +JEMALLOC_CFG_AC = $(JEMALLOC_DIR)/configure.ac +JEMALLOC_LIB_NAME = libjemalloc_pic.a +JEMALLOC_LIB = $(JEMALLOC_DIR)/$(JEMALLOC_OBJROOT)lib/$(JEMALLOC_LIB_NAME) + +JECONFIG_FILE = ../jemalloc.cfg +JECONFIG = $(shell cat $(JECONFIG_FILE)) + +MACHINE := $(shell uname -m) + +ifeq ($(MACHINE), x86_64) +ifneq ($(wildcard /usr/lib64),) +LIBDIR = usr/lib64 +else +LIBDIR = usr/lib +endif +else +LIBDIR = usr/lib +endif + +LIBS_DESTDIR = $(DESTDIR)/$(LIBDIR)/$(VARIANT_DESTDIR) + +vpath %.c .. +vpath %.h .. ../include +INCS = -I.. -I../include + +CFLAGS = -std=gnu99 -ggdb -Wall -Werror +LN = ln +TARGETS = libpmem.a libpmem.so libvmem.a libvmem.so +libpmem.a libpmem.so: LIBS += -luuid +COMMONOBJS = out.o util.o +PMEMOBJS = libpmem.o blk.o btt.o log.o pmem.o trn.o $(COMMONOBJS) +VMEMOBJS = libvmem.o vmem.o $(COMMONOBJS) +PMEMMAPFILE = ../libpmem.map +VMEMMAPFILE = ../libvmem.map +PMEMSOVERSION = 1 +VMEMSOVERSION = 1 +EXTRA_JECONFIG = +INSTALL_LINKS = libpmem.so.$(PMEMSOVERSION) libvmem.so.$(VMEMSOVERSION) + +SRCVERSION := $(shell git describe --tags) +out.o: CFLAGS += -DSRCVERSION=\"$(SRCVERSION)\" + +all: $(TARGETS) + +jemalloc: $(JEMALLOC_LIB) + +jeconfig $(JEMALLOC_MAKE): $(JEMALLOC_CFG) $(JECONFIG_FILE) + cd $(JEMALLOC_DIR) && \ + ./configure $(JECONFIG) $(EXTRA_JECONFIG) + -mv -f $(JEMALLOC_DIR)/Makefile $(JEMALLOC_MAKE) + +$(JEMALLOC_CFG): $(JEMALLOC_CFG_AC) + cd $(JEMALLOC_DIR) && \ + autoconf + +$(VMEMOBJS): $(JEMALLOC_LIB) + +$(JEMALLOC_LIB): $(JEMALLOC_MAKE) + make objroot=$(JEMALLOC_OBJROOT) -f $(JEMALLOC_MAKE_NAME) -C $(JEMALLOC_DIR) all + +libpmem.a: $(PMEMOBJS) + $(LD) -o $*_unscoped.o -r $(PMEMOBJS) + objcopy --localize-hidden `sed -n 's/^ *\([a-zA-Z0-9_]*\);$$/-G \1/p' $(PMEMMAPFILE)` $*_unscoped.o $*_all.o + $(AR) rv $@ $*_all.o + +libpmem.so: $(PMEMOBJS) + $(CC) -shared -Wl,--version-script=$(PMEMMAPFILE),-soname,$@.$(PMEMSOVERSION) -o $@ $(PMEMOBJS) $(LIBS) + $(RM) $@.$(PMEMSOVERSION) + $(LN) -s $@ $@.$(PMEMSOVERSION) + + +libvmem.a libvmem.so: INCS += -I$(JEMALLOC_DIR)/include/jemalloc + +libvmem.a: $(VMEMOBJS) $(JEMALLOC_LIB) + $(LD) -o $*_unscoped.o -r $(VMEMOBJS) $(JEMALLOC_LIB) + objcopy --localize-hidden `sed -n 's/^ *\([a-zA-Z0-9_]*\);$$/-G \1/p' $(VMEMMAPFILE)` $*_unscoped.o $*_all.o + $(AR) rv $@ $*_all.o + +libvmem.so: $(VMEMOBJS) $(JEMALLOC_LIB) + $(CC) -shared -Wl,--version-script=$(VMEMMAPFILE),-soname,$@.$(VMEMSOVERSION) -o $@ $(VMEMOBJS) $(JEMALLOC_LIB) + $(RM) $@.$(VMEMSOVERSION) + $(LN) -s $@ $@.$(VMEMSOVERSION) + +.c.o: + $(CC) -c -o $@ $(CFLAGS) $(INCS) -fPIC $< + +clean: + $(RM) *.o core a.out + @if [ -f $(JEMALLOC_MAKE) ];\ + then\ + make objroot=$(JEMALLOC_OBJROOT) -f $(JEMALLOC_MAKE_NAME) -C $(JEMALLOC_DIR) clean;\ + fi + +clobber: clean + $(RM) $(TARGETS) *.so.[0-9]* + -make cfgoutputs_out+=$(JEMALLOC_MAKE) objroot=$(JEMALLOC_OBJROOT) -f $(JEMALLOC_MAKE_NAME) -C $(JEMALLOC_DIR) distclean + rm -rf $(JEMALLOC_CFG) + +install: $(TARGETS) $(INSTALL_LINKS) + install -d $(LIBS_DESTDIR) + install -p -m 0755 $(TARGETS) $(LIBS_DESTDIR) + cp -d $(INSTALL_LINKS) $(LIBS_DESTDIR) + +.PHONY: all clean clobber jeconfig jemalloc install + +libpmem.o: libpmem.c libpmem.h pmem.h util.h out.h +blk.o: blk.c libpmem.h pmem.h blk.h util.h out.h +btt.o: btt.c util.h btt.h btt_layout.h +log.o: log.c libpmem.h pmem.h log.h util.h out.h +pmem.o: pmem.c libpmem.h pmem.h out.h +trn.o: trn.c libpmem.h pmem.h trn.h util.h out.h + +libvmem.o: libvmem.c libvmem.h vmem.h util.h out.h +vmem.o: vmem.c libvmem.h util.h out.h + +out.o: out.c out.h +util.o: util.c util.h out.h diff --git a/src/README b/src/README new file mode 100644 index 0000000000000000000000000000000000000000..dbc33077df6b86a57996fd5135bbcd95a602c2b8 --- /dev/null +++ b/src/README @@ -0,0 +1,20 @@ +Linux NVM Library + +This is src/README. + +This directory contains the source for the NVM Library. + +libvmem is largely just a wrapper around a modified jemalloc +library. See the "jemalloc" subdirectory and the git change +log for those files for details. + +The subdirectory "include" contains header files that get delivered +along with the libraries. Everything else is internal to the libraries +and lives in this directory. + +Two versions of the libraries are built, a debug version and a nondebug +version. The object files and the libraries themselves end up in the +subdirectories "debug" and "nondebug". + +See the top-level README for build, test, and installation instructions. +The basic "make" and "make test" targets also work from this directory. diff --git a/src/blk.c b/src/blk.c new file mode 100644 index 0000000000000000000000000000000000000000..2d2e08502a46bd92fa8651f28b6cd83d98883969 --- /dev/null +++ b/src/blk.c @@ -0,0 +1,572 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY LOG OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * blk.c -- block memory pool entry points for libpmem + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/param.h> +#include <sys/stat.h> +#include <signal.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> +#include <time.h> +#include <stdint.h> +#include <uuid/uuid.h> +#include <pthread.h> +#include <endian.h> +#include <libpmem.h> + +#include "pmem.h" +#include "util.h" +#include "out.h" +#include "btt.h" +#include "blk.h" + +/* + * blk_init -- (internal) load-time initialization for blk + * + * Called automatically by the run-time loader. + */ +__attribute__((constructor)) +static void +blk_init(void) +{ + out_init(LOG_PREFIX, LOG_LEVEL_VAR, LOG_FILE_VAR); + LOG(3, NULL); + util_init(); +} + +/* + * lane_enter -- (internal) acquire a unique lane number + */ +static int +lane_enter(PMEMblk *pbp) +{ + int mylane; + + mylane = __sync_fetch_and_add(&pbp->next_lane, 1) % pbp->nlane; + + /* lane selected, grab the per-lane lock */ + if (pthread_mutex_lock(&pbp->locks[mylane]) < 0) { + LOG(1, "!pthread_mutex_lock"); + return -1; + } + + return mylane; +} + +/* + * lane_exit -- (internal) drop lane lock + */ +static int +lane_exit(PMEMblk *pbp, int mylane) +{ + if (pthread_mutex_unlock(&pbp->locks[mylane]) < 0) { + LOG(1, "!pthread_mutex_unlock"); + return -1; + } + + return 0; +} + +/* + * nsread -- (internal) read data from the namespace encapsulating the BTT + * + * This routine is provided to btt_init() to allow the btt module to + * do I/O on the memory pool containing the BTT layout. + */ +static int +nsread(void *ns, int lane, void *buf, size_t count, off_t off) +{ + struct pmemblk *pbp = (struct pmemblk *)ns; + + LOG(13, "pbp %p lane %d count %zu off %zu", pbp, lane, count, off); + + if (off + count >= pbp->datasize) { + LOG(1, "offset + count (%zu) past end of data area (%zu)", + off + count, pbp->datasize - 1); + errno = EINVAL; + return -1; + } + + memcpy(buf, pbp->data + off, count); + + return 0; +} + +/* + * nswrite -- (internal) write data to the namespace encapsulating the BTT + * + * This routine is provided to btt_init() to allow the btt module to + * do I/O on the memory pool containing the BTT layout. + */ +static int +nswrite(void *ns, int lane, const void *buf, size_t count, off_t off) +{ + struct pmemblk *pbp = (struct pmemblk *)ns; + + LOG(13, "pbp %p lane %d count %zu off %zu", pbp, lane, count, off); + + if (off + count >= pbp->datasize) { + LOG(1, "offset + count (%zu) past end of data area (%zu)", + off + count, pbp->datasize - 1); + errno = EINVAL; + return -1; + } + + void *dest = pbp->data + off; + memcpy(dest, buf, count); + libpmem_persist(pbp->is_pmem, dest, count); + + return 0; +} + +/* + * nsmap -- (internal) allow direct access to a range of a namespace + * + * The caller requests a range to be "mapped" but the return value + * may indicate a smaller amount (in which case the caller is expected + * to call back later for another mapping). + * + * This routine is provided to btt_init() to allow the btt module to + * do I/O on the memory pool containing the BTT layout. + */ +static int +nsmap(void *ns, int lane, void **addrp, size_t len, off_t off) +{ + struct pmemblk *pbp = (struct pmemblk *)ns; + + LOG(12, "pbp %p lane %d len %zu off %zu", pbp, lane, len, off); + + if (off + len >= pbp->datasize) { + LOG(1, "offset + len (%zu) past end of data area (%zu)", + off + len, pbp->datasize - 1); + errno = EINVAL; + return -1; + } + + /* + * Since the entire file is memory-mapped, this callback + * can always provide the entire length requested. + */ + *addrp = pbp->data + off; + + LOG(12, "returning addr %p", *addrp); + + return len; +} + +/* + * nssync -- (internal) flush changes made to a namespace range + * + * This is used in conjunction with the addresses handed out by + * nsmap() above. There's no need to sync things written via + * nswrite() since those changes are flushed each time nswrite() + * is called. + * + * This routine is provided to btt_init() to allow the btt module to + * do I/O on the memory pool containing the BTT layout. + */ +static void +nssync(void *ns, int lane, void *addr, size_t len) +{ + struct pmemblk *pbp = (struct pmemblk *)ns; + + LOG(12, "pbp %p lane %d addr %p len %zu", pbp, lane, addr, len); + + libpmem_persist(pbp->is_pmem, addr, len); +} + +/* callbacks for btt_init() */ +static const struct ns_callback ns_cb = { + nsread, + nswrite, + nsmap, + nssync +}; + +/* + * pmemblk_map_common -- (internal) map a block memory pool + * + * This routine does all the work, but takes a rdonly flag so internal + * calls can map a read-only pool if required. + * + * Passing in bsize == 0 means a valid pool header must exist (which + * will supply the block size). + */ +static PMEMblk * +pmemblk_map_common(int fd, size_t bsize, int rdonly) +{ + LOG(3, "fd %d bsize %zu rdonly %d", fd, bsize, rdonly); + + /* things free by "goto err" if not NULL */ + void *addr = NULL; + struct btt *bttp = NULL; + pthread_mutex_t *locks = NULL; + + struct stat stbuf; + if (fstat(fd, &stbuf) < 0) { + LOG(1, "!fstat"); + return NULL; + } + + if (stbuf.st_size < PMEMBLK_MIN_POOL) { + LOG(1, "size %zu smaller than %zu", + stbuf.st_size, PMEMBLK_MIN_POOL); + errno = EINVAL; + return NULL; + } + + if ((addr = util_map(fd, stbuf.st_size, rdonly)) == NULL) + return NULL; /* util_map() set errno, called LOG */ + + /* check if the mapped region is located in persistent memory */ + int is_pmem = pmem_is_pmem(addr, stbuf.st_size); + + /* opaque info lives at the beginning of mapped memory pool */ + struct pmemblk *pbp = addr; + + struct pool_hdr hdr; + memcpy(&hdr, &pbp->hdr, sizeof (hdr)); + + if (util_convert_hdr(&hdr)) { + /* + * valid header found + */ + if (strncmp(hdr.signature, BLK_HDR_SIG, POOL_HDR_SIG_LEN)) { + LOG(1, "wrong pool type: \"%s\"", hdr.signature); + + errno = EINVAL; + goto err; + } + + if (hdr.major != BLK_FORMAT_MAJOR) { + LOG(1, "blk pool version %d (library expects %d)", + hdr.major, BLK_FORMAT_MAJOR); + + errno = EINVAL; + goto err; + } + + size_t hdr_bsize = le32toh(pbp->bsize); + if (bsize && bsize != hdr_bsize) { + LOG(1, "wrong bsize (%zu), pool created with bsize %zu", + bsize, hdr_bsize); + errno = EINVAL; + goto err; + } + bsize = hdr_bsize; + LOG(3, "using block size from header: %zu", bsize); + + int retval = util_feature_check(&hdr, BLK_FORMAT_INCOMPAT, + BLK_FORMAT_RO_COMPAT, + BLK_FORMAT_COMPAT); + if (retval < 0) + goto err; + else if (retval == 0) + rdonly = 1; + } else { + /* + * no valid header was found + */ + if (rdonly) { + LOG(1, "read-only and no header found"); + errno = EROFS; + goto err; + } + LOG(3, "creating new blk memory pool"); + + struct pool_hdr *hdrp = &pbp->hdr; + + memset(hdrp, '\0', sizeof (*hdrp)); + strncpy(hdrp->signature, BLK_HDR_SIG, POOL_HDR_SIG_LEN); + hdrp->major = htole32(BLK_FORMAT_MAJOR); + hdrp->compat_features = htole32(BLK_FORMAT_COMPAT); + hdrp->incompat_features = htole32(BLK_FORMAT_INCOMPAT); + hdrp->ro_compat_features = htole32(BLK_FORMAT_RO_COMPAT); + uuid_generate(hdrp->uuid); + hdrp->crtime = htole64((uint64_t)time(NULL)); + util_checksum(hdrp, sizeof (*hdrp), &hdrp->checksum, 1); + hdrp->checksum = htole64(hdrp->checksum); + + /* store pool's header */ + libpmem_persist(is_pmem, hdrp, sizeof (*hdrp)); + + /* create rest of required metadata */ + pbp->bsize = htole32(bsize); + libpmem_persist(is_pmem, &pbp->bsize, sizeof (bsize)); + } + + /* + * Use some of the memory pool area for run-time info. This + * run-time state is never loaded from the file, it is always + * created here, so no need to worry about byte-order. + */ + pbp->addr = addr; + pbp->size = stbuf.st_size; + pbp->rdonly = rdonly; + pbp->is_pmem = is_pmem; + pbp->data = addr + roundup(sizeof (*pbp), BLK_FORMAT_DATA_ALIGN); + pbp->datasize = (pbp->addr + pbp->size) - pbp->data; + + LOG(4, "data area %p data size %zu bsize %zu", + pbp->data, pbp->datasize, bsize); + + int ncpus = sysconf(_SC_NPROCESSORS_ONLN); + if (ncpus < 1) + ncpus = 1; + + bttp = btt_init(pbp->datasize, (uint32_t)bsize, pbp->hdr.uuid, + ncpus, pbp, &ns_cb); + + if (bttp == NULL) + goto err; /* btt_init set errno, called LOG */ + + pbp->bttp = bttp; + + pbp->nlane = btt_nlane(pbp->bttp); + pbp->next_lane = 0; + if ((locks = Malloc(pbp->nlane * sizeof (*locks))) == NULL) { + LOG(1, "!Malloc for lane locks"); + goto err; + } + + for (int i = 0; i < pbp->nlane; i++) + if (pthread_mutex_init(&locks[i], NULL) < 0) { + LOG(1, "!pthread_mutex_init"); + goto err; + } + + pbp->locks = locks; + + /* + * If possible, turn off all permissions on the pool header page. + * + * The prototype PMFS doesn't allow this when large pages are in + * use not it is not considered an error if this fails. + */ + util_range_none(addr, sizeof (struct pool_hdr)); + +#ifdef notdef + /* XXX not ready to protect the pool just yet */ + /* the rest should be kept read-only for debug version */ + RANGE_RO(addr + sizeof (struct pool_hdr), + stbuf.st_size - sizeof (struct pool_hdr)); +#endif /* notdef */ + + LOG(3, "pbp %p", pbp); + return pbp; + +err: + LOG(4, "error clean up"); + int oerrno = errno; + if (locks) + Free((void *)locks); + if (bttp) + btt_fini(bttp); + util_unmap(addr, stbuf.st_size); + errno = oerrno; + return NULL; +} + +/* + * pmemblk_map -- map a block memory pool + */ +PMEMblk * +pmemblk_map(int fd, size_t bsize) +{ + LOG(3, "fd %d bsize %zu", fd, bsize); + + return pmemblk_map_common(fd, bsize, 0); +} + +/* + * pmemblk_unmap -- unmap a block memory pool + */ +void +pmemblk_unmap(PMEMblk *pbp) +{ + LOG(3, "pbp %p", pbp); + + btt_fini(pbp->bttp); + if (pbp->locks) { + for (int i = 0; i < pbp->nlane; i++) + pthread_mutex_destroy(&pbp->locks[i]); + Free((void *)pbp->locks); + } + util_unmap(pbp->addr, pbp->size); +} + +/* + * pmemblk_nblock -- return number of usable blocks in a block memory pool + */ +size_t +pmemblk_nblock(PMEMblk *pbp) +{ + LOG(3, "pbp %p", pbp); + + return btt_nlba(pbp->bttp); +} + +/* + * pmemblk_read -- read a block in a block memory pool + */ +int +pmemblk_read(PMEMblk *pbp, void *buf, off_t blockno) +{ + LOG(3, "pbp %p buf %p blockno %zu", pbp, buf, blockno); + + int lane = lane_enter(pbp); + + if (lane < 0) + return -1; + + int err = btt_read(pbp->bttp, lane, blockno, buf); + + lane_exit(pbp, lane); + + return err; +} + +/* + * pmemblk_write -- write a block (atomically) in a block memory pool + */ +int +pmemblk_write(PMEMblk *pbp, const void *buf, off_t blockno) +{ + LOG(3, "pbp %p buf %p blockno %zu", pbp, buf, blockno); + + if (pbp->rdonly) { + LOG(1, "EROFS (pool is read-only)"); + errno = EROFS; + return -1; + } + + int lane = lane_enter(pbp); + + if (lane < 0) + return -1; + + int err = btt_write(pbp->bttp, lane, blockno, buf); + + lane_exit(pbp, lane); + + return err; +} + +/* + * pmemblk_set_zero -- zero a block in a block memory pool + */ +int +pmemblk_set_zero(PMEMblk *pbp, off_t blockno) +{ + LOG(3, "pbp %p blockno %zu", pbp, blockno); + + if (pbp->rdonly) { + LOG(1, "EROFS (pool is read-only)"); + errno = EROFS; + return -1; + } + + int lane = lane_enter(pbp); + + if (lane < 0) + return -1; + + int err = btt_set_zero(pbp->bttp, lane, blockno); + + lane_exit(pbp, lane); + + return err; +} + +/* + * pmemblk_set_error -- set the error state on a block in a block memory pool + */ +int +pmemblk_set_error(PMEMblk *pbp, off_t blockno) +{ + LOG(3, "pbp %p blockno %zu", pbp, blockno); + + if (pbp->rdonly) { + LOG(1, "EROFS (pool is read-only)"); + errno = EROFS; + return -1; + } + + int lane = lane_enter(pbp); + + if (lane < 0) + return -1; + + int err = btt_set_error(pbp->bttp, lane, blockno); + + lane_exit(pbp, lane); + + return err; +} + +/* + * pmemblk_check -- block memory pool consistency check + */ +int +pmemblk_check(const char *path) +{ + LOG(3, "path \"%s\"", path); + + int fd = open(path, O_RDWR); + + if (fd < 0) { + LOG(1, "!open"); + return -1; + } + + /* open the pool read-only */ + PMEMblk *pbp = pmemblk_map_common(fd, 0, 1); + close(fd); + + if (pbp == NULL) + return -1; /* errno set by pmemblk_map_common() */ + + int retval = btt_check(pbp->bttp); + int oerrno = errno; + pmemblk_unmap(pbp); + errno = oerrno; + + return retval; +} diff --git a/src/blk.h b/src/blk.h new file mode 100644 index 0000000000000000000000000000000000000000..5dfaf752b8a612300fef34c5c7099ea48d61369b --- /dev/null +++ b/src/blk.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * blk.h -- internal definitions for libpmem blk module + */ + +/* attributes of the blk memory pool format for the pool header */ +#define BLK_HDR_SIG "PMEMBLK" /* must be 8 bytes including '\0' */ +#define BLK_FORMAT_MAJOR 1 +#define BLK_FORMAT_COMPAT 0x0000 +#define BLK_FORMAT_INCOMPAT 0x0000 +#define BLK_FORMAT_RO_COMPAT 0x0000 + +struct pmemblk { + struct pool_hdr hdr; /* memory pool header */ + + /* root info for on-media format... */ + uint32_t bsize; /* block size */ + + /* some run-time state, allocated out of memory pool... */ + void *addr; /* mapped region */ + size_t size; /* size of mapped region */ + int is_pmem; /* true if pool is PMEM */ + int rdonly; /* true if pool is opened read-only */ + void *data; /* post-header data area */ + size_t datasize; /* size of data area */ + size_t nlba; /* number of LBAs in pool */ + struct btt *bttp; /* btt handle */ + struct ns_callback *ns_cbp; /* callbacks for btt_init() */ + int nlane; /* number of lanes */ + unsigned next_lane; /* used to rotate through lanes */ + pthread_mutex_t *locks; /* one per lane */ +}; + +/* data area starts at this alignement after the struct pmemblk above */ +#define BLK_FORMAT_DATA_ALIGN 4096 diff --git a/src/btt.c b/src/btt.c new file mode 100644 index 0000000000000000000000000000000000000000..c642aae529af829199f16952eea3855a1b4606f8 --- /dev/null +++ b/src/btt.c @@ -0,0 +1,1676 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * btt.c -- block translation table providing atomic block updates + * + * This is a user-space implementation of the BTT mechanism providing + * single block powerfail write atomicity, as described by: + * The NVDIMM Namespace Specification + * + * To use this module, the caller must provide three routines for + * accessing the namespace containing the data (in this context, + * "namespace" refers to the storage containing the BTT layout, such + * as a file). All namespace I/O is done by these three calls: + * + * nsread Read count bytes from namespace at offset off + * nswrite Write count bytes to namespace at offset off + * nsmap Return direct access to a range of a namespace + * nssync Flush changes made to an nsmap'd range + * + * Data written by the nswrite callback is flushed out to the media + * (made durable) when the call returns. Data written directly via + * the nsmap callback must be flushed explicitly using nssync. + * + * The caller passes these callbacks, along with information such as + * namespace size and UUID to btt_init() and gets back an opaque handle + * which is then used with the rest of the entry points. + * + * Here is a brief list of the entry points to this module: + * + * btt_nlane Returns number of concurrent threads allowed + * + * btt_nlba Returns the usable size, as a count of LBAs + * + * btt_read Reads a single block at a given LBA + * + * btt_write Writes a single block (atomically) at a given LBA + * + * btt_set_zero Sets a block to read back as zeros + * + * btt_set_error Sets a block to return error on read + * + * btt_check Checks the BTT metadata for consistency + * + * btt_fini Frees run-time state, done using namespace + * + * If the caller is multi-threaded, it must only allow btt_nlane() threads + * to enter this module at a time, each assigned a unique "lane" number + * between 0 and btt_nlane() - 1. + * + * There are a number of static routines defined in this module. Here's + * a brief overview of the most important routines: + * + * read_layout Checks for valid BTT layout and builds run-time state. + * A number of helper functions are used by read_layout + * to handle various parts of the metadata: + * read_info + * read_arenas + * read_arena + * read_flogs + * read_flog_pair + * + * write_layout Generates a new BTT layout when one doesn't exist. + * Once a new layout is written, write_layout uses + * the same helper functions above to construct the + * run-time state. + * + * invalid_lba Range check done by each entry point that takes + * an LBA. + * + * lba_to_arena_lba + * Find the arena and LBA in that arena for a given + * external LBA. This is the heart of the arena + * range matching logic. + * + * flog_update Update the BTT free list/log combined data structure + * (known as the "flog"). This is the heart of the + * logic that makes writes powerfail atomic. + * + * map_lock These routines provide atomic access to the BTT map + * map_unlock data structure in an area. + * map_abort + * + * map_entry_setf Common code for btt_set_zero() and btt_set_error(). + * + * zero_block Generate a block of all zeros (instead of actually + * doing a read), when the metadata indicates the + * block should read as zeros. + * + * build_rtt These routines construct the run-time tracking + * build_map_locks data structures used during I/O. + */ + +#include <stdio.h> +#include <sys/param.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <string.h> +#include <stdarg.h> +#include <stdint.h> +#include <pthread.h> +#include <endian.h> + +#include "out.h" +#include "util.h" +#include "btt.h" +#include "btt_layout.h" + +/* + * The opaque btt handle containing state tracked by this module + * for the btt namespace. This is created by btt_init(), handed to + * all the other btt_* entry points, and deleted by btt_fini(). + */ +struct btt { + int nlane; /* number of concurrent threads allowed per btt */ + + /* + * The laidout flag indicates whether the namespace contains valid BTT + * metadata. It is initialized by read_layout() and if no valid layout + * is found, all reads return zeros and the first write will write the + * BTT layout. The layout_write_mutex protects the laidout flag so + * only one write threads ends up writing the initial metadata by + * calling write_layout(). + */ + pthread_mutex_t layout_write_mutex; + int laidout; + + /* + * UUID of the containing namespace, used to validate BTT metadata. + */ + uint8_t parent_uuid[BTTINFO_UUID_LEN]; + + /* + * Parameters controlling/describing the BTT layout. + */ + uint64_t rawsize; /* size of containing namespace */ + uint32_t lbasize; /* external LBA size */ + uint32_t nfree; /* available flog entries */ + uint64_t nlba; /* total number of external LBAs */ + int narena; /* number of arenas */ + + /* run-time state kept for each arena */ + struct arena { + uint32_t flags; /* arena flags (btt_info) */ + uint64_t external_nlba; /* LBAs that live in this arena */ + uint32_t internal_lbasize; + uint32_t internal_nlba; + + /* + * The following offsets are relative to the beginning of + * the encapsulating namespace. This is different from + * how these offsets are stored on-media, where they are + * relative to the start of the arena. The offset are + * converted by read_layout() to make them more convenient + * for run-time use. + */ + uint64_t startoff; /* offset to start of arena */ + uint64_t dataoff; /* offset to arena data area */ + uint64_t mapoff; /* offset to area map */ + uint64_t flogoff; /* offset to area flog */ + uint64_t nextoff; /* offset to next arena */ + + /* + * Run-time flog state. Indexed by lane. + * + * The write path uses the flog to find the free block + * it writes to before atomically making it the new + * active block for an external LBA. + * + * The read path doesn't use the flog at all. + */ + struct flog_runtime { + struct btt_flog flog; /* current info */ + off_t entries[2]; /* offsets for flog pair */ + int next; /* next write (0 or 1) */ + } *flogs; + + /* + * Read tracking table. Indexed by lane. + * + * Before using a free block found in the flog, the write path + * scans the rtt to see if there are any outstanding reads on + * that block (reads that started before the block was freed by + * a concurrent write). Unused slots in the rtt are indicated + * by setting the error bit, BTT_MAP_ENTRY_ERROR, so that the + * entry won't match any post-map LBA when checked. + */ + uint32_t volatile *rtt; + + /* + * Map locking. Indexed by pre-map LBA modulo nlane. + */ + pthread_spinlock_t *map_locks; + } *arenas; + + /* + * Callbacks for doing I/O to namespace. These are provided by + * the code calling the BTT module, which passes them in to + * btt_init(). All namespace I/O is done using these. + * + * The opaque namespace handle "ns" was provided by the code calling + * the BTT module and is passed to each callback to identify the + * namespace being accessed. + */ + void *ns; + const struct ns_callback *ns_cbp; +}; + +/* + * Signature for arena info blocks. Total size is 16 bytes, including + * the '\0' added to the string by the declaration (the last two bytes + * of the string are '\0'). + */ +static const char Sig[] = "BTT_ARENA_INFO\0"; + +/* + * Zeroed out flog entry, used when initializing the flog. + */ +static const struct btt_flog Zflog; + +/* + * Lookup table and macro for looking up sequence numbers. These are + * the 2-bit numbers that cycle between 01, 10, and 11. + * + * To advance a sequence number to the next number, use something like: + * seq = NSEQ(seq); + */ +static const unsigned Nseq[] = { 0, 2, 3, 1 }; +#define NSEQ(seq) (Nseq[(seq) & 3]) + +/* + * invalid_lba -- (internal) set errno and return true if lba is invalid + * + * This function is used at the top of the entry points where an external + * LBA is provided, like this: + * + * if (invalid_lba(bttp, lba)) + * return -1; + */ +static int +invalid_lba(struct btt *bttp, uint64_t lba) +{ + LOG(3, "bttp %p lba %zu", bttp, lba); + + if (lba >= bttp->nlba) { + LOG(1, "lba out of range (nlba %zu)", bttp->nlba); + errno = EINVAL; + return 1; + } + + return 0; +} + +/* + * read_info -- (internal) convert btt_info to host byte order & validate + * + * Returns true if info block is valid, and all the integer fields are + * converted to host byte order. If the info block is not valid, this + * routine returns false and the info block passed in is left in an + * unknown state. + */ +static int +read_info(struct btt_info *infop) +{ + LOG(3, "infop %p", infop); + + if (memcmp(infop->sig, Sig, BTTINFO_SIG_LEN)) { + LOG(3, "signature invalid"); + return 0; + } + + /* to be valid, info block must have a major version of at least 1 */ + if ((infop->major = le16toh(infop->major)) == 0) { + LOG(3, "invalid major version (0)"); + return 0; + } + + infop->flags = le32toh(infop->flags); + infop->minor = le16toh(infop->minor); + infop->external_lbasize = le32toh(infop->external_lbasize); + infop->external_nlba = le32toh(infop->external_nlba); + infop->internal_lbasize = le32toh(infop->internal_lbasize); + infop->internal_nlba = le32toh(infop->internal_nlba); + infop->nfree = le32toh(infop->nfree); + infop->infosize = le32toh(infop->infosize); + infop->nextoff = le64toh(infop->nextoff); + infop->dataoff = le64toh(infop->dataoff); + infop->mapoff = le64toh(infop->mapoff); + infop->flogoff = le64toh(infop->flogoff); + infop->infooff = le64toh(infop->infooff); + infop->checksum = le64toh(infop->checksum); + + /* and to be valid, the fields must checksum correctly */ + if (!util_checksum(infop, sizeof (*infop), &infop->checksum, 0)) { + LOG(3, "invalid checksum"); + return 0; + } + + return 1; +} + +/* + * read_flog_pair -- (internal) load up a single flog pair + * + * Zero is returned on success, otherwise -1/errno. + * + * XXX lots of byzantine checks could be added, like range checking lbas + */ +static int +read_flog_pair(struct btt *bttp, int lane, struct arena *arenap, + off_t flog_off, struct flog_runtime *flog_runtimep, int flognum) +{ + LOG(5, "bttp %p lane %d arenap %p flog_off %zu runtimep %p flognum %d", + bttp, lane, arenap, flog_off, flog_runtimep, flognum); + + flog_runtimep->entries[0] = flog_off; + flog_runtimep->entries[1] = flog_off + sizeof (struct btt_flog); + + struct btt_flog flog_pair[2]; + if ((*bttp->ns_cbp->nsread)(bttp->ns, lane, flog_pair, + sizeof (flog_pair), flog_off) < 0) + return -1; + + flog_pair[0].lba = le32toh(flog_pair[0].lba); + flog_pair[0].old_map = le32toh(flog_pair[0].old_map); + flog_pair[0].new_map = le32toh(flog_pair[0].new_map); + flog_pair[0].seq = le32toh(flog_pair[0].seq); + + flog_pair[1].lba = le32toh(flog_pair[1].lba); + flog_pair[1].old_map = le32toh(flog_pair[1].old_map); + flog_pair[1].new_map = le32toh(flog_pair[1].new_map); + flog_pair[1].seq = le32toh(flog_pair[1].seq); + + LOG(6, "flog_pair[0] flog_off %zu old_map %u new_map %u seq %u", + flog_off, flog_pair[0].old_map, + flog_pair[0].new_map, flog_pair[0].seq); + LOG(6, "flog_pair[1] old_map %u new_map %u seq %u", + flog_pair[1].old_map, flog_pair[1].new_map, + flog_pair[1].seq); + + /* + * Interesting cases: + * - no valid seq numbers: layout consistency error + * - one valid seq number: that's the current entry + * - two valid seq numbers: higher number is current entry + * - identical seq numbers: layout consistency error + */ + struct btt_flog *currentp; + if (flog_pair[0].seq == flog_pair[1].seq) { + LOG(1, "flog layout error: bad seq numbers %d %d", + flog_pair[0].seq, flog_pair[1].seq); + arenap->flags |= BTTINFO_FLAG_ERROR; + return 0; + } else if (flog_pair[0].seq == 0) { + /* singleton valid flog at flog_pair[1] */ + currentp = &flog_pair[1]; + flog_runtimep->next = 0; + } else if (flog_pair[1].seq == 0) { + /* singleton valid flog at flog_pair[0] */ + currentp = &flog_pair[0]; + flog_runtimep->next = 1; + } else if (NSEQ(flog_pair[0].seq) == flog_pair[1].seq) { + /* flog_pair[1] has the later sequence number */ + currentp = &flog_pair[1]; + flog_runtimep->next = 0; + } else { + /* flog_pair[0] has the later sequence number */ + currentp = &flog_pair[0]; + flog_runtimep->next = 1; + } + + LOG(6, "run-time flog next is %d", flog_runtimep->next); + + /* copy current flog into run-time flog state */ + flog_runtimep->flog = *currentp; + + LOG(9, "read flog[%d]: lba %u old %u%s%s new %u%s%s", flognum, + currentp->lba, + currentp->old_map & BTT_MAP_ENTRY_LBA_MASK, + (currentp->old_map & BTT_MAP_ENTRY_ERROR) ? " ERROR" : "", + (currentp->old_map & BTT_MAP_ENTRY_ZERO) ? " ZERO" : "", + currentp->new_map & BTT_MAP_ENTRY_LBA_MASK, + (currentp->new_map & BTT_MAP_ENTRY_ERROR) ? " ERROR" : "", + (currentp->new_map & BTT_MAP_ENTRY_ZERO) ? " ZERO" : ""); + + /* + * Decide if the current flog info represents a completed + * operation or an incomplete operation. If completed, the + * old_map field will contain the free block to be used for + * the next write. But if the operation didn't complete (indicated + * by the map entry not being updated), then new_map is the free + * block since it never became active according to the map. + * + * A special case, used by flog entries when first created, is + * when old_map == new_map. This counts as a complete entry + * and doesn't require reading the map to see if recovery is + * required. + */ + if (currentp->old_map == currentp->new_map) { + LOG(9, "flog[%d] entry complete (initial state)", flognum); + return 0; + } + + /* convert pre-map LBA into an offset into the map */ + off_t map_entry_off = arenap->mapoff + + BTT_MAP_ENTRY_SIZE * currentp->lba; + + /* read current map entry */ + uint32_t entry; + if ((*bttp->ns_cbp->nsread)(bttp->ns, lane, &entry, + sizeof (entry), map_entry_off) < 0) + return -1; + + entry = le32toh(entry); + if (currentp->new_map != entry && currentp->old_map == entry) { + /* last update didn't complete */ + LOG(9, "recover flog[%d]: map[%u]: %u", + flognum, currentp->lba, currentp->new_map); + + /* + * Recovery step is to complete the transaction by + * updating the map entry. + */ + entry = htole32(currentp->new_map); + if ((*bttp->ns_cbp->nswrite)(bttp->ns, lane, &entry, + sizeof (uint32_t), map_entry_off) < 0) + return -1; + } + + return 0; +} + +/* + * flog_update -- (internal) write out an updated flog entry + * + * The flog entries are not checksummed. Instead, increasing sequence + * numbers are used to atomically switch the active flog entry between + * the first and second struct btt_flog in each slot. In order for this + * to work, the sequence number must be updated only after all the other + * fields in the flog are updated. So the writes to the flog are broken + * into two writes, one for the first three fields (lba, old_map, new_map) + * and, only after those fields are known to be written durably, the + * second write for the seq field is done. + * + * Returns 0 on success, otherwise -1/errno. + */ +static int +flog_update(struct btt *bttp, int lane, struct arena *arenap, + uint32_t lba, uint32_t old_map, uint32_t new_map) +{ + LOG(3, "bttp %p lane %d arenap %p lba %u old_map %u new_map %u", + bttp, lane, arenap, lba, old_map, new_map); + + /* construct new flog entry in little-endian byte order */ + struct btt_flog new_flog; + new_flog.lba = htole32(lba); + new_flog.old_map = htole32(old_map); + new_flog.new_map = htole32(new_map); + new_flog.seq = htole32(NSEQ(arenap->flogs[lane].flog.seq)); + + off_t new_flog_off = + arenap->flogs[lane].entries[arenap->flogs[lane].next]; + + /* write out first three fields first */ + /* XXX writing two fields and two fields will be faster */ + if ((*bttp->ns_cbp->nswrite)(bttp->ns, lane, &new_flog, + sizeof (uint32_t) * 3, new_flog_off) < 0) + return -1; + new_flog_off += sizeof (uint32_t) * 3; + + /* write out seq field to make it active */ + if ((*bttp->ns_cbp->nswrite)(bttp->ns, lane, &new_flog.seq, + sizeof (uint32_t), new_flog_off) < 0) + return -1; + + /* flog entry written successfully, update run-time state */ + arenap->flogs[lane].next = 1 - arenap->flogs[lane].next; + arenap->flogs[lane].flog.lba = lba; + arenap->flogs[lane].flog.old_map = old_map; + arenap->flogs[lane].flog.new_map = new_map; + arenap->flogs[lane].flog.seq = NSEQ(arenap->flogs[lane].flog.seq); + + LOG(9, "update flog[%d]: lba %u old %u%s%s new %u%s%s", lane, lba, + old_map & BTT_MAP_ENTRY_LBA_MASK, + (old_map & BTT_MAP_ENTRY_ERROR) ? " ERROR" : "", + (old_map & BTT_MAP_ENTRY_ZERO) ? " ZERO" : "", + new_map & BTT_MAP_ENTRY_LBA_MASK, + (new_map & BTT_MAP_ENTRY_ERROR) ? " ERROR" : "", + (new_map & BTT_MAP_ENTRY_ZERO) ? " ZERO" : ""); + + return 0; +} + +/* + * read_flogs -- (internal) load up all the flog entries for an arena + * + * Zero is returned on success, otherwise -1/errno. + */ +static int +read_flogs(struct btt *bttp, int lane, struct arena *arenap) +{ + if ((arenap->flogs = Malloc(bttp->nfree * + sizeof (struct flog_runtime))) == NULL) { + LOG(1, "!Malloc for %d flog entries", bttp->nfree); + return -1; + } + memset(arenap->flogs, '\0', bttp->nfree * sizeof (struct flog_runtime)); + + /* + * Load up the flog state. read_flog_pair() will determine if + * any recovery steps are required take them on the in-memory + * data structures it creates. + */ + off_t flog_off = arenap->flogoff; + struct flog_runtime *flog_runtimep = arenap->flogs; + for (int i = 0; i < bttp->nfree; i++) { + if (read_flog_pair(bttp, lane, arenap, flog_off, + flog_runtimep, i) < 0) + return -1; + + /* prepare for next time around the loop */ + flog_off += 2 * sizeof (struct btt_flog); + flog_runtimep++; + } + + return 0; +} + +/* + * build_rtt -- (internal) construct a read tracking table for an arena + * + * Zero is returned on success, otherwise -1/errno. + * + * The rtt is big enough to hold an entry for each free block (nfree) + * since nlane can't be bigger than nfree. nlane may end up smaller, + * in which case some of the high rtt entries will be unused. + */ +static int +build_rtt(struct btt *bttp, struct arena *arenap) +{ + if ((arenap->rtt = Malloc(bttp->nfree * sizeof (uint32_t))) + == NULL) { + LOG(1, "!Malloc for %d rtt entries", bttp->nfree); + return -1; + } + for (int lane = 0; lane < bttp->nfree; lane++) + arenap->rtt[lane] = BTT_MAP_ENTRY_ERROR; + __sync_synchronize(); + + return 0; +} + +/* + * build_map_locks -- (internal) construct map locks + * + * Zero is returned on success, otherwise -1/errno. + */ +static int +build_map_locks(struct btt *bttp, struct arena *arenap) +{ + if ((arenap->map_locks = + Malloc(bttp->nfree * sizeof (*arenap->map_locks))) + == NULL) { + LOG(1, "!Malloc for %d map_lock entries", bttp->nfree); + return -1; + } + for (int lane = 0; lane < bttp->nfree; lane++) + pthread_spin_init(&arenap->map_locks[lane], + PTHREAD_PROCESS_PRIVATE); + + return 0; +} + +/* + * read_arena -- (internal) load up an arena and build run-time state + * + * Zero is returned on success, otherwise -1/errno. + */ +static int +read_arena(struct btt *bttp, int lane, off_t arena_off, struct arena *arenap) +{ + LOG(3, "bttp %p lane %d arena_off %zu arenap %p", + bttp, lane, arena_off, arenap); + + struct btt_info info; + if ((*bttp->ns_cbp->nsread)(bttp->ns, lane, &info, sizeof (info), + arena_off) < 0) + return -1; + + arenap->flags = le32toh(info.flags); + arenap->external_nlba = le64toh(info.external_nlba); + arenap->internal_lbasize = le32toh(info.internal_lbasize); + arenap->internal_nlba = le32toh(info.internal_nlba); + + arenap->startoff = arena_off; + arenap->dataoff = arena_off + le64toh(info.dataoff); + arenap->mapoff = arena_off + le64toh(info.mapoff); + arenap->flogoff = arena_off + le64toh(info.flogoff); + arenap->nextoff = arena_off + le64toh(info.nextoff); + + if (read_flogs(bttp, lane, arenap) < 0) + return -1; + + if (build_rtt(bttp, arenap) < 0) + return -1; + + if (build_map_locks(bttp, arenap) < 0) + return -1; + + return 0; +} + +/* + * read_arenas -- (internal) load up all arenas and build run-time state + * + * On entry, layout must be known to be valid, and the number of arenas + * must be known. Zero is returned on success, otherwise -1/errno. + */ +static int +read_arenas(struct btt *bttp, int lane, int narena) +{ + LOG(3, "bttp %p lane %d narena %d", bttp, lane, narena); + + if ((bttp->arenas = Malloc(narena * sizeof (*bttp->arenas))) == NULL) { + LOG(1, "!Malloc for %d arenas", narena); + goto err; + } + memset(bttp->arenas, '\0', narena * sizeof (*bttp->arenas)); + + off_t arena_off = 0; + struct arena *arenap = bttp->arenas; + for (int i = 0; i < narena; i++) { + + if (read_arena(bttp, lane, arena_off, arenap) < 0) + goto err; + + /* prepare for next time around the loop */ + arena_off = arenap->nextoff; + arenap++; + } + + bttp->laidout = 1; + + return 0; + +err: + LOG(4, "error clean up"); + int oerrno = errno; + if (bttp->arenas) { + for (int i = 0; i < bttp->narena; i++) { + if (bttp->arenas[i].flogs) + Free(bttp->arenas[i].flogs); + if (bttp->arenas[i].rtt) + Free((void *)bttp->arenas[i].rtt); + if (bttp->arenas[i].map_locks) + Free((void *)bttp->arenas[i].map_locks); + } + Free(bttp->arenas); + bttp->arenas = NULL; + } + errno = oerrno; + return -1; +} + +/* + * write_layout -- (internal) write out the initial btt metadata layout + * + * Called with write == 1 only once in the life time of a btt namespace, when + * the first write happens. The caller of this routine is responsible for + * locking out multiple threads. This routine doesn't read anything -- by the + * time it is called, it is known there's no layout in the namespace and a new + * layout should be written. + * + * Calling with write == 0 tells this routine to do the calculations for + * bttp->narena and bttp->nlba, but don't write out any metadata. + * + * If successful, sets bttp->layout to 1 and returns 0. Otherwise -1 + * is returned and errno is set, and bttp->layout remains 0 so that + * later attempts to write will try again to create the layout. + */ +static int +write_layout(struct btt *bttp, int lane, int write) +{ + LOG(3, "bttp %p lane %d write %d", bttp, lane, write); + + ASSERT(bttp->rawsize >= BTT_MIN_SIZE); + ASSERT(bttp->nfree); + + /* + * The number of arenas is the number of full arena of + * size BTT_MAX_ARENA that fit into rawsize and then, if + * the remainder is at least BTT_MIN_SIZE in size, then + * that adds one more arena. + */ + bttp->narena = bttp->rawsize / BTT_MAX_ARENA; + if (bttp->rawsize % BTT_MAX_ARENA >= BTT_MIN_SIZE) + bttp->narena++; + LOG(4, "narena %u", bttp->narena); + + int flog_size = bttp->nfree * 2 * sizeof (struct btt_flog); + flog_size = roundup(flog_size, BTT_ALIGNMENT); + + uint32_t internal_lbasize = bttp->lbasize; + if (internal_lbasize < BTT_MIN_LBA) + internal_lbasize = BTT_MIN_LBA; + internal_lbasize = + roundup(internal_lbasize, BTT_INTERNAL_LBA_ALIGNMENT); + LOG(4, "adjusted internal_lbasize %u", internal_lbasize); + + uint64_t total_nlba = 0; + uint64_t rawsize = bttp->rawsize; + int arena_num = 0; + off_t arena_off = 0; + + /* + * for each arena... + */ + while (rawsize >= BTT_MIN_SIZE) { + LOG(4, "layout arena %u", arena_num); + + uint64_t arena_rawsize = rawsize; + if (arena_rawsize > BTT_MAX_ARENA) { + arena_rawsize = BTT_MAX_ARENA; + } + rawsize -= arena_rawsize; + arena_num++; + + uint64_t arena_datasize = arena_rawsize; + arena_datasize -= 2 * sizeof (struct btt_info); + arena_datasize -= flog_size; + + /* allow for map alignment padding */ + uint64_t internal_nlba = (arena_datasize - BTT_ALIGNMENT) / + (internal_lbasize + BTT_MAP_ENTRY_SIZE); + uint64_t external_nlba = internal_nlba - bttp->nfree; + + LOG(4, "internal_nlba %zu external_nlba %zu", + internal_nlba, external_nlba); + + total_nlba += external_nlba; + + /* + * The rest of the loop body calculates metadata structures + * and lays it out for this arena. So only continue if + * the write flag is set. + */ + if (!write) + continue; + + uint64_t mapsize = roundup(external_nlba * BTT_MAP_ENTRY_SIZE, + BTT_ALIGNMENT); + arena_datasize -= mapsize; + + ASSERT(arena_datasize / internal_lbasize >= internal_nlba); + + /* + * Calculate offsets for the BTT info block. These are + * all relative to the beginning of the arena. + */ + uint64_t nextoff; + if (rawsize) + nextoff = arena_rawsize; + else + nextoff = 0; + uint64_t infooff = arena_rawsize - sizeof (struct btt_info); + uint64_t flogoff = infooff - flog_size; + uint64_t mapoff = flogoff - mapsize; + uint64_t dataoff = sizeof (struct btt_info); + + LOG(4, "nextoff 0x%016lx", nextoff); + LOG(4, "dataoff 0x%016lx", dataoff); + LOG(4, "mapoff 0x%016lx", mapoff); + LOG(4, "flogoff 0x%016lx", flogoff); + LOG(4, "infooff 0x%016lx", infooff); + + ASSERTeq(arena_datasize, mapoff - dataoff); + + /* write out the initial map, identity style */ + off_t map_entry_off = arena_off + mapoff; + uint32_t *mapp = NULL; + int mlen = 0; + int next_index = 0; + int remaining = 0; + for (int i = 0; i < external_nlba; i++) { + if (remaining == 0) { + /* flush previous mapped area */ + if (mapp != NULL) + (*bttp->ns_cbp->nssync)(bttp->ns, + lane, mapp, mlen); + /* request a mapping of remaining map area */ + mlen = (*bttp->ns_cbp->nsmap)(bttp->ns, + lane, (void **)&mapp, + (external_nlba - i) * sizeof (uint32_t), + map_entry_off); + + if (mlen < 0) + return -1; + + remaining = mlen; + next_index = 0; + } + mapp[next_index++] = htole32(i | BTT_MAP_ENTRY_ZERO); + remaining -= sizeof (uint32_t); + } + /* flush previous mapped area */ + if (mapp != NULL) + (*bttp->ns_cbp->nssync)(bttp->ns, lane, mapp, mlen); + + /* write out the initial flog */ + off_t flog_entry_off = arena_off + flogoff; + uint32_t next_free_lba = external_nlba; + for (int i = 0; i < bttp->nfree; i++) { + struct btt_flog flog; + flog.lba = 0; + flog.old_map = flog.new_map = + htole32(next_free_lba | BTT_MAP_ENTRY_ZERO); + flog.seq = htole32(1); + + /* + * Write both btt_flog structs in the pair, writing + * the second one as all zeros. + */ + LOG(6, "flog[%d] entry off %zu initial %u + zero = %u", + i, flog_entry_off, next_free_lba, + next_free_lba | BTT_MAP_ENTRY_ZERO); + if ((*bttp->ns_cbp->nswrite)(bttp->ns, lane, &flog, + sizeof (flog), flog_entry_off) < 0) + return -1; + flog_entry_off += sizeof (flog); + + LOG(6, "flog[%d] entry off %zu zeros", + i, flog_entry_off); + if ((*bttp->ns_cbp->nswrite)(bttp->ns, lane, &Zflog, + sizeof (Zflog), flog_entry_off) < 0) + return -1; + flog_entry_off += sizeof (flog); + + next_free_lba++; + } + + /* + * Construct the BTT info block and write it out + * at both the beginning and end of the arena. + */ + struct btt_info info; + memset(&info, '\0', sizeof (info)); + memcpy(info.sig, Sig, BTTINFO_SIG_LEN); + memcpy(info.parent_uuid, bttp->parent_uuid, BTTINFO_UUID_LEN); + info.major = htole16(BTTINFO_MAJOR_VERSION); + info.minor = htole16(BTTINFO_MINOR_VERSION); + info.external_lbasize = htole32(bttp->lbasize); + info.external_nlba = htole32(external_nlba); + info.internal_lbasize = htole32(internal_lbasize); + info.internal_nlba = htole32(internal_nlba); + info.nfree = htole32(bttp->nfree); + info.infosize = htole32(sizeof (info)); + info.nextoff = htole64(nextoff); + info.dataoff = htole64(dataoff); + info.mapoff = htole64(mapoff); + info.flogoff = htole64(flogoff); + info.infooff = htole64(infooff); + + util_checksum(&info, sizeof (info), &info.checksum, 1); + + if ((*bttp->ns_cbp->nswrite)(bttp->ns, lane, &info, + sizeof (info), arena_off) < 0) + return -1; + if ((*bttp->ns_cbp->nswrite)(bttp->ns, lane, &info, + sizeof (info), arena_off + nextoff) < 0) + return -1; + + arena_off += nextoff; + } + + ASSERTeq(bttp->narena, arena_num); + + bttp->nlba = total_nlba; + + if (write) { + /* + * The layout is written now, so load up the arenas. + */ + return read_arenas(bttp, lane, bttp->narena); + } + + return 0; +} + +/* + * read_layout -- (internal) load up layout info from btt namespace + * + * Called once when the btt namespace is opened for use. + * Sets bttp->layout to 0 if no valid layout is found, 1 otherwise. + * + * Any recovery actions required (as indicated by the flog state) are + * performed by this routine. + * + * Any quick checks for layout consistency are performed by this routine + * (quick enough to be done each time a BTT area is opened for use, not + * like the slow consistency checks done by btt_check()). + * + * Returns 0 if no errors are encountered accessing the namespace (in this + * context, detecting there's no layout is not an error if the nsread function + * didn't have any problems doing the reads). Otherwise, -1 is returned + * and errno is set (by nsread). + */ +static int +read_layout(struct btt *bttp, int lane) +{ + LOG(3, "bttp %p", bttp); + + ASSERT(bttp->rawsize >= BTT_MIN_SIZE); + + int narena = 0; + uint32_t smallest_nfree = UINT32_MAX; + uint64_t rawsize = bttp->rawsize; + uint64_t total_nlba = 0; + off_t arena_off = 0; + + bttp->nfree = BTT_DEFAULT_NFREE; + + /* + * For each arena, see if there's a valid info block + */ + while (rawsize >= BTT_MIN_SIZE) { + narena++; + + struct btt_info info; + if ((*bttp->ns_cbp->nsread)(bttp->ns, lane, &info, + sizeof (info), arena_off) < 0) + return -1; + + if (!read_info(&info)) { + /* + * Failed to find complete BTT metadata. Just + * calculate the narena and nlba values that will + * result when write_layout() gets called. This + * allows checks against nlba to work correctly + * even before the layout is written. + */ + return write_layout(bttp, lane, 0); + } + + if (info.nfree < smallest_nfree) + smallest_nfree = info.nfree; + + total_nlba += info.external_nlba; + arena_off += info.nextoff; + if (info.nextoff == 0) + break; + rawsize -= info.nextoff; + } + + ASSERT(narena); + + bttp->narena = narena; + bttp->nlba = total_nlba; + + /* + * All arenas were valid. nfree should be the smallest value found. + */ + if (smallest_nfree < bttp->nfree) + bttp->nfree = smallest_nfree; + + /* + * Load up arenas. + */ + return read_arenas(bttp, lane, narena); +} + +/* + * zero_block -- (internal) satisfy a read with a block of zeros + * + * Returns 0 on success, otherwise -1/errno. + */ +static int +zero_block(struct btt *bttp, void *buf) +{ + LOG(3, "bttp %p", bttp); + + memset(buf, '\0', bttp->lbasize); + return 0; +} + +/* + * lba_to_arena_lba -- (internal) calculate the arena & pre-map LBA + * + * This routine takes the external LBA and matches it to the + * appropriate arena, adjusting the lba for use within that arena. + * + * If successful, zero is returned, *arenapp is a pointer to the appropriate + * arena struct in the run-time state, and *premap_lbap is the LBA adjusted + * to an arena-internal LBA (also known as the pre-map LBA). Otherwise + * -1/errno. + */ +static int +lba_to_arena_lba(struct btt *bttp, uint64_t lba, + struct arena **arenapp, uint32_t *premap_lbap) +{ + LOG(3, "bttp %p lba %zu", bttp, lba); + + ASSERT(bttp->laidout); + + int arena; + for (arena = 0; arena < bttp->narena; arena++) + if (lba < bttp->arenas[arena].external_nlba) + break; + else + lba -= bttp->arenas[arena].external_nlba; + + ASSERT(arena < bttp->narena); + + *arenapp = &bttp->arenas[arena]; + *premap_lbap = lba; + + LOG(3, "arenap %p pre-map LBA %u", *arenapp, *premap_lbap); + return 0; +} + +/* + * btt_init -- prepare a btt namespace for use, returning an opaque handle + * + * Returns handle on success, otherwise NULL/errno. + * + * XXX handle case where lbasize doesn't match lbasize found in valid arenas. + * XXX check rawsize against size from valid arenas. + * XXX what if write_layout produces something read_layout says is invalid? + * XXX what if arenas have different nfree? + */ +struct btt * +btt_init(uint64_t rawsize, uint32_t lbasize, uint8_t parent_uuid[], + int maxlane, void *ns, const struct ns_callback *ns_cbp) +{ + LOG(3, "rawsize %zu lbasize %u", rawsize, lbasize); + + if (rawsize < BTT_MIN_SIZE) { + LOG(1, "rawsize smaller than BTT_MIN_SIZE %zu", BTT_MIN_SIZE); + errno = EINVAL; + return NULL; + } + + struct btt *bttp = Malloc(sizeof (*bttp)); + + if (bttp == NULL) { + LOG(1, "!Malloc %zu bytes", sizeof (*bttp)); + return NULL; + } + + memset(bttp, '\0', sizeof (*bttp)); + + pthread_mutex_init(&bttp->layout_write_mutex, NULL); + memcpy(bttp->parent_uuid, parent_uuid, BTTINFO_UUID_LEN); + bttp->rawsize = rawsize; + bttp->lbasize = lbasize; + bttp->ns = ns; + bttp->ns_cbp = ns_cbp; + + /* + * Load up layout, if it exists. + * + * Whether read_layout() finds a valid layout or not, it finishes + * updating these layout-related fields: + * bttp->nfree + * bttp->nlba + * bttp->narena + * since these fields are used even before a valid layout it written. + */ + if (read_layout(bttp, 0) < 0) { + btt_fini(bttp); /* free up any allocations */ + return NULL; + } + + bttp->nlane = bttp->nfree; + + /* maxlane, if provided, is an upper bound on nlane */ + if (maxlane && bttp->nlane > maxlane) + bttp->nlane = maxlane; + + LOG(3, "success, bttp %p nlane %d", bttp, bttp->nlane); + return bttp; +} + +/* + * btt_nlane -- return the number of "lanes" for this btt namespace + * + * The number of lanes is the number of threads allowed in this module + * concurrently for a given btt. Each thread executing this code must + * have a unique "lane" number assigned to it between 0 and btt_nlane() - 1. + */ +int +btt_nlane(struct btt *bttp) +{ + LOG(3, "bttp %p", bttp); + + return bttp->nlane; +} + +/* + * btt_nlba -- return the number of usable blocks in a btt namespace + * + * Valid LBAs to pass to btt_read() and btt_write() are 0 through + * btt_nlba() - 1. + */ +size_t +btt_nlba(struct btt *bttp) +{ + LOG(3, "bttp %p", bttp); + + return bttp->nlba; +} + +/* + * btt_read -- read a block from a btt namespace + * + * Returns 0 on success, otherwise -1/errno. + */ +int +btt_read(struct btt *bttp, int lane, uint64_t lba, void *buf) +{ + LOG(3, "bttp %p lane %u lba %zu", bttp, lane, lba); + + if (invalid_lba(bttp, lba)) + return -1; + + /* if there's no layout written yet, all reads come back as zeros */ + if (!bttp->laidout) + return zero_block(bttp, buf); + + /* find which arena LBA lives in, and the offset to the map entry */ + struct arena *arenap; + uint32_t premap_lba; + off_t map_entry_off; + if (lba_to_arena_lba(bttp, lba, &arenap, &premap_lba) < 0) + return -1; + + /* convert pre-map LBA into an offset into the map */ + map_entry_off = arenap->mapoff + BTT_MAP_ENTRY_SIZE * premap_lba; + + /* + * Read the current map entry to get the post-map LBA for the data + * block read. + */ + uint32_t entry; + + if ((*bttp->ns_cbp->nsread)(bttp->ns, lane, &entry, + sizeof (entry), map_entry_off) < 0) + return -1; + + entry = le32toh(entry); + + /* + * Retries come back to the top of this loop (for a rare case where + * the map is changed by another thread doing writes to the same LBA). + */ + while (1) { + if (entry & BTT_MAP_ENTRY_ERROR) { + LOG(1, "EIO due to map entry error flag"); + errno = EIO; + return -1; + } + + if (entry & BTT_MAP_ENTRY_ZERO) + return zero_block(bttp, buf); + + /* + * Record the post-map LBA in the read tracking table during + * the read. The write will check entries in the read tracking + * table before allocating a block for a write, waiting for + * outstanding reads on that block to complete. + * + * No need to mask off ERROR and ZERO bits since the above + * checks make sure they are clear at this point. + */ + arenap->rtt[lane] = entry; + __sync_synchronize(); + + /* + * In case this thread was preempted between reading entry and + * storing it in the rtt, check to see if the map changed. If + * it changed, the block about to be read is at least free now + * (in the flog, but that's okay since the data will still be + * undisturbed) and potentially allocated and being used for + * another write (data disturbed, so not okay to continue). + */ + uint32_t latest_entry; + if ((*bttp->ns_cbp->nsread)(bttp->ns, lane, &latest_entry, + sizeof (latest_entry), map_entry_off) < 0) { + arenap->rtt[lane] = BTT_MAP_ENTRY_ERROR; + return -1; + } + + latest_entry = le32toh(latest_entry); + + if (entry == latest_entry) + break; /* map stayed the same */ + else + entry = latest_entry; /* try again */ + } + + /* + * It is safe to read the block now, since the rtt protects the + * block from getting re-allocated to something else by a write. + */ + off_t data_block_off = + arenap->dataoff + entry * arenap->internal_lbasize; + int readret = (*bttp->ns_cbp->nsread)(bttp->ns, lane, buf, + bttp->lbasize, data_block_off); + + /* done with read, so clear out rtt entry */ + arenap->rtt[lane] = BTT_MAP_ENTRY_ERROR; + + return readret; +} + +/* + * map_lock -- (internal) grab the map_lock and read a map entry + */ +static int +map_lock(struct btt *bttp, int lane, struct arena *arenap, + uint32_t *entryp, uint32_t premap_lba) +{ + LOG(3, "bttp %p lane %u arenap %p premap_lba %u", + bttp, lane, arenap, premap_lba); + + off_t map_entry_off = arenap->mapoff + BTT_MAP_ENTRY_SIZE * premap_lba; + int map_lock_num = premap_lba % bttp->nfree; + + pthread_spin_lock(&arenap->map_locks[map_lock_num]); + + /* read the old map entry */ + if ((*bttp->ns_cbp->nsread)(bttp->ns, lane, entryp, + sizeof (uint32_t), map_entry_off) < 0) { + pthread_spin_unlock(&arenap->map_locks[map_lock_num]); + return -1; + } + + LOG(9, "locked map[%d]: %u%s%s", premap_lba, + *entryp & BTT_MAP_ENTRY_LBA_MASK, + (*entryp & BTT_MAP_ENTRY_ERROR) ? " ERROR" : "", + (*entryp & BTT_MAP_ENTRY_ZERO) ? " ZERO" : ""); + + return 0; +} + +/* + * map_abort -- (internal) drop the map_lock without updating the entry + */ +void +map_abort(struct btt *bttp, int lane, struct arena *arenap, uint32_t premap_lba) +{ + LOG(3, "bttp %p lane %u arenap %p premap_lba %u", + bttp, lane, arenap, premap_lba); + + int map_lock_num = premap_lba % bttp->nfree; + pthread_spin_unlock(&arenap->map_locks[map_lock_num]); +} + +/* + * map_unlock -- (internal) update the map and drop the map_lock + */ +static int +map_unlock(struct btt *bttp, int lane, struct arena *arenap, + uint32_t entry, uint32_t premap_lba) +{ + LOG(3, "bttp %p lane %u arenap %p entry %u premap_lba %u", + bttp, lane, arenap, entry, premap_lba); + + off_t map_entry_off = arenap->mapoff + BTT_MAP_ENTRY_SIZE * premap_lba; + int map_lock_num = premap_lba % bttp->nfree; + + /* write the new map entry */ + int err = (*bttp->ns_cbp->nswrite)(bttp->ns, lane, &entry, + sizeof (uint32_t), map_entry_off); + + pthread_spin_unlock(&arenap->map_locks[map_lock_num]); + + LOG(9, "unlocked map[%d]: %u%s%s", premap_lba, + entry & BTT_MAP_ENTRY_LBA_MASK, + (entry & BTT_MAP_ENTRY_ERROR) ? " ERROR" : "", + (entry & BTT_MAP_ENTRY_ZERO) ? " ZERO" : ""); + + return err; +} + +/* + * btt_write -- write a block to a btt namespace + * + * Returns 0 on success, otherwise -1/errno. + */ +int +btt_write(struct btt *bttp, int lane, uint64_t lba, const void *buf) +{ + LOG(3, "bttp %p lane %u lba %zu", bttp, lane, lba); + + if (invalid_lba(bttp, lba)) + return -1; + + /* first write through here will initialize the metadata layout */ + if (!bttp->laidout) { + int err = 0; + + pthread_mutex_lock(&bttp->layout_write_mutex); + if (!bttp->laidout) + err = write_layout(bttp, lane, 1); + pthread_mutex_unlock(&bttp->layout_write_mutex); + + if (err < 0) + return err; + } + + /* find which arena LBA lives in, and the offset to the map entry */ + struct arena *arenap; + uint32_t premap_lba; + if (lba_to_arena_lba(bttp, lba, &arenap, &premap_lba) < 0) + return -1; + + /* if the arena is in an error state, writing is not allowed */ + if (arenap->flags & BTTINFO_FLAG_ERROR_MASK) { + LOG(1, "EIO due to btt_info error flags 0x%x", + arenap->flags & BTTINFO_FLAG_ERROR_MASK); + errno = EIO; + return -1; + } + + /* + * This routine was passed a unique "lane" which is an index + * into the flog. That means the free block held by flog[lane] + * is assigned to this thread and to no other threads (no additional + * locking required). So start by performing the write to the + * free block. It is only safe to write to a free block if it + * doesn't appear in the read tracking table, so scan that first + * and if found, wait for the thread reading from it to finish. + */ + uint32_t free_entry = + arenap->flogs[lane].flog.old_map & BTT_MAP_ENTRY_LBA_MASK; + + LOG(3, "free_entry %u (before mask %u)", free_entry, + arenap->flogs[lane].flog.old_map); + + /* wait for other threads to finish any reads on free block */ + for (int i = 0; i < bttp->nlane; i++) + while (arenap->rtt[i] == free_entry) + ; + + /* it is now safe to perform write to the free block */ + off_t data_block_off = + arenap->dataoff + free_entry * arenap->internal_lbasize; + if ((*bttp->ns_cbp->nswrite)(bttp->ns, lane, buf, + bttp->lbasize, data_block_off) < 0) + return -1; + + /* + * Make the new block active atomically by updating the on-media flog + * and then updating the map. + */ + uint32_t old_entry; + if (map_lock(bttp, lane, arenap, &old_entry, premap_lba) < 0) + return -1; + + old_entry = le32toh(old_entry); + + /* update the flog */ + if (flog_update(bttp, lane, arenap, premap_lba, + old_entry, free_entry) < 0) { + map_abort(bttp, lane, arenap, premap_lba); + return -1; + } + + if (map_unlock(bttp, lane, arenap, htole32(free_entry), + premap_lba) < 0) { + /* XXX retry? revert the flog? */ + return -1; + } + + return 0; +} + +/* + * map_entry_setf -- (internal) set a given flag on a map entry + * + * Returns 0 on success, otherwise -1/errno. + */ +static int +map_entry_setf(struct btt *bttp, int lane, uint64_t lba, uint32_t setf) +{ + LOG(3, "bttp %p lane %u lba %zu setf 0x%x", bttp, lane, lba, setf); + + if (invalid_lba(bttp, lba)) + return -1; + + if (!bttp->laidout) { + /* + * No layout is written yet. If the flag being set + * is the zero flag, it is superfluous since all blocks + * read as zero at this point. + */ + if (setf == BTT_MAP_ENTRY_ZERO) + return 0; + + /* + * Treat this like the first write and write out + * the metadata layout at this point. + */ + int err = 0; + pthread_mutex_lock(&bttp->layout_write_mutex); + if (!bttp->laidout) + err = write_layout(bttp, lane, 1); + pthread_mutex_unlock(&bttp->layout_write_mutex); + + if (err < 0) + return err; + } + + /* find which arena LBA lives in, and the offset to the map entry */ + struct arena *arenap; + uint32_t premap_lba; + if (lba_to_arena_lba(bttp, lba, &arenap, &premap_lba) < 0) + return -1; + + /* if the arena is in an error state, writing is not allowed */ + if (arenap->flags & BTTINFO_FLAG_ERROR_MASK) { + LOG(1, "EIO due to btt_info error flags 0x%x", + arenap->flags & BTTINFO_FLAG_ERROR_MASK); + errno = EIO; + return -1; + } + + /* + * Set the flags in the map entry. To do this, read the + * current map entry, set the flags, and write out the update. + */ + uint32_t old_entry; + uint32_t new_entry; + + if (map_lock(bttp, lane, arenap, &old_entry, premap_lba) < 0) + return -1; + + old_entry = le32toh(old_entry); + + if (setf == BTT_MAP_ENTRY_ZERO && (old_entry & BTT_MAP_ENTRY_ZERO)) { + map_abort(bttp, lane, arenap, premap_lba); + return 0; /* block already zero, nothing to do */ + } + + /* create the new map entry */ + new_entry = old_entry | setf; + + if (map_unlock(bttp, lane, arenap, htole32(new_entry), premap_lba) < 0) + return -1; + + return 0; +} + +/* + * btt_set_zero -- mark a block as zeroed in a btt namespace + * + * Returns 0 on success, otherwise -1/errno. + */ +int +btt_set_zero(struct btt *bttp, int lane, uint64_t lba) +{ + LOG(3, "bttp %p lane %u lba %zu", bttp, lane, lba); + + return map_entry_setf(bttp, lane, lba, BTT_MAP_ENTRY_ZERO); +} + +/* + * btt_set_error -- mark a block as in an error state in a btt namespace + * + * Returns 0 on success, otherwise -1/errno. + */ +int +btt_set_error(struct btt *bttp, int lane, uint64_t lba) +{ + LOG(3, "bttp %p lane %u lba %zu", bttp, lane, lba); + + return map_entry_setf(bttp, lane, lba, BTT_MAP_ENTRY_ERROR); +} + +/* + * check_arena -- (internal) perform a consistency check on an arena + */ +static int +check_arena(struct btt *bttp, struct arena *arenap) +{ + LOG(3, "bttp %p arenap %p", bttp, arenap); + + int consistent = 1; + + off_t map_entry_off = arenap->mapoff; + int bitmapsize = howmany(arenap->internal_nlba, 8); + char *bitmap = Malloc(bitmapsize); + if (bitmap == NULL) { + LOG(1, "!Malloc for bitmap"); + return -1; + } + memset(bitmap, '\0', bitmapsize); + + /* + * Go through every post-map LBA mentioned in the map and make sure + * there are no duplicates. bitmap is used to track which LBAs have + * been seen so far. + */ + uint32_t *mapp = NULL; + int mlen; + int next_index = 0; + int remaining = 0; + for (int i = 0; i < arenap->external_nlba; i++) { + uint32_t entry; + + if (remaining == 0) { + /* request a mapping of remaining map area */ + mlen = (*bttp->ns_cbp->nsmap)(bttp->ns, + 0, (void **)&mapp, + (arenap->external_nlba - i) * sizeof (uint32_t), + map_entry_off); + + if (mlen < 0) + return -1; + + remaining = mlen; + next_index = 0; + } + entry = le32toh(mapp[next_index]); + + /* for debug, dump non-zero map entries at log level 11 */ + if ((entry & BTT_MAP_ENTRY_ZERO) == 0) + LOG(11, "map[%d]: %u%s%s", i, + entry & BTT_MAP_ENTRY_LBA_MASK, + (entry & BTT_MAP_ENTRY_ERROR) ? " ERROR" : "", + (entry & BTT_MAP_ENTRY_ZERO) ? " ZERO" : ""); + + entry &= BTT_MAP_ENTRY_LBA_MASK; + + if (isset(bitmap, entry)) { + LOG(1, "map[%d] duplicate entry: %u", i, entry); + consistent = 0; + } else + setbit(bitmap, entry); + + map_entry_off += sizeof (uint32_t); + next_index++; + remaining -= sizeof (uint32_t); + } + + /* + * Go through the free blocks in the flog, adding them to bitmap + * and checking for duplications. It is sufficient to read the + * run-time flog here, avoiding more calls to nsread. + */ + for (int i = 0; i < bttp->nfree; i++) { + uint32_t entry = arenap->flogs[i].flog.old_map; + entry &= BTT_MAP_ENTRY_LBA_MASK; + + if (isset(bitmap, entry)) { + LOG(1, "flog[%d] duplicate entry: %u", i, entry); + consistent = 0; + } else + setbit(bitmap, entry); + } + + /* + * Make sure every possible post-map LBA was accounted for + * in the two loops above. + */ + for (int i = 0; i < arenap->internal_nlba; i++) + if (isclr(bitmap, i)) { + LOG(1, "unreferenced lba: %u", i); + consistent = 0; + } + + + Free(bitmap); + + return consistent; +} + +/* + * btt_check -- perform a consistency check on a btt namespace + * + * This routine contains a fairly high-impact set of consistency checks. + * It may use a good amount of dynamic memory and CPU time performing + * the checks. Any lightweight, quick consistency checks are included + * in read_layout() so they happen every time the BTT area is opened + * for use. + * + * Returns true if consistent, zero if inconsistent, -1/error if checking + * cannot happen due to other errors. + * + * No lane number required here because only one thread is allowed -- all + * other threads must be locked out of all btt routines for this btt + * namespace while this is running. + */ +int +btt_check(struct btt *bttp) +{ + LOG(3, "bttp %p", bttp); + + int consistent = 1; + + if (!bttp->laidout) { + /* consistent by definition */ + LOG(3, "no layout yet"); + return consistent; + } + + /* XXX report issues found during read_layout (from flags) */ + + /* for each arena... */ + struct arena *arenap = bttp->arenas; + for (int i = 0; i < bttp->narena; i++) { + /* + * Perform the consistency checks for the arena. + */ + int retval = check_arena(bttp, arenap); + if (retval < 0) + return retval; + else if (retval == 0) + consistent = 0; + } + + /* XXX stub */ + return consistent; +} + +/* + * btt_fini -- delete opaque btt info, done using btt namespace + */ +void +btt_fini(struct btt *bttp) +{ + LOG(3, "bttp %p", bttp); + + if (bttp->arenas) { + for (int i = 0; i < bttp->narena; i++) { + if (bttp->arenas[i].flogs) + Free(bttp->arenas[i].flogs); + if (bttp->arenas[i].rtt) + Free((void *)bttp->arenas[i].rtt); + if (bttp->arenas[i].rtt) + Free((void *)bttp->arenas[i].map_locks); + } + Free(bttp->arenas); + } + Free(bttp); +} diff --git a/src/btt.h b/src/btt.h new file mode 100644 index 0000000000000000000000000000000000000000..89d5b2feede311893329f8bb769880b5ddf1f34c --- /dev/null +++ b/src/btt.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * btt.h -- btt module definitions + */ + +/* callback functions passed to btt_init() */ +struct ns_callback { + int (*nsread)(void *ns, int lane, + void *buf, size_t count, off_t off); + int (*nswrite)(void *ns, int lane, + const void *buf, size_t count, off_t off); + int (*nsmap)(void *ns, int lane, void **addrp, size_t len, off_t off); + void (*nssync)(void *ns, int lane, void *addr, size_t len); +}; + +struct btt *btt_init(uint64_t rawsize, uint32_t lbasize, uint8_t parent_uuid[], + int maxlane, void *ns, const struct ns_callback *ns_cbp); +int btt_nlane(struct btt *bttp); +size_t btt_nlba(struct btt *bttp); +int btt_read(struct btt *bttp, int lane, uint64_t lba, void *buf); +int btt_write(struct btt *bttp, int lane, uint64_t lba, const void *buf); +int btt_set_zero(struct btt *bttp, int lane, uint64_t lba); +int btt_set_error(struct btt *bttp, int lane, uint64_t lba); +int btt_check(struct btt *bttp); +void btt_fini(struct btt *bttp); diff --git a/src/btt_layout.h b/src/btt_layout.h new file mode 100644 index 0000000000000000000000000000000000000000..f7cb956789c7a98de6c7cb0563e967679cfe8dc7 --- /dev/null +++ b/src/btt_layout.h @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * btt_layout.h -- block translation table on-media layout definitions + */ + +/* + * Layout of BTT info block. All integers are stored little-endian. + */ + +#define BTT_ALIGNMENT 4096 /* alignment of all BTT structures */ +#define BTTINFO_SIG_LEN 16 +#define BTTINFO_UUID_LEN 16 + +struct btt_info { + char sig[BTTINFO_SIG_LEN]; /* must be "BTT_ARENA_INFO\0\0" */ + uint8_t parent_uuid[BTTINFO_UUID_LEN]; /* UUID of container */ + uint32_t flags; /* see flag bits below */ + uint16_t major; /* major version */ + uint16_t minor; /* minor version */ + uint32_t external_lbasize; /* advertised LBA size (bytes) */ + uint32_t external_nlba; /* advertised LBAs in this arena */ + uint32_t internal_lbasize; /* size of data area blocks (bytes) */ + uint32_t internal_nlba; /* number of blocks in data area */ + uint32_t nfree; /* number of free blocks */ + uint32_t infosize; /* size of this info block */ + + /* + * The following offsets are relative to the beginning of + * the btt_info block. + */ + uint64_t nextoff; /* offset to next arena (or zero) */ + uint64_t dataoff; /* offset to arena data area */ + uint64_t mapoff; /* offset to area map */ + uint64_t flogoff; /* offset to area flog */ + uint64_t infooff; /* offset to backup info block */ + + char unused[3984]; /* must be zero */ + + uint64_t checksum; /* Fletcher64 of all fields */ +}; + +/* + * Definitions for flags mask for btt_info structure above. + */ +#define BTTINFO_FLAG_ERROR 0x00000001 /* error state (read-only) */ +#define BTTINFO_FLAG_ERROR_MASK 0x00000001 /* all error bits */ + +/* + * Current on-media format versions. + */ +#define BTTINFO_MAJOR_VERSION 1 +#define BTTINFO_MINOR_VERSION 1 + +/* + * Layout of a BTT "flog" entry. All integers are stored little-endian. + * + * The "nfree" field in the BTT info block determines how many of these + * flog entries there are, and each entry consists of two of the following + * structs (entry updates alternate between the two structs). + */ + +struct btt_flog { + uint32_t lba; /* last pre-map LBA using this entry */ + uint32_t old_map; /* old post-map LBA (the freed block) */ + uint32_t new_map; /* new post-map LBA */ + uint32_t seq; /* sequence number (01, 10, 11) */ +}; + +/* + * Layout of a BTT "map" entry. 4-byte internal LBA offset, little-endian. + */ +#define BTT_MAP_ENTRY_SIZE 4 +#define BTT_MAP_ENTRY_ZERO (1u << 30) +#define BTT_MAP_ENTRY_ERROR (1u << 31) +#define BTT_MAP_ENTRY_LBA_MASK 0x3fffffff + +/* + * BTT layout properties... + */ +#define BTT_MIN_SIZE ((size_t)(1ul << 20) * 512) +#define BTT_MAX_ARENA ((size_t)(1ul << 39)) /* 512GB per arena */ +#define BTT_MIN_LBA 512 +#define BTT_INTERNAL_LBA_ALIGNMENT 256 +#define BTT_DEFAULT_NFREE 256 diff --git a/src/debug/Makefile b/src/debug/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..7d7db8172756feb62ef5b353fecdba019382c024 --- /dev/null +++ b/src/debug/Makefile @@ -0,0 +1,45 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/debug/Makefile -- build the debug versions of the NVM Library +# + +JEMALLOC_MAKE_NAME = Makefile_debug +JEMALLOC_OBJROOT = debug + +VARIANT_DESTDIR = nvml_debug + +include ../Makefile.inc + +CFLAGS += -DDEBUG +EXTRA_JECONFIG += --enable-debug diff --git a/src/debug/README b/src/debug/README new file mode 100644 index 0000000000000000000000000000000000000000..5ed6e5a6d73c8e1106b9041ffd40b925c93590fa --- /dev/null +++ b/src/debug/README @@ -0,0 +1,9 @@ +Linux NVM Library + +This is src/debug/README. + +This directory is where debug versions of the object files and +the targets end up. To build just the debug version of the +library, use "make all" from this directory. To build both +the debug and nondebug version, use "make all" from the parent +directory. diff --git a/src/include/README b/src/include/README new file mode 100644 index 0000000000000000000000000000000000000000..6c3cfa7010f0921a68d48929960b42ddef422d74 --- /dev/null +++ b/src/include/README @@ -0,0 +1,17 @@ +Linux NVM Library + +This is src/include/README. + +This directory contains include files that are meant to be +installed on a system when the NVM Library package is installed. +These include files provide the public information exported +by the libraries that is necessary for applications to call into +the libraries. Private include files, used only internally in +the libraries, don't live here -- they typically live next to +the source for their module. + +Here you'll find: + +libpmem.h -- definitions of libpmem entry points (see libpmem(3)) + +libvmem.h -- definitions of libvmem entry points (see libvmem(3)) diff --git a/src/include/libpmem.h b/src/include/libpmem.h new file mode 100644 index 0000000000000000000000000000000000000000..017e642e142f4854b9440bdf078215c50910b417 --- /dev/null +++ b/src/include/libpmem.h @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * libpmem.h -- definitions of libpmem entry points + * + * This library provides support for programming with Persistent Memory (PMEM). + * + * The libpmem entry points are divided below into these categories: + * - basic PMEM flush-to-durability support + * - support for memory allocation and transactions in PMEM + * - support for arrays of atomically-writable blocks + * - support for PMEM-resident log files + * - managing overall library behavior + * + * See libpmem(3) for details. + */ + +#ifndef LIBPMEM_H +#define LIBPMEM_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#include <sys/types.h> +#include <sys/uio.h> + +/* + * opaque types internal to libpmem... + */ +typedef struct pmemtrn PMEMtrn; +typedef struct pmemblk PMEMblk; +typedef struct pmemlog PMEMlog; + +/* + * basic PMEM flush-to-durability support... + */ +int pmem_is_pmem(void *addr, size_t len); +void pmem_persist(void *addr, size_t len, int flags); +void pmem_flush(void *addr, size_t len, int flags); +void pmem_fence(void); +void pmem_drain(void); + +/* + * support for memory allocation and transactions in PMEM... + */ +#define PMEMTRN_MIN_POOL ((size_t)(1024 * 1024 * 2)) /* min pool size: 2MB */ +PMEMtrn *pmemtrn_map(int fd); +void pmemtrn_unmap(PMEMtrn *ptp); +void *pmemtrn_static_area(PMEMtrn *ptp); +int pmemtrn_begin(PMEMtrn *ptp); +int pmemtrn_commit(PMEMtrn *ptp, int tid); +int pmemtrn_abort(PMEMtrn *ptp, int tid); +void *pmemtrn_malloc(PMEMtrn *ptp, size_t size); +void pmemtrn_free(PMEMtrn *ptp, void *ptr); +void *pmemtrn_calloc(PMEMtrn *ptp, size_t nmemb, size_t size); +void *pmemtrn_realloc(PMEMtrn *ptp, void *ptr, size_t size); +void *pmemtrn_aligned_alloc(PMEMtrn *ptp, size_t alignment, size_t size); +char *pmemtrn_strdup(PMEMtrn *ptp, const char *s); +void *pmemtrn_alloc(PMEMtrn *ptp, void *oldptr, size_t alignment, int zeroed, + int tag, size_t size); +void pmemtrn_set(PMEMtrn *ptp, void *pmem_dest, const void *src, size_t n); +void pmemtrn_set_ptr(PMEMtrn *ptp, void *pmem_dest, const void *src); +void *pmemtrn_ptr(PMEMtrn *ptp, void *pmem_src); +void pmemtrn_strncpy(PMEMtrn *ptp, char *pmem_dest, const char *src, size_t n); +void pmemtrn_walk(PMEMtrn *ptp, + void (*cb)(const void *ptr, int tag, void *arg), void *arg); +PMEMtrn *pmemtrn_map_replicant(PMEMtrn *ptp, int fd); + +/* + * support for arrays of atomically-writable blocks... + */ +#define PMEMBLK_MIN_POOL ((size_t)(1024 * 1024 * 1024)) /* min pool size: 1GB */ +#define PMEMBLK_MIN_BLK ((size_t)512) +PMEMblk *pmemblk_map(int fd, size_t bsize); +void pmemblk_unmap(PMEMblk *pbp); +size_t pmemblk_nblock(PMEMblk *pbp); +int pmemblk_read(PMEMblk *pbp, void *buf, off_t blockno); +int pmemblk_write(PMEMblk *pbp, const void *buf, off_t blockno); +int pmemblk_set_zero(PMEMblk *pbp, off_t blockno); +int pmemblk_set_error(PMEMblk *pbp, off_t blockno); + +/* + * support for PMEM-resident log files... + */ +#define PMEMLOG_MIN_POOL ((size_t)(1024 * 1024 * 2)) /* min pool size: 2MB */ +PMEMlog *pmemlog_map(int fd); +void pmemlog_unmap(PMEMlog *plp); +size_t pmemlog_nbyte(PMEMlog *plp); +int pmemlog_append(PMEMlog *plp, const void *buf, size_t count); +int pmemlog_appendv(PMEMlog *plp, const struct iovec *iov, int iovcnt); +off_t pmemlog_tell(PMEMlog *plp); +void pmemlog_rewind(PMEMlog *plp); +void pmemlog_walk(PMEMlog *plp, size_t chunksize, + int (*process_chunk)(const void *buf, size_t len, void *arg), + void *arg); + +/* + * managing overall library behavior... + */ + +/* + * PMEM_MAJOR_VERSION and PMEM_MINOR_VERSION provide the current + * version of the libpmem API as provided by this header file. + * Applications can verify that the version available at run-time + * is compatible with the version used at compile-time by passing + * these defines to pmem_check_version(). + */ +#define PMEM_MAJOR_VERSION 1 +#define PMEM_MINOR_VERSION 0 +const char *pmem_check_version( + unsigned major_required, + unsigned minor_required); + +/* + * Passing NULL to pmem_set_funcs() tells libpmem to continue to use + * the default for that function. The replacement functions must + * not make calls back into libpmem. + * + * The print_func is called by libpmem based on the environment + * variable PMEM_LOG_LEVEL: + * 0 or unset: print_func is only called for pmem_pool_stats_print() + * 1: additional details are logged when errors are returned + * 2: basic operations (allocations/frees) are logged + * 3: produce very verbose tracing of function calls in libpmem + * 4: also log obscure stuff used to debug the library itself + * + * The default print_func prints to stderr. Applications can override this + * by setting the environment variable PMEM_LOG_FILE, or by supplying a + * replacement print function. + */ +void pmem_set_funcs( + void *(*malloc_func)(size_t size), + void (*free_func)(void *ptr), + void *(*realloc_func)(void *ptr, size_t size), + char *(*strdup_func)(const char *s), + void (*print_func)(const char *s), + void (*persist_func)(void *addr, size_t len, int flags)); + +/* + * These are consistency checkers, for library debugging/testing, meant to + * work on persistent memory files that are not current mapped or in use. + */ +int pmemtrn_check(const char *path); +int pmemblk_check(const char *path); +int pmemlog_check(const char *path); + +#ifdef __cplusplus +} +#endif +#endif /* libpmem.h */ diff --git a/src/include/libvmem.h b/src/include/libvmem.h new file mode 100644 index 0000000000000000000000000000000000000000..ba70969bc9e1e186d63945aace71f0879eee0d7c --- /dev/null +++ b/src/include/libvmem.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * libvmem.h -- definitions of libvmem entry points + * + * This library exposes memory-mapped files as volatile memory (a la malloc) + * + * See libvmem(3) for details. + */ + +#ifndef LIBVMEM_H +#define LIBVMEM_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#include <sys/types.h> + +typedef struct vmem VMEM; /* opaque type internal to libvmem */ + +/* + * managing volatile memory pools... + */ + +#define VMEM_MIN_POOL ((size_t)(1024 * 1024 * 14)) /* min pool size: 14MB */ + +VMEM *vmem_pool_create(const char *dir, size_t size); +VMEM *vmem_pool_create_in_region(void *addr, size_t size); +void vmem_pool_delete(VMEM *vmp); +int vmem_pool_check(VMEM *vmp); +size_t vmem_pool_freespace(VMEM *vmp); +void vmem_pool_stats_print(VMEM *vmp, const char *opts); + +/* + * support for malloc and friends... + */ +void *vmem_malloc(VMEM *vmp, size_t size); +void vmem_free(VMEM *vmp, void *ptr); +void *vmem_calloc(VMEM *vmp, size_t nmemb, size_t size); +void *vmem_realloc(VMEM *vmp, void *ptr, size_t size); +void *vmem_aligned_alloc(VMEM *vmp, size_t alignment, size_t size); +char *vmem_strdup(VMEM *vmp, const char *s); + +/* + * managing overall library behavior... + */ + +/* + * VMEM_MAJOR_VERSION and VMEM_MINOR_VERSION provide the current + * version of the libvmem API as provided by this header file. + * Applications can verify that the version available at run-time + * is compatible with the version used at compile-time by passing + * these defines to vmem_check_version(). + */ +#define VMEM_MAJOR_VERSION 1 +#define VMEM_MINOR_VERSION 0 +const char *vmem_check_version( + unsigned major_required, + unsigned minor_required); + +/* + * Passing NULL to vmem_set_funcs() tells libvmem to continue to use + * the default for that function. The replacement functions must + * not make calls back into libvmem. + * + * The print_func is called by libvmem based on the environment + * variable VMEM_LOG_LEVEL: + * 0 or unset: print_func is only called for vmem_pool_stats_print() + * 1: additional details are logged when errors are returned + * 2: basic operations (allocations/frees) are logged + * 3: produce very verbose tracing of function calls in libvmem + * 4: also log obscure stuff used to debug the library itself + * + * The default print_func prints to stderr. Applications can override this + * by setting the environment variable VMEM_LOG_FILE, or by supplying a + * replacement print function. + */ +void vmem_set_funcs( + void *(*malloc_func)(size_t size), + void (*free_func)(void *ptr), + void *(*realloc_func)(void *ptr, size_t size), + char *(*strdup_func)(const char *s), + void (*print_func)(const char *s)); + +#ifdef __cplusplus +} +#endif +#endif /* libvmem.h */ diff --git a/src/jemalloc.cfg b/src/jemalloc.cfg new file mode 100644 index 0000000000000000000000000000000000000000..90385c6834c4bf200ed0f65881eda3a6918b4754 --- /dev/null +++ b/src/jemalloc.cfg @@ -0,0 +1,7 @@ +--without-export +--with-jemalloc-prefix=je_vmem_ +--with-private-namespace=je_vmem_ +--disable-xmalloc +--disable-munmap +EXTRA_CFLAGS="-DJEMALLOC_LIBVMEM -Werror" + diff --git a/src/jemalloc/.gitignore b/src/jemalloc/.gitignore index 4c408ec2c28380571fd761abce5729b2cedc7ac5..a297b3d6a1a9749f1efd6c2cbf917392636aefe9 100644 --- a/src/jemalloc/.gitignore +++ b/src/jemalloc/.gitignore @@ -18,6 +18,7 @@ /lib/ /Makefile +/Makefile_debug /include/jemalloc/internal/jemalloc_internal.h /include/jemalloc/internal/jemalloc_internal_defs.h @@ -70,3 +71,5 @@ test/include/test/jemalloc_test_defs.h /test/unit/*.out /VERSION + +/debugsrc/* \ No newline at end of file diff --git a/src/jemalloc/INSTALL b/src/jemalloc/INSTALL index 841704d2a08d4ef5f1c1434b4a4d8e5d4df295d5..2df667cad5c2b2e6735bd022ad2d8987cfce9ac7 100644 --- a/src/jemalloc/INSTALL +++ b/src/jemalloc/INSTALL @@ -71,10 +71,10 @@ any of the following arguments (not a definitive list) to 'configure': versions of jemalloc can coexist in the same installation directory. For example, libjemalloc.so.0 becomes libjemalloc<suffix>.so.0. ---enable-cc-silence - Enable code that silences non-useful compiler warnings. This is helpful - when trying to tell serious warnings from those due to compiler - limitations, but it potentially incurs a performance penalty. +--disable-cc-silence + Disable code that silences non-useful compiler warnings. This is mainly + useful during development when auditing the set of warnings that are being + silenced. --enable-debug Enable assertions and validation code. This incurs a substantial @@ -132,12 +132,6 @@ any of the following arguments (not a definitive list) to 'configure': released in bulk, thus reducing the total number of mutex operations. See the "opt.tcache" option for usage details. ---enable-mremap - Enable huge realloc() via mremap(2). mremap() is disabled by default - because the flavor used is specific to Linux, which has a quirk in its - virtual memory allocation algorithm that causes semi-permanent VM map holes - under normal jemalloc operation. - --disable-munmap Disable virtual memory deallocation via munmap(2); instead keep track of the virtual memory for later use. munmap() is disabled by default (i.e. @@ -145,10 +139,6 @@ any of the following arguments (not a definitive list) to 'configure': memory allocation algorithm that causes semi-permanent VM map holes under normal jemalloc operation. ---enable-dss - Enable support for page allocation/deallocation via sbrk(2), in addition to - mmap(2). - --disable-fill Disable support for junk/zero filling of memory, quarantine, and redzones. See the "opt.junk", "opt.zero", "opt.quarantine", and "opt.redzone" option @@ -157,9 +147,6 @@ any of the following arguments (not a definitive list) to 'configure': --disable-valgrind Disable support for Valgrind. ---disable-experimental - Disable support for the experimental API (*allocm()). - --disable-zone-allocator Disable zone allocator for Darwin. This means jemalloc won't be hooked as the default allocator on OSX/iOS. diff --git a/src/jemalloc/Makefile.in b/src/jemalloc/Makefile.in index d6b7d6ea3b49a4161275570f657e6102db665115..e0dbb019e6a8d55b30e52b37c027e4b621fab593 100644 --- a/src/jemalloc/Makefile.in +++ b/src/jemalloc/Makefile.in @@ -48,7 +48,7 @@ cfgoutputs_in := @cfgoutputs_in@ cfgoutputs_out := @cfgoutputs_out@ enable_autogen := @enable_autogen@ enable_code_coverage := @enable_code_coverage@ -enable_experimental := @enable_experimental@ +enable_valgrind := @enable_valgrind@ enable_zone_allocator := @enable_zone_allocator@ DSO_LDFLAGS = @DSO_LDFLAGS@ SOREV = @SOREV@ @@ -75,14 +75,17 @@ LIBJEMALLOC := $(LIBPREFIX)jemalloc$(install_suffix) # Lists of files. BINS := $(srcroot)bin/pprof $(objroot)bin/jemalloc.sh C_HDRS := $(objroot)include/jemalloc/jemalloc$(install_suffix).h -C_SRCS := $(srcroot)src/jemalloc.c $(srcroot)src/arena.c \ +C_SRCS := $(srcroot)src/jemalloc.c $(srcroot)src/arena.c $(srcroot)src/pool.c \ $(srcroot)src/atomic.c $(srcroot)src/base.c $(srcroot)src/bitmap.c \ - $(srcroot)src/chunk.c $(srcroot)src/chunk_dss.c \ + $(srcroot)src/chunk.c $(srcroot)src/chunk_dss.c $(srcroot)src/vector.c \ $(srcroot)src/chunk_mmap.c $(srcroot)src/ckh.c $(srcroot)src/ctl.c \ $(srcroot)src/extent.c $(srcroot)src/hash.c $(srcroot)src/huge.c \ $(srcroot)src/mb.c $(srcroot)src/mutex.c $(srcroot)src/prof.c \ $(srcroot)src/quarantine.c $(srcroot)src/rtree.c $(srcroot)src/stats.c \ $(srcroot)src/tcache.c $(srcroot)src/util.c $(srcroot)src/tsd.c +ifeq ($(enable_valgrind), 1) +C_SRCS += $(srcroot)src/valgrind.c +endif ifeq ($(enable_zone_allocator), 1) C_SRCS += $(srcroot)src/zone.c endif @@ -127,23 +130,22 @@ TESTS_UNIT := $(srcroot)test/unit/bitmap.c \ $(srcroot)test/unit/stats.c \ $(srcroot)test/unit/tsd.c \ $(srcroot)test/unit/util.c \ - $(srcroot)test/unit/zero.c + $(srcroot)test/unit/zero.c \ + $(srcroot)test/unit/pool_base_alloc.c \ + $(srcroot)test/unit/pool_custom_alloc.c \ + $(srcroot)test/unit/pool_custom_alloc_internal.c TESTS_UNIT_AUX := $(srcroot)test/unit/prof_accum_a.c \ $(srcroot)test/unit/prof_accum_b.c TESTS_INTEGRATION := $(srcroot)test/integration/aligned_alloc.c \ $(srcroot)test/integration/allocated.c \ $(srcroot)test/integration/mallocx.c \ - $(srcroot)test/integration/mremap.c \ + $(srcroot)test/integration/MALLOCX_ARENA.c \ $(srcroot)test/integration/posix_memalign.c \ $(srcroot)test/integration/rallocx.c \ $(srcroot)test/integration/thread_arena.c \ $(srcroot)test/integration/thread_tcache_enabled.c \ - $(srcroot)test/integration/xallocx.c -ifeq ($(enable_experimental), 1) -TESTS_INTEGRATION += $(srcroot)test/integration/allocm.c \ - $(srcroot)test/integration/MALLOCX_ARENA.c \ - $(srcroot)test/integration/rallocm.c -endif + $(srcroot)test/integration/xallocx.c \ + $(srcroot)test/integration/chunk.c TESTS_STRESS := TESTS := $(TESTS_UNIT) $(TESTS_INTEGRATION) $(TESTS_STRESS) @@ -214,13 +216,13 @@ define make-unit-link-dep $(1): TESTS_UNIT_LINK_OBJS += $(2) $(1): $(2) endef -$(foreach test, $(TESTS_UNIT:$(srcroot)test/unit/%.c=$(objroot)test/unit/%$(EXE)), $(eval $(call make-unit-link-dep,$(test),$(filter $(test:%=%_a.$(O)) $(test:%=%_b.$(O)),$(TESTS_UNIT_AUX_OBJS))))) +$(foreach test, $(TESTS_UNIT:$(srcroot)test/unit/%.c=$(objroot)test/unit/%$(EXE)), $(eval $(call make-unit-link-dep,$(test),$(filter $(test:%$(EXE)=%_a.$(O)) $(test:%$(EXE)=%_b.$(O)),$(TESTS_UNIT_AUX_OBJS))))) $(TESTS_INTEGRATION_OBJS): CPPFLAGS += -DJEMALLOC_INTEGRATION_TEST $(TESTS_STRESS_OBJS): CPPFLAGS += -DJEMALLOC_STRESS_TEST $(TESTS_OBJS): $(objroot)test/%.$(O): $(srcroot)test/%.c $(TESTS_OBJS): CPPFLAGS += -I$(srcroot)test/include -I$(objroot)test/include ifneq ($(IMPORTLIB),$(SO)) -$(C_OBJS): CPPFLAGS += -DDLLEXPORT +$(C_OBJS) $(C_JET_OBJS): CPPFLAGS += -DDLLEXPORT endif ifndef CC_MM @@ -229,7 +231,7 @@ HEADER_DIRS = $(srcroot)include/jemalloc/internal \ $(objroot)include/jemalloc $(objroot)include/jemalloc/internal HEADERS = $(wildcard $(foreach dir,$(HEADER_DIRS),$(dir)/*.h)) $(C_OBJS) $(C_PIC_OBJS) $(C_JET_OBJS) $(C_TESTLIB_OBJS) $(TESTS_OBJS): $(HEADERS) -$(TESTS_OBJS): $(objroot)test/unit/jemalloc_test.h +$(TESTS_OBJS): $(objroot)test/include/test/jemalloc_test.h endif $(C_OBJS) $(C_PIC_OBJS) $(C_JET_OBJS) $(C_TESTLIB_OBJS) $(TESTS_OBJS): %.$(O): diff --git a/src/jemalloc/bin/pprof b/src/jemalloc/bin/pprof index a309943c1cb9383643fd06e3eb85371f184d274e..328138cd982f266bcfffa882a47c542416367bd9 100755 --- a/src/jemalloc/bin/pprof +++ b/src/jemalloc/bin/pprof @@ -2811,9 +2811,14 @@ sub RemoveUninterestingFrames { 'free', 'memalign', 'posix_memalign', + 'aligned_alloc', 'pvalloc', 'valloc', 'realloc', + 'mallocx', # jemalloc + 'rallocx', # jemalloc + 'xallocx', # jemalloc + 'dallocx', # jemalloc 'tc_calloc', 'tc_cfree', 'tc_malloc', @@ -2923,6 +2928,10 @@ sub RemoveUninterestingFrames { if (exists($symbols->{$a})) { my $func = $symbols->{$a}->[0]; if ($skip{$func} || ($func =~ m/$skip_regexp/)) { + # Throw away the portion of the backtrace seen so far, under the + # assumption that previous frames were for functions internal to the + # allocator. + @path = (); next; } } diff --git a/src/jemalloc/config.sub b/src/jemalloc/config.sub index 61cb4bc22db8e0a490b5ea5bffe6575c10ff92e0..c4cc98365fd3daa64d16f6ae1086bb3607ede579 100755 --- a/src/jemalloc/config.sub +++ b/src/jemalloc/config.sub @@ -1400,6 +1400,8 @@ case $os in -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; + -ios*) + ;; -linux-dietlibc) os=-linux-dietlibc ;; diff --git a/src/jemalloc/configure.ac b/src/jemalloc/configure.ac index 4de81dc1d9f21a635cd04c3f63d8dd9892e7ff93..38da66206da1fad18eb7e6dfda0c02e18b44af24 100644 --- a/src/jemalloc/configure.ac +++ b/src/jemalloc/configure.ac @@ -44,7 +44,7 @@ AC_CACHE_CHECK([whether $1 is compilable], dnl ============================================================================ dnl Library revision. -rev=1 +rev=2 AC_SUBST([rev]) srcroot=$srcdir @@ -141,7 +141,8 @@ if test "x$CFLAGS" = "x" ; then JE_CFLAGS_APPEND([-Zi]) JE_CFLAGS_APPEND([-MT]) JE_CFLAGS_APPEND([-W3]) - CPPFLAGS="$CPPFLAGS -I${srcroot}/include/msvc_compat" + JE_CFLAGS_APPEND([-FS]) + CPPFLAGS="$CPPFLAGS -I${srcdir}/include/msvc_compat" fi fi dnl Append EXTRA_CFLAGS to CFLAGS, if defined. @@ -155,6 +156,10 @@ if test "x${ac_cv_big_endian}" = "x1" ; then AC_DEFINE_UNQUOTED([JEMALLOC_BIG_ENDIAN], [ ]) fi +if test "x${je_cv_msvc}" = "xyes" -a "x${ac_cv_header_inttypes_h}" = "xno"; then + CPPFLAGS="$CPPFLAGS -I${srcdir}/include/msvc_compat/C99" +fi + AC_CHECK_SIZEOF([void *]) if test "x${ac_cv_sizeof_void_p}" = "x8" ; then LG_SIZEOF_PTR=3 @@ -258,9 +263,8 @@ dnl Define cpp macros in CPPFLAGS, rather than doing AC_DEFINE(macro), since the dnl definitions need to be seen before any headers are included, which is a pain dnl to make happen otherwise. default_munmap="1" -JEMALLOC_USABLE_SIZE_CONST="const" case "${host}" in - *-*-darwin*) + *-*-darwin* | *-*-ios*) CFLAGS="$CFLAGS" abi="macho" AC_DEFINE([JEMALLOC_PURGE_MADVISE_FREE], [ ]) @@ -286,7 +290,6 @@ case "${host}" in AC_DEFINE([JEMALLOC_HAS_ALLOCA_H]) AC_DEFINE([JEMALLOC_PURGE_MADVISE_DONTNEED], [ ]) AC_DEFINE([JEMALLOC_THREADED_INIT], [ ]) - JEMALLOC_USABLE_SIZE_CONST="" default_munmap="0" ;; *-*-netbsd*) @@ -351,6 +354,22 @@ case "${host}" in abi="elf" ;; esac + +JEMALLOC_USABLE_SIZE_CONST=const +AC_CHECK_HEADERS([malloc.h], [ + AC_MSG_CHECKING([whether malloc_usable_size definition can use const argument]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM( + [#include <malloc.h> + #include <stddef.h> + size_t malloc_usable_size(const void *ptr); + ], + [])],[ + AC_MSG_RESULT([yes]) + ],[ + JEMALLOC_USABLE_SIZE_CONST= + AC_MSG_RESULT([no]) + ]) +]) AC_DEFINE_UNQUOTED([JEMALLOC_USABLE_SIZE_CONST], [$JEMALLOC_USABLE_SIZE_CONST]) AC_SUBST([abi]) AC_SUBST([RPATH]) @@ -428,7 +447,7 @@ AC_PROG_RANLIB AC_PATH_PROG([LD], [ld], [false], [$PATH]) AC_PATH_PROG([AUTOCONF], [autoconf], [false], [$PATH]) -public_syms="malloc_conf malloc_message malloc calloc posix_memalign aligned_alloc realloc free mallocx rallocx xallocx sallocx dallocx nallocx mallctl mallctlnametomib mallctlbymib malloc_stats_print malloc_usable_size" +public_syms="pool_create pool_delete pool_malloc pool_calloc pool_ralloc pool_aligned_alloc pool_free pool_malloc_stats_print pool_extend pool_set_alloc_funcs malloc_conf malloc_message malloc calloc posix_memalign aligned_alloc realloc free mallocx rallocx xallocx sallocx dallocx nallocx mallctl mallctlnametomib mallctlbymib malloc_stats_print malloc_usable_size" dnl Check for allocator-related functions that should be wrapped. AC_CHECK_FUNC([memalign], @@ -438,24 +457,6 @@ AC_CHECK_FUNC([valloc], [AC_DEFINE([JEMALLOC_OVERRIDE_VALLOC], [ ]) public_syms="${public_syms} valloc"]) -dnl Support the experimental API by default. -AC_ARG_ENABLE([experimental], - [AS_HELP_STRING([--disable-experimental], - [Disable support for the experimental API])], -[if test "x$enable_experimental" = "xno" ; then - enable_experimental="0" -else - enable_experimental="1" -fi -], -[enable_experimental="1"] -) -if test "x$enable_experimental" = "x1" ; then - AC_DEFINE([JEMALLOC_EXPERIMENTAL], [ ]) - public_syms="${public_syms} allocm dallocm nallocm rallocm sallocm" -fi -AC_SUBST([enable_experimental]) - dnl Do not compute test code coverage by default. GCOV_FLAGS= AC_ARG_ENABLE([code-coverage], @@ -595,18 +596,17 @@ cfghdrs_tup="include/jemalloc/jemalloc_defs.h:include/jemalloc/jemalloc_defs.h.i cfghdrs_tup="${cfghdrs_tup} include/jemalloc/internal/jemalloc_internal_defs.h:${srcroot}include/jemalloc/internal/jemalloc_internal_defs.h.in" cfghdrs_tup="${cfghdrs_tup} test/include/test/jemalloc_test_defs.h:${srcroot}test/include/test/jemalloc_test_defs.h.in" -dnl Do not silence irrelevant compiler warnings by default, since enabling this -dnl option incurs a performance penalty. +dnl Silence irrelevant compiler warnings by default. AC_ARG_ENABLE([cc-silence], - [AS_HELP_STRING([--enable-cc-silence], - [Silence irrelevant compiler warnings])], + [AS_HELP_STRING([--disable-cc-silence], + [Do not silence irrelevant compiler warnings])], [if test "x$enable_cc_silence" = "xno" ; then enable_cc_silence="0" else enable_cc_silence="1" fi ], -[enable_cc_silence="0"] +[enable_cc_silence="1"] ) if test "x$enable_cc_silence" = "x1" ; then AC_DEFINE([JEMALLOC_CC_SILENCE], [ ]) @@ -721,7 +721,7 @@ fi, if test "x$backtrace_method" = "x" -a "x$enable_prof_libunwind" = "x1" ; then AC_CHECK_HEADERS([libunwind.h], , [enable_prof_libunwind="0"]) if test "x$LUNWIND" = "x-lunwind" ; then - AC_CHECK_LIB([unwind], [backtrace], [LIBS="$LIBS $LUNWIND"], + AC_CHECK_LIB([unwind], [unw_backtrace], [LIBS="$LIBS $LUNWIND"], [enable_prof_libunwind="0"]) else LIBS="$LIBS $LUNWIND" @@ -812,33 +812,6 @@ if test "x$enable_tcache" = "x1" ; then fi AC_SUBST([enable_tcache]) -dnl Disable mremap() for huge realloc() by default. -AC_ARG_ENABLE([mremap], - [AS_HELP_STRING([--enable-mremap], [Enable mremap(2) for huge realloc()])], -[if test "x$enable_mremap" = "xno" ; then - enable_mremap="0" -else - enable_mremap="1" -fi -], -[enable_mremap="0"] -) -if test "x$enable_mremap" = "x1" ; then - JE_COMPILABLE([mremap(...MREMAP_FIXED...)], [ -#define _GNU_SOURCE -#include <sys/mman.h> -], [ -void *p = mremap((void *)0, 0, 0, MREMAP_MAYMOVE|MREMAP_FIXED, (void *)0); -], [je_cv_mremap_fixed]) - if test "x${je_cv_mremap_fixed}" = "xno" ; then - enable_mremap="0" - fi -fi -if test "x$enable_mremap" = "x1" ; then - AC_DEFINE([JEMALLOC_MREMAP], [ ]) -fi -AC_SUBST([enable_mremap]) - dnl Enable VM deallocation via munmap() by default. AC_ARG_ENABLE([munmap], [AS_HELP_STRING([--disable-munmap], [Disable VM deallocation via munmap(2)])], @@ -855,34 +828,22 @@ if test "x$enable_munmap" = "x1" ; then fi AC_SUBST([enable_munmap]) -dnl Do not enable allocation from DSS by default. -AC_ARG_ENABLE([dss], - [AS_HELP_STRING([--enable-dss], [Enable allocation from DSS])], -[if test "x$enable_dss" = "xno" ; then - enable_dss="0" -else - enable_dss="1" -fi -], -[enable_dss="0"] -) +dnl Enable allocation from DSS if supported by the OS. +have_dss="1" dnl Check whether the BSD/SUSv1 sbrk() exists. If not, disable DSS support. AC_CHECK_FUNC([sbrk], [have_sbrk="1"], [have_sbrk="0"]) if test "x$have_sbrk" = "x1" ; then if test "x$sbrk_deprecated" == "x1" ; then AC_MSG_RESULT([Disabling dss allocation because sbrk is deprecated]) - enable_dss="0" - else - AC_DEFINE([JEMALLOC_HAVE_SBRK], [ ]) + have_dss="0" fi else - enable_dss="0" + have_dss="0" fi -if test "x$enable_dss" = "x1" ; then +if test "x$have_dss" = "x1" ; then AC_DEFINE([JEMALLOC_DSS], [ ]) fi -AC_SUBST([enable_dss]) dnl Support the junk/zero filling option by default. AC_ARG_ENABLE([fill], @@ -974,6 +935,44 @@ if test "x$enable_xmalloc" = "x1" ; then fi AC_SUBST([enable_xmalloc]) +dnl ============================================================================ +dnl Check for __builtin_ffsl(), then ffsl(3), and fail if neither are found. +dnl One of those two functions should (theoretically) exist on all platforms +dnl that jemalloc currently has a chance of functioning on without modification. +dnl We additionally assume ffs() or __builtin_ffs() are defined if +dnl ffsl() or __builtin_ffsl() are defined, respectively. +JE_COMPILABLE([a program using __builtin_ffsl], [ +#include <stdio.h> +#include <strings.h> +#include <string.h> +], [ + { + int rv = __builtin_ffsl(0x08); + printf("%d\n", rv); + } +], [je_cv_gcc_builtin_ffsl]) +if test "x${je_cv_gcc_builtin_ffsl}" == "xyes" ; then + AC_DEFINE([JEMALLOC_INTERNAL_FFSL], [__builtin_ffsl]) + AC_DEFINE([JEMALLOC_INTERNAL_FFS], [__builtin_ffs]) +else + JE_COMPILABLE([a program using ffsl], [ + #include <stdio.h> + #include <strings.h> + #include <string.h> + ], [ + { + int rv = ffsl(0x08); + printf("%d\n", rv); + } + ], [je_cv_function_ffsl]) + if test "x${je_cv_function_ffsl}" == "xyes" ; then + AC_DEFINE([JEMALLOC_INTERNAL_FFSL], [ffsl]) + AC_DEFINE([JEMALLOC_INTERNAL_FFS], [ffs]) + else + AC_MSG_ERROR([Cannot build without ffsl(3) or __builtin_ffsl()]) + fi +fi + AC_CACHE_CHECK([STATIC_PAGE_SHIFT], [je_cv_static_page_shift], AC_RUN_IFELSE([AC_LANG_PROGRAM( @@ -1000,7 +999,7 @@ AC_CACHE_CHECK([STATIC_PAGE_SHIFT], if (result == -1) { return 1; } - result = ffsl(result) - 1; + result = JEMALLOC_INTERNAL_FFSL(result) - 1; f = fopen("conftest.out", "w"); if (f == NULL) { @@ -1012,7 +1011,8 @@ AC_CACHE_CHECK([STATIC_PAGE_SHIFT], return 0; ]])], [je_cv_static_page_shift=`cat conftest.out`], - [je_cv_static_page_shift=undefined])) + [je_cv_static_page_shift=undefined], + [je_cv_static_page_shift=12])) if test "x$je_cv_static_page_shift" != "xundefined"; then AC_DEFINE_UNQUOTED([STATIC_PAGE_SHIFT], [$je_cv_static_page_shift]) @@ -1146,24 +1146,6 @@ elif test "x${force_tls}" = "x1" ; then AC_MSG_ERROR([Failed to configure TLS, which is mandatory for correct function]) fi -dnl ============================================================================ -dnl Check for ffsl(3), and fail if not found. This function exists on all -dnl platforms that jemalloc currently has a chance of functioning on without -dnl modification. -JE_COMPILABLE([a program using ffsl], [ -#include <stdio.h> -#include <strings.h> -#include <string.h> -], [ - { - int rv = ffsl(0x08); - printf("%d\n", rv); - } -], [je_cv_function_ffsl]) -if test "x${je_cv_function_ffsl}" != "xyes" ; then - AC_MSG_ERROR([Cannot build without ffsl(3)]) -fi - dnl ============================================================================ dnl Check for atomic(9) operations as provided on FreeBSD. @@ -1209,6 +1191,20 @@ if test "x${je_cv_osatomic}" = "xyes" ; then AC_DEFINE([JEMALLOC_OSATOMIC], [ ]) fi +dnl ============================================================================ +dnl Check for madvise(2). + +JE_COMPILABLE([madvise(2)], [ +#include <sys/mman.h> +], [ + { + madvise((void *)0, 0, 0); + } +], [je_cv_madvise]) +if test "x${je_cv_madvise}" = "xyes" ; then + AC_DEFINE([JEMALLOC_HAVE_MADVISE], [ ]) +fi + dnl ============================================================================ dnl Check whether __sync_{add,sub}_and_fetch() are available despite dnl __GCC_HAVE_SYNC_COMPARE_AND_SWAP_n macros being undefined. @@ -1243,6 +1239,29 @@ if test "x${je_cv_atomic9}" != "xyes" -a "x${je_cv_osatomic}" != "xyes" ; then JE_SYNC_COMPARE_AND_SWAP_CHECK(64, 8) fi +dnl ============================================================================ +dnl Check for __builtin_clz() and __builtin_clzl(). + +AC_CACHE_CHECK([for __builtin_clz], + [je_cv_builtin_clz], + [AC_LINK_IFELSE([AC_LANG_PROGRAM([], + [ + { + unsigned x = 0; + int y = __builtin_clz(x); + } + { + unsigned long x = 0; + int y = __builtin_clzl(x); + } + ])], + [je_cv_builtin_clz=yes], + [je_cv_builtin_clz=no])]) + +if test "x${je_cv_builtin_clz}" = "xyes" ; then + AC_DEFINE([JEMALLOC_HAVE_BUILTIN_CLZ], [ ]) +fi + dnl ============================================================================ dnl Check for spinlock(3) operations as provided on Darwin. @@ -1465,7 +1484,6 @@ AC_MSG_RESULT([JEMALLOC_PRIVATE_NAMESPACE]) AC_MSG_RESULT([ : ${JEMALLOC_PRIVATE_NAMESPACE}]) AC_MSG_RESULT([install_suffix : ${install_suffix}]) AC_MSG_RESULT([autogen : ${enable_autogen}]) -AC_MSG_RESULT([experimental : ${enable_experimental}]) AC_MSG_RESULT([cc-silence : ${enable_cc_silence}]) AC_MSG_RESULT([debug : ${enable_debug}]) AC_MSG_RESULT([code-coverage : ${enable_code_coverage}]) @@ -1479,9 +1497,7 @@ AC_MSG_RESULT([fill : ${enable_fill}]) AC_MSG_RESULT([utrace : ${enable_utrace}]) AC_MSG_RESULT([valgrind : ${enable_valgrind}]) AC_MSG_RESULT([xmalloc : ${enable_xmalloc}]) -AC_MSG_RESULT([mremap : ${enable_mremap}]) AC_MSG_RESULT([munmap : ${enable_munmap}]) -AC_MSG_RESULT([dss : ${enable_dss}]) AC_MSG_RESULT([lazy_lock : ${enable_lazy_lock}]) AC_MSG_RESULT([tls : ${enable_tls}]) AC_MSG_RESULT([===============================================================================]) diff --git a/src/jemalloc/doc/jemalloc.xml.in b/src/jemalloc/doc/jemalloc.xml.in index d8e2e711f2c8c25d90f64ea90feec4fce376afec..308d0c6530c789a32b3531b6e26b71afd3545b9d 100644 --- a/src/jemalloc/doc/jemalloc.xml.in +++ b/src/jemalloc/doc/jemalloc.xml.in @@ -44,11 +44,6 @@ <refname>mallctlbymib</refname> <refname>malloc_stats_print</refname> <refname>malloc_usable_size</refname> - <refname>allocm</refname> - <refname>rallocm</refname> - <refname>sallocm</refname> - <refname>dallocm</refname> - <refname>nallocm</refname> --> <refpurpose>general purpose memory allocation functions</refpurpose> </refnamediv> @@ -172,41 +167,6 @@ </funcprototype> <para><type>const char *</type><varname>malloc_conf</varname>;</para> </refsect2> - <refsect2> - <title>Experimental API</title> - <funcprototype> - <funcdef>int <function>allocm</function></funcdef> - <paramdef>void **<parameter>ptr</parameter></paramdef> - <paramdef>size_t *<parameter>rsize</parameter></paramdef> - <paramdef>size_t <parameter>size</parameter></paramdef> - <paramdef>int <parameter>flags</parameter></paramdef> - </funcprototype> - <funcprototype> - <funcdef>int <function>rallocm</function></funcdef> - <paramdef>void **<parameter>ptr</parameter></paramdef> - <paramdef>size_t *<parameter>rsize</parameter></paramdef> - <paramdef>size_t <parameter>size</parameter></paramdef> - <paramdef>size_t <parameter>extra</parameter></paramdef> - <paramdef>int <parameter>flags</parameter></paramdef> - </funcprototype> - <funcprototype> - <funcdef>int <function>sallocm</function></funcdef> - <paramdef>const void *<parameter>ptr</parameter></paramdef> - <paramdef>size_t *<parameter>rsize</parameter></paramdef> - <paramdef>int <parameter>flags</parameter></paramdef> - </funcprototype> - <funcprototype> - <funcdef>int <function>dallocm</function></funcdef> - <paramdef>void *<parameter>ptr</parameter></paramdef> - <paramdef>int <parameter>flags</parameter></paramdef> - </funcprototype> - <funcprototype> - <funcdef>int <function>nallocm</function></funcdef> - <paramdef>size_t *<parameter>rsize</parameter></paramdef> - <paramdef>size_t <parameter>size</parameter></paramdef> - <paramdef>int <parameter>flags</parameter></paramdef> - </funcprototype> - </refsect2> </funcsynopsis> </refsynopsisdiv> <refsect1 id="description"> @@ -229,15 +189,15 @@ <para>The <function>posix_memalign<parameter/></function> function allocates <parameter>size</parameter> bytes of memory such that the - allocation's base address is an even multiple of + allocation's base address is a multiple of <parameter>alignment</parameter>, and returns the allocation in the value pointed to by <parameter>ptr</parameter>. The requested - <parameter>alignment</parameter> must be a power of 2 at least as large - as <code language="C">sizeof(<type>void *</type>)</code>.</para> + <parameter>alignment</parameter> must be a power of 2 at least as large as + <code language="C">sizeof(<type>void *</type>)</code>.</para> <para>The <function>aligned_alloc<parameter/></function> function allocates <parameter>size</parameter> bytes of memory such that the - allocation's base address is an even multiple of + allocation's base address is a multiple of <parameter>alignment</parameter>. The requested <parameter>alignment</parameter> must be a power of 2. Behavior is undefined if <parameter>size</parameter> is not an integral multiple of @@ -310,10 +270,10 @@ <listitem><para>Use the arena specified by the index <parameter>a</parameter> (and by necessity bypass the thread - cache). This macro has no effect for huge regions, nor for regions - that were allocated via an arena other than the one specified. - This macro does not validate that <parameter>a</parameter> - specifies an arena index in the valid range.</para></listitem> + cache). This macro has no effect for regions that were allocated + via an arena other than the one specified. This macro does not + validate that <parameter>a</parameter> specifies an arena index in + the valid range.</para></listitem> </varlistentry> </variablelist> </para> @@ -449,116 +409,6 @@ for (i = 0; i < nbins; i++) { depended on, since such behavior is entirely implementation-dependent. </para> </refsect2> - <refsect2> - <title>Experimental API</title> - <para>The experimental API is subject to change or removal without regard - for backward compatibility. If <option>--disable-experimental</option> - is specified during configuration, the experimental API is - omitted.</para> - - <para>The <function>allocm<parameter/></function>, - <function>rallocm<parameter/></function>, - <function>sallocm<parameter/></function>, - <function>dallocm<parameter/></function>, and - <function>nallocm<parameter/></function> functions all have a - <parameter>flags</parameter> argument that can be used to specify - options. The functions only check the options that are contextually - relevant. Use bitwise or (<code language="C">|</code>) operations to - specify one or more of the following: - <variablelist> - <varlistentry> - <term><constant>ALLOCM_LG_ALIGN(<parameter>la</parameter>) - </constant></term> - - <listitem><para>Align the memory allocation to start at an address - that is a multiple of <code language="C">(1 << - <parameter>la</parameter>)</code>. This macro does not validate - that <parameter>la</parameter> is within the valid - range.</para></listitem> - </varlistentry> - <varlistentry> - <term><constant>ALLOCM_ALIGN(<parameter>a</parameter>) - </constant></term> - - <listitem><para>Align the memory allocation to start at an address - that is a multiple of <parameter>a</parameter>, where - <parameter>a</parameter> is a power of two. This macro does not - validate that <parameter>a</parameter> is a power of 2. - </para></listitem> - </varlistentry> - <varlistentry> - <term><constant>ALLOCM_ZERO</constant></term> - - <listitem><para>Initialize newly allocated memory to contain zero - bytes. In the growing reallocation case, the real size prior to - reallocation defines the boundary between untouched bytes and those - that are initialized to contain zero bytes. If this macro is - absent, newly allocated memory is uninitialized.</para></listitem> - </varlistentry> - <varlistentry> - <term><constant>ALLOCM_NO_MOVE</constant></term> - - <listitem><para>For reallocation, fail rather than moving the - object. This constraint can apply to both growth and - shrinkage.</para></listitem> - </varlistentry> - <varlistentry> - <term><constant>ALLOCM_ARENA(<parameter>a</parameter>) - </constant></term> - - <listitem><para>Use the arena specified by the index - <parameter>a</parameter> (and by necessity bypass the thread - cache). This macro has no effect for huge regions, nor for regions - that were allocated via an arena other than the one specified. - This macro does not validate that <parameter>a</parameter> - specifies an arena index in the valid range.</para></listitem> - </varlistentry> - </variablelist> - </para> - - <para>The <function>allocm<parameter/></function> function allocates at - least <parameter>size</parameter> bytes of memory, sets - <parameter>*ptr</parameter> to the base address of the allocation, and - sets <parameter>*rsize</parameter> to the real size of the allocation if - <parameter>rsize</parameter> is not <constant>NULL</constant>. Behavior - is undefined if <parameter>size</parameter> is <constant>0</constant>, or - if request size overflows due to size class and/or alignment - constraints.</para> - - <para>The <function>rallocm<parameter/></function> function resizes the - allocation at <parameter>*ptr</parameter> to be at least - <parameter>size</parameter> bytes, sets <parameter>*ptr</parameter> to - the base address of the allocation if it moved, and sets - <parameter>*rsize</parameter> to the real size of the allocation if - <parameter>rsize</parameter> is not <constant>NULL</constant>. If - <parameter>extra</parameter> is non-zero, an attempt is made to resize - the allocation to be at least <code - language="C">(<parameter>size</parameter> + - <parameter>extra</parameter>)</code> bytes, though inability to allocate - the extra byte(s) will not by itself result in failure. Behavior is - undefined if <parameter>size</parameter> is <constant>0</constant>, if - request size overflows due to size class and/or alignment constraints, or - if <code language="C">(<parameter>size</parameter> + - <parameter>extra</parameter> > - <constant>SIZE_T_MAX</constant>)</code>.</para> - - <para>The <function>sallocm<parameter/></function> function sets - <parameter>*rsize</parameter> to the real size of the allocation.</para> - - <para>The <function>dallocm<parameter/></function> function causes the - memory referenced by <parameter>ptr</parameter> to be made available for - future allocations.</para> - - <para>The <function>nallocm<parameter/></function> function allocates no - memory, but it performs the same size computation as the - <function>allocm<parameter/></function> function, and if - <parameter>rsize</parameter> is not <constant>NULL</constant> it sets - <parameter>*rsize</parameter> to the real size of the allocation that - would result from the equivalent <function>allocm<parameter/></function> - function call. Behavior is undefined if <parameter>size</parameter> is - <constant>0</constant>, or if request size overflows due to size class - and/or alignment constraints.</para> - </refsect2> </refsect1> <refsect1 id="tuning"> <title>TUNING</title> @@ -598,8 +448,10 @@ for (i = 0; i < nbins; i++) { <manvolnum>2</manvolnum></citerefentry> to obtain memory, which is suboptimal for several reasons, including race conditions, increased fragmentation, and artificial limitations on maximum usable memory. If - <option>--enable-dss</option> is specified during configuration, this - allocator uses both <citerefentry><refentrytitle>mmap</refentrytitle> + <citerefentry><refentrytitle>sbrk</refentrytitle> + <manvolnum>2</manvolnum></citerefentry> is supported by the operating + system, this allocator uses both + <citerefentry><refentrytitle>mmap</refentrytitle> <manvolnum>2</manvolnum></citerefentry> and <citerefentry><refentrytitle>sbrk</refentrytitle> <manvolnum>2</manvolnum></citerefentry>, in that order of preference; @@ -634,10 +486,11 @@ for (i = 0; i < nbins; i++) { <para>User objects are broken into three categories according to size: small, large, and huge. Small objects are smaller than one page. Large objects are smaller than the chunk size. Huge objects are a multiple of - the chunk size. Small and large objects are managed by arenas; huge - objects are managed separately in a single data structure that is shared by - all threads. Huge objects are used by applications infrequently enough - that this single data structure is not a scalability issue.</para> + the chunk size. Small and large objects are managed entirely by arenas; + huge objects are additionally aggregated in a single data structure that is + shared by all threads. Huge objects are typically used by applications + infrequently enough that this single data structure is not a scalability + issue.</para> <para>Each chunk that is managed by an arena tracks its contents as runs of contiguous pages (unused, backing a set of small objects, or backing one @@ -775,16 +628,6 @@ for (i = 0; i < nbins; i++) { build configuration.</para></listitem> </varlistentry> - <varlistentry id="config.dss"> - <term> - <mallctl>config.dss</mallctl> - (<type>bool</type>) - <literal>r-</literal> - </term> - <listitem><para><option>--enable-dss</option> was specified during - build configuration.</para></listitem> - </varlistentry> - <varlistentry id="config.fill"> <term> <mallctl>config.fill</mallctl> @@ -805,16 +648,6 @@ for (i = 0; i < nbins; i++) { during build configuration.</para></listitem> </varlistentry> - <varlistentry id="config.mremap"> - <term> - <mallctl>config.mremap</mallctl> - (<type>bool</type>) - <literal>r-</literal> - </term> - <listitem><para><option>--enable-mremap</option> was specified during - build configuration.</para></listitem> - </varlistentry> - <varlistentry id="config.munmap"> <term> <mallctl>config.munmap</mallctl> @@ -940,10 +773,15 @@ for (i = 0; i < nbins; i++) { <manvolnum>2</manvolnum></citerefentry>) allocation precedence as related to <citerefentry><refentrytitle>mmap</refentrytitle> <manvolnum>2</manvolnum></citerefentry> allocation. The following - settings are supported: “disabled”, “primary”, - and “secondary”. The default is “secondary” if - <link linkend="config.dss"><mallctl>config.dss</mallctl></link> is - true, “disabled” otherwise. + settings are supported if + <citerefentry><refentrytitle>sbrk</refentrytitle> + <manvolnum>2</manvolnum></citerefentry> is supported by the operating + system: “disabled”, “primary”, and + “secondary”; otherwise only “disabled” is + supported. The default is “secondary” if + <citerefentry><refentrytitle>sbrk</refentrytitle> + <manvolnum>2</manvolnum></citerefentry> is supported by the operating + system; “disabled” otherwise. </para></listitem> </varlistentry> @@ -1076,9 +914,8 @@ for (i = 0; i < nbins; i++) { <listitem><para>Zero filling enabled/disabled. If enabled, each byte of uninitialized allocated memory will be initialized to 0. Note that this initialization only happens once for each byte, so - <function>realloc<parameter/></function>, - <function>rallocx<parameter/></function> and - <function>rallocm<parameter/></function> calls do not zero memory that + <function>realloc<parameter/></function> and + <function>rallocx<parameter/></function> calls do not zero memory that was previously allocated. This is intended for debugging and will impact performance negatively. This option is disabled by default. </para></listitem> @@ -1097,19 +934,6 @@ for (i = 0; i < nbins; i++) { is disabled by default.</para></listitem> </varlistentry> - <varlistentry id="opt.valgrind"> - <term> - <mallctl>opt.valgrind</mallctl> - (<type>bool</type>) - <literal>r-</literal> - [<option>--enable-valgrind</option>] - </term> - <listitem><para><ulink url="http://valgrind.org/">Valgrind</ulink> - support enabled/disabled. This option is vestigal because jemalloc - auto-detects whether it is running inside Valgrind. This option is - disabled by default, unless running inside Valgrind.</para></listitem> - </varlistentry> - <varlistentry id="opt.xmalloc"> <term> <mallctl>opt.xmalloc</mallctl> @@ -1146,7 +970,8 @@ malloc_conf = "xmalloc:true";]]></programlisting> linkend="opt.lg_tcache_max"><mallctl>opt.lg_tcache_max</mallctl></link> option for related tuning information. This option is enabled by default unless running inside <ulink - url="http://valgrind.org/">Valgrind</ulink>.</para></listitem> + url="http://valgrind.org/">Valgrind</ulink>, in which case it is + forcefully disabled.</para></listitem> </varlistentry> <varlistentry id="opt.lg_tcache_max"> @@ -1421,7 +1246,7 @@ malloc_conf = "xmalloc:true";]]></programlisting> <varlistentry id="arena.i.purge"> <term> <mallctl>arena.<i>.purge</mallctl> - (<type>unsigned</type>) + (<type>void</type>) <literal>--</literal> </term> <listitem><para>Purge unused dirty pages for arena <i>, or for @@ -1439,14 +1264,77 @@ malloc_conf = "xmalloc:true";]]></programlisting> <listitem><para>Set the precedence of dss allocation as related to mmap allocation for arena <i>, or for all arenas if <i> equals <link - linkend="arenas.narenas"><mallctl>arenas.narenas</mallctl></link>. Note - that even during huge allocation this setting is read from the arena - that would be chosen for small or large allocation so that applications - can depend on consistent dss versus mmap allocation regardless of - allocation size. See <link - linkend="opt.dss"><mallctl>opt.dss</mallctl></link> for supported - settings. - </para></listitem> + linkend="arenas.narenas"><mallctl>arenas.narenas</mallctl></link>. See + <link linkend="opt.dss"><mallctl>opt.dss</mallctl></link> for supported + settings.</para></listitem> + </varlistentry> + + <varlistentry id="arena.i.chunk.alloc"> + <term> + <mallctl>arena.<i>.chunk.alloc</mallctl> + (<type>chunk_alloc_t *</type>) + <literal>rw</literal> + </term> + <listitem><para>Get or set the chunk allocation function for arena + <i>. If setting, the chunk deallocation function should + also be set via <link linkend="arena.i.chunk.dalloc"> + <mallctl>arena.<i>.chunk.dalloc</mallctl></link> to a companion + function that knows how to deallocate the chunks. + <funcprototype> + <funcdef>typedef void *<function>(chunk_alloc_t)</function></funcdef> + <paramdef>size_t <parameter>size</parameter></paramdef> + <paramdef>size_t <parameter>alignment</parameter></paramdef> + <paramdef>bool *<parameter>zero</parameter></paramdef> + <paramdef>unsigned <parameter>arena_ind</parameter></paramdef> + </funcprototype> + A chunk allocation function conforms to the <type>chunk_alloc_t</type> + type and upon success returns a pointer to <parameter>size</parameter> + bytes of memory on behalf of arena <parameter>arena_ind</parameter> such + that the chunk's base address is a multiple of + <parameter>alignment</parameter>, as well as setting + <parameter>*zero</parameter> to indicate whether the chunk is zeroed. + Upon error the function returns <constant>NULL</constant> and leaves + <parameter>*zero</parameter> unmodified. The + <parameter>size</parameter> parameter is always a multiple of the chunk + size. The <parameter>alignment</parameter> parameter is always a power + of two at least as large as the chunk size. Zeroing is mandatory if + <parameter>*zero</parameter> is true upon function + entry.</para> + + <para>Note that replacing the default chunk allocation function makes + the arena's <link + linkend="arena.i.dss"><mallctl>arena.<i>.dss</mallctl></link> + setting irrelevant.</para></listitem> + </varlistentry> + + <varlistentry id="arena.i.chunk.dalloc"> + <term> + <mallctl>arena.<i>.chunk.dalloc</mallctl> + (<type>chunk_dalloc_t *</type>) + <literal>rw</literal> + </term> + <listitem><para>Get or set the chunk deallocation function for arena + <i>. If setting, the chunk deallocation function must + be capable of deallocating all extant chunks associated with arena + <i>, usually by passing unknown chunks to the deallocation + function that was replaced. In practice, it is feasible to control + allocation for arenas created via <link + linkend="arenas.extend"><mallctl>arenas.extend</mallctl></link> such + that all chunks originate from an application-supplied chunk allocator + (by setting custom chunk allocation/deallocation functions just after + arena creation), but the automatically created arenas may have already + created chunks prior to the application having an opportunity to take + over chunk allocation. + <funcprototype> + <funcdef>typedef void <function>(chunk_dalloc_t)</function></funcdef> + <paramdef>void *<parameter>chunk</parameter></paramdef> + <paramdef>size_t <parameter>size</parameter></paramdef> + <paramdef>unsigned <parameter>arena_ind</parameter></paramdef> + </funcprototype> + A chunk deallocation function conforms to the + <type>chunk_dalloc_t</type> type and deallocates a + <parameter>chunk</parameter> of given <parameter>size</parameter> on + behalf of arena <parameter>arena_ind</parameter>.</para></listitem> </varlistentry> <varlistentry id="arenas.narenas"> @@ -1564,16 +1452,6 @@ malloc_conf = "xmalloc:true";]]></programlisting> class.</para></listitem> </varlistentry> - <varlistentry id="arenas.purge"> - <term> - <mallctl>arenas.purge</mallctl> - (<type>unsigned</type>) - <literal>-w</literal> - </term> - <listitem><para>Purge unused dirty pages for the specified arena, or - for all arenas if none is specified.</para></listitem> - </varlistentry> - <varlistentry id="arenas.extend"> <term> <mallctl>arenas.extend</mallctl> @@ -1721,39 +1599,6 @@ malloc_conf = "xmalloc:true";]]></programlisting> </para></listitem> </varlistentry> - <varlistentry id="stats.huge.allocated"> - <term> - <mallctl>stats.huge.allocated</mallctl> - (<type>size_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Number of bytes currently allocated by huge objects. - </para></listitem> - </varlistentry> - - <varlistentry id="stats.huge.nmalloc"> - <term> - <mallctl>stats.huge.nmalloc</mallctl> - (<type>uint64_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Cumulative number of huge allocation requests. - </para></listitem> - </varlistentry> - - <varlistentry id="stats.huge.ndalloc"> - <term> - <mallctl>stats.huge.ndalloc</mallctl> - (<type>uint64_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Cumulative number of huge deallocation requests. - </para></listitem> - </varlistentry> - <varlistentry id="stats.arenas.i.dss"> <term> <mallctl>stats.arenas.<i>.dss</mallctl> @@ -1930,6 +1775,50 @@ malloc_conf = "xmalloc:true";]]></programlisting> </para></listitem> </varlistentry> + <varlistentry id="stats.arenas.i.huge.allocated"> + <term> + <mallctl>stats.arenas.<i>.huge.allocated</mallctl> + (<type>size_t</type>) + <literal>r-</literal> + [<option>--enable-stats</option>] + </term> + <listitem><para>Number of bytes currently allocated by huge objects. + </para></listitem> + </varlistentry> + + <varlistentry id="stats.arenas.i.huge.nmalloc"> + <term> + <mallctl>stats.arenas.<i>.huge.nmalloc</mallctl> + (<type>uint64_t</type>) + <literal>r-</literal> + [<option>--enable-stats</option>] + </term> + <listitem><para>Cumulative number of huge allocation requests served + directly by the arena.</para></listitem> + </varlistentry> + + <varlistentry id="stats.arenas.i.huge.ndalloc"> + <term> + <mallctl>stats.arenas.<i>.huge.ndalloc</mallctl> + (<type>uint64_t</type>) + <literal>r-</literal> + [<option>--enable-stats</option>] + </term> + <listitem><para>Cumulative number of huge deallocation requests served + directly by the arena.</para></listitem> + </varlistentry> + + <varlistentry id="stats.arenas.i.huge.nrequests"> + <term> + <mallctl>stats.arenas.<i>.huge.nrequests</mallctl> + (<type>uint64_t</type>) + <literal>r-</literal> + [<option>--enable-stats</option>] + </term> + <listitem><para>Cumulative number of huge allocation requests. + </para></listitem> + </varlistentry> + <varlistentry id="stats.arenas.i.bins.j.allocated"> <term> <mallctl>stats.arenas.<i>.bins.<j>.allocated</mallctl> @@ -2253,42 +2142,6 @@ malloc_conf = "xmalloc:true";]]></programlisting> returns the usable size of the allocation pointed to by <parameter>ptr</parameter>. </para> </refsect2> - <refsect2> - <title>Experimental API</title> - <para>The <function>allocm<parameter/></function>, - <function>rallocm<parameter/></function>, - <function>sallocm<parameter/></function>, - <function>dallocm<parameter/></function>, and - <function>nallocm<parameter/></function> functions return - <constant>ALLOCM_SUCCESS</constant> on success; otherwise they return an - error value. The <function>allocm<parameter/></function>, - <function>rallocm<parameter/></function>, and - <function>nallocm<parameter/></function> functions will fail if: - <variablelist> - <varlistentry> - <term><errorname>ALLOCM_ERR_OOM</errorname></term> - - <listitem><para>Out of memory. Insufficient contiguous memory was - available to service the allocation request. The - <function>allocm<parameter/></function> function additionally sets - <parameter>*ptr</parameter> to <constant>NULL</constant>, whereas - the <function>rallocm<parameter/></function> function leaves - <constant>*ptr</constant> unmodified.</para></listitem> - </varlistentry> - </variablelist> - The <function>rallocm<parameter/></function> function will also - fail if: - <variablelist> - <varlistentry> - <term><errorname>ALLOCM_ERR_NOT_MOVED</errorname></term> - - <listitem><para><constant>ALLOCM_NO_MOVE</constant> was specified, - but the reallocation request could not be serviced without moving - the object.</para></listitem> - </varlistentry> - </variablelist> - </para> - </refsect2> </refsect1> <refsect1 id="environment"> <title>ENVIRONMENT</title> diff --git a/src/jemalloc/include/jemalloc/internal/arena.h b/src/jemalloc/include/jemalloc/internal/arena.h index 9d000c03decbde17338f9c205f21b370854d7f7f..2a2145293cf5428a0b50435abe35b63f7dce83d6 100644 --- a/src/jemalloc/include/jemalloc/internal/arena.h +++ b/src/jemalloc/include/jemalloc/internal/arena.h @@ -110,7 +110,6 @@ struct arena_chunk_map_s { * p : run page offset * s : run size * n : binind for size class; large objects set these to BININD_INVALID - * except for promoted allocations (see prof_promote) * x : don't care * - : 0 * + : 1 @@ -216,8 +215,6 @@ struct arena_run_s { * | ... | * bitmap_offset | bitmap | * | ... | - * ctx0_offset | ctx map | - * | ... | * |--------------------| * | redzone | * reg0_offset | region 0 | @@ -270,12 +267,6 @@ struct arena_bin_info_s { */ bitmap_info_t bitmap_info; - /* - * Offset of first (prof_ctx_t *) in a run header for this bin's size - * class, or 0 if (config_prof == false || opt_prof == false). - */ - uint32_t ctx0_offset; - /* Offset of first region in a run for this bin's size class. */ uint32_t reg0_offset; }; @@ -312,6 +303,9 @@ struct arena_s { /* This arena's index within the arenas array. */ unsigned ind; + /* This arena's pool. */ + pool_t *pool; + /* * Number of threads currently assigned to this arena. This field is * protected by arenas_lock. @@ -354,7 +348,7 @@ struct arena_s { */ arena_chunk_t *spare; - /* Number of pages in active runs. */ + /* Number of pages in active runs and huge regions. */ size_t nactive; /* @@ -379,6 +373,12 @@ struct arena_s { */ arena_avail_tree_t runs_avail; + /* + * user-configureable chunk allocation and deallocation functions. + */ + chunk_alloc_t *chunk_alloc; + chunk_dalloc_t *chunk_dalloc; + /* bins is used to store trees of free regions. */ arena_bin_t bins[NBINS]; }; @@ -389,18 +389,26 @@ struct arena_s { extern ssize_t opt_lg_dirty_mult; /* - * small_size2bin is a compact lookup table that rounds request sizes up to + * small_size2bin_tab is a compact lookup table that rounds request sizes up to * size classes. In order to reduce cache footprint, the table is compressed, - * and all accesses are via the SMALL_SIZE2BIN macro. + * and all accesses are via small_size2bin(). + */ +extern uint8_t const small_size2bin_tab[]; +/* + * small_bin2size_tab duplicates information in arena_bin_info, but in a const + * array, for which it is easier for the compiler to optimize repeated + * dereferences. */ -extern uint8_t const small_size2bin[]; -#define SMALL_SIZE2BIN(s) (small_size2bin[(s-1) >> LG_TINY_MIN]) +extern uint32_t const small_bin2size_tab[NBINS]; extern arena_bin_info_t arena_bin_info[NBINS]; /* Number of large size classes. */ #define nlclasses (chunk_npages - map_bias) +void *arena_chunk_alloc_huge(arena_t *arena, size_t size, size_t alignment, + bool *zero); +void arena_chunk_dalloc_huge(arena_t *arena, void *chunk, size_t size); void arena_purge_all(arena_t *arena); void arena_tcache_fill_small(arena_t *arena, tcache_bin_t *tbin, size_t binind, uint64_t prof_accumbytes); @@ -443,11 +451,11 @@ void *arena_ralloc(arena_t *arena, void *ptr, size_t oldsize, size_t size, size_t extra, size_t alignment, bool zero, bool try_tcache_alloc, bool try_tcache_dalloc); dss_prec_t arena_dss_prec_get(arena_t *arena); -void arena_dss_prec_set(arena_t *arena, dss_prec_t dss_prec); +bool arena_dss_prec_set(arena_t *arena, dss_prec_t dss_prec); void arena_stats_merge(arena_t *arena, const char **dss, size_t *nactive, size_t *ndirty, arena_stats_t *astats, malloc_bin_stats_t *bstats, malloc_large_stats_t *lstats); -bool arena_new(arena_t *arena, unsigned ind); +bool arena_new(pool_t *pool, arena_t *arena, unsigned ind); void arena_boot(void); void arena_prefork(arena_t *arena); void arena_postfork_parent(arena_t *arena); @@ -458,6 +466,15 @@ void arena_postfork_child(arena_t *arena); #ifdef JEMALLOC_H_INLINES #ifndef JEMALLOC_ENABLE_INLINE +size_t small_size2bin_compute(size_t size); +size_t small_size2bin_lookup(size_t size); +size_t small_size2bin(size_t size); +size_t small_bin2size_compute(size_t binind); +size_t small_bin2size_lookup(size_t binind); +size_t small_bin2size(size_t binind); +size_t small_s2u_compute(size_t size); +size_t small_s2u_lookup(size_t size); +size_t small_s2u(size_t size); arena_chunk_map_t *arena_mapp_get(arena_chunk_t *chunk, size_t pageind); size_t *arena_mapbitsp_get(arena_chunk_t *chunk, size_t pageind); size_t arena_mapbitsp_read(size_t *mapbitsp); @@ -492,15 +509,156 @@ size_t arena_bin_index(arena_t *arena, arena_bin_t *bin); unsigned arena_run_regind(arena_run_t *run, arena_bin_info_t *bin_info, const void *ptr); prof_ctx_t *arena_prof_ctx_get(const void *ptr); -void arena_prof_ctx_set(const void *ptr, size_t usize, prof_ctx_t *ctx); +void arena_prof_ctx_set(const void *ptr, prof_ctx_t *ctx); void *arena_malloc(arena_t *arena, size_t size, bool zero, bool try_tcache); size_t arena_salloc(const void *ptr, bool demote); -void arena_dalloc(arena_t *arena, arena_chunk_t *chunk, void *ptr, - bool try_tcache); +void arena_dalloc(arena_chunk_t *chunk, void *ptr, bool try_tcache); #endif #if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_ARENA_C_)) # ifdef JEMALLOC_ARENA_INLINE_A +JEMALLOC_INLINE size_t +small_size2bin_compute(size_t size) +{ +#if (NTBINS != 0) + if (size <= (ZU(1) << LG_TINY_MAXCLASS)) { + size_t lg_tmin = LG_TINY_MAXCLASS - NTBINS + 1; + size_t lg_ceil = lg_floor(pow2_ceil(size)); + return (lg_ceil < lg_tmin ? 0 : lg_ceil - lg_tmin); + } else +#endif + { + size_t x = lg_floor((size<<1)-1); + size_t shift = (x < LG_SIZE_CLASS_GROUP + LG_QUANTUM) ? 0 : + x - (LG_SIZE_CLASS_GROUP + LG_QUANTUM); + size_t grp = shift << LG_SIZE_CLASS_GROUP; + + size_t lg_delta = (x < LG_SIZE_CLASS_GROUP + LG_QUANTUM + 1) + ? LG_QUANTUM : x - LG_SIZE_CLASS_GROUP - 1; + + size_t delta_inverse_mask = ZI(-1) << lg_delta; + size_t mod = ((((size-1) & delta_inverse_mask) >> lg_delta)) & + ((ZU(1) << LG_SIZE_CLASS_GROUP) - 1); + + size_t bin = NTBINS + grp + mod; + return (bin); + } +} + +JEMALLOC_ALWAYS_INLINE size_t +small_size2bin_lookup(size_t size) +{ + + assert(size <= LOOKUP_MAXCLASS); + { + size_t ret = ((size_t)(small_size2bin_tab[(size-1) >> + LG_TINY_MIN])); + assert(ret == small_size2bin_compute(size)); + return (ret); + } +} + +JEMALLOC_ALWAYS_INLINE size_t +small_size2bin(size_t size) +{ + + assert(size > 0); + if (size <= LOOKUP_MAXCLASS) + return (small_size2bin_lookup(size)); + else + return (small_size2bin_compute(size)); +} + +JEMALLOC_INLINE size_t +small_bin2size_compute(size_t binind) +{ +#if (NTBINS > 0) + if (binind < NTBINS) + return (ZU(1) << (LG_TINY_MAXCLASS - NTBINS + 1 + binind)); + else +#endif + { + size_t reduced_binind = binind - NTBINS; + size_t grp = reduced_binind >> LG_SIZE_CLASS_GROUP; + size_t mod = reduced_binind & ((ZU(1) << LG_SIZE_CLASS_GROUP) - + 1); + + size_t grp_size_mask = ~((!!grp)-1); + size_t grp_size = ((ZU(1) << (LG_QUANTUM + + (LG_SIZE_CLASS_GROUP-1))) << grp) & grp_size_mask; + + size_t shift = (grp == 0) ? 1 : grp; + size_t lg_delta = shift + (LG_QUANTUM-1); + size_t mod_size = (mod+1) << lg_delta; + + size_t usize = grp_size + mod_size; + return (usize); + } +} + +JEMALLOC_ALWAYS_INLINE size_t +small_bin2size_lookup(size_t binind) +{ + + assert(binind < NBINS); + { + size_t ret = ((size_t)(small_bin2size_tab[binind])); + assert(ret == small_bin2size_compute(binind)); + return (ret); + } +} + +JEMALLOC_ALWAYS_INLINE size_t +small_bin2size(size_t binind) +{ + + return (small_bin2size_lookup(binind)); +} + +JEMALLOC_ALWAYS_INLINE size_t +small_s2u_compute(size_t size) +{ +#if (NTBINS > 0) + if (size <= (ZU(1) << LG_TINY_MAXCLASS)) { + size_t lg_tmin = LG_TINY_MAXCLASS - NTBINS + 1; + size_t lg_ceil = lg_floor(pow2_ceil(size)); + return (lg_ceil < lg_tmin ? (ZU(1) << lg_tmin) : + (ZU(1) << lg_ceil)); + } else +#endif + { + size_t x = lg_floor((size<<1)-1); + size_t lg_delta = (x < LG_SIZE_CLASS_GROUP + LG_QUANTUM + 1) + ? LG_QUANTUM : x - LG_SIZE_CLASS_GROUP - 1; + size_t delta = ZU(1) << lg_delta; + size_t delta_mask = delta - 1; + size_t usize = (size + delta_mask) & ~delta_mask; + return (usize); + } +} + +JEMALLOC_ALWAYS_INLINE size_t +small_s2u_lookup(size_t size) +{ + size_t ret = (small_bin2size(small_size2bin(size))); + + assert(ret == small_s2u_compute(size)); + return (ret); +} + +JEMALLOC_ALWAYS_INLINE size_t +small_s2u(size_t size) +{ + + assert(size > 0); + if (size <= LOOKUP_MAXCLASS) + return (small_s2u_lookup(size)); + else + return (small_s2u_compute(size)); +} +# endif /* JEMALLOC_ARENA_INLINE_A */ + +# ifdef JEMALLOC_ARENA_INLINE_B JEMALLOC_ALWAYS_INLINE arena_chunk_map_t * arena_mapp_get(arena_chunk_t *chunk, size_t pageind) { @@ -782,9 +940,9 @@ arena_ptr_small_binind_get(const void *ptr, size_t mapbits) return (binind); } -# endif /* JEMALLOC_ARENA_INLINE_A */ +# endif /* JEMALLOC_ARENA_INLINE_B */ -# ifdef JEMALLOC_ARENA_INLINE_B +# ifdef JEMALLOC_ARENA_INLINE_C JEMALLOC_INLINE size_t arena_bin_index(arena_t *arena, arena_bin_t *bin) { @@ -815,7 +973,7 @@ arena_run_regind(arena_run_t *run, arena_bin_info_t *bin_info, const void *ptr) /* Rescale (factor powers of 2 out of the numerator and denominator). */ interval = bin_info->reg_interval; - shift = ffs(interval) - 1; + shift = jemalloc_ffs(interval) - 1; diff >>= shift; interval >>= shift; @@ -880,31 +1038,16 @@ arena_prof_ctx_get(const void *ptr) pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE; mapbits = arena_mapbits_get(chunk, pageind); assert((mapbits & CHUNK_MAP_ALLOCATED) != 0); - if ((mapbits & CHUNK_MAP_LARGE) == 0) { - if (prof_promote) - ret = (prof_ctx_t *)(uintptr_t)1U; - else { - arena_run_t *run = (arena_run_t *)((uintptr_t)chunk + - (uintptr_t)((pageind - (mapbits >> LG_PAGE)) << - LG_PAGE)); - size_t binind = arena_ptr_small_binind_get(ptr, - mapbits); - arena_bin_info_t *bin_info = &arena_bin_info[binind]; - unsigned regind; - - regind = arena_run_regind(run, bin_info, ptr); - ret = *(prof_ctx_t **)((uintptr_t)run + - bin_info->ctx0_offset + (regind * - sizeof(prof_ctx_t *))); - } - } else + if ((mapbits & CHUNK_MAP_LARGE) == 0) + ret = (prof_ctx_t *)(uintptr_t)1U; + else ret = arena_mapp_get(chunk, pageind)->prof_ctx; return (ret); } JEMALLOC_INLINE void -arena_prof_ctx_set(const void *ptr, size_t usize, prof_ctx_t *ctx) +arena_prof_ctx_set(const void *ptr, prof_ctx_t *ctx) { arena_chunk_t *chunk; size_t pageind; @@ -917,43 +1060,21 @@ arena_prof_ctx_set(const void *ptr, size_t usize, prof_ctx_t *ctx) pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE; assert(arena_mapbits_allocated_get(chunk, pageind) != 0); - if (usize > SMALL_MAXCLASS || (prof_promote && - ((uintptr_t)ctx != (uintptr_t)1U || arena_mapbits_large_get(chunk, - pageind) != 0))) { - assert(arena_mapbits_large_get(chunk, pageind) != 0); + if (arena_mapbits_large_get(chunk, pageind) != 0) arena_mapp_get(chunk, pageind)->prof_ctx = ctx; - } else { - assert(arena_mapbits_large_get(chunk, pageind) == 0); - if (prof_promote == false) { - size_t mapbits = arena_mapbits_get(chunk, pageind); - arena_run_t *run = (arena_run_t *)((uintptr_t)chunk + - (uintptr_t)((pageind - (mapbits >> LG_PAGE)) << - LG_PAGE)); - size_t binind; - arena_bin_info_t *bin_info; - unsigned regind; - - binind = arena_ptr_small_binind_get(ptr, mapbits); - bin_info = &arena_bin_info[binind]; - regind = arena_run_regind(run, bin_info, ptr); - - *((prof_ctx_t **)((uintptr_t)run + - bin_info->ctx0_offset + (regind * sizeof(prof_ctx_t - *)))) = ctx; - } - } } JEMALLOC_ALWAYS_INLINE void * arena_malloc(arena_t *arena, size_t size, bool zero, bool try_tcache) { tcache_t *tcache; + pool_t *pool = arena->pool; assert(size != 0); assert(size <= arena_maxclass); if (size <= SMALL_MAXCLASS) { - if (try_tcache && (tcache = tcache_get(true)) != NULL) + if (try_tcache && (tcache = tcache_get(pool, true)) != NULL) return (tcache_alloc_small(tcache, size, zero)); else { return (arena_malloc_small(choose_arena(arena), size, @@ -965,7 +1086,7 @@ arena_malloc(arena_t *arena, size_t size, bool zero, bool try_tcache) * infinite recursion during tcache initialization. */ if (try_tcache && size <= tcache_maxclass && (tcache = - tcache_get(true)) != NULL) + tcache_get(pool, true)) != NULL) return (tcache_alloc_large(tcache, size, zero)); else { return (arena_malloc_large(choose_arena(arena), size, @@ -984,13 +1105,12 @@ arena_salloc(const void *ptr, bool demote) assert(ptr != NULL); assert(CHUNK_ADDR2BASE(ptr) != ptr); - chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE; assert(arena_mapbits_allocated_get(chunk, pageind) != 0); binind = arena_mapbits_binind_get(chunk, pageind); if (binind == BININD_INVALID || (config_prof && demote == false && - prof_promote && arena_mapbits_large_get(chunk, pageind) != 0)) { + arena_mapbits_large_get(chunk, pageind) != 0)) { /* * Large allocation. In the common case (demote == true), and * as this is an inline function, most callers will only end up @@ -1008,27 +1128,22 @@ arena_salloc(const void *ptr, bool demote) assert(arena_mapbits_dirty_get(chunk, pageind) == arena_mapbits_dirty_get(chunk, pageind+(ret>>LG_PAGE)-1)); } else { - /* - * Small allocation (possibly promoted to a large object due to - * prof_promote). - */ + /* Small allocation (possibly promoted to a large object). */ assert(arena_mapbits_large_get(chunk, pageind) != 0 || arena_ptr_small_binind_get(ptr, arena_mapbits_get(chunk, pageind)) == binind); - ret = arena_bin_info[binind].reg_size; + ret = small_bin2size(binind); } return (ret); } JEMALLOC_ALWAYS_INLINE void -arena_dalloc(arena_t *arena, arena_chunk_t *chunk, void *ptr, bool try_tcache) +arena_dalloc(arena_chunk_t *chunk, void *ptr, bool try_tcache) { size_t pageind, mapbits; tcache_t *tcache; - assert(arena != NULL); - assert(chunk->arena == arena); assert(ptr != NULL); assert(CHUNK_ADDR2BASE(ptr) != ptr); @@ -1037,26 +1152,26 @@ arena_dalloc(arena_t *arena, arena_chunk_t *chunk, void *ptr, bool try_tcache) assert(arena_mapbits_allocated_get(chunk, pageind) != 0); if ((mapbits & CHUNK_MAP_LARGE) == 0) { /* Small allocation. */ - if (try_tcache && (tcache = tcache_get(false)) != NULL) { + if (try_tcache && (tcache = tcache_get(chunk->arena->pool, false)) != NULL) { size_t binind; binind = arena_ptr_small_binind_get(ptr, mapbits); tcache_dalloc_small(tcache, ptr, binind); } else - arena_dalloc_small(arena, chunk, ptr, pageind); + arena_dalloc_small(chunk->arena, chunk, ptr, pageind); } else { size_t size = arena_mapbits_large_size_get(chunk, pageind); assert(((uintptr_t)ptr & PAGE_MASK) == 0); if (try_tcache && size <= tcache_maxclass && (tcache = - tcache_get(false)) != NULL) { + tcache_get(chunk->arena->pool, false)) != NULL) { tcache_dalloc_large(tcache, ptr, size); } else - arena_dalloc_large(arena, chunk, ptr); + arena_dalloc_large(chunk->arena, chunk, ptr); } } -# endif /* JEMALLOC_ARENA_INLINE_B */ +# endif /* JEMALLOC_ARENA_INLINE_C */ #endif #endif /* JEMALLOC_H_INLINES */ diff --git a/src/jemalloc/include/jemalloc/internal/base.h b/src/jemalloc/include/jemalloc/internal/base.h index 9cf75ffb0b3c1d4e9ee5b5c855127f4112538872..d29115501562fdb36817f774362ac5ba1571a146 100644 --- a/src/jemalloc/include/jemalloc/internal/base.h +++ b/src/jemalloc/include/jemalloc/internal/base.h @@ -9,14 +9,15 @@ /******************************************************************************/ #ifdef JEMALLOC_H_EXTERNS -void *base_alloc(size_t size); -void *base_calloc(size_t number, size_t size); -extent_node_t *base_node_alloc(void); -void base_node_dealloc(extent_node_t *node); -bool base_boot(void); -void base_prefork(void); -void base_postfork_parent(void); -void base_postfork_child(void); +void *base_alloc(pool_t *pool, size_t size); +void *base_calloc(pool_t *pool, size_t number, size_t size); +extent_node_t *base_node_alloc(pool_t *pool); +void base_node_dalloc(pool_t *pool, extent_node_t *node); +size_t base_node_prealloc(pool_t *pool, size_t number); +bool base_boot(pool_t *pool); +void base_prefork(pool_t *pool); +void base_postfork_parent(pool_t *pool); +void base_postfork_child(pool_t *pool); #endif /* JEMALLOC_H_EXTERNS */ /******************************************************************************/ diff --git a/src/jemalloc/include/jemalloc/internal/bitmap.h b/src/jemalloc/include/jemalloc/internal/bitmap.h index 605ebac58c17a2650cd7cbe65a9b0ae795dee7f6..6db4ab703d7ecfebf4b06e5681750a38d7df0862 100644 --- a/src/jemalloc/include/jemalloc/internal/bitmap.h +++ b/src/jemalloc/include/jemalloc/internal/bitmap.h @@ -130,11 +130,11 @@ bitmap_sfu(bitmap_t *bitmap, const bitmap_info_t *binfo) i = binfo->nlevels - 1; g = bitmap[binfo->levels[i].group_offset]; - bit = ffsl(g) - 1; + bit = jemalloc_ffsl(g) - 1; while (i > 0) { i--; g = bitmap[binfo->levels[i].group_offset + bit]; - bit = (bit << LG_BITMAP_GROUP_NBITS) + (ffsl(g) - 1); + bit = (bit << LG_BITMAP_GROUP_NBITS) + (jemalloc_ffsl(g) - 1); } bitmap_set(bitmap, binfo, bit); diff --git a/src/jemalloc/include/jemalloc/internal/chunk.h b/src/jemalloc/include/jemalloc/internal/chunk.h index 87d8700dac8adad1510d3b4a1cd978d7fe6b05e4..16a6aa619891013f54d36e186e828468489aebf4 100644 --- a/src/jemalloc/include/jemalloc/internal/chunk.h +++ b/src/jemalloc/include/jemalloc/internal/chunk.h @@ -30,27 +30,27 @@ extern size_t opt_lg_chunk; extern const char *opt_dss; -/* Protects stats_chunks; currently not used for any other purpose. */ -extern malloc_mutex_t chunks_mtx; -/* Chunk statistics. */ -extern chunk_stats_t stats_chunks; - -extern rtree_t *chunks_rtree; - extern size_t chunksize; extern size_t chunksize_mask; /* (chunksize - 1). */ extern size_t chunk_npages; extern size_t map_bias; /* Number of arena chunk header pages. */ extern size_t arena_maxclass; /* Max size class for arenas. */ -void *chunk_alloc(size_t size, size_t alignment, bool base, bool *zero, - dss_prec_t dss_prec); -void chunk_unmap(void *chunk, size_t size); -void chunk_dealloc(void *chunk, size_t size, bool unmap); -bool chunk_boot(void); -void chunk_prefork(void); -void chunk_postfork_parent(void); -void chunk_postfork_child(void); +void *chunk_alloc_base(pool_t *pool, size_t size); +void *chunk_alloc_arena(chunk_alloc_t *chunk_alloc, + chunk_dalloc_t *chunk_dalloc, arena_t *arena, size_t size, + size_t alignment, bool *zero); +void *chunk_alloc_default(size_t size, size_t alignment, bool *zero, + unsigned arena_ind, pool_t *pool); +void chunk_unmap(pool_t *pool, void *chunk, size_t size); +bool chunk_dalloc_default(void *chunk, size_t size, unsigned arena_ind, pool_t *pool); +void chunk_record(pool_t *pool, extent_tree_t *chunks_szad, + extent_tree_t *chunks_ad, void *chunk, size_t size, bool zeroed); +void chunk_global_boot(); +bool chunk_boot(pool_t *pool); +void chunk_prefork(pool_t *pool); +void chunk_postfork_parent(pool_t *pool); +void chunk_postfork_child(pool_t *pool); #endif /* JEMALLOC_H_EXTERNS */ /******************************************************************************/ diff --git a/src/jemalloc/include/jemalloc/internal/chunk_mmap.h b/src/jemalloc/include/jemalloc/internal/chunk_mmap.h index f24abac753823d1e06e1cc6e5663676c7442927f..c5d5c6c0c7ac41fa42bb1766a21e959a3d1db84f 100644 --- a/src/jemalloc/include/jemalloc/internal/chunk_mmap.h +++ b/src/jemalloc/include/jemalloc/internal/chunk_mmap.h @@ -12,7 +12,7 @@ bool pages_purge(void *addr, size_t length); void *chunk_alloc_mmap(size_t size, size_t alignment, bool *zero); -bool chunk_dealloc_mmap(void *chunk, size_t size); +bool chunk_dalloc_mmap(void *chunk, size_t size); #endif /* JEMALLOC_H_EXTERNS */ /******************************************************************************/ diff --git a/src/jemalloc/include/jemalloc/internal/ctl.h b/src/jemalloc/include/jemalloc/internal/ctl.h index 0ffecc5f2a23feeba1f5dba9547eee8e63ae0a4e..fe0070c1b61249c4f0b7dccf4ce346e512a538d1 100644 --- a/src/jemalloc/include/jemalloc/internal/ctl.h +++ b/src/jemalloc/include/jemalloc/internal/ctl.h @@ -49,19 +49,11 @@ struct ctl_arena_stats_s { }; struct ctl_stats_s { - size_t allocated; - size_t active; - size_t mapped; struct { size_t current; /* stats_chunks.curchunks */ uint64_t total; /* stats_chunks.nchunks */ size_t high; /* stats_chunks.highchunks */ } chunks; - struct { - size_t allocated; /* huge_allocated */ - uint64_t nmalloc; /* huge_nmalloc */ - uint64_t ndalloc; /* huge_ndalloc */ - } huge; unsigned narenas; ctl_arena_stats_t *arenas; /* (narenas + 1) elements. */ }; diff --git a/src/jemalloc/include/jemalloc/internal/extent.h b/src/jemalloc/include/jemalloc/internal/extent.h index ba95ca816bd9a81feb9bb65c3fa69f71ce10ab28..000ef6d5aa8db198c7d77f4669bf9cf16dc7e10a 100644 --- a/src/jemalloc/include/jemalloc/internal/extent.h +++ b/src/jemalloc/include/jemalloc/internal/extent.h @@ -24,6 +24,9 @@ struct extent_node_s { /* Total region size. */ size_t size; + /* Arena from which this extent came, if any */ + arena_t *arena; + /* True if zero-filled; used by chunk recycling code. */ bool zeroed; }; diff --git a/src/jemalloc/include/jemalloc/internal/hash.h b/src/jemalloc/include/jemalloc/internal/hash.h index c7183ede82d7e846b7d27d19d98e4d5907891d25..a43bbbeccd4615ab96b00ddcf23276db76e2eb35 100644 --- a/src/jemalloc/include/jemalloc/internal/hash.h +++ b/src/jemalloc/include/jemalloc/internal/hash.h @@ -76,9 +76,9 @@ hash_fmix_64(uint64_t k) { k ^= k >> 33; - k *= QU(0xff51afd7ed558ccdLLU); + k *= KQU(0xff51afd7ed558ccd); k ^= k >> 33; - k *= QU(0xc4ceb9fe1a85ec53LLU); + k *= KQU(0xc4ceb9fe1a85ec53); k ^= k >> 33; return (k); @@ -247,8 +247,8 @@ hash_x64_128(const void *key, const int len, const uint32_t seed, uint64_t h1 = seed; uint64_t h2 = seed; - const uint64_t c1 = QU(0x87c37b91114253d5LLU); - const uint64_t c2 = QU(0x4cf5ad432745937fLLU); + const uint64_t c1 = KQU(0x87c37b91114253d5); + const uint64_t c2 = KQU(0x4cf5ad432745937f); /* body */ { diff --git a/src/jemalloc/include/jemalloc/internal/huge.h b/src/jemalloc/include/jemalloc/internal/huge.h index a2b9c779191f1eefb9f509bfbd46d6c585ca8f5e..d527d748f5941bab7d2e84af28e49dc29f451b7e 100644 --- a/src/jemalloc/include/jemalloc/internal/huge.h +++ b/src/jemalloc/include/jemalloc/internal/huge.h @@ -9,34 +9,24 @@ /******************************************************************************/ #ifdef JEMALLOC_H_EXTERNS -/* Huge allocation statistics. */ -extern uint64_t huge_nmalloc; -extern uint64_t huge_ndalloc; -extern size_t huge_allocated; - -/* Protects chunk-related data structures. */ -extern malloc_mutex_t huge_mtx; - -void *huge_malloc(size_t size, bool zero, dss_prec_t dss_prec); -void *huge_palloc(size_t size, size_t alignment, bool zero, - dss_prec_t dss_prec); +void *huge_malloc(arena_t *arena, size_t size, bool zero); +void *huge_palloc(arena_t *arena, size_t size, size_t alignment, bool zero); bool huge_ralloc_no_move(void *ptr, size_t oldsize, size_t size, size_t extra); -void *huge_ralloc(void *ptr, size_t oldsize, size_t size, size_t extra, - size_t alignment, bool zero, bool try_tcache_dalloc, dss_prec_t dss_prec); +void *huge_ralloc(arena_t *arena, void *ptr, size_t oldsize, size_t size, + size_t extra, size_t alignment, bool zero, bool try_tcache_dalloc); #ifdef JEMALLOC_JET typedef void (huge_dalloc_junk_t)(void *, size_t); extern huge_dalloc_junk_t *huge_dalloc_junk; #endif -void huge_dalloc(void *ptr, bool unmap); +void huge_dalloc(pool_t *pool, void *ptr); size_t huge_salloc(const void *ptr); -dss_prec_t huge_dss_prec_get(arena_t *arena); prof_ctx_t *huge_prof_ctx_get(const void *ptr); void huge_prof_ctx_set(const void *ptr, prof_ctx_t *ctx); -bool huge_boot(void); -void huge_prefork(void); -void huge_postfork_parent(void); -void huge_postfork_child(void); +bool huge_boot(pool_t *pool); +void huge_prefork(pool_t *pool); +void huge_postfork_parent(pool_t *pool); +void huge_postfork_child(pool_t *pool); #endif /* JEMALLOC_H_EXTERNS */ /******************************************************************************/ diff --git a/src/jemalloc/include/jemalloc/internal/jemalloc_internal.h.in b/src/jemalloc/include/jemalloc/internal/jemalloc_internal.h.in index 574bbb14186decae29948422ae19f64d4580a9da..3ce6a7e9abacd14df5ae03b45ac56b3ac24bb66d 100644 --- a/src/jemalloc/include/jemalloc/internal/jemalloc_internal.h.in +++ b/src/jemalloc/include/jemalloc/internal/jemalloc_internal.h.in @@ -1,70 +1,13 @@ #ifndef JEMALLOC_INTERNAL_H #define JEMALLOC_INTERNAL_H -#include <math.h> -#ifdef _WIN32 -# include <windows.h> -# define ENOENT ERROR_PATH_NOT_FOUND -# define EINVAL ERROR_BAD_ARGUMENTS -# define EAGAIN ERROR_OUTOFMEMORY -# define EPERM ERROR_WRITE_FAULT -# define EFAULT ERROR_INVALID_ADDRESS -# define ENOMEM ERROR_NOT_ENOUGH_MEMORY -# undef ERANGE -# define ERANGE ERROR_INVALID_DATA -#else -# include <sys/param.h> -# include <sys/mman.h> -# include <sys/syscall.h> -# if !defined(SYS_write) && defined(__NR_write) -# define SYS_write __NR_write -# endif -# include <sys/uio.h> -# include <pthread.h> -# include <errno.h> -#endif -#include <sys/types.h> - -#include <limits.h> -#ifndef SIZE_T_MAX -# define SIZE_T_MAX SIZE_MAX -#endif -#include <stdarg.h> -#include <stdbool.h> -#include <stdio.h> -#include <stdlib.h> -#include <stdint.h> -#include <stddef.h> -#ifndef offsetof -# define offsetof(type, member) ((size_t)&(((type *)NULL)->member)) -#endif -#include <inttypes.h> -#include <string.h> -#include <strings.h> -#include <ctype.h> -#ifdef _MSC_VER -# include <io.h> -typedef intptr_t ssize_t; -# define PATH_MAX 1024 -# define STDERR_FILENO 2 -# define __func__ __FUNCTION__ -/* Disable warnings about deprecated system functions */ -# pragma warning(disable: 4996) -#else -# include <unistd.h> -#endif -#include <fcntl.h> #include "jemalloc_internal_defs.h" +#include "jemalloc/internal/jemalloc_internal_decls.h" #ifdef JEMALLOC_UTRACE #include <sys/ktrace.h> #endif -#ifdef JEMALLOC_VALGRIND -#include <valgrind/valgrind.h> -#include <valgrind/memcheck.h> -#endif - #define JEMALLOC_NO_DEMANGLE #ifdef JEMALLOC_JET # define JEMALLOC_N(n) jet_##n @@ -85,7 +28,7 @@ static const bool config_debug = false #endif ; -static const bool config_dss = +static const bool have_dss = #ifdef JEMALLOC_DSS true #else @@ -127,13 +70,6 @@ static const bool config_prof_libunwind = false #endif ; -static const bool config_mremap = -#ifdef JEMALLOC_MREMAP - true -#else - false -#endif - ; static const bool config_munmap = #ifdef JEMALLOC_MUNMAP true @@ -230,7 +166,6 @@ static const bool config_ivsalloc = #include "jemalloc/internal/jemalloc_internal_macros.h" #define MALLOCX_LG_ALIGN_MASK ((int)0x3f) -#define ALLOCM_LG_ALIGN_MASK ((int)0x3f) /* Smallest size class to support. */ #define LG_TINY_MIN 3 @@ -280,6 +215,9 @@ static const bool config_ivsalloc = # ifdef __tile__ # define LG_QUANTUM 4 # endif +# ifdef __le32__ +# define LG_QUANTUM 4 +# endif # ifndef LG_QUANTUM # error "No LG_QUANTUM definition for architecture; specify via CPPFLAGS" # endif @@ -358,86 +296,12 @@ static const bool config_ivsalloc = # endif # endif # define VARIABLE_ARRAY(type, name, count) \ - type *name = alloca(sizeof(type) * count) -#else -# define VARIABLE_ARRAY(type, name, count) type name[count] -#endif - -#ifdef JEMALLOC_VALGRIND -/* - * The JEMALLOC_VALGRIND_*() macros must be macros rather than functions - * so that when Valgrind reports errors, there are no extra stack frames - * in the backtraces. - * - * The size that is reported to valgrind must be consistent through a chain of - * malloc..realloc..realloc calls. Request size isn't recorded anywhere in - * jemalloc, so it is critical that all callers of these macros provide usize - * rather than request size. As a result, buffer overflow detection is - * technically weakened for the standard API, though it is generally accepted - * practice to consider any extra bytes reported by malloc_usable_size() as - * usable space. - */ -#define JEMALLOC_VALGRIND_MALLOC(cond, ptr, usize, zero) do { \ - if (config_valgrind && opt_valgrind && cond) \ - VALGRIND_MALLOCLIKE_BLOCK(ptr, usize, p2rz(ptr), zero); \ -} while (0) -#define JEMALLOC_VALGRIND_REALLOC(ptr, usize, old_ptr, old_usize, \ - old_rzsize, zero) do { \ - if (config_valgrind && opt_valgrind) { \ - size_t rzsize = p2rz(ptr); \ - \ - if (ptr == old_ptr) { \ - VALGRIND_RESIZEINPLACE_BLOCK(ptr, old_usize, \ - usize, rzsize); \ - if (zero && old_usize < usize) { \ - VALGRIND_MAKE_MEM_DEFINED( \ - (void *)((uintptr_t)ptr + \ - old_usize), usize - old_usize); \ - } \ - } else { \ - if (old_ptr != NULL) { \ - VALGRIND_FREELIKE_BLOCK(old_ptr, \ - old_rzsize); \ - } \ - if (ptr != NULL) { \ - size_t copy_size = (old_usize < usize) \ - ? old_usize : usize; \ - size_t tail_size = usize - copy_size; \ - VALGRIND_MALLOCLIKE_BLOCK(ptr, usize, \ - rzsize, false); \ - if (copy_size > 0) { \ - VALGRIND_MAKE_MEM_DEFINED(ptr, \ - copy_size); \ - } \ - if (zero && tail_size > 0) { \ - VALGRIND_MAKE_MEM_DEFINED( \ - (void *)((uintptr_t)ptr + \ - copy_size), tail_size); \ - } \ - } \ - } \ - } \ -} while (0) -#define JEMALLOC_VALGRIND_FREE(ptr, rzsize) do { \ - if (config_valgrind && opt_valgrind) \ - VALGRIND_FREELIKE_BLOCK(ptr, rzsize); \ -} while (0) + type *name = alloca(sizeof(type) * (count)) #else -#define RUNNING_ON_VALGRIND ((unsigned)0) -#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \ - do {} while (0) -#define VALGRIND_RESIZEINPLACE_BLOCK(addr, oldSizeB, newSizeB, rzB) \ - do {} while (0) -#define VALGRIND_FREELIKE_BLOCK(addr, rzB) do {} while (0) -#define VALGRIND_MAKE_MEM_NOACCESS(_qzz_addr, _qzz_len) do {} while (0) -#define VALGRIND_MAKE_MEM_UNDEFINED(_qzz_addr, _qzz_len) do {} while (0) -#define VALGRIND_MAKE_MEM_DEFINED(_qzz_addr, _qzz_len) do {} while (0) -#define JEMALLOC_VALGRIND_MALLOC(cond, ptr, usize, zero) do {} while (0) -#define JEMALLOC_VALGRIND_REALLOC(ptr, usize, old_ptr, old_usize, \ - old_rzsize, zero) do {} while (0) -#define JEMALLOC_VALGRIND_FREE(ptr, rzsize) do {} while (0) +# define VARIABLE_ARRAY(type, name, count) type name[(count)] #endif +#include "jemalloc/internal/valgrind.h" #include "jemalloc/internal/util.h" #include "jemalloc/internal/atomic.h" #include "jemalloc/internal/prng.h" @@ -459,11 +323,14 @@ static const bool config_ivsalloc = #include "jemalloc/internal/hash.h" #include "jemalloc/internal/quarantine.h" #include "jemalloc/internal/prof.h" +#include "jemalloc/internal/pool.h" +#include "jemalloc/internal/vector.h" #undef JEMALLOC_H_TYPES /******************************************************************************/ #define JEMALLOC_H_STRUCTS +#include "jemalloc/internal/valgrind.h" #include "jemalloc/internal/util.h" #include "jemalloc/internal/atomic.h" #include "jemalloc/internal/prng.h" @@ -485,6 +352,8 @@ static const bool config_ivsalloc = #include "jemalloc/internal/hash.h" #include "jemalloc/internal/quarantine.h" #include "jemalloc/internal/prof.h" +#include "jemalloc/internal/pool.h" +#include "jemalloc/internal/vector.h" typedef struct { uint64_t allocated; @@ -505,35 +374,30 @@ extern bool opt_junk; extern size_t opt_quarantine; extern bool opt_redzone; extern bool opt_utrace; -extern bool opt_valgrind; extern bool opt_xmalloc; extern bool opt_zero; extern size_t opt_narenas; +extern bool in_valgrind; + /* Number of CPUs. */ extern unsigned ncpus; -/* Protects arenas initialization (arenas, arenas_total). */ -extern malloc_mutex_t arenas_lock; -/* - * Arenas that are used to service external requests. Not all elements of the - * arenas array are necessarily used; arenas are created lazily as needed. - * - * arenas[0..narenas_auto) are used for automatic multiplexing of threads and - * arenas. arenas[narenas_auto..narenas_total) are only used if the application - * takes some action to create them and allocate from them. - */ -extern arena_t **arenas; -extern unsigned narenas_total; -extern unsigned narenas_auto; /* Read-only after initialization. */ +extern unsigned npools; +extern pool_t *pools[POOLS_MAX]; -arena_t *arenas_extend(unsigned ind); +extern malloc_mutex_t pools_lock; +extern void *(*je_base_malloc)(size_t); +extern void (*je_base_free)(void *); + +arena_t *arenas_extend(pool_t *pool, unsigned ind); void arenas_cleanup(void *arg); -arena_t *choose_arena_hard(void); +arena_t *choose_arena_hard(pool_t *pool); void jemalloc_prefork(void); void jemalloc_postfork_parent(void); void jemalloc_postfork_child(void); +#include "jemalloc/internal/valgrind.h" #include "jemalloc/internal/util.h" #include "jemalloc/internal/atomic.h" #include "jemalloc/internal/prng.h" @@ -555,11 +419,14 @@ void jemalloc_postfork_child(void); #include "jemalloc/internal/hash.h" #include "jemalloc/internal/quarantine.h" #include "jemalloc/internal/prof.h" +#include "jemalloc/internal/pool.h" +#include "jemalloc/internal/vector.h" #undef JEMALLOC_H_EXTERNS /******************************************************************************/ #define JEMALLOC_H_INLINES +#include "jemalloc/internal/valgrind.h" #include "jemalloc/internal/util.h" #include "jemalloc/internal/atomic.h" #include "jemalloc/internal/prng.h" @@ -575,12 +442,20 @@ void jemalloc_postfork_child(void); #include "jemalloc/internal/chunk.h" #include "jemalloc/internal/huge.h" +/* + * Include arena.h the first time in order to provide inline functions for this + * header's inlines. + */ +#define JEMALLOC_ARENA_INLINE_A +#include "jemalloc/internal/arena.h" +#undef JEMALLOC_ARENA_INLINE_A + #ifndef JEMALLOC_ENABLE_INLINE -malloc_tsd_protos(JEMALLOC_ATTR(unused), arenas, arena_t *) +malloc_tsd_protos(JEMALLOC_ATTR(unused), arenas, tsd_pool_t) size_t s2u(size_t size); size_t sa2u(size_t size, size_t alignment); -unsigned narenas_total_get(void); +unsigned narenas_total_get(pool_t *pool); arena_t *choose_arena(arena_t *arena); #endif @@ -589,10 +464,19 @@ arena_t *choose_arena(arena_t *arena); * Map of pthread_self() --> arenas[???], used for selecting an arena to use * for allocations. */ -malloc_tsd_externs(arenas, arena_t *) -malloc_tsd_funcs(JEMALLOC_ALWAYS_INLINE, arenas, arena_t *, NULL, +malloc_tsd_externs(arenas, tsd_pool_t) +malloc_tsd_funcs(JEMALLOC_ALWAYS_INLINE, arenas, tsd_pool_t, NULL, arenas_cleanup) + +/* + * Check if the arena is dummy. + */ +JEMALLOC_ALWAYS_INLINE bool +is_arena_dummy(arena_t *arena) { + return (arena->ind == ARENA_DUMMY_IND); +} + /* * Compute usable size that would result from allocating an object with the * specified size. @@ -602,7 +486,7 @@ s2u(size_t size) { if (size <= SMALL_MAXCLASS) - return (arena_bin_info[SMALL_SIZE2BIN(size)].reg_size); + return (small_s2u(size)); if (size <= arena_maxclass) return (PAGE_CEILING(size)); return (CHUNK_CEILING(size)); @@ -645,7 +529,7 @@ sa2u(size_t size, size_t alignment) if (usize <= arena_maxclass && alignment <= PAGE) { if (usize <= SMALL_MAXCLASS) - return (arena_bin_info[SMALL_SIZE2BIN(usize)].reg_size); + return (small_s2u(usize)); return (PAGE_CEILING(usize)); } else { size_t run_size; @@ -687,28 +571,37 @@ sa2u(size_t size, size_t alignment) } JEMALLOC_INLINE unsigned -narenas_total_get(void) +narenas_total_get(pool_t *pool) { unsigned narenas; - - malloc_mutex_lock(&arenas_lock); - narenas = narenas_total; - malloc_mutex_unlock(&arenas_lock); + malloc_mutex_lock(&pool->arenas_lock); + narenas = pool->narenas_total; + malloc_mutex_unlock(&pool->arenas_lock); return (narenas); } -/* Choose an arena based on a per-thread value. */ +/* + * Choose an arena based on a per-thread value. + * Arena pointer must be either a valid arena pointer or a dummy arena with + * pool field filled. + */ JEMALLOC_INLINE arena_t * choose_arena(arena_t *arena) { arena_t *ret; + tsd_pool_t *tsd; + pool_t *pool; - if (arena != NULL) + if (!is_arena_dummy(arena)) return (arena); - if ((ret = *arenas_tsd_get()) == NULL) { - ret = choose_arena_hard(); + pool = arena->pool; + tsd = arenas_tsd_get(); + + if ( (tsd->seqno[pool->pool_id] != pool->seqno) || + (ret = tsd->arenas[pool->pool_id]) == NULL) { + ret = choose_arena_hard(pool); assert(ret != NULL); } @@ -719,27 +612,30 @@ choose_arena(arena_t *arena) #include "jemalloc/internal/bitmap.h" #include "jemalloc/internal/rtree.h" /* - * Include arena.h twice in order to resolve circular dependencies with - * tcache.h. + * Include arena.h the second and third times in order to resolve circular + * dependencies with tcache.h. */ -#define JEMALLOC_ARENA_INLINE_A -#include "jemalloc/internal/arena.h" -#undef JEMALLOC_ARENA_INLINE_A -#include "jemalloc/internal/tcache.h" #define JEMALLOC_ARENA_INLINE_B #include "jemalloc/internal/arena.h" #undef JEMALLOC_ARENA_INLINE_B +#include "jemalloc/internal/tcache.h" +#define JEMALLOC_ARENA_INLINE_C +#include "jemalloc/internal/arena.h" +#undef JEMALLOC_ARENA_INLINE_C #include "jemalloc/internal/hash.h" #include "jemalloc/internal/quarantine.h" #ifndef JEMALLOC_ENABLE_INLINE void *imalloct(size_t size, bool try_tcache, arena_t *arena); void *imalloc(size_t size); +void *pool_imalloc(pool_t *pool, size_t size); void *icalloct(size_t size, bool try_tcache, arena_t *arena); void *icalloc(size_t size); +void *pool_icalloc(pool_t *pool, size_t size); void *ipalloct(size_t usize, size_t alignment, bool zero, bool try_tcache, arena_t *arena); void *ipalloc(size_t usize, size_t alignment, bool zero); +void *pool_ipalloc(pool_t *pool, size_t usize, size_t alignment, bool zero); size_t isalloc(const void *ptr, bool demote); size_t ivsalloc(const void *ptr, bool demote); size_t u2rz(size_t usize); @@ -755,6 +651,8 @@ void *iralloct(void *ptr, size_t size, size_t extra, size_t alignment, bool zero, bool try_tcache_alloc, bool try_tcache_dalloc, arena_t *arena); void *iralloc(void *ptr, size_t size, size_t extra, size_t alignment, bool zero); +void *pool_iralloc(pool_t *pool, void *ptr, size_t size, size_t extra, + size_t alignment, bool zero); bool ixalloc(void *ptr, size_t size, size_t extra, size_t alignment, bool zero); malloc_tsd_protos(JEMALLOC_ATTR(unused), thread_allocated, thread_allocated_t) @@ -764,37 +662,53 @@ malloc_tsd_protos(JEMALLOC_ATTR(unused), thread_allocated, thread_allocated_t) JEMALLOC_ALWAYS_INLINE void * imalloct(size_t size, bool try_tcache, arena_t *arena) { - assert(size != 0); if (size <= arena_maxclass) return (arena_malloc(arena, size, false, try_tcache)); else - return (huge_malloc(size, false, huge_dss_prec_get(arena))); + return (huge_malloc(arena, size, false)); } JEMALLOC_ALWAYS_INLINE void * imalloc(size_t size) { + arena_t dummy; + DUMMY_ARENA_INITIALIZE(dummy, pools[0]); + return (imalloct(size, true, &dummy)); +} - return (imalloct(size, true, NULL)); +JEMALLOC_ALWAYS_INLINE void * +pool_imalloc(pool_t *pool, size_t size) +{ + arena_t dummy; + DUMMY_ARENA_INITIALIZE(dummy, pool); + return (imalloct(size, true, &dummy)); } JEMALLOC_ALWAYS_INLINE void * icalloct(size_t size, bool try_tcache, arena_t *arena) { - if (size <= arena_maxclass) return (arena_malloc(arena, size, true, try_tcache)); else - return (huge_malloc(size, true, huge_dss_prec_get(arena))); + return (huge_malloc(arena, size, true)); } JEMALLOC_ALWAYS_INLINE void * icalloc(size_t size) { + arena_t dummy; + DUMMY_ARENA_INITIALIZE(dummy, pools[0]); + return (icalloct(size, true, &dummy)); +} - return (icalloct(size, true, NULL)); +JEMALLOC_ALWAYS_INLINE void * +pool_icalloc(pool_t *pool, size_t size) +{ + arena_t dummy; + DUMMY_ARENA_INITIALIZE(dummy, pool); + return (icalloct(size, true, &dummy)); } JEMALLOC_ALWAYS_INLINE void * @@ -813,9 +727,9 @@ ipalloct(size_t usize, size_t alignment, bool zero, bool try_tcache, ret = arena_palloc(choose_arena(arena), usize, alignment, zero); } else if (alignment <= chunksize) - ret = huge_malloc(usize, zero, huge_dss_prec_get(arena)); + ret = huge_malloc(arena, usize, zero); else - ret = huge_palloc(usize, alignment, zero, huge_dss_prec_get(arena)); + ret = huge_palloc(arena, usize, alignment, zero); } assert(ALIGNMENT_ADDR2BASE(ret, alignment) == ret); @@ -825,8 +739,17 @@ ipalloct(size_t usize, size_t alignment, bool zero, bool try_tcache, JEMALLOC_ALWAYS_INLINE void * ipalloc(size_t usize, size_t alignment, bool zero) { + arena_t dummy; + DUMMY_ARENA_INITIALIZE(dummy, pools[0]); + return (ipalloct(usize, alignment, zero, true, &dummy)); +} - return (ipalloct(usize, alignment, zero, true, NULL)); +JEMALLOC_ALWAYS_INLINE void * +pool_ipalloc(pool_t *pool, size_t usize, size_t alignment, bool zero) +{ + arena_t dummy; + DUMMY_ARENA_INITIALIZE(dummy, pool); + return (ipalloct(usize, alignment, zero, true, &dummy)); } /* @@ -856,9 +779,18 @@ isalloc(const void *ptr, bool demote) JEMALLOC_ALWAYS_INLINE size_t ivsalloc(const void *ptr, bool demote) { + int i; + for (i = 0; i < POOLS_MAX; ++i) { + pool_t *pool = pools[i]; + if (pool == NULL) + continue; + + /* Return 0 if ptr is not within a chunk managed by jemalloc. */ + if (rtree_get(pool->chunks_rtree, (uintptr_t)CHUNK_ADDR2BASE(ptr)) != 0) + break; + } - /* Return 0 if ptr is not within a chunk managed by jemalloc. */ - if (rtree_get(chunks_rtree, (uintptr_t)CHUNK_ADDR2BASE(ptr)) == 0) + if (i == POOLS_MAX) return (0); return (isalloc(ptr, demote)); @@ -870,7 +802,7 @@ u2rz(size_t usize) size_t ret; if (usize <= SMALL_MAXCLASS) { - size_t binind = SMALL_SIZE2BIN(usize); + size_t binind = small_size2bin(usize); ret = arena_bin_info[binind].redzone_size; } else ret = 0; @@ -890,14 +822,15 @@ JEMALLOC_ALWAYS_INLINE void idalloct(void *ptr, bool try_tcache) { arena_chunk_t *chunk; + pool_t *base_pool = pools[0]; assert(ptr != NULL); chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); if (chunk != ptr) - arena_dalloc(chunk->arena, chunk, ptr, try_tcache); + arena_dalloc(chunk, ptr, try_tcache); else - huge_dalloc(ptr, true); + huge_dalloc(base_pool, ptr); } JEMALLOC_ALWAYS_INLINE void @@ -983,16 +916,26 @@ iralloct(void *ptr, size_t size, size_t extra, size_t alignment, bool zero, alignment, zero, try_tcache_alloc, try_tcache_dalloc)); } else { - return (huge_ralloc(ptr, oldsize, size, extra, - alignment, zero, try_tcache_dalloc, huge_dss_prec_get(arena))); + return (huge_ralloc(arena, ptr, oldsize, size, extra, + alignment, zero, try_tcache_dalloc)); } } JEMALLOC_ALWAYS_INLINE void * iralloc(void *ptr, size_t size, size_t extra, size_t alignment, bool zero) { + arena_t dummy; + DUMMY_ARENA_INITIALIZE(dummy, pools[0]); + return (iralloct(ptr, size, extra, alignment, zero, true, true, &dummy)); +} - return (iralloct(ptr, size, extra, alignment, zero, true, true, NULL)); +JEMALLOC_ALWAYS_INLINE void * +pool_iralloc(pool_t *pool, void *ptr, size_t size, size_t extra, + size_t alignment, bool zero) +{ + arena_t dummy; + DUMMY_ARENA_INITIALIZE(dummy, pool); + return (iralloct(ptr, size, extra, alignment, zero, true, true, &dummy)); } JEMALLOC_ALWAYS_INLINE bool diff --git a/src/jemalloc/include/jemalloc/internal/jemalloc_internal_decls.h b/src/jemalloc/include/jemalloc/internal/jemalloc_internal_decls.h new file mode 100644 index 0000000000000000000000000000000000000000..fa590404708baf8129564203da583fe829be60bb --- /dev/null +++ b/src/jemalloc/include/jemalloc/internal/jemalloc_internal_decls.h @@ -0,0 +1,60 @@ +#ifndef JEMALLOC_INTERNAL_DECLS_H +#define JEMALLOC_INTERNAL_DECLS_H + +#include <math.h> +#ifdef _WIN32 +# include <windows.h> +# define ENOENT ERROR_PATH_NOT_FOUND +# define EINVAL ERROR_BAD_ARGUMENTS +# define EAGAIN ERROR_OUTOFMEMORY +# define EPERM ERROR_WRITE_FAULT +# define EFAULT ERROR_INVALID_ADDRESS +# define ENOMEM ERROR_NOT_ENOUGH_MEMORY +# undef ERANGE +# define ERANGE ERROR_INVALID_DATA +#else +# include <sys/param.h> +# include <sys/mman.h> +# if !defined(__pnacl__) && !defined(__native_client__) +# include <sys/syscall.h> +# if !defined(SYS_write) && defined(__NR_write) +# define SYS_write __NR_write +# endif +# include <sys/uio.h> +# endif +# include <pthread.h> +# include <errno.h> +#endif +#include <sys/types.h> + +#include <limits.h> +#ifndef SIZE_T_MAX +# define SIZE_T_MAX SIZE_MAX +#endif +#include <stdarg.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <stddef.h> +#ifndef offsetof +# define offsetof(type, member) ((size_t)&(((type *)NULL)->member)) +#endif +#include <inttypes.h> +#include <string.h> +#include <strings.h> +#include <ctype.h> +#ifdef _MSC_VER +# include <io.h> +typedef intptr_t ssize_t; +# define PATH_MAX 1024 +# define STDERR_FILENO 2 +# define __func__ __FUNCTION__ +/* Disable warnings about deprecated system functions */ +# pragma warning(disable: 4996) +#else +# include <unistd.h> +#endif +#include <fcntl.h> + +#endif /* JEMALLOC_INTERNAL_H */ diff --git a/src/jemalloc/include/jemalloc/internal/jemalloc_internal_defs.h.in b/src/jemalloc/include/jemalloc/internal/jemalloc_internal_defs.h.in index c166fbd9e41b6a7160cee51883399cddaa8cf1d1..93716b0a4b96931f44a2833d7333688300028fe1 100644 --- a/src/jemalloc/include/jemalloc/internal/jemalloc_internal_defs.h.in +++ b/src/jemalloc/include/jemalloc/internal/jemalloc_internal_defs.h.in @@ -47,6 +47,16 @@ */ #undef JE_FORCE_SYNC_COMPARE_AND_SWAP_8 +/* + * Defined if __builtin_clz() and __builtin_clzl() are available. + */ +#undef JEMALLOC_HAVE_BUILTIN_CLZ + +/* + * Defined if madvise(2) is available. + */ +#undef JEMALLOC_HAVE_MADVISE + /* * Defined if OSSpin*() functions are available, as provided by Darwin, and * documented in the spinlock(3) manual page. @@ -76,9 +86,6 @@ */ #undef JEMALLOC_MUTEX_INIT_CB -/* Defined if sbrk() is supported. */ -#undef JEMALLOC_HAVE_SBRK - /* Non-empty if the tls_model attribute is supported. */ #undef JEMALLOC_TLS_MODEL @@ -147,16 +154,16 @@ */ #undef JEMALLOC_MUNMAP -/* - * If defined, use mremap(...MREMAP_FIXED...) for huge realloc(). This is - * disabled by default because it is Linux-specific and it will cause virtual - * memory map holes, much like munmap(2) does. - */ -#undef JEMALLOC_MREMAP - /* TLS is used to map arenas and magazine caches to threads. */ #undef JEMALLOC_TLS +/* + * ffs()/ffsl() functions to use for bitmapping. Don't use these directly; + * instead, use jemalloc_ffs() or jemalloc_ffsl() from util.h. + */ +#undef JEMALLOC_INTERNAL_FFSL +#undef JEMALLOC_INTERNAL_FFS + /* * JEMALLOC_IVSALLOC enables ivsalloc(), which verifies that pointers reside * within jemalloc-owned chunks before dereferencing them. diff --git a/src/jemalloc/include/jemalloc/internal/jemalloc_internal_macros.h b/src/jemalloc/include/jemalloc/internal/jemalloc_internal_macros.h index 4e2392302c7687ab91d6980ebce9e847ea5f3a9d..a08ba772ead406d34e5739d7b62b58597ab28d66 100644 --- a/src/jemalloc/include/jemalloc/internal/jemalloc_internal_macros.h +++ b/src/jemalloc/include/jemalloc/internal/jemalloc_internal_macros.h @@ -39,9 +39,15 @@ #endif #define ZU(z) ((size_t)z) +#define ZI(z) ((ssize_t)z) #define QU(q) ((uint64_t)q) #define QI(q) ((int64_t)q) +#define KZU(z) ZU(z##ULL) +#define KZI(z) ZI(z##LL) +#define KQU(q) QU(q##ULL) +#define KQI(q) QI(q##LL) + #ifndef __DECONST # define __DECONST(type, var) ((type)(uintptr_t)(const void *)(var)) #endif diff --git a/src/jemalloc/include/jemalloc/internal/pool.h b/src/jemalloc/include/jemalloc/internal/pool.h new file mode 100644 index 0000000000000000000000000000000000000000..ef4c5fb700c4e08b04811928a6e6de622a9c4f71 --- /dev/null +++ b/src/jemalloc/include/jemalloc/internal/pool.h @@ -0,0 +1,129 @@ +/******************************************************************************/ +#ifdef JEMALLOC_H_TYPES + +#define POOLS_MAX 10 + +/* + * We want to expose pool_t to the library user + * as a result typedef for pool_s is located in "jemalloc.h" + */ +typedef struct tsd_pool_s tsd_pool_t; + +/* + * Dummy arena is used to pass pool structure to choose_arena function + * through various alloc/free variants + */ +#define ARENA_DUMMY_IND (~0) +#define DUMMY_ARENA_INITIALIZE(name, p) \ +do { \ +(name).ind = ARENA_DUMMY_IND; \ +(name).pool = (p); \ +} while (0) + +#define TSD_POOL_INITIALIZER JEMALLOC_ARG_CONCAT({.arenas = {0}}) + + +#endif /* JEMALLOC_H_TYPES */ +/******************************************************************************/ +#ifdef JEMALLOC_H_STRUCTS + +struct pool_s { + /* This pool's index within the pools array. */ + unsigned pool_id; + /* + * Unique pool number. A pool_id can be reused, seqno helping to check + * that data in Thread Storage Data are still valid. + */ + unsigned seqno; + /* Protects arenas initialization (arenas, arenas_total). */ + malloc_mutex_t arenas_lock; + /* + * Arenas that are used to service external requests. Not all elements of the + * arenas array are necessarily used; arenas are created lazily as needed. + * + * arenas[0..narenas_auto) are used for automatic multiplexing of threads and + * arenas. arenas[narenas_auto..narenas_total) are only used if the application + * takes some action to create them and allocate from them. + */ + arena_t **arenas; + unsigned narenas_total; + unsigned narenas_auto; + + /* Tree of chunks that are stand-alone huge allocations. */ + extent_tree_t huge; + /* Protects chunk-related data structures. */ + malloc_mutex_t huge_mtx; + + malloc_mutex_t chunks_mtx; + chunk_stats_t stats_chunks; + + /* + * Trees of chunks that were previously allocated (trees differ only in node + * ordering). These are used when allocating chunks, in an attempt to re-use + * address space. Depending on function, different tree orderings are needed, + * which is why there are two trees with the same contents. + */ + extent_tree_t chunks_szad_mmap; + extent_tree_t chunks_ad_mmap; + extent_tree_t chunks_szad_dss; + extent_tree_t chunks_ad_dss; + + rtree_t *chunks_rtree; + + /* Protects base-related data structures. */ + malloc_mutex_t base_mtx; + malloc_mutex_t base_node_mtx; + /* + * Current pages that are being used for internal memory allocations. These + * pages are carved up in cacheline-size quanta, so that there is no chance of + * false cache line sharing. + */ + void *base_next_addr; + void *base_past_addr; /* Addr immediately past base_pages. */ + extent_node_t *base_nodes; + + /* + * Per pool statistics variables + */ + bool ctl_initialized; + ctl_stats_t ctl_stats; + size_t ctl_stats_allocated; + size_t ctl_stats_active; + size_t ctl_stats_mapped; + size_t stats_cactive; +}; + +struct tsd_pool_s { + unsigned seqno[POOLS_MAX]; /* Sequence number of pool */ + arena_t *arenas[POOLS_MAX]; +}; + +/* + * Minimal size of pool, includes header alignment to cache line size, + * initial space for base allocator, and size of at least one chunk + * of memory with address alignment to multiple of chunksize. + */ +#define POOL_MINIMAL_SIZE (3*chunksize) + + +#endif /* JEMALLOC_H_STRUCTS */ +/******************************************************************************/ +#ifdef JEMALLOC_H_EXTERNS + +bool pool_new(pool_t *pool, unsigned pool_id); +void pool_destroy(pool_t *pool); + +extern malloc_mutex_t pools_lock; +extern malloc_mutex_t pool_base_lock; + +bool pool_boot(); +void pool_prefork(); +void pool_postfork_parent(); +void pool_postfork_child(); + +#endif /* JEMALLOC_H_EXTERNS */ +/******************************************************************************/ +#ifdef JEMALLOC_H_INLINES + +#endif /* JEMALLOC_H_INLINES */ +/******************************************************************************/ diff --git a/src/jemalloc/include/jemalloc/internal/private_symbols.txt b/src/jemalloc/include/jemalloc/internal/private_symbols.txt index 93516d242b69e6a0e11b1b7ff91035b625b486c6..66335375eac1285ebc8677e7848eb7aff1b460a8 100644 --- a/src/jemalloc/include/jemalloc/internal/private_symbols.txt +++ b/src/jemalloc/include/jemalloc/internal/private_symbols.txt @@ -5,6 +5,8 @@ arena_alloc_junk_small arena_bin_index arena_bin_info arena_boot +arena_chunk_alloc_huge +arena_chunk_dalloc_huge arena_dalloc arena_dalloc_bin arena_dalloc_bin_locked @@ -61,6 +63,7 @@ arena_salloc arena_stats_merge arena_tcache_fill_small arenas +pools arenas_booted arenas_cleanup arenas_extend @@ -86,7 +89,7 @@ base_alloc base_boot base_calloc base_node_alloc -base_node_dealloc +base_node_dalloc base_postfork_child base_postfork_parent base_prefork @@ -103,12 +106,15 @@ bt_init buferror choose_arena choose_arena_hard -chunk_alloc +chunk_alloc_arena +chunk_alloc_base +chunk_alloc_default chunk_alloc_dss chunk_alloc_mmap +chunk_global_boot chunk_boot -chunk_dealloc -chunk_dealloc_mmap +chunk_dalloc_default +chunk_dalloc_mmap chunk_dss_boot chunk_dss_postfork_child chunk_dss_postfork_parent @@ -121,6 +127,7 @@ chunk_postfork_child chunk_postfork_parent chunk_prefork chunk_unmap +chunk_record chunks_mtx chunks_rtree chunksize @@ -197,9 +204,7 @@ huge_allocated huge_boot huge_dalloc huge_dalloc_junk -huge_dss_prec_get huge_malloc -huge_mtx huge_ndalloc huge_nmalloc huge_palloc @@ -211,13 +216,13 @@ huge_prof_ctx_set huge_ralloc huge_ralloc_no_move huge_salloc -iallocm icalloc icalloct idalloc idalloct imalloc imalloct +in_valgrind ipalloc ipalloct iqalloc @@ -232,6 +237,7 @@ ixalloc jemalloc_postfork_child jemalloc_postfork_parent jemalloc_prefork +lg_floor malloc_cprintf malloc_mutex_init malloc_mutex_lock @@ -279,7 +285,6 @@ opt_redzone opt_stats_print opt_tcache opt_utrace -opt_valgrind opt_xmalloc opt_zero p2rz @@ -299,11 +304,11 @@ prof_idump prof_interval prof_lookup prof_malloc +prof_malloc_record_object prof_mdump prof_postfork_child prof_postfork_parent prof_prefork -prof_promote prof_realloc prof_sample_accum_update prof_sample_threshold_update @@ -346,7 +351,17 @@ rtree_set s2u sa2u set_errno +small_bin2size +small_bin2size_compute +small_bin2size_lookup +small_bin2size_tab +small_s2u +small_s2u_compute +small_s2u_lookup small_size2bin +small_size2bin_compute +small_size2bin_lookup +small_size2bin_tab stats_cactive stats_cactive_add stats_cactive_get @@ -385,6 +400,7 @@ tcache_event tcache_event_hard tcache_flush tcache_get +tcache_get_hard tcache_initialized tcache_maxclass tcache_salloc @@ -411,3 +427,19 @@ thread_allocated_tsd_set tsd_init_check_recursion tsd_init_finish u2rz +valgrind_freelike_block +valgrind_make_mem_defined +valgrind_make_mem_noaccess +valgrind_make_mem_undefined +pool_new +pool_destroy +pools_lock +pool_base_lock +pool_boot +pool_prefork +pool_postfork_parent +pool_postfork_child +pool_alloc +vec_get +vec_set +vec_delete \ No newline at end of file diff --git a/src/jemalloc/include/jemalloc/internal/prof.h b/src/jemalloc/include/jemalloc/internal/prof.h index 6f162d21e8403ce6dc1ac8d6df1b4468a70d5693..d82fbc4f21d48d1da990801579431128ff33a3a6 100644 --- a/src/jemalloc/include/jemalloc/internal/prof.h +++ b/src/jemalloc/include/jemalloc/internal/prof.h @@ -63,7 +63,6 @@ struct prof_bt_s { /* Data structure passed to libgcc _Unwind_Backtrace() callback functions. */ typedef struct { prof_bt_t *bt; - unsigned nignore; unsigned max; } prof_unwind_data_t; #endif @@ -177,8 +176,7 @@ struct prof_tdata_s { /* Sampling state. */ uint64_t prng_state; - uint64_t threshold; - uint64_t accum; + uint64_t bytes_until_sample; /* State used to avoid dumping while operating on prof internals. */ bool enq; @@ -220,14 +218,8 @@ extern char opt_prof_prefix[ */ extern uint64_t prof_interval; -/* - * If true, promote small sampled objects to large objects, since small run - * headers do not have embedded profile context pointers. - */ -extern bool prof_promote; - void bt_init(prof_bt_t *bt, void **vec); -void prof_backtrace(prof_bt_t *bt, unsigned nignore); +void prof_backtrace(prof_bt_t *bt); prof_thr_cnt_t *prof_lookup(prof_bt_t *bt); #ifdef JEMALLOC_JET size_t prof_bt_count(void); @@ -245,60 +237,25 @@ bool prof_boot2(void); void prof_prefork(void); void prof_postfork_parent(void); void prof_postfork_child(void); +void prof_sample_threshold_update(prof_tdata_t *prof_tdata); #endif /* JEMALLOC_H_EXTERNS */ /******************************************************************************/ #ifdef JEMALLOC_H_INLINES -#define PROF_ALLOC_PREP(nignore, size, ret) do { \ +#define PROF_ALLOC_PREP(size, ret) do { \ prof_tdata_t *prof_tdata; \ prof_bt_t bt; \ \ assert(size == s2u(size)); \ \ - prof_tdata = prof_tdata_get(true); \ - if ((uintptr_t)prof_tdata <= (uintptr_t)PROF_TDATA_STATE_MAX) { \ - if (prof_tdata != NULL) \ - ret = (prof_thr_cnt_t *)(uintptr_t)1U; \ - else \ - ret = NULL; \ - break; \ - } \ - \ - if (opt_prof_active == false) { \ - /* Sampling is currently inactive, so avoid sampling. */\ + if (!opt_prof_active || \ + prof_sample_accum_update(size, false, &prof_tdata)) { \ ret = (prof_thr_cnt_t *)(uintptr_t)1U; \ - } else if (opt_lg_prof_sample == 0) { \ - /* Don't bother with sampling logic, since sampling */\ - /* interval is 1. */\ + } else { \ bt_init(&bt, prof_tdata->vec); \ - prof_backtrace(&bt, nignore); \ + prof_backtrace(&bt); \ ret = prof_lookup(&bt); \ - } else { \ - if (prof_tdata->threshold == 0) { \ - /* Initialize. Seed the prng differently for */\ - /* each thread. */\ - prof_tdata->prng_state = \ - (uint64_t)(uintptr_t)&size; \ - prof_sample_threshold_update(prof_tdata); \ - } \ - \ - /* Determine whether to capture a backtrace based on */\ - /* whether size is enough for prof_accum to reach */\ - /* prof_tdata->threshold. However, delay updating */\ - /* these variables until prof_{m,re}alloc(), because */\ - /* we don't know for sure that the allocation will */\ - /* succeed. */\ - /* */\ - /* Use subtraction rather than addition to avoid */\ - /* potential integer overflow. */\ - if (size >= prof_tdata->threshold - \ - prof_tdata->accum) { \ - bt_init(&bt, prof_tdata->vec); \ - prof_backtrace(&bt, nignore); \ - ret = prof_lookup(&bt); \ - } else \ - ret = (prof_thr_cnt_t *)(uintptr_t)1U; \ } \ } while (0) @@ -306,10 +263,12 @@ void prof_postfork_child(void); malloc_tsd_protos(JEMALLOC_ATTR(unused), prof_tdata, prof_tdata_t *) prof_tdata_t *prof_tdata_get(bool create); -void prof_sample_threshold_update(prof_tdata_t *prof_tdata); +bool prof_sample_accum_update(size_t size, bool commit, + prof_tdata_t **prof_tdata_out); prof_ctx_t *prof_ctx_get(const void *ptr); -void prof_ctx_set(const void *ptr, size_t usize, prof_ctx_t *ctx); -bool prof_sample_accum_update(size_t size); +void prof_ctx_set(const void *ptr, prof_ctx_t *ctx); +void prof_malloc_record_object(const void *ptr, size_t usize, + prof_thr_cnt_t *cnt); void prof_malloc(const void *ptr, size_t usize, prof_thr_cnt_t *cnt); void prof_realloc(const void *ptr, size_t usize, prof_thr_cnt_t *cnt, size_t old_usize, prof_ctx_t *old_ctx); @@ -336,55 +295,6 @@ prof_tdata_get(bool create) return (prof_tdata); } -JEMALLOC_INLINE void -prof_sample_threshold_update(prof_tdata_t *prof_tdata) -{ - /* - * The body of this function is compiled out unless heap profiling is - * enabled, so that it is possible to compile jemalloc with floating - * point support completely disabled. Avoiding floating point code is - * important on memory-constrained systems, but it also enables a - * workaround for versions of glibc that don't properly save/restore - * floating point registers during dynamic lazy symbol loading (which - * internally calls into whatever malloc implementation happens to be - * integrated into the application). Note that some compilers (e.g. - * gcc 4.8) may use floating point registers for fast memory moves, so - * jemalloc must be compiled with such optimizations disabled (e.g. - * -mno-sse) in order for the workaround to be complete. - */ -#ifdef JEMALLOC_PROF - uint64_t r; - double u; - - cassert(config_prof); - - /* - * Compute sample threshold as a geometrically distributed random - * variable with mean (2^opt_lg_prof_sample). - * - * __ __ - * | log(u) | 1 - * prof_tdata->threshold = | -------- |, where p = ------------------- - * | log(1-p) | opt_lg_prof_sample - * 2 - * - * For more information on the math, see: - * - * Non-Uniform Random Variate Generation - * Luc Devroye - * Springer-Verlag, New York, 1986 - * pp 500 - * (http://luc.devroye.org/rnbookindex.html) - */ - prng64(r, 53, prof_tdata->prng_state, - UINT64_C(6364136223846793005), UINT64_C(1442695040888963407)); - u = (double)r * (1.0/9007199254740992.0L); - prof_tdata->threshold = (uint64_t)(log(u) / - log(1.0 - (1.0 / (double)((uint64_t)1U << opt_lg_prof_sample)))) - + (uint64_t)1U; -#endif -} - JEMALLOC_INLINE prof_ctx_t * prof_ctx_get(const void *ptr) { @@ -405,7 +315,7 @@ prof_ctx_get(const void *ptr) } JEMALLOC_INLINE void -prof_ctx_set(const void *ptr, size_t usize, prof_ctx_t *ctx) +prof_ctx_set(const void *ptr, prof_ctx_t *ctx) { arena_chunk_t *chunk; @@ -415,40 +325,64 @@ prof_ctx_set(const void *ptr, size_t usize, prof_ctx_t *ctx) chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); if (chunk != ptr) { /* Region. */ - arena_prof_ctx_set(ptr, usize, ctx); + arena_prof_ctx_set(ptr, ctx); } else huge_prof_ctx_set(ptr, ctx); } JEMALLOC_INLINE bool -prof_sample_accum_update(size_t size) +prof_sample_accum_update(size_t size, bool commit, + prof_tdata_t **prof_tdata_out) { prof_tdata_t *prof_tdata; cassert(config_prof); - /* Sampling logic is unnecessary if the interval is 1. */ - assert(opt_lg_prof_sample != 0); - prof_tdata = prof_tdata_get(false); + prof_tdata = prof_tdata_get(true); if ((uintptr_t)prof_tdata <= (uintptr_t)PROF_TDATA_STATE_MAX) + prof_tdata = NULL; + + if (prof_tdata_out != NULL) + *prof_tdata_out = prof_tdata; + + if (prof_tdata == NULL) return (true); - /* Take care to avoid integer overflow. */ - if (size >= prof_tdata->threshold - prof_tdata->accum) { - prof_tdata->accum -= (prof_tdata->threshold - size); + if (prof_tdata->bytes_until_sample >= size) { + if (commit) + prof_tdata->bytes_until_sample -= size; + return (true); + } else { /* Compute new sample threshold. */ - prof_sample_threshold_update(prof_tdata); - while (prof_tdata->accum >= prof_tdata->threshold) { - prof_tdata->accum -= prof_tdata->threshold; + if (commit) prof_sample_threshold_update(prof_tdata); - } return (false); - } else { - prof_tdata->accum += size; - return (true); } } +JEMALLOC_INLINE void +prof_malloc_record_object(const void *ptr, size_t usize, prof_thr_cnt_t *cnt) { + prof_ctx_set(ptr, cnt->ctx); + + cnt->epoch++; + /*********/ + mb_write(); + /*********/ + cnt->cnts.curobjs++; + cnt->cnts.curbytes += usize; + if (opt_prof_accum) { + cnt->cnts.accumobjs++; + cnt->cnts.accumbytes += usize; + } + /*********/ + mb_write(); + /*********/ + cnt->epoch++; + /*********/ + mb_write(); + /*********/ +} + JEMALLOC_INLINE void prof_malloc(const void *ptr, size_t usize, prof_thr_cnt_t *cnt) { @@ -457,41 +391,21 @@ prof_malloc(const void *ptr, size_t usize, prof_thr_cnt_t *cnt) assert(ptr != NULL); assert(usize == isalloc(ptr, true)); - if (opt_lg_prof_sample != 0) { - if (prof_sample_accum_update(usize)) { - /* - * Don't sample. For malloc()-like allocation, it is - * always possible to tell in advance how large an - * object's usable size will be, so there should never - * be a difference between the usize passed to - * PROF_ALLOC_PREP() and prof_malloc(). - */ - assert((uintptr_t)cnt == (uintptr_t)1U); - } + if (prof_sample_accum_update(usize, true, NULL)) { + /* + * Don't sample. For malloc()-like allocation, it is + * always possible to tell in advance how large an + * object's usable size will be, so there should never + * be a difference between the usize passed to + * PROF_ALLOC_PREP() and prof_malloc(). + */ + assert((uintptr_t)cnt == (uintptr_t)1U); } - if ((uintptr_t)cnt > (uintptr_t)1U) { - prof_ctx_set(ptr, usize, cnt->ctx); - - cnt->epoch++; - /*********/ - mb_write(); - /*********/ - cnt->cnts.curobjs++; - cnt->cnts.curbytes += usize; - if (opt_prof_accum) { - cnt->cnts.accumobjs++; - cnt->cnts.accumbytes += usize; - } - /*********/ - mb_write(); - /*********/ - cnt->epoch++; - /*********/ - mb_write(); - /*********/ - } else - prof_ctx_set(ptr, usize, (prof_ctx_t *)(uintptr_t)1U); + if ((uintptr_t)cnt > (uintptr_t)1U) + prof_malloc_record_object(ptr, usize, cnt); + else + prof_ctx_set(ptr, (prof_ctx_t *)(uintptr_t)1U); } JEMALLOC_INLINE void @@ -505,18 +419,16 @@ prof_realloc(const void *ptr, size_t usize, prof_thr_cnt_t *cnt, if (ptr != NULL) { assert(usize == isalloc(ptr, true)); - if (opt_lg_prof_sample != 0) { - if (prof_sample_accum_update(usize)) { - /* - * Don't sample. The usize passed to - * PROF_ALLOC_PREP() was larger than what - * actually got allocated, so a backtrace was - * captured for this allocation, even though - * its actual usize was insufficient to cross - * the sample threshold. - */ - cnt = (prof_thr_cnt_t *)(uintptr_t)1U; - } + if (prof_sample_accum_update(usize, true, NULL)) { + /* + * Don't sample. The usize passed to + * PROF_ALLOC_PREP() was larger than what + * actually got allocated, so a backtrace was + * captured for this allocation, even though + * its actual usize was insufficient to cross + * the sample threshold. + */ + cnt = (prof_thr_cnt_t *)(uintptr_t)1U; } } @@ -539,10 +451,10 @@ prof_realloc(const void *ptr, size_t usize, prof_thr_cnt_t *cnt, if ((uintptr_t)told_cnt > (uintptr_t)1U) told_cnt->epoch++; if ((uintptr_t)cnt > (uintptr_t)1U) { - prof_ctx_set(ptr, usize, cnt->ctx); + prof_ctx_set(ptr, cnt->ctx); cnt->epoch++; } else if (ptr != NULL) - prof_ctx_set(ptr, usize, (prof_ctx_t *)(uintptr_t)1U); + prof_ctx_set(ptr, (prof_ctx_t *)(uintptr_t)1U); /*********/ mb_write(); /*********/ diff --git a/src/jemalloc/include/jemalloc/internal/rtree.h b/src/jemalloc/include/jemalloc/internal/rtree.h index bc74769f50ed68588850c36366b9ec7df9896f8d..3a1d62667fe8c38e31f4763160ae5a07913c8415 100644 --- a/src/jemalloc/include/jemalloc/internal/rtree.h +++ b/src/jemalloc/include/jemalloc/internal/rtree.h @@ -16,8 +16,8 @@ typedef struct rtree_s rtree_t; */ #define RTREE_NODESIZE (1U << 16) -typedef void *(rtree_alloc_t)(size_t); -typedef void (rtree_dalloc_t)(void *); +typedef void *(rtree_alloc_t)(pool_t *, size_t); +typedef void (rtree_dalloc_t)(pool_t *, void *); #endif /* JEMALLOC_H_TYPES */ /******************************************************************************/ @@ -26,6 +26,7 @@ typedef void (rtree_dalloc_t)(void *); struct rtree_s { rtree_alloc_t *alloc; rtree_dalloc_t *dalloc; + pool_t *pool; malloc_mutex_t mutex; void **root; unsigned height; @@ -36,7 +37,8 @@ struct rtree_s { /******************************************************************************/ #ifdef JEMALLOC_H_EXTERNS -rtree_t *rtree_new(unsigned bits, rtree_alloc_t *alloc, rtree_dalloc_t *dalloc); +rtree_t *rtree_new(unsigned bits, rtree_alloc_t *alloc, rtree_dalloc_t *dalloc, + pool_t *pool); void rtree_delete(rtree_t *rtree); void rtree_prefork(rtree_t *rtree); void rtree_postfork_parent(rtree_t *rtree); @@ -145,7 +147,7 @@ rtree_set(rtree_t *rtree, uintptr_t key, uint8_t val) if (child == NULL) { size_t size = ((i + 1 < height - 1) ? sizeof(void *) : (sizeof(uint8_t))) << rtree->level2bits[i+1]; - child = (void**)rtree->alloc(size); + child = (void**)rtree->alloc(rtree->pool, size); if (child == NULL) { malloc_mutex_unlock(&rtree->mutex); return (true); diff --git a/src/jemalloc/include/jemalloc/internal/size_classes.sh b/src/jemalloc/include/jemalloc/internal/size_classes.sh index 29c80c1fb8d1bdfd7ebe880043a2d06aa367f4d4..3edebf2387cd75aa65bf860f306cbb0d8e0d29ac 100755 --- a/src/jemalloc/include/jemalloc/internal/size_classes.sh +++ b/src/jemalloc/include/jemalloc/internal/size_classes.sh @@ -2,16 +2,23 @@ # The following limits are chosen such that they cover all supported platforms. -# Range of quanta. -lg_qmin=3 -lg_qmax=4 +# Pointer sizes. +lg_zarr="2 3" + +# Quanta. +lg_qarr="3 4" # The range of tiny size classes is [2^lg_tmin..2^(lg_q-1)]. lg_tmin=3 -# Range of page sizes. -lg_pmin=12 -lg_pmax=16 +# Maximum lookup size. +lg_kmax=12 + +# Page sizes. +lg_parr="12 13 16" + +# Size class group size (number of size classes for each size doubling). +lg_g=2 pow2() { e=$1 @@ -22,68 +29,206 @@ pow2() { done } +lg() { + x=$1 + lg_result=0 + while [ ${x} -gt 1 ] ; do + lg_result=$((${lg_result} + 1)) + x=$((${x} / 2)) + done +} + +size_class() { + index=$1 + lg_grp=$2 + lg_delta=$3 + ndelta=$4 + lg_p=$5 + lg_kmax=$6 + + lg ${ndelta}; lg_ndelta=${lg_result}; pow2 ${lg_ndelta} + if [ ${pow2_result} -lt ${ndelta} ] ; then + rem="yes" + else + rem="no" + fi + + lg_size=${lg_grp} + if [ $((${lg_delta} + ${lg_ndelta})) -eq ${lg_grp} ] ; then + lg_size=$((${lg_grp} + 1)) + else + lg_size=${lg_grp} + rem="yes" + fi + + if [ ${lg_size} -lt ${lg_p} ] ; then + bin="yes" + else + bin="no" + fi + if [ ${lg_size} -lt ${lg_kmax} \ + -o ${lg_size} -eq ${lg_kmax} -a ${rem} = "no" ] ; then + lg_delta_lookup=${lg_delta} + else + lg_delta_lookup="no" + fi + printf ' SC(%3d, %6d, %8d, %6d, %3s, %2s) \\\n' ${index} ${lg_grp} ${lg_delta} ${ndelta} ${bin} ${lg_delta_lookup} + # Defined upon return: + # - lg_delta_lookup (${lg_delta} or "no") + # - bin ("yes" or "no") +} + +sep_line() { + echo " \\" +} + +size_classes() { + lg_z=$1 + lg_q=$2 + lg_t=$3 + lg_p=$4 + lg_g=$5 + + pow2 $((${lg_z} + 3)); ptr_bits=${pow2_result} + pow2 ${lg_g}; g=${pow2_result} + + echo "#define SIZE_CLASSES \\" + echo " /* index, lg_grp, lg_delta, ndelta, bin, lg_delta_lookup */ \\" + + ntbins=0 + nlbins=0 + lg_tiny_maxclass='"NA"' + nbins=0 + + # Tiny size classes. + ndelta=0 + index=0 + lg_grp=${lg_t} + lg_delta=${lg_grp} + while [ ${lg_grp} -lt ${lg_q} ] ; do + size_class ${index} ${lg_grp} ${lg_delta} ${ndelta} ${lg_p} ${lg_kmax} + if [ ${lg_delta_lookup} != "no" ] ; then + nlbins=$((${index} + 1)) + fi + if [ ${bin} != "no" ] ; then + nbins=$((${index} + 1)) + fi + ntbins=$((${ntbins} + 1)) + lg_tiny_maxclass=${lg_grp} # Final written value is correct. + index=$((${index} + 1)) + lg_delta=${lg_grp} + lg_grp=$((${lg_grp} + 1)) + done + + # First non-tiny group. + if [ ${ntbins} -gt 0 ] ; then + sep_line + # The first size class has an unusual encoding, because the size has to be + # split between grp and delta*ndelta. + lg_grp=$((${lg_grp} - 1)) + ndelta=1 + size_class ${index} ${lg_grp} ${lg_delta} ${ndelta} ${lg_p} ${lg_kmax} + index=$((${index} + 1)) + lg_grp=$((${lg_grp} + 1)) + lg_delta=$((${lg_delta} + 1)) + fi + while [ ${ndelta} -lt ${g} ] ; do + size_class ${index} ${lg_grp} ${lg_delta} ${ndelta} ${lg_p} ${lg_kmax} + index=$((${index} + 1)) + ndelta=$((${ndelta} + 1)) + done + + # All remaining groups. + lg_grp=$((${lg_grp} + ${lg_g})) + while [ ${lg_grp} -lt ${ptr_bits} ] ; do + sep_line + ndelta=1 + if [ ${lg_grp} -eq $((${ptr_bits} - 1)) ] ; then + ndelta_limit=$((${g} - 1)) + else + ndelta_limit=${g} + fi + while [ ${ndelta} -le ${ndelta_limit} ] ; do + size_class ${index} ${lg_grp} ${lg_delta} ${ndelta} ${lg_p} ${lg_kmax} + if [ ${lg_delta_lookup} != "no" ] ; then + nlbins=$((${index} + 1)) + # Final written value is correct: + lookup_maxclass="((((size_t)1) << ${lg_grp}) + (((size_t)${ndelta}) << ${lg_delta}))" + fi + if [ ${bin} != "no" ] ; then + nbins=$((${index} + 1)) + # Final written value is correct: + small_maxclass="((((size_t)1) << ${lg_grp}) + (((size_t)${ndelta}) << ${lg_delta}))" + fi + index=$((${index} + 1)) + ndelta=$((${ndelta} + 1)) + done + lg_grp=$((${lg_grp} + 1)) + lg_delta=$((${lg_delta} + 1)) + done + echo + + # Defined upon completion: + # - ntbins + # - nlbins + # - nbins + # - lg_tiny_maxclass + # - lookup_maxclass + # - small_maxclass +} + cat <<EOF /* This file was automatically generated by size_classes.sh. */ /******************************************************************************/ #ifdef JEMALLOC_H_TYPES +/* + * This header requires LG_SIZEOF_PTR, LG_TINY_MIN, LG_QUANTUM, and LG_PAGE to + * be defined prior to inclusion, and it in turn defines: + * + * LG_SIZE_CLASS_GROUP: Lg of size class count for each size doubling. + * SIZE_CLASSES: Complete table of + * SC(index, lg_delta, size, bin, lg_delta_lookup) tuples. + * index: Size class index. + * lg_grp: Lg group base size (no deltas added). + * lg_delta: Lg delta to previous size class. + * ndelta: Delta multiplier. size == 1<<lg_grp + ndelta<<lg_delta + * bin: 'yes' if a small bin size class, 'no' otherwise. + * lg_delta_lookup: Same as lg_delta if a lookup table size class, 'no' + * otherwise. + * NTBINS: Number of tiny bins. + * NLBINS: Number of bins supported by the lookup table. + * NBINS: Number of small size class bins. + * LG_TINY_MAXCLASS: Lg of maximum tiny size class. + * LOOKUP_MAXCLASS: Maximum size class included in lookup table. + * SMALL_MAXCLASS: Maximum small size class. + */ + +#define LG_SIZE_CLASS_GROUP ${lg_g} + EOF -lg_q=${lg_qmin} -while [ ${lg_q} -le ${lg_qmax} ] ; do - lg_t=${lg_tmin} - while [ ${lg_t} -le ${lg_q} ] ; do - lg_p=${lg_pmin} - while [ ${lg_p} -le ${lg_pmax} ] ; do - echo "#if (LG_TINY_MIN == ${lg_t} && LG_QUANTUM == ${lg_q} && LG_PAGE == ${lg_p})" - echo "#define SIZE_CLASSES_DEFINED" - pow2 ${lg_q}; q=${pow2_result} - pow2 ${lg_t}; t=${pow2_result} - pow2 ${lg_p}; p=${pow2_result} - bin=0 - psz=0 - sz=${t} - delta=$((${sz} - ${psz})) - echo "/* SIZE_CLASS(bin, delta, sz) */" - echo "#define SIZE_CLASSES \\" - - # Tiny size classes. - while [ ${sz} -lt ${q} ] ; do - echo " SIZE_CLASS(${bin}, ${delta}, ${sz}) \\" - bin=$((${bin} + 1)) - psz=${sz} - sz=$((${sz} + ${sz})) - delta=$((${sz} - ${psz})) - done - # Quantum-multiple size classes. For each doubling of sz, as many as 4 - # size classes exist. Their spacing is the greater of: - # - q - # - sz/4, where sz is a power of 2 - while [ ${sz} -lt ${p} ] ; do - if [ ${sz} -ge $((${q} * 4)) ] ; then - i=$((${sz} / 4)) - else - i=${q} - fi - next_2pow=$((${sz} * 2)) - while [ ${sz} -lt $next_2pow ] ; do - echo " SIZE_CLASS(${bin}, ${delta}, ${sz}) \\" - bin=$((${bin} + 1)) - psz=${sz} - sz=$((${sz} + ${i})) - delta=$((${sz} - ${psz})) - done +for lg_z in ${lg_zarr} ; do + for lg_q in ${lg_qarr} ; do + lg_t=${lg_tmin} + while [ ${lg_t} -le ${lg_q} ] ; do + # Iterate through page sizes and compute how many bins there are. + for lg_p in ${lg_parr} ; do + echo "#if (LG_SIZEOF_PTR == ${lg_z} && LG_TINY_MIN == ${lg_t} && LG_QUANTUM == ${lg_q} && LG_PAGE == ${lg_p})" + size_classes ${lg_z} ${lg_q} ${lg_t} ${lg_p} ${lg_g} + echo "#define SIZE_CLASSES_DEFINED" + echo "#define NTBINS ${ntbins}" + echo "#define NLBINS ${nlbins}" + echo "#define NBINS ${nbins}" + echo "#define LG_TINY_MAXCLASS ${lg_tiny_maxclass}" + echo "#define LOOKUP_MAXCLASS ${lookup_maxclass}" + echo "#define SMALL_MAXCLASS ${small_maxclass}" + echo "#endif" + echo done - echo - echo "#define NBINS ${bin}" - echo "#define SMALL_MAXCLASS ${psz}" - echo "#endif" - echo - lg_p=$((${lg_p} + 1)) + lg_t=$((${lg_t} + 1)) done - lg_t=$((${lg_t} + 1)) done - lg_q=$((${lg_q} + 1)) done cat <<EOF @@ -94,9 +239,8 @@ cat <<EOF /* * The small_size2bin lookup table uses uint8_t to encode each bin index, so we * cannot support more than 256 small size classes. Further constrain NBINS to - * 255 to support prof_promote, since all small size classes, plus a "not - * small" size class must be stored in 8 bits of arena_chunk_map_t's bits - * field. + * 255 since all small size classes, plus a "not small" size class must be + * stored in 8 bits of arena_chunk_map_t's bits field. */ #if (NBINS > 255) # error "Too many small size classes" diff --git a/src/jemalloc/include/jemalloc/internal/stats.h b/src/jemalloc/include/jemalloc/internal/stats.h index 27f68e3681cfa7480612b871a083b3ca8b126e6e..5540d84059eb80e541574e80ccb9b654ee2bb4ed 100644 --- a/src/jemalloc/include/jemalloc/internal/stats.h +++ b/src/jemalloc/include/jemalloc/internal/stats.h @@ -101,6 +101,11 @@ struct arena_stats_s { uint64_t ndalloc_large; uint64_t nrequests_large; + size_t allocated_huge; + uint64_t nmalloc_huge; + uint64_t ndalloc_huge; + uint64_t nrequests_huge; + /* * One element for each possible size class, including sizes that * overlap with bin size classes. This is necessary because ipalloc() @@ -131,9 +136,7 @@ struct chunk_stats_s { extern bool opt_stats_print; -extern size_t stats_cactive; - -void stats_print(void (*write)(void *, const char *), void *cbopaque, +void stats_print(pool_t *pool, void (*write)(void *, const char *), void *cbopaque, const char *opts); #endif /* JEMALLOC_H_EXTERNS */ @@ -141,31 +144,31 @@ void stats_print(void (*write)(void *, const char *), void *cbopaque, #ifdef JEMALLOC_H_INLINES #ifndef JEMALLOC_ENABLE_INLINE -size_t stats_cactive_get(void); -void stats_cactive_add(size_t size); -void stats_cactive_sub(size_t size); +size_t stats_cactive_get(pool_t *pool); +void stats_cactive_add(pool_t *pool, size_t size); +void stats_cactive_sub(pool_t *pool, size_t size); #endif #if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_STATS_C_)) JEMALLOC_INLINE size_t -stats_cactive_get(void) +stats_cactive_get(pool_t *pool) { - return (atomic_read_z(&stats_cactive)); + return (atomic_read_z(&(pool->stats_cactive))); } JEMALLOC_INLINE void -stats_cactive_add(size_t size) +stats_cactive_add(pool_t *pool, size_t size) { - atomic_add_z(&stats_cactive, size); + atomic_add_z(&(pool->stats_cactive), size); } JEMALLOC_INLINE void -stats_cactive_sub(size_t size) +stats_cactive_sub(pool_t *pool, size_t size) { - atomic_sub_z(&stats_cactive, size); + atomic_sub_z(&(pool->stats_cactive), size); } #endif diff --git a/src/jemalloc/include/jemalloc/internal/tcache.h b/src/jemalloc/include/jemalloc/internal/tcache.h index c3d4b58d4dc5ff572f4cad3245c2c3faf98f56a6..eaccd8e465f78ca479d48ed1c9290fe036cb002b 100644 --- a/src/jemalloc/include/jemalloc/internal/tcache.h +++ b/src/jemalloc/include/jemalloc/internal/tcache.h @@ -4,6 +4,7 @@ typedef struct tcache_bin_info_s tcache_bin_info_t; typedef struct tcache_bin_s tcache_bin_t; typedef struct tcache_s tcache_t; +typedef struct tsd_tcache_s tsd_tcache_t; /* * tcache pointers close to NULL are used to encode state information that is @@ -41,6 +42,8 @@ typedef struct tcache_s tcache_t; #define TCACHE_GC_INCR \ ((TCACHE_GC_SWEEP / NBINS) + ((TCACHE_GC_SWEEP / NBINS == 0) ? 0 : 1)) +#define TSD_TCACHE_INITIALIZER JEMALLOC_ARG_CONCAT({.tcaches = {0}}) + #endif /* JEMALLOC_H_TYPES */ /******************************************************************************/ #ifdef JEMALLOC_H_STRUCTS @@ -82,6 +85,11 @@ struct tcache_s { */ }; +struct tsd_tcache_s { + unsigned seqno[POOLS_MAX]; /* Sequence number of pool */ + tcache_t* tcaches[POOLS_MAX]; +}; + #endif /* JEMALLOC_H_STRUCTS */ /******************************************************************************/ #ifdef JEMALLOC_H_EXTERNS @@ -110,6 +118,7 @@ void tcache_bin_flush_large(tcache_bin_t *tbin, size_t binind, unsigned rem, tcache_t *tcache); void tcache_arena_associate(tcache_t *tcache, arena_t *arena); void tcache_arena_dissociate(tcache_t *tcache); +tcache_t *tcache_get_hard(tcache_t *tcache, pool_t *pool, bool create); tcache_t *tcache_create(arena_t *arena); void tcache_destroy(tcache_t *tcache); void tcache_thread_cleanup(void *arg); @@ -122,13 +131,13 @@ bool tcache_boot1(void); #ifdef JEMALLOC_H_INLINES #ifndef JEMALLOC_ENABLE_INLINE -malloc_tsd_protos(JEMALLOC_ATTR(unused), tcache, tcache_t *) +malloc_tsd_protos(JEMALLOC_ATTR(unused), tcache, tsd_tcache_t) malloc_tsd_protos(JEMALLOC_ATTR(unused), tcache_enabled, tcache_enabled_t) void tcache_event(tcache_t *tcache); -void tcache_flush(void); +void tcache_flush(pool_t *pool); bool tcache_enabled_get(void); -tcache_t *tcache_get(bool create); +tcache_t *tcache_get(pool_t *pool, bool create); void tcache_enabled_set(bool enabled); void *tcache_alloc_easy(tcache_bin_t *tbin); void *tcache_alloc_small(tcache_t *tcache, size_t size, bool zero); @@ -139,8 +148,8 @@ void tcache_dalloc_large(tcache_t *tcache, void *ptr, size_t size); #if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_TCACHE_C_)) /* Map of thread-specific caches. */ -malloc_tsd_externs(tcache, tcache_t *) -malloc_tsd_funcs(JEMALLOC_ALWAYS_INLINE, tcache, tcache_t *, NULL, +malloc_tsd_externs(tcache, tsd_tcache_t) +malloc_tsd_funcs(JEMALLOC_ALWAYS_INLINE, tcache, tsd_tcache_t, NULL, tcache_thread_cleanup) /* Per thread flag that allows thread caches to be disabled. */ malloc_tsd_externs(tcache_enabled, tcache_enabled_t) @@ -148,18 +157,20 @@ malloc_tsd_funcs(JEMALLOC_ALWAYS_INLINE, tcache_enabled, tcache_enabled_t, tcache_enabled_default, malloc_tsd_no_cleanup) JEMALLOC_INLINE void -tcache_flush(void) +tcache_flush(pool_t *pool) { - tcache_t *tcache; + tsd_tcache_t *tsd = tcache_tsd_get(); - cassert(config_tcache); + tcache_t *tcache = tsd->tcaches[pool->pool_id]; - tcache = *tcache_tsd_get(); - if ((uintptr_t)tcache <= (uintptr_t)TCACHE_STATE_MAX) - return; - tcache_destroy(tcache); - tcache = NULL; - tcache_tsd_set(&tcache); + if (tsd->seqno[pool->pool_id] == pool->seqno) { + cassert(config_tcache); + + if ((uintptr_t)tcache <= (uintptr_t)TCACHE_STATE_MAX) + return; + tcache_destroy(tcache); + } + tsd->tcaches[pool->pool_id] = NULL; } JEMALLOC_INLINE bool @@ -182,77 +193,66 @@ JEMALLOC_INLINE void tcache_enabled_set(bool enabled) { tcache_enabled_t tcache_enabled; + tsd_tcache_t *tsd; tcache_t *tcache; + int i; cassert(config_tcache); tcache_enabled = (tcache_enabled_t)enabled; tcache_enabled_tsd_set(&tcache_enabled); - tcache = *tcache_tsd_get(); - if (enabled) { - if (tcache == TCACHE_STATE_DISABLED) { - tcache = NULL; - tcache_tsd_set(&tcache); - } - } else /* disabled */ { - if (tcache > TCACHE_STATE_MAX) { - tcache_destroy(tcache); - tcache = NULL; - } - if (tcache == NULL) { - tcache = TCACHE_STATE_DISABLED; - tcache_tsd_set(&tcache); + tsd = tcache_tsd_get(); + + malloc_mutex_lock(&pools_lock); + for (i = 0; i < POOLS_MAX; i++) { + tcache = tsd->tcaches[i]; + if (tcache != NULL) { + if (enabled) { + if (tcache == TCACHE_STATE_DISABLED) { + tsd->tcaches[i] = NULL; + } + } else /* disabled */ { + if (tcache > TCACHE_STATE_MAX) { + if (pools[i] != NULL && tsd->seqno[i] == pools[i]->seqno) + tcache_destroy(tcache); + + tcache = NULL; + } + if (tcache == NULL) { + tsd->tcaches[i] = TCACHE_STATE_DISABLED; + } + } } } + malloc_mutex_unlock(&pools_lock); } JEMALLOC_ALWAYS_INLINE tcache_t * -tcache_get(bool create) +tcache_get(pool_t *pool, bool create) { tcache_t *tcache; + tsd_tcache_t *tsd; if (config_tcache == false) return (NULL); if (config_lazy_lock && isthreaded == false) return (NULL); - tcache = *tcache_tsd_get(); + tsd = tcache_tsd_get(); + + /* + * All subsequent pools with the same id have to cleanup tcache before + * calling tcache_get_hard. + */ + if (tsd->seqno[pool->pool_id] != pool->seqno) { + tsd->tcaches[pool->pool_id] = NULL; + } + + tcache = tsd->tcaches[pool->pool_id]; if ((uintptr_t)tcache <= (uintptr_t)TCACHE_STATE_MAX) { if (tcache == TCACHE_STATE_DISABLED) return (NULL); - if (tcache == NULL) { - if (create == false) { - /* - * Creating a tcache here would cause - * allocation as a side effect of free(). - * Ordinarily that would be okay since - * tcache_create() failure is a soft failure - * that doesn't propagate. However, if TLS - * data are freed via free() as in glibc, - * subtle corruption could result from setting - * a TLS variable after its backing memory is - * freed. - */ - return (NULL); - } - if (tcache_enabled_get() == false) { - tcache_enabled_set(false); /* Memoize. */ - return (NULL); - } - return (tcache_create(choose_arena(NULL))); - } - if (tcache == TCACHE_STATE_PURGATORY) { - /* - * Make a note that an allocator function was called - * after tcache_thread_cleanup() was called. - */ - tcache = TCACHE_STATE_REINCARNATED; - tcache_tsd_set(&tcache); - return (NULL); - } - if (tcache == TCACHE_STATE_REINCARNATED) - return (NULL); - not_reached(); + tcache = tcache_get_hard(tcache, pool, create); } return (tcache); @@ -294,17 +294,17 @@ tcache_alloc_small(tcache_t *tcache, size_t size, bool zero) size_t binind; tcache_bin_t *tbin; - binind = SMALL_SIZE2BIN(size); + binind = small_size2bin(size); assert(binind < NBINS); tbin = &tcache->tbins[binind]; - size = arena_bin_info[binind].reg_size; + size = small_bin2size(binind); ret = tcache_alloc_easy(tbin); if (ret == NULL) { ret = tcache_alloc_small_hard(tcache, tbin, binind); if (ret == NULL) return (NULL); } - assert(tcache_salloc(ret) == arena_bin_info[binind].reg_size); + assert(tcache_salloc(ret) == size); if (zero == false) { if (config_fill) { @@ -314,20 +314,18 @@ tcache_alloc_small(tcache_t *tcache, size_t size, bool zero) } else if (opt_zero) memset(ret, 0, size); } - VALGRIND_MAKE_MEM_UNDEFINED(ret, size); } else { if (config_fill && opt_junk) { arena_alloc_junk_small(ret, &arena_bin_info[binind], true); } - VALGRIND_MAKE_MEM_UNDEFINED(ret, size); memset(ret, 0, size); } if (config_stats) tbin->tstats.nrequests++; if (config_prof) - tcache->prof_accumbytes += arena_bin_info[binind].reg_size; + tcache->prof_accumbytes += size; tcache_event(tcache); return (ret); } @@ -354,7 +352,7 @@ tcache_alloc_large(tcache_t *tcache, size_t size, bool zero) if (ret == NULL) return (NULL); } else { - if (config_prof && prof_promote && size == PAGE) { + if (config_prof && size == PAGE) { arena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ret); size_t pageind = (((uintptr_t)ret - (uintptr_t)chunk) >> @@ -369,11 +367,8 @@ tcache_alloc_large(tcache_t *tcache, size_t size, bool zero) else if (opt_zero) memset(ret, 0, size); } - VALGRIND_MAKE_MEM_UNDEFINED(ret, size); - } else { - VALGRIND_MAKE_MEM_UNDEFINED(ret, size); + } else memset(ret, 0, size); - } if (config_stats) tbin->tstats.nrequests++; diff --git a/src/jemalloc/include/jemalloc/internal/tsd.h b/src/jemalloc/include/jemalloc/internal/tsd.h index 9fb4a23ec6bfcaa951a112c336d876e1ad25d980..11d99f08878de8c3246c3a6465151936474df076 100644 --- a/src/jemalloc/include/jemalloc/internal/tsd.h +++ b/src/jemalloc/include/jemalloc/internal/tsd.h @@ -393,6 +393,42 @@ a_name##_tsd_set(a_type *val) \ } #endif + + +/* + * Vector data container implemented as TSD/TLS macros. + * These functions behave exactly like the regular version, + * except for the fact that they take an index argument in accessor functions. + */ + +/* malloc_tsd_vector_protos(). */ +#define malloc_tsd_vector_protos(a_attr, a_name) \ +malloc_tsd_protos(a_attr, a_name, vector_t) + +#define malloc_tsd_vector_externs(a_name) \ +malloc_tsd_externs(a_name, vector_t) + +#define malloc_tsd_vector_data(a_attr, a_name) \ +malloc_tsd_data(a_attr, a_name, vector_t, VECTOR_INITIALIZER) + +#define malloc_tsd_vector_funcs(a_attr, a_name, a_type, a_cleanup) \ +malloc_tsd_funcs(a_attr, a_name, vector_t, VECTOR_INITIALIZER, \ + a_cleanup) \ + \ +a_attr a_type * \ +a_name##_vec_tsd_get(uint32_t index) \ +{ \ + vector_t *v = a_name##_tsd_get(); \ + return (a_type *)vec_get(v, index); \ +} \ + \ +a_attr void \ +a_name##_vec_tsd_set(uint32_t index, a_type *val) \ +{ \ + vector_t *v = a_name##_tsd_get(); \ + vec_set(v, index, (void *)val); \ +} \ + #endif /* JEMALLOC_H_TYPES */ /******************************************************************************/ #ifdef JEMALLOC_H_STRUCTS diff --git a/src/jemalloc/include/jemalloc/internal/util.h b/src/jemalloc/include/jemalloc/internal/util.h index 6b938f746889bc3350b8996077946451222b8fa5..d2b7a9678ff807763173cd3f0afdfbc81f436b15 100644 --- a/src/jemalloc/include/jemalloc/internal/util.h +++ b/src/jemalloc/include/jemalloc/internal/util.h @@ -109,12 +109,35 @@ void malloc_printf(const char *format, ...) #ifdef JEMALLOC_H_INLINES #ifndef JEMALLOC_ENABLE_INLINE +int jemalloc_ffsl(long bitmap); +int jemalloc_ffs(int bitmap); size_t pow2_ceil(size_t x); +size_t lg_floor(size_t x); void set_errno(int errnum); int get_errno(void); #endif #if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_UTIL_C_)) + +/* Sanity check: */ +#if !defined(JEMALLOC_INTERNAL_FFSL) || !defined(JEMALLOC_INTERNAL_FFS) +# error Both JEMALLOC_INTERNAL_FFSL && JEMALLOC_INTERNAL_FFS should have been defined by configure +#endif + +JEMALLOC_ALWAYS_INLINE int +jemalloc_ffsl(long bitmap) +{ + + return (JEMALLOC_INTERNAL_FFSL(bitmap)); +} + +JEMALLOC_ALWAYS_INLINE int +jemalloc_ffs(int bitmap) +{ + + return (JEMALLOC_INTERNAL_FFS(bitmap)); +} + /* Compute the smallest power of 2 that is >= x. */ JEMALLOC_INLINE size_t pow2_ceil(size_t x) @@ -133,6 +156,58 @@ pow2_ceil(size_t x) return (x); } +#if (defined(__i386__) || defined(__amd64__) || defined(__x86_64__)) +JEMALLOC_INLINE size_t +lg_floor(size_t x) +{ + size_t ret; + + asm ("bsr %1, %0" + : "=r"(ret) // Outputs. + : "r"(x) // Inputs. + ); + return (ret); +} +#elif (defined(JEMALLOC_HAVE_BUILTIN_CLZ)) +JEMALLOC_INLINE size_t +lg_floor(size_t x) +{ + +#if (LG_SIZEOF_PTR == LG_SIZEOF_INT) + return (((8 << LG_SIZEOF_PTR) - 1) - __builtin_clz(x)); +#elif (LG_SIZEOF_PTR == LG_SIZEOF_LONG) + return (((8 << LG_SIZEOF_PTR) - 1) - __builtin_clzl(x)); +#else +# error "Unsupported type sizes for lg_floor()" +#endif +} +#else +JEMALLOC_INLINE size_t +lg_floor(size_t x) +{ + + x |= (x >> 1); + x |= (x >> 2); + x |= (x >> 4); + x |= (x >> 8); + x |= (x >> 16); +#if (LG_SIZEOF_PTR == 3 && LG_SIZEOF_PTR == LG_SIZEOF_LONG) + x |= (x >> 32); + if (x == KZU(0xffffffffffffffff)) + return (63); + x++; + return (jemalloc_ffsl(x) - 2); +#elif (LG_SIZEOF_PTR == 2) + if (x == KZU(0xffffffff)) + return (31); + x++; + return (jemalloc_ffs(x) - 2); +#else +# error "Unsupported type sizes for lg_floor()" +#endif +} +#endif + /* Sets error code */ JEMALLOC_INLINE void set_errno(int errnum) diff --git a/src/jemalloc/include/jemalloc/internal/valgrind.h b/src/jemalloc/include/jemalloc/internal/valgrind.h new file mode 100644 index 0000000000000000000000000000000000000000..52c93f2999222f6dc93cd2dad91c3d9e9add69a2 --- /dev/null +++ b/src/jemalloc/include/jemalloc/internal/valgrind.h @@ -0,0 +1,112 @@ +/******************************************************************************/ +#ifdef JEMALLOC_H_TYPES + +#ifdef JEMALLOC_VALGRIND +#include <valgrind/valgrind.h> + +/* + * The size that is reported to Valgrind must be consistent through a chain of + * malloc..realloc..realloc calls. Request size isn't recorded anywhere in + * jemalloc, so it is critical that all callers of these macros provide usize + * rather than request size. As a result, buffer overflow detection is + * technically weakened for the standard API, though it is generally accepted + * practice to consider any extra bytes reported by malloc_usable_size() as + * usable space. + */ +#define JEMALLOC_VALGRIND_MAKE_MEM_NOACCESS(ptr, usize) do { \ + if (in_valgrind) \ + valgrind_make_mem_noaccess(ptr, usize); \ +} while (0) +#define JEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(ptr, usize) do { \ + if (in_valgrind) \ + valgrind_make_mem_undefined(ptr, usize); \ +} while (0) +#define JEMALLOC_VALGRIND_MAKE_MEM_DEFINED(ptr, usize) do { \ + if (in_valgrind) \ + valgrind_make_mem_defined(ptr, usize); \ +} while (0) +/* + * The VALGRIND_MALLOCLIKE_BLOCK() and VALGRIND_RESIZEINPLACE_BLOCK() macro + * calls must be embedded in macros rather than in functions so that when + * Valgrind reports errors, there are no extra stack frames in the backtraces. + */ +#define JEMALLOC_VALGRIND_MALLOC(cond, ptr, usize, zero) do { \ + if (in_valgrind && cond) \ + VALGRIND_MALLOCLIKE_BLOCK(ptr, usize, p2rz(ptr), zero); \ +} while (0) +#define JEMALLOC_VALGRIND_REALLOC(maybe_moved, ptr, usize, \ + ptr_maybe_null, old_ptr, old_usize, old_rzsize, old_ptr_maybe_null, \ + zero) do { \ + if (in_valgrind) { \ + size_t rzsize = p2rz(ptr); \ + \ + if (!maybe_moved || ptr == old_ptr) { \ + VALGRIND_RESIZEINPLACE_BLOCK(ptr, old_usize, \ + usize, rzsize); \ + if (zero && old_usize < usize) { \ + valgrind_make_mem_defined( \ + (void *)((uintptr_t)ptr + \ + old_usize), usize - old_usize); \ + } \ + } else { \ + if (!old_ptr_maybe_null || old_ptr != NULL) { \ + valgrind_freelike_block(old_ptr, \ + old_rzsize); \ + } \ + if (!ptr_maybe_null || ptr != NULL) { \ + size_t copy_size = (old_usize < usize) \ + ? old_usize : usize; \ + size_t tail_size = usize - copy_size; \ + VALGRIND_MALLOCLIKE_BLOCK(ptr, usize, \ + rzsize, false); \ + if (copy_size > 0) { \ + valgrind_make_mem_defined(ptr, \ + copy_size); \ + } \ + if (zero && tail_size > 0) { \ + valgrind_make_mem_defined( \ + (void *)((uintptr_t)ptr + \ + copy_size), tail_size); \ + } \ + } \ + } \ + } \ +} while (0) +#define JEMALLOC_VALGRIND_FREE(ptr, rzsize) do { \ + if (in_valgrind) \ + valgrind_freelike_block(ptr, rzsize); \ +} while (0) +#else +#define RUNNING_ON_VALGRIND ((unsigned)0) +#define JEMALLOC_VALGRIND_MAKE_MEM_NOACCESS(ptr, usize) do {} while (0) +#define JEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(ptr, usize) do {} while (0) +#define JEMALLOC_VALGRIND_MAKE_MEM_DEFINED(ptr, usize) do {} while (0) +#define JEMALLOC_VALGRIND_MALLOC(cond, ptr, usize, zero) do {} while (0) +#define JEMALLOC_VALGRIND_REALLOC(maybe_moved, ptr, usize, \ + ptr_maybe_null, old_ptr, old_usize, old_rzsize, old_ptr_maybe_null, \ + zero) do {} while (0) +#define JEMALLOC_VALGRIND_FREE(ptr, rzsize) do {} while (0) +#endif + +#endif /* JEMALLOC_H_TYPES */ +/******************************************************************************/ +#ifdef JEMALLOC_H_STRUCTS + +#endif /* JEMALLOC_H_STRUCTS */ +/******************************************************************************/ +#ifdef JEMALLOC_H_EXTERNS + +#ifdef JEMALLOC_VALGRIND +void valgrind_make_mem_noaccess(void *ptr, size_t usize); +void valgrind_make_mem_undefined(void *ptr, size_t usize); +void valgrind_make_mem_defined(void *ptr, size_t usize); +void valgrind_freelike_block(void *ptr, size_t usize); +#endif + +#endif /* JEMALLOC_H_EXTERNS */ +/******************************************************************************/ +#ifdef JEMALLOC_H_INLINES + +#endif /* JEMALLOC_H_INLINES */ +/******************************************************************************/ + diff --git a/src/jemalloc/include/jemalloc/internal/vector.h b/src/jemalloc/include/jemalloc/internal/vector.h new file mode 100644 index 0000000000000000000000000000000000000000..8cbd747bdcf83a48a09df177f75141c92d258b63 --- /dev/null +++ b/src/jemalloc/include/jemalloc/internal/vector.h @@ -0,0 +1,38 @@ +/******************************************************************************/ +#ifdef JEMALLOC_H_TYPES + +typedef struct vector_s vector_t; +typedef struct vec_list_s vec_list_t; + +#define VECTOR_MIN_PART_SIZE 8 + +#define VECTOR_INITIALIZER JEMALLOC_ARG_CONCAT({.data = NULL, .size = 0}) + +#endif /* JEMALLOC_H_TYPES */ +/******************************************************************************/ +#ifdef JEMALLOC_H_STRUCTS + +struct vec_list_s { + vec_list_t *next; + int length; + void *data[]; +}; + +struct vector_s { + vec_list_t *list; +}; + +#endif /* JEMALLOC_H_STRUCTS */ +/******************************************************************************/ +#ifdef JEMALLOC_H_EXTERNS + +void *vec_get(vector_t *vector, int index); +void vec_set(vector_t *vector, int index, void *val); +void vec_delete(vector_t *vector); + +#endif /* JEMALLOC_H_EXTERNS */ +/******************************************************************************/ +#ifdef JEMALLOC_H_INLINES + +#endif /* JEMALLOC_H_INLINES */ +/******************************************************************************/ diff --git a/src/jemalloc/include/jemalloc/jemalloc_defs.h.in b/src/jemalloc/include/jemalloc/jemalloc_defs.h.in index eb38d7105ca54882fe3c9e30d8d9dac7873696b9..ce6c6987c5b07d4fbea4b3f62b4d8c5e31d78cf0 100644 --- a/src/jemalloc/include/jemalloc/jemalloc_defs.h.in +++ b/src/jemalloc/include/jemalloc/jemalloc_defs.h.in @@ -1,9 +1,6 @@ /* Defined if __attribute__((...)) syntax is supported. */ #undef JEMALLOC_HAVE_ATTR -/* Support the experimental API. */ -#undef JEMALLOC_EXPERIMENTAL - /* * Define overrides for non-standard allocator-related functions if they are * present on the system. diff --git a/src/jemalloc/include/jemalloc/jemalloc_macros.h.in b/src/jemalloc/include/jemalloc/jemalloc_macros.h.in index 13dbdd91209a46cf5a845a4182ec362557efa3c1..0f09bea1e7814bb0358cc0790d91f151d9601f7e 100644 --- a/src/jemalloc/include/jemalloc/jemalloc_macros.h.in +++ b/src/jemalloc/include/jemalloc/jemalloc_macros.h.in @@ -1,5 +1,6 @@ #include <limits.h> #include <strings.h> +#include <stdbool.h> #define JEMALLOC_VERSION "@jemalloc_version@" #define JEMALLOC_VERSION_MAJOR @jemalloc_version_major@ @@ -19,23 +20,6 @@ /* Bias arena index bits so that 0 encodes "MALLOCX_ARENA() unspecified". */ # define MALLOCX_ARENA(a) ((int)(((a)+1) << 8)) -#ifdef JEMALLOC_EXPERIMENTAL -# define ALLOCM_LG_ALIGN(la) (la) -# if LG_SIZEOF_PTR == 2 -# define ALLOCM_ALIGN(a) (ffs(a)-1) -# else -# define ALLOCM_ALIGN(a) \ - ((a < (size_t)INT_MAX) ? ffs(a)-1 : ffs(a>>32)+31) -# endif -# define ALLOCM_ZERO ((int)0x40) -# define ALLOCM_NO_MOVE ((int)0x80) -/* Bias arena index bits so that 0 encodes "ALLOCM_ARENA() unspecified". */ -# define ALLOCM_ARENA(a) ((int)(((a)+1) << 8)) -# define ALLOCM_SUCCESS 0 -# define ALLOCM_ERR_OOM 1 -# define ALLOCM_ERR_NOT_MOVED 2 -#endif - #ifdef JEMALLOC_HAVE_ATTR # define JEMALLOC_ATTR(s) __attribute__((s)) # define JEMALLOC_EXPORT JEMALLOC_ATTR(visibility("default")) diff --git a/src/jemalloc/include/jemalloc/jemalloc_protos.h.in b/src/jemalloc/include/jemalloc/jemalloc_protos.h.in index 25446de3d96ec376f26e8cf33b745aa0705bb116..8a2e35a0e8393ce1f29b85d417a4d239ed96e3c4 100644 --- a/src/jemalloc/include/jemalloc/jemalloc_protos.h.in +++ b/src/jemalloc/include/jemalloc/jemalloc_protos.h.in @@ -7,6 +7,23 @@ extern JEMALLOC_EXPORT const char *@je_@malloc_conf; extern JEMALLOC_EXPORT void (*@je_@malloc_message)(void *cbopaque, const char *s); +typedef struct pool_s pool_t; + +JEMALLOC_EXPORT pool_t *@je_@pool_create(void *addr, size_t size, int zeroed); +JEMALLOC_EXPORT void @je_@pool_delete(pool_t *pool); +JEMALLOC_EXPORT size_t @je_@pool_extend(pool_t *pool, void *addr, + size_t size, int zeroed); +JEMALLOC_EXPORT void *@je_@pool_malloc(pool_t *pool, size_t size); +JEMALLOC_EXPORT void *@je_@pool_calloc(pool_t *pool, size_t nmemb, size_t size); +JEMALLOC_EXPORT void *@je_@pool_ralloc(pool_t *pool, void *ptr, size_t size); +JEMALLOC_EXPORT void *@je_@pool_aligned_alloc(pool_t *pool, size_t alignment, size_t size); +JEMALLOC_EXPORT void @je_@pool_free(pool_t *pool, void *ptr); +JEMALLOC_EXPORT void @je_@pool_malloc_stats_print(pool_t *pool, + void (*write_cb)(void *, const char *), + void *cbopaque, const char *opts); +JEMALLOC_EXPORT void @je_@pool_set_alloc_funcs(void *(*malloc_func)(size_t), + void (*free_func)(void *)); + JEMALLOC_EXPORT void *@je_@malloc(size_t size) JEMALLOC_ATTR(malloc); JEMALLOC_EXPORT void *@je_@calloc(size_t num, size_t size) JEMALLOC_ATTR(malloc); @@ -45,14 +62,5 @@ JEMALLOC_EXPORT void * @je_@memalign(size_t alignment, size_t size) JEMALLOC_EXPORT void * @je_@valloc(size_t size) JEMALLOC_ATTR(malloc); #endif -#ifdef JEMALLOC_EXPERIMENTAL -JEMALLOC_EXPORT int @je_@allocm(void **ptr, size_t *rsize, size_t size, - int flags) JEMALLOC_ATTR(nonnull(1)); -JEMALLOC_EXPORT int @je_@rallocm(void **ptr, size_t *rsize, size_t size, - size_t extra, int flags) JEMALLOC_ATTR(nonnull(1)); -JEMALLOC_EXPORT int @je_@sallocm(const void *ptr, size_t *rsize, int flags) - JEMALLOC_ATTR(nonnull(1)); -JEMALLOC_EXPORT int @je_@dallocm(void *ptr, int flags) - JEMALLOC_ATTR(nonnull(1)); -JEMALLOC_EXPORT int @je_@nallocm(size_t *rsize, size_t size, int flags); -#endif +typedef void *(chunk_alloc_t)(size_t, size_t, bool *, unsigned, pool_t *); +typedef bool (chunk_dalloc_t)(void *, size_t, unsigned, pool_t *); diff --git a/src/jemalloc/include/msvc_compat/C99/inttypes.h b/src/jemalloc/include/msvc_compat/C99/inttypes.h new file mode 100644 index 0000000000000000000000000000000000000000..a4e6b75cb9146411972426ebf530a21cf4dccb15 --- /dev/null +++ b/src/jemalloc/include/msvc_compat/C99/inttypes.h @@ -0,0 +1,313 @@ +// ISO C9x compliant inttypes.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006 Alexander Chemeris +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. The name of the author may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_INTTYPES_H_ // [ +#define _MSC_INTTYPES_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +#include "stdint.h" + +// 7.8 Format conversion of integer types + +typedef struct { + intmax_t quot; + intmax_t rem; +} imaxdiv_t; + +// 7.8.1 Macros for format specifiers + +#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198 + +#ifdef _WIN64 +# define __PRI64_PREFIX "l" +# define __PRIPTR_PREFIX "l" +#else +# define __PRI64_PREFIX "ll" +# define __PRIPTR_PREFIX +#endif + +// The fprintf macros for signed integers are: +#define PRId8 "d" +#define PRIi8 "i" +#define PRIdLEAST8 "d" +#define PRIiLEAST8 "i" +#define PRIdFAST8 "d" +#define PRIiFAST8 "i" + +#define PRId16 "hd" +#define PRIi16 "hi" +#define PRIdLEAST16 "hd" +#define PRIiLEAST16 "hi" +#define PRIdFAST16 "hd" +#define PRIiFAST16 "hi" + +#define PRId32 "d" +#define PRIi32 "i" +#define PRIdLEAST32 "d" +#define PRIiLEAST32 "i" +#define PRIdFAST32 "d" +#define PRIiFAST32 "i" + +#define PRId64 __PRI64_PREFIX "d" +#define PRIi64 __PRI64_PREFIX "i" +#define PRIdLEAST64 __PRI64_PREFIX "d" +#define PRIiLEAST64 __PRI64_PREFIX "i" +#define PRIdFAST64 __PRI64_PREFIX "d" +#define PRIiFAST64 __PRI64_PREFIX "i" + +#define PRIdMAX __PRI64_PREFIX "d" +#define PRIiMAX __PRI64_PREFIX "i" + +#define PRIdPTR __PRIPTR_PREFIX "d" +#define PRIiPTR __PRIPTR_PREFIX "i" + +// The fprintf macros for unsigned integers are: +#define PRIo8 "o" +#define PRIu8 "u" +#define PRIx8 "x" +#define PRIX8 "X" +#define PRIoLEAST8 "o" +#define PRIuLEAST8 "u" +#define PRIxLEAST8 "x" +#define PRIXLEAST8 "X" +#define PRIoFAST8 "o" +#define PRIuFAST8 "u" +#define PRIxFAST8 "x" +#define PRIXFAST8 "X" + +#define PRIo16 "ho" +#define PRIu16 "hu" +#define PRIx16 "hx" +#define PRIX16 "hX" +#define PRIoLEAST16 "ho" +#define PRIuLEAST16 "hu" +#define PRIxLEAST16 "hx" +#define PRIXLEAST16 "hX" +#define PRIoFAST16 "ho" +#define PRIuFAST16 "hu" +#define PRIxFAST16 "hx" +#define PRIXFAST16 "hX" + +#define PRIo32 "o" +#define PRIu32 "u" +#define PRIx32 "x" +#define PRIX32 "X" +#define PRIoLEAST32 "o" +#define PRIuLEAST32 "u" +#define PRIxLEAST32 "x" +#define PRIXLEAST32 "X" +#define PRIoFAST32 "o" +#define PRIuFAST32 "u" +#define PRIxFAST32 "x" +#define PRIXFAST32 "X" + +#define PRIo64 __PRI64_PREFIX "o" +#define PRIu64 __PRI64_PREFIX "u" +#define PRIx64 __PRI64_PREFIX "x" +#define PRIX64 __PRI64_PREFIX "X" +#define PRIoLEAST64 __PRI64_PREFIX "o" +#define PRIuLEAST64 __PRI64_PREFIX "u" +#define PRIxLEAST64 __PRI64_PREFIX "x" +#define PRIXLEAST64 __PRI64_PREFIX "X" +#define PRIoFAST64 __PRI64_PREFIX "o" +#define PRIuFAST64 __PRI64_PREFIX "u" +#define PRIxFAST64 __PRI64_PREFIX "x" +#define PRIXFAST64 __PRI64_PREFIX "X" + +#define PRIoMAX __PRI64_PREFIX "o" +#define PRIuMAX __PRI64_PREFIX "u" +#define PRIxMAX __PRI64_PREFIX "x" +#define PRIXMAX __PRI64_PREFIX "X" + +#define PRIoPTR __PRIPTR_PREFIX "o" +#define PRIuPTR __PRIPTR_PREFIX "u" +#define PRIxPTR __PRIPTR_PREFIX "x" +#define PRIXPTR __PRIPTR_PREFIX "X" + +// The fscanf macros for signed integers are: +#define SCNd8 "d" +#define SCNi8 "i" +#define SCNdLEAST8 "d" +#define SCNiLEAST8 "i" +#define SCNdFAST8 "d" +#define SCNiFAST8 "i" + +#define SCNd16 "hd" +#define SCNi16 "hi" +#define SCNdLEAST16 "hd" +#define SCNiLEAST16 "hi" +#define SCNdFAST16 "hd" +#define SCNiFAST16 "hi" + +#define SCNd32 "ld" +#define SCNi32 "li" +#define SCNdLEAST32 "ld" +#define SCNiLEAST32 "li" +#define SCNdFAST32 "ld" +#define SCNiFAST32 "li" + +#define SCNd64 "I64d" +#define SCNi64 "I64i" +#define SCNdLEAST64 "I64d" +#define SCNiLEAST64 "I64i" +#define SCNdFAST64 "I64d" +#define SCNiFAST64 "I64i" + +#define SCNdMAX "I64d" +#define SCNiMAX "I64i" + +#ifdef _WIN64 // [ +# define SCNdPTR "I64d" +# define SCNiPTR "I64i" +#else // _WIN64 ][ +# define SCNdPTR "ld" +# define SCNiPTR "li" +#endif // _WIN64 ] + +// The fscanf macros for unsigned integers are: +#define SCNo8 "o" +#define SCNu8 "u" +#define SCNx8 "x" +#define SCNX8 "X" +#define SCNoLEAST8 "o" +#define SCNuLEAST8 "u" +#define SCNxLEAST8 "x" +#define SCNXLEAST8 "X" +#define SCNoFAST8 "o" +#define SCNuFAST8 "u" +#define SCNxFAST8 "x" +#define SCNXFAST8 "X" + +#define SCNo16 "ho" +#define SCNu16 "hu" +#define SCNx16 "hx" +#define SCNX16 "hX" +#define SCNoLEAST16 "ho" +#define SCNuLEAST16 "hu" +#define SCNxLEAST16 "hx" +#define SCNXLEAST16 "hX" +#define SCNoFAST16 "ho" +#define SCNuFAST16 "hu" +#define SCNxFAST16 "hx" +#define SCNXFAST16 "hX" + +#define SCNo32 "lo" +#define SCNu32 "lu" +#define SCNx32 "lx" +#define SCNX32 "lX" +#define SCNoLEAST32 "lo" +#define SCNuLEAST32 "lu" +#define SCNxLEAST32 "lx" +#define SCNXLEAST32 "lX" +#define SCNoFAST32 "lo" +#define SCNuFAST32 "lu" +#define SCNxFAST32 "lx" +#define SCNXFAST32 "lX" + +#define SCNo64 "I64o" +#define SCNu64 "I64u" +#define SCNx64 "I64x" +#define SCNX64 "I64X" +#define SCNoLEAST64 "I64o" +#define SCNuLEAST64 "I64u" +#define SCNxLEAST64 "I64x" +#define SCNXLEAST64 "I64X" +#define SCNoFAST64 "I64o" +#define SCNuFAST64 "I64u" +#define SCNxFAST64 "I64x" +#define SCNXFAST64 "I64X" + +#define SCNoMAX "I64o" +#define SCNuMAX "I64u" +#define SCNxMAX "I64x" +#define SCNXMAX "I64X" + +#ifdef _WIN64 // [ +# define SCNoPTR "I64o" +# define SCNuPTR "I64u" +# define SCNxPTR "I64x" +# define SCNXPTR "I64X" +#else // _WIN64 ][ +# define SCNoPTR "lo" +# define SCNuPTR "lu" +# define SCNxPTR "lx" +# define SCNXPTR "lX" +#endif // _WIN64 ] + +#endif // __STDC_FORMAT_MACROS ] + +// 7.8.2 Functions for greatest-width integer types + +// 7.8.2.1 The imaxabs function +#define imaxabs _abs64 + +// 7.8.2.2 The imaxdiv function + +// This is modified version of div() function from Microsoft's div.c found +// in %MSVC.NET%\crt\src\div.c +#ifdef STATIC_IMAXDIV // [ +static +#else // STATIC_IMAXDIV ][ +_inline +#endif // STATIC_IMAXDIV ] +imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom) +{ + imaxdiv_t result; + + result.quot = numer / denom; + result.rem = numer % denom; + + if (numer < 0 && result.rem > 0) { + // did division wrong; must fix up + ++result.quot; + result.rem -= denom; + } + + return result; +} + +// 7.8.2.3 The strtoimax and strtoumax functions +#define strtoimax _strtoi64 +#define strtoumax _strtoui64 + +// 7.8.2.4 The wcstoimax and wcstoumax functions +#define wcstoimax _wcstoi64 +#define wcstoumax _wcstoui64 + + +#endif // _MSC_INTTYPES_H_ ] diff --git a/src/jemalloc/include/msvc_compat/C99/stdbool.h b/src/jemalloc/include/msvc_compat/C99/stdbool.h new file mode 100644 index 0000000000000000000000000000000000000000..d92160ebc752ff28f9b9f66cd9b5c0d7755c3f4d --- /dev/null +++ b/src/jemalloc/include/msvc_compat/C99/stdbool.h @@ -0,0 +1,20 @@ +#ifndef stdbool_h +#define stdbool_h + +#include <wtypes.h> + +/* MSVC doesn't define _Bool or bool in C, but does have BOOL */ +/* Note this doesn't pass autoconf's test because (bool) 0.5 != true */ +/* Clang-cl uses MSVC headers, so needs msvc_compat, but has _Bool as + * a built-in type. */ +#ifndef __clang__ +typedef BOOL _Bool; +#endif + +#define bool _Bool +#define true 1 +#define false 0 + +#define __bool_true_false_are_defined 1 + +#endif /* stdbool_h */ diff --git a/src/jemalloc/include/msvc_compat/C99/stdint.h b/src/jemalloc/include/msvc_compat/C99/stdint.h new file mode 100644 index 0000000000000000000000000000000000000000..d02608a5972642c7b7a13b987f21e2502a5af3ea --- /dev/null +++ b/src/jemalloc/include/msvc_compat/C99/stdint.h @@ -0,0 +1,247 @@ +// ISO C9x compliant stdint.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006-2008 Alexander Chemeris +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. The name of the author may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_STDINT_H_ // [ +#define _MSC_STDINT_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +#include <limits.h> + +// For Visual Studio 6 in C++ mode and for many Visual Studio versions when +// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}' +// or compiler give many errors like this: +// error C2733: second C linkage of overloaded function 'wmemchr' not allowed +#ifdef __cplusplus +extern "C" { +#endif +# include <wchar.h> +#ifdef __cplusplus +} +#endif + +// Define _W64 macros to mark types changing their size, like intptr_t. +#ifndef _W64 +# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 +# define _W64 __w64 +# else +# define _W64 +# endif +#endif + + +// 7.18.1 Integer types + +// 7.18.1.1 Exact-width integer types + +// Visual Studio 6 and Embedded Visual C++ 4 doesn't +// realize that, e.g. char has the same size as __int8 +// so we give up on __intX for them. +#if (_MSC_VER < 1300) + typedef signed char int8_t; + typedef signed short int16_t; + typedef signed int int32_t; + typedef unsigned char uint8_t; + typedef unsigned short uint16_t; + typedef unsigned int uint32_t; +#else + typedef signed __int8 int8_t; + typedef signed __int16 int16_t; + typedef signed __int32 int32_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; +#endif +typedef signed __int64 int64_t; +typedef unsigned __int64 uint64_t; + + +// 7.18.1.2 Minimum-width integer types +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +typedef int64_t int_least64_t; +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +typedef uint64_t uint_least64_t; + +// 7.18.1.3 Fastest minimum-width integer types +typedef int8_t int_fast8_t; +typedef int16_t int_fast16_t; +typedef int32_t int_fast32_t; +typedef int64_t int_fast64_t; +typedef uint8_t uint_fast8_t; +typedef uint16_t uint_fast16_t; +typedef uint32_t uint_fast32_t; +typedef uint64_t uint_fast64_t; + +// 7.18.1.4 Integer types capable of holding object pointers +#ifdef _WIN64 // [ + typedef signed __int64 intptr_t; + typedef unsigned __int64 uintptr_t; +#else // _WIN64 ][ + typedef _W64 signed int intptr_t; + typedef _W64 unsigned int uintptr_t; +#endif // _WIN64 ] + +// 7.18.1.5 Greatest-width integer types +typedef int64_t intmax_t; +typedef uint64_t uintmax_t; + + +// 7.18.2 Limits of specified-width integer types + +#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 + +// 7.18.2.1 Limits of exact-width integer types +#define INT8_MIN ((int8_t)_I8_MIN) +#define INT8_MAX _I8_MAX +#define INT16_MIN ((int16_t)_I16_MIN) +#define INT16_MAX _I16_MAX +#define INT32_MIN ((int32_t)_I32_MIN) +#define INT32_MAX _I32_MAX +#define INT64_MIN ((int64_t)_I64_MIN) +#define INT64_MAX _I64_MAX +#define UINT8_MAX _UI8_MAX +#define UINT16_MAX _UI16_MAX +#define UINT32_MAX _UI32_MAX +#define UINT64_MAX _UI64_MAX + +// 7.18.2.2 Limits of minimum-width integer types +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MIN INT64_MIN +#define INT_LEAST64_MAX INT64_MAX +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +// 7.18.2.3 Limits of fastest minimum-width integer types +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST16_MIN INT16_MIN +#define INT_FAST16_MAX INT16_MAX +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST32_MAX INT32_MAX +#define INT_FAST64_MIN INT64_MIN +#define INT_FAST64_MAX INT64_MAX +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST16_MAX UINT16_MAX +#define UINT_FAST32_MAX UINT32_MAX +#define UINT_FAST64_MAX UINT64_MAX + +// 7.18.2.4 Limits of integer types capable of holding object pointers +#ifdef _WIN64 // [ +# define INTPTR_MIN INT64_MIN +# define INTPTR_MAX INT64_MAX +# define UINTPTR_MAX UINT64_MAX +#else // _WIN64 ][ +# define INTPTR_MIN INT32_MIN +# define INTPTR_MAX INT32_MAX +# define UINTPTR_MAX UINT32_MAX +#endif // _WIN64 ] + +// 7.18.2.5 Limits of greatest-width integer types +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +// 7.18.3 Limits of other integer types + +#ifdef _WIN64 // [ +# define PTRDIFF_MIN _I64_MIN +# define PTRDIFF_MAX _I64_MAX +#else // _WIN64 ][ +# define PTRDIFF_MIN _I32_MIN +# define PTRDIFF_MAX _I32_MAX +#endif // _WIN64 ] + +#define SIG_ATOMIC_MIN INT_MIN +#define SIG_ATOMIC_MAX INT_MAX + +#ifndef SIZE_MAX // [ +# ifdef _WIN64 // [ +# define SIZE_MAX _UI64_MAX +# else // _WIN64 ][ +# define SIZE_MAX _UI32_MAX +# endif // _WIN64 ] +#endif // SIZE_MAX ] + +// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h> +#ifndef WCHAR_MIN // [ +# define WCHAR_MIN 0 +#endif // WCHAR_MIN ] +#ifndef WCHAR_MAX // [ +# define WCHAR_MAX _UI16_MAX +#endif // WCHAR_MAX ] + +#define WINT_MIN 0 +#define WINT_MAX _UI16_MAX + +#endif // __STDC_LIMIT_MACROS ] + + +// 7.18.4 Limits of other integer types + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 + +// 7.18.4.1 Macros for minimum-width integer constants + +#define INT8_C(val) val##i8 +#define INT16_C(val) val##i16 +#define INT32_C(val) val##i32 +#define INT64_C(val) val##i64 + +#define UINT8_C(val) val##ui8 +#define UINT16_C(val) val##ui16 +#define UINT32_C(val) val##ui32 +#define UINT64_C(val) val##ui64 + +// 7.18.4.2 Macros for greatest-width integer constants +#define INTMAX_C INT64_C +#define UINTMAX_C UINT64_C + +#endif // __STDC_CONSTANT_MACROS ] + + +#endif // _MSC_STDINT_H_ ] diff --git a/src/jemalloc/src/arena.c b/src/jemalloc/src/arena.c index dad707b63d0539d0b78511751a0c4fed53862693..5212d748b73256e9bfe11e9a079ec25eabe9fec0 100644 --- a/src/jemalloc/src/arena.c +++ b/src/jemalloc/src/arena.c @@ -8,33 +8,40 @@ ssize_t opt_lg_dirty_mult = LG_DIRTY_MULT_DEFAULT; arena_bin_info_t arena_bin_info[NBINS]; JEMALLOC_ALIGNED(CACHELINE) -const uint8_t small_size2bin[] = { -#define S2B_8(i) i, -#define S2B_16(i) S2B_8(i) S2B_8(i) -#define S2B_32(i) S2B_16(i) S2B_16(i) -#define S2B_64(i) S2B_32(i) S2B_32(i) -#define S2B_128(i) S2B_64(i) S2B_64(i) -#define S2B_256(i) S2B_128(i) S2B_128(i) -#define S2B_512(i) S2B_256(i) S2B_256(i) -#define S2B_1024(i) S2B_512(i) S2B_512(i) -#define S2B_2048(i) S2B_1024(i) S2B_1024(i) -#define S2B_4096(i) S2B_2048(i) S2B_2048(i) -#define S2B_8192(i) S2B_4096(i) S2B_4096(i) -#define SIZE_CLASS(bin, delta, size) \ - S2B_##delta(bin) +const uint32_t small_bin2size_tab[NBINS] = { +#define B2S_bin_yes(size) \ + size, +#define B2S_bin_no(size) +#define SC(index, lg_grp, lg_delta, ndelta, bin, lg_delta_lookup) \ + B2S_bin_##bin((ZU(1)<<lg_grp) + (ZU(ndelta)<<lg_delta)) SIZE_CLASSES +#undef B2S_bin_yes +#undef B2S_bin_no +#undef SC +}; + +JEMALLOC_ALIGNED(CACHELINE) +const uint8_t small_size2bin_tab[] = { +#define S2B_3(i) i, +#define S2B_4(i) S2B_3(i) S2B_3(i) +#define S2B_5(i) S2B_4(i) S2B_4(i) +#define S2B_6(i) S2B_5(i) S2B_5(i) +#define S2B_7(i) S2B_6(i) S2B_6(i) +#define S2B_8(i) S2B_7(i) S2B_7(i) +#define S2B_9(i) S2B_8(i) S2B_8(i) +#define S2B_no(i) +#define SC(index, lg_grp, lg_delta, ndelta, bin, lg_delta_lookup) \ + S2B_##lg_delta_lookup(index) + SIZE_CLASSES +#undef S2B_3 +#undef S2B_4 +#undef S2B_5 +#undef S2B_6 +#undef S2B_7 #undef S2B_8 -#undef S2B_16 -#undef S2B_32 -#undef S2B_64 -#undef S2B_128 -#undef S2B_256 -#undef S2B_512 -#undef S2B_1024 -#undef S2B_2048 -#undef S2B_4096 -#undef S2B_8192 -#undef SIZE_CLASS +#undef S2B_9 +#undef S2B_no +#undef SC }; /******************************************************************************/ @@ -53,6 +60,22 @@ static void arena_bin_lower_run(arena_t *arena, arena_chunk_t *chunk, /******************************************************************************/ +JEMALLOC_INLINE_C size_t +arena_mapelm_to_pageind(arena_chunk_map_t *mapelm) +{ + uintptr_t map_offset = + CHUNK_ADDR2OFFSET(mapelm) - offsetof(arena_chunk_t, map); + + return ((map_offset / sizeof(arena_chunk_map_t)) + map_bias); +} + +JEMALLOC_INLINE_C size_t +arena_mapelm_to_bits(arena_chunk_map_t *mapelm) +{ + + return (mapelm->bits); +} + static inline int arena_run_comp(arena_chunk_map_t *a, arena_chunk_map_t *b) { @@ -73,26 +96,19 @@ static inline int arena_avail_comp(arena_chunk_map_t *a, arena_chunk_map_t *b) { int ret; - size_t a_size = a->bits & ~PAGE_MASK; - size_t b_size = b->bits & ~PAGE_MASK; - - ret = (a_size > b_size) - (a_size < b_size); - if (ret == 0) { - uintptr_t a_mapelm, b_mapelm; + size_t a_size; + size_t b_size = arena_mapelm_to_bits(b) & ~PAGE_MASK; + uintptr_t a_mapelm = (uintptr_t)a; + uintptr_t b_mapelm = (uintptr_t)b; - if ((a->bits & CHUNK_MAP_KEY) != CHUNK_MAP_KEY) - a_mapelm = (uintptr_t)a; - else { - /* - * Treat keys as though they are lower than anything - * else. - */ - a_mapelm = 0; - } - b_mapelm = (uintptr_t)b; + if (a_mapelm & CHUNK_MAP_KEY) + a_size = a_mapelm & ~PAGE_MASK; + else + a_size = arena_mapelm_to_bits(a) & ~PAGE_MASK; + ret = (a_size > b_size) - (a_size < b_size); + if (ret == 0 && (!(a_mapelm & CHUNK_MAP_KEY))) ret = (a_mapelm > b_mapelm) - (a_mapelm < b_mapelm); - } return (ret); } @@ -328,8 +344,8 @@ static inline void arena_run_zero(arena_chunk_t *chunk, size_t run_ind, size_t npages) { - VALGRIND_MAKE_MEM_UNDEFINED((void *)((uintptr_t)chunk + (run_ind << - LG_PAGE)), (npages << LG_PAGE)); + JEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED((void *)((uintptr_t)chunk + + (run_ind << LG_PAGE)), (npages << LG_PAGE)); memset((void *)((uintptr_t)chunk + (run_ind << LG_PAGE)), 0, (npages << LG_PAGE)); } @@ -338,8 +354,8 @@ static inline void arena_run_page_mark_zeroed(arena_chunk_t *chunk, size_t run_ind) { - VALGRIND_MAKE_MEM_DEFINED((void *)((uintptr_t)chunk + (run_ind << - LG_PAGE)), PAGE); + JEMALLOC_VALGRIND_MAKE_MEM_DEFINED((void *)((uintptr_t)chunk + (run_ind + << LG_PAGE)), PAGE); } static inline void @@ -362,7 +378,7 @@ arena_cactive_update(arena_t *arena, size_t add_pages, size_t sub_pages) add_pages) << LG_PAGE) - CHUNK_CEILING((arena->nactive - sub_pages) << LG_PAGE); if (cactive_diff != 0) - stats_cactive_add(cactive_diff); + stats_cactive_add(arena->pool, cactive_diff); } } @@ -448,7 +464,7 @@ arena_run_split_large_helper(arena_t *arena, arena_run_t *run, size_t size, arena_run_zero(chunk, run_ind, need_pages); } } else { - VALGRIND_MAKE_MEM_UNDEFINED((void *)((uintptr_t)chunk + + JEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED((void *)((uintptr_t)chunk + (run_ind << LG_PAGE)), (need_pages << LG_PAGE)); } @@ -516,7 +532,7 @@ arena_run_split_small(arena_t *arena, arena_run_t *run, size_t size, if (config_debug && flag_dirty == 0 && arena_mapbits_unzeroed_get(chunk, run_ind+need_pages-1) == 0) arena_run_page_validate_zeroed(chunk, run_ind+need_pages-1); - VALGRIND_MAKE_MEM_UNDEFINED((void *)((uintptr_t)chunk + + JEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED((void *)((uintptr_t)chunk + (run_ind << LG_PAGE)), (need_pages << LG_PAGE)); } @@ -542,6 +558,65 @@ arena_chunk_init_spare(arena_t *arena) return (chunk); } +static arena_chunk_t * +arena_chunk_alloc_internal(arena_t *arena, size_t size, size_t alignment, + bool *zero) +{ + arena_chunk_t *chunk; + chunk_alloc_t *chunk_alloc; + chunk_dalloc_t *chunk_dalloc; + + chunk_alloc = arena->chunk_alloc; + chunk_dalloc = arena->chunk_dalloc; + malloc_mutex_unlock(&arena->lock); + chunk = (arena_chunk_t *)chunk_alloc_arena(chunk_alloc, chunk_dalloc, + arena, size, alignment, zero); + malloc_mutex_lock(&arena->lock); + if (config_stats && chunk != NULL) + arena->stats.mapped += chunksize; + + return (chunk); +} + +void * +arena_chunk_alloc_huge(arena_t *arena, size_t size, size_t alignment, + bool *zero) +{ + void *ret; + chunk_alloc_t *chunk_alloc; + chunk_dalloc_t *chunk_dalloc; + + malloc_mutex_lock(&arena->lock); + chunk_alloc = arena->chunk_alloc; + chunk_dalloc = arena->chunk_dalloc; + if (config_stats) { + /* Optimistically update stats prior to unlocking. */ + arena->stats.mapped += size; + arena->stats.allocated_huge += size; + arena->stats.nmalloc_huge++; + arena->stats.nrequests_huge++; + } + arena->nactive += (size >> LG_PAGE); + malloc_mutex_unlock(&arena->lock); + + ret = chunk_alloc_arena(chunk_alloc, chunk_dalloc, arena, size, + alignment, zero); + if (config_stats) { + if (ret != NULL) + stats_cactive_add(arena->pool, size); + else { + /* Revert optimistic stats updates. */ + malloc_mutex_lock(&arena->lock); + arena->stats.mapped -= size; + arena->stats.allocated_huge -= size; + arena->stats.nmalloc_huge--; + malloc_mutex_unlock(&arena->lock); + } + } + + return (ret); +} + static arena_chunk_t * arena_chunk_init_hard(arena_t *arena) { @@ -552,14 +627,9 @@ arena_chunk_init_hard(arena_t *arena) assert(arena->spare == NULL); zero = false; - malloc_mutex_unlock(&arena->lock); - chunk = (arena_chunk_t *)chunk_alloc(chunksize, chunksize, false, - &zero, arena->dss_prec); - malloc_mutex_lock(&arena->lock); + chunk = arena_chunk_alloc_internal(arena, chunksize, chunksize, &zero); if (chunk == NULL) return (NULL); - if (config_stats) - arena->stats.mapped += chunksize; chunk->arena = arena; @@ -583,14 +653,14 @@ arena_chunk_init_hard(arena_t *arena) * the chunk is not zeroed. */ if (zero == false) { - VALGRIND_MAKE_MEM_UNDEFINED((void *)arena_mapp_get(chunk, - map_bias+1), (size_t)((uintptr_t) arena_mapp_get(chunk, - chunk_npages-1) - (uintptr_t)arena_mapp_get(chunk, - map_bias+1))); + JEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED( + (void *)arena_mapp_get(chunk, map_bias+1), + (size_t)((uintptr_t) arena_mapp_get(chunk, chunk_npages-1) - + (uintptr_t)arena_mapp_get(chunk, map_bias+1))); for (i = map_bias+1; i < chunk_npages-1; i++) arena_mapbits_unzeroed_set(chunk, i, unzeroed); } else { - VALGRIND_MAKE_MEM_DEFINED((void *)arena_mapp_get(chunk, + JEMALLOC_VALGRIND_MAKE_MEM_DEFINED((void *)arena_mapp_get(chunk, map_bias+1), (size_t)((uintptr_t) arena_mapp_get(chunk, chunk_npages-1) - (uintptr_t)arena_mapp_get(chunk, map_bias+1))); @@ -628,7 +698,38 @@ arena_chunk_alloc(arena_t *arena) } static void -arena_chunk_dealloc(arena_t *arena, arena_chunk_t *chunk) +arena_chunk_dalloc_internal(arena_t *arena, arena_chunk_t *chunk) +{ + chunk_dalloc_t *chunk_dalloc; + + chunk_dalloc = arena->chunk_dalloc; + malloc_mutex_unlock(&arena->lock); + chunk_dalloc((void *)chunk, chunksize, arena->ind, arena->pool); + malloc_mutex_lock(&arena->lock); + if (config_stats) + arena->stats.mapped -= chunksize; +} + +void +arena_chunk_dalloc_huge(arena_t *arena, void *chunk, size_t size) +{ + chunk_dalloc_t *chunk_dalloc; + + malloc_mutex_lock(&arena->lock); + chunk_dalloc = arena->chunk_dalloc; + if (config_stats) { + arena->stats.mapped -= size; + arena->stats.allocated_huge -= size; + arena->stats.ndalloc_huge++; + stats_cactive_sub(arena->pool, size); + } + arena->nactive -= (size >> LG_PAGE); + malloc_mutex_unlock(&arena->lock); + chunk_dalloc(chunk, size, arena->ind, arena->pool); +} + +static void +arena_chunk_dalloc(arena_t *arena, arena_chunk_t *chunk) { assert(arena_mapbits_allocated_get(chunk, map_bias) == 0); assert(arena_mapbits_allocated_get(chunk, chunk_npages-1) == 0); @@ -650,11 +751,7 @@ arena_chunk_dealloc(arena_t *arena, arena_chunk_t *chunk) arena_chunk_t *spare = arena->spare; arena->spare = chunk; - malloc_mutex_unlock(&arena->lock); - chunk_dealloc((void *)spare, chunksize, true); - malloc_mutex_lock(&arena->lock); - if (config_stats) - arena->stats.mapped -= chunksize; + arena_chunk_dalloc_internal(arena, spare); } else arena->spare = chunk; } @@ -663,15 +760,14 @@ static arena_run_t * arena_run_alloc_large_helper(arena_t *arena, size_t size, bool zero) { arena_run_t *run; - arena_chunk_map_t *mapelm, key; + arena_chunk_map_t *mapelm; + arena_chunk_map_t *key; - key.bits = size | CHUNK_MAP_KEY; - mapelm = arena_avail_tree_nsearch(&arena->runs_avail, &key); + key = (arena_chunk_map_t *)(size | CHUNK_MAP_KEY); + mapelm = arena_avail_tree_nsearch(&arena->runs_avail, key); if (mapelm != NULL) { arena_chunk_t *run_chunk = CHUNK_ADDR2BASE(mapelm); - size_t pageind = (((uintptr_t)mapelm - - (uintptr_t)run_chunk->map) / sizeof(arena_chunk_map_t)) - + map_bias; + size_t pageind = arena_mapelm_to_pageind(mapelm); run = (arena_run_t *)((uintptr_t)run_chunk + (pageind << LG_PAGE)); @@ -718,15 +814,14 @@ static arena_run_t * arena_run_alloc_small_helper(arena_t *arena, size_t size, size_t binind) { arena_run_t *run; - arena_chunk_map_t *mapelm, key; + arena_chunk_map_t *mapelm; + arena_chunk_map_t *key; - key.bits = size | CHUNK_MAP_KEY; - mapelm = arena_avail_tree_nsearch(&arena->runs_avail, &key); + key = (arena_chunk_map_t *)(size | CHUNK_MAP_KEY); + mapelm = arena_avail_tree_nsearch(&arena->runs_avail, key); if (mapelm != NULL) { arena_chunk_t *run_chunk = CHUNK_ADDR2BASE(mapelm); - size_t pageind = (((uintptr_t)mapelm - - (uintptr_t)run_chunk->map) / sizeof(arena_chunk_map_t)) - + map_bias; + size_t pageind = arena_mapelm_to_pageind(mapelm); run = (arena_run_t *)((uintptr_t)run_chunk + (pageind << LG_PAGE)); @@ -897,8 +992,7 @@ arena_chunk_purge_stashed(arena_t *arena, arena_chunk_t *chunk, bool unzeroed; size_t flag_unzeroed, i; - pageind = (((uintptr_t)mapelm - (uintptr_t)chunk->map) / - sizeof(arena_chunk_map_t)) + map_bias; + pageind = arena_mapelm_to_pageind(mapelm); npages = arena_mapbits_large_size_get(chunk, pageind) >> LG_PAGE; assert(pageind + npages <= chunk_npages); @@ -942,8 +1036,7 @@ arena_chunk_unstash_purged(arena_t *arena, arena_chunk_t *chunk, mapelm = ql_first(mapelms)) { arena_run_t *run; - pageind = (((uintptr_t)mapelm - (uintptr_t)chunk->map) / - sizeof(arena_chunk_map_t)) + map_bias; + pageind = arena_mapelm_to_pageind(mapelm); run = (arena_run_t *)((uintptr_t)chunk + (uintptr_t)(pageind << LG_PAGE)); ql_remove(mapelms, mapelm, u.ql_link); @@ -1082,7 +1175,6 @@ arena_purge(arena_t *arena, bool all) void arena_purge_all(arena_t *arena) { - malloc_mutex_lock(&arena->lock); arena_purge(arena, true); malloc_mutex_unlock(&arena->lock); @@ -1218,7 +1310,7 @@ arena_run_dalloc(arena_t *arena, arena_run_t *run, bool dirty, bool cleaned) if (size == arena_maxclass) { assert(run_ind == map_bias); assert(run_pages == (arena_maxclass >> LG_PAGE)); - arena_chunk_dealloc(arena, chunk); + arena_chunk_dalloc(arena, chunk); } /* @@ -1307,8 +1399,7 @@ arena_bin_runs_first(arena_bin_t *bin) arena_run_t *run; chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(mapelm); - pageind = ((((uintptr_t)mapelm - (uintptr_t)chunk->map) / - sizeof(arena_chunk_map_t))) + map_bias; + pageind = arena_mapelm_to_pageind(mapelm); run = (arena_run_t *)((uintptr_t)chunk + (uintptr_t)((pageind - arena_mapbits_small_runind_get(chunk, pageind)) << LG_PAGE)); @@ -1485,8 +1576,7 @@ arena_tcache_fill_small(arena_t *arena, tcache_bin_t *tbin, size_t binind, arena_alloc_junk_small(ptr, &arena_bin_info[binind], true); } - /* Insert such that low regions get used first. */ - tbin->avail[nfill - 1 - i] = ptr; + tbin->avail[i] = ptr; } if (config_stats) { bin->stats.allocated += i * arena_bin_info[binind].reg_size; @@ -1595,7 +1685,7 @@ arena_quarantine_junk_small(void *ptr, size_t usize) assert(opt_quarantine); assert(usize <= SMALL_MAXCLASS); - binind = SMALL_SIZE2BIN(usize); + binind = small_size2bin(usize); bin_info = &arena_bin_info[binind]; arena_redzones_validate(ptr, bin_info, true); } @@ -1608,10 +1698,10 @@ arena_malloc_small(arena_t *arena, size_t size, bool zero) arena_run_t *run; size_t binind; - binind = SMALL_SIZE2BIN(size); + binind = small_size2bin(size); assert(binind < NBINS); bin = &arena->bins[binind]; - size = arena_bin_info[binind].reg_size; + size = small_bin2size(binind); malloc_mutex_lock(&bin->lock); if ((run = bin->runcur) != NULL && run->nfree > 0) @@ -1641,13 +1731,13 @@ arena_malloc_small(arena_t *arena, size_t size, bool zero) } else if (opt_zero) memset(ret, 0, size); } - VALGRIND_MAKE_MEM_UNDEFINED(ret, size); + JEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(ret, size); } else { if (config_fill && opt_junk) { arena_alloc_junk_small(ret, &arena_bin_info[binind], true); } - VALGRIND_MAKE_MEM_UNDEFINED(ret, size); + JEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(ret, size); memset(ret, 0, size); } @@ -1765,7 +1855,7 @@ arena_prof_promoted(const void *ptr, size_t size) chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE; - binind = SMALL_SIZE2BIN(size); + binind = small_size2bin(size); assert(binind < NBINS); arena_mapbits_large_binind_set(chunk, pageind, binind); @@ -1882,7 +1972,7 @@ arena_dalloc_bin_locked(arena_t *arena, arena_chunk_t *chunk, void *ptr, run = (arena_run_t *)((uintptr_t)chunk + (uintptr_t)((pageind - arena_mapbits_small_runind_get(chunk, pageind)) << LG_PAGE)); bin = run->bin; - binind = arena_ptr_small_binind_get(ptr, mapelm->bits); + binind = arena_ptr_small_binind_get(ptr, arena_mapbits_get(chunk, pageind)); bin_info = &arena_bin_info[binind]; if (config_fill || config_stats) size = bin_info->reg_size; @@ -2152,11 +2242,11 @@ arena_ralloc_no_move(void *ptr, size_t oldsize, size_t size, size_t extra, */ if (oldsize <= arena_maxclass) { if (oldsize <= SMALL_MAXCLASS) { - assert(arena_bin_info[SMALL_SIZE2BIN(oldsize)].reg_size + assert(arena_bin_info[small_size2bin(oldsize)].reg_size == oldsize); if ((size + extra <= SMALL_MAXCLASS && - SMALL_SIZE2BIN(size + extra) == - SMALL_SIZE2BIN(oldsize)) || (size <= oldsize && + small_size2bin(size + extra) == + small_size2bin(oldsize)) || (size <= oldsize && size + extra >= oldsize)) return (false); } else { @@ -2222,7 +2312,7 @@ arena_ralloc(arena_t *arena, void *ptr, size_t oldsize, size_t size, * expectation that the extra bytes will be reliably preserved. */ copysize = (size < oldsize) ? size : oldsize; - VALGRIND_MAKE_MEM_UNDEFINED(ret, copysize); + JEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(ret, copysize); memcpy(ret, ptr, copysize); iqalloct(ptr, try_tcache_dalloc); return (ret); @@ -2239,13 +2329,16 @@ arena_dss_prec_get(arena_t *arena) return (ret); } -void +bool arena_dss_prec_set(arena_t *arena, dss_prec_t dss_prec) { + if (have_dss == false) + return (dss_prec != dss_prec_disabled); malloc_mutex_lock(&arena->lock); arena->dss_prec = dss_prec; malloc_mutex_unlock(&arena->lock); + return (false); } void @@ -2268,6 +2361,10 @@ arena_stats_merge(arena_t *arena, const char **dss, size_t *nactive, astats->nmalloc_large += arena->stats.nmalloc_large; astats->ndalloc_large += arena->stats.ndalloc_large; astats->nrequests_large += arena->stats.nrequests_large; + astats->allocated_huge += arena->stats.allocated_huge; + astats->nmalloc_huge += arena->stats.nmalloc_huge; + astats->ndalloc_huge += arena->stats.ndalloc_huge; + astats->nrequests_huge += arena->stats.nrequests_huge; for (i = 0; i < nlclasses; i++) { lstats[i].nmalloc += arena->stats.lstats[i].nmalloc; @@ -2297,13 +2394,16 @@ arena_stats_merge(arena_t *arena, const char **dss, size_t *nactive, } bool -arena_new(arena_t *arena, unsigned ind) +arena_new(pool_t *pool, arena_t *arena, unsigned ind) { unsigned i; arena_bin_t *bin; arena->ind = ind; arena->nthreads = 0; + arena->chunk_alloc = chunk_alloc_default; + arena->chunk_dalloc = chunk_dalloc_default; + arena->pool = pool; if (malloc_mutex_init(&arena->lock)) return (true); @@ -2311,7 +2411,7 @@ arena_new(arena_t *arena, unsigned ind) if (config_stats) { memset(&arena->stats, 0, sizeof(arena_stats_t)); arena->stats.lstats = - (malloc_large_stats_t *)base_alloc(nlclasses * + (malloc_large_stats_t *)base_alloc(pool, nlclasses * sizeof(malloc_large_stats_t)); if (arena->stats.lstats == NULL) return (true); @@ -2369,7 +2469,6 @@ bin_info_run_size_calc(arena_bin_info_t *bin_info, size_t min_run_size) uint32_t try_nregs, good_nregs; uint32_t try_hdr_size, good_hdr_size; uint32_t try_bitmap_offset, good_bitmap_offset; - uint32_t try_ctx0_offset, good_ctx0_offset; uint32_t try_redzone0_offset, good_redzone0_offset; assert(min_run_size >= PAGE); @@ -2383,7 +2482,7 @@ bin_info_run_size_calc(arena_bin_info_t *bin_info, size_t min_run_size) * be twice as large in order to maintain alignment. */ if (config_fill && opt_redzone) { - size_t align_min = ZU(1) << (ffs(bin_info->reg_size) - 1); + size_t align_min = ZU(1) << (jemalloc_ffs(bin_info->reg_size) - 1); if (align_min <= REDZONE_MINSIZE) { bin_info->redzone_size = REDZONE_MINSIZE; pad_size = 0; @@ -2424,14 +2523,6 @@ bin_info_run_size_calc(arena_bin_info_t *bin_info, size_t min_run_size) try_bitmap_offset = try_hdr_size; /* Add space for bitmap. */ try_hdr_size += bitmap_size(try_nregs); - if (config_prof && opt_prof && prof_promote == false) { - /* Pad to a quantum boundary. */ - try_hdr_size = QUANTUM_CEILING(try_hdr_size); - try_ctx0_offset = try_hdr_size; - /* Add space for one (prof_ctx_t *) per region. */ - try_hdr_size += try_nregs * sizeof(prof_ctx_t *); - } else - try_ctx0_offset = 0; try_redzone0_offset = try_run_size - (try_nregs * bin_info->reg_interval) - pad_size; } while (try_hdr_size > try_redzone0_offset); @@ -2445,7 +2536,6 @@ bin_info_run_size_calc(arena_bin_info_t *bin_info, size_t min_run_size) good_nregs = try_nregs; good_hdr_size = try_hdr_size; good_bitmap_offset = try_bitmap_offset; - good_ctx0_offset = try_ctx0_offset; good_redzone0_offset = try_redzone0_offset; /* Try more aggressive settings. */ @@ -2465,16 +2555,6 @@ bin_info_run_size_calc(arena_bin_info_t *bin_info, size_t min_run_size) try_bitmap_offset = try_hdr_size; /* Add space for bitmap. */ try_hdr_size += bitmap_size(try_nregs); - if (config_prof && opt_prof && prof_promote == false) { - /* Pad to a quantum boundary. */ - try_hdr_size = QUANTUM_CEILING(try_hdr_size); - try_ctx0_offset = try_hdr_size; - /* - * Add space for one (prof_ctx_t *) per region. - */ - try_hdr_size += try_nregs * - sizeof(prof_ctx_t *); - } try_redzone0_offset = try_run_size - (try_nregs * bin_info->reg_interval) - pad_size; } while (try_hdr_size > try_redzone0_offset); @@ -2490,7 +2570,6 @@ bin_info_run_size_calc(arena_bin_info_t *bin_info, size_t min_run_size) bin_info->run_size = good_run_size; bin_info->nregs = good_nregs; bin_info->bitmap_offset = good_bitmap_offset; - bin_info->ctx0_offset = good_ctx0_offset; bin_info->reg0_offset = good_redzone0_offset + bin_info->redzone_size; assert(bin_info->reg0_offset - bin_info->redzone_size + (bin_info->nregs @@ -2505,13 +2584,18 @@ bin_info_init(void) arena_bin_info_t *bin_info; size_t prev_run_size = PAGE; -#define SIZE_CLASS(bin, delta, size) \ - bin_info = &arena_bin_info[bin]; \ +#define BIN_INFO_INIT_bin_yes(index, size) \ + bin_info = &arena_bin_info[index]; \ bin_info->reg_size = size; \ prev_run_size = bin_info_run_size_calc(bin_info, prev_run_size);\ bitmap_info_init(&bin_info->bitmap_info, bin_info->nregs); +#define BIN_INFO_INIT_bin_no(index, size) +#define SC(index, lg_grp, lg_delta, ndelta, bin, lg_delta_lookup) \ + BIN_INFO_INIT_bin_##bin(index, (ZU(1)<<lg_grp) + (ZU(ndelta)<<lg_delta)) SIZE_CLASSES -#undef SIZE_CLASS +#undef BIN_INFO_INIT_bin_yes +#undef BIN_INFO_INIT_bin_no +#undef SC } void diff --git a/src/jemalloc/src/base.c b/src/jemalloc/src/base.c index 4e62e8fa9189fe9ebdcdbbe7e49e38c62cb5de62..91178eba61f73db790bc0f07ecaff0e9548df2da 100644 --- a/src/jemalloc/src/base.c +++ b/src/jemalloc/src/base.c @@ -1,49 +1,26 @@ #define JEMALLOC_BASE_C_ #include "jemalloc/internal/jemalloc_internal.h" -/******************************************************************************/ -/* Data. */ - -static malloc_mutex_t base_mtx; - -/* - * Current pages that are being used for internal memory allocations. These - * pages are carved up in cacheline-size quanta, so that there is no chance of - * false cache line sharing. - */ -static void *base_pages; -static void *base_next_addr; -static void *base_past_addr; /* Addr immediately past base_pages. */ -static extent_node_t *base_nodes; - -/******************************************************************************/ -/* Function prototypes for non-inline static functions. */ - -static bool base_pages_alloc(size_t minsize); - -/******************************************************************************/ static bool -base_pages_alloc(size_t minsize) +base_pages_alloc(pool_t *pool, size_t minsize) { size_t csize; - bool zero; + void* base_pages; assert(minsize != 0); csize = CHUNK_CEILING(minsize); - zero = false; - base_pages = chunk_alloc(csize, chunksize, true, &zero, - chunk_dss_prec_get()); + base_pages = chunk_alloc_base(pool, csize); if (base_pages == NULL) return (true); - base_next_addr = base_pages; - base_past_addr = (void *)((uintptr_t)base_pages + csize); + pool->base_next_addr = base_pages; + pool->base_past_addr = (void *)((uintptr_t)base_pages + csize); return (false); } void * -base_alloc(size_t size) +base_alloc(pool_t *pool, size_t size) { void *ret; size_t csize; @@ -51,27 +28,27 @@ base_alloc(size_t size) /* Round size up to nearest multiple of the cacheline size. */ csize = CACHELINE_CEILING(size); - malloc_mutex_lock(&base_mtx); + malloc_mutex_lock(&pool->base_mtx); /* Make sure there's enough space for the allocation. */ - if ((uintptr_t)base_next_addr + csize > (uintptr_t)base_past_addr) { - if (base_pages_alloc(csize)) { - malloc_mutex_unlock(&base_mtx); + if ((uintptr_t)pool->base_next_addr + csize > (uintptr_t)pool->base_past_addr) { + if (base_pages_alloc(pool, csize)) { + malloc_mutex_unlock(&pool->base_mtx); return (NULL); } } /* Allocate. */ - ret = base_next_addr; - base_next_addr = (void *)((uintptr_t)base_next_addr + csize); - malloc_mutex_unlock(&base_mtx); - VALGRIND_MAKE_MEM_UNDEFINED(ret, csize); + ret = pool->base_next_addr; + pool->base_next_addr = (void *)((uintptr_t)pool->base_next_addr + csize); + malloc_mutex_unlock(&pool->base_mtx); + JEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(ret, csize); return (ret); } void * -base_calloc(size_t number, size_t size) +base_calloc(pool_t *pool, size_t number, size_t size) { - void *ret = base_alloc(number * size); + void *ret = base_alloc(pool, number * size); if (ret != NULL) memset(ret, 0, number * size); @@ -80,63 +57,88 @@ base_calloc(size_t number, size_t size) } extent_node_t * -base_node_alloc(void) +base_node_alloc(pool_t *pool) { extent_node_t *ret; - malloc_mutex_lock(&base_mtx); - if (base_nodes != NULL) { - ret = base_nodes; - base_nodes = *(extent_node_t **)ret; - malloc_mutex_unlock(&base_mtx); - VALGRIND_MAKE_MEM_UNDEFINED(ret, sizeof(extent_node_t)); + malloc_mutex_lock(&pool->base_node_mtx); + if (pool->base_nodes != NULL) { + ret = pool->base_nodes; + pool->base_nodes = *(extent_node_t **)ret; + JEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(ret, + sizeof(extent_node_t)); } else { - malloc_mutex_unlock(&base_mtx); - ret = (extent_node_t *)base_alloc(sizeof(extent_node_t)); + /* preallocated nodes for pools other than 0 */ + if (pool->pool_id == 0) { + ret = (extent_node_t *)base_alloc(pool, sizeof(extent_node_t)); + } else { + ret = NULL; + } } - + malloc_mutex_unlock(&pool->base_node_mtx); return (ret); } void -base_node_dealloc(extent_node_t *node) +base_node_dalloc(pool_t *pool, extent_node_t *node) { - VALGRIND_MAKE_MEM_UNDEFINED(node, sizeof(extent_node_t)); - malloc_mutex_lock(&base_mtx); - *(extent_node_t **)node = base_nodes; - base_nodes = node; - malloc_mutex_unlock(&base_mtx); + JEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(node, sizeof(extent_node_t)); + malloc_mutex_lock(&pool->base_node_mtx); + *(extent_node_t **)node = pool->base_nodes; + pool->base_nodes = node; + malloc_mutex_unlock(&pool->base_node_mtx); +} + +size_t +base_node_prealloc(pool_t *pool, size_t number) +{ + extent_node_t *node; + malloc_mutex_lock(&pool->base_node_mtx); + for (; number > 0; --number) { + node = (extent_node_t *)base_alloc(pool, sizeof(extent_node_t)); + if (node == NULL) + break; + JEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(node, sizeof(extent_node_t)); + *(extent_node_t **)node = pool->base_nodes; + pool->base_nodes = node; + } + malloc_mutex_unlock(&pool->base_node_mtx); + + /* return number of nodes that couldn't be allocated */ + return number; } bool -base_boot(void) +base_boot(pool_t *pool) { + pool->base_nodes = NULL; + if (malloc_mutex_init(&pool->base_mtx)) + return (true); - base_nodes = NULL; - if (malloc_mutex_init(&base_mtx)) + if (malloc_mutex_init(&pool->base_node_mtx)) return (true); return (false); } void -base_prefork(void) +base_prefork(pool_t *pool) { - malloc_mutex_prefork(&base_mtx); + malloc_mutex_prefork(&pool->base_mtx); } void -base_postfork_parent(void) +base_postfork_parent(pool_t *pool) { - malloc_mutex_postfork_parent(&base_mtx); + malloc_mutex_postfork_parent(&pool->base_mtx); } void -base_postfork_child(void) +base_postfork_child(pool_t *pool) { - malloc_mutex_postfork_child(&base_mtx); + malloc_mutex_postfork_child(&pool->base_mtx); } diff --git a/src/jemalloc/src/chunk.c b/src/jemalloc/src/chunk.c index 90ab116ae5fa42e53070ff03d389ff22420a25c1..746c6bc0aa82c6eedb7a07d6a5e28eb8396cc957 100644 --- a/src/jemalloc/src/chunk.c +++ b/src/jemalloc/src/chunk.c @@ -7,21 +7,6 @@ const char *opt_dss = DSS_DEFAULT; size_t opt_lg_chunk = LG_CHUNK_DEFAULT; -malloc_mutex_t chunks_mtx; -chunk_stats_t stats_chunks; - -/* - * Trees of chunks that were previously allocated (trees differ only in node - * ordering). These are used when allocating chunks, in an attempt to re-use - * address space. Depending on function, different tree orderings are needed, - * which is why there are two trees with the same contents. - */ -static extent_tree_t chunks_szad_mmap; -static extent_tree_t chunks_ad_mmap; -static extent_tree_t chunks_szad_dss; -static extent_tree_t chunks_ad_dss; - -rtree_t *chunks_rtree; /* Various chunk-related settings. */ size_t chunksize; @@ -31,18 +16,17 @@ size_t map_bias; size_t arena_maxclass; /* Max size class for arenas. */ /******************************************************************************/ -/* Function prototypes for non-inline static functions. */ +/* + * Function prototypes for static functions that are referenced prior to + * definition. + */ -static void *chunk_recycle(extent_tree_t *chunks_szad, - extent_tree_t *chunks_ad, size_t size, size_t alignment, bool base, - bool *zero); -static void chunk_record(extent_tree_t *chunks_szad, - extent_tree_t *chunks_ad, void *chunk, size_t size); +static void chunk_dalloc_core(pool_t *pool, void *chunk, size_t size); /******************************************************************************/ static void * -chunk_recycle(extent_tree_t *chunks_szad, extent_tree_t *chunks_ad, size_t size, +chunk_recycle(pool_t *pool, extent_tree_t *chunks_szad, extent_tree_t *chunks_ad, size_t size, size_t alignment, bool base, bool *zero) { void *ret; @@ -67,10 +51,10 @@ chunk_recycle(extent_tree_t *chunks_szad, extent_tree_t *chunks_ad, size_t size, return (NULL); key.addr = NULL; key.size = alloc_size; - malloc_mutex_lock(&chunks_mtx); + malloc_mutex_lock(&pool->chunks_mtx); node = extent_tree_szad_nsearch(chunks_szad, &key); if (node == NULL) { - malloc_mutex_unlock(&chunks_mtx); + malloc_mutex_unlock(&pool->chunks_mtx); return (NULL); } leadsize = ALIGNMENT_CEILING((uintptr_t)node->addr, alignment) - @@ -101,13 +85,13 @@ chunk_recycle(extent_tree_t *chunks_szad, extent_tree_t *chunks_ad, size_t size, * deadlock, and if node allocation fails, deallocate * the result before returning an error. */ - malloc_mutex_unlock(&chunks_mtx); - node = base_node_alloc(); + malloc_mutex_unlock(&pool->chunks_mtx); + node = base_node_alloc(pool); if (node == NULL) { - chunk_dealloc(ret, size, true); + chunk_dalloc_core(pool, ret, size); return (NULL); } - malloc_mutex_lock(&chunks_mtx); + malloc_mutex_lock(&pool->chunks_mtx); } node->addr = (void *)((uintptr_t)(ret) + size); node->size = trailsize; @@ -116,10 +100,10 @@ chunk_recycle(extent_tree_t *chunks_szad, extent_tree_t *chunks_ad, size_t size, extent_tree_ad_insert(chunks_ad, node); node = NULL; } - malloc_mutex_unlock(&chunks_mtx); + malloc_mutex_unlock(&pool->chunks_mtx); if (node != NULL) - base_node_dealloc(node); + base_node_dalloc(pool, node); if (*zero) { if (zeroed == false) memset(ret, 0, size); @@ -127,7 +111,7 @@ chunk_recycle(extent_tree_t *chunks_szad, extent_tree_t *chunks_ad, size_t size, size_t i; size_t *p = (size_t *)(uintptr_t)ret; - VALGRIND_MAKE_MEM_DEFINED(ret, size); + JEMALLOC_VALGRIND_MAKE_MEM_DEFINED(ret, size); for (i = 0; i < size / sizeof(size_t); i++) assert(p[i] == 0); } @@ -141,8 +125,8 @@ chunk_recycle(extent_tree_t *chunks_szad, extent_tree_t *chunks_ad, size_t size, * takes advantage of this to avoid demanding zeroed chunks, but taking * advantage of them if they are returned. */ -void * -chunk_alloc(size_t size, size_t alignment, bool base, bool *zero, +static void * +chunk_alloc_core(pool_t *pool, size_t size, size_t alignment, bool base, bool *zero, dss_prec_t dss_prec) { void *ret; @@ -152,72 +136,132 @@ chunk_alloc(size_t size, size_t alignment, bool base, bool *zero, assert(alignment != 0); assert((alignment & chunksize_mask) == 0); + /* Custom pools can only use existing chunks. */ + if (pool->pool_id != 0) { + return chunk_recycle(pool, + &pool->chunks_szad_mmap, &pool->chunks_ad_mmap, + size, alignment, false, zero); + } + /* "primary" dss. */ - if (config_dss && dss_prec == dss_prec_primary) { - if ((ret = chunk_recycle(&chunks_szad_dss, &chunks_ad_dss, size, + if (have_dss && dss_prec == dss_prec_primary) { + if ((ret = chunk_recycle(pool, &pool->chunks_szad_dss, &pool->chunks_ad_dss, size, alignment, base, zero)) != NULL) - goto label_return; + return (ret); if ((ret = chunk_alloc_dss(size, alignment, zero)) != NULL) - goto label_return; + return (ret); } /* mmap. */ - if ((ret = chunk_recycle(&chunks_szad_mmap, &chunks_ad_mmap, size, + if ((ret = chunk_recycle(pool, &pool->chunks_szad_mmap, &pool->chunks_ad_mmap, size, alignment, base, zero)) != NULL) - goto label_return; + return (ret); if ((ret = chunk_alloc_mmap(size, alignment, zero)) != NULL) - goto label_return; + return (ret); /* "secondary" dss. */ - if (config_dss && dss_prec == dss_prec_secondary) { - if ((ret = chunk_recycle(&chunks_szad_dss, &chunks_ad_dss, size, + if (have_dss && dss_prec == dss_prec_secondary) { + if ((ret = chunk_recycle(pool, &pool->chunks_szad_dss, &pool->chunks_ad_dss, size, alignment, base, zero)) != NULL) - goto label_return; + return (ret); if ((ret = chunk_alloc_dss(size, alignment, zero)) != NULL) - goto label_return; + return (ret); } /* All strategies for allocation failed. */ - ret = NULL; -label_return: - if (ret != NULL) { - if (config_ivsalloc && base == false) { - if (rtree_set(chunks_rtree, (uintptr_t)ret, 1)) { - chunk_dealloc(ret, size, true); - return (NULL); - } - } - if (config_stats || config_prof) { - bool gdump; - malloc_mutex_lock(&chunks_mtx); - if (config_stats) - stats_chunks.nchunks += (size / chunksize); - stats_chunks.curchunks += (size / chunksize); - if (stats_chunks.curchunks > stats_chunks.highchunks) { - stats_chunks.highchunks = - stats_chunks.curchunks; - if (config_prof) - gdump = true; - } else if (config_prof) - gdump = false; - malloc_mutex_unlock(&chunks_mtx); - if (config_prof && opt_prof && opt_prof_gdump && gdump) - prof_gdump(); - } - if (config_valgrind) - VALGRIND_MAKE_MEM_UNDEFINED(ret, size); + return (NULL); +} + +static bool +chunk_register(pool_t *pool, void *chunk, size_t size, bool base) +{ + assert(chunk != NULL); + assert(CHUNK_ADDR2BASE(chunk) == chunk); + + if (config_ivsalloc && base == false) { + if (rtree_set(pool->chunks_rtree, (uintptr_t)chunk, 1)) + return (true); + } + if (config_stats || config_prof) { + bool gdump; + malloc_mutex_lock(&pool->chunks_mtx); + if (config_stats) + pool->stats_chunks.nchunks += (size / chunksize); + pool->stats_chunks.curchunks += (size / chunksize); + if (pool->stats_chunks.curchunks > pool->stats_chunks.highchunks) { + pool->stats_chunks.highchunks = + pool->stats_chunks.curchunks; + if (config_prof) + gdump = true; + } else if (config_prof) + gdump = false; + malloc_mutex_unlock(&pool->chunks_mtx); + if (config_prof && opt_prof && opt_prof_gdump && gdump) + prof_gdump(); + } + if (config_valgrind) + JEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(chunk, size); + return (false); +} + +void * +chunk_alloc_base(pool_t *pool, size_t size) +{ + void *ret; + bool zero; + + zero = false; + ret = chunk_alloc_core(pool, size, chunksize, true, &zero, + chunk_dss_prec_get()); + if (ret == NULL) + return (NULL); + if (chunk_register(pool, ret, size, true)) { + chunk_dalloc_core(pool, ret, size); + return (NULL); } - assert(CHUNK_ADDR2BASE(ret) == ret); return (ret); } -static void -chunk_record(extent_tree_t *chunks_szad, extent_tree_t *chunks_ad, void *chunk, - size_t size) +void * +chunk_alloc_arena(chunk_alloc_t *chunk_alloc, chunk_dalloc_t *chunk_dalloc, + arena_t *arena, size_t size, size_t alignment, bool *zero) +{ + void *ret; + + ret = chunk_alloc(size, alignment, zero, + arena->ind, arena->pool); + if (ret != NULL && chunk_register(arena->pool, ret, size, false)) { + chunk_dalloc(ret, size, arena->ind, arena->pool); + ret = NULL; + } + + return (ret); +} + +/* Default arena chunk allocation routine in the absence of user override. */ +void * +chunk_alloc_default(size_t size, size_t alignment, bool *zero, + unsigned arena_ind, pool_t *pool) +{ + return (chunk_alloc_core(pool, size, alignment, false, zero, + pool->arenas[arena_ind]->dss_prec)); +} + +void +chunk_record(pool_t *pool, extent_tree_t *chunks_szad, extent_tree_t *chunks_ad, void *chunk, + size_t size, bool zeroed) { bool unzeroed; extent_node_t *xnode, *node, *prev, *xprev, key; unzeroed = pages_purge(chunk, size); - VALGRIND_MAKE_MEM_NOACCESS(chunk, size); + JEMALLOC_VALGRIND_MAKE_MEM_NOACCESS(chunk, size); + + /* + * If pages_purge() returned that the pages were zeroed + * as a side effect of purging we can safely do this assignment. + */ + if (zeroed == false && unzeroed == false) { + zeroed = true; + } /* * Allocate a node before acquiring chunks_mtx even though it might not @@ -225,11 +269,11 @@ chunk_record(extent_tree_t *chunks_szad, extent_tree_t *chunks_ad, void *chunk, * be allocated, which could cause deadlock if chunks_mtx were already * held. */ - xnode = base_node_alloc(); + xnode = base_node_alloc(pool); /* Use xprev to implement conditional deferred deallocation of prev. */ xprev = NULL; - malloc_mutex_lock(&chunks_mtx); + malloc_mutex_lock(&pool->chunks_mtx); key.addr = (void *)((uintptr_t)chunk + size); node = extent_tree_ad_nsearch(chunks_ad, &key); /* Try to coalesce forward. */ @@ -242,7 +286,7 @@ chunk_record(extent_tree_t *chunks_szad, extent_tree_t *chunks_ad, void *chunk, extent_tree_szad_remove(chunks_szad, node); node->addr = chunk; node->size += size; - node->zeroed = (node->zeroed && (unzeroed == false)); + node->zeroed = (node->zeroed && zeroed); extent_tree_szad_insert(chunks_szad, node); } else { /* Coalescing forward failed, so insert a new node. */ @@ -259,7 +303,7 @@ chunk_record(extent_tree_t *chunks_szad, extent_tree_t *chunks_ad, void *chunk, xnode = NULL; /* Prevent deallocation below. */ node->addr = chunk; node->size = size; - node->zeroed = (unzeroed == false); + node->zeroed = zeroed; extent_tree_ad_insert(chunks_ad, node); extent_tree_szad_insert(chunks_szad, node); } @@ -286,33 +330,33 @@ chunk_record(extent_tree_t *chunks_szad, extent_tree_t *chunks_ad, void *chunk, } label_return: - malloc_mutex_unlock(&chunks_mtx); + malloc_mutex_unlock(&pool->chunks_mtx); /* * Deallocate xnode and/or xprev after unlocking chunks_mtx in order to * avoid potential deadlock. */ if (xnode != NULL) - base_node_dealloc(xnode); + base_node_dalloc(pool, xnode); if (xprev != NULL) - base_node_dealloc(xprev); + base_node_dalloc(pool, xprev); } void -chunk_unmap(void *chunk, size_t size) +chunk_unmap(pool_t *pool, void *chunk, size_t size) { assert(chunk != NULL); assert(CHUNK_ADDR2BASE(chunk) == chunk); assert(size != 0); assert((size & chunksize_mask) == 0); - if (config_dss && chunk_in_dss(chunk)) - chunk_record(&chunks_szad_dss, &chunks_ad_dss, chunk, size); - else if (chunk_dealloc_mmap(chunk, size)) - chunk_record(&chunks_szad_mmap, &chunks_ad_mmap, chunk, size); + if (have_dss && chunk_in_dss(chunk)) + chunk_record(pool, &pool->chunks_szad_dss, &pool->chunks_ad_dss, chunk, size, false); + else if (chunk_dalloc_mmap(chunk, size)) + chunk_record(pool, &pool->chunks_szad_mmap, &pool->chunks_ad_mmap, chunk, size, false); } -void -chunk_dealloc(void *chunk, size_t size, bool unmap) +static void +chunk_dalloc_core(pool_t *pool, void *chunk, size_t size) { assert(chunk != NULL); @@ -321,43 +365,52 @@ chunk_dealloc(void *chunk, size_t size, bool unmap) assert((size & chunksize_mask) == 0); if (config_ivsalloc) - rtree_set(chunks_rtree, (uintptr_t)chunk, 0); + rtree_set(pool->chunks_rtree, (uintptr_t)chunk, 0); if (config_stats || config_prof) { - malloc_mutex_lock(&chunks_mtx); - assert(stats_chunks.curchunks >= (size / chunksize)); - stats_chunks.curchunks -= (size / chunksize); - malloc_mutex_unlock(&chunks_mtx); + malloc_mutex_lock(&pool->chunks_mtx); + assert(pool->stats_chunks.curchunks >= (size / chunksize)); + pool->stats_chunks.curchunks -= (size / chunksize); + malloc_mutex_unlock(&pool->chunks_mtx); } - if (unmap) - chunk_unmap(chunk, size); + chunk_unmap(pool, chunk, size); } +/* Default arena chunk deallocation routine in the absence of user override. */ bool -chunk_boot(void) +chunk_dalloc_default(void *chunk, size_t size, unsigned arena_ind, pool_t *pool) { + chunk_dalloc_core(pool, chunk, size); + return (false); +} +void +chunk_global_boot() { /* Set variables according to the value of opt_lg_chunk. */ chunksize = (ZU(1) << opt_lg_chunk); assert(chunksize >= PAGE); chunksize_mask = chunksize - 1; - chunk_npages = (chunksize >> LG_PAGE); + chunk_npages = (chunksize >> LG_PAGE); +} +bool +chunk_boot(pool_t *pool) +{ if (config_stats || config_prof) { - if (malloc_mutex_init(&chunks_mtx)) + if (malloc_mutex_init(&pool->chunks_mtx)) return (true); - memset(&stats_chunks, 0, sizeof(chunk_stats_t)); + memset(&pool->stats_chunks, 0, sizeof(chunk_stats_t)); } - if (config_dss && chunk_dss_boot()) + if (have_dss && chunk_dss_boot()) return (true); - extent_tree_szad_new(&chunks_szad_mmap); - extent_tree_ad_new(&chunks_ad_mmap); - extent_tree_szad_new(&chunks_szad_dss); - extent_tree_ad_new(&chunks_ad_dss); + extent_tree_szad_new(&pool->chunks_szad_mmap); + extent_tree_ad_new(&pool->chunks_ad_mmap); + extent_tree_szad_new(&pool->chunks_szad_dss); + extent_tree_ad_new(&pool->chunks_ad_dss); if (config_ivsalloc) { - chunks_rtree = rtree_new((ZU(1) << (LG_SIZEOF_PTR+3)) - - opt_lg_chunk, base_alloc, NULL); - if (chunks_rtree == NULL) + pool->chunks_rtree = rtree_new((ZU(1) << (LG_SIZEOF_PTR+3)) - + opt_lg_chunk, base_alloc, NULL, pool); + if (pool->chunks_rtree == NULL) return (true); } @@ -365,31 +418,31 @@ chunk_boot(void) } void -chunk_prefork(void) +chunk_prefork(pool_t *pool) { - malloc_mutex_prefork(&chunks_mtx); + malloc_mutex_prefork(&pool->chunks_mtx); if (config_ivsalloc) - rtree_prefork(chunks_rtree); + rtree_prefork(pool->chunks_rtree); chunk_dss_prefork(); } void -chunk_postfork_parent(void) +chunk_postfork_parent(pool_t *pool) { chunk_dss_postfork_parent(); if (config_ivsalloc) - rtree_postfork_parent(chunks_rtree); - malloc_mutex_postfork_parent(&chunks_mtx); + rtree_postfork_parent(pool->chunks_rtree); + malloc_mutex_postfork_parent(&pool->chunks_mtx); } void -chunk_postfork_child(void) +chunk_postfork_child(pool_t *pool) { chunk_dss_postfork_child(); if (config_ivsalloc) - rtree_postfork_child(chunks_rtree); - malloc_mutex_postfork_child(&chunks_mtx); + rtree_postfork_child(pool->chunks_rtree); + malloc_mutex_postfork_child(&pool->chunks_mtx); } diff --git a/src/jemalloc/src/chunk_dss.c b/src/jemalloc/src/chunk_dss.c index 510bb8bee8590121db55d4fc4413520df859bf62..8f5b0f30eb3c36bb3e2f1ebdfc76b8ffb0504778 100644 --- a/src/jemalloc/src/chunk_dss.c +++ b/src/jemalloc/src/chunk_dss.c @@ -32,7 +32,7 @@ static void * chunk_dss_sbrk(intptr_t increment) { -#ifdef JEMALLOC_HAVE_SBRK +#ifdef JEMALLOC_DSS return (sbrk(increment)); #else not_implemented(); @@ -45,7 +45,7 @@ chunk_dss_prec_get(void) { dss_prec_t ret; - if (config_dss == false) + if (have_dss == false) return (dss_prec_disabled); malloc_mutex_lock(&dss_mtx); ret = dss_prec_default; @@ -57,8 +57,8 @@ bool chunk_dss_prec_set(dss_prec_t dss_prec) { - if (config_dss == false) - return (true); + if (have_dss == false) + return (dss_prec != dss_prec_disabled); malloc_mutex_lock(&dss_mtx); dss_prec_default = dss_prec; malloc_mutex_unlock(&dss_mtx); @@ -69,8 +69,9 @@ void * chunk_alloc_dss(size_t size, size_t alignment, bool *zero) { void *ret; + pool_t *base_pool = pools[0]; - cassert(config_dss); + cassert(have_dss); assert(size > 0 && (size & chunksize_mask) == 0); assert(alignment > 0 && (alignment & chunksize_mask) == 0); @@ -124,9 +125,10 @@ chunk_alloc_dss(size_t size, size_t alignment, bool *zero) dss_max = dss_next; malloc_mutex_unlock(&dss_mtx); if (cpad_size != 0) - chunk_unmap(cpad, cpad_size); + chunk_unmap(base_pool, cpad, cpad_size); if (*zero) { - VALGRIND_MAKE_MEM_UNDEFINED(ret, size); + JEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED( + ret, size); memset(ret, 0, size); } return (ret); @@ -143,7 +145,7 @@ chunk_in_dss(void *chunk) { bool ret; - cassert(config_dss); + cassert(have_dss); malloc_mutex_lock(&dss_mtx); if ((uintptr_t)chunk >= (uintptr_t)dss_base @@ -160,7 +162,7 @@ bool chunk_dss_boot(void) { - cassert(config_dss); + cassert(have_dss); if (malloc_mutex_init(&dss_mtx)) return (true); @@ -175,7 +177,7 @@ void chunk_dss_prefork(void) { - if (config_dss) + if (have_dss) malloc_mutex_prefork(&dss_mtx); } @@ -183,7 +185,7 @@ void chunk_dss_postfork_parent(void) { - if (config_dss) + if (have_dss) malloc_mutex_postfork_parent(&dss_mtx); } @@ -191,7 +193,7 @@ void chunk_dss_postfork_child(void) { - if (config_dss) + if (have_dss) malloc_mutex_postfork_child(&dss_mtx); } diff --git a/src/jemalloc/src/chunk_mmap.c b/src/jemalloc/src/chunk_mmap.c index 2056d793f05314689751f71b0bbd3f65cb893912..65137b4181dd8e6988618150828ac75f47db3891 100644 --- a/src/jemalloc/src/chunk_mmap.c +++ b/src/jemalloc/src/chunk_mmap.c @@ -121,7 +121,7 @@ pages_purge(void *addr, size_t length) #ifdef _WIN32 VirtualAlloc(addr, length, MEM_RESET, PAGE_READWRITE); unzeroed = true; -#else +#elif defined(JEMALLOC_HAVE_MADVISE) # ifdef JEMALLOC_PURGE_MADVISE_DONTNEED # define JEMALLOC_MADV_PURGE MADV_DONTNEED # define JEMALLOC_MADV_ZEROS true @@ -129,12 +129,15 @@ pages_purge(void *addr, size_t length) # define JEMALLOC_MADV_PURGE MADV_FREE # define JEMALLOC_MADV_ZEROS false # else -# error "No method defined for purging unused dirty pages." +# error "No madvise(2) flag defined for purging unused dirty pages." # endif int err = madvise(addr, length, JEMALLOC_MADV_PURGE); unzeroed = (JEMALLOC_MADV_ZEROS == false || err != 0); # undef JEMALLOC_MADV_PURGE # undef JEMALLOC_MADV_ZEROS +#else + /* Last resort no-op. */ + unzeroed = true; #endif return (unzeroed); } @@ -200,7 +203,7 @@ chunk_alloc_mmap(size_t size, size_t alignment, bool *zero) } bool -chunk_dealloc_mmap(void *chunk, size_t size) +chunk_dalloc_mmap(void *chunk, size_t size) { if (config_munmap) diff --git a/src/jemalloc/src/ctl.c b/src/jemalloc/src/ctl.c index cc2c5aef570f293a04eb182c83af712e2012dbf8..553a446d62f796f95cdc0f346cb0ef5326b0ea43 100644 --- a/src/jemalloc/src/ctl.c +++ b/src/jemalloc/src/ctl.c @@ -1,5 +1,6 @@ #define JEMALLOC_CTL_C_ #include "jemalloc/internal/jemalloc_internal.h" +#include "jemalloc/internal/pool.h" /******************************************************************************/ /* Data. */ @@ -9,10 +10,8 @@ * - ctl_stats.* * - opt_prof_active */ -static malloc_mutex_t ctl_mtx; -static bool ctl_initialized; +static malloc_mutex_t ctl_mtx; /* XXX seperate mutex for each pool? */ static uint64_t ctl_epoch; -static ctl_stats_t ctl_stats; /******************************************************************************/ /* Helpers for named and indexed nodes. */ @@ -58,14 +57,17 @@ static void ctl_arena_stats_amerge(ctl_arena_stats_t *cstats, static void ctl_arena_stats_smerge(ctl_arena_stats_t *sstats, ctl_arena_stats_t *astats); static void ctl_arena_refresh(arena_t *arena, unsigned i); -static bool ctl_grow(void); +static bool ctl_grow(pool_t *pool); +static void ctl_refresh_pool(pool_t *pool); static void ctl_refresh(void); +static bool ctl_init_pool(pool_t *pool); static bool ctl_init(void); static int ctl_lookup(const char *name, ctl_node_t const **nodesp, size_t *mibp, size_t *depthp); CTL_PROTO(version) CTL_PROTO(epoch) +INDEX_PROTO(thread_pool_i) CTL_PROTO(thread_tcache_enabled) CTL_PROTO(thread_tcache_flush) CTL_PROTO(thread_arena) @@ -74,10 +76,8 @@ CTL_PROTO(thread_allocatedp) CTL_PROTO(thread_deallocated) CTL_PROTO(thread_deallocatedp) CTL_PROTO(config_debug) -CTL_PROTO(config_dss) CTL_PROTO(config_fill) CTL_PROTO(config_lazy_lock) -CTL_PROTO(config_mremap) CTL_PROTO(config_munmap) CTL_PROTO(config_prof) CTL_PROTO(config_prof_libgcc) @@ -99,7 +99,6 @@ CTL_PROTO(opt_zero) CTL_PROTO(opt_quarantine) CTL_PROTO(opt_redzone) CTL_PROTO(opt_utrace) -CTL_PROTO(opt_valgrind) CTL_PROTO(opt_xmalloc) CTL_PROTO(opt_tcache) CTL_PROTO(opt_lg_tcache_max) @@ -113,8 +112,10 @@ CTL_PROTO(opt_prof_final) CTL_PROTO(opt_prof_leak) CTL_PROTO(opt_prof_accum) CTL_PROTO(arena_i_purge) -static void arena_purge(unsigned arena_ind); +static void arena_purge(pool_t *pool, unsigned arena_ind); CTL_PROTO(arena_i_dss) +CTL_PROTO(arena_i_chunk_alloc) +CTL_PROTO(arena_i_chunk_dalloc) INDEX_PROTO(arena_i) CTL_PROTO(arenas_bin_i_size) CTL_PROTO(arenas_bin_i_nregs) @@ -130,7 +131,6 @@ CTL_PROTO(arenas_tcache_max) CTL_PROTO(arenas_nbins) CTL_PROTO(arenas_nhbins) CTL_PROTO(arenas_nlruns) -CTL_PROTO(arenas_purge) CTL_PROTO(arenas_extend) CTL_PROTO(prof_active) CTL_PROTO(prof_dump) @@ -138,9 +138,6 @@ CTL_PROTO(prof_interval) CTL_PROTO(stats_chunks_current) CTL_PROTO(stats_chunks_total) CTL_PROTO(stats_chunks_high) -CTL_PROTO(stats_huge_allocated) -CTL_PROTO(stats_huge_nmalloc) -CTL_PROTO(stats_huge_ndalloc) CTL_PROTO(stats_arenas_i_small_allocated) CTL_PROTO(stats_arenas_i_small_nmalloc) CTL_PROTO(stats_arenas_i_small_ndalloc) @@ -149,6 +146,10 @@ CTL_PROTO(stats_arenas_i_large_allocated) CTL_PROTO(stats_arenas_i_large_nmalloc) CTL_PROTO(stats_arenas_i_large_ndalloc) CTL_PROTO(stats_arenas_i_large_nrequests) +CTL_PROTO(stats_arenas_i_huge_allocated) +CTL_PROTO(stats_arenas_i_huge_nmalloc) +CTL_PROTO(stats_arenas_i_huge_ndalloc) +CTL_PROTO(stats_arenas_i_huge_nrequests) CTL_PROTO(stats_arenas_i_bins_j_allocated) CTL_PROTO(stats_arenas_i_bins_j_nmalloc) CTL_PROTO(stats_arenas_i_bins_j_ndalloc) @@ -177,12 +178,16 @@ CTL_PROTO(stats_cactive) CTL_PROTO(stats_allocated) CTL_PROTO(stats_active) CTL_PROTO(stats_mapped) +INDEX_PROTO(pool_i) +CTL_PROTO(pools_npools) +CTL_PROTO(pool_i_base) +CTL_PROTO(pool_i_size) /******************************************************************************/ /* mallctl tree. */ /* Maximum tree depth. */ -#define CTL_MAX_DEPTH 6 +#define CTL_MAX_DEPTH 8 #define NAME(n) {true}, n #define CHILD(t, c) \ @@ -201,9 +206,21 @@ static const ctl_named_node_t tcache_node[] = { {NAME("enabled"), CTL(thread_tcache_enabled)}, {NAME("flush"), CTL(thread_tcache_flush)} }; +static const ctl_named_node_t thread_pool_i_node[] = { + {NAME("arena"), CTL(thread_arena)}, +}; + +static const ctl_named_node_t super_thread_pool_i_node[] = { + {NAME(""), CHILD(named, thread_pool_i)} +}; + +static const ctl_indexed_node_t thread_pool_node[] = { + {INDEX(thread_pool_i)} +}; + static const ctl_named_node_t thread_node[] = { - {NAME("arena"), CTL(thread_arena)}, + {NAME("pool"), CHILD(indexed, thread_pool)}, {NAME("allocated"), CTL(thread_allocated)}, {NAME("allocatedp"), CTL(thread_allocatedp)}, {NAME("deallocated"), CTL(thread_deallocated)}, @@ -213,10 +230,8 @@ static const ctl_named_node_t thread_node[] = { static const ctl_named_node_t config_node[] = { {NAME("debug"), CTL(config_debug)}, - {NAME("dss"), CTL(config_dss)}, {NAME("fill"), CTL(config_fill)}, {NAME("lazy_lock"), CTL(config_lazy_lock)}, - {NAME("mremap"), CTL(config_mremap)}, {NAME("munmap"), CTL(config_munmap)}, {NAME("prof"), CTL(config_prof)}, {NAME("prof_libgcc"), CTL(config_prof_libgcc)}, @@ -241,7 +256,6 @@ static const ctl_named_node_t opt_node[] = { {NAME("quarantine"), CTL(opt_quarantine)}, {NAME("redzone"), CTL(opt_redzone)}, {NAME("utrace"), CTL(opt_utrace)}, - {NAME("valgrind"), CTL(opt_valgrind)}, {NAME("xmalloc"), CTL(opt_xmalloc)}, {NAME("tcache"), CTL(opt_tcache)}, {NAME("lg_tcache_max"), CTL(opt_lg_tcache_max)}, @@ -256,9 +270,15 @@ static const ctl_named_node_t opt_node[] = { {NAME("prof_accum"), CTL(opt_prof_accum)} }; +static const ctl_named_node_t chunk_node[] = { + {NAME("alloc"), CTL(arena_i_chunk_alloc)}, + {NAME("dalloc"), CTL(arena_i_chunk_dalloc)} +}; + static const ctl_named_node_t arena_i_node[] = { {NAME("purge"), CTL(arena_i_purge)}, - {NAME("dss"), CTL(arena_i_dss)} + {NAME("dss"), CTL(arena_i_dss)}, + {NAME("chunk"), CHILD(named, chunk)}, }; static const ctl_named_node_t super_arena_i_node[] = { {NAME(""), CHILD(named, arena_i)} @@ -303,7 +323,6 @@ static const ctl_named_node_t arenas_node[] = { {NAME("bin"), CHILD(indexed, arenas_bin)}, {NAME("nlruns"), CTL(arenas_nlruns)}, {NAME("lrun"), CHILD(indexed, arenas_lrun)}, - {NAME("purge"), CTL(arenas_purge)}, {NAME("extend"), CTL(arenas_extend)} }; @@ -319,12 +338,6 @@ static const ctl_named_node_t stats_chunks_node[] = { {NAME("high"), CTL(stats_chunks_high)} }; -static const ctl_named_node_t stats_huge_node[] = { - {NAME("allocated"), CTL(stats_huge_allocated)}, - {NAME("nmalloc"), CTL(stats_huge_nmalloc)}, - {NAME("ndalloc"), CTL(stats_huge_ndalloc)} -}; - static const ctl_named_node_t stats_arenas_i_small_node[] = { {NAME("allocated"), CTL(stats_arenas_i_small_allocated)}, {NAME("nmalloc"), CTL(stats_arenas_i_small_nmalloc)}, @@ -339,6 +352,13 @@ static const ctl_named_node_t stats_arenas_i_large_node[] = { {NAME("nrequests"), CTL(stats_arenas_i_large_nrequests)} }; +static const ctl_named_node_t stats_arenas_i_huge_node[] = { + {NAME("allocated"), CTL(stats_arenas_i_huge_allocated)}, + {NAME("nmalloc"), CTL(stats_arenas_i_huge_nmalloc)}, + {NAME("ndalloc"), CTL(stats_arenas_i_huge_ndalloc)}, + {NAME("nrequests"), CTL(stats_arenas_i_huge_nrequests)}, +}; + static const ctl_named_node_t stats_arenas_i_bins_j_node[] = { {NAME("allocated"), CTL(stats_arenas_i_bins_j_allocated)}, {NAME("nmalloc"), CTL(stats_arenas_i_bins_j_nmalloc)}, @@ -383,9 +403,11 @@ static const ctl_named_node_t stats_arenas_i_node[] = { {NAME("purged"), CTL(stats_arenas_i_purged)}, {NAME("small"), CHILD(named, stats_arenas_i_small)}, {NAME("large"), CHILD(named, stats_arenas_i_large)}, + {NAME("huge"), CHILD(named, stats_arenas_i_huge)}, {NAME("bins"), CHILD(indexed, stats_arenas_i_bins)}, {NAME("lruns"), CHILD(indexed, stats_arenas_i_lruns)} }; + static const ctl_named_node_t super_stats_arenas_i_node[] = { {NAME(""), CHILD(named, stats_arenas_i)} }; @@ -394,14 +416,33 @@ static const ctl_indexed_node_t stats_arenas_node[] = { {INDEX(stats_arenas_i)} }; -static const ctl_named_node_t stats_node[] = { +static const ctl_named_node_t pool_stats_node[] = { + {NAME("chunks"), CHILD(named, stats_chunks)}, + {NAME("arenas"), CHILD(indexed, stats_arenas)}, {NAME("cactive"), CTL(stats_cactive)}, {NAME("allocated"), CTL(stats_allocated)}, {NAME("active"), CTL(stats_active)}, - {NAME("mapped"), CTL(stats_mapped)}, - {NAME("chunks"), CHILD(named, stats_chunks)}, - {NAME("huge"), CHILD(named, stats_huge)}, - {NAME("arenas"), CHILD(indexed, stats_arenas)} + {NAME("mapped"), CTL(stats_mapped)} +}; + +static const ctl_named_node_t pools_node[] = { + {NAME("npools"), CTL(pools_npools)}, +}; + +static const ctl_named_node_t pool_i_node[] = { + {NAME("mem_base"), CTL(pool_i_base)}, + {NAME("mem_size"), CTL(pool_i_size)}, + {NAME("arena"), CHILD(indexed, arena)}, + {NAME("arenas"), CHILD(named, arenas)}, + {NAME("stats"), CHILD(named, pool_stats)} +}; + +static const ctl_named_node_t super_pool_i_node[] = { + {NAME(""), CHILD(named, pool_i)} +}; + +static const ctl_indexed_node_t pool_node[] = { + {INDEX(pool_i)} }; static const ctl_named_node_t root_node[] = { @@ -410,10 +451,9 @@ static const ctl_named_node_t root_node[] = { {NAME("thread"), CHILD(named, thread)}, {NAME("config"), CHILD(named, config)}, {NAME("opt"), CHILD(named, opt)}, - {NAME("arena"), CHILD(indexed, arena)}, - {NAME("arenas"), CHILD(named, arenas)}, - {NAME("prof"), CHILD(named, prof)}, - {NAME("stats"), CHILD(named, stats)} + {NAME("pool"), CHILD(indexed, pool)}, + {NAME("pools"), CHILD(named, pools)}, + {NAME("prof"), CHILD(named, prof)} }; static const ctl_named_node_t super_root_node[] = { {NAME(""), CHILD(named, root)} @@ -429,9 +469,9 @@ static const ctl_named_node_t super_root_node[] = { static bool ctl_arena_init(ctl_arena_stats_t *astats) { - + pool_t *pool = pools[0]; if (astats->lstats == NULL) { - astats->lstats = (malloc_large_stats_t *)base_alloc(nlclasses * + astats->lstats = (malloc_large_stats_t *)base_alloc(pool, nlclasses * sizeof(malloc_large_stats_t)); if (astats->lstats == NULL) return (true); @@ -498,6 +538,11 @@ ctl_arena_stats_smerge(ctl_arena_stats_t *sstats, ctl_arena_stats_t *astats) sstats->astats.ndalloc_large += astats->astats.ndalloc_large; sstats->astats.nrequests_large += astats->astats.nrequests_large; + sstats->astats.allocated_huge += astats->astats.allocated_huge; + sstats->astats.nmalloc_huge += astats->astats.nmalloc_huge; + sstats->astats.ndalloc_huge += astats->astats.ndalloc_huge; + sstats->astats.nrequests_huge += astats->astats.nrequests_huge; + for (i = 0; i < nlclasses; i++) { sstats->lstats[i].nmalloc += astats->lstats[i].nmalloc; sstats->lstats[i].ndalloc += astats->lstats[i].ndalloc; @@ -524,8 +569,9 @@ ctl_arena_stats_smerge(ctl_arena_stats_t *sstats, ctl_arena_stats_t *astats) static void ctl_arena_refresh(arena_t *arena, unsigned i) { - ctl_arena_stats_t *astats = &ctl_stats.arenas[i]; - ctl_arena_stats_t *sstats = &ctl_stats.arenas[ctl_stats.narenas]; + pool_t *pool = arena->pool; + ctl_arena_stats_t *astats = &pool->ctl_stats.arenas[i]; + ctl_arena_stats_t *sstats = &pool->ctl_stats.arenas[pool->ctl_stats.narenas]; ctl_arena_clear(astats); @@ -544,17 +590,17 @@ ctl_arena_refresh(arena_t *arena, unsigned i) } static bool -ctl_grow(void) +ctl_grow(pool_t *pool) { ctl_arena_stats_t *astats; arena_t **tarenas; /* Allocate extended arena stats and arenas arrays. */ - astats = (ctl_arena_stats_t *)imalloc((ctl_stats.narenas + 2) * + astats = (ctl_arena_stats_t *)imalloc((pool->ctl_stats.narenas + 2) * sizeof(ctl_arena_stats_t)); if (astats == NULL) return (true); - tarenas = (arena_t **)imalloc((ctl_stats.narenas + 1) * + tarenas = (arena_t **)imalloc((pool->ctl_stats.narenas + 1) * sizeof(arena_t *)); if (tarenas == NULL) { idalloc(astats); @@ -562,10 +608,10 @@ ctl_grow(void) } /* Initialize the new astats element. */ - memcpy(astats, ctl_stats.arenas, (ctl_stats.narenas + 1) * + memcpy(astats, pool->ctl_stats.arenas, (pool->ctl_stats.narenas + 1) * sizeof(ctl_arena_stats_t)); - memset(&astats[ctl_stats.narenas + 1], 0, sizeof(ctl_arena_stats_t)); - if (ctl_arena_init(&astats[ctl_stats.narenas + 1])) { + memset(&astats[pool->ctl_stats.narenas + 1], 0, sizeof(ctl_arena_stats_t)); + if (ctl_arena_init(&astats[pool->ctl_stats.narenas + 1])) { idalloc(tarenas); idalloc(astats); return (true); @@ -573,17 +619,17 @@ ctl_grow(void) /* Swap merged stats to their new location. */ { ctl_arena_stats_t tstats; - memcpy(&tstats, &astats[ctl_stats.narenas], + memcpy(&tstats, &astats[pool->ctl_stats.narenas], sizeof(ctl_arena_stats_t)); - memcpy(&astats[ctl_stats.narenas], - &astats[ctl_stats.narenas + 1], sizeof(ctl_arena_stats_t)); - memcpy(&astats[ctl_stats.narenas + 1], &tstats, + memcpy(&astats[pool->ctl_stats.narenas], + &astats[pool->ctl_stats.narenas + 1], sizeof(ctl_arena_stats_t)); + memcpy(&astats[pool->ctl_stats.narenas + 1], &tstats, sizeof(ctl_arena_stats_t)); } /* Initialize the new arenas element. */ - tarenas[ctl_stats.narenas] = NULL; + tarenas[pool->ctl_stats.narenas] = NULL; { - arena_t **arenas_old = arenas; + arena_t **arenas_old = pool->arenas; /* * Swap extended arenas array into place. Although ctl_mtx * protects this function from other threads extending the @@ -592,126 +638,127 @@ ctl_grow(void) * point to them). Therefore, array copying must happen under * the protection of arenas_lock. */ - malloc_mutex_lock(&arenas_lock); - arenas = tarenas; - memcpy(arenas, arenas_old, ctl_stats.narenas * + malloc_mutex_lock(&pool->arenas_lock); + pool->arenas = tarenas; + memcpy(pool->arenas, arenas_old, pool->ctl_stats.narenas * sizeof(arena_t *)); - narenas_total++; - arenas_extend(narenas_total - 1); - malloc_mutex_unlock(&arenas_lock); + pool->narenas_total++; + arenas_extend(pool, pool->narenas_total - 1); + malloc_mutex_unlock(&pool->arenas_lock); /* * Deallocate arenas_old only if it came from imalloc() (not * base_alloc()). */ - if (ctl_stats.narenas != narenas_auto) + if (pool->ctl_stats.narenas != pool->narenas_auto) idalloc(arenas_old); } - ctl_stats.arenas = astats; - ctl_stats.narenas++; + pool->ctl_stats.arenas = astats; + pool->ctl_stats.narenas++; return (false); } static void -ctl_refresh(void) +ctl_refresh_pool(pool_t *pool) { unsigned i; - VARIABLE_ARRAY(arena_t *, tarenas, ctl_stats.narenas); + VARIABLE_ARRAY(arena_t *, tarenas, pool->ctl_stats.narenas); if (config_stats) { - malloc_mutex_lock(&chunks_mtx); - ctl_stats.chunks.current = stats_chunks.curchunks; - ctl_stats.chunks.total = stats_chunks.nchunks; - ctl_stats.chunks.high = stats_chunks.highchunks; - malloc_mutex_unlock(&chunks_mtx); - - malloc_mutex_lock(&huge_mtx); - ctl_stats.huge.allocated = huge_allocated; - ctl_stats.huge.nmalloc = huge_nmalloc; - ctl_stats.huge.ndalloc = huge_ndalloc; - malloc_mutex_unlock(&huge_mtx); + malloc_mutex_lock(&pool->chunks_mtx); + pool->ctl_stats.chunks.current = pool->stats_chunks.curchunks; + pool->ctl_stats.chunks.total = pool->stats_chunks.nchunks; + pool->ctl_stats.chunks.high = pool->stats_chunks.highchunks; + malloc_mutex_unlock(&pool->chunks_mtx); } /* * Clear sum stats, since they will be merged into by * ctl_arena_refresh(). */ - ctl_stats.arenas[ctl_stats.narenas].nthreads = 0; - ctl_arena_clear(&ctl_stats.arenas[ctl_stats.narenas]); - - malloc_mutex_lock(&arenas_lock); - memcpy(tarenas, arenas, sizeof(arena_t *) * ctl_stats.narenas); - for (i = 0; i < ctl_stats.narenas; i++) { - if (arenas[i] != NULL) - ctl_stats.arenas[i].nthreads = arenas[i]->nthreads; + pool->ctl_stats.arenas[pool->ctl_stats.narenas].nthreads = 0; + ctl_arena_clear(&pool->ctl_stats.arenas[pool->ctl_stats.narenas]); + + malloc_mutex_lock(&pool->arenas_lock); + memcpy(tarenas, pool->arenas, sizeof(arena_t *) * pool->ctl_stats.narenas); + for (i = 0; i < pool->ctl_stats.narenas; i++) { + if (pool->arenas[i] != NULL) + pool->ctl_stats.arenas[i].nthreads = pool->arenas[i]->nthreads; else - ctl_stats.arenas[i].nthreads = 0; + pool->ctl_stats.arenas[i].nthreads = 0; } - malloc_mutex_unlock(&arenas_lock); - for (i = 0; i < ctl_stats.narenas; i++) { + malloc_mutex_unlock(&pool->arenas_lock); + for (i = 0; i < pool->ctl_stats.narenas; i++) { bool initialized = (tarenas[i] != NULL); - ctl_stats.arenas[i].initialized = initialized; + pool->ctl_stats.arenas[i].initialized = initialized; if (initialized) ctl_arena_refresh(tarenas[i], i); } if (config_stats) { - ctl_stats.allocated = - ctl_stats.arenas[ctl_stats.narenas].allocated_small - + ctl_stats.arenas[ctl_stats.narenas].astats.allocated_large - + ctl_stats.huge.allocated; - ctl_stats.active = - (ctl_stats.arenas[ctl_stats.narenas].pactive << LG_PAGE) - + ctl_stats.huge.allocated; - ctl_stats.mapped = (ctl_stats.chunks.current << opt_lg_chunk); + pool->ctl_stats_allocated = + pool->ctl_stats.arenas[pool->ctl_stats.narenas].allocated_small + + pool->ctl_stats.arenas[pool->ctl_stats.narenas].astats.allocated_large + + pool->ctl_stats.arenas[pool->ctl_stats.narenas].astats.allocated_huge; + pool->ctl_stats_active = + (pool->ctl_stats.arenas[pool->ctl_stats.narenas].pactive << LG_PAGE); + pool->ctl_stats_mapped = (pool->ctl_stats.chunks.current << opt_lg_chunk); } ctl_epoch++; } +static void +ctl_refresh(void) +{ + for (int i = 0; i < POOLS_MAX; ++i) { + if (pools[i] != NULL) { + ctl_refresh_pool(pools[i]); + } + } +} + static bool -ctl_init(void) +ctl_init_pool(pool_t *pool) { bool ret; - malloc_mutex_lock(&ctl_mtx); - if (ctl_initialized == false) { - /* - * Allocate space for one extra arena stats element, which - * contains summed stats across all arenas. - */ - assert(narenas_auto == narenas_total_get()); - ctl_stats.narenas = narenas_auto; - ctl_stats.arenas = (ctl_arena_stats_t *)base_alloc( - (ctl_stats.narenas + 1) * sizeof(ctl_arena_stats_t)); - if (ctl_stats.arenas == NULL) { - ret = true; - goto label_return; - } - memset(ctl_stats.arenas, 0, (ctl_stats.narenas + 1) * - sizeof(ctl_arena_stats_t)); + /* + * Allocate space for one extra arena stats element, which + * contains summed stats across all arenas. + */ + assert(pool->narenas_auto == narenas_total_get(pool)); + pool->ctl_stats.narenas = pool->narenas_auto; + pool->ctl_stats.arenas = (ctl_arena_stats_t *)base_alloc(pool, + (pool->ctl_stats.narenas + 1) * sizeof(ctl_arena_stats_t)); - /* - * Initialize all stats structures, regardless of whether they - * ever get used. Lazy initialization would allow errors to - * cause inconsistent state to be viewable by the application. - */ - if (config_stats) { - unsigned i; - for (i = 0; i <= ctl_stats.narenas; i++) { - if (ctl_arena_init(&ctl_stats.arenas[i])) { - ret = true; - goto label_return; - } + if (pool->ctl_stats.arenas == NULL) { + ret = true; + goto label_return; + } + memset(pool->ctl_stats.arenas, 0, (pool->ctl_stats.narenas + 1) * + sizeof(ctl_arena_stats_t)); + + /* + * Initialize all stats structures, regardless of whether they + * ever get used. Lazy initialization would allow errors to + * cause inconsistent state to be viewable by the application. + */ + if (config_stats) { + unsigned i; + for (i = 0; i <= pool->ctl_stats.narenas; i++) { + if (ctl_arena_init(&pool->ctl_stats.arenas[i])) { + ret = true; + goto label_return; } } - ctl_stats.arenas[ctl_stats.narenas].initialized = true; - - ctl_epoch = 0; - ctl_refresh(); - ctl_initialized = true; } + pool->ctl_stats.arenas[pool->ctl_stats.narenas].initialized = true; + + ctl_epoch = 0; + ctl_refresh_pool(pool); + pool->ctl_initialized = true; ret = false; label_return: @@ -719,6 +766,27 @@ label_return: return (ret); } +static bool +ctl_init(void) +{ + bool ret; + malloc_mutex_lock(&ctl_mtx); + for (int i = 0; i < POOLS_MAX; ++i) { + if (pools[i] != NULL && pools[i]->ctl_initialized == false) { + if (ctl_init_pool(pools[i])) { + ret = true; + goto label_return; + } + } + } + /* false means that functions ends with success */ + ret = false; + +label_return: + malloc_mutex_unlock(&ctl_mtx); + return (ret); +} + static int ctl_lookup(const char *name, ctl_node_t const **nodesp, size_t *mibp, size_t *depthp) @@ -826,7 +894,7 @@ ctl_byname(const char *name, void *oldp, size_t *oldlenp, void *newp, size_t mib[CTL_MAX_DEPTH]; const ctl_named_node_t *node; - if (ctl_initialized == false && ctl_init()) { + if (ctl_init()) { ret = EAGAIN; goto label_return; } @@ -853,7 +921,7 @@ ctl_nametomib(const char *name, size_t *mibp, size_t *miblenp) { int ret; - if (ctl_initialized == false && ctl_init()) { + if (ctl_init()) { ret = EAGAIN; goto label_return; } @@ -871,7 +939,7 @@ ctl_bymib(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, const ctl_named_node_t *node; size_t i; - if (ctl_initialized == false && ctl_init()) { + if (ctl_init()) { ret = EAGAIN; goto label_return; } @@ -920,8 +988,6 @@ ctl_boot(void) if (malloc_mutex_init(&ctl_mtx)) return (true); - ctl_initialized = false; - return (false); } @@ -1136,10 +1202,8 @@ label_return: /******************************************************************************/ CTL_RO_BOOL_CONFIG_GEN(config_debug) -CTL_RO_BOOL_CONFIG_GEN(config_dss) CTL_RO_BOOL_CONFIG_GEN(config_fill) CTL_RO_BOOL_CONFIG_GEN(config_lazy_lock) -CTL_RO_BOOL_CONFIG_GEN(config_mremap) CTL_RO_BOOL_CONFIG_GEN(config_munmap) CTL_RO_BOOL_CONFIG_GEN(config_prof) CTL_RO_BOOL_CONFIG_GEN(config_prof_libgcc) @@ -1164,7 +1228,6 @@ CTL_RO_NL_CGEN(config_fill, opt_quarantine, opt_quarantine, size_t) CTL_RO_NL_CGEN(config_fill, opt_redzone, opt_redzone, bool) CTL_RO_NL_CGEN(config_fill, opt_zero, opt_zero, bool) CTL_RO_NL_CGEN(config_utrace, opt_utrace, opt_utrace, bool) -CTL_RO_NL_CGEN(config_valgrind, opt_valgrind, opt_valgrind, bool) CTL_RO_NL_CGEN(config_xmalloc, opt_xmalloc, opt_xmalloc, bool) CTL_RO_NL_CGEN(config_tcache, opt_tcache, opt_tcache, bool) CTL_RO_NL_CGEN(config_tcache, opt_lg_tcache_max, opt_lg_tcache_max, ssize_t) @@ -1186,43 +1249,60 @@ thread_arena_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, { int ret; unsigned newind, oldind; + unsigned pool_ind = mib[1]; + pool_t *pool; + arena_t dummy; + if (pool_ind >= POOLS_MAX) { + ret = ENOENT; + goto label_return; + } + pool = pools[pool_ind]; + DUMMY_ARENA_INITIALIZE(dummy, pool); + tsd_tcache_t *tcache_tsd = tcache_tsd_get(); malloc_mutex_lock(&ctl_mtx); - newind = oldind = choose_arena(NULL)->ind; + newind = oldind = choose_arena(&dummy)->ind; WRITE(newind, unsigned); READ(oldind, unsigned); if (newind != oldind) { arena_t *arena; + tsd_pool_t *tsd; - if (newind >= ctl_stats.narenas) { + if (newind >= pool->ctl_stats.narenas) { /* New arena index is out of range. */ ret = EFAULT; goto label_return; } /* Initialize arena if necessary. */ - malloc_mutex_lock(&arenas_lock); - if ((arena = arenas[newind]) == NULL && (arena = - arenas_extend(newind)) == NULL) { - malloc_mutex_unlock(&arenas_lock); + malloc_mutex_lock(&pool->arenas_lock); + if ((arena = pool->arenas[newind]) == NULL && (arena = + arenas_extend(pool, newind)) == NULL) { + malloc_mutex_unlock(&pool->arenas_lock); ret = EAGAIN; goto label_return; } - assert(arena == arenas[newind]); - arenas[oldind]->nthreads--; - arenas[newind]->nthreads++; - malloc_mutex_unlock(&arenas_lock); + assert(arena == pool->arenas[newind]); + pool->arenas[oldind]->nthreads--; + pool->arenas[newind]->nthreads++; + malloc_mutex_unlock(&pool->arenas_lock); /* Set new arena association. */ if (config_tcache) { - tcache_t *tcache; - if ((uintptr_t)(tcache = *tcache_tsd_get()) > - (uintptr_t)TCACHE_STATE_MAX) { - tcache_arena_dissociate(tcache); + tcache_t *tcache = tcache_tsd->tcaches[pool->pool_id]; + if ((uintptr_t)(tcache) > (uintptr_t)TCACHE_STATE_MAX) { + + if(tcache_tsd->seqno[pool->pool_id] == pool->seqno) + tcache_arena_dissociate(tcache); + tcache_arena_associate(tcache, arena); + tcache_tsd->seqno[pool->pool_id] = pool->seqno; } } - arenas_tsd_set(&arena); + + tsd = arenas_tsd_get(); + tsd->seqno[0] = pool->seqno; + tsd->arenas[0] = arena; } ret = 0; @@ -1271,13 +1351,15 @@ thread_tcache_flush_ctl(const size_t *mib, size_t miblen, void *oldp, { int ret; + pool_t *pool = pools[0]; + if (config_tcache == false) return (ENOENT); READONLY(); WRITEONLY(); - tcache_flush(); + tcache_flush(pool); ret = 0; label_return: @@ -1288,22 +1370,22 @@ label_return: /* ctl_mutex must be held during execution of this function. */ static void -arena_purge(unsigned arena_ind) +arena_purge(pool_t *pool, unsigned arena_ind) { - VARIABLE_ARRAY(arena_t *, tarenas, ctl_stats.narenas); + VARIABLE_ARRAY(arena_t *, tarenas, pool->ctl_stats.narenas); - malloc_mutex_lock(&arenas_lock); - memcpy(tarenas, arenas, sizeof(arena_t *) * ctl_stats.narenas); - malloc_mutex_unlock(&arenas_lock); + malloc_mutex_lock(&pool->arenas_lock); + memcpy(tarenas, pool->arenas, sizeof(arena_t *) * pool->ctl_stats.narenas); + malloc_mutex_unlock(&pool->arenas_lock); - if (arena_ind == ctl_stats.narenas) { + if (arena_ind == pool->ctl_stats.narenas) { unsigned i; - for (i = 0; i < ctl_stats.narenas; i++) { + for (i = 0; i < pool->ctl_stats.narenas; i++) { if (tarenas[i] != NULL) arena_purge_all(tarenas[i]); } } else { - assert(arena_ind < ctl_stats.narenas); + assert(arena_ind < pool->ctl_stats.narenas); if (tarenas[arena_ind] != NULL) arena_purge_all(tarenas[arena_ind]); } @@ -1315,10 +1397,15 @@ arena_i_purge_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, { int ret; + if (mib[1] >= POOLS_MAX) { + ret = ENOENT; + goto label_return; + } + READONLY(); WRITEONLY(); malloc_mutex_lock(&ctl_mtx); - arena_purge(mib[1]); + arena_purge(pools[mib[1]], mib[3]); malloc_mutex_unlock(&ctl_mtx); ret = 0; @@ -1333,11 +1420,19 @@ arena_i_dss_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, int ret, i; bool match, err; const char *dss; - unsigned arena_ind = mib[1]; + unsigned pool_ind = mib[1]; + unsigned arena_ind = mib[3]; dss_prec_t dss_prec_old = dss_prec_limit; dss_prec_t dss_prec = dss_prec_limit; + pool_t *pool; + + if (pool_ind >= POOLS_MAX) { + ret = ENOENT; + goto label_return; + } malloc_mutex_lock(&ctl_mtx); + pool = pools[pool_ind]; WRITE(dss, const char *); match = false; for (i = 0; i < dss_prec_limit; i++) { @@ -1352,12 +1447,11 @@ arena_i_dss_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, goto label_return; } - if (arena_ind < ctl_stats.narenas) { - arena_t *arena = arenas[arena_ind]; + if (arena_ind < pool->ctl_stats.narenas) { + arena_t *arena = pool->arenas[arena_ind]; if (arena != NULL) { dss_prec_old = arena_dss_prec_get(arena); - arena_dss_prec_set(arena, dss_prec); - err = false; + err = arena_dss_prec_set(arena, dss_prec); } else err = true; } else { @@ -1377,13 +1471,80 @@ label_return: return (ret); } +static int +arena_i_chunk_alloc_ctl(const size_t *mib, size_t miblen, void *oldp, + size_t *oldlenp, void *newp, size_t newlen) +{ + int ret; + unsigned pool_ind = mib[1]; + unsigned arena_ind = mib[3]; + arena_t *arena; + pool_t *pool; + + if (pool_ind >= POOLS_MAX) { + ret = ENOENT; + goto label_outer_return; + } + + malloc_mutex_lock(&ctl_mtx); + pool = pools[pool_ind]; + if (arena_ind < pool->narenas_total && (arena = pool->arenas[arena_ind]) != NULL) { + malloc_mutex_lock(&arena->lock); + READ(arena->chunk_alloc, chunk_alloc_t *); + WRITE(arena->chunk_alloc, chunk_alloc_t *); + } else { + ret = EFAULT; + goto label_outer_return; + } + ret = 0; +label_return: + malloc_mutex_unlock(&arena->lock); +label_outer_return: + malloc_mutex_unlock(&ctl_mtx); + return (ret); +} + +static int +arena_i_chunk_dalloc_ctl(const size_t *mib, size_t miblen, void *oldp, + size_t *oldlenp, void *newp, size_t newlen) +{ + + int ret; + unsigned pool_ind = mib[1]; + unsigned arena_ind = mib[3]; + arena_t *arena; + pool_t *pool; + + if (pool_ind >= POOLS_MAX) { + ret = ENOENT; + goto label_outer_return; + } + + malloc_mutex_lock(&ctl_mtx); + pool = pools[pool_ind]; + if (arena_ind < pool->narenas_total && (arena = pool->arenas[arena_ind]) != NULL) { + malloc_mutex_lock(&arena->lock); + READ(arena->chunk_dalloc, chunk_dalloc_t *); + WRITE(arena->chunk_dalloc, chunk_dalloc_t *); + } else { + ret = EFAULT; + goto label_outer_return; + } + ret = 0; +label_return: + malloc_mutex_unlock(&arena->lock); +label_outer_return: + malloc_mutex_unlock(&ctl_mtx); + return (ret); +} + static const ctl_named_node_t * arena_i_index(const size_t *mib, size_t miblen, size_t i) { const ctl_named_node_t * ret; malloc_mutex_lock(&ctl_mtx); - if (i > ctl_stats.narenas) { + if (i > pools[mib[1]]->ctl_stats.narenas) { ret = NULL; goto label_return; } @@ -1409,7 +1570,7 @@ arenas_narenas_ctl(const size_t *mib, size_t miblen, void *oldp, ret = EINVAL; goto label_return; } - narenas = ctl_stats.narenas; + narenas = pools[mib[1]]->ctl_stats.narenas; READ(narenas, unsigned); ret = 0; @@ -1424,20 +1585,22 @@ arenas_initialized_ctl(const size_t *mib, size_t miblen, void *oldp, { int ret; unsigned nread, i; + pool_t *pool; malloc_mutex_lock(&ctl_mtx); READONLY(); - if (*oldlenp != ctl_stats.narenas * sizeof(bool)) { + pool = pools[mib[1]]; + if (*oldlenp != pool->ctl_stats.narenas * sizeof(bool)) { ret = EINVAL; - nread = (*oldlenp < ctl_stats.narenas * sizeof(bool)) - ? (*oldlenp / sizeof(bool)) : ctl_stats.narenas; + nread = (*oldlenp < pool->ctl_stats.narenas * sizeof(bool)) + ? (*oldlenp / sizeof(bool)) : pool->ctl_stats.narenas; } else { ret = 0; - nread = ctl_stats.narenas; + nread = pool->ctl_stats.narenas; } for (i = 0; i < nread; i++) - ((bool *)oldp)[i] = ctl_stats.arenas[i].initialized; + ((bool *)oldp)[i] = pool->ctl_stats.arenas[i].initialized; label_return: malloc_mutex_unlock(&ctl_mtx); @@ -1449,9 +1612,9 @@ CTL_RO_NL_GEN(arenas_page, PAGE, size_t) CTL_RO_NL_CGEN(config_tcache, arenas_tcache_max, tcache_maxclass, size_t) CTL_RO_NL_GEN(arenas_nbins, NBINS, unsigned) CTL_RO_NL_CGEN(config_tcache, arenas_nhbins, nhbins, unsigned) -CTL_RO_NL_GEN(arenas_bin_i_size, arena_bin_info[mib[2]].reg_size, size_t) -CTL_RO_NL_GEN(arenas_bin_i_nregs, arena_bin_info[mib[2]].nregs, uint32_t) -CTL_RO_NL_GEN(arenas_bin_i_run_size, arena_bin_info[mib[2]].run_size, size_t) +CTL_RO_NL_GEN(arenas_bin_i_size, arena_bin_info[mib[4]].reg_size, size_t) +CTL_RO_NL_GEN(arenas_bin_i_nregs, arena_bin_info[mib[4]].nregs, uint32_t) +CTL_RO_NL_GEN(arenas_bin_i_run_size, arena_bin_info[mib[4]].run_size, size_t) static const ctl_named_node_t * arenas_bin_i_index(const size_t *mib, size_t miblen, size_t i) { @@ -1462,7 +1625,7 @@ arenas_bin_i_index(const size_t *mib, size_t miblen, size_t i) } CTL_RO_NL_GEN(arenas_nlruns, nlclasses, size_t) -CTL_RO_NL_GEN(arenas_lrun_i_size, ((mib[2]+1) << LG_PAGE), size_t) +CTL_RO_NL_GEN(arenas_lrun_i_size, ((mib[4]+1) << LG_PAGE), size_t) static const ctl_named_node_t * arenas_lrun_i_index(const size_t *mib, size_t miblen, size_t i) { @@ -1473,52 +1636,121 @@ arenas_lrun_i_index(const size_t *mib, size_t miblen, size_t i) } static int -arenas_purge_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, +arenas_extend_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int ret; - unsigned arena_ind; + unsigned narenas; + unsigned pool_ind = mib[1]; + pool_t *pool; + + if (pool_ind >= POOLS_MAX) { + ret = ENOENT; + goto label_return; + } + pool = pools[pool_ind]; malloc_mutex_lock(&ctl_mtx); - WRITEONLY(); - arena_ind = UINT_MAX; - WRITE(arena_ind, unsigned); - if (newp != NULL && arena_ind >= ctl_stats.narenas) - ret = EFAULT; - else { - if (arena_ind == UINT_MAX) - arena_ind = ctl_stats.narenas; - arena_purge(arena_ind); - ret = 0; + READONLY(); + if (ctl_grow(pool)) { + ret = EAGAIN; + goto label_return; } + narenas = pool->ctl_stats.narenas - 1; + READ(narenas, unsigned); + ret = 0; label_return: malloc_mutex_unlock(&ctl_mtx); return (ret); } +/** + * @stub + */ static int -arenas_extend_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, +pools_npools_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { - int ret; - unsigned narenas; + int ret; + unsigned _npools; + + malloc_mutex_lock(&ctl_mtx); + READONLY(); + if (*oldlenp != sizeof(unsigned)) { + ret = EINVAL; + goto label_return; + } + _npools = npools; + READ(_npools, unsigned); + + ret = 0; +label_return: + malloc_mutex_unlock(&ctl_mtx); + return (ret); +} - malloc_mutex_lock(&ctl_mtx); - READONLY(); - if (ctl_grow()) { - ret = EAGAIN; - goto label_return; - } - narenas = ctl_stats.narenas - 1; - READ(narenas, unsigned); +/** + * @stub + */ +static int +pool_i_base_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, + void *newp, size_t newlen) +{ + int ret; - ret = 0; + READONLY(); + WRITEONLY(); + malloc_mutex_lock(&ctl_mtx); + //TODO + malloc_mutex_unlock(&ctl_mtx); + + ret = 0; label_return: - malloc_mutex_unlock(&ctl_mtx); - return (ret); + return (ret); +} + +/** + * @stub + */ +static int +pool_i_size_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, + void *newp, size_t newlen) +{ + int ret; + + READONLY(); + WRITEONLY(); + malloc_mutex_lock(&ctl_mtx); + //TODO + malloc_mutex_unlock(&ctl_mtx); + + ret = 0; +label_return: + return (ret); +} + +/** + * @stub + */ +static const ctl_named_node_t * +pool_i_index(const size_t *mib, size_t miblen, size_t i) +{ + const ctl_named_node_t * ret; + + malloc_mutex_lock(&ctl_mtx); + if (i > POOLS_MAX) { + ret = NULL; + goto label_return; + } + + ret = super_pool_i_node; +label_return: + malloc_mutex_unlock(&ctl_mtx); + return (ret); } + /******************************************************************************/ static int @@ -1576,68 +1808,75 @@ label_return: CTL_RO_NL_CGEN(config_prof, prof_interval, prof_interval, uint64_t) /******************************************************************************/ +/* + * @TODO remember to split up stats to arena-related and th rest + */ -CTL_RO_CGEN(config_stats, stats_cactive, &stats_cactive, size_t *) -CTL_RO_CGEN(config_stats, stats_allocated, ctl_stats.allocated, size_t) -CTL_RO_CGEN(config_stats, stats_active, ctl_stats.active, size_t) -CTL_RO_CGEN(config_stats, stats_mapped, ctl_stats.mapped, size_t) - -CTL_RO_CGEN(config_stats, stats_chunks_current, ctl_stats.chunks.current, +CTL_RO_CGEN(config_stats, stats_cactive, &(pools[mib[1]]->stats_cactive), size_t *) +CTL_RO_CGEN(config_stats, stats_allocated, pools[mib[1]]->ctl_stats_allocated, size_t) +CTL_RO_CGEN(config_stats, stats_active, pools[mib[1]]->ctl_stats_active, size_t) +CTL_RO_CGEN(config_stats, stats_mapped, pools[mib[1]]->ctl_stats_mapped, size_t) +CTL_RO_CGEN(config_stats, stats_chunks_current, pools[mib[1]]->ctl_stats.chunks.current, size_t) -CTL_RO_CGEN(config_stats, stats_chunks_total, ctl_stats.chunks.total, uint64_t) -CTL_RO_CGEN(config_stats, stats_chunks_high, ctl_stats.chunks.high, size_t) -CTL_RO_CGEN(config_stats, stats_huge_allocated, huge_allocated, size_t) -CTL_RO_CGEN(config_stats, stats_huge_nmalloc, huge_nmalloc, uint64_t) -CTL_RO_CGEN(config_stats, stats_huge_ndalloc, huge_ndalloc, uint64_t) - -CTL_RO_GEN(stats_arenas_i_dss, ctl_stats.arenas[mib[2]].dss, const char *) -CTL_RO_GEN(stats_arenas_i_nthreads, ctl_stats.arenas[mib[2]].nthreads, unsigned) -CTL_RO_GEN(stats_arenas_i_pactive, ctl_stats.arenas[mib[2]].pactive, size_t) -CTL_RO_GEN(stats_arenas_i_pdirty, ctl_stats.arenas[mib[2]].pdirty, size_t) +CTL_RO_CGEN(config_stats, stats_chunks_total, pools[mib[1]]->ctl_stats.chunks.total, uint64_t) +CTL_RO_CGEN(config_stats, stats_chunks_high, pools[mib[1]]->ctl_stats.chunks.high, size_t) + +CTL_RO_GEN(stats_arenas_i_dss, pools[mib[1]]->ctl_stats.arenas[mib[4]].dss, const char *) +CTL_RO_GEN(stats_arenas_i_nthreads, pools[mib[1]]->ctl_stats.arenas[mib[4]].nthreads, unsigned) +CTL_RO_GEN(stats_arenas_i_pactive, pools[mib[1]]->ctl_stats.arenas[mib[4]].pactive, size_t) +CTL_RO_GEN(stats_arenas_i_pdirty, pools[mib[1]]->ctl_stats.arenas[mib[4]].pdirty, size_t) CTL_RO_CGEN(config_stats, stats_arenas_i_mapped, - ctl_stats.arenas[mib[2]].astats.mapped, size_t) + pools[mib[1]]->ctl_stats.arenas[mib[4]].astats.mapped, size_t) CTL_RO_CGEN(config_stats, stats_arenas_i_npurge, - ctl_stats.arenas[mib[2]].astats.npurge, uint64_t) + pools[mib[1]]->ctl_stats.arenas[mib[4]].astats.npurge, uint64_t) CTL_RO_CGEN(config_stats, stats_arenas_i_nmadvise, - ctl_stats.arenas[mib[2]].astats.nmadvise, uint64_t) + pools[mib[1]]->ctl_stats.arenas[mib[4]].astats.nmadvise, uint64_t) CTL_RO_CGEN(config_stats, stats_arenas_i_purged, - ctl_stats.arenas[mib[2]].astats.purged, uint64_t) + pools[mib[1]]->ctl_stats.arenas[mib[4]].astats.purged, uint64_t) CTL_RO_CGEN(config_stats, stats_arenas_i_small_allocated, - ctl_stats.arenas[mib[2]].allocated_small, size_t) + pools[mib[1]]->ctl_stats.arenas[mib[4]].allocated_small, size_t) CTL_RO_CGEN(config_stats, stats_arenas_i_small_nmalloc, - ctl_stats.arenas[mib[2]].nmalloc_small, uint64_t) + pools[mib[1]]->ctl_stats.arenas[mib[4]].nmalloc_small, uint64_t) CTL_RO_CGEN(config_stats, stats_arenas_i_small_ndalloc, - ctl_stats.arenas[mib[2]].ndalloc_small, uint64_t) + pools[mib[1]]->ctl_stats.arenas[mib[4]].ndalloc_small, uint64_t) CTL_RO_CGEN(config_stats, stats_arenas_i_small_nrequests, - ctl_stats.arenas[mib[2]].nrequests_small, uint64_t) + pools[mib[1]]->ctl_stats.arenas[mib[4]].nrequests_small, uint64_t) CTL_RO_CGEN(config_stats, stats_arenas_i_large_allocated, - ctl_stats.arenas[mib[2]].astats.allocated_large, size_t) + pools[mib[1]]->ctl_stats.arenas[mib[4]].astats.allocated_large, size_t) CTL_RO_CGEN(config_stats, stats_arenas_i_large_nmalloc, - ctl_stats.arenas[mib[2]].astats.nmalloc_large, uint64_t) + pools[mib[1]]->ctl_stats.arenas[mib[4]].astats.nmalloc_large, uint64_t) CTL_RO_CGEN(config_stats, stats_arenas_i_large_ndalloc, - ctl_stats.arenas[mib[2]].astats.ndalloc_large, uint64_t) + pools[mib[1]]->ctl_stats.arenas[mib[4]].astats.ndalloc_large, uint64_t) CTL_RO_CGEN(config_stats, stats_arenas_i_large_nrequests, - ctl_stats.arenas[mib[2]].astats.nrequests_large, uint64_t) + pools[mib[1]]->ctl_stats.arenas[mib[4]].astats.nrequests_large, uint64_t) +CTL_RO_CGEN(config_stats, stats_arenas_i_huge_allocated, + pools[mib[1]]->ctl_stats.arenas[mib[4]].astats.allocated_huge, size_t) +CTL_RO_CGEN(config_stats, stats_arenas_i_huge_nmalloc, + pools[mib[1]]->ctl_stats.arenas[mib[4]].astats.nmalloc_huge, uint64_t) +CTL_RO_CGEN(config_stats, stats_arenas_i_huge_ndalloc, + pools[mib[1]]->ctl_stats.arenas[mib[4]].astats.ndalloc_huge, uint64_t) +CTL_RO_CGEN(config_stats, stats_arenas_i_huge_nrequests, + pools[mib[1]]->ctl_stats.arenas[mib[4]].astats.nrequests_huge, uint64_t) CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_allocated, - ctl_stats.arenas[mib[2]].bstats[mib[4]].allocated, size_t) + pools[mib[1]]->ctl_stats.arenas[mib[4]].bstats[mib[6]].allocated, size_t) CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nmalloc, - ctl_stats.arenas[mib[2]].bstats[mib[4]].nmalloc, uint64_t) + pools[mib[1]]->ctl_stats.arenas[mib[4]].bstats[mib[6]].nmalloc, uint64_t) CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_ndalloc, - ctl_stats.arenas[mib[2]].bstats[mib[4]].ndalloc, uint64_t) + pools[mib[1]]->ctl_stats.arenas[mib[4]].bstats[mib[6]].ndalloc, uint64_t) CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nrequests, - ctl_stats.arenas[mib[2]].bstats[mib[4]].nrequests, uint64_t) + pools[mib[1]]->ctl_stats.arenas[mib[4]].bstats[mib[6]].nrequests, uint64_t) CTL_RO_CGEN(config_stats && config_tcache, stats_arenas_i_bins_j_nfills, - ctl_stats.arenas[mib[2]].bstats[mib[4]].nfills, uint64_t) + pools[mib[1]]->ctl_stats.arenas[mib[4]].bstats[mib[6]].nfills, uint64_t) CTL_RO_CGEN(config_stats && config_tcache, stats_arenas_i_bins_j_nflushes, - ctl_stats.arenas[mib[2]].bstats[mib[4]].nflushes, uint64_t) + pools[mib[1]]->ctl_stats.arenas[mib[4]].bstats[mib[6]].nflushes, uint64_t) CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nruns, - ctl_stats.arenas[mib[2]].bstats[mib[4]].nruns, uint64_t) + pools[mib[1]]->ctl_stats.arenas[mib[4]].bstats[mib[6]].nruns, uint64_t) CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nreruns, - ctl_stats.arenas[mib[2]].bstats[mib[4]].reruns, uint64_t) + pools[mib[1]]->ctl_stats.arenas[mib[4]].bstats[mib[6]].reruns, uint64_t) CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_curruns, - ctl_stats.arenas[mib[2]].bstats[mib[4]].curruns, size_t) + pools[mib[1]]->ctl_stats.arenas[mib[4]].bstats[mib[6]].curruns, size_t) static const ctl_named_node_t * stats_arenas_i_bins_j_index(const size_t *mib, size_t miblen, size_t j) @@ -1649,13 +1888,13 @@ stats_arenas_i_bins_j_index(const size_t *mib, size_t miblen, size_t j) } CTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_nmalloc, - ctl_stats.arenas[mib[2]].lstats[mib[4]].nmalloc, uint64_t) + pools[mib[1]]->ctl_stats.arenas[mib[4]].lstats[mib[6]].nmalloc, uint64_t) CTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_ndalloc, - ctl_stats.arenas[mib[2]].lstats[mib[4]].ndalloc, uint64_t) + pools[mib[1]]->ctl_stats.arenas[mib[4]].lstats[mib[6]].ndalloc, uint64_t) CTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_nrequests, - ctl_stats.arenas[mib[2]].lstats[mib[4]].nrequests, uint64_t) + pools[mib[1]]->ctl_stats.arenas[mib[4]].lstats[mib[6]].nrequests, uint64_t) CTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_curruns, - ctl_stats.arenas[mib[2]].lstats[mib[4]].curruns, size_t) + pools[mib[1]]->ctl_stats.arenas[mib[4]].lstats[mib[6]].curruns, size_t) static const ctl_named_node_t * stats_arenas_i_lruns_j_index(const size_t *mib, size_t miblen, size_t j) @@ -1669,10 +1908,11 @@ stats_arenas_i_lruns_j_index(const size_t *mib, size_t miblen, size_t j) static const ctl_named_node_t * stats_arenas_i_index(const size_t *mib, size_t miblen, size_t i) { - const ctl_named_node_t * ret; + const ctl_named_node_t *ret; malloc_mutex_lock(&ctl_mtx); - if (i > ctl_stats.narenas || ctl_stats.arenas[i].initialized == false) { + if (i > pools[mib[1]]->ctl_stats.narenas || + pools[mib[1]]->ctl_stats.arenas[i].initialized == false) { ret = NULL; goto label_return; } @@ -1682,3 +1922,20 @@ label_return: malloc_mutex_unlock(&ctl_mtx); return (ret); } + +static const ctl_named_node_t * +thread_pool_i_index(const size_t *mib, size_t miblen, size_t i) +{ + const ctl_named_node_t *ret; + + malloc_mutex_lock(&ctl_mtx); + if (i > POOLS_MAX) { + ret = NULL; + goto label_return; + } + + ret = super_thread_pool_i_node; +label_return: + malloc_mutex_unlock(&ctl_mtx); + return (ret); +} diff --git a/src/jemalloc/src/huge.c b/src/jemalloc/src/huge.c index d72f21357021aee8d14ca7971e0b75e03c4675cb..536e0821917e54f31c982e90b230d6ae08d5aeeb 100644 --- a/src/jemalloc/src/huge.c +++ b/src/jemalloc/src/huge.c @@ -1,34 +1,20 @@ #define JEMALLOC_HUGE_C_ #include "jemalloc/internal/jemalloc_internal.h" -/******************************************************************************/ -/* Data. */ - -uint64_t huge_nmalloc; -uint64_t huge_ndalloc; -size_t huge_allocated; - -malloc_mutex_t huge_mtx; - -/******************************************************************************/ - -/* Tree of chunks that are stand-alone huge allocations. */ -static extent_tree_t huge; - void * -huge_malloc(size_t size, bool zero, dss_prec_t dss_prec) +huge_malloc(arena_t *arena, size_t size, bool zero) { - - return (huge_palloc(size, chunksize, zero, dss_prec)); + return (huge_palloc(arena, size, chunksize, zero)); } void * -huge_palloc(size_t size, size_t alignment, bool zero, dss_prec_t dss_prec) +huge_palloc(arena_t *arena, size_t size, size_t alignment, bool zero) { void *ret; size_t csize; extent_node_t *node; bool is_zeroed; + pool_t *pool; /* Allocate one or more contiguous chunks for this request. */ @@ -38,34 +24,33 @@ huge_palloc(size_t size, size_t alignment, bool zero, dss_prec_t dss_prec) return (NULL); } - /* Allocate an extent node with which to track the chunk. */ - node = base_node_alloc(); - if (node == NULL) - return (NULL); - /* * Copy zero into is_zeroed and pass the copy to chunk_alloc(), so that * it is possible to make correct junk/zero fill decisions below. */ is_zeroed = zero; - ret = chunk_alloc(csize, alignment, false, &is_zeroed, dss_prec); + arena = choose_arena(arena); + pool = arena->pool; + + /* Allocate an extent node with which to track the chunk. */ + node = base_node_alloc(pool); + if (node == NULL) + return (NULL); + + ret = arena_chunk_alloc_huge(arena, csize, alignment, &is_zeroed); if (ret == NULL) { - base_node_dealloc(node); + base_node_dalloc(pool, node); return (NULL); } /* Insert node into huge. */ node->addr = ret; node->size = csize; + node->arena = arena; - malloc_mutex_lock(&huge_mtx); - extent_tree_ad_insert(&huge, node); - if (config_stats) { - stats_cactive_add(csize); - huge_nmalloc++; - huge_allocated += csize; - } - malloc_mutex_unlock(&huge_mtx); + malloc_mutex_lock(&pool->huge_mtx); + extent_tree_ad_insert(&pool->huge, node); + malloc_mutex_unlock(&pool->huge_mtx); if (config_fill && zero == false) { if (opt_junk) @@ -96,8 +81,8 @@ huge_ralloc_no_move(void *ptr, size_t oldsize, size_t size, size_t extra) } void * -huge_ralloc(void *ptr, size_t oldsize, size_t size, size_t extra, - size_t alignment, bool zero, bool try_tcache_dalloc, dss_prec_t dss_prec) +huge_ralloc(arena_t *arena, void *ptr, size_t oldsize, size_t size, + size_t extra, size_t alignment, bool zero, bool try_tcache_dalloc) { void *ret; size_t copysize; @@ -112,18 +97,18 @@ huge_ralloc(void *ptr, size_t oldsize, size_t size, size_t extra, * space and copying. */ if (alignment > chunksize) - ret = huge_palloc(size + extra, alignment, zero, dss_prec); + ret = huge_palloc(arena, size + extra, alignment, zero); else - ret = huge_malloc(size + extra, zero, dss_prec); + ret = huge_malloc(arena, size + extra, zero); if (ret == NULL) { if (extra == 0) return (NULL); /* Try again, this time without extra. */ if (alignment > chunksize) - ret = huge_palloc(size, alignment, zero, dss_prec); + ret = huge_palloc(arena, size, alignment, zero); else - ret = huge_malloc(size, zero, dss_prec); + ret = huge_malloc(arena, size, zero); if (ret == NULL) return (NULL); @@ -134,59 +119,8 @@ huge_ralloc(void *ptr, size_t oldsize, size_t size, size_t extra, * expectation that the extra bytes will be reliably preserved. */ copysize = (size < oldsize) ? size : oldsize; - -#ifdef JEMALLOC_MREMAP - /* - * Use mremap(2) if this is a huge-->huge reallocation, and neither the - * source nor the destination are in dss. - */ - if (oldsize >= chunksize && (config_dss == false || (chunk_in_dss(ptr) - == false && chunk_in_dss(ret) == false))) { - size_t newsize = huge_salloc(ret); - - /* - * Remove ptr from the tree of huge allocations before - * performing the remap operation, in order to avoid the - * possibility of another thread acquiring that mapping before - * this one removes it from the tree. - */ - huge_dalloc(ptr, false); - if (mremap(ptr, oldsize, newsize, MREMAP_MAYMOVE|MREMAP_FIXED, - ret) == MAP_FAILED) { - /* - * Assuming no chunk management bugs in the allocator, - * the only documented way an error can occur here is - * if the application changed the map type for a - * portion of the old allocation. This is firmly in - * undefined behavior territory, so write a diagnostic - * message, and optionally abort. - */ - char buf[BUFERROR_BUF]; - - buferror(get_errno(), buf, sizeof(buf)); - malloc_printf("<jemalloc>: Error in mremap(): %s\n", - buf); - if (opt_abort) - abort(); - memcpy(ret, ptr, copysize); - chunk_dealloc_mmap(ptr, oldsize); - } else if (config_fill && zero == false && opt_junk && oldsize - < newsize) { - /* - * mremap(2) clobbers the original mapping, so - * junk/zero filling is not preserved. There is no - * need to zero fill here, since any trailing - * uninititialized memory is demand-zeroed by the - * kernel, but junk filling must be redone. - */ - memset(ret + oldsize, 0xa5, newsize - oldsize); - } - } else -#endif - { - memcpy(ret, ptr, copysize); - iqalloct(ptr, try_tcache_dalloc); - } + memcpy(ret, ptr, copysize); + iqalloct(ptr, try_tcache_dalloc); return (ret); } @@ -198,12 +132,12 @@ static void huge_dalloc_junk(void *ptr, size_t usize) { - if (config_fill && config_dss && opt_junk) { + if (config_fill && have_dss && opt_junk) { /* * Only bother junk filling if the chunk isn't about to be * unmapped. */ - if (config_munmap == false || (config_dss && chunk_in_dss(ptr))) + if (config_munmap == false || (have_dss && chunk_in_dss(ptr))) memset(ptr, 0x5a, usize); } } @@ -214,78 +148,75 @@ huge_dalloc_junk_t *huge_dalloc_junk = JEMALLOC_N(huge_dalloc_junk_impl); #endif void -huge_dalloc(void *ptr, bool unmap) +huge_dalloc(pool_t *pool, void *ptr) { extent_node_t *node, key; - malloc_mutex_lock(&huge_mtx); + malloc_mutex_lock(&pool->huge_mtx); /* Extract from tree of huge allocations. */ key.addr = ptr; - node = extent_tree_ad_search(&huge, &key); + node = extent_tree_ad_search(&pool->huge, &key); assert(node != NULL); assert(node->addr == ptr); - extent_tree_ad_remove(&huge, node); - - if (config_stats) { - stats_cactive_sub(node->size); - huge_ndalloc++; - huge_allocated -= node->size; - } - - malloc_mutex_unlock(&huge_mtx); + extent_tree_ad_remove(&pool->huge, node); - if (unmap) - huge_dalloc_junk(node->addr, node->size); + malloc_mutex_unlock(&pool->huge_mtx); - chunk_dealloc(node->addr, node->size, unmap); - - base_node_dealloc(node); + huge_dalloc_junk(node->addr, node->size); + arena_chunk_dalloc_huge(node->arena, node->addr, node->size); + base_node_dalloc(pool, node); } size_t huge_salloc(const void *ptr) { - size_t ret; + size_t ret = 0; + int i; extent_node_t *node, key; - - malloc_mutex_lock(&huge_mtx); - - /* Extract from tree of huge allocations. */ - key.addr = __DECONST(void *, ptr); - node = extent_tree_ad_search(&huge, &key); - assert(node != NULL); - - ret = node->size; - - malloc_mutex_unlock(&huge_mtx); + for (i = 0; i < POOLS_MAX; ++i) { + pool_t *pool = pools[i]; + if (pool == NULL) + continue; + malloc_mutex_lock(&pool->huge_mtx); + + /* Extract from tree of huge allocations. */ + key.addr = __DECONST(void *, ptr); + node = extent_tree_ad_search(&pool->huge, &key); + if (node != NULL) + ret = node->size; + + malloc_mutex_unlock(&pool->huge_mtx); + if (ret != 0) + break; + } return (ret); } -dss_prec_t -huge_dss_prec_get(arena_t *arena) -{ - - return (arena_dss_prec_get(choose_arena(arena))); -} - prof_ctx_t * huge_prof_ctx_get(const void *ptr) { - prof_ctx_t *ret; + prof_ctx_t *ret = NULL; + int i; extent_node_t *node, key; - malloc_mutex_lock(&huge_mtx); - - /* Extract from tree of huge allocations. */ - key.addr = __DECONST(void *, ptr); - node = extent_tree_ad_search(&huge, &key); - assert(node != NULL); - - ret = node->prof_ctx; - - malloc_mutex_unlock(&huge_mtx); + for (i = 0; i < POOLS_MAX; ++i) { + pool_t *pool = pools[i]; + if (pool == NULL) + continue; + malloc_mutex_lock(&pool->huge_mtx); + + /* Extract from tree of huge allocations. */ + key.addr = __DECONST(void *, ptr); + node = extent_tree_ad_search(&pool->huge, &key); + if (node != NULL) + ret = node->prof_ctx; + + malloc_mutex_unlock(&pool->huge_mtx); + if (ret != NULL) + break; + } return (ret); } @@ -294,54 +225,56 @@ void huge_prof_ctx_set(const void *ptr, prof_ctx_t *ctx) { extent_node_t *node, key; + int i; - malloc_mutex_lock(&huge_mtx); + for (i = 0; i < POOLS_MAX; ++i) { + pool_t *pool = pools[i]; + if (pool == NULL) + continue; + malloc_mutex_lock(&pool->huge_mtx); - /* Extract from tree of huge allocations. */ - key.addr = __DECONST(void *, ptr); - node = extent_tree_ad_search(&huge, &key); - assert(node != NULL); + /* Extract from tree of huge allocations. */ + key.addr = __DECONST(void *, ptr); + node = extent_tree_ad_search(&pool->huge, &key); + if (node != NULL) + node->prof_ctx = ctx; - node->prof_ctx = ctx; + malloc_mutex_unlock(&pool->huge_mtx); - malloc_mutex_unlock(&huge_mtx); + if (node != NULL) + break; + } } bool -huge_boot(void) +huge_boot(pool_t *pool) { /* Initialize chunks data. */ - if (malloc_mutex_init(&huge_mtx)) + if (malloc_mutex_init(&pool->huge_mtx)) return (true); - extent_tree_ad_new(&huge); - - if (config_stats) { - huge_nmalloc = 0; - huge_ndalloc = 0; - huge_allocated = 0; - } + extent_tree_ad_new(&pool->huge); return (false); } void -huge_prefork(void) +huge_prefork(pool_t *pool) { - malloc_mutex_prefork(&huge_mtx); + malloc_mutex_prefork(&pool->huge_mtx); } void -huge_postfork_parent(void) +huge_postfork_parent(pool_t *pool) { - malloc_mutex_postfork_parent(&huge_mtx); + malloc_mutex_postfork_parent(&pool->huge_mtx); } void -huge_postfork_child(void) +huge_postfork_child(pool_t *pool) { - malloc_mutex_postfork_child(&huge_mtx); + malloc_mutex_postfork_child(&pool->huge_mtx); } diff --git a/src/jemalloc/src/jemalloc.c b/src/jemalloc/src/jemalloc.c index 204778bc89d8f40105a7fc4943df3620d24c8cfa..cb5ed9ec2867084475abc8c22c5579b49a6a522f 100644 --- a/src/jemalloc/src/jemalloc.c +++ b/src/jemalloc/src/jemalloc.c @@ -3,8 +3,7 @@ /******************************************************************************/ /* Data. */ - -malloc_tsd_data(, arenas, arena_t *, NULL) +malloc_tsd_data(, arenas, tsd_pool_t, TSD_POOL_INITIALIZER) malloc_tsd_data(, thread_allocated, thread_allocated_t, THREAD_ALLOCATED_INITIALIZER) @@ -27,17 +26,29 @@ bool opt_junk = size_t opt_quarantine = ZU(0); bool opt_redzone = false; bool opt_utrace = false; -bool opt_valgrind = false; bool opt_xmalloc = false; bool opt_zero = false; size_t opt_narenas = 0; +/* Initialized to true if the process is running inside Valgrind. */ +bool in_valgrind; + + +unsigned npools; unsigned ncpus; -malloc_mutex_t arenas_lock; -arena_t **arenas; -unsigned narenas_total; -unsigned narenas_auto; +pool_t *pools[POOLS_MAX]; +pool_t init_pool; +unsigned pool_seqno = 0; +bool pools_shared_data_initialized; + +/* + * Custom malloc() and free() for shared data and for data needed to + * initialize pool. If not defined functions then base_pool will be + * created for allocations from RAM. + */ +void *(*je_base_malloc)(size_t); +void (*je_base_free)(void *); /* Set to true once the allocator has been initialized. */ static bool malloc_initialized = false; @@ -106,6 +117,10 @@ typedef struct { */ static bool malloc_init_hard(void); +static bool malloc_init_base_pool(void); +static bool pools_shared_data_create(void); +static void *base_malloc_default(size_t size); +static void base_free_default(void *ptr); /******************************************************************************/ /* @@ -114,13 +129,13 @@ static bool malloc_init_hard(void); /* Create a new arena and insert it into the arenas array at index ind. */ arena_t * -arenas_extend(unsigned ind) +arenas_extend(pool_t *pool, unsigned ind) { arena_t *ret; - ret = (arena_t *)base_alloc(sizeof(arena_t)); - if (ret != NULL && arena_new(ret, ind) == false) { - arenas[ind] = ret; + ret = (arena_t *)base_alloc(pool, sizeof(arena_t)); + if (ret != NULL && arena_new(pool, ret, ind) == false) { + pool->arenas[ind] = ret; return (ret); } /* Only reached if there is an OOM error. */ @@ -135,32 +150,33 @@ arenas_extend(unsigned ind) if (opt_abort) abort(); - return (arenas[0]); + return (pool->arenas[0]); } /* Slow path, called only by choose_arena(). */ arena_t * -choose_arena_hard(void) +choose_arena_hard(pool_t *pool) { arena_t *ret; + tsd_pool_t *tsd; - if (narenas_auto > 1) { + if (pool->narenas_auto > 1) { unsigned i, choose, first_null; choose = 0; - first_null = narenas_auto; - malloc_mutex_lock(&arenas_lock); - assert(arenas[0] != NULL); - for (i = 1; i < narenas_auto; i++) { - if (arenas[i] != NULL) { + first_null = pool->narenas_auto; + malloc_mutex_lock(&pool->arenas_lock); + assert(pool->arenas[0] != NULL); + for (i = 1; i < pool->narenas_auto; i++) { + if (pool->arenas[i] != NULL) { /* * Choose the first arena that has the lowest * number of threads assigned to it. */ - if (arenas[i]->nthreads < - arenas[choose]->nthreads) + if (pool->arenas[i]->nthreads < + pool->arenas[choose]->nthreads) choose = i; - } else if (first_null == narenas_auto) { + } else if (first_null == pool->narenas_auto) { /* * Record the index of the first uninitialized * arena, in case all extant arenas are in use. @@ -174,27 +190,30 @@ choose_arena_hard(void) } } - if (arenas[choose]->nthreads == 0 - || first_null == narenas_auto) { + if (pool->arenas[choose]->nthreads == 0 + || first_null == pool->narenas_auto) { /* * Use an unloaded arena, or the least loaded arena if * all arenas are already initialized. */ - ret = arenas[choose]; + ret = pool->arenas[choose]; } else { /* Initialize a new arena. */ - ret = arenas_extend(first_null); + ret = arenas_extend(pool, first_null); } ret->nthreads++; - malloc_mutex_unlock(&arenas_lock); + malloc_mutex_unlock(&pool->arenas_lock); } else { - ret = arenas[0]; - malloc_mutex_lock(&arenas_lock); + ret = pool->arenas[0]; + malloc_mutex_lock(&pool->arenas_lock); ret->nthreads++; - malloc_mutex_unlock(&arenas_lock); + malloc_mutex_unlock(&pool->arenas_lock); } - arenas_tsd_set(&ret); + tsd = arenas_tsd_get(); + tsd->seqno[pool->pool_id] = pool->seqno; + tsd->arenas[pool->pool_id] = ret; + return (ret); } @@ -204,7 +223,8 @@ stats_print_atexit(void) { if (config_tcache && config_stats) { - unsigned narenas, i; + unsigned narenas, i, j; + pool_t *pool; /* * Merge stats from extant threads. This is racy, since @@ -213,24 +233,31 @@ stats_print_atexit(void) * out of date by the time they are reported, if other threads * continue to allocate. */ - for (i = 0, narenas = narenas_total_get(); i < narenas; i++) { - arena_t *arena = arenas[i]; - if (arena != NULL) { - tcache_t *tcache; - - /* - * tcache_stats_merge() locks bins, so if any - * code is introduced that acquires both arena - * and bin locks in the opposite order, - * deadlocks may result. - */ - malloc_mutex_lock(&arena->lock); - ql_foreach(tcache, &arena->tcache_ql, link) { - tcache_stats_merge(tcache, arena); + malloc_mutex_lock(&pools_lock); + for (i = 0; i < POOLS_MAX; i++) { + pool = pools[i]; + if (pool != NULL) { + for (j = 0, narenas = narenas_total_get(pool); j < narenas; j++) { + arena_t *arena = pool->arenas[j]; + if (arena != NULL) { + tcache_t *tcache; + + /* + * tcache_stats_merge() locks bins, so if any + * code is introduced that acquires both arena + * and bin locks in the opposite order, + * deadlocks may result. + */ + malloc_mutex_lock(&arena->lock); + ql_foreach(tcache, &arena->tcache_ql, link) { + tcache_stats_merge(tcache, arena); + } + malloc_mutex_unlock(&arena->lock); + } } - malloc_mutex_unlock(&arena->lock); } } + malloc_mutex_unlock(&pools_lock); } je_malloc_stats_print(NULL, NULL, NULL); } @@ -261,16 +288,77 @@ malloc_ncpus(void) void arenas_cleanup(void *arg) { - arena_t *arena = *(arena_t **)arg; + unsigned i; + pool_t *pool; + tsd_pool_t *tsd = arg; + malloc_mutex_lock(&pools_lock); + for (i = 0; i < POOLS_MAX; i++) { + pool = pools[i]; + if (pool != NULL) { + if (pool->seqno == tsd->seqno[i] && tsd->arenas[i] != NULL) { + malloc_mutex_lock(&pool->arenas_lock); + tsd->arenas[i]->nthreads--; + malloc_mutex_unlock(&pool->arenas_lock); + } + } + } + malloc_mutex_unlock(&pools_lock); - malloc_mutex_lock(&arenas_lock); - arena->nthreads--; - malloc_mutex_unlock(&arenas_lock); } JEMALLOC_ALWAYS_INLINE_C void malloc_thread_init(void) { + if (config_fill && opt_quarantine && je_base_malloc == base_malloc_default) { + /* create pool base and call quarantine_alloc_hook() inside */ + malloc_init_base_pool(); + } +} + +JEMALLOC_ALWAYS_INLINE_C bool +malloc_init(void) +{ + + if (malloc_initialized == false && malloc_init_hard()) + return (true); + + return (false); +} + +static bool +malloc_init_base_pool(void) +{ + pool_t *base_pool; + + if (malloc_initialized == false && malloc_init_hard()) + return (true); + + if (pools[0] != NULL) + return (false); + + malloc_mutex_lock(&pool_base_lock); + if (pools[0] != NULL) { + /* + * Another thread initialized the base pool before this one + * acquired pools_lock. + */ + malloc_mutex_unlock(&pool_base_lock); + return (false); + } + + base_pool = &init_pool; + npools++; + pools[0] = base_pool; + pools[0]->seqno = ++pool_seqno; + + pools_shared_data_create(); + + if (pool_new(base_pool, 0)) { + malloc_mutex_unlock(&pool_base_lock); + return (true); + } + + malloc_mutex_unlock(&pool_base_lock); /* * TSD initialization can't be safely done as a side effect of @@ -281,17 +369,10 @@ malloc_thread_init(void) * a best effort attempt at initializing its TSD by hooking all * allocation events. */ - if (config_fill && opt_quarantine) + if (config_fill && opt_quarantine) { quarantine_alloc_hook(); -} - -JEMALLOC_ALWAYS_INLINE_C bool -malloc_init(void) -{ + } - if (malloc_initialized == false && malloc_init_hard()) - return (true); - malloc_thread_init(); return (false); } @@ -394,14 +475,14 @@ malloc_conf_init(void) * valgrind option remains in jemalloc 3.x for compatibility reasons. */ if (config_valgrind) { - opt_valgrind = (RUNNING_ON_VALGRIND != 0) ? true : false; - if (config_fill && opt_valgrind) { + in_valgrind = (RUNNING_ON_VALGRIND != 0) ? true : false; + if (config_fill && in_valgrind) { opt_junk = false; assert(opt_zero == false); opt_quarantine = JEMALLOC_VALGRIND_QUARANTINE_DEFAULT; opt_redzone = true; } - if (config_tcache && opt_valgrind) + if (config_tcache && in_valgrind) opt_tcache = false; } @@ -477,9 +558,10 @@ malloc_conf_init(void) while (*opts != '\0' && malloc_conf_next(&opts, &k, &klen, &v, &vlen) == false) { -#define CONF_HANDLE_BOOL(o, n) \ - if (sizeof(n)-1 == klen && strncmp(n, k, \ - klen) == 0) { \ +#define CONF_MATCH(n) \ + (sizeof(n)-1 == klen && strncmp(n, k, klen) == 0) +#define CONF_HANDLE_BOOL(o, n, cont) \ + if (CONF_MATCH(n)) { \ if (strncmp("true", v, vlen) == 0 && \ vlen == sizeof("true")-1) \ o = true; \ @@ -491,11 +573,11 @@ malloc_conf_init(void) "Invalid conf value", \ k, klen, v, vlen); \ } \ - continue; \ + if (cont) \ + continue; \ } #define CONF_HANDLE_SIZE_T(o, n, min, max, clip) \ - if (sizeof(n)-1 == klen && strncmp(n, k, \ - klen) == 0) { \ + if (CONF_MATCH(n)) { \ uintmax_t um; \ char *end; \ \ @@ -526,8 +608,7 @@ malloc_conf_init(void) continue; \ } #define CONF_HANDLE_SSIZE_T(o, n, min, max) \ - if (sizeof(n)-1 == klen && strncmp(n, k, \ - klen) == 0) { \ + if (CONF_MATCH(n)) { \ long l; \ char *end; \ \ @@ -548,8 +629,7 @@ malloc_conf_init(void) continue; \ } #define CONF_HANDLE_CHAR_P(o, n, d) \ - if (sizeof(n)-1 == klen && strncmp(n, k, \ - klen) == 0) { \ + if (CONF_MATCH(n)) { \ size_t cpylen = (vlen <= \ sizeof(o)-1) ? vlen : \ sizeof(o)-1; \ @@ -558,7 +638,7 @@ malloc_conf_init(void) continue; \ } - CONF_HANDLE_BOOL(opt_abort, "abort") + CONF_HANDLE_BOOL(opt_abort, "abort", true) /* * Chunks always require at least one header page, plus * one data page in the absence of redzones, or three @@ -597,47 +677,62 @@ malloc_conf_init(void) SIZE_T_MAX, false) CONF_HANDLE_SSIZE_T(opt_lg_dirty_mult, "lg_dirty_mult", -1, (sizeof(size_t) << 3) - 1) - CONF_HANDLE_BOOL(opt_stats_print, "stats_print") + CONF_HANDLE_BOOL(opt_stats_print, "stats_print", true) if (config_fill) { - CONF_HANDLE_BOOL(opt_junk, "junk") + CONF_HANDLE_BOOL(opt_junk, "junk", true) CONF_HANDLE_SIZE_T(opt_quarantine, "quarantine", 0, SIZE_T_MAX, false) - CONF_HANDLE_BOOL(opt_redzone, "redzone") - CONF_HANDLE_BOOL(opt_zero, "zero") + CONF_HANDLE_BOOL(opt_redzone, "redzone", true) + CONF_HANDLE_BOOL(opt_zero, "zero", true) } if (config_utrace) { - CONF_HANDLE_BOOL(opt_utrace, "utrace") - } - if (config_valgrind) { - CONF_HANDLE_BOOL(opt_valgrind, "valgrind") + CONF_HANDLE_BOOL(opt_utrace, "utrace", true) } if (config_xmalloc) { - CONF_HANDLE_BOOL(opt_xmalloc, "xmalloc") + CONF_HANDLE_BOOL(opt_xmalloc, "xmalloc", true) } if (config_tcache) { - CONF_HANDLE_BOOL(opt_tcache, "tcache") + CONF_HANDLE_BOOL(opt_tcache, "tcache", + !config_valgrind || !in_valgrind) + if (CONF_MATCH("tcache")) { + assert(config_valgrind && in_valgrind); + if (opt_tcache) { + opt_tcache = false; + malloc_conf_error( + "tcache cannot be enabled " + "while running inside Valgrind", + k, klen, v, vlen); + } + continue; + } CONF_HANDLE_SSIZE_T(opt_lg_tcache_max, "lg_tcache_max", -1, (sizeof(size_t) << 3) - 1) } if (config_prof) { - CONF_HANDLE_BOOL(opt_prof, "prof") + CONF_HANDLE_BOOL(opt_prof, "prof", true) CONF_HANDLE_CHAR_P(opt_prof_prefix, "prof_prefix", "jeprof") - CONF_HANDLE_BOOL(opt_prof_active, "prof_active") + CONF_HANDLE_BOOL(opt_prof_active, "prof_active", + true) CONF_HANDLE_SSIZE_T(opt_lg_prof_sample, "lg_prof_sample", 0, (sizeof(uint64_t) << 3) - 1) - CONF_HANDLE_BOOL(opt_prof_accum, "prof_accum") + CONF_HANDLE_BOOL(opt_prof_accum, "prof_accum", + true) CONF_HANDLE_SSIZE_T(opt_lg_prof_interval, "lg_prof_interval", -1, (sizeof(uint64_t) << 3) - 1) - CONF_HANDLE_BOOL(opt_prof_gdump, "prof_gdump") - CONF_HANDLE_BOOL(opt_prof_final, "prof_final") - CONF_HANDLE_BOOL(opt_prof_leak, "prof_leak") + CONF_HANDLE_BOOL(opt_prof_gdump, "prof_gdump", + true) + CONF_HANDLE_BOOL(opt_prof_final, "prof_final", + true) + CONF_HANDLE_BOOL(opt_prof_leak, "prof_leak", + true) } malloc_conf_error("Invalid conf pair", k, klen, v, vlen); +#undef CONF_MATCH #undef CONF_HANDLE_BOOL #undef CONF_HANDLE_SIZE_T #undef CONF_HANDLE_SSIZE_T @@ -649,8 +744,6 @@ malloc_conf_init(void) static bool malloc_init_hard(void) { - arena_t *init_arenas[1]; - malloc_mutex_lock(&init_lock); if (malloc_initialized || IS_INITIALIZER) { /* @@ -690,15 +783,14 @@ malloc_init_hard(void) } } - if (base_boot()) { - malloc_mutex_unlock(&init_lock); - return (true); - } + npools = 0; + pools_shared_data_initialized = false; + memset(pools, 0, sizeof(pool_t *) * POOLS_MAX); - if (chunk_boot()) { - malloc_mutex_unlock(&init_lock); - return (true); - } + je_base_malloc = base_malloc_default; + je_base_free = base_free_default; + + chunk_global_boot(); if (ctl_boot()) { malloc_mutex_unlock(&init_lock); @@ -710,38 +802,7 @@ malloc_init_hard(void) arena_boot(); - if (config_tcache && tcache_boot0()) { - malloc_mutex_unlock(&init_lock); - return (true); - } - - if (huge_boot()) { - malloc_mutex_unlock(&init_lock); - return (true); - } - - if (malloc_mutex_init(&arenas_lock)) { - malloc_mutex_unlock(&init_lock); - return (true); - } - - /* - * Create enough scaffolding to allow recursive allocation in - * malloc_ncpus(). - */ - narenas_total = narenas_auto = 1; - arenas = init_arenas; - memset(arenas, 0, sizeof(arena_t *) * narenas_auto); - - /* - * Initialize one arena here. The rest are lazily created in - * choose_arena_hard(). - */ - arenas_extend(0); - if (arenas[0] == NULL) { - malloc_mutex_unlock(&init_lock); - return (true); - } + pool_boot(); /* Initialize allocation counters before any allocations can occur. */ if (config_stats && thread_allocated_tsd_boot()) { @@ -776,7 +837,7 @@ malloc_init_hard(void) ncpus = malloc_ncpus(); #if (!defined(JEMALLOC_MUTEX_INIT_CB) && !defined(JEMALLOC_ZONE) \ - && !defined(_WIN32)) + && !defined(_WIN32) && !defined(__native_client__)) /* LinuxThreads's pthread_atfork() allocates. */ if (pthread_atfork(jemalloc_prefork, jemalloc_postfork_parent, jemalloc_postfork_child) != 0) { @@ -805,32 +866,6 @@ malloc_init_hard(void) else opt_narenas = 1; } - narenas_auto = opt_narenas; - /* - * Make sure that the arenas array can be allocated. In practice, this - * limit is enough to allow the allocator to function, but the ctl - * machinery will fail to allocate memory at far lower limits. - */ - if (narenas_auto > chunksize / sizeof(arena_t *)) { - narenas_auto = chunksize / sizeof(arena_t *); - malloc_printf("<jemalloc>: Reducing narenas to limit (%d)\n", - narenas_auto); - } - narenas_total = narenas_auto; - - /* Allocate and initialize arenas. */ - arenas = (arena_t **)base_alloc(sizeof(arena_t *) * narenas_total); - if (arenas == NULL) { - malloc_mutex_unlock(&init_lock); - return (true); - } - /* - * Zero the array. In practice, this should always be pre-zeroed, - * since it was just mmap()ed, but let's be sure. - */ - memset(arenas, 0, sizeof(arena_t *) * narenas_total); - /* Copy the pointer to the one arena that was already initialized. */ - arenas[0] = init_arenas[0]; malloc_initialized = true; malloc_mutex_unlock(&init_lock); @@ -853,7 +888,7 @@ imalloc_prof_sample(size_t usize, prof_thr_cnt_t *cnt) if (cnt == NULL) return (NULL); - if (prof_promote && usize <= SMALL_MAXCLASS) { + if (usize <= SMALL_MAXCLASS) { p = imalloc(SMALL_MAXCLASS+1); if (p == NULL) return (NULL); @@ -865,10 +900,12 @@ imalloc_prof_sample(size_t usize, prof_thr_cnt_t *cnt) } JEMALLOC_ALWAYS_INLINE_C void * -imalloc_prof(size_t usize, prof_thr_cnt_t *cnt) +imalloc_prof(size_t usize) { void *p; + prof_thr_cnt_t *cnt; + PROF_ALLOC_PREP(usize, cnt); if ((uintptr_t)cnt != (uintptr_t)1U) p = imalloc_prof_sample(usize, cnt); else @@ -880,42 +917,22 @@ imalloc_prof(size_t usize, prof_thr_cnt_t *cnt) return (p); } -/* - * MALLOC_BODY() is a macro rather than a function because its contents are in - * the fast path, but inlining would cause reliability issues when determining - * how many frames to discard from heap profiling backtraces. - */ -#define MALLOC_BODY(ret, size, usize) do { \ - if (malloc_init()) \ - ret = NULL; \ - else { \ - if (config_prof && opt_prof) { \ - prof_thr_cnt_t *cnt; \ - \ - usize = s2u(size); \ - /* \ - * Call PROF_ALLOC_PREP() here rather than in \ - * imalloc_prof() so that imalloc_prof() can be \ - * inlined without introducing uncertainty \ - * about the number of backtrace frames to \ - * ignore. imalloc_prof() is in the fast path \ - * when heap profiling is enabled, so inlining \ - * is critical to performance. (For \ - * consistency all callers of PROF_ALLOC_PREP() \ - * are structured similarly, even though e.g. \ - * realloc() isn't called enough for inlining \ - * to be critical.) \ - */ \ - PROF_ALLOC_PREP(1, usize, cnt); \ - ret = imalloc_prof(usize, cnt); \ - } else { \ - if (config_stats || (config_valgrind && \ - opt_valgrind)) \ - usize = s2u(size); \ - ret = imalloc(size); \ - } \ - } \ -} while (0) +JEMALLOC_ALWAYS_INLINE_C void * +imalloc_body(size_t size, size_t *usize) +{ + + if (malloc_init_base_pool()) + return (NULL); + + if (config_prof && opt_prof) { + *usize = s2u(size); + return (imalloc_prof(*usize)); + } + + if (config_stats || (config_valgrind && in_valgrind)) + *usize = s2u(size); + return (imalloc(size)); +} void * je_malloc(size_t size) @@ -926,8 +943,7 @@ je_malloc(size_t size) if (size == 0) size = 1; - MALLOC_BODY(ret, size, usize); - + ret = imalloc_body(size, &usize); if (ret == NULL) { if (config_xmalloc && opt_xmalloc) { malloc_write("<jemalloc>: Error in malloc(): " @@ -952,7 +968,7 @@ imemalign_prof_sample(size_t alignment, size_t usize, prof_thr_cnt_t *cnt) if (cnt == NULL) return (NULL); - if (prof_promote && usize <= SMALL_MAXCLASS) { + if (usize <= SMALL_MAXCLASS) { assert(sa2u(SMALL_MAXCLASS+1, alignment) != 0); p = ipalloc(sa2u(SMALL_MAXCLASS+1, alignment), alignment, false); @@ -982,13 +998,6 @@ imemalign_prof(size_t alignment, size_t usize, prof_thr_cnt_t *cnt) } JEMALLOC_ATTR(nonnull(1)) -#ifdef JEMALLOC_PROF -/* - * Avoid any uncertainty as to how many backtrace frames to ignore in - * PROF_ALLOC_PREP(). - */ -JEMALLOC_NOINLINE -#endif static int imemalign(void **memptr, size_t alignment, size_t size, size_t min_alignment) { @@ -998,7 +1007,7 @@ imemalign(void **memptr, size_t alignment, size_t size, size_t min_alignment) assert(min_alignment != 0); - if (malloc_init()) { + if (malloc_init_base_pool()) { result = NULL; goto label_oom; } else { @@ -1027,7 +1036,7 @@ imemalign(void **memptr, size_t alignment, size_t size, size_t min_alignment) if (config_prof && opt_prof) { prof_thr_cnt_t *cnt; - PROF_ALLOC_PREP(2, usize, cnt); + PROF_ALLOC_PREP(usize, cnt); result = imemalign_prof(alignment, usize, cnt); } else result = ipalloc(usize, alignment, false); @@ -1086,7 +1095,7 @@ icalloc_prof_sample(size_t usize, prof_thr_cnt_t *cnt) if (cnt == NULL) return (NULL); - if (prof_promote && usize <= SMALL_MAXCLASS) { + if (usize <= SMALL_MAXCLASS) { p = icalloc(SMALL_MAXCLASS+1); if (p == NULL) return (NULL); @@ -1120,7 +1129,7 @@ je_calloc(size_t num, size_t size) size_t num_size; size_t usize JEMALLOC_CC_SILENCE_INIT(0); - if (malloc_init()) { + if (malloc_init_base_pool()) { num_size = 0; ret = NULL; goto label_return; @@ -1150,10 +1159,10 @@ je_calloc(size_t num, size_t size) prof_thr_cnt_t *cnt; usize = s2u(num_size); - PROF_ALLOC_PREP(1, usize, cnt); + PROF_ALLOC_PREP(usize, cnt); ret = icalloc_prof(usize, cnt); } else { - if (config_stats || (config_valgrind && opt_valgrind)) + if (config_stats || (config_valgrind && in_valgrind)) usize = s2u(num_size); ret = icalloc(num_size); } @@ -1183,7 +1192,7 @@ irealloc_prof_sample(void *oldptr, size_t usize, prof_thr_cnt_t *cnt) if (cnt == NULL) return (NULL); - if (prof_promote && usize <= SMALL_MAXCLASS) { + if (usize <= SMALL_MAXCLASS) { p = iralloc(oldptr, SMALL_MAXCLASS+1, 0, 0, false); if (p == NULL) return (NULL); @@ -1220,6 +1229,7 @@ ifree(void *ptr) assert(ptr != NULL); assert(malloc_initialized || IS_INITIALIZER); + assert(pools[0] != NULL); if (config_prof && opt_prof) { usize = isalloc(ptr, config_prof); @@ -1228,7 +1238,7 @@ ifree(void *ptr) usize = isalloc(ptr, config_prof); if (config_stats) thread_allocated_tsd_get()->deallocated += usize; - if (config_valgrind && opt_valgrind) + if (config_valgrind && in_valgrind) rzsize = p2rz(ptr); iqalloc(ptr); JEMALLOC_VALGRIND_FREE(ptr, rzsize); @@ -1254,28 +1264,29 @@ je_realloc(void *ptr, size_t size) if (ptr != NULL) { assert(malloc_initialized || IS_INITIALIZER); + assert(pools[0] != NULL); malloc_thread_init(); if ((config_prof && opt_prof) || config_stats || - (config_valgrind && opt_valgrind)) + (config_valgrind && in_valgrind)) old_usize = isalloc(ptr, config_prof); - if (config_valgrind && opt_valgrind) + if (config_valgrind && in_valgrind) old_rzsize = config_prof ? p2rz(ptr) : u2rz(old_usize); if (config_prof && opt_prof) { prof_thr_cnt_t *cnt; usize = s2u(size); - PROF_ALLOC_PREP(1, usize, cnt); + PROF_ALLOC_PREP(usize, cnt); ret = irealloc_prof(ptr, old_usize, usize, cnt); } else { - if (config_stats || (config_valgrind && opt_valgrind)) + if (config_stats || (config_valgrind && in_valgrind)) usize = s2u(size); ret = iralloc(ptr, size, 0, 0, false); } } else { /* realloc(NULL, size) is equivalent to malloc(size). */ - MALLOC_BODY(ret, size, usize); + ret = imalloc_body(size, &usize); } if (ret == NULL) { @@ -1294,8 +1305,8 @@ je_realloc(void *ptr, size_t size) ta->deallocated += old_usize; } UTRACE(ptr, size, ret); - JEMALLOC_VALGRIND_REALLOC(ret, usize, ptr, old_usize, old_rzsize, - false); + JEMALLOC_VALGRIND_REALLOC(true, ret, usize, true, ptr, old_usize, + old_rzsize, true, false); return (ret); } @@ -1356,10 +1367,10 @@ je_valloc(size_t size) * passed an extra argument for the caller return address, which will be * ignored. */ -JEMALLOC_EXPORT void (* __free_hook)(void *ptr) = je_free; -JEMALLOC_EXPORT void *(* __malloc_hook)(size_t size) = je_malloc; -JEMALLOC_EXPORT void *(* __realloc_hook)(void *ptr, size_t size) = je_realloc; -JEMALLOC_EXPORT void *(* __memalign_hook)(size_t alignment, size_t size) = +JEMALLOC_EXPORT void (*__free_hook)(void *ptr) = je_free; +JEMALLOC_EXPORT void *(*__malloc_hook)(size_t size) = je_malloc; +JEMALLOC_EXPORT void *(*__realloc_hook)(void *ptr, size_t size) = je_realloc; +JEMALLOC_EXPORT void *(*__memalign_hook)(size_t alignment, size_t size) = je_memalign; #endif @@ -1371,56 +1382,242 @@ JEMALLOC_EXPORT void *(* __memalign_hook)(size_t alignment, size_t size) = * Begin non-standard functions. */ -JEMALLOC_ALWAYS_INLINE_C void * -imallocx(size_t usize, size_t alignment, bool zero, bool try_tcache, - arena_t *arena) +static void* +base_malloc_default(size_t size) { + pool_t *pool = pools[0]; + return base_alloc(pool, size); +} - assert(usize == ((alignment == 0) ? s2u(usize) : sa2u(usize, - alignment))); +static void +base_free_default(void *ptr) +{ - if (alignment != 0) - return (ipalloct(usize, alignment, zero, try_tcache, arena)); - else if (zero) - return (icalloct(usize, try_tcache, arena)); - else - return (imalloct(usize, try_tcache, arena)); +} + +static bool +pools_shared_data_create(void) +{ + if (malloc_initialized == false && malloc_init_hard()) + return (true); + + assert(je_base_malloc != base_malloc_default || pools[0] != NULL); + + if (pools_shared_data_initialized) + return (false); + + if (config_tcache && tcache_boot0()) { + return (true); + } + + pools_shared_data_initialized = true; + + return (false); +} + +void pools_shared_data_destroy(void) +{ + /* Only destroy when no pools exist */ + if (npools == 0) { + pools_shared_data_initialized = false; + + je_base_free(tcache_bin_info); + tcache_bin_info = NULL; + } +} + +pool_t * +je_pool_create(void *addr, size_t size, int zeroed) +{ + if (addr == NULL || size < POOL_MINIMAL_SIZE) + return NULL; + + pool_t *pool = (pool_t *)addr; + unsigned pool_id = POOLS_MAX; + size_t result; + + if (je_base_malloc == base_malloc_default) { + /* Preinit base pool if not exist, before lock pool_lock */ + if (malloc_init_base_pool()) + return NULL; + } + + malloc_mutex_lock(&pools_lock); + + /* Find unused pool ID */ + if (npools < POOLS_MAX) { + /* + * Pool 0 is a special pool with reserved ID. Pool is created during + * malloc_init_pool_base() and allocates memory from RAM. + */ + int i; + for (i = 1; i < POOLS_MAX; ++i) { + if (pools[i] == NULL) { + pool_id = i; + break; + } + } + } + + if (pool_id == POOLS_MAX) { + malloc_mutex_unlock(&pools_lock); + malloc_printf("<jemalloc>: Too many pools\n"); + return NULL; + } + + if (pools_shared_data_create()) { + malloc_mutex_unlock(&pools_lock); + return NULL; + } + + if (!zeroed) + memset(addr, 0, sizeof (pool_t)); + + /* preinit base allocator in unused space, align the address to the cache line */ + pool->base_next_addr = (void *)CACHELINE_CEILING((uintptr_t)addr + + sizeof (pool_t)); + pool->base_past_addr = (void *)((uintptr_t)addr + size); + + /* prepare pool and internal structures */ + if (pool_new(pool, pool_id)) { + assert(pools[pool_id] == NULL); + malloc_mutex_unlock(&pools_lock); + pools_shared_data_destroy(); + return NULL; + } + + /* preallocate the chunk tree nodes for the maximum possible number of chunks */ + result = base_node_prealloc(pool, size/chunksize); + assert(result == 0); + + assert(pools[pool_id] == NULL); + pool->seqno = pool_seqno++; + pools[pool_id] = pool; + npools++; + malloc_mutex_unlock(&pools_lock); + + /* pointer to the address of chunks, align the address to chunksize */ + void *usable_addr = (void*)CHUNK_CEILING((uintptr_t)pool->base_next_addr); + + /* reduce end of base allocator up to chunks start */ + pool->base_past_addr = usable_addr; + + /* usable chunks space, must be multiple of chunksize */ + size_t usable_size = (size - (uintptr_t)(usable_addr - addr)) + & ~chunksize_mask; + + assert(usable_size > 0); + + /* register the usable pool space as a single big chunk */ + chunk_record(pool, + &pool->chunks_szad_mmap, &pool->chunks_ad_mmap, + usable_addr, usable_size, zeroed); + + pool->ctl_initialized = false; + + return pool; +} + +void +je_pool_delete(pool_t *pool) +{ + unsigned pool_id = pool->pool_id; + + /* Remove pool from global array */ + malloc_mutex_lock(&pools_lock); + pool_destroy(pool); + pools[pool_id] = NULL; + npools--; + + /* + * TODO: Destroy mutex + * base_mtx + */ + + pools_shared_data_destroy(); + + malloc_mutex_unlock(&pools_lock); +} + +/* + * add more memory to a pool + */ +size_t +je_pool_extend(pool_t *pool, void *addr, size_t size, int zeroed) +{ + void *usable_addr = addr; + size_t nodes_number = size/chunksize; + if (size < POOL_MINIMAL_SIZE) + return 0; + + /* preallocate the chunk tree nodes for the maximum possible number of chunks */ + nodes_number = base_node_prealloc(pool, nodes_number); + if (nodes_number > 0) { + /* + * If base allocation using existing chunks fails, then use the new + * chunk as a source for further base allocations. + */ + malloc_mutex_lock(&pool->base_mtx); + /* preinit base allocator in unused space, align the address to the cache line */ + pool->base_next_addr = (void *)CACHELINE_CEILING((uintptr_t)addr); + pool->base_past_addr = (void *)((uintptr_t)addr + size); + malloc_mutex_unlock(&pool->base_mtx); + + nodes_number = base_node_prealloc(pool, nodes_number); + assert(nodes_number == 0); + + /* pointer to the address of chunks, align the address to chunksize */ + usable_addr = (void*)CHUNK_CEILING((uintptr_t)pool->base_next_addr); + /* reduce end of base allocator up to chunks */ + pool->base_past_addr = usable_addr; + } + + + usable_addr = (void*)CHUNK_CEILING((uintptr_t)usable_addr); + + size_t usable_size = (size - (uintptr_t)(usable_addr - addr)) + & ~chunksize_mask; + + assert(usable_size > 0); + + chunk_record(pool, + &pool->chunks_szad_mmap, &pool->chunks_ad_mmap, + usable_addr, usable_size, zeroed); + + return usable_size; } static void * -imallocx_prof_sample(size_t usize, size_t alignment, bool zero, bool try_tcache, - arena_t *arena, prof_thr_cnt_t *cnt) +pool_ialloc_prof_sample(pool_t *pool, size_t usize, prof_thr_cnt_t *cnt, + void *(*ialloc)(pool_t *, size_t)) { void *p; if (cnt == NULL) return (NULL); - if (prof_promote && usize <= SMALL_MAXCLASS) { - size_t usize_promoted = (alignment == 0) ? - s2u(SMALL_MAXCLASS+1) : sa2u(SMALL_MAXCLASS+1, alignment); - assert(usize_promoted != 0); - p = imallocx(usize_promoted, alignment, zero, try_tcache, - arena); + if (usize <= SMALL_MAXCLASS) { + p = ialloc(pool, SMALL_MAXCLASS+1); if (p == NULL) return (NULL); arena_prof_promoted(p, usize); } else - p = imallocx(usize, alignment, zero, try_tcache, arena); + p = ialloc(pool, usize); return (p); } JEMALLOC_ALWAYS_INLINE_C void * -imallocx_prof(size_t usize, size_t alignment, bool zero, bool try_tcache, - arena_t *arena, prof_thr_cnt_t *cnt) +pool_ialloc_prof(pool_t *pool, size_t usize, + void *(*ialloc)(pool_t *, size_t)) { void *p; + prof_thr_cnt_t *cnt; - if ((uintptr_t)cnt != (uintptr_t)1U) { - p = imallocx_prof_sample(usize, alignment, zero, try_tcache, - arena, cnt); - } else - p = imallocx(usize, alignment, zero, try_tcache, arena); + PROF_ALLOC_PREP(usize, cnt); + if ((uintptr_t)cnt != (uintptr_t)1U) + p = pool_ialloc_prof_sample(pool, usize, cnt, ialloc); + else + p = ialloc(pool, usize); if (p == NULL) return (NULL); prof_malloc(p, usize, cnt); @@ -1428,39 +1625,480 @@ imallocx_prof(size_t usize, size_t alignment, bool zero, bool try_tcache, return (p); } -void * -je_mallocx(size_t size, int flags) +JEMALLOC_ALWAYS_INLINE_C void * +pool_imalloc_body(pool_t *pool, size_t size, size_t *usize) { - void *p; - size_t usize; - size_t alignment = (ZU(1) << (flags & MALLOCX_LG_ALIGN_MASK) - & (SIZE_T_MAX-1)); - bool zero = flags & MALLOCX_ZERO; - unsigned arena_ind = ((unsigned)(flags >> 8)) - 1; - arena_t *arena; - bool try_tcache; - - assert(size != 0); if (malloc_init()) - goto label_oom; + return (NULL); - if (arena_ind != UINT_MAX) { - arena = arenas[arena_ind]; - try_tcache = false; - } else { - arena = NULL; - try_tcache = true; + if (config_prof && opt_prof) { + *usize = s2u(size); + return (pool_ialloc_prof(pool, *usize, pool_imalloc)); } - usize = (alignment == 0) ? s2u(size) : sa2u(size, alignment); - assert(usize != 0); + if (config_stats || (config_valgrind && in_valgrind)) + *usize = s2u(size); + return (pool_imalloc(pool, size)); +} - if (config_prof && opt_prof) { - prof_thr_cnt_t *cnt; +void * +je_pool_malloc(pool_t *pool, size_t size) +{ + void *ret; + size_t usize JEMALLOC_CC_SILENCE_INIT(0); - PROF_ALLOC_PREP(1, usize, cnt); - p = imallocx_prof(usize, alignment, zero, try_tcache, arena, + if (size == 0) + size = 1; + + ret = pool_imalloc_body(pool, size, &usize); + if (ret == NULL) { + if (config_xmalloc && opt_xmalloc) { + malloc_write("<jemalloc>: Error in pool_malloc(): " + "out of memory\n"); + abort(); + } + set_errno(ENOMEM); + } + if (config_stats && ret != NULL) { + assert(usize == isalloc(ret, config_prof)); + thread_allocated_tsd_get()->allocated += usize; + } + UTRACE(0, size, ret); + JEMALLOC_VALGRIND_MALLOC(ret != NULL, ret, usize, false); + return (ret); +} + +void * +je_pool_calloc(pool_t *pool, size_t num, size_t size) +{ + void *ret; + size_t usize JEMALLOC_CC_SILENCE_INIT(0); + size_t num_size; + + num_size = num * size; + if (num_size == 0) { + if (num == 0 || size == 0) + num_size = 1; + else { + ret = NULL; + goto label_return; + } + + } else if (((num | size) & (SIZE_T_MAX << (sizeof(size_t) << 2))) + && (num_size / size != num)) { + ret = NULL; + goto label_return; + } + + if (config_prof && opt_prof) { + usize = s2u(num_size); + ret = pool_ialloc_prof(pool, usize, pool_icalloc); + } else { + if (config_stats || (config_valgrind && in_valgrind)) + usize = s2u(num_size); + ret = pool_icalloc(pool, num_size); + } + +label_return: + if (ret == NULL) { + if (config_xmalloc && opt_xmalloc) { + malloc_write("<jemalloc>: Error in pool_calloc(): " + "out of memory\n"); + abort(); + } + set_errno(ENOMEM); + } + if (config_stats && ret != NULL) { + assert(usize == isalloc(ret, config_prof)); + thread_allocated_tsd_get()->allocated += usize; + } + UTRACE(0, num_size, ret); + JEMALLOC_VALGRIND_MALLOC(ret != NULL, ret, usize, true); + return (ret); +} + +static void * +pool_irealloc_prof_sample(pool_t *pool, void *oldptr, size_t usize, + prof_thr_cnt_t *cnt) +{ + void *p; + + if (cnt == NULL) + return (NULL); + if (usize <= SMALL_MAXCLASS) { + p = pool_iralloc(pool, oldptr, SMALL_MAXCLASS+1, 0, 0, false); + if (p == NULL) + return (NULL); + arena_prof_promoted(p, usize); + } else + p = pool_iralloc(pool, oldptr, usize, 0, 0, false); + + return (p); +} + +JEMALLOC_ALWAYS_INLINE_C void * +pool_irealloc_prof(pool_t *pool, void *oldptr, size_t old_usize, + size_t usize, prof_thr_cnt_t *cnt) +{ + void *p; + prof_ctx_t *old_ctx; + + old_ctx = prof_ctx_get(oldptr); + if ((uintptr_t)cnt != (uintptr_t)1U) + p = pool_irealloc_prof_sample(pool, oldptr, usize, cnt); + else + p = pool_iralloc(pool, oldptr, usize, 0, 0, false); + if (p == NULL) + return (NULL); + prof_realloc(p, usize, cnt, old_usize, old_ctx); + + return (p); +} + +JEMALLOC_INLINE_C void +pool_ifree(pool_t *pool, void *ptr) +{ + size_t usize; + UNUSED size_t rzsize JEMALLOC_CC_SILENCE_INIT(0); + arena_chunk_t *chunk; + + assert(ptr != NULL); + assert(malloc_initialized || IS_INITIALIZER); + + if (config_prof && opt_prof) { + usize = isalloc(ptr, config_prof); + prof_free(ptr, usize); + } else if (config_stats || config_valgrind) + usize = isalloc(ptr, config_prof); + if (config_stats) + thread_allocated_tsd_get()->deallocated += usize; + if (config_valgrind && in_valgrind) + rzsize = p2rz(ptr); + + chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); + if (chunk != ptr) + arena_dalloc(chunk, ptr, false); + else + huge_dalloc(pool, ptr); + + JEMALLOC_VALGRIND_FREE(ptr, rzsize); +} + +void * +je_pool_ralloc(pool_t *pool, void *ptr, size_t size) +{ + void *ret; + size_t usize JEMALLOC_CC_SILENCE_INIT(0); + size_t old_usize = 0; + UNUSED size_t old_rzsize JEMALLOC_CC_SILENCE_INIT(0); + + if (size == 0) { + if (ptr != NULL) { + /* realloc(ptr, 0) is equivalent to free(ptr). */ + UTRACE(ptr, 0, 0); + pool_ifree(pool, ptr); + return (NULL); + } + size = 1; + } + + if (ptr != NULL) { + assert(malloc_initialized || IS_INITIALIZER); + malloc_init(); + + if ((config_prof && opt_prof) || config_stats || + (config_valgrind && in_valgrind)) + old_usize = isalloc(ptr, config_prof); + if (config_valgrind && in_valgrind) + old_rzsize = config_prof ? p2rz(ptr) : u2rz(old_usize); + + if (config_prof && opt_prof) { + prof_thr_cnt_t *cnt; + + usize = s2u(size); + PROF_ALLOC_PREP(usize, cnt); + ret = pool_irealloc_prof(pool, ptr, old_usize, + usize, cnt); + } else { + if (config_stats || (config_valgrind && in_valgrind)) + usize = s2u(size); + ret = pool_iralloc(pool, ptr, size, 0, 0, false); + } + } else { + /* realloc(NULL, size) is equivalent to malloc(size). */ + ret = pool_imalloc_body(pool, size, &usize); + } + + if (ret == NULL) { + if (config_xmalloc && opt_xmalloc) { + malloc_write("<jemalloc>: Error in pool_ralloc(): " + "out of memory\n"); + abort(); + } + set_errno(ENOMEM); + } + if (config_stats && ret != NULL) { + thread_allocated_t *ta; + assert(usize == isalloc(ret, config_prof)); + ta = thread_allocated_tsd_get(); + ta->allocated += usize; + ta->deallocated += old_usize; + } + UTRACE(ptr, size, ret); + JEMALLOC_VALGRIND_REALLOC(true, ret, usize, true, ptr, old_usize, + old_rzsize, true, false); + return (ret); +} + +static void * +pool_imemalign_prof_sample(pool_t *pool, size_t alignment, size_t usize, + prof_thr_cnt_t *cnt) +{ + void *p; + + if (cnt == NULL) + return (NULL); + if (usize <= SMALL_MAXCLASS) { + assert(sa2u(SMALL_MAXCLASS+1, alignment) != 0); + p = pool_ipalloc(pool, sa2u(SMALL_MAXCLASS+1, alignment), + alignment, false); + if (p == NULL) + return (NULL); + arena_prof_promoted(p, usize); + } else + p = pool_ipalloc(pool, usize, alignment, false); + + return (p); +} + +JEMALLOC_ALWAYS_INLINE_C void * +pool_imemalign_prof(pool_t *pool, size_t alignment, size_t usize, + prof_thr_cnt_t *cnt) +{ + void *p; + + if ((uintptr_t)cnt != (uintptr_t)1U) + p = pool_imemalign_prof_sample(pool, alignment, usize, cnt); + else + p = pool_ipalloc(pool, usize, alignment, false); + if (p == NULL) + return (NULL); + prof_malloc(p, usize, cnt); + + return (p); +} + +JEMALLOC_ATTR(nonnull(1)) +static int +pool_imemalign(pool_t *pool, void **memptr, size_t alignment, size_t size, + size_t min_alignment) +{ + int ret; + size_t usize; + void *result; + + assert(min_alignment != 0); + + if (malloc_init()) { + result = NULL; + goto label_oom; + } else { + if (size == 0) + size = 1; + + /* Make sure that alignment is a large enough power of 2. */ + if (((alignment - 1) & alignment) != 0 + || (alignment < min_alignment)) { + if (config_xmalloc && opt_xmalloc) { + malloc_write("<jemalloc>: Error allocating pool" + " aligned memory: invalid alignment\n"); + abort(); + } + result = NULL; + ret = EINVAL; + goto label_return; + } + + usize = sa2u(size, alignment); + if (usize == 0) { + result = NULL; + goto label_oom; + } + + if (config_prof && opt_prof) { + prof_thr_cnt_t *cnt; + + PROF_ALLOC_PREP(usize, cnt); + result = pool_imemalign_prof(pool, alignment, + usize, cnt); + } else + result = pool_ipalloc(pool, usize, alignment, false); + if (result == NULL) + goto label_oom; + } + + *memptr = result; + ret = 0; +label_return: + if (config_stats && result != NULL) { + assert(usize == isalloc(result, config_prof)); + thread_allocated_tsd_get()->allocated += usize; + } + UTRACE(0, size, result); + return (ret); +label_oom: + assert(result == NULL); + if (config_xmalloc && opt_xmalloc) { + malloc_write("<jemalloc>: Error allocating pool " + "aligned memory: out of memory\n"); + abort(); + } + ret = ENOMEM; + goto label_return; +} + +void * +je_pool_aligned_alloc(pool_t *pool, size_t alignment, size_t size) +{ + void *ret; + int err; + + if ((err = pool_imemalign(pool, &ret, alignment, size, 1)) != 0) { + ret = NULL; + set_errno(err); + } + JEMALLOC_VALGRIND_MALLOC(err == 0, ret, isalloc(ret, config_prof), + false); + return (ret); +} + +void +je_pool_free(pool_t *pool, void *ptr) +{ + UTRACE(ptr, 0, 0); + if (ptr != NULL) + pool_ifree(pool, ptr); +} + +void +je_pool_malloc_stats_print(pool_t *pool, + void (*write_cb)(void *, const char *), + void *cbopaque, const char *opts) +{ + + stats_print(pool, write_cb, cbopaque, opts); +} + +void +je_pool_set_alloc_funcs(void *(*malloc_func)(size_t), + void (*free_func)(void *)) +{ + if (malloc_func != NULL && free_func != NULL) { + malloc_mutex_lock(&pool_base_lock); + if (pools[0] == NULL) { + je_base_malloc = malloc_func; + je_base_free = free_func; + } + malloc_mutex_unlock(&pool_base_lock); + } +} + + +JEMALLOC_ALWAYS_INLINE_C void * +imallocx(size_t usize, size_t alignment, bool zero, bool try_tcache, + arena_t *arena) +{ + + assert(usize == ((alignment == 0) ? s2u(usize) : sa2u(usize, + alignment))); + + if (alignment != 0) + return (ipalloct(usize, alignment, zero, try_tcache, arena)); + else if (zero) + return (icalloct(usize, try_tcache, arena)); + else + return (imalloct(usize, try_tcache, arena)); +} + +static void * +imallocx_prof_sample(size_t usize, size_t alignment, bool zero, bool try_tcache, + arena_t *arena, prof_thr_cnt_t *cnt) +{ + void *p; + + if (cnt == NULL) + return (NULL); + if (usize <= SMALL_MAXCLASS) { + size_t usize_promoted = (alignment == 0) ? + s2u(SMALL_MAXCLASS+1) : sa2u(SMALL_MAXCLASS+1, alignment); + assert(usize_promoted != 0); + p = imallocx(usize_promoted, alignment, zero, try_tcache, + arena); + if (p == NULL) + return (NULL); + arena_prof_promoted(p, usize); + } else + p = imallocx(usize, alignment, zero, try_tcache, arena); + + return (p); +} + +JEMALLOC_ALWAYS_INLINE_C void * +imallocx_prof(size_t usize, size_t alignment, bool zero, bool try_tcache, + arena_t *arena, prof_thr_cnt_t *cnt) +{ + void *p; + + if ((uintptr_t)cnt != (uintptr_t)1U) { + p = imallocx_prof_sample(usize, alignment, zero, try_tcache, + arena, cnt); + } else + p = imallocx(usize, alignment, zero, try_tcache, arena); + if (p == NULL) + return (NULL); + prof_malloc(p, usize, cnt); + + return (p); +} + +void * +je_mallocx(size_t size, int flags) +{ + void *p; + size_t usize; + size_t alignment = (ZU(1) << (flags & MALLOCX_LG_ALIGN_MASK) + & (SIZE_T_MAX-1)); + bool zero = flags & MALLOCX_ZERO; + unsigned arena_ind = ((unsigned)(flags >> 8)) - 1; + unsigned pool_id = 0; // TODO add another flag + pool_t *pool = pools[pool_id]; + arena_t dummy_arena; + DUMMY_ARENA_INITIALIZE(dummy_arena, pool); + arena_t *arena; + bool try_tcache; + + assert(size != 0); + + if (malloc_init_base_pool()) + goto label_oom; + + if (arena_ind != UINT_MAX) { + arena = pool->arenas[arena_ind]; + try_tcache = false; + } else { + arena = &dummy_arena; + try_tcache = true; + } + + usize = (alignment == 0) ? s2u(size) : sa2u(size, alignment); + assert(usize != 0); + + if (config_prof && opt_prof) { + prof_thr_cnt_t *cnt; + + PROF_ALLOC_PREP(usize, cnt); + p = imallocx_prof(usize, alignment, zero, try_tcache, arena, cnt); } else p = imallocx(usize, alignment, zero, try_tcache, arena); @@ -1492,7 +2130,7 @@ irallocx_prof_sample(void *oldptr, size_t size, size_t alignment, size_t usize, if (cnt == NULL) return (NULL); - if (prof_promote && usize <= SMALL_MAXCLASS) { + if (usize <= SMALL_MAXCLASS) { p = iralloct(oldptr, SMALL_MAXCLASS+1, (SMALL_MAXCLASS+1 >= size) ? 0 : size - (SMALL_MAXCLASS+1), alignment, zero, try_tcache_alloc, try_tcache_dalloc, arena); @@ -1552,12 +2190,17 @@ je_rallocx(void *ptr, size_t size, int flags) & (SIZE_T_MAX-1)); bool zero = flags & MALLOCX_ZERO; unsigned arena_ind = ((unsigned)(flags >> 8)) - 1; + unsigned pool_id = 0; // TODO add another flag + pool_t *pool = pools[pool_id]; + arena_t dummy_arena; + DUMMY_ARENA_INITIALIZE(dummy_arena, pool); bool try_tcache_alloc, try_tcache_dalloc; arena_t *arena; assert(ptr != NULL); assert(size != 0); assert(malloc_initialized || IS_INITIALIZER); + assert(pools[0] != NULL); malloc_thread_init(); if (arena_ind != UINT_MAX) { @@ -1565,18 +2208,18 @@ je_rallocx(void *ptr, size_t size, int flags) try_tcache_alloc = false; chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); try_tcache_dalloc = (chunk == ptr || chunk->arena != - arenas[arena_ind]); - arena = arenas[arena_ind]; + pool->arenas[arena_ind]); + arena = pool->arenas[arena_ind]; } else { try_tcache_alloc = true; try_tcache_dalloc = true; - arena = NULL; + arena = &dummy_arena; } if ((config_prof && opt_prof) || config_stats || - (config_valgrind && opt_valgrind)) + (config_valgrind && in_valgrind)) old_usize = isalloc(ptr, config_prof); - if (config_valgrind && opt_valgrind) + if (config_valgrind && in_valgrind) old_rzsize = u2rz(old_usize); if (config_prof && opt_prof) { @@ -1584,7 +2227,7 @@ je_rallocx(void *ptr, size_t size, int flags) usize = (alignment == 0) ? s2u(size) : sa2u(size, alignment); assert(usize != 0); - PROF_ALLOC_PREP(1, usize, cnt); + PROF_ALLOC_PREP(usize, cnt); p = irallocx_prof(ptr, old_usize, size, alignment, &usize, zero, try_tcache_alloc, try_tcache_dalloc, arena, cnt); if (p == NULL) @@ -1594,7 +2237,7 @@ je_rallocx(void *ptr, size_t size, int flags) try_tcache_dalloc, arena); if (p == NULL) goto label_oom; - if (config_stats || (config_valgrind && opt_valgrind)) + if (config_stats || (config_valgrind && in_valgrind)) usize = isalloc(p, config_prof); } @@ -1605,7 +2248,8 @@ je_rallocx(void *ptr, size_t size, int flags) ta->deallocated += old_usize; } UTRACE(ptr, size, p); - JEMALLOC_VALGRIND_REALLOC(p, usize, ptr, old_usize, old_rzsize, zero); + JEMALLOC_VALGRIND_REALLOC(true, p, usize, false, ptr, old_usize, + old_rzsize, false, zero); return (p); label_oom: if (config_xmalloc && opt_xmalloc) { @@ -1639,8 +2283,8 @@ ixallocx_prof_sample(void *ptr, size_t old_usize, size_t size, size_t extra, if (cnt == NULL) return (old_usize); /* Use minimum usize to determine whether promotion may happen. */ - if (prof_promote && ((alignment == 0) ? s2u(size) : sa2u(size, - alignment)) <= SMALL_MAXCLASS) { + if (((alignment == 0) ? s2u(size) : sa2u(size, alignment)) <= + SMALL_MAXCLASS) { if (ixalloc(ptr, SMALL_MAXCLASS+1, (SMALL_MAXCLASS+1 >= size+extra) ? 0 : size+extra - (SMALL_MAXCLASS+1), alignment, zero)) @@ -1688,21 +2332,26 @@ je_xallocx(void *ptr, size_t size, size_t extra, int flags) & (SIZE_T_MAX-1)); bool zero = flags & MALLOCX_ZERO; unsigned arena_ind = ((unsigned)(flags >> 8)) - 1; + unsigned pool_id = 0; // TODO add another flag + pool_t *pool = pools[pool_id]; + arena_t dummy_arena; + DUMMY_ARENA_INITIALIZE(dummy_arena, pool); arena_t *arena; assert(ptr != NULL); assert(size != 0); assert(SIZE_T_MAX - size >= extra); assert(malloc_initialized || IS_INITIALIZER); + assert(pools[0] != NULL); malloc_thread_init(); if (arena_ind != UINT_MAX) - arena = arenas[arena_ind]; + arena = pool->arenas[arena_ind]; else - arena = NULL; + arena = &dummy_arena; old_usize = isalloc(ptr, config_prof); - if (config_valgrind && opt_valgrind) + if (config_valgrind && in_valgrind) old_rzsize = u2rz(old_usize); if (config_prof && opt_prof) { @@ -1716,7 +2365,7 @@ je_xallocx(void *ptr, size_t size, size_t extra, int flags) */ size_t max_usize = (alignment == 0) ? s2u(size+extra) : sa2u(size+extra, alignment); - PROF_ALLOC_PREP(1, max_usize, cnt); + PROF_ALLOC_PREP(max_usize, cnt); usize = ixallocx_prof(ptr, old_usize, size, extra, alignment, max_usize, zero, arena, cnt); } else { @@ -1732,7 +2381,8 @@ je_xallocx(void *ptr, size_t size, size_t extra, int flags) ta->allocated += usize; ta->deallocated += old_usize; } - JEMALLOC_VALGRIND_REALLOC(ptr, usize, ptr, old_usize, old_rzsize, zero); + JEMALLOC_VALGRIND_REALLOC(false, ptr, usize, false, ptr, old_usize, + old_rzsize, false, zero); label_not_resized: UTRACE(ptr, size, ptr); return (usize); @@ -1744,6 +2394,7 @@ je_sallocx(const void *ptr, int flags) size_t usize; assert(malloc_initialized || IS_INITIALIZER); + assert(pools[0] != NULL); malloc_thread_init(); if (config_ivsalloc) @@ -1762,15 +2413,18 @@ je_dallocx(void *ptr, int flags) size_t usize; UNUSED size_t rzsize JEMALLOC_CC_SILENCE_INIT(0); unsigned arena_ind = ((unsigned)(flags >> 8)) - 1; + unsigned pool_id = 0; // TODO add another flag + pool_t *pool = pools[pool_id]; bool try_tcache; assert(ptr != NULL); assert(malloc_initialized || IS_INITIALIZER); + assert(pools[0] != NULL); if (arena_ind != UINT_MAX) { arena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); try_tcache = (chunk == ptr || chunk->arena != - arenas[arena_ind]); + pool->arenas[arena_ind]); } else try_tcache = true; @@ -1784,7 +2438,7 @@ je_dallocx(void *ptr, int flags) } if (config_stats) thread_allocated_tsd_get()->deallocated += usize; - if (config_valgrind && opt_valgrind) + if (config_valgrind && in_valgrind) rzsize = p2rz(ptr); iqalloct(ptr, try_tcache); JEMALLOC_VALGRIND_FREE(ptr, rzsize); @@ -1799,7 +2453,7 @@ je_nallocx(size_t size, int flags) assert(size != 0); - if (malloc_init()) + if (malloc_init_base_pool()) return (0); usize = (alignment == 0) ? s2u(size) : sa2u(size, alignment); @@ -1812,7 +2466,7 @@ je_mallctl(const char *name, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { - if (malloc_init()) + if (malloc_init_base_pool()) return (EAGAIN); return (ctl_byname(name, oldp, oldlenp, newp, newlen)); @@ -1822,7 +2476,7 @@ int je_mallctlnametomib(const char *name, size_t *mibp, size_t *miblenp) { - if (malloc_init()) + if (malloc_init_base_pool()) return (EAGAIN); return (ctl_nametomib(name, mibp, miblenp)); @@ -1833,7 +2487,7 @@ je_mallctlbymib(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { - if (malloc_init()) + if (malloc_init_base_pool()) return (EAGAIN); return (ctl_bymib(mib, miblen, oldp, oldlenp, newp, newlen)); @@ -1843,8 +2497,8 @@ void je_malloc_stats_print(void (*write_cb)(void *, const char *), void *cbopaque, const char *opts) { - - stats_print(write_cb, cbopaque, opts); + pool_t *base_pool = pools[0]; + stats_print(base_pool, write_cb, cbopaque, opts); } size_t @@ -1853,6 +2507,7 @@ je_malloc_usable_size(JEMALLOC_USABLE_SIZE_CONST void *ptr) size_t ret; assert(malloc_initialized || IS_INITIALIZER); + assert(pools[0] != NULL); malloc_thread_init(); if (config_ivsalloc) @@ -1867,91 +2522,6 @@ je_malloc_usable_size(JEMALLOC_USABLE_SIZE_CONST void *ptr) * End non-standard functions. */ /******************************************************************************/ -/* - * Begin experimental functions. - */ -#ifdef JEMALLOC_EXPERIMENTAL - -int -je_allocm(void **ptr, size_t *rsize, size_t size, int flags) -{ - void *p; - - assert(ptr != NULL); - - p = je_mallocx(size, flags); - if (p == NULL) - return (ALLOCM_ERR_OOM); - if (rsize != NULL) - *rsize = isalloc(p, config_prof); - *ptr = p; - return (ALLOCM_SUCCESS); -} - -int -je_rallocm(void **ptr, size_t *rsize, size_t size, size_t extra, int flags) -{ - int ret; - bool no_move = flags & ALLOCM_NO_MOVE; - - assert(ptr != NULL); - assert(*ptr != NULL); - assert(size != 0); - assert(SIZE_T_MAX - size >= extra); - - if (no_move) { - size_t usize = je_xallocx(*ptr, size, extra, flags); - ret = (usize >= size) ? ALLOCM_SUCCESS : ALLOCM_ERR_NOT_MOVED; - if (rsize != NULL) - *rsize = usize; - } else { - void *p = je_rallocx(*ptr, size+extra, flags); - if (p != NULL) { - *ptr = p; - ret = ALLOCM_SUCCESS; - } else - ret = ALLOCM_ERR_OOM; - if (rsize != NULL) - *rsize = isalloc(*ptr, config_prof); - } - return (ret); -} - -int -je_sallocm(const void *ptr, size_t *rsize, int flags) -{ - - assert(rsize != NULL); - *rsize = je_sallocx(ptr, flags); - return (ALLOCM_SUCCESS); -} - -int -je_dallocm(void *ptr, int flags) -{ - - je_dallocx(ptr, flags); - return (ALLOCM_SUCCESS); -} - -int -je_nallocm(size_t *rsize, size_t size, int flags) -{ - size_t usize; - - usize = je_nallocx(size, flags); - if (usize == 0) - return (ALLOCM_ERR_OOM); - if (rsize != NULL) - *rsize = usize; - return (ALLOCM_SUCCESS); -} - -#endif -/* - * End experimental functions. - */ -/******************************************************************************/ /* * The following functions are used by threading libraries for protection of * malloc during fork(). @@ -1978,6 +2548,16 @@ jemalloc_constructor(void) malloc_init(); } + +#define FOREACH_POOL(func) \ +do { \ + unsigned i; \ + for (i = 0; i < POOLS_MAX; i++) { \ + if (pools[i]) \ + (func)(pools[i]); \ + } \ +} while(0) + #ifndef JEMALLOC_MUTEX_INIT_CB void jemalloc_prefork(void) @@ -1986,7 +2566,8 @@ JEMALLOC_EXPORT void _malloc_prefork(void) #endif { - unsigned i; + unsigned i, j; + pool_t *pool; #ifdef JEMALLOC_MUTEX_INIT_CB if (malloc_initialized == false) @@ -1997,14 +2578,22 @@ _malloc_prefork(void) /* Acquire all mutexes in a safe order. */ ctl_prefork(); prof_prefork(); - malloc_mutex_prefork(&arenas_lock); - for (i = 0; i < narenas_total; i++) { - if (arenas[i] != NULL) - arena_prefork(arenas[i]); + pool_prefork(); + for (i = 0; i < POOLS_MAX; i++) { + pool = pools[i]; + if (pool != NULL) { + for (j = 0; j < pool->narenas_total; j++) { + if (pool->arenas[j] != NULL) + arena_prefork(pool->arenas[j]); + } + } } - chunk_prefork(); - base_prefork(); - huge_prefork(); + + FOREACH_POOL(chunk_prefork); + + FOREACH_POOL(base_prefork); + + FOREACH_POOL(huge_prefork); } #ifndef JEMALLOC_MUTEX_INIT_CB @@ -2015,7 +2604,8 @@ JEMALLOC_EXPORT void _malloc_postfork(void) #endif { - unsigned i; + unsigned i, j; + pool_t *pool; #ifdef JEMALLOC_MUTEX_INIT_CB if (malloc_initialized == false) @@ -2024,14 +2614,22 @@ _malloc_postfork(void) assert(malloc_initialized); /* Release all mutexes, now that fork() has completed. */ - huge_postfork_parent(); - base_postfork_parent(); - chunk_postfork_parent(); - for (i = 0; i < narenas_total; i++) { - if (arenas[i] != NULL) - arena_postfork_parent(arenas[i]); - } - malloc_mutex_postfork_parent(&arenas_lock); + FOREACH_POOL(huge_postfork_parent); + + FOREACH_POOL(base_postfork_parent); + + FOREACH_POOL(chunk_postfork_parent); + + for (i = 0; i < POOLS_MAX; i++) { + pool = pools[i]; + if (pool != NULL) { + for (j = 0; j < pool->narenas_total; j++) { + if (pool->arenas[j] != NULL) + arena_postfork_parent(pool->arenas[j]); + } + } + } + pool_postfork_parent(); prof_postfork_parent(); ctl_postfork_parent(); } @@ -2039,19 +2637,28 @@ _malloc_postfork(void) void jemalloc_postfork_child(void) { - unsigned i; + unsigned i, j; + pool_t *pool; assert(malloc_initialized); /* Release all mutexes, now that fork() has completed. */ - huge_postfork_child(); - base_postfork_child(); - chunk_postfork_child(); - for (i = 0; i < narenas_total; i++) { - if (arenas[i] != NULL) - arena_postfork_child(arenas[i]); - } - malloc_mutex_postfork_child(&arenas_lock); + FOREACH_POOL(huge_postfork_child); + + FOREACH_POOL(base_postfork_child); + + FOREACH_POOL(chunk_postfork_child); + + for (i = 0; i < POOLS_MAX; i++) { + pool = pools[i]; + if (pool != NULL) { + for (j = 0; j < pool->narenas_total; j++) { + if (pool->arenas[j] != NULL) + arena_postfork_child(pool->arenas[j]); + } + } + } + pool_postfork_child(); prof_postfork_child(); ctl_postfork_child(); } @@ -2066,17 +2673,18 @@ jemalloc_postfork_child(void) static void * a0alloc(size_t size, bool zero) { + pool_t *base_pool = pools[0]; - if (malloc_init()) + if (malloc_init_base_pool()) return (NULL); if (size == 0) size = 1; if (size <= arena_maxclass) - return (arena_malloc(arenas[0], size, zero, false)); + return (arena_malloc(base_pool->arenas[0], size, zero, false)); else - return (huge_malloc(size, zero, huge_dss_prec_get(arenas[0]))); + return (huge_malloc(NULL, size, zero)); } void * @@ -2096,6 +2704,7 @@ a0calloc(size_t num, size_t size) void a0free(void *ptr) { + pool_t *base_pool = pools[0]; arena_chunk_t *chunk; if (ptr == NULL) @@ -2103,9 +2712,9 @@ a0free(void *ptr) chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); if (chunk != ptr) - arena_dalloc(chunk->arena, chunk, ptr, false); + arena_dalloc(chunk, ptr, false); else - huge_dalloc(ptr, true); + huge_dalloc(base_pool, ptr); } /******************************************************************************/ diff --git a/src/jemalloc/src/pool.c b/src/jemalloc/src/pool.c new file mode 100644 index 0000000000000000000000000000000000000000..f3cd79a6ef706ccc9822226972b6e995696e6a42 --- /dev/null +++ b/src/jemalloc/src/pool.c @@ -0,0 +1,99 @@ +#define JEMALLOC_POOL_C_ +#include "jemalloc/internal/jemalloc_internal.h" + +malloc_mutex_t pool_base_lock; +malloc_mutex_t pools_lock; + +/* Initialize pool and create its base arena. */ +bool pool_new(pool_t *pool, unsigned pool_id) +{ + pool->pool_id = pool_id; + + if (malloc_mutex_init(&pool->arenas_lock)) { + return (true); + } + + if (base_boot(pool)) { + return (true); + } + + if (chunk_boot(pool)) { + return (true); + } + + if (huge_boot(pool)) { + return (true); + } + + pool->stats_cactive = 0; + pool->ctl_stats_active = 0; + pool->ctl_stats_allocated = 0; + pool->ctl_stats_mapped = 0; + + pool->narenas_auto = opt_narenas; + /* + * Make sure that the arenas array can be allocated. In practice, this + * limit is enough to allow the allocator to function, but the ctl + * machinery will fail to allocate memory at far lower limits. + */ + if (pool->narenas_auto > chunksize / sizeof(arena_t *)) { + pool->narenas_auto = chunksize / sizeof(arena_t *); + malloc_printf("<jemalloc>: Reducing narenas to limit (%d)\n", + pool->narenas_auto); + } + pool->narenas_total = pool->narenas_auto; + + /* Allocate and initialize arenas. */ + pool->arenas = (arena_t **)base_calloc(pool, sizeof(arena_t *), + pool->narenas_total); + + if (pool->arenas == NULL) { + return (true); + } + + arenas_extend(pool, 0); + + return false; +} + +/* Release the arenas associated with a pool. */ +void pool_destroy(pool_t *pool) +{ + int i; + for (i = 0; i < pool->narenas_total; ++i) { + if (pool->arenas[i] != NULL) { + arena_purge_all(pool->arenas[i]); + } + } +} + +bool pool_boot() +{ + if (malloc_mutex_init(&pools_lock)) { + return (true); + } + + if (malloc_mutex_init(&pool_base_lock)) { + return (true); + } + + return (false); +} + +void pool_prefork() +{ + malloc_mutex_prefork(&pools_lock); + malloc_mutex_prefork(&pool_base_lock); +} + +void pool_postfork_parent() +{ + malloc_mutex_postfork_parent(&pools_lock); + malloc_mutex_prefork(&pool_base_lock); +} + +void pool_postfork_child() +{ + malloc_mutex_postfork_child(&pools_lock); + malloc_mutex_prefork(&pool_base_lock); +} \ No newline at end of file diff --git a/src/jemalloc/src/prof.c b/src/jemalloc/src/prof.c index 7722b7b4373940feaccbc1ab7c15fc8da16fe483..1dd9b6117761a041d300476973a7037cf411d7b3 100644 --- a/src/jemalloc/src/prof.c +++ b/src/jemalloc/src/prof.c @@ -32,7 +32,6 @@ char opt_prof_prefix[ 1]; uint64_t prof_interval = 0; -bool prof_promote; /* * Table of mutexes that are shared among ctx's. These are leaf locks, so @@ -159,38 +158,18 @@ prof_leave(prof_tdata_t *prof_tdata) #ifdef JEMALLOC_PROF_LIBUNWIND void -prof_backtrace(prof_bt_t *bt, unsigned nignore) +prof_backtrace(prof_bt_t *bt) { - unw_context_t uc; - unw_cursor_t cursor; - unsigned i; - int err; + int nframes; cassert(config_prof); assert(bt->len == 0); assert(bt->vec != NULL); - unw_getcontext(&uc); - unw_init_local(&cursor, &uc); - - /* Throw away (nignore+1) stack frames, if that many exist. */ - for (i = 0; i < nignore + 1; i++) { - err = unw_step(&cursor); - if (err <= 0) - return; - } - - /* - * Iterate over stack frames until there are no more, or until no space - * remains in bt. - */ - for (i = 0; i < PROF_BT_MAX; i++) { - unw_get_reg(&cursor, UNW_REG_IP, (unw_word_t *)&bt->vec[i]); - bt->len++; - err = unw_step(&cursor); - if (err <= 0) - break; - } + nframes = unw_backtrace(bt->vec, PROF_BT_MAX); + if (nframes <= 0) + return; + bt->len = nframes; } #elif (defined(JEMALLOC_PROF_LIBGCC)) static _Unwind_Reason_Code @@ -206,25 +185,25 @@ static _Unwind_Reason_Code prof_unwind_callback(struct _Unwind_Context *context, void *arg) { prof_unwind_data_t *data = (prof_unwind_data_t *)arg; + void *ip; cassert(config_prof); - if (data->nignore > 0) - data->nignore--; - else { - data->bt->vec[data->bt->len] = (void *)_Unwind_GetIP(context); - data->bt->len++; - if (data->bt->len == data->max) - return (_URC_END_OF_STACK); - } + ip = (void *)_Unwind_GetIP(context); + if (ip == NULL) + return (_URC_END_OF_STACK); + data->bt->vec[data->bt->len] = ip; + data->bt->len++; + if (data->bt->len == data->max) + return (_URC_END_OF_STACK); return (_URC_NO_REASON); } void -prof_backtrace(prof_bt_t *bt, unsigned nignore) +prof_backtrace(prof_bt_t *bt) { - prof_unwind_data_t data = {bt, nignore, PROF_BT_MAX}; + prof_unwind_data_t data = {bt, PROF_BT_MAX}; cassert(config_prof); @@ -232,25 +211,22 @@ prof_backtrace(prof_bt_t *bt, unsigned nignore) } #elif (defined(JEMALLOC_PROF_GCC)) void -prof_backtrace(prof_bt_t *bt, unsigned nignore) +prof_backtrace(prof_bt_t *bt) { #define BT_FRAME(i) \ - if ((i) < nignore + PROF_BT_MAX) { \ + if ((i) < PROF_BT_MAX) { \ void *p; \ if (__builtin_frame_address(i) == 0) \ return; \ p = __builtin_return_address(i); \ if (p == NULL) \ return; \ - if (i >= nignore) { \ - bt->vec[(i) - nignore] = p; \ - bt->len = (i) - nignore + 1; \ - } \ + bt->vec[(i)] = p; \ + bt->len = (i) + 1; \ } else \ return; cassert(config_prof); - assert(nignore <= 3); BT_FRAME(0) BT_FRAME(1) @@ -392,16 +368,11 @@ prof_backtrace(prof_bt_t *bt, unsigned nignore) BT_FRAME(125) BT_FRAME(126) BT_FRAME(127) - - /* Extras to compensate for nignore. */ - BT_FRAME(128) - BT_FRAME(129) - BT_FRAME(130) #undef BT_FRAME } #else void -prof_backtrace(prof_bt_t *bt, unsigned nignore) +prof_backtrace(prof_bt_t *bt) { cassert(config_prof); @@ -646,6 +617,66 @@ prof_lookup(prof_bt_t *bt) return (ret.p); } + +void +prof_sample_threshold_update(prof_tdata_t *prof_tdata) +{ + /* + * The body of this function is compiled out unless heap profiling is + * enabled, so that it is possible to compile jemalloc with floating + * point support completely disabled. Avoiding floating point code is + * important on memory-constrained systems, but it also enables a + * workaround for versions of glibc that don't properly save/restore + * floating point registers during dynamic lazy symbol loading (which + * internally calls into whatever malloc implementation happens to be + * integrated into the application). Note that some compilers (e.g. + * gcc 4.8) may use floating point registers for fast memory moves, so + * jemalloc must be compiled with such optimizations disabled (e.g. + * -mno-sse) in order for the workaround to be complete. + */ +#ifdef JEMALLOC_PROF + uint64_t r; + double u; + + if (!config_prof) + return; + + if (prof_tdata == NULL) + prof_tdata = prof_tdata_get(false); + + if (opt_lg_prof_sample == 0) { + prof_tdata->bytes_until_sample = 0; + return; + } + + /* + * Compute sample threshold as a geometrically distributed random + * variable with mean (2^opt_lg_prof_sample). + * + * __ __ + * | log(u) | 1 + * prof_tdata->threshold = | -------- |, where p = ------------------- + * | log(1-p) | opt_lg_prof_sample + * 2 + * + * For more information on the math, see: + * + * Non-Uniform Random Variate Generation + * Luc Devroye + * Springer-Verlag, New York, 1986 + * pp 500 + * (http://luc.devroye.org/rnbookindex.html) + */ + prng64(r, 53, prof_tdata->prng_state, + UINT64_C(6364136223846793005), UINT64_C(1442695040888963407)); + u = (double)r * (1.0/9007199254740992.0L); + prof_tdata->bytes_until_sample = (uint64_t)(log(u) / + log(1.0 - (1.0 / (double)((uint64_t)1U << opt_lg_prof_sample)))) + + (uint64_t)1U; +#endif +} + + #ifdef JEMALLOC_JET size_t prof_bt_count(void) @@ -1062,7 +1093,7 @@ label_open_close_error: #define DUMP_FILENAME_BUFSIZE (PATH_MAX + 1) #define VSEQ_INVALID UINT64_C(0xffffffffffffffff) static void -prof_dump_filename(char *filename, char v, int64_t vseq) +prof_dump_filename(char *filename, char v, uint64_t vseq) { cassert(config_prof); @@ -1070,7 +1101,7 @@ prof_dump_filename(char *filename, char v, int64_t vseq) if (vseq != VSEQ_INVALID) { /* "<prefix>.<pid>.<seq>.v<vseq>.heap" */ malloc_snprintf(filename, DUMP_FILENAME_BUFSIZE, - "%s.%d.%"PRIu64".%c%"PRId64".heap", + "%s.%d.%"PRIu64".%c%"PRIu64".heap", opt_prof_prefix, (int)getpid(), prof_dump_seq, v, vseq); } else { /* "<prefix>.<pid>.<seq>.<v>.heap" */ @@ -1225,9 +1256,8 @@ prof_tdata_init(void) return (NULL); } - prof_tdata->prng_state = 0; - prof_tdata->threshold = 0; - prof_tdata->accum = 0; + prof_tdata->prng_state = (uint64_t)(uintptr_t)prof_tdata; + prof_sample_threshold_update(prof_tdata); prof_tdata->enq = false; prof_tdata->enq_idump = false; @@ -1300,8 +1330,8 @@ prof_boot1(void) cassert(config_prof); /* - * opt_prof and prof_promote must be in their final state before any - * arenas are initialized, so this function must be executed early. + * opt_prof must be in its final state before any arenas are + * initialized, so this function must be executed early. */ if (opt_prof_leak && opt_prof == false) { @@ -1317,14 +1347,11 @@ prof_boot1(void) opt_lg_prof_interval); } } - - prof_promote = (opt_prof && opt_lg_prof_sample > LG_PAGE); } bool prof_boot2(void) { - cassert(config_prof); if (opt_prof) { @@ -1351,8 +1378,7 @@ prof_boot2(void) if (opt_abort) abort(); } - - ctx_locks = (malloc_mutex_t *)base_alloc(PROF_NCTX_LOCKS * + ctx_locks = (malloc_mutex_t *)je_base_malloc(PROF_NCTX_LOCKS * sizeof(malloc_mutex_t)); if (ctx_locks == NULL) return (true); diff --git a/src/jemalloc/src/quarantine.c b/src/jemalloc/src/quarantine.c index 5431511640a59e0880c958b18f9b47f1f0127002..3b874422c638b93112fc792222c0ded170163d4b 100644 --- a/src/jemalloc/src/quarantine.c +++ b/src/jemalloc/src/quarantine.c @@ -146,7 +146,7 @@ quarantine(void *ptr) * Only do redzone validation if Valgrind isn't in * operation. */ - if ((config_valgrind == false || opt_valgrind == false) + if ((config_valgrind == false || in_valgrind == false) && usize <= SMALL_MAXCLASS) arena_quarantine_junk_small(ptr, usize); else diff --git a/src/jemalloc/src/rtree.c b/src/jemalloc/src/rtree.c index 205957ac4e1a447d077c68f7fdc733dc2de0abea..25f603193d8e97e3c356841f97a7d42203adbcb8 100644 --- a/src/jemalloc/src/rtree.c +++ b/src/jemalloc/src/rtree.c @@ -2,15 +2,16 @@ #include "jemalloc/internal/jemalloc_internal.h" rtree_t * -rtree_new(unsigned bits, rtree_alloc_t *alloc, rtree_dalloc_t *dalloc) +rtree_new(unsigned bits, rtree_alloc_t *alloc, rtree_dalloc_t *dalloc, + pool_t *pool) { rtree_t *ret; unsigned bits_per_level, bits_in_leaf, height, i; assert(bits > 0 && bits <= (sizeof(uintptr_t) << 3)); - bits_per_level = ffs(pow2_ceil((RTREE_NODESIZE / sizeof(void *)))) - 1; - bits_in_leaf = ffs(pow2_ceil((RTREE_NODESIZE / sizeof(uint8_t)))) - 1; + bits_per_level = jemalloc_ffs(pow2_ceil((RTREE_NODESIZE / sizeof(void *)))) - 1; + bits_in_leaf = jemalloc_ffs(pow2_ceil((RTREE_NODESIZE / sizeof(uint8_t)))) - 1; if (bits > bits_in_leaf) { height = 1 + (bits - bits_in_leaf) / bits_per_level; if ((height-1) * bits_per_level + bits_in_leaf != bits) @@ -20,7 +21,7 @@ rtree_new(unsigned bits, rtree_alloc_t *alloc, rtree_dalloc_t *dalloc) } assert((height-1) * bits_per_level + bits_in_leaf >= bits); - ret = (rtree_t*)alloc(offsetof(rtree_t, level2bits) + + ret = (rtree_t*)alloc(pool, offsetof(rtree_t, level2bits) + (sizeof(unsigned) * height)); if (ret == NULL) return (NULL); @@ -29,9 +30,10 @@ rtree_new(unsigned bits, rtree_alloc_t *alloc, rtree_dalloc_t *dalloc) ret->alloc = alloc; ret->dalloc = dalloc; + ret->pool = pool; if (malloc_mutex_init(&ret->mutex)) { if (dalloc != NULL) - dalloc(ret); + dalloc(pool, ret); return (NULL); } ret->height = height; @@ -47,10 +49,10 @@ rtree_new(unsigned bits, rtree_alloc_t *alloc, rtree_dalloc_t *dalloc) } else ret->level2bits[0] = bits; - ret->root = (void**)alloc(sizeof(void *) << ret->level2bits[0]); + ret->root = (void**)alloc(pool, sizeof(void *) << ret->level2bits[0]); if (ret->root == NULL) { if (dalloc != NULL) - dalloc(ret); + dalloc(pool, ret); return (NULL); } memset(ret->root, 0, sizeof(void *) << ret->level2bits[0]); @@ -72,7 +74,7 @@ rtree_delete_subtree(rtree_t *rtree, void **node, unsigned level) rtree_delete_subtree(rtree, child, level + 1); } } - rtree->dalloc(node); + rtree->dalloc(rtree->pool, node); } void @@ -80,7 +82,7 @@ rtree_delete(rtree_t *rtree) { rtree_delete_subtree(rtree, rtree->root, 0); - rtree->dalloc(rtree); + rtree->dalloc(rtree->pool, rtree); } void diff --git a/src/jemalloc/src/stats.c b/src/jemalloc/src/stats.c index bef2ab33cd4de0891826afb8573d65095211b8ef..70aff04bbfcabcfdd1d2c99926d3a746aab32c2b 100644 --- a/src/jemalloc/src/stats.c +++ b/src/jemalloc/src/stats.c @@ -6,64 +6,76 @@ xmallctl(n, v, &sz, NULL, 0); \ } while (0) -#define CTL_I_GET(n, v, t) do { \ - size_t mib[6]; \ +#define CTL_P_GET_ARRAY(n, v, t, c) do { \ + size_t mib[8]; \ size_t miblen = sizeof(mib) / sizeof(size_t); \ - size_t sz = sizeof(t); \ + size_t sz = sizeof(t) * c; \ xmallctlnametomib(n, mib, &miblen); \ - mib[2] = i; \ + mib[1] = p; \ xmallctlbymib(mib, miblen, v, &sz, NULL, 0); \ } while (0) -#define CTL_J_GET(n, v, t) do { \ - size_t mib[6]; \ +#define CTL_P_GET(n, v, t) CTL_P_GET_ARRAY(n, v, t, 1) + +#define CTL_PI_GET(n, v, t) do { \ + size_t mib[8]; \ size_t miblen = sizeof(mib) / sizeof(size_t); \ size_t sz = sizeof(t); \ xmallctlnametomib(n, mib, &miblen); \ - mib[2] = j; \ + mib[1] = p; \ + mib[4] = i; \ xmallctlbymib(mib, miblen, v, &sz, NULL, 0); \ } while (0) -#define CTL_IJ_GET(n, v, t) do { \ - size_t mib[6]; \ +#define CTL_PJ_GET(n, v, t) do { \ + size_t mib[8]; \ size_t miblen = sizeof(mib) / sizeof(size_t); \ size_t sz = sizeof(t); \ xmallctlnametomib(n, mib, &miblen); \ - mib[2] = i; \ + mib[1] = p; \ mib[4] = j; \ xmallctlbymib(mib, miblen, v, &sz, NULL, 0); \ } while (0) +#define CTL_PIJ_GET(n, v, t) do { \ + size_t mib[8]; \ + size_t miblen = sizeof(mib) / sizeof(size_t); \ + size_t sz = sizeof(t); \ + xmallctlnametomib(n, mib, &miblen); \ + mib[1] = p; \ + mib[4] = i; \ + mib[6] = j; \ + xmallctlbymib(mib, miblen, v, &sz, NULL, 0); \ +} while (0) + /******************************************************************************/ /* Data. */ bool opt_stats_print = false; -size_t stats_cactive = 0; - /******************************************************************************/ /* Function prototypes for non-inline static functions. */ static void stats_arena_bins_print(void (*write_cb)(void *, const char *), - void *cbopaque, unsigned i); + void *cbopaque, unsigned p, unsigned i); static void stats_arena_lruns_print(void (*write_cb)(void *, const char *), - void *cbopaque, unsigned i); + void *cbopaque, unsigned p, unsigned i); static void stats_arena_print(void (*write_cb)(void *, const char *), - void *cbopaque, unsigned i, bool bins, bool large); + void *cbopaque, unsigned p, unsigned i, bool bins, bool large); /******************************************************************************/ static void stats_arena_bins_print(void (*write_cb)(void *, const char *), void *cbopaque, - unsigned i) + unsigned p, unsigned i) { size_t page; bool config_tcache; unsigned nbins, j, gap_start; - CTL_GET("arenas.page", &page, size_t); + CTL_P_GET("pool.0.arenas.page", &page, size_t); - CTL_GET("config.tcache", &config_tcache, bool); + CTL_P_GET("config.tcache", &config_tcache, bool); if (config_tcache) { malloc_cprintf(write_cb, cbopaque, "bins: bin size regs pgs allocated nmalloc" @@ -74,11 +86,11 @@ stats_arena_bins_print(void (*write_cb)(void *, const char *), void *cbopaque, "bins: bin size regs pgs allocated nmalloc" " ndalloc newruns reruns curruns\n"); } - CTL_GET("arenas.nbins", &nbins, unsigned); + CTL_P_GET("pool.0.arenas.nbins", &nbins, unsigned); for (j = 0, gap_start = UINT_MAX; j < nbins; j++) { uint64_t nruns; - CTL_IJ_GET("stats.arenas.0.bins.0.nruns", &nruns, uint64_t); + CTL_PIJ_GET("pool.0.stats.arenas.0.bins.0.nruns", &nruns, uint64_t); if (nruns == 0) { if (gap_start == UINT_MAX) gap_start = j; @@ -102,26 +114,26 @@ stats_arena_bins_print(void (*write_cb)(void *, const char *), void *cbopaque, } gap_start = UINT_MAX; } - CTL_J_GET("arenas.bin.0.size", ®_size, size_t); - CTL_J_GET("arenas.bin.0.nregs", &nregs, uint32_t); - CTL_J_GET("arenas.bin.0.run_size", &run_size, size_t); - CTL_IJ_GET("stats.arenas.0.bins.0.allocated", + CTL_PJ_GET("pool.0.arenas.bin.0.size", ®_size, size_t); + CTL_PJ_GET("pool.0.arenas.bin.0.nregs", &nregs, uint32_t); + CTL_PJ_GET("pool.0.arenas.bin.0.run_size", &run_size, size_t); + CTL_PIJ_GET("pool.0.stats.arenas.0.bins.0.allocated", &allocated, size_t); - CTL_IJ_GET("stats.arenas.0.bins.0.nmalloc", + CTL_PIJ_GET("pool.0.stats.arenas.0.bins.0.nmalloc", &nmalloc, uint64_t); - CTL_IJ_GET("stats.arenas.0.bins.0.ndalloc", + CTL_PIJ_GET("pool.0.stats.arenas.0.bins.0.ndalloc", &ndalloc, uint64_t); if (config_tcache) { - CTL_IJ_GET("stats.arenas.0.bins.0.nrequests", + CTL_PIJ_GET("pool.0.stats.arenas.0.bins.0.nrequests", &nrequests, uint64_t); - CTL_IJ_GET("stats.arenas.0.bins.0.nfills", + CTL_PIJ_GET("pool.0.stats.arenas.0.bins.0.nfills", &nfills, uint64_t); - CTL_IJ_GET("stats.arenas.0.bins.0.nflushes", + CTL_PIJ_GET("pool.0.stats.arenas.0.bins.0.nflushes", &nflushes, uint64_t); } - CTL_IJ_GET("stats.arenas.0.bins.0.nreruns", &reruns, + CTL_PIJ_GET("pool.0.stats.arenas.0.bins.0.nreruns", &reruns, uint64_t); - CTL_IJ_GET("stats.arenas.0.bins.0.curruns", &curruns, + CTL_PIJ_GET("pool.0.stats.arenas.0.bins.0.curruns", &curruns, size_t); if (config_tcache) { malloc_cprintf(write_cb, cbopaque, @@ -157,33 +169,33 @@ stats_arena_bins_print(void (*write_cb)(void *, const char *), void *cbopaque, static void stats_arena_lruns_print(void (*write_cb)(void *, const char *), void *cbopaque, - unsigned i) + unsigned p, unsigned i) { size_t page, nlruns, j; ssize_t gap_start; - CTL_GET("arenas.page", &page, size_t); + CTL_P_GET("pool.0.arenas.page", &page, size_t); malloc_cprintf(write_cb, cbopaque, "large: size pages nmalloc ndalloc nrequests" " curruns\n"); - CTL_GET("arenas.nlruns", &nlruns, size_t); + CTL_P_GET("pool.0.arenas.nlruns", &nlruns, size_t); for (j = 0, gap_start = -1; j < nlruns; j++) { uint64_t nmalloc, ndalloc, nrequests; size_t run_size, curruns; - CTL_IJ_GET("stats.arenas.0.lruns.0.nmalloc", &nmalloc, + CTL_PIJ_GET("pool.0.stats.arenas.0.lruns.0.nmalloc", &nmalloc, uint64_t); - CTL_IJ_GET("stats.arenas.0.lruns.0.ndalloc", &ndalloc, + CTL_PIJ_GET("pool.0.stats.arenas.0.lruns.0.ndalloc", &ndalloc, uint64_t); - CTL_IJ_GET("stats.arenas.0.lruns.0.nrequests", &nrequests, + CTL_PIJ_GET("pool.0.stats.arenas.0.lruns.0.nrequests", &nrequests, uint64_t); if (nrequests == 0) { if (gap_start == -1) gap_start = j; } else { - CTL_J_GET("arenas.lrun.0.size", &run_size, size_t); - CTL_IJ_GET("stats.arenas.0.lruns.0.curruns", &curruns, + CTL_PJ_GET("pool.0.arenas.lrun.0.size", &run_size, size_t); + CTL_PIJ_GET("pool.0.stats.arenas.0.lruns.0.curruns", &curruns, size_t); if (gap_start != -1) { malloc_cprintf(write_cb, cbopaque, "[%zu]\n", @@ -203,7 +215,7 @@ stats_arena_lruns_print(void (*write_cb)(void *, const char *), void *cbopaque, static void stats_arena_print(void (*write_cb)(void *, const char *), void *cbopaque, - unsigned i, bool bins, bool large) + unsigned p, unsigned i, bool bins, bool large) { unsigned nthreads; const char *dss; @@ -213,20 +225,22 @@ stats_arena_print(void (*write_cb)(void *, const char *), void *cbopaque, uint64_t small_nmalloc, small_ndalloc, small_nrequests; size_t large_allocated; uint64_t large_nmalloc, large_ndalloc, large_nrequests; + size_t huge_allocated; + uint64_t huge_nmalloc, huge_ndalloc, huge_nrequests; - CTL_GET("arenas.page", &page, size_t); + CTL_P_GET("pool.0.arenas.page", &page, size_t); - CTL_I_GET("stats.arenas.0.nthreads", &nthreads, unsigned); + CTL_PI_GET("pool.0.stats.arenas.0.nthreads", &nthreads, unsigned); malloc_cprintf(write_cb, cbopaque, "assigned threads: %u\n", nthreads); - CTL_I_GET("stats.arenas.0.dss", &dss, const char *); + CTL_PI_GET("pool.0.stats.arenas.0.dss", &dss, const char *); malloc_cprintf(write_cb, cbopaque, "dss allocation precedence: %s\n", dss); - CTL_I_GET("stats.arenas.0.pactive", &pactive, size_t); - CTL_I_GET("stats.arenas.0.pdirty", &pdirty, size_t); - CTL_I_GET("stats.arenas.0.npurge", &npurge, uint64_t); - CTL_I_GET("stats.arenas.0.nmadvise", &nmadvise, uint64_t); - CTL_I_GET("stats.arenas.0.purged", &purged, uint64_t); + CTL_PI_GET("pool.0.stats.arenas.0.pactive", &pactive, size_t); + CTL_PI_GET("pool.0.stats.arenas.0.pdirty", &pdirty, size_t); + CTL_PI_GET("pool.0.stats.arenas.0.npurge", &npurge, uint64_t); + CTL_PI_GET("pool.0.stats.arenas.0.nmadvise", &nmadvise, uint64_t); + CTL_PI_GET("pool.0.stats.arenas.0.purged", &purged, uint64_t); malloc_cprintf(write_cb, cbopaque, "dirty pages: %zu:%zu active:dirty, %"PRIu64" sweep%s," " %"PRIu64" madvise%s, %"PRIu64" purged\n", @@ -235,38 +249,45 @@ stats_arena_print(void (*write_cb)(void *, const char *), void *cbopaque, malloc_cprintf(write_cb, cbopaque, " allocated nmalloc ndalloc nrequests\n"); - CTL_I_GET("stats.arenas.0.small.allocated", &small_allocated, size_t); - CTL_I_GET("stats.arenas.0.small.nmalloc", &small_nmalloc, uint64_t); - CTL_I_GET("stats.arenas.0.small.ndalloc", &small_ndalloc, uint64_t); - CTL_I_GET("stats.arenas.0.small.nrequests", &small_nrequests, uint64_t); + CTL_PI_GET("pool.0.stats.arenas.0.small.allocated", &small_allocated, size_t); + CTL_PI_GET("pool.0.stats.arenas.0.small.nmalloc", &small_nmalloc, uint64_t); + CTL_PI_GET("pool.0.stats.arenas.0.small.ndalloc", &small_ndalloc, uint64_t); + CTL_PI_GET("pool.0.stats.arenas.0.small.nrequests", &small_nrequests, uint64_t); malloc_cprintf(write_cb, cbopaque, "small: %12zu %12"PRIu64" %12"PRIu64" %12"PRIu64"\n", small_allocated, small_nmalloc, small_ndalloc, small_nrequests); - CTL_I_GET("stats.arenas.0.large.allocated", &large_allocated, size_t); - CTL_I_GET("stats.arenas.0.large.nmalloc", &large_nmalloc, uint64_t); - CTL_I_GET("stats.arenas.0.large.ndalloc", &large_ndalloc, uint64_t); - CTL_I_GET("stats.arenas.0.large.nrequests", &large_nrequests, uint64_t); + CTL_PI_GET("pool.0.stats.arenas.0.large.allocated", &large_allocated, size_t); + CTL_PI_GET("pool.0.stats.arenas.0.large.nmalloc", &large_nmalloc, uint64_t); + CTL_PI_GET("pool.0.stats.arenas.0.large.ndalloc", &large_ndalloc, uint64_t); + CTL_PI_GET("pool.0.stats.arenas.0.large.nrequests", &large_nrequests, uint64_t); malloc_cprintf(write_cb, cbopaque, "large: %12zu %12"PRIu64" %12"PRIu64" %12"PRIu64"\n", large_allocated, large_nmalloc, large_ndalloc, large_nrequests); + CTL_PI_GET("pool.0.stats.arenas.0.huge.allocated", &huge_allocated, size_t); + CTL_PI_GET("pool.0.stats.arenas.0.huge.nmalloc", &huge_nmalloc, uint64_t); + CTL_PI_GET("pool.0.stats.arenas.0.huge.ndalloc", &huge_ndalloc, uint64_t); + CTL_PI_GET("pool.0.stats.arenas.0.huge.nrequests", &huge_nrequests, uint64_t); + malloc_cprintf(write_cb, cbopaque, + "huge: %12zu %12"PRIu64" %12"PRIu64" %12"PRIu64"\n", + huge_allocated, huge_nmalloc, huge_ndalloc, huge_nrequests); malloc_cprintf(write_cb, cbopaque, "total: %12zu %12"PRIu64" %12"PRIu64" %12"PRIu64"\n", - small_allocated + large_allocated, - small_nmalloc + large_nmalloc, - small_ndalloc + large_ndalloc, - small_nrequests + large_nrequests); + small_allocated + large_allocated + huge_allocated, + small_nmalloc + large_nmalloc + huge_nmalloc, + small_ndalloc + large_ndalloc + huge_ndalloc, + small_nrequests + large_nrequests + huge_nrequests); malloc_cprintf(write_cb, cbopaque, "active: %12zu\n", pactive * page); - CTL_I_GET("stats.arenas.0.mapped", &mapped, size_t); + CTL_PI_GET("pool.0.stats.arenas.0.mapped", &mapped, size_t); malloc_cprintf(write_cb, cbopaque, "mapped: %12zu\n", mapped); if (bins) - stats_arena_bins_print(write_cb, cbopaque, i); + stats_arena_bins_print(write_cb, cbopaque, p, i); if (large) - stats_arena_lruns_print(write_cb, cbopaque, i); + stats_arena_lruns_print(write_cb, cbopaque, p, i); } void -stats_print(void (*write_cb)(void *, const char *), void *cbopaque, +stats_print(pool_t *pool, void (*write_cb)(void *, const char *), void *cbopaque, const char *opts) { int err; @@ -277,6 +298,7 @@ stats_print(void (*write_cb)(void *, const char *), void *cbopaque, bool unmerged = true; bool bins = true; bool large = true; + unsigned p = pool->pool_id; /* * Refresh stats, in case mallctl() was called by the application. @@ -404,19 +426,19 @@ stats_print(void (*write_cb)(void *, const char *), void *cbopaque, malloc_cprintf(write_cb, cbopaque, "CPUs: %u\n", ncpus); - CTL_GET("arenas.narenas", &uv, unsigned); + CTL_P_GET("pool.0.arenas.narenas", &uv, unsigned); malloc_cprintf(write_cb, cbopaque, "Arenas: %u\n", uv); malloc_cprintf(write_cb, cbopaque, "Pointer size: %zu\n", sizeof(void *)); - CTL_GET("arenas.quantum", &sv, size_t); + CTL_P_GET("pool.0.arenas.quantum", &sv, size_t); malloc_cprintf(write_cb, cbopaque, "Quantum size: %zu\n", sv); - CTL_GET("arenas.page", &sv, size_t); + CTL_P_GET("pool.0.arenas.page", &sv, size_t); malloc_cprintf(write_cb, cbopaque, "Page size: %zu\n", sv); - CTL_GET("opt.lg_dirty_mult", &ssv, ssize_t); + CTL_P_GET("opt.lg_dirty_mult", &ssv, ssize_t); if (ssv >= 0) { malloc_cprintf(write_cb, cbopaque, "Min active:dirty page ratio per arena: %u:1\n", @@ -458,13 +480,11 @@ stats_print(void (*write_cb)(void *, const char *), void *cbopaque, size_t allocated, active, mapped; size_t chunks_current, chunks_high; uint64_t chunks_total; - size_t huge_allocated; - uint64_t huge_nmalloc, huge_ndalloc; - CTL_GET("stats.cactive", &cactive, size_t *); - CTL_GET("stats.allocated", &allocated, size_t); - CTL_GET("stats.active", &active, size_t); - CTL_GET("stats.mapped", &mapped, size_t); + CTL_P_GET("pool.0.stats.cactive", &cactive, size_t *); + CTL_P_GET("pool.0.stats.allocated", &allocated, size_t); + CTL_P_GET("pool.0.stats.active", &active, size_t); + CTL_P_GET("pool.0.stats.mapped", &mapped, size_t); malloc_cprintf(write_cb, cbopaque, "Allocated: %zu, active: %zu, mapped: %zu\n", allocated, active, mapped); @@ -472,36 +492,26 @@ stats_print(void (*write_cb)(void *, const char *), void *cbopaque, "Current active ceiling: %zu\n", atomic_read_z(cactive)); /* Print chunk stats. */ - CTL_GET("stats.chunks.total", &chunks_total, uint64_t); - CTL_GET("stats.chunks.high", &chunks_high, size_t); - CTL_GET("stats.chunks.current", &chunks_current, size_t); + CTL_P_GET("pool.0.stats.chunks.total", &chunks_total, uint64_t); + CTL_P_GET("pool.0.stats.chunks.high", &chunks_high, size_t); + CTL_P_GET("pool.0.stats.chunks.current", &chunks_current, size_t); malloc_cprintf(write_cb, cbopaque, "chunks: nchunks " "highchunks curchunks\n"); malloc_cprintf(write_cb, cbopaque, " %13"PRIu64" %12zu %12zu\n", chunks_total, chunks_high, chunks_current); - /* Print huge stats. */ - CTL_GET("stats.huge.nmalloc", &huge_nmalloc, uint64_t); - CTL_GET("stats.huge.ndalloc", &huge_ndalloc, uint64_t); - CTL_GET("stats.huge.allocated", &huge_allocated, size_t); - malloc_cprintf(write_cb, cbopaque, - "huge: nmalloc ndalloc allocated\n"); - malloc_cprintf(write_cb, cbopaque, - " %12"PRIu64" %12"PRIu64" %12zu\n", - huge_nmalloc, huge_ndalloc, huge_allocated); - if (merged) { unsigned narenas; - CTL_GET("arenas.narenas", &narenas, unsigned); + CTL_P_GET("pool.0.arenas.narenas", &narenas, unsigned); { VARIABLE_ARRAY(bool, initialized, narenas); size_t isz; unsigned i, ninitialized; isz = sizeof(bool) * narenas; - xmallctl("arenas.initialized", initialized, + xmallctl("pool.0.arenas.initialized", initialized, &isz, NULL, 0); for (i = ninitialized = 0; i < narenas; i++) { if (initialized[i]) @@ -513,7 +523,7 @@ stats_print(void (*write_cb)(void *, const char *), void *cbopaque, malloc_cprintf(write_cb, cbopaque, "\nMerged arenas stats:\n"); stats_arena_print(write_cb, cbopaque, - narenas, bins, large); + p, narenas, bins, large); } } } @@ -523,15 +533,13 @@ stats_print(void (*write_cb)(void *, const char *), void *cbopaque, /* Print stats for each arena. */ - CTL_GET("arenas.narenas", &narenas, unsigned); + CTL_P_GET("pool.0.arenas.narenas", &narenas, unsigned); { VARIABLE_ARRAY(bool, initialized, narenas); - size_t isz; unsigned i; - isz = sizeof(bool) * narenas; - xmallctl("arenas.initialized", initialized, - &isz, NULL, 0); + CTL_P_GET_ARRAY("pool.0.arenas.initialized", + initialized, bool, narenas); for (i = 0; i < narenas; i++) { if (initialized[i]) { @@ -539,7 +547,7 @@ stats_print(void (*write_cb)(void *, const char *), void *cbopaque, cbopaque, "\narenas[%u]:\n", i); stats_arena_print(write_cb, - cbopaque, i, bins, large); + cbopaque, p, i, bins, large); } } } diff --git a/src/jemalloc/src/tcache.c b/src/jemalloc/src/tcache.c index 6de92960b2df249b1d71094ef365205aa73508f5..aaa126f150cf4d238accde612cbfc123c28de56e 100644 --- a/src/jemalloc/src/tcache.c +++ b/src/jemalloc/src/tcache.c @@ -3,8 +3,8 @@ /******************************************************************************/ /* Data. */ - -malloc_tsd_data(, tcache, tcache_t *, NULL) +#define ARR_INITIALIZER JEMALLOC_ARG_CONCAT({0}) +malloc_tsd_data(, tcache, tsd_tcache_t, TSD_TCACHE_INITIALIZER) malloc_tsd_data(, tcache_enabled, tcache_enabled_t, tcache_enabled_default) bool opt_tcache = true; @@ -265,12 +265,56 @@ tcache_arena_dissociate(tcache_t *tcache) } } +tcache_t * +tcache_get_hard(tcache_t *tcache, pool_t *pool, bool create) +{ + arena_t dummy; + DUMMY_ARENA_INITIALIZE(dummy, pool); + if (tcache == NULL) { + if (create == false) { + /* + * Creating a tcache here would cause + * allocation as a side effect of free(). + * Ordinarily that would be okay since + * tcache_create() failure is a soft failure + * that doesn't propagate. However, if TLS + * data are freed via free() as in glibc, + * subtle corruption could result from setting + * a TLS variable after its backing memory is + * freed. + */ + return (NULL); + } + if (tcache_enabled_get() == false) { + tcache_enabled_set(false); /* Memoize. */ + return (NULL); + } + return (tcache_create(choose_arena(&dummy))); + } + if (tcache == TCACHE_STATE_PURGATORY) { + /* + * Make a note that an allocator function was called + * after tcache_thread_cleanup() was called. + */ + tsd_tcache_t *tsd = tcache_tsd_get(); + tcache = TCACHE_STATE_REINCARNATED; + tsd->seqno[pool->pool_id] = pool->seqno; + tsd->tcaches[pool->pool_id] = tcache; + return (NULL); + } + if (tcache == TCACHE_STATE_REINCARNATED) + return (NULL); + not_reached(); + return (NULL); +} + tcache_t * tcache_create(arena_t *arena) { tcache_t *tcache; size_t size, stack_offset; unsigned i; + tsd_tcache_t *tsd = tcache_tsd_get(); size = offsetof(tcache_t, tbins) + (sizeof(tcache_bin_t) * nhbins); /* Naturally align the pointer stacks. */ @@ -307,7 +351,8 @@ tcache_create(arena_t *arena) stack_offset += tcache_bin_info[i].ncached_max * sizeof(void *); } - tcache_tsd_set(&tcache); + tsd->seqno[arena->pool->pool_id] = arena->pool->seqno; + tsd->tcaches[arena->pool->pool_id] = tcache; return (tcache); } @@ -372,31 +417,39 @@ tcache_destroy(tcache_t *tcache) void tcache_thread_cleanup(void *arg) { - tcache_t *tcache = *(tcache_t **)arg; + int i; + tsd_tcache_t *tsd_array = arg; + + malloc_mutex_lock(&pools_lock); + for (i = 0; i < POOLS_MAX; ++i) { + tcache_t *tcache = tsd_array->tcaches[i]; + if (tcache != NULL) { + if (tcache == TCACHE_STATE_DISABLED) { + /* Do nothing. */ + } else if (tcache == TCACHE_STATE_REINCARNATED) { + /* + * Another destructor called an allocator function after this + * destructor was called. Reset tcache to + * TCACHE_STATE_PURGATORY in order to receive another callback. + */ + tsd_array->tcaches[i] = TCACHE_STATE_PURGATORY; + } else if (tcache == TCACHE_STATE_PURGATORY) { + /* + * The previous time this destructor was called, we set the key + * to TCACHE_STATE_PURGATORY so that other destructors wouldn't + * cause re-creation of the tcache. This time, do nothing, so + * that the destructor will not be called again. + */ + } else if (tcache != NULL) { + assert(tcache != TCACHE_STATE_PURGATORY); + if (pools[i] != NULL && tsd_array->seqno[i] == pools[i]->seqno) + tcache_destroy(tcache); - if (tcache == TCACHE_STATE_DISABLED) { - /* Do nothing. */ - } else if (tcache == TCACHE_STATE_REINCARNATED) { - /* - * Another destructor called an allocator function after this - * destructor was called. Reset tcache to - * TCACHE_STATE_PURGATORY in order to receive another callback. - */ - tcache = TCACHE_STATE_PURGATORY; - tcache_tsd_set(&tcache); - } else if (tcache == TCACHE_STATE_PURGATORY) { - /* - * The previous time this destructor was called, we set the key - * to TCACHE_STATE_PURGATORY so that other destructors wouldn't - * cause re-creation of the tcache. This time, do nothing, so - * that the destructor will not be called again. - */ - } else if (tcache != NULL) { - assert(tcache != TCACHE_STATE_PURGATORY); - tcache_destroy(tcache); - tcache = TCACHE_STATE_PURGATORY; - tcache_tsd_set(&tcache); + tsd_array->tcaches[i] = TCACHE_STATE_PURGATORY; + } + } } + malloc_mutex_unlock(&pools_lock); } /* Caller must own arena->lock. */ @@ -431,6 +484,10 @@ tcache_boot0(void) { unsigned i; + /* Array still initialized */ + if (tcache_bin_info != NULL) + return (false); + /* * If necessary, clamp opt_lg_tcache_max, now that arena_maxclass is * known. @@ -445,8 +502,9 @@ tcache_boot0(void) nhbins = NBINS + (tcache_maxclass >> LG_PAGE); /* Initialize tcache_bin_info. */ - tcache_bin_info = (tcache_bin_info_t *)base_alloc(nhbins * - sizeof(tcache_bin_info_t)); + tcache_bin_info = (tcache_bin_info_t *)je_base_malloc(nhbins * + sizeof(tcache_bin_info_t)); + if (tcache_bin_info == NULL) return (true); stack_nelms = 0; diff --git a/src/jemalloc/src/tsd.c b/src/jemalloc/src/tsd.c index 700caabfe47789f57e3ea6ea67196e2b15f7e88e..a116d86999a66bebff0e46643f17e731420190ae 100644 --- a/src/jemalloc/src/tsd.c +++ b/src/jemalloc/src/tsd.c @@ -12,9 +12,9 @@ static malloc_tsd_cleanup_t cleanups[MALLOC_TSD_CLEANUPS_MAX]; void * malloc_tsd_malloc(size_t size) { - + pool_t *base_pool = pools[0]; /* Avoid choose_arena() in order to dodge bootstrapping issues. */ - return (arena_malloc(arenas[0], size, false, false)); + return (arena_malloc(base_pool->arenas[0], size, false, false)); } void diff --git a/src/jemalloc/src/util.c b/src/jemalloc/src/util.c index 93a19fd16f7609efb5b49dc704fdcd3bd89a5da8..1717f08eac61ff576ebafdb942fe82a46441033f 100644 --- a/src/jemalloc/src/util.c +++ b/src/jemalloc/src/util.c @@ -100,7 +100,7 @@ uintmax_t malloc_strtoumax(const char *restrict nptr, char **restrict endptr, int base) { uintmax_t ret, digit; - int b; + unsigned b; bool neg; const char *p, *ns; @@ -381,7 +381,9 @@ malloc_vsnprintf(char *str, size_t size, const char *format, va_list ap) case 'p': /* Synthetic; used for %p. */ \ val = va_arg(ap, uintptr_t); \ break; \ - default: not_reached(); \ + default: \ + not_reached(); \ + val = 0; \ } \ } while (0) @@ -548,7 +550,7 @@ malloc_vsnprintf(char *str, size_t size, const char *format, va_list ap) assert(len == '?' || len == 'l'); assert_not_implemented(len != 'l'); s = va_arg(ap, char *); - slen = (prec < 0) ? strlen(s) : prec; + slen = (prec < 0) ? strlen(s) : (size_t)prec; APPEND_PADDED_S(s, slen, width, left_justify); f++; break; diff --git a/src/jemalloc/src/valgrind.c b/src/jemalloc/src/valgrind.c new file mode 100644 index 0000000000000000000000000000000000000000..ffee4c738cf41bf4fc258cfbc25a4e90d17d0809 --- /dev/null +++ b/src/jemalloc/src/valgrind.c @@ -0,0 +1,34 @@ +#include "jemalloc/internal/jemalloc_internal.h" +#ifndef JEMALLOC_VALGRIND +# error "This source file is for Valgrind integration." +#endif + +#include <valgrind/memcheck.h> + +void +valgrind_make_mem_noaccess(void *ptr, size_t usize) +{ + + (void)VALGRIND_MAKE_MEM_NOACCESS(ptr, usize); +} + +void +valgrind_make_mem_undefined(void *ptr, size_t usize) +{ + + (void)VALGRIND_MAKE_MEM_UNDEFINED(ptr, usize); +} + +void +valgrind_make_mem_defined(void *ptr, size_t usize) +{ + + (void)VALGRIND_MAKE_MEM_DEFINED(ptr, usize); +} + +void +valgrind_freelike_block(void *ptr, size_t usize) +{ + + VALGRIND_FREELIKE_BLOCK(ptr, usize); +} diff --git a/src/jemalloc/src/vector.c b/src/jemalloc/src/vector.c new file mode 100644 index 0000000000000000000000000000000000000000..0067b693ff76293a0adf9f5120753a2bb247adb7 --- /dev/null +++ b/src/jemalloc/src/vector.c @@ -0,0 +1,82 @@ +#define JEMALLOC_VECTOR_C_ +#include "jemalloc/internal/jemalloc_internal.h" + +/* Round up the value to the closest power of two. */ +static inline unsigned +ceil_p2(unsigned n) +{ + return 1 << (32 - __builtin_clz(n)); +} + +/* Calculate how big should be the vector list array. */ +static inline unsigned +get_vec_part_len(unsigned n) +{ + return MAX(ceil_p2(n), VECTOR_MIN_PART_SIZE); +} + +/* + * Find the vector list element in which the index should be stored, + * if no such list exist return a pointer to a place in memory where it should + * be allocated. + */ +static vec_list_t ** +find_vec_list(vector_t *vector, int *index) +{ + vec_list_t **vec_list; + + for (vec_list = &vector->list; + *vec_list != NULL; vec_list = &(*vec_list)->next) { + if (*index < (*vec_list)->length) + break; + + *index -= (*vec_list)->length; + } + + return vec_list; +} + +/* Return a value from vector at index. */ +void * +vec_get(vector_t *vector, int index) +{ + vec_list_t *vec_list = *find_vec_list(vector, &index); + + return (vec_list == NULL) ? NULL : vec_list->data[index]; +} + +/* Set a value to vector at index. */ +void +vec_set(vector_t *vector, int index, void *val) +{ + vec_list_t **vec_list = find_vec_list(vector, &index); + + /* + * There's no array to put the value in, + * which means a new one has to be allocated. + */ + if (*vec_list == NULL) { + int vec_part_len = get_vec_part_len(index); + + *vec_list = je_base_malloc(sizeof(vec_list_t) + + sizeof(void *) * vec_part_len); + if (*vec_list == NULL) + return; + (*vec_list)->next = NULL; + (*vec_list)->length = vec_part_len; + } + + (*vec_list)->data[index] = val; +} + +/* Free all the memory in the container. */ +void +vec_delete(vector_t *vector) +{ + vec_list_t *vec_list_next, *vec_list = vector->list; + while (vec_list != NULL) { + vec_list_next = vec_list->next; + je_base_free(vec_list); + vec_list = vec_list_next; + } +} \ No newline at end of file diff --git a/src/jemalloc/src/zone.c b/src/jemalloc/src/zone.c index e0302ef4edc35402adef563fdc72252ce8431cb7..a722287b2e9c70e380752a6c4357259199b552c1 100644 --- a/src/jemalloc/src/zone.c +++ b/src/jemalloc/src/zone.c @@ -176,6 +176,7 @@ register_zone(void) * register jemalloc's. */ malloc_zone_t *default_zone = malloc_default_zone(); + malloc_zone_t *purgeable_zone = NULL; if (!default_zone->zone_name || strcmp(default_zone->zone_name, "DefaultMallocZone") != 0) { return; @@ -237,22 +238,37 @@ register_zone(void) * run time. */ if (malloc_default_purgeable_zone != NULL) - malloc_default_purgeable_zone(); + purgeable_zone = malloc_default_purgeable_zone(); /* Register the custom zone. At this point it won't be the default. */ malloc_zone_register(&zone); - /* - * Unregister and reregister the default zone. On OSX >= 10.6, - * unregistering takes the last registered zone and places it at the - * location of the specified zone. Unregistering the default zone thus - * makes the last registered one the default. On OSX < 10.6, - * unregistering shifts all registered zones. The first registered zone - * then becomes the default. - */ do { default_zone = malloc_default_zone(); + /* + * Unregister and reregister the default zone. On OSX >= 10.6, + * unregistering takes the last registered zone and places it + * at the location of the specified zone. Unregistering the + * default zone thus makes the last registered one the default. + * On OSX < 10.6, unregistering shifts all registered zones. + * The first registered zone then becomes the default. + */ malloc_zone_unregister(default_zone); malloc_zone_register(default_zone); + /* + * On OSX 10.6, having the default purgeable zone appear before + * the default zone makes some things crash because it thinks it + * owns the default zone allocated pointers. We thus unregister/ + * re-register it in order to ensure it's always after the + * default zone. On OSX < 10.6, there is no purgeable zone, so + * this does nothing. On OSX >= 10.6, unregistering replaces the + * purgeable zone with the last registered zone above, i.e the + * default zone. Registering it again then puts it at the end, + * obviously after the default zone. + */ + if (purgeable_zone) { + malloc_zone_unregister(purgeable_zone); + malloc_zone_register(purgeable_zone); + } } while (malloc_default_zone() != &zone); } diff --git a/src/jemalloc/test/include/test/jemalloc_test_defs.h.in b/src/jemalloc/test/include/test/jemalloc_test_defs.h.in index 18a9773d705e8001e0a30cd9ad625754a0d61564..aaaaec14b2cb890736d56f0c01664e7b378fd73d 100644 --- a/src/jemalloc/test/include/test/jemalloc_test_defs.h.in +++ b/src/jemalloc/test/include/test/jemalloc_test_defs.h.in @@ -1,4 +1,5 @@ #include "jemalloc/internal/jemalloc_internal_defs.h" +#include "jemalloc/internal/jemalloc_internal_decls.h" /* For use by SFMT. */ #undef HAVE_SSE2 diff --git a/src/jemalloc/test/include/test/test.h b/src/jemalloc/test/include/test/test.h index a32ec07c4c51362428b313173f4ae54f1026a90f..863e20b234828592ccc55ca1ab6717b4c7748922 100644 --- a/src/jemalloc/test/include/test/test.h +++ b/src/jemalloc/test/include/test/test.h @@ -1,6 +1,6 @@ #define ASSERT_BUFSIZE 256 -#define assert_cmp(t, a, b, cmp, neg_cmp, pri, fmt...) do { \ +#define assert_cmp(t, a, b, cmp, neg_cmp, pri, ...) do { \ t a_ = (a); \ t b_ = (b); \ if (!(a_ cmp b_)) { \ @@ -12,205 +12,205 @@ "%"pri" "#neg_cmp" %"pri": ", \ __func__, __FILE__, __LINE__, \ #a, #b, a_, b_); \ - malloc_snprintf(message, sizeof(message), fmt); \ + malloc_snprintf(message, sizeof(message), __VA_ARGS__); \ p_test_fail(prefix, message); \ } \ } while (0) -#define assert_ptr_eq(a, b, fmt...) assert_cmp(void *, a, b, ==, \ - !=, "p", fmt) -#define assert_ptr_ne(a, b, fmt...) assert_cmp(void *, a, b, !=, \ - ==, "p", fmt) -#define assert_ptr_null(a, fmt...) assert_cmp(void *, a, NULL, ==, \ - !=, "p", fmt) -#define assert_ptr_not_null(a, fmt...) assert_cmp(void *, a, NULL, !=, \ - ==, "p", fmt) - -#define assert_c_eq(a, b, fmt...) assert_cmp(char, a, b, ==, !=, "c", fmt) -#define assert_c_ne(a, b, fmt...) assert_cmp(char, a, b, !=, ==, "c", fmt) -#define assert_c_lt(a, b, fmt...) assert_cmp(char, a, b, <, >=, "c", fmt) -#define assert_c_le(a, b, fmt...) assert_cmp(char, a, b, <=, >, "c", fmt) -#define assert_c_ge(a, b, fmt...) assert_cmp(char, a, b, >=, <, "c", fmt) -#define assert_c_gt(a, b, fmt...) assert_cmp(char, a, b, >, <=, "c", fmt) - -#define assert_x_eq(a, b, fmt...) assert_cmp(int, a, b, ==, !=, "#x", fmt) -#define assert_x_ne(a, b, fmt...) assert_cmp(int, a, b, !=, ==, "#x", fmt) -#define assert_x_lt(a, b, fmt...) assert_cmp(int, a, b, <, >=, "#x", fmt) -#define assert_x_le(a, b, fmt...) assert_cmp(int, a, b, <=, >, "#x", fmt) -#define assert_x_ge(a, b, fmt...) assert_cmp(int, a, b, >=, <, "#x", fmt) -#define assert_x_gt(a, b, fmt...) assert_cmp(int, a, b, >, <=, "#x", fmt) - -#define assert_d_eq(a, b, fmt...) assert_cmp(int, a, b, ==, !=, "d", fmt) -#define assert_d_ne(a, b, fmt...) assert_cmp(int, a, b, !=, ==, "d", fmt) -#define assert_d_lt(a, b, fmt...) assert_cmp(int, a, b, <, >=, "d", fmt) -#define assert_d_le(a, b, fmt...) assert_cmp(int, a, b, <=, >, "d", fmt) -#define assert_d_ge(a, b, fmt...) assert_cmp(int, a, b, >=, <, "d", fmt) -#define assert_d_gt(a, b, fmt...) assert_cmp(int, a, b, >, <=, "d", fmt) - -#define assert_u_eq(a, b, fmt...) assert_cmp(int, a, b, ==, !=, "u", fmt) -#define assert_u_ne(a, b, fmt...) assert_cmp(int, a, b, !=, ==, "u", fmt) -#define assert_u_lt(a, b, fmt...) assert_cmp(int, a, b, <, >=, "u", fmt) -#define assert_u_le(a, b, fmt...) assert_cmp(int, a, b, <=, >, "u", fmt) -#define assert_u_ge(a, b, fmt...) assert_cmp(int, a, b, >=, <, "u", fmt) -#define assert_u_gt(a, b, fmt...) assert_cmp(int, a, b, >, <=, "u", fmt) - -#define assert_ld_eq(a, b, fmt...) assert_cmp(long, a, b, ==, \ - !=, "ld", fmt) -#define assert_ld_ne(a, b, fmt...) assert_cmp(long, a, b, !=, \ - ==, "ld", fmt) -#define assert_ld_lt(a, b, fmt...) assert_cmp(long, a, b, <, \ - >=, "ld", fmt) -#define assert_ld_le(a, b, fmt...) assert_cmp(long, a, b, <=, \ - >, "ld", fmt) -#define assert_ld_ge(a, b, fmt...) assert_cmp(long, a, b, >=, \ - <, "ld", fmt) -#define assert_ld_gt(a, b, fmt...) assert_cmp(long, a, b, >, \ - <=, "ld", fmt) - -#define assert_lu_eq(a, b, fmt...) assert_cmp(unsigned long, \ - a, b, ==, !=, "lu", fmt) -#define assert_lu_ne(a, b, fmt...) assert_cmp(unsigned long, \ - a, b, !=, ==, "lu", fmt) -#define assert_lu_lt(a, b, fmt...) assert_cmp(unsigned long, \ - a, b, <, >=, "lu", fmt) -#define assert_lu_le(a, b, fmt...) assert_cmp(unsigned long, \ - a, b, <=, >, "lu", fmt) -#define assert_lu_ge(a, b, fmt...) assert_cmp(unsigned long, \ - a, b, >=, <, "lu", fmt) -#define assert_lu_gt(a, b, fmt...) assert_cmp(unsigned long, \ - a, b, >, <=, "lu", fmt) - -#define assert_qd_eq(a, b, fmt...) assert_cmp(long long, a, b, ==, \ - !=, "qd", fmt) -#define assert_qd_ne(a, b, fmt...) assert_cmp(long long, a, b, !=, \ - ==, "qd", fmt) -#define assert_qd_lt(a, b, fmt...) assert_cmp(long long, a, b, <, \ - >=, "qd", fmt) -#define assert_qd_le(a, b, fmt...) assert_cmp(long long, a, b, <=, \ - >, "qd", fmt) -#define assert_qd_ge(a, b, fmt...) assert_cmp(long long, a, b, >=, \ - <, "qd", fmt) -#define assert_qd_gt(a, b, fmt...) assert_cmp(long long, a, b, >, \ - <=, "qd", fmt) - -#define assert_qu_eq(a, b, fmt...) assert_cmp(unsigned long long, \ - a, b, ==, !=, "qu", fmt) -#define assert_qu_ne(a, b, fmt...) assert_cmp(unsigned long long, \ - a, b, !=, ==, "qu", fmt) -#define assert_qu_lt(a, b, fmt...) assert_cmp(unsigned long long, \ - a, b, <, >=, "qu", fmt) -#define assert_qu_le(a, b, fmt...) assert_cmp(unsigned long long, \ - a, b, <=, >, "qu", fmt) -#define assert_qu_ge(a, b, fmt...) assert_cmp(unsigned long long, \ - a, b, >=, <, "qu", fmt) -#define assert_qu_gt(a, b, fmt...) assert_cmp(unsigned long long, \ - a, b, >, <=, "qu", fmt) - -#define assert_jd_eq(a, b, fmt...) assert_cmp(intmax_t, a, b, ==, \ - !=, "jd", fmt) -#define assert_jd_ne(a, b, fmt...) assert_cmp(intmax_t, a, b, !=, \ - ==, "jd", fmt) -#define assert_jd_lt(a, b, fmt...) assert_cmp(intmax_t, a, b, <, \ - >=, "jd", fmt) -#define assert_jd_le(a, b, fmt...) assert_cmp(intmax_t, a, b, <=, \ - >, "jd", fmt) -#define assert_jd_ge(a, b, fmt...) assert_cmp(intmax_t, a, b, >=, \ - <, "jd", fmt) -#define assert_jd_gt(a, b, fmt...) assert_cmp(intmax_t, a, b, >, \ - <=, "jd", fmt) - -#define assert_ju_eq(a, b, fmt...) assert_cmp(uintmax_t, a, b, ==, \ - !=, "ju", fmt) -#define assert_ju_ne(a, b, fmt...) assert_cmp(uintmax_t, a, b, !=, \ - ==, "ju", fmt) -#define assert_ju_lt(a, b, fmt...) assert_cmp(uintmax_t, a, b, <, \ - >=, "ju", fmt) -#define assert_ju_le(a, b, fmt...) assert_cmp(uintmax_t, a, b, <=, \ - >, "ju", fmt) -#define assert_ju_ge(a, b, fmt...) assert_cmp(uintmax_t, a, b, >=, \ - <, "ju", fmt) -#define assert_ju_gt(a, b, fmt...) assert_cmp(uintmax_t, a, b, >, \ - <=, "ju", fmt) - -#define assert_zd_eq(a, b, fmt...) assert_cmp(ssize_t, a, b, ==, \ - !=, "zd", fmt) -#define assert_zd_ne(a, b, fmt...) assert_cmp(ssize_t, a, b, !=, \ - ==, "zd", fmt) -#define assert_zd_lt(a, b, fmt...) assert_cmp(ssize_t, a, b, <, \ - >=, "zd", fmt) -#define assert_zd_le(a, b, fmt...) assert_cmp(ssize_t, a, b, <=, \ - >, "zd", fmt) -#define assert_zd_ge(a, b, fmt...) assert_cmp(ssize_t, a, b, >=, \ - <, "zd", fmt) -#define assert_zd_gt(a, b, fmt...) assert_cmp(ssize_t, a, b, >, \ - <=, "zd", fmt) - -#define assert_zu_eq(a, b, fmt...) assert_cmp(size_t, a, b, ==, \ - !=, "zu", fmt) -#define assert_zu_ne(a, b, fmt...) assert_cmp(size_t, a, b, !=, \ - ==, "zu", fmt) -#define assert_zu_lt(a, b, fmt...) assert_cmp(size_t, a, b, <, \ - >=, "zu", fmt) -#define assert_zu_le(a, b, fmt...) assert_cmp(size_t, a, b, <=, \ - >, "zu", fmt) -#define assert_zu_ge(a, b, fmt...) assert_cmp(size_t, a, b, >=, \ - <, "zu", fmt) -#define assert_zu_gt(a, b, fmt...) assert_cmp(size_t, a, b, >, \ - <=, "zu", fmt) - -#define assert_d32_eq(a, b, fmt...) assert_cmp(int32_t, a, b, ==, \ - !=, PRId32, fmt) -#define assert_d32_ne(a, b, fmt...) assert_cmp(int32_t, a, b, !=, \ - ==, PRId32, fmt) -#define assert_d32_lt(a, b, fmt...) assert_cmp(int32_t, a, b, <, \ - >=, PRId32, fmt) -#define assert_d32_le(a, b, fmt...) assert_cmp(int32_t, a, b, <=, \ - >, PRId32, fmt) -#define assert_d32_ge(a, b, fmt...) assert_cmp(int32_t, a, b, >=, \ - <, PRId32, fmt) -#define assert_d32_gt(a, b, fmt...) assert_cmp(int32_t, a, b, >, \ - <=, PRId32, fmt) - -#define assert_u32_eq(a, b, fmt...) assert_cmp(uint32_t, a, b, ==, \ - !=, PRIu32, fmt) -#define assert_u32_ne(a, b, fmt...) assert_cmp(uint32_t, a, b, !=, \ - ==, PRIu32, fmt) -#define assert_u32_lt(a, b, fmt...) assert_cmp(uint32_t, a, b, <, \ - >=, PRIu32, fmt) -#define assert_u32_le(a, b, fmt...) assert_cmp(uint32_t, a, b, <=, \ - >, PRIu32, fmt) -#define assert_u32_ge(a, b, fmt...) assert_cmp(uint32_t, a, b, >=, \ - <, PRIu32, fmt) -#define assert_u32_gt(a, b, fmt...) assert_cmp(uint32_t, a, b, >, \ - <=, PRIu32, fmt) - -#define assert_d64_eq(a, b, fmt...) assert_cmp(int64_t, a, b, ==, \ - !=, PRId64, fmt) -#define assert_d64_ne(a, b, fmt...) assert_cmp(int64_t, a, b, !=, \ - ==, PRId64, fmt) -#define assert_d64_lt(a, b, fmt...) assert_cmp(int64_t, a, b, <, \ - >=, PRId64, fmt) -#define assert_d64_le(a, b, fmt...) assert_cmp(int64_t, a, b, <=, \ - >, PRId64, fmt) -#define assert_d64_ge(a, b, fmt...) assert_cmp(int64_t, a, b, >=, \ - <, PRId64, fmt) -#define assert_d64_gt(a, b, fmt...) assert_cmp(int64_t, a, b, >, \ - <=, PRId64, fmt) - -#define assert_u64_eq(a, b, fmt...) assert_cmp(uint64_t, a, b, ==, \ - !=, PRIu64, fmt) -#define assert_u64_ne(a, b, fmt...) assert_cmp(uint64_t, a, b, !=, \ - ==, PRIu64, fmt) -#define assert_u64_lt(a, b, fmt...) assert_cmp(uint64_t, a, b, <, \ - >=, PRIu64, fmt) -#define assert_u64_le(a, b, fmt...) assert_cmp(uint64_t, a, b, <=, \ - >, PRIu64, fmt) -#define assert_u64_ge(a, b, fmt...) assert_cmp(uint64_t, a, b, >=, \ - <, PRIu64, fmt) -#define assert_u64_gt(a, b, fmt...) assert_cmp(uint64_t, a, b, >, \ - <=, PRIu64, fmt) - -#define assert_b_eq(a, b, fmt...) do { \ +#define assert_ptr_eq(a, b, ...) assert_cmp(void *, a, b, ==, \ + !=, "p", __VA_ARGS__) +#define assert_ptr_ne(a, b, ...) assert_cmp(void *, a, b, !=, \ + ==, "p", __VA_ARGS__) +#define assert_ptr_null(a, ...) assert_cmp(void *, a, NULL, ==, \ + !=, "p", __VA_ARGS__) +#define assert_ptr_not_null(a, ...) assert_cmp(void *, a, NULL, !=, \ + ==, "p", __VA_ARGS__) + +#define assert_c_eq(a, b, ...) assert_cmp(char, a, b, ==, !=, "c", __VA_ARGS__) +#define assert_c_ne(a, b, ...) assert_cmp(char, a, b, !=, ==, "c", __VA_ARGS__) +#define assert_c_lt(a, b, ...) assert_cmp(char, a, b, <, >=, "c", __VA_ARGS__) +#define assert_c_le(a, b, ...) assert_cmp(char, a, b, <=, >, "c", __VA_ARGS__) +#define assert_c_ge(a, b, ...) assert_cmp(char, a, b, >=, <, "c", __VA_ARGS__) +#define assert_c_gt(a, b, ...) assert_cmp(char, a, b, >, <=, "c", __VA_ARGS__) + +#define assert_x_eq(a, b, ...) assert_cmp(int, a, b, ==, !=, "#x", __VA_ARGS__) +#define assert_x_ne(a, b, ...) assert_cmp(int, a, b, !=, ==, "#x", __VA_ARGS__) +#define assert_x_lt(a, b, ...) assert_cmp(int, a, b, <, >=, "#x", __VA_ARGS__) +#define assert_x_le(a, b, ...) assert_cmp(int, a, b, <=, >, "#x", __VA_ARGS__) +#define assert_x_ge(a, b, ...) assert_cmp(int, a, b, >=, <, "#x", __VA_ARGS__) +#define assert_x_gt(a, b, ...) assert_cmp(int, a, b, >, <=, "#x", __VA_ARGS__) + +#define assert_d_eq(a, b, ...) assert_cmp(int, a, b, ==, !=, "d", __VA_ARGS__) +#define assert_d_ne(a, b, ...) assert_cmp(int, a, b, !=, ==, "d", __VA_ARGS__) +#define assert_d_lt(a, b, ...) assert_cmp(int, a, b, <, >=, "d", __VA_ARGS__) +#define assert_d_le(a, b, ...) assert_cmp(int, a, b, <=, >, "d", __VA_ARGS__) +#define assert_d_ge(a, b, ...) assert_cmp(int, a, b, >=, <, "d", __VA_ARGS__) +#define assert_d_gt(a, b, ...) assert_cmp(int, a, b, >, <=, "d", __VA_ARGS__) + +#define assert_u_eq(a, b, ...) assert_cmp(int, a, b, ==, !=, "u", __VA_ARGS__) +#define assert_u_ne(a, b, ...) assert_cmp(int, a, b, !=, ==, "u", __VA_ARGS__) +#define assert_u_lt(a, b, ...) assert_cmp(int, a, b, <, >=, "u", __VA_ARGS__) +#define assert_u_le(a, b, ...) assert_cmp(int, a, b, <=, >, "u", __VA_ARGS__) +#define assert_u_ge(a, b, ...) assert_cmp(int, a, b, >=, <, "u", __VA_ARGS__) +#define assert_u_gt(a, b, ...) assert_cmp(int, a, b, >, <=, "u", __VA_ARGS__) + +#define assert_ld_eq(a, b, ...) assert_cmp(long, a, b, ==, \ + !=, "ld", __VA_ARGS__) +#define assert_ld_ne(a, b, ...) assert_cmp(long, a, b, !=, \ + ==, "ld", __VA_ARGS__) +#define assert_ld_lt(a, b, ...) assert_cmp(long, a, b, <, \ + >=, "ld", __VA_ARGS__) +#define assert_ld_le(a, b, ...) assert_cmp(long, a, b, <=, \ + >, "ld", __VA_ARGS__) +#define assert_ld_ge(a, b, ...) assert_cmp(long, a, b, >=, \ + <, "ld", __VA_ARGS__) +#define assert_ld_gt(a, b, ...) assert_cmp(long, a, b, >, \ + <=, "ld", __VA_ARGS__) + +#define assert_lu_eq(a, b, ...) assert_cmp(unsigned long, \ + a, b, ==, !=, "lu", __VA_ARGS__) +#define assert_lu_ne(a, b, ...) assert_cmp(unsigned long, \ + a, b, !=, ==, "lu", __VA_ARGS__) +#define assert_lu_lt(a, b, ...) assert_cmp(unsigned long, \ + a, b, <, >=, "lu", __VA_ARGS__) +#define assert_lu_le(a, b, ...) assert_cmp(unsigned long, \ + a, b, <=, >, "lu", __VA_ARGS__) +#define assert_lu_ge(a, b, ...) assert_cmp(unsigned long, \ + a, b, >=, <, "lu", __VA_ARGS__) +#define assert_lu_gt(a, b, ...) assert_cmp(unsigned long, \ + a, b, >, <=, "lu", __VA_ARGS__) + +#define assert_qd_eq(a, b, ...) assert_cmp(long long, a, b, ==, \ + !=, "qd", __VA_ARGS__) +#define assert_qd_ne(a, b, ...) assert_cmp(long long, a, b, !=, \ + ==, "qd", __VA_ARGS__) +#define assert_qd_lt(a, b, ...) assert_cmp(long long, a, b, <, \ + >=, "qd", __VA_ARGS__) +#define assert_qd_le(a, b, ...) assert_cmp(long long, a, b, <=, \ + >, "qd", __VA_ARGS__) +#define assert_qd_ge(a, b, ...) assert_cmp(long long, a, b, >=, \ + <, "qd", __VA_ARGS__) +#define assert_qd_gt(a, b, ...) assert_cmp(long long, a, b, >, \ + <=, "qd", __VA_ARGS__) + +#define assert_qu_eq(a, b, ...) assert_cmp(unsigned long long, \ + a, b, ==, !=, "qu", __VA_ARGS__) +#define assert_qu_ne(a, b, ...) assert_cmp(unsigned long long, \ + a, b, !=, ==, "qu", __VA_ARGS__) +#define assert_qu_lt(a, b, ...) assert_cmp(unsigned long long, \ + a, b, <, >=, "qu", __VA_ARGS__) +#define assert_qu_le(a, b, ...) assert_cmp(unsigned long long, \ + a, b, <=, >, "qu", __VA_ARGS__) +#define assert_qu_ge(a, b, ...) assert_cmp(unsigned long long, \ + a, b, >=, <, "qu", __VA_ARGS__) +#define assert_qu_gt(a, b, ...) assert_cmp(unsigned long long, \ + a, b, >, <=, "qu", __VA_ARGS__) + +#define assert_jd_eq(a, b, ...) assert_cmp(intmax_t, a, b, ==, \ + !=, "jd", __VA_ARGS__) +#define assert_jd_ne(a, b, ...) assert_cmp(intmax_t, a, b, !=, \ + ==, "jd", __VA_ARGS__) +#define assert_jd_lt(a, b, ...) assert_cmp(intmax_t, a, b, <, \ + >=, "jd", __VA_ARGS__) +#define assert_jd_le(a, b, ...) assert_cmp(intmax_t, a, b, <=, \ + >, "jd", __VA_ARGS__) +#define assert_jd_ge(a, b, ...) assert_cmp(intmax_t, a, b, >=, \ + <, "jd", __VA_ARGS__) +#define assert_jd_gt(a, b, ...) assert_cmp(intmax_t, a, b, >, \ + <=, "jd", __VA_ARGS__) + +#define assert_ju_eq(a, b, ...) assert_cmp(uintmax_t, a, b, ==, \ + !=, "ju", __VA_ARGS__) +#define assert_ju_ne(a, b, ...) assert_cmp(uintmax_t, a, b, !=, \ + ==, "ju", __VA_ARGS__) +#define assert_ju_lt(a, b, ...) assert_cmp(uintmax_t, a, b, <, \ + >=, "ju", __VA_ARGS__) +#define assert_ju_le(a, b, ...) assert_cmp(uintmax_t, a, b, <=, \ + >, "ju", __VA_ARGS__) +#define assert_ju_ge(a, b, ...) assert_cmp(uintmax_t, a, b, >=, \ + <, "ju", __VA_ARGS__) +#define assert_ju_gt(a, b, ...) assert_cmp(uintmax_t, a, b, >, \ + <=, "ju", __VA_ARGS__) + +#define assert_zd_eq(a, b, ...) assert_cmp(ssize_t, a, b, ==, \ + !=, "zd", __VA_ARGS__) +#define assert_zd_ne(a, b, ...) assert_cmp(ssize_t, a, b, !=, \ + ==, "zd", __VA_ARGS__) +#define assert_zd_lt(a, b, ...) assert_cmp(ssize_t, a, b, <, \ + >=, "zd", __VA_ARGS__) +#define assert_zd_le(a, b, ...) assert_cmp(ssize_t, a, b, <=, \ + >, "zd", __VA_ARGS__) +#define assert_zd_ge(a, b, ...) assert_cmp(ssize_t, a, b, >=, \ + <, "zd", __VA_ARGS__) +#define assert_zd_gt(a, b, ...) assert_cmp(ssize_t, a, b, >, \ + <=, "zd", __VA_ARGS__) + +#define assert_zu_eq(a, b, ...) assert_cmp(size_t, a, b, ==, \ + !=, "zu", __VA_ARGS__) +#define assert_zu_ne(a, b, ...) assert_cmp(size_t, a, b, !=, \ + ==, "zu", __VA_ARGS__) +#define assert_zu_lt(a, b, ...) assert_cmp(size_t, a, b, <, \ + >=, "zu", __VA_ARGS__) +#define assert_zu_le(a, b, ...) assert_cmp(size_t, a, b, <=, \ + >, "zu", __VA_ARGS__) +#define assert_zu_ge(a, b, ...) assert_cmp(size_t, a, b, >=, \ + <, "zu", __VA_ARGS__) +#define assert_zu_gt(a, b, ...) assert_cmp(size_t, a, b, >, \ + <=, "zu", __VA_ARGS__) + +#define assert_d32_eq(a, b, ...) assert_cmp(int32_t, a, b, ==, \ + !=, PRId32, __VA_ARGS__) +#define assert_d32_ne(a, b, ...) assert_cmp(int32_t, a, b, !=, \ + ==, PRId32, __VA_ARGS__) +#define assert_d32_lt(a, b, ...) assert_cmp(int32_t, a, b, <, \ + >=, PRId32, __VA_ARGS__) +#define assert_d32_le(a, b, ...) assert_cmp(int32_t, a, b, <=, \ + >, PRId32, __VA_ARGS__) +#define assert_d32_ge(a, b, ...) assert_cmp(int32_t, a, b, >=, \ + <, PRId32, __VA_ARGS__) +#define assert_d32_gt(a, b, ...) assert_cmp(int32_t, a, b, >, \ + <=, PRId32, __VA_ARGS__) + +#define assert_u32_eq(a, b, ...) assert_cmp(uint32_t, a, b, ==, \ + !=, PRIu32, __VA_ARGS__) +#define assert_u32_ne(a, b, ...) assert_cmp(uint32_t, a, b, !=, \ + ==, PRIu32, __VA_ARGS__) +#define assert_u32_lt(a, b, ...) assert_cmp(uint32_t, a, b, <, \ + >=, PRIu32, __VA_ARGS__) +#define assert_u32_le(a, b, ...) assert_cmp(uint32_t, a, b, <=, \ + >, PRIu32, __VA_ARGS__) +#define assert_u32_ge(a, b, ...) assert_cmp(uint32_t, a, b, >=, \ + <, PRIu32, __VA_ARGS__) +#define assert_u32_gt(a, b, ...) assert_cmp(uint32_t, a, b, >, \ + <=, PRIu32, __VA_ARGS__) + +#define assert_d64_eq(a, b, ...) assert_cmp(int64_t, a, b, ==, \ + !=, PRId64, __VA_ARGS__) +#define assert_d64_ne(a, b, ...) assert_cmp(int64_t, a, b, !=, \ + ==, PRId64, __VA_ARGS__) +#define assert_d64_lt(a, b, ...) assert_cmp(int64_t, a, b, <, \ + >=, PRId64, __VA_ARGS__) +#define assert_d64_le(a, b, ...) assert_cmp(int64_t, a, b, <=, \ + >, PRId64, __VA_ARGS__) +#define assert_d64_ge(a, b, ...) assert_cmp(int64_t, a, b, >=, \ + <, PRId64, __VA_ARGS__) +#define assert_d64_gt(a, b, ...) assert_cmp(int64_t, a, b, >, \ + <=, PRId64, __VA_ARGS__) + +#define assert_u64_eq(a, b, ...) assert_cmp(uint64_t, a, b, ==, \ + !=, PRIu64, __VA_ARGS__) +#define assert_u64_ne(a, b, ...) assert_cmp(uint64_t, a, b, !=, \ + ==, PRIu64, __VA_ARGS__) +#define assert_u64_lt(a, b, ...) assert_cmp(uint64_t, a, b, <, \ + >=, PRIu64, __VA_ARGS__) +#define assert_u64_le(a, b, ...) assert_cmp(uint64_t, a, b, <=, \ + >, PRIu64, __VA_ARGS__) +#define assert_u64_ge(a, b, ...) assert_cmp(uint64_t, a, b, >=, \ + <, PRIu64, __VA_ARGS__) +#define assert_u64_gt(a, b, ...) assert_cmp(uint64_t, a, b, >, \ + <=, PRIu64, __VA_ARGS__) + +#define assert_b_eq(a, b, ...) do { \ bool a_ = (a); \ bool b_ = (b); \ if (!(a_ == b_)) { \ @@ -222,11 +222,11 @@ __func__, __FILE__, __LINE__, \ #a, #b, a_ ? "true" : "false", \ b_ ? "true" : "false"); \ - malloc_snprintf(message, sizeof(message), fmt); \ + malloc_snprintf(message, sizeof(message), __VA_ARGS__); \ p_test_fail(prefix, message); \ } \ } while (0) -#define assert_b_ne(a, b, fmt...) do { \ +#define assert_b_ne(a, b, ...) do { \ bool a_ = (a); \ bool b_ = (b); \ if (!(a_ != b_)) { \ @@ -238,14 +238,14 @@ __func__, __FILE__, __LINE__, \ #a, #b, a_ ? "true" : "false", \ b_ ? "true" : "false"); \ - malloc_snprintf(message, sizeof(message), fmt); \ + malloc_snprintf(message, sizeof(message), __VA_ARGS__); \ p_test_fail(prefix, message); \ } \ } while (0) -#define assert_true(a, fmt...) assert_b_eq(a, true, fmt) -#define assert_false(a, fmt...) assert_b_eq(a, false, fmt) +#define assert_true(a, ...) assert_b_eq(a, true, __VA_ARGS__) +#define assert_false(a, ...) assert_b_eq(a, false, __VA_ARGS__) -#define assert_str_eq(a, b, fmt...) do { \ +#define assert_str_eq(a, b, ...) do { \ if (strcmp((a), (b))) { \ char prefix[ASSERT_BUFSIZE]; \ char message[ASSERT_BUFSIZE]; \ @@ -254,11 +254,11 @@ "(%s) same as (%s) --> " \ "\"%s\" differs from \"%s\": ", \ __func__, __FILE__, __LINE__, #a, #b, a, b); \ - malloc_snprintf(message, sizeof(message), fmt); \ + malloc_snprintf(message, sizeof(message), __VA_ARGS__); \ p_test_fail(prefix, message); \ } \ } while (0) -#define assert_str_ne(a, b, fmt...) do { \ +#define assert_str_ne(a, b, ...) do { \ if (!strcmp((a), (b))) { \ char prefix[ASSERT_BUFSIZE]; \ char message[ASSERT_BUFSIZE]; \ @@ -267,18 +267,18 @@ "(%s) differs from (%s) --> " \ "\"%s\" same as \"%s\": ", \ __func__, __FILE__, __LINE__, #a, #b, a, b); \ - malloc_snprintf(message, sizeof(message), fmt); \ + malloc_snprintf(message, sizeof(message), __VA_ARGS__); \ p_test_fail(prefix, message); \ } \ } while (0) -#define assert_not_reached(fmt...) do { \ +#define assert_not_reached(...) do { \ char prefix[ASSERT_BUFSIZE]; \ char message[ASSERT_BUFSIZE]; \ malloc_snprintf(prefix, sizeof(prefix), \ "%s:%s:%d: Unreachable code reached: ", \ __func__, __FILE__, __LINE__); \ - malloc_snprintf(message, sizeof(message), fmt); \ + malloc_snprintf(message, sizeof(message), __VA_ARGS__); \ p_test_fail(prefix, message); \ } while (0) @@ -308,8 +308,12 @@ label_test_end: \ p_test_fini(); \ } -#define test(tests...) \ - p_test(tests, NULL) +#define test(...) \ + p_test(__VA_ARGS__, NULL) + +#define test_not_init(...) \ + p_test_not_init(__VA_ARGS__, NULL) + #define test_skip_if(e) do { \ if (e) { \ @@ -323,7 +327,8 @@ void test_skip(const char *format, ...) JEMALLOC_ATTR(format(printf, 1, 2)); void test_fail(const char *format, ...) JEMALLOC_ATTR(format(printf, 1, 2)); /* For private use by macros. */ -test_status_t p_test(test_t* t, ...); +test_status_t p_test(test_t *t, ...); +test_status_t p_test_not_init(test_t *t, ...); void p_test_init(const char *name); void p_test_fini(void); void p_test_fail(const char *prefix, const char *message); diff --git a/src/jemalloc/test/integration/MALLOCX_ARENA.c b/src/jemalloc/test/integration/MALLOCX_ARENA.c index 71cf6f255e84fddf78a753c63ed7ffc9fe0b8998..88623fd28bc5c03698534aeeca30fc3788d11135 100644 --- a/src/jemalloc/test/integration/MALLOCX_ARENA.c +++ b/src/jemalloc/test/integration/MALLOCX_ARENA.c @@ -2,6 +2,14 @@ #define NTHREADS 10 +static bool have_dss = +#ifdef JEMALLOC_DSS + true +#else + false +#endif + ; + void * thd_start(void *arg) { @@ -11,20 +19,23 @@ thd_start(void *arg) size_t sz; sz = sizeof(arena_ind); - assert_d_eq(mallctl("arenas.extend", &arena_ind, &sz, NULL, 0), 0, - "Error in arenas.extend"); + assert_d_eq(mallctl("pool.0.arenas.extend", &arena_ind, &sz, NULL, 0), 0, + "Error in pool.0.arenas.extend"); if (thread_ind % 4 != 3) { - size_t mib[3]; + size_t mib[5]; size_t miblen = sizeof(mib) / sizeof(size_t); const char *dss_precs[] = {"disabled", "primary", "secondary"}; - const char *dss = dss_precs[thread_ind % - (sizeof(dss_precs)/sizeof(char*))]; - assert_d_eq(mallctlnametomib("arena.0.dss", mib, &miblen), 0, + unsigned prec_ind = thread_ind % + (sizeof(dss_precs)/sizeof(char*)); + const char *dss = dss_precs[prec_ind]; + int expected_err = (have_dss || prec_ind == 0) ? 0 : EFAULT; + assert_d_eq(mallctlnametomib("pool.0.arena.0.dss", mib, &miblen), 0, "Error in mallctlnametomib()"); - mib[1] = arena_ind; + mib[3] = arena_ind; assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, (void *)&dss, - sizeof(const char *)), 0, "Error in mallctlbymib()"); + sizeof(const char *)), expected_err, + "Error in mallctlbymib()"); } p = mallocx(1, MALLOCX_ARENA(arena_ind)); @@ -34,7 +45,7 @@ thd_start(void *arg) return (NULL); } -TEST_BEGIN(test_ALLOCM_ARENA) +TEST_BEGIN(test_MALLOCX_ARENA) { thd_t thds[NTHREADS]; unsigned i; @@ -54,5 +65,5 @@ main(void) { return (test( - test_ALLOCM_ARENA)); + test_MALLOCX_ARENA)); } diff --git a/src/jemalloc/test/integration/chunk.c b/src/jemalloc/test/integration/chunk.c new file mode 100644 index 0000000000000000000000000000000000000000..1ed0954a0938b53e7cf0bf440d4adbb883648493 --- /dev/null +++ b/src/jemalloc/test/integration/chunk.c @@ -0,0 +1,58 @@ +#include "test/jemalloc_test.h" + +chunk_alloc_t *old_alloc; +chunk_dalloc_t *old_dalloc; + +bool +chunk_dalloc(void *chunk, size_t size, unsigned arena_ind, pool_t *pool) +{ + + return (old_dalloc(chunk, size, arena_ind, pool)); +} + +void * +chunk_alloc(size_t size, size_t alignment, bool *zero, unsigned arena_ind, pool_t *pool) +{ + + return (old_alloc(size, alignment, zero, arena_ind, pool)); +} + +TEST_BEGIN(test_chunk) +{ + void *p; + chunk_alloc_t *new_alloc; + chunk_dalloc_t *new_dalloc; + size_t old_size, new_size; + + new_alloc = chunk_alloc; + new_dalloc = chunk_dalloc; + old_size = sizeof(chunk_alloc_t *); + new_size = sizeof(chunk_alloc_t *); + + assert_d_eq(mallctl("pool.0.arena.0.chunk.alloc", &old_alloc, + &old_size, &new_alloc, new_size), 0, + "Unexpected alloc error"); + assert_ptr_ne(old_alloc, new_alloc, + "Unexpected alloc error"); + assert_d_eq(mallctl("pool.0.arena.0.chunk.dalloc", &old_dalloc, &old_size, + &new_dalloc, new_size), 0, "Unexpected dalloc error"); + assert_ptr_ne(old_dalloc, new_dalloc, "Unexpected dalloc error"); + + p = mallocx(42, 0); + assert_ptr_ne(p, NULL, "Unexpected alloc error"); + free(p); + + assert_d_eq(mallctl("pool.0.arena.0.chunk.alloc", NULL, + NULL, &old_alloc, old_size), 0, + "Unexpected alloc error"); + assert_d_eq(mallctl("pool.0.arena.0.chunk.dalloc", NULL, NULL, &old_dalloc, + old_size), 0, "Unexpected dalloc error"); +} +TEST_END + +int +main(void) +{ + + return (test(test_chunk)); +} diff --git a/src/jemalloc/test/integration/rallocx.c b/src/jemalloc/test/integration/rallocx.c index ee21aedff70ef2fde48b1e7a50238e2c9bce99e7..b69807298c0703205dcb21d260672c0d24371c42 100644 --- a/src/jemalloc/test/integration/rallocx.c +++ b/src/jemalloc/test/integration/rallocx.c @@ -95,7 +95,8 @@ TEST_BEGIN(test_zero) "Expected zeroed memory"); } if (psz != qsz) { - memset(q+psz, FILL_BYTE, qsz-psz); + memset((void *)((uintptr_t)q+psz), FILL_BYTE, + qsz-psz); psz = qsz; } p = q; @@ -159,8 +160,9 @@ TEST_BEGIN(test_lg_align_and_zero) } else { assert_false(validate_fill(q, 0, 0, MAX_VALIDATE), "Expected zeroed memory"); - assert_false(validate_fill(q+sz-MAX_VALIDATE, 0, 0, - MAX_VALIDATE), "Expected zeroed memory"); + assert_false(validate_fill( + (void *)((uintptr_t)q+sz-MAX_VALIDATE), + 0, 0, MAX_VALIDATE), "Expected zeroed memory"); } p = q; } diff --git a/src/jemalloc/test/integration/thread_arena.c b/src/jemalloc/test/integration/thread_arena.c index 67be5351335078baa5074f8bde0f553da29d093a..c43542dfd48ef474ad70e0518bf61e452d9cc7c7 100644 --- a/src/jemalloc/test/integration/thread_arena.c +++ b/src/jemalloc/test/integration/thread_arena.c @@ -16,7 +16,7 @@ thd_start(void *arg) free(p); size = sizeof(arena_ind); - if ((err = mallctl("thread.arena", &arena_ind, &size, &main_arena_ind, + if ((err = mallctl("thread.pool.0.arena", &arena_ind, &size, &main_arena_ind, sizeof(main_arena_ind)))) { char buf[BUFERROR_BUF]; @@ -25,7 +25,7 @@ thd_start(void *arg) } size = sizeof(arena_ind); - if ((err = mallctl("thread.arena", &arena_ind, &size, NULL, 0))) { + if ((err = mallctl("thread.pool.0.arena", &arena_ind, &size, NULL, 0))) { char buf[BUFERROR_BUF]; buferror(err, buf, sizeof(buf)); @@ -50,7 +50,7 @@ TEST_BEGIN(test_thread_arena) assert_ptr_not_null(p, "Error in malloc()"); size = sizeof(arena_ind); - if ((err = mallctl("thread.arena", &arena_ind, &size, NULL, 0))) { + if ((err = mallctl("thread.pool.0.arena", &arena_ind, &size, NULL, 0))) { char buf[BUFERROR_BUF]; buferror(err, buf, sizeof(buf)); diff --git a/src/jemalloc/test/src/SFMT.c b/src/jemalloc/test/src/SFMT.c index e6f8deecb37808a83c2093ceb1d8e158af652592..22a5ac554b1cb2b663768a8ab5f9cdcf544a5c5a 100644 --- a/src/jemalloc/test/src/SFMT.c +++ b/src/jemalloc/test/src/SFMT.c @@ -511,7 +511,7 @@ uint64_t gen_rand64(sfmt_t *ctx) { uint64_t gen_rand64_range(sfmt_t *ctx, uint64_t limit) { uint64_t ret, above; - above = 0xffffffffffffffffLLU - (0xffffffffffffffffLLU % limit); + above = KQU(0xffffffffffffffff) - (KQU(0xffffffffffffffff) % limit); while (1) { ret = gen_rand64(ctx); if (ret < above) { diff --git a/src/jemalloc/test/src/mtx.c b/src/jemalloc/test/src/mtx.c index 41b95d59de80fc4d080effd5417aad4a3d464646..73bd02f6df11c0436c6fa1a82d386f7ca1ae23ac 100644 --- a/src/jemalloc/test/src/mtx.c +++ b/src/jemalloc/test/src/mtx.c @@ -1,5 +1,9 @@ #include "test/jemalloc_test.h" +#ifndef _CRT_SPINCOUNT +#define _CRT_SPINCOUNT 4000 +#endif + bool mtx_init(mtx_t *mtx) { diff --git a/src/jemalloc/test/src/test.c b/src/jemalloc/test/src/test.c index 528d858317a1dc3e794a2b39dfbffa7d5fe98d74..0dd2f69bd327e08f70d2ad8bede295141d4ab3bf 100644 --- a/src/jemalloc/test/src/test.c +++ b/src/jemalloc/test/src/test.c @@ -61,13 +61,52 @@ p_test_fini(void) } test_status_t -p_test(test_t* t, ...) +p_test(test_t *t, ...) { - test_status_t ret = test_status_pass; + test_status_t ret; va_list ap; + /* + * Make sure initialization occurs prior to running tests. Tests are + * special because they may use internal facilities prior to triggering + * initialization as a side effect of calling into the public API. This + * is a final safety that works even if jemalloc_constructor() doesn't + * run, as for MSVC builds. + */ + if (nallocx(1, 0) == 0) { + malloc_printf("Initialization error"); + return (test_status_fail); + } + + ret = test_status_pass; + va_start(ap, t); + for (; t != NULL; t = va_arg(ap, test_t *)) { + t(); + if (test_status > ret) + ret = test_status; + } + va_end(ap); + + malloc_printf("--- %s: %u/%u, %s: %u/%u, %s: %u/%u ---\n", + test_status_string(test_status_pass), + test_counts[test_status_pass], test_count, + test_status_string(test_status_skip), + test_counts[test_status_skip], test_count, + test_status_string(test_status_fail), + test_counts[test_status_fail], test_count); + + return (ret); +} + +test_status_t +p_test_not_init(test_t *t, ...) +{ + test_status_t ret; + va_list ap; + + ret = test_status_pass; va_start(ap, t); - for (; t != NULL; t = va_arg(ap, test_t*)) { + for (; t != NULL; t = va_arg(ap, test_t *)) { t(); if (test_status > ret) ret = test_status; diff --git a/src/jemalloc/test/src/thd.c b/src/jemalloc/test/src/thd.c index 233242a161e246cb31173ca936bf265ab6a0bd9b..c9d0065869b3275b77d63ffd3f9afe3fc53b2adf 100644 --- a/src/jemalloc/test/src/thd.c +++ b/src/jemalloc/test/src/thd.c @@ -14,7 +14,11 @@ void thd_join(thd_t thd, void **ret) { - WaitForSingleObject(thd, INFINITE); + if (WaitForSingleObject(thd, INFINITE) == WAIT_OBJECT_0 && ret) { + DWORD exit_code; + GetExitCodeThread(thd, (LPDWORD) &exit_code); + *ret = (void *)(uintptr_t)exit_code; + } } #else diff --git a/src/jemalloc/test/unit/SFMT.c b/src/jemalloc/test/unit/SFMT.c index c57bd68df3d887a0bb95c65ecd5f9e6b0b945f16..88b31f6efdb8f70fd24a7d6ba736a66debb693e2 100644 --- a/src/jemalloc/test/unit/SFMT.c +++ b/src/jemalloc/test/unit/SFMT.c @@ -445,1008 +445,1008 @@ static const uint32_t init_by_array_32_expected[] = { 2750138839U, 3518055702U, 733072558U, 4169325400U, 788493625U }; static const uint64_t init_gen_rand_64_expected[] = { - QU(16924766246869039260LLU), QU( 8201438687333352714LLU), - QU( 2265290287015001750LLU), QU(18397264611805473832LLU), - QU( 3375255223302384358LLU), QU( 6345559975416828796LLU), - QU(18229739242790328073LLU), QU( 7596792742098800905LLU), - QU( 255338647169685981LLU), QU( 2052747240048610300LLU), - QU(18328151576097299343LLU), QU(12472905421133796567LLU), - QU(11315245349717600863LLU), QU(16594110197775871209LLU), - QU(15708751964632456450LLU), QU(10452031272054632535LLU), - QU(11097646720811454386LLU), QU( 4556090668445745441LLU), - QU(17116187693090663106LLU), QU(14931526836144510645LLU), - QU( 9190752218020552591LLU), QU( 9625800285771901401LLU), - QU(13995141077659972832LLU), QU( 5194209094927829625LLU), - QU( 4156788379151063303LLU), QU( 8523452593770139494LLU), - QU(14082382103049296727LLU), QU( 2462601863986088483LLU), - QU( 3030583461592840678LLU), QU( 5221622077872827681LLU), - QU( 3084210671228981236LLU), QU(13956758381389953823LLU), - QU(13503889856213423831LLU), QU(15696904024189836170LLU), - QU( 4612584152877036206LLU), QU( 6231135538447867881LLU), - QU(10172457294158869468LLU), QU( 6452258628466708150LLU), - QU(14044432824917330221LLU), QU( 370168364480044279LLU), - QU(10102144686427193359LLU), QU( 667870489994776076LLU), - QU( 2732271956925885858LLU), QU(18027788905977284151LLU), - QU(15009842788582923859LLU), QU( 7136357960180199542LLU), - QU(15901736243475578127LLU), QU(16951293785352615701LLU), - QU(10551492125243691632LLU), QU(17668869969146434804LLU), - QU(13646002971174390445LLU), QU( 9804471050759613248LLU), - QU( 5511670439655935493LLU), QU(18103342091070400926LLU), - QU(17224512747665137533LLU), QU(15534627482992618168LLU), - QU( 1423813266186582647LLU), QU(15821176807932930024LLU), - QU( 30323369733607156LLU), QU(11599382494723479403LLU), - QU( 653856076586810062LLU), QU( 3176437395144899659LLU), - QU(14028076268147963917LLU), QU(16156398271809666195LLU), - QU( 3166955484848201676LLU), QU( 5746805620136919390LLU), - QU(17297845208891256593LLU), QU(11691653183226428483LLU), - QU(17900026146506981577LLU), QU(15387382115755971042LLU), - QU(16923567681040845943LLU), QU( 8039057517199388606LLU), - QU(11748409241468629263LLU), QU( 794358245539076095LLU), - QU(13438501964693401242LLU), QU(14036803236515618962LLU), - QU( 5252311215205424721LLU), QU(17806589612915509081LLU), - QU( 6802767092397596006LLU), QU(14212120431184557140LLU), - QU( 1072951366761385712LLU), QU(13098491780722836296LLU), - QU( 9466676828710797353LLU), QU(12673056849042830081LLU), - QU(12763726623645357580LLU), QU(16468961652999309493LLU), - QU(15305979875636438926LLU), QU(17444713151223449734LLU), - QU( 5692214267627883674LLU), QU(13049589139196151505LLU), - QU( 880115207831670745LLU), QU( 1776529075789695498LLU), - QU(16695225897801466485LLU), QU(10666901778795346845LLU), - QU( 6164389346722833869LLU), QU( 2863817793264300475LLU), - QU( 9464049921886304754LLU), QU( 3993566636740015468LLU), - QU( 9983749692528514136LLU), QU(16375286075057755211LLU), - QU(16042643417005440820LLU), QU(11445419662923489877LLU), - QU( 7999038846885158836LLU), QU( 6721913661721511535LLU), - QU( 5363052654139357320LLU), QU( 1817788761173584205LLU), - QU(13290974386445856444LLU), QU( 4650350818937984680LLU), - QU( 8219183528102484836LLU), QU( 1569862923500819899LLU), - QU( 4189359732136641860LLU), QU(14202822961683148583LLU), - QU( 4457498315309429058LLU), QU(13089067387019074834LLU), - QU(11075517153328927293LLU), QU(10277016248336668389LLU), - QU( 7070509725324401122LLU), QU(17808892017780289380LLU), - QU(13143367339909287349LLU), QU( 1377743745360085151LLU), - QU( 5749341807421286485LLU), QU(14832814616770931325LLU), - QU( 7688820635324359492LLU), QU(10960474011539770045LLU), - QU( 81970066653179790LLU), QU(12619476072607878022LLU), - QU( 4419566616271201744LLU), QU(15147917311750568503LLU), - QU( 5549739182852706345LLU), QU( 7308198397975204770LLU), - QU(13580425496671289278LLU), QU(17070764785210130301LLU), - QU( 8202832846285604405LLU), QU( 6873046287640887249LLU), - QU( 6927424434308206114LLU), QU( 6139014645937224874LLU), - QU(10290373645978487639LLU), QU(15904261291701523804LLU), - QU( 9628743442057826883LLU), QU(18383429096255546714LLU), - QU( 4977413265753686967LLU), QU( 7714317492425012869LLU), - QU( 9025232586309926193LLU), QU(14627338359776709107LLU), - QU(14759849896467790763LLU), QU(10931129435864423252LLU), - QU( 4588456988775014359LLU), QU(10699388531797056724LLU), - QU( 468652268869238792LLU), QU( 5755943035328078086LLU), - QU( 2102437379988580216LLU), QU( 9986312786506674028LLU), - QU( 2654207180040945604LLU), QU( 8726634790559960062LLU), - QU( 100497234871808137LLU), QU( 2800137176951425819LLU), - QU( 6076627612918553487LLU), QU( 5780186919186152796LLU), - QU( 8179183595769929098LLU), QU( 6009426283716221169LLU), - QU( 2796662551397449358LLU), QU( 1756961367041986764LLU), - QU( 6972897917355606205LLU), QU(14524774345368968243LLU), - QU( 2773529684745706940LLU), QU( 4853632376213075959LLU), - QU( 4198177923731358102LLU), QU( 8271224913084139776LLU), - QU( 2741753121611092226LLU), QU(16782366145996731181LLU), - QU(15426125238972640790LLU), QU(13595497100671260342LLU), - QU( 3173531022836259898LLU), QU( 6573264560319511662LLU), - QU(18041111951511157441LLU), QU( 2351433581833135952LLU), - QU( 3113255578908173487LLU), QU( 1739371330877858784LLU), - QU(16046126562789165480LLU), QU( 8072101652214192925LLU), - QU(15267091584090664910LLU), QU( 9309579200403648940LLU), - QU( 5218892439752408722LLU), QU(14492477246004337115LLU), - QU(17431037586679770619LLU), QU( 7385248135963250480LLU), - QU( 9580144956565560660LLU), QU( 4919546228040008720LLU), - QU(15261542469145035584LLU), QU(18233297270822253102LLU), - QU( 5453248417992302857LLU), QU( 9309519155931460285LLU), - QU(10342813012345291756LLU), QU(15676085186784762381LLU), - QU(15912092950691300645LLU), QU( 9371053121499003195LLU), - QU( 9897186478226866746LLU), QU(14061858287188196327LLU), - QU( 122575971620788119LLU), QU(12146750969116317754LLU), - QU( 4438317272813245201LLU), QU( 8332576791009527119LLU), - QU(13907785691786542057LLU), QU(10374194887283287467LLU), - QU( 2098798755649059566LLU), QU( 3416235197748288894LLU), - QU( 8688269957320773484LLU), QU( 7503964602397371571LLU), - QU(16724977015147478236LLU), QU( 9461512855439858184LLU), - QU(13259049744534534727LLU), QU( 3583094952542899294LLU), - QU( 8764245731305528292LLU), QU(13240823595462088985LLU), - QU(13716141617617910448LLU), QU(18114969519935960955LLU), - QU( 2297553615798302206LLU), QU( 4585521442944663362LLU), - QU(17776858680630198686LLU), QU( 4685873229192163363LLU), - QU( 152558080671135627LLU), QU(15424900540842670088LLU), - QU(13229630297130024108LLU), QU(17530268788245718717LLU), - QU(16675633913065714144LLU), QU( 3158912717897568068LLU), - QU(15399132185380087288LLU), QU( 7401418744515677872LLU), - QU(13135412922344398535LLU), QU( 6385314346100509511LLU), - QU(13962867001134161139LLU), QU(10272780155442671999LLU), - QU(12894856086597769142LLU), QU(13340877795287554994LLU), - QU(12913630602094607396LLU), QU(12543167911119793857LLU), - QU(17343570372251873096LLU), QU(10959487764494150545LLU), - QU( 6966737953093821128LLU), QU(13780699135496988601LLU), - QU( 4405070719380142046LLU), QU(14923788365607284982LLU), - QU( 2869487678905148380LLU), QU( 6416272754197188403LLU), - QU(15017380475943612591LLU), QU( 1995636220918429487LLU), - QU( 3402016804620122716LLU), QU(15800188663407057080LLU), - QU(11362369990390932882LLU), QU(15262183501637986147LLU), - QU(10239175385387371494LLU), QU( 9352042420365748334LLU), - QU( 1682457034285119875LLU), QU( 1724710651376289644LLU), - QU( 2038157098893817966LLU), QU( 9897825558324608773LLU), - QU( 1477666236519164736LLU), QU(16835397314511233640LLU), - QU(10370866327005346508LLU), QU(10157504370660621982LLU), - QU(12113904045335882069LLU), QU(13326444439742783008LLU), - QU(11302769043000765804LLU), QU(13594979923955228484LLU), - QU(11779351762613475968LLU), QU( 3786101619539298383LLU), - QU( 8021122969180846063LLU), QU(15745904401162500495LLU), - QU(10762168465993897267LLU), QU(13552058957896319026LLU), - QU(11200228655252462013LLU), QU( 5035370357337441226LLU), - QU( 7593918984545500013LLU), QU( 5418554918361528700LLU), - QU( 4858270799405446371LLU), QU( 9974659566876282544LLU), - QU(18227595922273957859LLU), QU( 2772778443635656220LLU), - QU(14285143053182085385LLU), QU( 9939700992429600469LLU), - QU(12756185904545598068LLU), QU( 2020783375367345262LLU), - QU( 57026775058331227LLU), QU( 950827867930065454LLU), - QU( 6602279670145371217LLU), QU( 2291171535443566929LLU), - QU( 5832380724425010313LLU), QU( 1220343904715982285LLU), - QU(17045542598598037633LLU), QU(15460481779702820971LLU), - QU(13948388779949365130LLU), QU(13975040175430829518LLU), - QU(17477538238425541763LLU), QU(11104663041851745725LLU), - QU(15860992957141157587LLU), QU(14529434633012950138LLU), - QU( 2504838019075394203LLU), QU( 7512113882611121886LLU), - QU( 4859973559980886617LLU), QU( 1258601555703250219LLU), - QU(15594548157514316394LLU), QU( 4516730171963773048LLU), - QU(11380103193905031983LLU), QU( 6809282239982353344LLU), - QU(18045256930420065002LLU), QU( 2453702683108791859LLU), - QU( 977214582986981460LLU), QU( 2006410402232713466LLU), - QU( 6192236267216378358LLU), QU( 3429468402195675253LLU), - QU(18146933153017348921LLU), QU(17369978576367231139LLU), - QU( 1246940717230386603LLU), QU(11335758870083327110LLU), - QU(14166488801730353682LLU), QU( 9008573127269635732LLU), - QU(10776025389820643815LLU), QU(15087605441903942962LLU), - QU( 1359542462712147922LLU), QU(13898874411226454206LLU), - QU(17911176066536804411LLU), QU( 9435590428600085274LLU), - QU( 294488509967864007LLU), QU( 8890111397567922046LLU), - QU( 7987823476034328778LLU), QU(13263827582440967651LLU), - QU( 7503774813106751573LLU), QU(14974747296185646837LLU), - QU( 8504765037032103375LLU), QU(17340303357444536213LLU), - QU( 7704610912964485743LLU), QU( 8107533670327205061LLU), - QU( 9062969835083315985LLU), QU(16968963142126734184LLU), - QU(12958041214190810180LLU), QU( 2720170147759570200LLU), - QU( 2986358963942189566LLU), QU(14884226322219356580LLU), - QU( 286224325144368520LLU), QU(11313800433154279797LLU), - QU(18366849528439673248LLU), QU(17899725929482368789LLU), - QU( 3730004284609106799LLU), QU( 1654474302052767205LLU), - QU( 5006698007047077032LLU), QU( 8196893913601182838LLU), - QU(15214541774425211640LLU), QU(17391346045606626073LLU), - QU( 8369003584076969089LLU), QU( 3939046733368550293LLU), - QU(10178639720308707785LLU), QU( 2180248669304388697LLU), - QU( 62894391300126322LLU), QU( 9205708961736223191LLU), - QU( 6837431058165360438LLU), QU( 3150743890848308214LLU), - QU(17849330658111464583LLU), QU(12214815643135450865LLU), - QU(13410713840519603402LLU), QU( 3200778126692046802LLU), - QU(13354780043041779313LLU), QU( 800850022756886036LLU), - QU(15660052933953067433LLU), QU( 6572823544154375676LLU), - QU(11030281857015819266LLU), QU(12682241941471433835LLU), - QU(11654136407300274693LLU), QU( 4517795492388641109LLU), - QU( 9757017371504524244LLU), QU(17833043400781889277LLU), - QU(12685085201747792227LLU), QU(10408057728835019573LLU), - QU( 98370418513455221LLU), QU( 6732663555696848598LLU), - QU(13248530959948529780LLU), QU( 3530441401230622826LLU), - QU(18188251992895660615LLU), QU( 1847918354186383756LLU), - QU( 1127392190402660921LLU), QU(11293734643143819463LLU), - QU( 3015506344578682982LLU), QU(13852645444071153329LLU), - QU( 2121359659091349142LLU), QU( 1294604376116677694LLU), - QU( 5616576231286352318LLU), QU( 7112502442954235625LLU), - QU(11676228199551561689LLU), QU(12925182803007305359LLU), - QU( 7852375518160493082LLU), QU( 1136513130539296154LLU), - QU( 5636923900916593195LLU), QU( 3221077517612607747LLU), - QU(17784790465798152513LLU), QU( 3554210049056995938LLU), - QU(17476839685878225874LLU), QU( 3206836372585575732LLU), - QU( 2765333945644823430LLU), QU(10080070903718799528LLU), - QU( 5412370818878286353LLU), QU( 9689685887726257728LLU), - QU( 8236117509123533998LLU), QU( 1951139137165040214LLU), - QU( 4492205209227980349LLU), QU(16541291230861602967LLU), - QU( 1424371548301437940LLU), QU( 9117562079669206794LLU), - QU(14374681563251691625LLU), QU(13873164030199921303LLU), - QU( 6680317946770936731LLU), QU(15586334026918276214LLU), - QU(10896213950976109802LLU), QU( 9506261949596413689LLU), - QU( 9903949574308040616LLU), QU( 6038397344557204470LLU), - QU( 174601465422373648LLU), QU(15946141191338238030LLU), - QU(17142225620992044937LLU), QU( 7552030283784477064LLU), - QU( 2947372384532947997LLU), QU( 510797021688197711LLU), - QU( 4962499439249363461LLU), QU( 23770320158385357LLU), - QU( 959774499105138124LLU), QU( 1468396011518788276LLU), - QU( 2015698006852312308LLU), QU( 4149400718489980136LLU), - QU( 5992916099522371188LLU), QU(10819182935265531076LLU), - QU(16189787999192351131LLU), QU( 342833961790261950LLU), - QU(12470830319550495336LLU), QU(18128495041912812501LLU), - QU( 1193600899723524337LLU), QU( 9056793666590079770LLU), - QU( 2154021227041669041LLU), QU( 4963570213951235735LLU), - QU( 4865075960209211409LLU), QU( 2097724599039942963LLU), - QU( 2024080278583179845LLU), QU(11527054549196576736LLU), - QU(10650256084182390252LLU), QU( 4808408648695766755LLU), - QU( 1642839215013788844LLU), QU(10607187948250398390LLU), - QU( 7076868166085913508LLU), QU( 730522571106887032LLU), - QU(12500579240208524895LLU), QU( 4484390097311355324LLU), - QU(15145801330700623870LLU), QU( 8055827661392944028LLU), - QU( 5865092976832712268LLU), QU(15159212508053625143LLU), - QU( 3560964582876483341LLU), QU( 4070052741344438280LLU), - QU( 6032585709886855634LLU), QU(15643262320904604873LLU), - QU( 2565119772293371111LLU), QU( 318314293065348260LLU), - QU(15047458749141511872LLU), QU( 7772788389811528730LLU), - QU( 7081187494343801976LLU), QU( 6465136009467253947LLU), - QU(10425940692543362069LLU), QU( 554608190318339115LLU), - QU(14796699860302125214LLU), QU( 1638153134431111443LLU), - QU(10336967447052276248LLU), QU( 8412308070396592958LLU), - QU( 4004557277152051226LLU), QU( 8143598997278774834LLU), - QU(16413323996508783221LLU), QU(13139418758033994949LLU), - QU( 9772709138335006667LLU), QU( 2818167159287157659LLU), - QU(17091740573832523669LLU), QU(14629199013130751608LLU), - QU(18268322711500338185LLU), QU( 8290963415675493063LLU), - QU( 8830864907452542588LLU), QU( 1614839084637494849LLU), - QU(14855358500870422231LLU), QU( 3472996748392519937LLU), - QU(15317151166268877716LLU), QU( 5825895018698400362LLU), - QU(16730208429367544129LLU), QU(10481156578141202800LLU), - QU( 4746166512382823750LLU), QU(12720876014472464998LLU), - QU( 8825177124486735972LLU), QU(13733447296837467838LLU), - QU( 6412293741681359625LLU), QU( 8313213138756135033LLU), - QU(11421481194803712517LLU), QU( 7997007691544174032LLU), - QU( 6812963847917605930LLU), QU( 9683091901227558641LLU), - QU(14703594165860324713LLU), QU( 1775476144519618309LLU), - QU( 2724283288516469519LLU), QU( 717642555185856868LLU), - QU( 8736402192215092346LLU), QU(11878800336431381021LLU), - QU( 4348816066017061293LLU), QU( 6115112756583631307LLU), - QU( 9176597239667142976LLU), QU(12615622714894259204LLU), - QU(10283406711301385987LLU), QU( 5111762509485379420LLU), - QU( 3118290051198688449LLU), QU( 7345123071632232145LLU), - QU( 9176423451688682359LLU), QU( 4843865456157868971LLU), - QU(12008036363752566088LLU), QU(12058837181919397720LLU), - QU( 2145073958457347366LLU), QU( 1526504881672818067LLU), - QU( 3488830105567134848LLU), QU(13208362960674805143LLU), - QU( 4077549672899572192LLU), QU( 7770995684693818365LLU), - QU( 1398532341546313593LLU), QU(12711859908703927840LLU), - QU( 1417561172594446813LLU), QU(17045191024194170604LLU), - QU( 4101933177604931713LLU), QU(14708428834203480320LLU), - QU(17447509264469407724LLU), QU(14314821973983434255LLU), - QU(17990472271061617265LLU), QU( 5087756685841673942LLU), - QU(12797820586893859939LLU), QU( 1778128952671092879LLU), - QU( 3535918530508665898LLU), QU( 9035729701042481301LLU), - QU(14808661568277079962LLU), QU(14587345077537747914LLU), - QU(11920080002323122708LLU), QU( 6426515805197278753LLU), - QU( 3295612216725984831LLU), QU(11040722532100876120LLU), - QU(12305952936387598754LLU), QU(16097391899742004253LLU), - QU( 4908537335606182208LLU), QU(12446674552196795504LLU), - QU(16010497855816895177LLU), QU( 9194378874788615551LLU), - QU( 3382957529567613384LLU), QU( 5154647600754974077LLU), - QU( 9801822865328396141LLU), QU( 9023662173919288143LLU), - QU(17623115353825147868LLU), QU( 8238115767443015816LLU), - QU(15811444159859002560LLU), QU( 9085612528904059661LLU), - QU( 6888601089398614254LLU), QU( 258252992894160189LLU), - QU( 6704363880792428622LLU), QU( 6114966032147235763LLU), - QU(11075393882690261875LLU), QU( 8797664238933620407LLU), - QU( 5901892006476726920LLU), QU( 5309780159285518958LLU), - QU(14940808387240817367LLU), QU(14642032021449656698LLU), - QU( 9808256672068504139LLU), QU( 3670135111380607658LLU), - QU(11211211097845960152LLU), QU( 1474304506716695808LLU), - QU(15843166204506876239LLU), QU( 7661051252471780561LLU), - QU(10170905502249418476LLU), QU( 7801416045582028589LLU), - QU( 2763981484737053050LLU), QU( 9491377905499253054LLU), - QU(16201395896336915095LLU), QU( 9256513756442782198LLU), - QU( 5411283157972456034LLU), QU( 5059433122288321676LLU), - QU( 4327408006721123357LLU), QU( 9278544078834433377LLU), - QU( 7601527110882281612LLU), QU(11848295896975505251LLU), - QU(12096998801094735560LLU), QU(14773480339823506413LLU), - QU(15586227433895802149LLU), QU(12786541257830242872LLU), - QU( 6904692985140503067LLU), QU( 5309011515263103959LLU), - QU(12105257191179371066LLU), QU(14654380212442225037LLU), - QU( 2556774974190695009LLU), QU( 4461297399927600261LLU), - QU(14888225660915118646LLU), QU(14915459341148291824LLU), - QU( 2738802166252327631LLU), QU( 6047155789239131512LLU), - QU(12920545353217010338LLU), QU(10697617257007840205LLU), - QU( 2751585253158203504LLU), QU(13252729159780047496LLU), - QU(14700326134672815469LLU), QU(14082527904374600529LLU), - QU(16852962273496542070LLU), QU(17446675504235853907LLU), - QU(15019600398527572311LLU), QU(12312781346344081551LLU), - QU(14524667935039810450LLU), QU( 5634005663377195738LLU), - QU(11375574739525000569LLU), QU( 2423665396433260040LLU), - QU( 5222836914796015410LLU), QU( 4397666386492647387LLU), - QU( 4619294441691707638LLU), QU( 665088602354770716LLU), - QU(13246495665281593610LLU), QU( 6564144270549729409LLU), - QU(10223216188145661688LLU), QU( 3961556907299230585LLU), - QU(11543262515492439914LLU), QU(16118031437285993790LLU), - QU( 7143417964520166465LLU), QU(13295053515909486772LLU), - QU( 40434666004899675LLU), QU(17127804194038347164LLU), - QU( 8599165966560586269LLU), QU( 8214016749011284903LLU), - QU(13725130352140465239LLU), QU( 5467254474431726291LLU), - QU( 7748584297438219877LLU), QU(16933551114829772472LLU), - QU( 2169618439506799400LLU), QU( 2169787627665113463LLU), - QU(17314493571267943764LLU), QU(18053575102911354912LLU), - QU(11928303275378476973LLU), QU(11593850925061715550LLU), - QU(17782269923473589362LLU), QU( 3280235307704747039LLU), - QU( 6145343578598685149LLU), QU(17080117031114086090LLU), - QU(18066839902983594755LLU), QU( 6517508430331020706LLU), - QU( 8092908893950411541LLU), QU(12558378233386153732LLU), - QU( 4476532167973132976LLU), QU(16081642430367025016LLU), - QU( 4233154094369139361LLU), QU( 8693630486693161027LLU), - QU(11244959343027742285LLU), QU(12273503967768513508LLU), - QU(14108978636385284876LLU), QU( 7242414665378826984LLU), - QU( 6561316938846562432LLU), QU( 8601038474994665795LLU), - QU(17532942353612365904LLU), QU(17940076637020912186LLU), - QU( 7340260368823171304LLU), QU( 7061807613916067905LLU), - QU(10561734935039519326LLU), QU(17990796503724650862LLU), - QU( 6208732943911827159LLU), QU( 359077562804090617LLU), - QU(14177751537784403113LLU), QU(10659599444915362902LLU), - QU(15081727220615085833LLU), QU(13417573895659757486LLU), - QU(15513842342017811524LLU), QU(11814141516204288231LLU), - QU( 1827312513875101814LLU), QU( 2804611699894603103LLU), - QU(17116500469975602763LLU), QU(12270191815211952087LLU), - QU(12256358467786024988LLU), QU(18435021722453971267LLU), - QU( 671330264390865618LLU), QU( 476504300460286050LLU), - QU(16465470901027093441LLU), QU( 4047724406247136402LLU), - QU( 1322305451411883346LLU), QU( 1388308688834322280LLU), - QU( 7303989085269758176LLU), QU( 9323792664765233642LLU), - QU( 4542762575316368936LLU), QU(17342696132794337618LLU), - QU( 4588025054768498379LLU), QU(13415475057390330804LLU), - QU(17880279491733405570LLU), QU(10610553400618620353LLU), - QU( 3180842072658960139LLU), QU(13002966655454270120LLU), - QU( 1665301181064982826LLU), QU( 7083673946791258979LLU), - QU( 190522247122496820LLU), QU(17388280237250677740LLU), - QU( 8430770379923642945LLU), QU(12987180971921668584LLU), - QU( 2311086108365390642LLU), QU( 2870984383579822345LLU), - QU(14014682609164653318LLU), QU(14467187293062251484LLU), - QU( 192186361147413298LLU), QU(15171951713531796524LLU), - QU( 9900305495015948728LLU), QU(17958004775615466344LLU), - QU(14346380954498606514LLU), QU(18040047357617407096LLU), - QU( 5035237584833424532LLU), QU(15089555460613972287LLU), - QU( 4131411873749729831LLU), QU( 1329013581168250330LLU), - QU(10095353333051193949LLU), QU(10749518561022462716LLU), - QU( 9050611429810755847LLU), QU(15022028840236655649LLU), - QU( 8775554279239748298LLU), QU(13105754025489230502LLU), - QU(15471300118574167585LLU), QU( 89864764002355628LLU), - QU( 8776416323420466637LLU), QU( 5280258630612040891LLU), - QU( 2719174488591862912LLU), QU( 7599309137399661994LLU), - QU(15012887256778039979LLU), QU(14062981725630928925LLU), - QU(12038536286991689603LLU), QU( 7089756544681775245LLU), - QU(10376661532744718039LLU), QU( 1265198725901533130LLU), - QU(13807996727081142408LLU), QU( 2935019626765036403LLU), - QU( 7651672460680700141LLU), QU( 3644093016200370795LLU), - QU( 2840982578090080674LLU), QU(17956262740157449201LLU), - QU(18267979450492880548LLU), QU(11799503659796848070LLU), - QU( 9942537025669672388LLU), QU(11886606816406990297LLU), - QU( 5488594946437447576LLU), QU( 7226714353282744302LLU), - QU( 3784851653123877043LLU), QU( 878018453244803041LLU), - QU(12110022586268616085LLU), QU( 734072179404675123LLU), - QU(11869573627998248542LLU), QU( 469150421297783998LLU), - QU( 260151124912803804LLU), QU(11639179410120968649LLU), - QU( 9318165193840846253LLU), QU(12795671722734758075LLU), - QU(15318410297267253933LLU), QU( 691524703570062620LLU), - QU( 5837129010576994601LLU), QU(15045963859726941052LLU), - QU( 5850056944932238169LLU), QU(12017434144750943807LLU), - QU( 7447139064928956574LLU), QU( 3101711812658245019LLU), - QU(16052940704474982954LLU), QU(18195745945986994042LLU), - QU( 8932252132785575659LLU), QU(13390817488106794834LLU), - QU(11582771836502517453LLU), QU( 4964411326683611686LLU), - QU( 2195093981702694011LLU), QU(14145229538389675669LLU), - QU(16459605532062271798LLU), QU( 866316924816482864LLU), - QU( 4593041209937286377LLU), QU( 8415491391910972138LLU), - QU( 4171236715600528969LLU), QU(16637569303336782889LLU), - QU( 2002011073439212680LLU), QU(17695124661097601411LLU), - QU( 4627687053598611702LLU), QU( 7895831936020190403LLU), - QU( 8455951300917267802LLU), QU( 2923861649108534854LLU), - QU( 8344557563927786255LLU), QU( 6408671940373352556LLU), - QU(12210227354536675772LLU), QU(14294804157294222295LLU), - QU(10103022425071085127LLU), QU(10092959489504123771LLU), - QU( 6554774405376736268LLU), QU(12629917718410641774LLU), - QU( 6260933257596067126LLU), QU( 2460827021439369673LLU), - QU( 2541962996717103668LLU), QU( 597377203127351475LLU), - QU( 5316984203117315309LLU), QU( 4811211393563241961LLU), - QU(13119698597255811641LLU), QU( 8048691512862388981LLU), - QU(10216818971194073842LLU), QU( 4612229970165291764LLU), - QU(10000980798419974770LLU), QU( 6877640812402540687LLU), - QU( 1488727563290436992LLU), QU( 2227774069895697318LLU), - QU(11237754507523316593LLU), QU(13478948605382290972LLU), - QU( 1963583846976858124LLU), QU( 5512309205269276457LLU), - QU( 3972770164717652347LLU), QU( 3841751276198975037LLU), - QU(10283343042181903117LLU), QU( 8564001259792872199LLU), - QU(16472187244722489221LLU), QU( 8953493499268945921LLU), - QU( 3518747340357279580LLU), QU( 4003157546223963073LLU), - QU( 3270305958289814590LLU), QU( 3966704458129482496LLU), - QU( 8122141865926661939LLU), QU(14627734748099506653LLU), - QU(13064426990862560568LLU), QU( 2414079187889870829LLU), - QU( 5378461209354225306LLU), QU(10841985740128255566LLU), - QU( 538582442885401738LLU), QU( 7535089183482905946LLU), - QU(16117559957598879095LLU), QU( 8477890721414539741LLU), - QU( 1459127491209533386LLU), QU(17035126360733620462LLU), - QU( 8517668552872379126LLU), QU(10292151468337355014LLU), - QU(17081267732745344157LLU), QU(13751455337946087178LLU), - QU(14026945459523832966LLU), QU( 6653278775061723516LLU), - QU(10619085543856390441LLU), QU( 2196343631481122885LLU), - QU(10045966074702826136LLU), QU(10082317330452718282LLU), - QU( 5920859259504831242LLU), QU( 9951879073426540617LLU), - QU( 7074696649151414158LLU), QU(15808193543879464318LLU), - QU( 7385247772746953374LLU), QU( 3192003544283864292LLU), - QU(18153684490917593847LLU), QU(12423498260668568905LLU), - QU(10957758099756378169LLU), QU(11488762179911016040LLU), - QU( 2099931186465333782LLU), QU(11180979581250294432LLU), - QU( 8098916250668367933LLU), QU( 3529200436790763465LLU), - QU(12988418908674681745LLU), QU( 6147567275954808580LLU), - QU( 3207503344604030989LLU), QU(10761592604898615360LLU), - QU( 229854861031893504LLU), QU( 8809853962667144291LLU), - QU(13957364469005693860LLU), QU( 7634287665224495886LLU), - QU(12353487366976556874LLU), QU( 1134423796317152034LLU), - QU( 2088992471334107068LLU), QU( 7393372127190799698LLU), - QU( 1845367839871058391LLU), QU( 207922563987322884LLU), - QU(11960870813159944976LLU), QU(12182120053317317363LLU), - QU(17307358132571709283LLU), QU(13871081155552824936LLU), - QU(18304446751741566262LLU), QU( 7178705220184302849LLU), - QU(10929605677758824425LLU), QU(16446976977835806844LLU), - QU(13723874412159769044LLU), QU( 6942854352100915216LLU), - QU( 1726308474365729390LLU), QU( 2150078766445323155LLU), - QU(15345558947919656626LLU), QU(12145453828874527201LLU), - QU( 2054448620739726849LLU), QU( 2740102003352628137LLU), - QU(11294462163577610655LLU), QU( 756164283387413743LLU), - QU(17841144758438810880LLU), QU(10802406021185415861LLU), - QU( 8716455530476737846LLU), QU( 6321788834517649606LLU), - QU(14681322910577468426LLU), QU(17330043563884336387LLU), - QU(12701802180050071614LLU), QU(14695105111079727151LLU), - QU( 5112098511654172830LLU), QU( 4957505496794139973LLU), - QU( 8270979451952045982LLU), QU(12307685939199120969LLU), - QU(12425799408953443032LLU), QU( 8376410143634796588LLU), - QU(16621778679680060464LLU), QU( 3580497854566660073LLU), - QU( 1122515747803382416LLU), QU( 857664980960597599LLU), - QU( 6343640119895925918LLU), QU(12878473260854462891LLU), - QU(10036813920765722626LLU), QU(14451335468363173812LLU), - QU( 5476809692401102807LLU), QU(16442255173514366342LLU), - QU(13060203194757167104LLU), QU(14354124071243177715LLU), - QU(15961249405696125227LLU), QU(13703893649690872584LLU), - QU( 363907326340340064LLU), QU( 6247455540491754842LLU), - QU(12242249332757832361LLU), QU( 156065475679796717LLU), - QU( 9351116235749732355LLU), QU( 4590350628677701405LLU), - QU( 1671195940982350389LLU), QU(13501398458898451905LLU), - QU( 6526341991225002255LLU), QU( 1689782913778157592LLU), - QU( 7439222350869010334LLU), QU(13975150263226478308LLU), - QU(11411961169932682710LLU), QU(17204271834833847277LLU), - QU( 541534742544435367LLU), QU( 6591191931218949684LLU), - QU( 2645454775478232486LLU), QU( 4322857481256485321LLU), - QU( 8477416487553065110LLU), QU(12902505428548435048LLU), - QU( 971445777981341415LLU), QU(14995104682744976712LLU), - QU( 4243341648807158063LLU), QU( 8695061252721927661LLU), - QU( 5028202003270177222LLU), QU( 2289257340915567840LLU), - QU(13870416345121866007LLU), QU(13994481698072092233LLU), - QU( 6912785400753196481LLU), QU( 2278309315841980139LLU), - QU( 4329765449648304839LLU), QU( 5963108095785485298LLU), - QU( 4880024847478722478LLU), QU(16015608779890240947LLU), - QU( 1866679034261393544LLU), QU( 914821179919731519LLU), - QU( 9643404035648760131LLU), QU( 2418114953615593915LLU), - QU( 944756836073702374LLU), QU(15186388048737296834LLU), - QU( 7723355336128442206LLU), QU( 7500747479679599691LLU), - QU(18013961306453293634LLU), QU( 2315274808095756456LLU), - QU(13655308255424029566LLU), QU(17203800273561677098LLU), - QU( 1382158694422087756LLU), QU( 5090390250309588976LLU), - QU( 517170818384213989LLU), QU( 1612709252627729621LLU), - QU( 1330118955572449606LLU), QU( 300922478056709885LLU), - QU(18115693291289091987LLU), QU(13491407109725238321LLU), - QU(15293714633593827320LLU), QU( 5151539373053314504LLU), - QU( 5951523243743139207LLU), QU(14459112015249527975LLU), - QU( 5456113959000700739LLU), QU( 3877918438464873016LLU), - QU(12534071654260163555LLU), QU(15871678376893555041LLU), - QU(11005484805712025549LLU), QU(16353066973143374252LLU), - QU( 4358331472063256685LLU), QU( 8268349332210859288LLU), - QU(12485161590939658075LLU), QU(13955993592854471343LLU), - QU( 5911446886848367039LLU), QU(14925834086813706974LLU), - QU( 6590362597857994805LLU), QU( 1280544923533661875LLU), - QU( 1637756018947988164LLU), QU( 4734090064512686329LLU), - QU(16693705263131485912LLU), QU( 6834882340494360958LLU), - QU( 8120732176159658505LLU), QU( 2244371958905329346LLU), - QU(10447499707729734021LLU), QU( 7318742361446942194LLU), - QU( 8032857516355555296LLU), QU(14023605983059313116LLU), - QU( 1032336061815461376LLU), QU( 9840995337876562612LLU), - QU( 9869256223029203587LLU), QU(12227975697177267636LLU), - QU(12728115115844186033LLU), QU( 7752058479783205470LLU), - QU( 729733219713393087LLU), QU(12954017801239007622LLU) + KQU(16924766246869039260), KQU( 8201438687333352714), + KQU( 2265290287015001750), KQU(18397264611805473832), + KQU( 3375255223302384358), KQU( 6345559975416828796), + KQU(18229739242790328073), KQU( 7596792742098800905), + KQU( 255338647169685981), KQU( 2052747240048610300), + KQU(18328151576097299343), KQU(12472905421133796567), + KQU(11315245349717600863), KQU(16594110197775871209), + KQU(15708751964632456450), KQU(10452031272054632535), + KQU(11097646720811454386), KQU( 4556090668445745441), + KQU(17116187693090663106), KQU(14931526836144510645), + KQU( 9190752218020552591), KQU( 9625800285771901401), + KQU(13995141077659972832), KQU( 5194209094927829625), + KQU( 4156788379151063303), KQU( 8523452593770139494), + KQU(14082382103049296727), KQU( 2462601863986088483), + KQU( 3030583461592840678), KQU( 5221622077872827681), + KQU( 3084210671228981236), KQU(13956758381389953823), + KQU(13503889856213423831), KQU(15696904024189836170), + KQU( 4612584152877036206), KQU( 6231135538447867881), + KQU(10172457294158869468), KQU( 6452258628466708150), + KQU(14044432824917330221), KQU( 370168364480044279), + KQU(10102144686427193359), KQU( 667870489994776076), + KQU( 2732271956925885858), KQU(18027788905977284151), + KQU(15009842788582923859), KQU( 7136357960180199542), + KQU(15901736243475578127), KQU(16951293785352615701), + KQU(10551492125243691632), KQU(17668869969146434804), + KQU(13646002971174390445), KQU( 9804471050759613248), + KQU( 5511670439655935493), KQU(18103342091070400926), + KQU(17224512747665137533), KQU(15534627482992618168), + KQU( 1423813266186582647), KQU(15821176807932930024), + KQU( 30323369733607156), KQU(11599382494723479403), + KQU( 653856076586810062), KQU( 3176437395144899659), + KQU(14028076268147963917), KQU(16156398271809666195), + KQU( 3166955484848201676), KQU( 5746805620136919390), + KQU(17297845208891256593), KQU(11691653183226428483), + KQU(17900026146506981577), KQU(15387382115755971042), + KQU(16923567681040845943), KQU( 8039057517199388606), + KQU(11748409241468629263), KQU( 794358245539076095), + KQU(13438501964693401242), KQU(14036803236515618962), + KQU( 5252311215205424721), KQU(17806589612915509081), + KQU( 6802767092397596006), KQU(14212120431184557140), + KQU( 1072951366761385712), KQU(13098491780722836296), + KQU( 9466676828710797353), KQU(12673056849042830081), + KQU(12763726623645357580), KQU(16468961652999309493), + KQU(15305979875636438926), KQU(17444713151223449734), + KQU( 5692214267627883674), KQU(13049589139196151505), + KQU( 880115207831670745), KQU( 1776529075789695498), + KQU(16695225897801466485), KQU(10666901778795346845), + KQU( 6164389346722833869), KQU( 2863817793264300475), + KQU( 9464049921886304754), KQU( 3993566636740015468), + KQU( 9983749692528514136), KQU(16375286075057755211), + KQU(16042643417005440820), KQU(11445419662923489877), + KQU( 7999038846885158836), KQU( 6721913661721511535), + KQU( 5363052654139357320), KQU( 1817788761173584205), + KQU(13290974386445856444), KQU( 4650350818937984680), + KQU( 8219183528102484836), KQU( 1569862923500819899), + KQU( 4189359732136641860), KQU(14202822961683148583), + KQU( 4457498315309429058), KQU(13089067387019074834), + KQU(11075517153328927293), KQU(10277016248336668389), + KQU( 7070509725324401122), KQU(17808892017780289380), + KQU(13143367339909287349), KQU( 1377743745360085151), + KQU( 5749341807421286485), KQU(14832814616770931325), + KQU( 7688820635324359492), KQU(10960474011539770045), + KQU( 81970066653179790), KQU(12619476072607878022), + KQU( 4419566616271201744), KQU(15147917311750568503), + KQU( 5549739182852706345), KQU( 7308198397975204770), + KQU(13580425496671289278), KQU(17070764785210130301), + KQU( 8202832846285604405), KQU( 6873046287640887249), + KQU( 6927424434308206114), KQU( 6139014645937224874), + KQU(10290373645978487639), KQU(15904261291701523804), + KQU( 9628743442057826883), KQU(18383429096255546714), + KQU( 4977413265753686967), KQU( 7714317492425012869), + KQU( 9025232586309926193), KQU(14627338359776709107), + KQU(14759849896467790763), KQU(10931129435864423252), + KQU( 4588456988775014359), KQU(10699388531797056724), + KQU( 468652268869238792), KQU( 5755943035328078086), + KQU( 2102437379988580216), KQU( 9986312786506674028), + KQU( 2654207180040945604), KQU( 8726634790559960062), + KQU( 100497234871808137), KQU( 2800137176951425819), + KQU( 6076627612918553487), KQU( 5780186919186152796), + KQU( 8179183595769929098), KQU( 6009426283716221169), + KQU( 2796662551397449358), KQU( 1756961367041986764), + KQU( 6972897917355606205), KQU(14524774345368968243), + KQU( 2773529684745706940), KQU( 4853632376213075959), + KQU( 4198177923731358102), KQU( 8271224913084139776), + KQU( 2741753121611092226), KQU(16782366145996731181), + KQU(15426125238972640790), KQU(13595497100671260342), + KQU( 3173531022836259898), KQU( 6573264560319511662), + KQU(18041111951511157441), KQU( 2351433581833135952), + KQU( 3113255578908173487), KQU( 1739371330877858784), + KQU(16046126562789165480), KQU( 8072101652214192925), + KQU(15267091584090664910), KQU( 9309579200403648940), + KQU( 5218892439752408722), KQU(14492477246004337115), + KQU(17431037586679770619), KQU( 7385248135963250480), + KQU( 9580144956565560660), KQU( 4919546228040008720), + KQU(15261542469145035584), KQU(18233297270822253102), + KQU( 5453248417992302857), KQU( 9309519155931460285), + KQU(10342813012345291756), KQU(15676085186784762381), + KQU(15912092950691300645), KQU( 9371053121499003195), + KQU( 9897186478226866746), KQU(14061858287188196327), + KQU( 122575971620788119), KQU(12146750969116317754), + KQU( 4438317272813245201), KQU( 8332576791009527119), + KQU(13907785691786542057), KQU(10374194887283287467), + KQU( 2098798755649059566), KQU( 3416235197748288894), + KQU( 8688269957320773484), KQU( 7503964602397371571), + KQU(16724977015147478236), KQU( 9461512855439858184), + KQU(13259049744534534727), KQU( 3583094952542899294), + KQU( 8764245731305528292), KQU(13240823595462088985), + KQU(13716141617617910448), KQU(18114969519935960955), + KQU( 2297553615798302206), KQU( 4585521442944663362), + KQU(17776858680630198686), KQU( 4685873229192163363), + KQU( 152558080671135627), KQU(15424900540842670088), + KQU(13229630297130024108), KQU(17530268788245718717), + KQU(16675633913065714144), KQU( 3158912717897568068), + KQU(15399132185380087288), KQU( 7401418744515677872), + KQU(13135412922344398535), KQU( 6385314346100509511), + KQU(13962867001134161139), KQU(10272780155442671999), + KQU(12894856086597769142), KQU(13340877795287554994), + KQU(12913630602094607396), KQU(12543167911119793857), + KQU(17343570372251873096), KQU(10959487764494150545), + KQU( 6966737953093821128), KQU(13780699135496988601), + KQU( 4405070719380142046), KQU(14923788365607284982), + KQU( 2869487678905148380), KQU( 6416272754197188403), + KQU(15017380475943612591), KQU( 1995636220918429487), + KQU( 3402016804620122716), KQU(15800188663407057080), + KQU(11362369990390932882), KQU(15262183501637986147), + KQU(10239175385387371494), KQU( 9352042420365748334), + KQU( 1682457034285119875), KQU( 1724710651376289644), + KQU( 2038157098893817966), KQU( 9897825558324608773), + KQU( 1477666236519164736), KQU(16835397314511233640), + KQU(10370866327005346508), KQU(10157504370660621982), + KQU(12113904045335882069), KQU(13326444439742783008), + KQU(11302769043000765804), KQU(13594979923955228484), + KQU(11779351762613475968), KQU( 3786101619539298383), + KQU( 8021122969180846063), KQU(15745904401162500495), + KQU(10762168465993897267), KQU(13552058957896319026), + KQU(11200228655252462013), KQU( 5035370357337441226), + KQU( 7593918984545500013), KQU( 5418554918361528700), + KQU( 4858270799405446371), KQU( 9974659566876282544), + KQU(18227595922273957859), KQU( 2772778443635656220), + KQU(14285143053182085385), KQU( 9939700992429600469), + KQU(12756185904545598068), KQU( 2020783375367345262), + KQU( 57026775058331227), KQU( 950827867930065454), + KQU( 6602279670145371217), KQU( 2291171535443566929), + KQU( 5832380724425010313), KQU( 1220343904715982285), + KQU(17045542598598037633), KQU(15460481779702820971), + KQU(13948388779949365130), KQU(13975040175430829518), + KQU(17477538238425541763), KQU(11104663041851745725), + KQU(15860992957141157587), KQU(14529434633012950138), + KQU( 2504838019075394203), KQU( 7512113882611121886), + KQU( 4859973559980886617), KQU( 1258601555703250219), + KQU(15594548157514316394), KQU( 4516730171963773048), + KQU(11380103193905031983), KQU( 6809282239982353344), + KQU(18045256930420065002), KQU( 2453702683108791859), + KQU( 977214582986981460), KQU( 2006410402232713466), + KQU( 6192236267216378358), KQU( 3429468402195675253), + KQU(18146933153017348921), KQU(17369978576367231139), + KQU( 1246940717230386603), KQU(11335758870083327110), + KQU(14166488801730353682), KQU( 9008573127269635732), + KQU(10776025389820643815), KQU(15087605441903942962), + KQU( 1359542462712147922), KQU(13898874411226454206), + KQU(17911176066536804411), KQU( 9435590428600085274), + KQU( 294488509967864007), KQU( 8890111397567922046), + KQU( 7987823476034328778), KQU(13263827582440967651), + KQU( 7503774813106751573), KQU(14974747296185646837), + KQU( 8504765037032103375), KQU(17340303357444536213), + KQU( 7704610912964485743), KQU( 8107533670327205061), + KQU( 9062969835083315985), KQU(16968963142126734184), + KQU(12958041214190810180), KQU( 2720170147759570200), + KQU( 2986358963942189566), KQU(14884226322219356580), + KQU( 286224325144368520), KQU(11313800433154279797), + KQU(18366849528439673248), KQU(17899725929482368789), + KQU( 3730004284609106799), KQU( 1654474302052767205), + KQU( 5006698007047077032), KQU( 8196893913601182838), + KQU(15214541774425211640), KQU(17391346045606626073), + KQU( 8369003584076969089), KQU( 3939046733368550293), + KQU(10178639720308707785), KQU( 2180248669304388697), + KQU( 62894391300126322), KQU( 9205708961736223191), + KQU( 6837431058165360438), KQU( 3150743890848308214), + KQU(17849330658111464583), KQU(12214815643135450865), + KQU(13410713840519603402), KQU( 3200778126692046802), + KQU(13354780043041779313), KQU( 800850022756886036), + KQU(15660052933953067433), KQU( 6572823544154375676), + KQU(11030281857015819266), KQU(12682241941471433835), + KQU(11654136407300274693), KQU( 4517795492388641109), + KQU( 9757017371504524244), KQU(17833043400781889277), + KQU(12685085201747792227), KQU(10408057728835019573), + KQU( 98370418513455221), KQU( 6732663555696848598), + KQU(13248530959948529780), KQU( 3530441401230622826), + KQU(18188251992895660615), KQU( 1847918354186383756), + KQU( 1127392190402660921), KQU(11293734643143819463), + KQU( 3015506344578682982), KQU(13852645444071153329), + KQU( 2121359659091349142), KQU( 1294604376116677694), + KQU( 5616576231286352318), KQU( 7112502442954235625), + KQU(11676228199551561689), KQU(12925182803007305359), + KQU( 7852375518160493082), KQU( 1136513130539296154), + KQU( 5636923900916593195), KQU( 3221077517612607747), + KQU(17784790465798152513), KQU( 3554210049056995938), + KQU(17476839685878225874), KQU( 3206836372585575732), + KQU( 2765333945644823430), KQU(10080070903718799528), + KQU( 5412370818878286353), KQU( 9689685887726257728), + KQU( 8236117509123533998), KQU( 1951139137165040214), + KQU( 4492205209227980349), KQU(16541291230861602967), + KQU( 1424371548301437940), KQU( 9117562079669206794), + KQU(14374681563251691625), KQU(13873164030199921303), + KQU( 6680317946770936731), KQU(15586334026918276214), + KQU(10896213950976109802), KQU( 9506261949596413689), + KQU( 9903949574308040616), KQU( 6038397344557204470), + KQU( 174601465422373648), KQU(15946141191338238030), + KQU(17142225620992044937), KQU( 7552030283784477064), + KQU( 2947372384532947997), KQU( 510797021688197711), + KQU( 4962499439249363461), KQU( 23770320158385357), + KQU( 959774499105138124), KQU( 1468396011518788276), + KQU( 2015698006852312308), KQU( 4149400718489980136), + KQU( 5992916099522371188), KQU(10819182935265531076), + KQU(16189787999192351131), KQU( 342833961790261950), + KQU(12470830319550495336), KQU(18128495041912812501), + KQU( 1193600899723524337), KQU( 9056793666590079770), + KQU( 2154021227041669041), KQU( 4963570213951235735), + KQU( 4865075960209211409), KQU( 2097724599039942963), + KQU( 2024080278583179845), KQU(11527054549196576736), + KQU(10650256084182390252), KQU( 4808408648695766755), + KQU( 1642839215013788844), KQU(10607187948250398390), + KQU( 7076868166085913508), KQU( 730522571106887032), + KQU(12500579240208524895), KQU( 4484390097311355324), + KQU(15145801330700623870), KQU( 8055827661392944028), + KQU( 5865092976832712268), KQU(15159212508053625143), + KQU( 3560964582876483341), KQU( 4070052741344438280), + KQU( 6032585709886855634), KQU(15643262320904604873), + KQU( 2565119772293371111), KQU( 318314293065348260), + KQU(15047458749141511872), KQU( 7772788389811528730), + KQU( 7081187494343801976), KQU( 6465136009467253947), + KQU(10425940692543362069), KQU( 554608190318339115), + KQU(14796699860302125214), KQU( 1638153134431111443), + KQU(10336967447052276248), KQU( 8412308070396592958), + KQU( 4004557277152051226), KQU( 8143598997278774834), + KQU(16413323996508783221), KQU(13139418758033994949), + KQU( 9772709138335006667), KQU( 2818167159287157659), + KQU(17091740573832523669), KQU(14629199013130751608), + KQU(18268322711500338185), KQU( 8290963415675493063), + KQU( 8830864907452542588), KQU( 1614839084637494849), + KQU(14855358500870422231), KQU( 3472996748392519937), + KQU(15317151166268877716), KQU( 5825895018698400362), + KQU(16730208429367544129), KQU(10481156578141202800), + KQU( 4746166512382823750), KQU(12720876014472464998), + KQU( 8825177124486735972), KQU(13733447296837467838), + KQU( 6412293741681359625), KQU( 8313213138756135033), + KQU(11421481194803712517), KQU( 7997007691544174032), + KQU( 6812963847917605930), KQU( 9683091901227558641), + KQU(14703594165860324713), KQU( 1775476144519618309), + KQU( 2724283288516469519), KQU( 717642555185856868), + KQU( 8736402192215092346), KQU(11878800336431381021), + KQU( 4348816066017061293), KQU( 6115112756583631307), + KQU( 9176597239667142976), KQU(12615622714894259204), + KQU(10283406711301385987), KQU( 5111762509485379420), + KQU( 3118290051198688449), KQU( 7345123071632232145), + KQU( 9176423451688682359), KQU( 4843865456157868971), + KQU(12008036363752566088), KQU(12058837181919397720), + KQU( 2145073958457347366), KQU( 1526504881672818067), + KQU( 3488830105567134848), KQU(13208362960674805143), + KQU( 4077549672899572192), KQU( 7770995684693818365), + KQU( 1398532341546313593), KQU(12711859908703927840), + KQU( 1417561172594446813), KQU(17045191024194170604), + KQU( 4101933177604931713), KQU(14708428834203480320), + KQU(17447509264469407724), KQU(14314821973983434255), + KQU(17990472271061617265), KQU( 5087756685841673942), + KQU(12797820586893859939), KQU( 1778128952671092879), + KQU( 3535918530508665898), KQU( 9035729701042481301), + KQU(14808661568277079962), KQU(14587345077537747914), + KQU(11920080002323122708), KQU( 6426515805197278753), + KQU( 3295612216725984831), KQU(11040722532100876120), + KQU(12305952936387598754), KQU(16097391899742004253), + KQU( 4908537335606182208), KQU(12446674552196795504), + KQU(16010497855816895177), KQU( 9194378874788615551), + KQU( 3382957529567613384), KQU( 5154647600754974077), + KQU( 9801822865328396141), KQU( 9023662173919288143), + KQU(17623115353825147868), KQU( 8238115767443015816), + KQU(15811444159859002560), KQU( 9085612528904059661), + KQU( 6888601089398614254), KQU( 258252992894160189), + KQU( 6704363880792428622), KQU( 6114966032147235763), + KQU(11075393882690261875), KQU( 8797664238933620407), + KQU( 5901892006476726920), KQU( 5309780159285518958), + KQU(14940808387240817367), KQU(14642032021449656698), + KQU( 9808256672068504139), KQU( 3670135111380607658), + KQU(11211211097845960152), KQU( 1474304506716695808), + KQU(15843166204506876239), KQU( 7661051252471780561), + KQU(10170905502249418476), KQU( 7801416045582028589), + KQU( 2763981484737053050), KQU( 9491377905499253054), + KQU(16201395896336915095), KQU( 9256513756442782198), + KQU( 5411283157972456034), KQU( 5059433122288321676), + KQU( 4327408006721123357), KQU( 9278544078834433377), + KQU( 7601527110882281612), KQU(11848295896975505251), + KQU(12096998801094735560), KQU(14773480339823506413), + KQU(15586227433895802149), KQU(12786541257830242872), + KQU( 6904692985140503067), KQU( 5309011515263103959), + KQU(12105257191179371066), KQU(14654380212442225037), + KQU( 2556774974190695009), KQU( 4461297399927600261), + KQU(14888225660915118646), KQU(14915459341148291824), + KQU( 2738802166252327631), KQU( 6047155789239131512), + KQU(12920545353217010338), KQU(10697617257007840205), + KQU( 2751585253158203504), KQU(13252729159780047496), + KQU(14700326134672815469), KQU(14082527904374600529), + KQU(16852962273496542070), KQU(17446675504235853907), + KQU(15019600398527572311), KQU(12312781346344081551), + KQU(14524667935039810450), KQU( 5634005663377195738), + KQU(11375574739525000569), KQU( 2423665396433260040), + KQU( 5222836914796015410), KQU( 4397666386492647387), + KQU( 4619294441691707638), KQU( 665088602354770716), + KQU(13246495665281593610), KQU( 6564144270549729409), + KQU(10223216188145661688), KQU( 3961556907299230585), + KQU(11543262515492439914), KQU(16118031437285993790), + KQU( 7143417964520166465), KQU(13295053515909486772), + KQU( 40434666004899675), KQU(17127804194038347164), + KQU( 8599165966560586269), KQU( 8214016749011284903), + KQU(13725130352140465239), KQU( 5467254474431726291), + KQU( 7748584297438219877), KQU(16933551114829772472), + KQU( 2169618439506799400), KQU( 2169787627665113463), + KQU(17314493571267943764), KQU(18053575102911354912), + KQU(11928303275378476973), KQU(11593850925061715550), + KQU(17782269923473589362), KQU( 3280235307704747039), + KQU( 6145343578598685149), KQU(17080117031114086090), + KQU(18066839902983594755), KQU( 6517508430331020706), + KQU( 8092908893950411541), KQU(12558378233386153732), + KQU( 4476532167973132976), KQU(16081642430367025016), + KQU( 4233154094369139361), KQU( 8693630486693161027), + KQU(11244959343027742285), KQU(12273503967768513508), + KQU(14108978636385284876), KQU( 7242414665378826984), + KQU( 6561316938846562432), KQU( 8601038474994665795), + KQU(17532942353612365904), KQU(17940076637020912186), + KQU( 7340260368823171304), KQU( 7061807613916067905), + KQU(10561734935039519326), KQU(17990796503724650862), + KQU( 6208732943911827159), KQU( 359077562804090617), + KQU(14177751537784403113), KQU(10659599444915362902), + KQU(15081727220615085833), KQU(13417573895659757486), + KQU(15513842342017811524), KQU(11814141516204288231), + KQU( 1827312513875101814), KQU( 2804611699894603103), + KQU(17116500469975602763), KQU(12270191815211952087), + KQU(12256358467786024988), KQU(18435021722453971267), + KQU( 671330264390865618), KQU( 476504300460286050), + KQU(16465470901027093441), KQU( 4047724406247136402), + KQU( 1322305451411883346), KQU( 1388308688834322280), + KQU( 7303989085269758176), KQU( 9323792664765233642), + KQU( 4542762575316368936), KQU(17342696132794337618), + KQU( 4588025054768498379), KQU(13415475057390330804), + KQU(17880279491733405570), KQU(10610553400618620353), + KQU( 3180842072658960139), KQU(13002966655454270120), + KQU( 1665301181064982826), KQU( 7083673946791258979), + KQU( 190522247122496820), KQU(17388280237250677740), + KQU( 8430770379923642945), KQU(12987180971921668584), + KQU( 2311086108365390642), KQU( 2870984383579822345), + KQU(14014682609164653318), KQU(14467187293062251484), + KQU( 192186361147413298), KQU(15171951713531796524), + KQU( 9900305495015948728), KQU(17958004775615466344), + KQU(14346380954498606514), KQU(18040047357617407096), + KQU( 5035237584833424532), KQU(15089555460613972287), + KQU( 4131411873749729831), KQU( 1329013581168250330), + KQU(10095353333051193949), KQU(10749518561022462716), + KQU( 9050611429810755847), KQU(15022028840236655649), + KQU( 8775554279239748298), KQU(13105754025489230502), + KQU(15471300118574167585), KQU( 89864764002355628), + KQU( 8776416323420466637), KQU( 5280258630612040891), + KQU( 2719174488591862912), KQU( 7599309137399661994), + KQU(15012887256778039979), KQU(14062981725630928925), + KQU(12038536286991689603), KQU( 7089756544681775245), + KQU(10376661532744718039), KQU( 1265198725901533130), + KQU(13807996727081142408), KQU( 2935019626765036403), + KQU( 7651672460680700141), KQU( 3644093016200370795), + KQU( 2840982578090080674), KQU(17956262740157449201), + KQU(18267979450492880548), KQU(11799503659796848070), + KQU( 9942537025669672388), KQU(11886606816406990297), + KQU( 5488594946437447576), KQU( 7226714353282744302), + KQU( 3784851653123877043), KQU( 878018453244803041), + KQU(12110022586268616085), KQU( 734072179404675123), + KQU(11869573627998248542), KQU( 469150421297783998), + KQU( 260151124912803804), KQU(11639179410120968649), + KQU( 9318165193840846253), KQU(12795671722734758075), + KQU(15318410297267253933), KQU( 691524703570062620), + KQU( 5837129010576994601), KQU(15045963859726941052), + KQU( 5850056944932238169), KQU(12017434144750943807), + KQU( 7447139064928956574), KQU( 3101711812658245019), + KQU(16052940704474982954), KQU(18195745945986994042), + KQU( 8932252132785575659), KQU(13390817488106794834), + KQU(11582771836502517453), KQU( 4964411326683611686), + KQU( 2195093981702694011), KQU(14145229538389675669), + KQU(16459605532062271798), KQU( 866316924816482864), + KQU( 4593041209937286377), KQU( 8415491391910972138), + KQU( 4171236715600528969), KQU(16637569303336782889), + KQU( 2002011073439212680), KQU(17695124661097601411), + KQU( 4627687053598611702), KQU( 7895831936020190403), + KQU( 8455951300917267802), KQU( 2923861649108534854), + KQU( 8344557563927786255), KQU( 6408671940373352556), + KQU(12210227354536675772), KQU(14294804157294222295), + KQU(10103022425071085127), KQU(10092959489504123771), + KQU( 6554774405376736268), KQU(12629917718410641774), + KQU( 6260933257596067126), KQU( 2460827021439369673), + KQU( 2541962996717103668), KQU( 597377203127351475), + KQU( 5316984203117315309), KQU( 4811211393563241961), + KQU(13119698597255811641), KQU( 8048691512862388981), + KQU(10216818971194073842), KQU( 4612229970165291764), + KQU(10000980798419974770), KQU( 6877640812402540687), + KQU( 1488727563290436992), KQU( 2227774069895697318), + KQU(11237754507523316593), KQU(13478948605382290972), + KQU( 1963583846976858124), KQU( 5512309205269276457), + KQU( 3972770164717652347), KQU( 3841751276198975037), + KQU(10283343042181903117), KQU( 8564001259792872199), + KQU(16472187244722489221), KQU( 8953493499268945921), + KQU( 3518747340357279580), KQU( 4003157546223963073), + KQU( 3270305958289814590), KQU( 3966704458129482496), + KQU( 8122141865926661939), KQU(14627734748099506653), + KQU(13064426990862560568), KQU( 2414079187889870829), + KQU( 5378461209354225306), KQU(10841985740128255566), + KQU( 538582442885401738), KQU( 7535089183482905946), + KQU(16117559957598879095), KQU( 8477890721414539741), + KQU( 1459127491209533386), KQU(17035126360733620462), + KQU( 8517668552872379126), KQU(10292151468337355014), + KQU(17081267732745344157), KQU(13751455337946087178), + KQU(14026945459523832966), KQU( 6653278775061723516), + KQU(10619085543856390441), KQU( 2196343631481122885), + KQU(10045966074702826136), KQU(10082317330452718282), + KQU( 5920859259504831242), KQU( 9951879073426540617), + KQU( 7074696649151414158), KQU(15808193543879464318), + KQU( 7385247772746953374), KQU( 3192003544283864292), + KQU(18153684490917593847), KQU(12423498260668568905), + KQU(10957758099756378169), KQU(11488762179911016040), + KQU( 2099931186465333782), KQU(11180979581250294432), + KQU( 8098916250668367933), KQU( 3529200436790763465), + KQU(12988418908674681745), KQU( 6147567275954808580), + KQU( 3207503344604030989), KQU(10761592604898615360), + KQU( 229854861031893504), KQU( 8809853962667144291), + KQU(13957364469005693860), KQU( 7634287665224495886), + KQU(12353487366976556874), KQU( 1134423796317152034), + KQU( 2088992471334107068), KQU( 7393372127190799698), + KQU( 1845367839871058391), KQU( 207922563987322884), + KQU(11960870813159944976), KQU(12182120053317317363), + KQU(17307358132571709283), KQU(13871081155552824936), + KQU(18304446751741566262), KQU( 7178705220184302849), + KQU(10929605677758824425), KQU(16446976977835806844), + KQU(13723874412159769044), KQU( 6942854352100915216), + KQU( 1726308474365729390), KQU( 2150078766445323155), + KQU(15345558947919656626), KQU(12145453828874527201), + KQU( 2054448620739726849), KQU( 2740102003352628137), + KQU(11294462163577610655), KQU( 756164283387413743), + KQU(17841144758438810880), KQU(10802406021185415861), + KQU( 8716455530476737846), KQU( 6321788834517649606), + KQU(14681322910577468426), KQU(17330043563884336387), + KQU(12701802180050071614), KQU(14695105111079727151), + KQU( 5112098511654172830), KQU( 4957505496794139973), + KQU( 8270979451952045982), KQU(12307685939199120969), + KQU(12425799408953443032), KQU( 8376410143634796588), + KQU(16621778679680060464), KQU( 3580497854566660073), + KQU( 1122515747803382416), KQU( 857664980960597599), + KQU( 6343640119895925918), KQU(12878473260854462891), + KQU(10036813920765722626), KQU(14451335468363173812), + KQU( 5476809692401102807), KQU(16442255173514366342), + KQU(13060203194757167104), KQU(14354124071243177715), + KQU(15961249405696125227), KQU(13703893649690872584), + KQU( 363907326340340064), KQU( 6247455540491754842), + KQU(12242249332757832361), KQU( 156065475679796717), + KQU( 9351116235749732355), KQU( 4590350628677701405), + KQU( 1671195940982350389), KQU(13501398458898451905), + KQU( 6526341991225002255), KQU( 1689782913778157592), + KQU( 7439222350869010334), KQU(13975150263226478308), + KQU(11411961169932682710), KQU(17204271834833847277), + KQU( 541534742544435367), KQU( 6591191931218949684), + KQU( 2645454775478232486), KQU( 4322857481256485321), + KQU( 8477416487553065110), KQU(12902505428548435048), + KQU( 971445777981341415), KQU(14995104682744976712), + KQU( 4243341648807158063), KQU( 8695061252721927661), + KQU( 5028202003270177222), KQU( 2289257340915567840), + KQU(13870416345121866007), KQU(13994481698072092233), + KQU( 6912785400753196481), KQU( 2278309315841980139), + KQU( 4329765449648304839), KQU( 5963108095785485298), + KQU( 4880024847478722478), KQU(16015608779890240947), + KQU( 1866679034261393544), KQU( 914821179919731519), + KQU( 9643404035648760131), KQU( 2418114953615593915), + KQU( 944756836073702374), KQU(15186388048737296834), + KQU( 7723355336128442206), KQU( 7500747479679599691), + KQU(18013961306453293634), KQU( 2315274808095756456), + KQU(13655308255424029566), KQU(17203800273561677098), + KQU( 1382158694422087756), KQU( 5090390250309588976), + KQU( 517170818384213989), KQU( 1612709252627729621), + KQU( 1330118955572449606), KQU( 300922478056709885), + KQU(18115693291289091987), KQU(13491407109725238321), + KQU(15293714633593827320), KQU( 5151539373053314504), + KQU( 5951523243743139207), KQU(14459112015249527975), + KQU( 5456113959000700739), KQU( 3877918438464873016), + KQU(12534071654260163555), KQU(15871678376893555041), + KQU(11005484805712025549), KQU(16353066973143374252), + KQU( 4358331472063256685), KQU( 8268349332210859288), + KQU(12485161590939658075), KQU(13955993592854471343), + KQU( 5911446886848367039), KQU(14925834086813706974), + KQU( 6590362597857994805), KQU( 1280544923533661875), + KQU( 1637756018947988164), KQU( 4734090064512686329), + KQU(16693705263131485912), KQU( 6834882340494360958), + KQU( 8120732176159658505), KQU( 2244371958905329346), + KQU(10447499707729734021), KQU( 7318742361446942194), + KQU( 8032857516355555296), KQU(14023605983059313116), + KQU( 1032336061815461376), KQU( 9840995337876562612), + KQU( 9869256223029203587), KQU(12227975697177267636), + KQU(12728115115844186033), KQU( 7752058479783205470), + KQU( 729733219713393087), KQU(12954017801239007622) }; static const uint64_t init_by_array_64_expected[] = { - QU( 2100341266307895239LLU), QU( 8344256300489757943LLU), - QU(15687933285484243894LLU), QU( 8268620370277076319LLU), - QU(12371852309826545459LLU), QU( 8800491541730110238LLU), - QU(18113268950100835773LLU), QU( 2886823658884438119LLU), - QU( 3293667307248180724LLU), QU( 9307928143300172731LLU), - QU( 7688082017574293629LLU), QU( 900986224735166665LLU), - QU( 9977972710722265039LLU), QU( 6008205004994830552LLU), - QU( 546909104521689292LLU), QU( 7428471521869107594LLU), - QU(14777563419314721179LLU), QU(16116143076567350053LLU), - QU( 5322685342003142329LLU), QU( 4200427048445863473LLU), - QU( 4693092150132559146LLU), QU(13671425863759338582LLU), - QU( 6747117460737639916LLU), QU( 4732666080236551150LLU), - QU( 5912839950611941263LLU), QU( 3903717554504704909LLU), - QU( 2615667650256786818LLU), QU(10844129913887006352LLU), - QU(13786467861810997820LLU), QU(14267853002994021570LLU), - QU(13767807302847237439LLU), QU(16407963253707224617LLU), - QU( 4802498363698583497LLU), QU( 2523802839317209764LLU), - QU( 3822579397797475589LLU), QU( 8950320572212130610LLU), - QU( 3745623504978342534LLU), QU(16092609066068482806LLU), - QU( 9817016950274642398LLU), QU(10591660660323829098LLU), - QU(11751606650792815920LLU), QU( 5122873818577122211LLU), - QU(17209553764913936624LLU), QU( 6249057709284380343LLU), - QU(15088791264695071830LLU), QU(15344673071709851930LLU), - QU( 4345751415293646084LLU), QU( 2542865750703067928LLU), - QU(13520525127852368784LLU), QU(18294188662880997241LLU), - QU( 3871781938044881523LLU), QU( 2873487268122812184LLU), - QU(15099676759482679005LLU), QU(15442599127239350490LLU), - QU( 6311893274367710888LLU), QU( 3286118760484672933LLU), - QU( 4146067961333542189LLU), QU(13303942567897208770LLU), - QU( 8196013722255630418LLU), QU( 4437815439340979989LLU), - QU(15433791533450605135LLU), QU( 4254828956815687049LLU), - QU( 1310903207708286015LLU), QU(10529182764462398549LLU), - QU(14900231311660638810LLU), QU( 9727017277104609793LLU), - QU( 1821308310948199033LLU), QU(11628861435066772084LLU), - QU( 9469019138491546924LLU), QU( 3145812670532604988LLU), - QU( 9938468915045491919LLU), QU( 1562447430672662142LLU), - QU(13963995266697989134LLU), QU( 3356884357625028695LLU), - QU( 4499850304584309747LLU), QU( 8456825817023658122LLU), - QU(10859039922814285279LLU), QU( 8099512337972526555LLU), - QU( 348006375109672149LLU), QU(11919893998241688603LLU), - QU( 1104199577402948826LLU), QU(16689191854356060289LLU), - QU(10992552041730168078LLU), QU( 7243733172705465836LLU), - QU( 5668075606180319560LLU), QU(18182847037333286970LLU), - QU( 4290215357664631322LLU), QU( 4061414220791828613LLU), - QU(13006291061652989604LLU), QU( 7140491178917128798LLU), - QU(12703446217663283481LLU), QU( 5500220597564558267LLU), - QU(10330551509971296358LLU), QU(15958554768648714492LLU), - QU( 5174555954515360045LLU), QU( 1731318837687577735LLU), - QU( 3557700801048354857LLU), QU(13764012341928616198LLU), - QU(13115166194379119043LLU), QU( 7989321021560255519LLU), - QU( 2103584280905877040LLU), QU( 9230788662155228488LLU), - QU(16396629323325547654LLU), QU( 657926409811318051LLU), - QU(15046700264391400727LLU), QU( 5120132858771880830LLU), - QU( 7934160097989028561LLU), QU( 6963121488531976245LLU), - QU(17412329602621742089LLU), QU(15144843053931774092LLU), - QU(17204176651763054532LLU), QU(13166595387554065870LLU), - QU( 8590377810513960213LLU), QU( 5834365135373991938LLU), - QU( 7640913007182226243LLU), QU( 3479394703859418425LLU), - QU(16402784452644521040LLU), QU( 4993979809687083980LLU), - QU(13254522168097688865LLU), QU(15643659095244365219LLU), - QU( 5881437660538424982LLU), QU(11174892200618987379LLU), - QU( 254409966159711077LLU), QU(17158413043140549909LLU), - QU( 3638048789290376272LLU), QU( 1376816930299489190LLU), - QU( 4622462095217761923LLU), QU(15086407973010263515LLU), - QU(13253971772784692238LLU), QU( 5270549043541649236LLU), - QU(11182714186805411604LLU), QU(12283846437495577140LLU), - QU( 5297647149908953219LLU), QU(10047451738316836654LLU), - QU( 4938228100367874746LLU), QU(12328523025304077923LLU), - QU( 3601049438595312361LLU), QU( 9313624118352733770LLU), - QU(13322966086117661798LLU), QU(16660005705644029394LLU), - QU(11337677526988872373LLU), QU(13869299102574417795LLU), - QU(15642043183045645437LLU), QU( 3021755569085880019LLU), - QU( 4979741767761188161LLU), QU(13679979092079279587LLU), - QU( 3344685842861071743LLU), QU(13947960059899588104LLU), - QU( 305806934293368007LLU), QU( 5749173929201650029LLU), - QU(11123724852118844098LLU), QU(15128987688788879802LLU), - QU(15251651211024665009LLU), QU( 7689925933816577776LLU), - QU(16732804392695859449LLU), QU(17087345401014078468LLU), - QU(14315108589159048871LLU), QU( 4820700266619778917LLU), - QU(16709637539357958441LLU), QU( 4936227875177351374LLU), - QU( 2137907697912987247LLU), QU(11628565601408395420LLU), - QU( 2333250549241556786LLU), QU( 5711200379577778637LLU), - QU( 5170680131529031729LLU), QU(12620392043061335164LLU), - QU( 95363390101096078LLU), QU( 5487981914081709462LLU), - QU( 1763109823981838620LLU), QU( 3395861271473224396LLU), - QU( 1300496844282213595LLU), QU( 6894316212820232902LLU), - QU(10673859651135576674LLU), QU( 5911839658857903252LLU), - QU(17407110743387299102LLU), QU( 8257427154623140385LLU), - QU(11389003026741800267LLU), QU( 4070043211095013717LLU), - QU(11663806997145259025LLU), QU(15265598950648798210LLU), - QU( 630585789434030934LLU), QU( 3524446529213587334LLU), - QU( 7186424168495184211LLU), QU(10806585451386379021LLU), - QU(11120017753500499273LLU), QU( 1586837651387701301LLU), - QU(17530454400954415544LLU), QU( 9991670045077880430LLU), - QU( 7550997268990730180LLU), QU( 8640249196597379304LLU), - QU( 3522203892786893823LLU), QU(10401116549878854788LLU), - QU(13690285544733124852LLU), QU( 8295785675455774586LLU), - QU(15535716172155117603LLU), QU( 3112108583723722511LLU), - QU(17633179955339271113LLU), QU(18154208056063759375LLU), - QU( 1866409236285815666LLU), QU(13326075895396412882LLU), - QU( 8756261842948020025LLU), QU( 6281852999868439131LLU), - QU(15087653361275292858LLU), QU(10333923911152949397LLU), - QU( 5265567645757408500LLU), QU(12728041843210352184LLU), - QU( 6347959327507828759LLU), QU( 154112802625564758LLU), - QU(18235228308679780218LLU), QU( 3253805274673352418LLU), - QU( 4849171610689031197LLU), QU(17948529398340432518LLU), - QU(13803510475637409167LLU), QU(13506570190409883095LLU), - QU(15870801273282960805LLU), QU( 8451286481299170773LLU), - QU( 9562190620034457541LLU), QU( 8518905387449138364LLU), - QU(12681306401363385655LLU), QU( 3788073690559762558LLU), - QU( 5256820289573487769LLU), QU( 2752021372314875467LLU), - QU( 6354035166862520716LLU), QU( 4328956378309739069LLU), - QU( 449087441228269600LLU), QU( 5533508742653090868LLU), - QU( 1260389420404746988LLU), QU(18175394473289055097LLU), - QU( 1535467109660399420LLU), QU( 8818894282874061442LLU), - QU(12140873243824811213LLU), QU(15031386653823014946LLU), - QU( 1286028221456149232LLU), QU( 6329608889367858784LLU), - QU( 9419654354945132725LLU), QU( 6094576547061672379LLU), - QU(17706217251847450255LLU), QU( 1733495073065878126LLU), - QU(16918923754607552663LLU), QU( 8881949849954945044LLU), - QU(12938977706896313891LLU), QU(14043628638299793407LLU), - QU(18393874581723718233LLU), QU( 6886318534846892044LLU), - QU(14577870878038334081LLU), QU(13541558383439414119LLU), - QU(13570472158807588273LLU), QU(18300760537910283361LLU), - QU( 818368572800609205LLU), QU( 1417000585112573219LLU), - QU(12337533143867683655LLU), QU(12433180994702314480LLU), - QU( 778190005829189083LLU), QU(13667356216206524711LLU), - QU( 9866149895295225230LLU), QU(11043240490417111999LLU), - QU( 1123933826541378598LLU), QU( 6469631933605123610LLU), - QU(14508554074431980040LLU), QU(13918931242962026714LLU), - QU( 2870785929342348285LLU), QU(14786362626740736974LLU), - QU(13176680060902695786LLU), QU( 9591778613541679456LLU), - QU( 9097662885117436706LLU), QU( 749262234240924947LLU), - QU( 1944844067793307093LLU), QU( 4339214904577487742LLU), - QU( 8009584152961946551LLU), QU(16073159501225501777LLU), - QU( 3335870590499306217LLU), QU(17088312653151202847LLU), - QU( 3108893142681931848LLU), QU(16636841767202792021LLU), - QU(10423316431118400637LLU), QU( 8008357368674443506LLU), - QU(11340015231914677875LLU), QU(17687896501594936090LLU), - QU(15173627921763199958LLU), QU( 542569482243721959LLU), - QU(15071714982769812975LLU), QU( 4466624872151386956LLU), - QU( 1901780715602332461LLU), QU( 9822227742154351098LLU), - QU( 1479332892928648780LLU), QU( 6981611948382474400LLU), - QU( 7620824924456077376LLU), QU(14095973329429406782LLU), - QU( 7902744005696185404LLU), QU(15830577219375036920LLU), - QU(10287076667317764416LLU), QU(12334872764071724025LLU), - QU( 4419302088133544331LLU), QU(14455842851266090520LLU), - QU(12488077416504654222LLU), QU( 7953892017701886766LLU), - QU( 6331484925529519007LLU), QU( 4902145853785030022LLU), - QU(17010159216096443073LLU), QU(11945354668653886087LLU), - QU(15112022728645230829LLU), QU(17363484484522986742LLU), - QU( 4423497825896692887LLU), QU( 8155489510809067471LLU), - QU( 258966605622576285LLU), QU( 5462958075742020534LLU), - QU( 6763710214913276228LLU), QU( 2368935183451109054LLU), - QU(14209506165246453811LLU), QU( 2646257040978514881LLU), - QU( 3776001911922207672LLU), QU( 1419304601390147631LLU), - QU(14987366598022458284LLU), QU( 3977770701065815721LLU), - QU( 730820417451838898LLU), QU( 3982991703612885327LLU), - QU( 2803544519671388477LLU), QU(17067667221114424649LLU), - QU( 2922555119737867166LLU), QU( 1989477584121460932LLU), - QU(15020387605892337354LLU), QU( 9293277796427533547LLU), - QU(10722181424063557247LLU), QU(16704542332047511651LLU), - QU( 5008286236142089514LLU), QU(16174732308747382540LLU), - QU(17597019485798338402LLU), QU(13081745199110622093LLU), - QU( 8850305883842258115LLU), QU(12723629125624589005LLU), - QU( 8140566453402805978LLU), QU(15356684607680935061LLU), - QU(14222190387342648650LLU), QU(11134610460665975178LLU), - QU( 1259799058620984266LLU), QU(13281656268025610041LLU), - QU( 298262561068153992LLU), QU(12277871700239212922LLU), - QU(13911297774719779438LLU), QU(16556727962761474934LLU), - QU(17903010316654728010LLU), QU( 9682617699648434744LLU), - QU(14757681836838592850LLU), QU( 1327242446558524473LLU), - QU(11126645098780572792LLU), QU( 1883602329313221774LLU), - QU( 2543897783922776873LLU), QU(15029168513767772842LLU), - QU(12710270651039129878LLU), QU(16118202956069604504LLU), - QU(15010759372168680524LLU), QU( 2296827082251923948LLU), - QU(10793729742623518101LLU), QU(13829764151845413046LLU), - QU(17769301223184451213LLU), QU( 3118268169210783372LLU), - QU(17626204544105123127LLU), QU( 7416718488974352644LLU), - QU(10450751996212925994LLU), QU( 9352529519128770586LLU), - QU( 259347569641110140LLU), QU( 8048588892269692697LLU), - QU( 1774414152306494058LLU), QU(10669548347214355622LLU), - QU(13061992253816795081LLU), QU(18432677803063861659LLU), - QU( 8879191055593984333LLU), QU(12433753195199268041LLU), - QU(14919392415439730602LLU), QU( 6612848378595332963LLU), - QU( 6320986812036143628LLU), QU(10465592420226092859LLU), - QU( 4196009278962570808LLU), QU( 3747816564473572224LLU), - QU(17941203486133732898LLU), QU( 2350310037040505198LLU), - QU( 5811779859134370113LLU), QU(10492109599506195126LLU), - QU( 7699650690179541274LLU), QU( 1954338494306022961LLU), - QU(14095816969027231152LLU), QU( 5841346919964852061LLU), - QU(14945969510148214735LLU), QU( 3680200305887550992LLU), - QU( 6218047466131695792LLU), QU( 8242165745175775096LLU), - QU(11021371934053307357LLU), QU( 1265099502753169797LLU), - QU( 4644347436111321718LLU), QU( 3609296916782832859LLU), - QU( 8109807992218521571LLU), QU(18387884215648662020LLU), - QU(14656324896296392902LLU), QU(17386819091238216751LLU), - QU(17788300878582317152LLU), QU( 7919446259742399591LLU), - QU( 4466613134576358004LLU), QU(12928181023667938509LLU), - QU(13147446154454932030LLU), QU(16552129038252734620LLU), - QU( 8395299403738822450LLU), QU(11313817655275361164LLU), - QU( 434258809499511718LLU), QU( 2074882104954788676LLU), - QU( 7929892178759395518LLU), QU( 9006461629105745388LLU), - QU( 5176475650000323086LLU), QU(11128357033468341069LLU), - QU(12026158851559118955LLU), QU(14699716249471156500LLU), - QU( 448982497120206757LLU), QU( 4156475356685519900LLU), - QU( 6063816103417215727LLU), QU(10073289387954971479LLU), - QU( 8174466846138590962LLU), QU( 2675777452363449006LLU), - QU( 9090685420572474281LLU), QU( 6659652652765562060LLU), - QU(12923120304018106621LLU), QU(11117480560334526775LLU), - QU( 937910473424587511LLU), QU( 1838692113502346645LLU), - QU(11133914074648726180LLU), QU( 7922600945143884053LLU), - QU(13435287702700959550LLU), QU( 5287964921251123332LLU), - QU(11354875374575318947LLU), QU(17955724760748238133LLU), - QU(13728617396297106512LLU), QU( 4107449660118101255LLU), - QU( 1210269794886589623LLU), QU(11408687205733456282LLU), - QU( 4538354710392677887LLU), QU(13566803319341319267LLU), - QU(17870798107734050771LLU), QU( 3354318982568089135LLU), - QU( 9034450839405133651LLU), QU(13087431795753424314LLU), - QU( 950333102820688239LLU), QU( 1968360654535604116LLU), - QU(16840551645563314995LLU), QU( 8867501803892924995LLU), - QU(11395388644490626845LLU), QU( 1529815836300732204LLU), - QU(13330848522996608842LLU), QU( 1813432878817504265LLU), - QU( 2336867432693429560LLU), QU(15192805445973385902LLU), - QU( 2528593071076407877LLU), QU( 128459777936689248LLU), - QU( 9976345382867214866LLU), QU( 6208885766767996043LLU), - QU(14982349522273141706LLU), QU( 3099654362410737822LLU), - QU(13776700761947297661LLU), QU( 8806185470684925550LLU), - QU( 8151717890410585321LLU), QU( 640860591588072925LLU), - QU(14592096303937307465LLU), QU( 9056472419613564846LLU), - QU(14861544647742266352LLU), QU(12703771500398470216LLU), - QU( 3142372800384138465LLU), QU( 6201105606917248196LLU), - QU(18337516409359270184LLU), QU(15042268695665115339LLU), - QU(15188246541383283846LLU), QU(12800028693090114519LLU), - QU( 5992859621101493472LLU), QU(18278043971816803521LLU), - QU( 9002773075219424560LLU), QU( 7325707116943598353LLU), - QU( 7930571931248040822LLU), QU( 5645275869617023448LLU), - QU( 7266107455295958487LLU), QU( 4363664528273524411LLU), - QU(14313875763787479809LLU), QU(17059695613553486802LLU), - QU( 9247761425889940932LLU), QU(13704726459237593128LLU), - QU( 2701312427328909832LLU), QU(17235532008287243115LLU), - QU(14093147761491729538LLU), QU( 6247352273768386516LLU), - QU( 8268710048153268415LLU), QU( 7985295214477182083LLU), - QU(15624495190888896807LLU), QU( 3772753430045262788LLU), - QU( 9133991620474991698LLU), QU( 5665791943316256028LLU), - QU( 7551996832462193473LLU), QU(13163729206798953877LLU), - QU( 9263532074153846374LLU), QU( 1015460703698618353LLU), - QU(17929874696989519390LLU), QU(18257884721466153847LLU), - QU(16271867543011222991LLU), QU( 3905971519021791941LLU), - QU(16814488397137052085LLU), QU( 1321197685504621613LLU), - QU( 2870359191894002181LLU), QU(14317282970323395450LLU), - QU(13663920845511074366LLU), QU( 2052463995796539594LLU), - QU(14126345686431444337LLU), QU( 1727572121947022534LLU), - QU(17793552254485594241LLU), QU( 6738857418849205750LLU), - QU( 1282987123157442952LLU), QU(16655480021581159251LLU), - QU( 6784587032080183866LLU), QU(14726758805359965162LLU), - QU( 7577995933961987349LLU), QU(12539609320311114036LLU), - QU(10789773033385439494LLU), QU( 8517001497411158227LLU), - QU(10075543932136339710LLU), QU(14838152340938811081LLU), - QU( 9560840631794044194LLU), QU(17445736541454117475LLU), - QU(10633026464336393186LLU), QU(15705729708242246293LLU), - QU( 1117517596891411098LLU), QU( 4305657943415886942LLU), - QU( 4948856840533979263LLU), QU(16071681989041789593LLU), - QU(13723031429272486527LLU), QU( 7639567622306509462LLU), - QU(12670424537483090390LLU), QU( 9715223453097197134LLU), - QU( 5457173389992686394LLU), QU( 289857129276135145LLU), - QU(17048610270521972512LLU), QU( 692768013309835485LLU), - QU(14823232360546632057LLU), QU(18218002361317895936LLU), - QU( 3281724260212650204LLU), QU(16453957266549513795LLU), - QU( 8592711109774511881LLU), QU( 929825123473369579LLU), - QU(15966784769764367791LLU), QU( 9627344291450607588LLU), - QU(10849555504977813287LLU), QU( 9234566913936339275LLU), - QU( 6413807690366911210LLU), QU(10862389016184219267LLU), - QU(13842504799335374048LLU), QU( 1531994113376881174LLU), - QU( 2081314867544364459LLU), QU(16430628791616959932LLU), - QU( 8314714038654394368LLU), QU( 9155473892098431813LLU), - QU(12577843786670475704LLU), QU( 4399161106452401017LLU), - QU( 1668083091682623186LLU), QU( 1741383777203714216LLU), - QU( 2162597285417794374LLU), QU(15841980159165218736LLU), - QU( 1971354603551467079LLU), QU( 1206714764913205968LLU), - QU( 4790860439591272330LLU), QU(14699375615594055799LLU), - QU( 8374423871657449988LLU), QU(10950685736472937738LLU), - QU( 697344331343267176LLU), QU(10084998763118059810LLU), - QU(12897369539795983124LLU), QU(12351260292144383605LLU), - QU( 1268810970176811234LLU), QU( 7406287800414582768LLU), - QU( 516169557043807831LLU), QU( 5077568278710520380LLU), - QU( 3828791738309039304LLU), QU( 7721974069946943610LLU), - QU( 3534670260981096460LLU), QU( 4865792189600584891LLU), - QU(16892578493734337298LLU), QU( 9161499464278042590LLU), - QU(11976149624067055931LLU), QU(13219479887277343990LLU), - QU(14161556738111500680LLU), QU(14670715255011223056LLU), - QU( 4671205678403576558LLU), QU(12633022931454259781LLU), - QU(14821376219869187646LLU), QU( 751181776484317028LLU), - QU( 2192211308839047070LLU), QU(11787306362361245189LLU), - QU(10672375120744095707LLU), QU( 4601972328345244467LLU), - QU(15457217788831125879LLU), QU( 8464345256775460809LLU), - QU(10191938789487159478LLU), QU( 6184348739615197613LLU), - QU(11425436778806882100LLU), QU( 2739227089124319793LLU), - QU( 461464518456000551LLU), QU( 4689850170029177442LLU), - QU( 6120307814374078625LLU), QU(11153579230681708671LLU), - QU( 7891721473905347926LLU), QU(10281646937824872400LLU), - QU( 3026099648191332248LLU), QU( 8666750296953273818LLU), - QU(14978499698844363232LLU), QU(13303395102890132065LLU), - QU( 8182358205292864080LLU), QU(10560547713972971291LLU), - QU(11981635489418959093LLU), QU( 3134621354935288409LLU), - QU(11580681977404383968LLU), QU(14205530317404088650LLU), - QU( 5997789011854923157LLU), QU(13659151593432238041LLU), - QU(11664332114338865086LLU), QU( 7490351383220929386LLU), - QU( 7189290499881530378LLU), QU(15039262734271020220LLU), - QU( 2057217285976980055LLU), QU( 555570804905355739LLU), - QU(11235311968348555110LLU), QU(13824557146269603217LLU), - QU(16906788840653099693LLU), QU( 7222878245455661677LLU), - QU( 5245139444332423756LLU), QU( 4723748462805674292LLU), - QU(12216509815698568612LLU), QU(17402362976648951187LLU), - QU(17389614836810366768LLU), QU( 4880936484146667711LLU), - QU( 9085007839292639880LLU), QU(13837353458498535449LLU), - QU(11914419854360366677LLU), QU(16595890135313864103LLU), - QU( 6313969847197627222LLU), QU(18296909792163910431LLU), - QU(10041780113382084042LLU), QU( 2499478551172884794LLU), - QU(11057894246241189489LLU), QU( 9742243032389068555LLU), - QU(12838934582673196228LLU), QU(13437023235248490367LLU), - QU(13372420669446163240LLU), QU( 6752564244716909224LLU), - QU( 7157333073400313737LLU), QU(12230281516370654308LLU), - QU( 1182884552219419117LLU), QU( 2955125381312499218LLU), - QU(10308827097079443249LLU), QU( 1337648572986534958LLU), - QU(16378788590020343939LLU), QU( 108619126514420935LLU), - QU( 3990981009621629188LLU), QU( 5460953070230946410LLU), - QU( 9703328329366531883LLU), QU(13166631489188077236LLU), - QU( 1104768831213675170LLU), QU( 3447930458553877908LLU), - QU( 8067172487769945676LLU), QU( 5445802098190775347LLU), - QU( 3244840981648973873LLU), QU(17314668322981950060LLU), - QU( 5006812527827763807LLU), QU(18158695070225526260LLU), - QU( 2824536478852417853LLU), QU(13974775809127519886LLU), - QU( 9814362769074067392LLU), QU(17276205156374862128LLU), - QU(11361680725379306967LLU), QU( 3422581970382012542LLU), - QU(11003189603753241266LLU), QU(11194292945277862261LLU), - QU( 6839623313908521348LLU), QU(11935326462707324634LLU), - QU( 1611456788685878444LLU), QU(13112620989475558907LLU), - QU( 517659108904450427LLU), QU(13558114318574407624LLU), - QU(15699089742731633077LLU), QU( 4988979278862685458LLU), - QU( 8111373583056521297LLU), QU( 3891258746615399627LLU), - QU( 8137298251469718086LLU), QU(12748663295624701649LLU), - QU( 4389835683495292062LLU), QU( 5775217872128831729LLU), - QU( 9462091896405534927LLU), QU( 8498124108820263989LLU), - QU( 8059131278842839525LLU), QU(10503167994254090892LLU), - QU(11613153541070396656LLU), QU(18069248738504647790LLU), - QU( 570657419109768508LLU), QU( 3950574167771159665LLU), - QU( 5514655599604313077LLU), QU( 2908460854428484165LLU), - QU(10777722615935663114LLU), QU(12007363304839279486LLU), - QU( 9800646187569484767LLU), QU( 8795423564889864287LLU), - QU(14257396680131028419LLU), QU( 6405465117315096498LLU), - QU( 7939411072208774878LLU), QU(17577572378528990006LLU), - QU(14785873806715994850LLU), QU(16770572680854747390LLU), - QU(18127549474419396481LLU), QU(11637013449455757750LLU), - QU(14371851933996761086LLU), QU( 3601181063650110280LLU), - QU( 4126442845019316144LLU), QU(10198287239244320669LLU), - QU(18000169628555379659LLU), QU(18392482400739978269LLU), - QU( 6219919037686919957LLU), QU( 3610085377719446052LLU), - QU( 2513925039981776336LLU), QU(16679413537926716955LLU), - QU(12903302131714909434LLU), QU( 5581145789762985009LLU), - QU(12325955044293303233LLU), QU(17216111180742141204LLU), - QU( 6321919595276545740LLU), QU( 3507521147216174501LLU), - QU( 9659194593319481840LLU), QU(11473976005975358326LLU), - QU(14742730101435987026LLU), QU( 492845897709954780LLU), - QU(16976371186162599676LLU), QU(17712703422837648655LLU), - QU( 9881254778587061697LLU), QU( 8413223156302299551LLU), - QU( 1563841828254089168LLU), QU( 9996032758786671975LLU), - QU( 138877700583772667LLU), QU(13003043368574995989LLU), - QU( 4390573668650456587LLU), QU( 8610287390568126755LLU), - QU(15126904974266642199LLU), QU( 6703637238986057662LLU), - QU( 2873075592956810157LLU), QU( 6035080933946049418LLU), - QU(13382846581202353014LLU), QU( 7303971031814642463LLU), - QU(18418024405307444267LLU), QU( 5847096731675404647LLU), - QU( 4035880699639842500LLU), QU(11525348625112218478LLU), - QU( 3041162365459574102LLU), QU( 2604734487727986558LLU), - QU(15526341771636983145LLU), QU(14556052310697370254LLU), - QU(12997787077930808155LLU), QU( 9601806501755554499LLU), - QU(11349677952521423389LLU), QU(14956777807644899350LLU), - QU(16559736957742852721LLU), QU(12360828274778140726LLU), - QU( 6685373272009662513LLU), QU(16932258748055324130LLU), - QU(15918051131954158508LLU), QU( 1692312913140790144LLU), - QU( 546653826801637367LLU), QU( 5341587076045986652LLU), - QU(14975057236342585662LLU), QU(12374976357340622412LLU), - QU(10328833995181940552LLU), QU(12831807101710443149LLU), - QU(10548514914382545716LLU), QU( 2217806727199715993LLU), - QU(12627067369242845138LLU), QU( 4598965364035438158LLU), - QU( 150923352751318171LLU), QU(14274109544442257283LLU), - QU( 4696661475093863031LLU), QU( 1505764114384654516LLU), - QU(10699185831891495147LLU), QU( 2392353847713620519LLU), - QU( 3652870166711788383LLU), QU( 8640653276221911108LLU), - QU( 3894077592275889704LLU), QU( 4918592872135964845LLU), - QU(16379121273281400789LLU), QU(12058465483591683656LLU), - QU(11250106829302924945LLU), QU( 1147537556296983005LLU), - QU( 6376342756004613268LLU), QU(14967128191709280506LLU), - QU(18007449949790627628LLU), QU( 9497178279316537841LLU), - QU( 7920174844809394893LLU), QU(10037752595255719907LLU), - QU(15875342784985217697LLU), QU(15311615921712850696LLU), - QU( 9552902652110992950LLU), QU(14054979450099721140LLU), - QU( 5998709773566417349LLU), QU(18027910339276320187LLU), - QU( 8223099053868585554LLU), QU( 7842270354824999767LLU), - QU( 4896315688770080292LLU), QU(12969320296569787895LLU), - QU( 2674321489185759961LLU), QU( 4053615936864718439LLU), - QU(11349775270588617578LLU), QU( 4743019256284553975LLU), - QU( 5602100217469723769LLU), QU(14398995691411527813LLU), - QU( 7412170493796825470LLU), QU( 836262406131744846LLU), - QU( 8231086633845153022LLU), QU( 5161377920438552287LLU), - QU( 8828731196169924949LLU), QU(16211142246465502680LLU), - QU( 3307990879253687818LLU), QU( 5193405406899782022LLU), - QU( 8510842117467566693LLU), QU( 6070955181022405365LLU), - QU(14482950231361409799LLU), QU(12585159371331138077LLU), - QU( 3511537678933588148LLU), QU( 2041849474531116417LLU), - QU(10944936685095345792LLU), QU(18303116923079107729LLU), - QU( 2720566371239725320LLU), QU( 4958672473562397622LLU), - QU( 3032326668253243412LLU), QU(13689418691726908338LLU), - QU( 1895205511728843996LLU), QU( 8146303515271990527LLU), - QU(16507343500056113480LLU), QU( 473996939105902919LLU), - QU( 9897686885246881481LLU), QU(14606433762712790575LLU), - QU( 6732796251605566368LLU), QU( 1399778120855368916LLU), - QU( 935023885182833777LLU), QU(16066282816186753477LLU), - QU( 7291270991820612055LLU), QU(17530230393129853844LLU), - QU(10223493623477451366LLU), QU(15841725630495676683LLU), - QU(17379567246435515824LLU), QU( 8588251429375561971LLU), - QU(18339511210887206423LLU), QU(17349587430725976100LLU), - QU(12244876521394838088LLU), QU( 6382187714147161259LLU), - QU(12335807181848950831LLU), QU(16948885622305460665LLU), - QU(13755097796371520506LLU), QU(14806740373324947801LLU), - QU( 4828699633859287703LLU), QU( 8209879281452301604LLU), - QU(12435716669553736437LLU), QU(13970976859588452131LLU), - QU( 6233960842566773148LLU), QU(12507096267900505759LLU), - QU( 1198713114381279421LLU), QU(14989862731124149015LLU), - QU(15932189508707978949LLU), QU( 2526406641432708722LLU), - QU( 29187427817271982LLU), QU( 1499802773054556353LLU), - QU(10816638187021897173LLU), QU( 5436139270839738132LLU), - QU( 6659882287036010082LLU), QU( 2154048955317173697LLU), - QU(10887317019333757642LLU), QU(16281091802634424955LLU), - QU(10754549879915384901LLU), QU(10760611745769249815LLU), - QU( 2161505946972504002LLU), QU( 5243132808986265107LLU), - QU(10129852179873415416LLU), QU( 710339480008649081LLU), - QU( 7802129453068808528LLU), QU(17967213567178907213LLU), - QU(15730859124668605599LLU), QU(13058356168962376502LLU), - QU( 3701224985413645909LLU), QU(14464065869149109264LLU), - QU( 9959272418844311646LLU), QU(10157426099515958752LLU), - QU(14013736814538268528LLU), QU(17797456992065653951LLU), - QU(17418878140257344806LLU), QU(15457429073540561521LLU), - QU( 2184426881360949378LLU), QU( 2062193041154712416LLU), - QU( 8553463347406931661LLU), QU( 4913057625202871854LLU), - QU( 2668943682126618425LLU), QU(17064444737891172288LLU), - QU( 4997115903913298637LLU), QU(12019402608892327416LLU), - QU(17603584559765897352LLU), QU(11367529582073647975LLU), - QU( 8211476043518436050LLU), QU( 8676849804070323674LLU), - QU(18431829230394475730LLU), QU(10490177861361247904LLU), - QU( 9508720602025651349LLU), QU( 7409627448555722700LLU), - QU( 5804047018862729008LLU), QU(11943858176893142594LLU), - QU(11908095418933847092LLU), QU( 5415449345715887652LLU), - QU( 1554022699166156407LLU), QU( 9073322106406017161LLU), - QU( 7080630967969047082LLU), QU(18049736940860732943LLU), - QU(12748714242594196794LLU), QU( 1226992415735156741LLU), - QU(17900981019609531193LLU), QU(11720739744008710999LLU), - QU( 3006400683394775434LLU), QU(11347974011751996028LLU), - QU( 3316999628257954608LLU), QU( 8384484563557639101LLU), - QU(18117794685961729767LLU), QU( 1900145025596618194LLU), - QU(17459527840632892676LLU), QU( 5634784101865710994LLU), - QU( 7918619300292897158LLU), QU( 3146577625026301350LLU), - QU( 9955212856499068767LLU), QU( 1873995843681746975LLU), - QU( 1561487759967972194LLU), QU( 8322718804375878474LLU), - QU(11300284215327028366LLU), QU( 4667391032508998982LLU), - QU( 9820104494306625580LLU), QU(17922397968599970610LLU), - QU( 1784690461886786712LLU), QU(14940365084341346821LLU), - QU( 5348719575594186181LLU), QU(10720419084507855261LLU), - QU(14210394354145143274LLU), QU( 2426468692164000131LLU), - QU(16271062114607059202LLU), QU(14851904092357070247LLU), - QU( 6524493015693121897LLU), QU( 9825473835127138531LLU), - QU(14222500616268569578LLU), QU(15521484052007487468LLU), - QU(14462579404124614699LLU), QU(11012375590820665520LLU), - QU(11625327350536084927LLU), QU(14452017765243785417LLU), - QU( 9989342263518766305LLU), QU( 3640105471101803790LLU), - QU( 4749866455897513242LLU), QU(13963064946736312044LLU), - QU(10007416591973223791LLU), QU(18314132234717431115LLU), - QU( 3286596588617483450LLU), QU( 7726163455370818765LLU), - QU( 7575454721115379328LLU), QU( 5308331576437663422LLU), - QU(18288821894903530934LLU), QU( 8028405805410554106LLU), - QU(15744019832103296628LLU), QU( 149765559630932100LLU), - QU( 6137705557200071977LLU), QU(14513416315434803615LLU), - QU(11665702820128984473LLU), QU( 218926670505601386LLU), - QU( 6868675028717769519LLU), QU(15282016569441512302LLU), - QU( 5707000497782960236LLU), QU( 6671120586555079567LLU), - QU( 2194098052618985448LLU), QU(16849577895477330978LLU), - QU(12957148471017466283LLU), QU( 1997805535404859393LLU), - QU( 1180721060263860490LLU), QU(13206391310193756958LLU), - QU(12980208674461861797LLU), QU( 3825967775058875366LLU), - QU(17543433670782042631LLU), QU( 1518339070120322730LLU), - QU(16344584340890991669LLU), QU( 2611327165318529819LLU), - QU(11265022723283422529LLU), QU( 4001552800373196817LLU), - QU(14509595890079346161LLU), QU( 3528717165416234562LLU), - QU(18153222571501914072LLU), QU( 9387182977209744425LLU), - QU(10064342315985580021LLU), QU(11373678413215253977LLU), - QU( 2308457853228798099LLU), QU( 9729042942839545302LLU), - QU( 7833785471140127746LLU), QU( 6351049900319844436LLU), - QU(14454610627133496067LLU), QU(12533175683634819111LLU), - QU(15570163926716513029LLU), QU(13356980519185762498LLU) + KQU( 2100341266307895239), KQU( 8344256300489757943), + KQU(15687933285484243894), KQU( 8268620370277076319), + KQU(12371852309826545459), KQU( 8800491541730110238), + KQU(18113268950100835773), KQU( 2886823658884438119), + KQU( 3293667307248180724), KQU( 9307928143300172731), + KQU( 7688082017574293629), KQU( 900986224735166665), + KQU( 9977972710722265039), KQU( 6008205004994830552), + KQU( 546909104521689292), KQU( 7428471521869107594), + KQU(14777563419314721179), KQU(16116143076567350053), + KQU( 5322685342003142329), KQU( 4200427048445863473), + KQU( 4693092150132559146), KQU(13671425863759338582), + KQU( 6747117460737639916), KQU( 4732666080236551150), + KQU( 5912839950611941263), KQU( 3903717554504704909), + KQU( 2615667650256786818), KQU(10844129913887006352), + KQU(13786467861810997820), KQU(14267853002994021570), + KQU(13767807302847237439), KQU(16407963253707224617), + KQU( 4802498363698583497), KQU( 2523802839317209764), + KQU( 3822579397797475589), KQU( 8950320572212130610), + KQU( 3745623504978342534), KQU(16092609066068482806), + KQU( 9817016950274642398), KQU(10591660660323829098), + KQU(11751606650792815920), KQU( 5122873818577122211), + KQU(17209553764913936624), KQU( 6249057709284380343), + KQU(15088791264695071830), KQU(15344673071709851930), + KQU( 4345751415293646084), KQU( 2542865750703067928), + KQU(13520525127852368784), KQU(18294188662880997241), + KQU( 3871781938044881523), KQU( 2873487268122812184), + KQU(15099676759482679005), KQU(15442599127239350490), + KQU( 6311893274367710888), KQU( 3286118760484672933), + KQU( 4146067961333542189), KQU(13303942567897208770), + KQU( 8196013722255630418), KQU( 4437815439340979989), + KQU(15433791533450605135), KQU( 4254828956815687049), + KQU( 1310903207708286015), KQU(10529182764462398549), + KQU(14900231311660638810), KQU( 9727017277104609793), + KQU( 1821308310948199033), KQU(11628861435066772084), + KQU( 9469019138491546924), KQU( 3145812670532604988), + KQU( 9938468915045491919), KQU( 1562447430672662142), + KQU(13963995266697989134), KQU( 3356884357625028695), + KQU( 4499850304584309747), KQU( 8456825817023658122), + KQU(10859039922814285279), KQU( 8099512337972526555), + KQU( 348006375109672149), KQU(11919893998241688603), + KQU( 1104199577402948826), KQU(16689191854356060289), + KQU(10992552041730168078), KQU( 7243733172705465836), + KQU( 5668075606180319560), KQU(18182847037333286970), + KQU( 4290215357664631322), KQU( 4061414220791828613), + KQU(13006291061652989604), KQU( 7140491178917128798), + KQU(12703446217663283481), KQU( 5500220597564558267), + KQU(10330551509971296358), KQU(15958554768648714492), + KQU( 5174555954515360045), KQU( 1731318837687577735), + KQU( 3557700801048354857), KQU(13764012341928616198), + KQU(13115166194379119043), KQU( 7989321021560255519), + KQU( 2103584280905877040), KQU( 9230788662155228488), + KQU(16396629323325547654), KQU( 657926409811318051), + KQU(15046700264391400727), KQU( 5120132858771880830), + KQU( 7934160097989028561), KQU( 6963121488531976245), + KQU(17412329602621742089), KQU(15144843053931774092), + KQU(17204176651763054532), KQU(13166595387554065870), + KQU( 8590377810513960213), KQU( 5834365135373991938), + KQU( 7640913007182226243), KQU( 3479394703859418425), + KQU(16402784452644521040), KQU( 4993979809687083980), + KQU(13254522168097688865), KQU(15643659095244365219), + KQU( 5881437660538424982), KQU(11174892200618987379), + KQU( 254409966159711077), KQU(17158413043140549909), + KQU( 3638048789290376272), KQU( 1376816930299489190), + KQU( 4622462095217761923), KQU(15086407973010263515), + KQU(13253971772784692238), KQU( 5270549043541649236), + KQU(11182714186805411604), KQU(12283846437495577140), + KQU( 5297647149908953219), KQU(10047451738316836654), + KQU( 4938228100367874746), KQU(12328523025304077923), + KQU( 3601049438595312361), KQU( 9313624118352733770), + KQU(13322966086117661798), KQU(16660005705644029394), + KQU(11337677526988872373), KQU(13869299102574417795), + KQU(15642043183045645437), KQU( 3021755569085880019), + KQU( 4979741767761188161), KQU(13679979092079279587), + KQU( 3344685842861071743), KQU(13947960059899588104), + KQU( 305806934293368007), KQU( 5749173929201650029), + KQU(11123724852118844098), KQU(15128987688788879802), + KQU(15251651211024665009), KQU( 7689925933816577776), + KQU(16732804392695859449), KQU(17087345401014078468), + KQU(14315108589159048871), KQU( 4820700266619778917), + KQU(16709637539357958441), KQU( 4936227875177351374), + KQU( 2137907697912987247), KQU(11628565601408395420), + KQU( 2333250549241556786), KQU( 5711200379577778637), + KQU( 5170680131529031729), KQU(12620392043061335164), + KQU( 95363390101096078), KQU( 5487981914081709462), + KQU( 1763109823981838620), KQU( 3395861271473224396), + KQU( 1300496844282213595), KQU( 6894316212820232902), + KQU(10673859651135576674), KQU( 5911839658857903252), + KQU(17407110743387299102), KQU( 8257427154623140385), + KQU(11389003026741800267), KQU( 4070043211095013717), + KQU(11663806997145259025), KQU(15265598950648798210), + KQU( 630585789434030934), KQU( 3524446529213587334), + KQU( 7186424168495184211), KQU(10806585451386379021), + KQU(11120017753500499273), KQU( 1586837651387701301), + KQU(17530454400954415544), KQU( 9991670045077880430), + KQU( 7550997268990730180), KQU( 8640249196597379304), + KQU( 3522203892786893823), KQU(10401116549878854788), + KQU(13690285544733124852), KQU( 8295785675455774586), + KQU(15535716172155117603), KQU( 3112108583723722511), + KQU(17633179955339271113), KQU(18154208056063759375), + KQU( 1866409236285815666), KQU(13326075895396412882), + KQU( 8756261842948020025), KQU( 6281852999868439131), + KQU(15087653361275292858), KQU(10333923911152949397), + KQU( 5265567645757408500), KQU(12728041843210352184), + KQU( 6347959327507828759), KQU( 154112802625564758), + KQU(18235228308679780218), KQU( 3253805274673352418), + KQU( 4849171610689031197), KQU(17948529398340432518), + KQU(13803510475637409167), KQU(13506570190409883095), + KQU(15870801273282960805), KQU( 8451286481299170773), + KQU( 9562190620034457541), KQU( 8518905387449138364), + KQU(12681306401363385655), KQU( 3788073690559762558), + KQU( 5256820289573487769), KQU( 2752021372314875467), + KQU( 6354035166862520716), KQU( 4328956378309739069), + KQU( 449087441228269600), KQU( 5533508742653090868), + KQU( 1260389420404746988), KQU(18175394473289055097), + KQU( 1535467109660399420), KQU( 8818894282874061442), + KQU(12140873243824811213), KQU(15031386653823014946), + KQU( 1286028221456149232), KQU( 6329608889367858784), + KQU( 9419654354945132725), KQU( 6094576547061672379), + KQU(17706217251847450255), KQU( 1733495073065878126), + KQU(16918923754607552663), KQU( 8881949849954945044), + KQU(12938977706896313891), KQU(14043628638299793407), + KQU(18393874581723718233), KQU( 6886318534846892044), + KQU(14577870878038334081), KQU(13541558383439414119), + KQU(13570472158807588273), KQU(18300760537910283361), + KQU( 818368572800609205), KQU( 1417000585112573219), + KQU(12337533143867683655), KQU(12433180994702314480), + KQU( 778190005829189083), KQU(13667356216206524711), + KQU( 9866149895295225230), KQU(11043240490417111999), + KQU( 1123933826541378598), KQU( 6469631933605123610), + KQU(14508554074431980040), KQU(13918931242962026714), + KQU( 2870785929342348285), KQU(14786362626740736974), + KQU(13176680060902695786), KQU( 9591778613541679456), + KQU( 9097662885117436706), KQU( 749262234240924947), + KQU( 1944844067793307093), KQU( 4339214904577487742), + KQU( 8009584152961946551), KQU(16073159501225501777), + KQU( 3335870590499306217), KQU(17088312653151202847), + KQU( 3108893142681931848), KQU(16636841767202792021), + KQU(10423316431118400637), KQU( 8008357368674443506), + KQU(11340015231914677875), KQU(17687896501594936090), + KQU(15173627921763199958), KQU( 542569482243721959), + KQU(15071714982769812975), KQU( 4466624872151386956), + KQU( 1901780715602332461), KQU( 9822227742154351098), + KQU( 1479332892928648780), KQU( 6981611948382474400), + KQU( 7620824924456077376), KQU(14095973329429406782), + KQU( 7902744005696185404), KQU(15830577219375036920), + KQU(10287076667317764416), KQU(12334872764071724025), + KQU( 4419302088133544331), KQU(14455842851266090520), + KQU(12488077416504654222), KQU( 7953892017701886766), + KQU( 6331484925529519007), KQU( 4902145853785030022), + KQU(17010159216096443073), KQU(11945354668653886087), + KQU(15112022728645230829), KQU(17363484484522986742), + KQU( 4423497825896692887), KQU( 8155489510809067471), + KQU( 258966605622576285), KQU( 5462958075742020534), + KQU( 6763710214913276228), KQU( 2368935183451109054), + KQU(14209506165246453811), KQU( 2646257040978514881), + KQU( 3776001911922207672), KQU( 1419304601390147631), + KQU(14987366598022458284), KQU( 3977770701065815721), + KQU( 730820417451838898), KQU( 3982991703612885327), + KQU( 2803544519671388477), KQU(17067667221114424649), + KQU( 2922555119737867166), KQU( 1989477584121460932), + KQU(15020387605892337354), KQU( 9293277796427533547), + KQU(10722181424063557247), KQU(16704542332047511651), + KQU( 5008286236142089514), KQU(16174732308747382540), + KQU(17597019485798338402), KQU(13081745199110622093), + KQU( 8850305883842258115), KQU(12723629125624589005), + KQU( 8140566453402805978), KQU(15356684607680935061), + KQU(14222190387342648650), KQU(11134610460665975178), + KQU( 1259799058620984266), KQU(13281656268025610041), + KQU( 298262561068153992), KQU(12277871700239212922), + KQU(13911297774719779438), KQU(16556727962761474934), + KQU(17903010316654728010), KQU( 9682617699648434744), + KQU(14757681836838592850), KQU( 1327242446558524473), + KQU(11126645098780572792), KQU( 1883602329313221774), + KQU( 2543897783922776873), KQU(15029168513767772842), + KQU(12710270651039129878), KQU(16118202956069604504), + KQU(15010759372168680524), KQU( 2296827082251923948), + KQU(10793729742623518101), KQU(13829764151845413046), + KQU(17769301223184451213), KQU( 3118268169210783372), + KQU(17626204544105123127), KQU( 7416718488974352644), + KQU(10450751996212925994), KQU( 9352529519128770586), + KQU( 259347569641110140), KQU( 8048588892269692697), + KQU( 1774414152306494058), KQU(10669548347214355622), + KQU(13061992253816795081), KQU(18432677803063861659), + KQU( 8879191055593984333), KQU(12433753195199268041), + KQU(14919392415439730602), KQU( 6612848378595332963), + KQU( 6320986812036143628), KQU(10465592420226092859), + KQU( 4196009278962570808), KQU( 3747816564473572224), + KQU(17941203486133732898), KQU( 2350310037040505198), + KQU( 5811779859134370113), KQU(10492109599506195126), + KQU( 7699650690179541274), KQU( 1954338494306022961), + KQU(14095816969027231152), KQU( 5841346919964852061), + KQU(14945969510148214735), KQU( 3680200305887550992), + KQU( 6218047466131695792), KQU( 8242165745175775096), + KQU(11021371934053307357), KQU( 1265099502753169797), + KQU( 4644347436111321718), KQU( 3609296916782832859), + KQU( 8109807992218521571), KQU(18387884215648662020), + KQU(14656324896296392902), KQU(17386819091238216751), + KQU(17788300878582317152), KQU( 7919446259742399591), + KQU( 4466613134576358004), KQU(12928181023667938509), + KQU(13147446154454932030), KQU(16552129038252734620), + KQU( 8395299403738822450), KQU(11313817655275361164), + KQU( 434258809499511718), KQU( 2074882104954788676), + KQU( 7929892178759395518), KQU( 9006461629105745388), + KQU( 5176475650000323086), KQU(11128357033468341069), + KQU(12026158851559118955), KQU(14699716249471156500), + KQU( 448982497120206757), KQU( 4156475356685519900), + KQU( 6063816103417215727), KQU(10073289387954971479), + KQU( 8174466846138590962), KQU( 2675777452363449006), + KQU( 9090685420572474281), KQU( 6659652652765562060), + KQU(12923120304018106621), KQU(11117480560334526775), + KQU( 937910473424587511), KQU( 1838692113502346645), + KQU(11133914074648726180), KQU( 7922600945143884053), + KQU(13435287702700959550), KQU( 5287964921251123332), + KQU(11354875374575318947), KQU(17955724760748238133), + KQU(13728617396297106512), KQU( 4107449660118101255), + KQU( 1210269794886589623), KQU(11408687205733456282), + KQU( 4538354710392677887), KQU(13566803319341319267), + KQU(17870798107734050771), KQU( 3354318982568089135), + KQU( 9034450839405133651), KQU(13087431795753424314), + KQU( 950333102820688239), KQU( 1968360654535604116), + KQU(16840551645563314995), KQU( 8867501803892924995), + KQU(11395388644490626845), KQU( 1529815836300732204), + KQU(13330848522996608842), KQU( 1813432878817504265), + KQU( 2336867432693429560), KQU(15192805445973385902), + KQU( 2528593071076407877), KQU( 128459777936689248), + KQU( 9976345382867214866), KQU( 6208885766767996043), + KQU(14982349522273141706), KQU( 3099654362410737822), + KQU(13776700761947297661), KQU( 8806185470684925550), + KQU( 8151717890410585321), KQU( 640860591588072925), + KQU(14592096303937307465), KQU( 9056472419613564846), + KQU(14861544647742266352), KQU(12703771500398470216), + KQU( 3142372800384138465), KQU( 6201105606917248196), + KQU(18337516409359270184), KQU(15042268695665115339), + KQU(15188246541383283846), KQU(12800028693090114519), + KQU( 5992859621101493472), KQU(18278043971816803521), + KQU( 9002773075219424560), KQU( 7325707116943598353), + KQU( 7930571931248040822), KQU( 5645275869617023448), + KQU( 7266107455295958487), KQU( 4363664528273524411), + KQU(14313875763787479809), KQU(17059695613553486802), + KQU( 9247761425889940932), KQU(13704726459237593128), + KQU( 2701312427328909832), KQU(17235532008287243115), + KQU(14093147761491729538), KQU( 6247352273768386516), + KQU( 8268710048153268415), KQU( 7985295214477182083), + KQU(15624495190888896807), KQU( 3772753430045262788), + KQU( 9133991620474991698), KQU( 5665791943316256028), + KQU( 7551996832462193473), KQU(13163729206798953877), + KQU( 9263532074153846374), KQU( 1015460703698618353), + KQU(17929874696989519390), KQU(18257884721466153847), + KQU(16271867543011222991), KQU( 3905971519021791941), + KQU(16814488397137052085), KQU( 1321197685504621613), + KQU( 2870359191894002181), KQU(14317282970323395450), + KQU(13663920845511074366), KQU( 2052463995796539594), + KQU(14126345686431444337), KQU( 1727572121947022534), + KQU(17793552254485594241), KQU( 6738857418849205750), + KQU( 1282987123157442952), KQU(16655480021581159251), + KQU( 6784587032080183866), KQU(14726758805359965162), + KQU( 7577995933961987349), KQU(12539609320311114036), + KQU(10789773033385439494), KQU( 8517001497411158227), + KQU(10075543932136339710), KQU(14838152340938811081), + KQU( 9560840631794044194), KQU(17445736541454117475), + KQU(10633026464336393186), KQU(15705729708242246293), + KQU( 1117517596891411098), KQU( 4305657943415886942), + KQU( 4948856840533979263), KQU(16071681989041789593), + KQU(13723031429272486527), KQU( 7639567622306509462), + KQU(12670424537483090390), KQU( 9715223453097197134), + KQU( 5457173389992686394), KQU( 289857129276135145), + KQU(17048610270521972512), KQU( 692768013309835485), + KQU(14823232360546632057), KQU(18218002361317895936), + KQU( 3281724260212650204), KQU(16453957266549513795), + KQU( 8592711109774511881), KQU( 929825123473369579), + KQU(15966784769764367791), KQU( 9627344291450607588), + KQU(10849555504977813287), KQU( 9234566913936339275), + KQU( 6413807690366911210), KQU(10862389016184219267), + KQU(13842504799335374048), KQU( 1531994113376881174), + KQU( 2081314867544364459), KQU(16430628791616959932), + KQU( 8314714038654394368), KQU( 9155473892098431813), + KQU(12577843786670475704), KQU( 4399161106452401017), + KQU( 1668083091682623186), KQU( 1741383777203714216), + KQU( 2162597285417794374), KQU(15841980159165218736), + KQU( 1971354603551467079), KQU( 1206714764913205968), + KQU( 4790860439591272330), KQU(14699375615594055799), + KQU( 8374423871657449988), KQU(10950685736472937738), + KQU( 697344331343267176), KQU(10084998763118059810), + KQU(12897369539795983124), KQU(12351260292144383605), + KQU( 1268810970176811234), KQU( 7406287800414582768), + KQU( 516169557043807831), KQU( 5077568278710520380), + KQU( 3828791738309039304), KQU( 7721974069946943610), + KQU( 3534670260981096460), KQU( 4865792189600584891), + KQU(16892578493734337298), KQU( 9161499464278042590), + KQU(11976149624067055931), KQU(13219479887277343990), + KQU(14161556738111500680), KQU(14670715255011223056), + KQU( 4671205678403576558), KQU(12633022931454259781), + KQU(14821376219869187646), KQU( 751181776484317028), + KQU( 2192211308839047070), KQU(11787306362361245189), + KQU(10672375120744095707), KQU( 4601972328345244467), + KQU(15457217788831125879), KQU( 8464345256775460809), + KQU(10191938789487159478), KQU( 6184348739615197613), + KQU(11425436778806882100), KQU( 2739227089124319793), + KQU( 461464518456000551), KQU( 4689850170029177442), + KQU( 6120307814374078625), KQU(11153579230681708671), + KQU( 7891721473905347926), KQU(10281646937824872400), + KQU( 3026099648191332248), KQU( 8666750296953273818), + KQU(14978499698844363232), KQU(13303395102890132065), + KQU( 8182358205292864080), KQU(10560547713972971291), + KQU(11981635489418959093), KQU( 3134621354935288409), + KQU(11580681977404383968), KQU(14205530317404088650), + KQU( 5997789011854923157), KQU(13659151593432238041), + KQU(11664332114338865086), KQU( 7490351383220929386), + KQU( 7189290499881530378), KQU(15039262734271020220), + KQU( 2057217285976980055), KQU( 555570804905355739), + KQU(11235311968348555110), KQU(13824557146269603217), + KQU(16906788840653099693), KQU( 7222878245455661677), + KQU( 5245139444332423756), KQU( 4723748462805674292), + KQU(12216509815698568612), KQU(17402362976648951187), + KQU(17389614836810366768), KQU( 4880936484146667711), + KQU( 9085007839292639880), KQU(13837353458498535449), + KQU(11914419854360366677), KQU(16595890135313864103), + KQU( 6313969847197627222), KQU(18296909792163910431), + KQU(10041780113382084042), KQU( 2499478551172884794), + KQU(11057894246241189489), KQU( 9742243032389068555), + KQU(12838934582673196228), KQU(13437023235248490367), + KQU(13372420669446163240), KQU( 6752564244716909224), + KQU( 7157333073400313737), KQU(12230281516370654308), + KQU( 1182884552219419117), KQU( 2955125381312499218), + KQU(10308827097079443249), KQU( 1337648572986534958), + KQU(16378788590020343939), KQU( 108619126514420935), + KQU( 3990981009621629188), KQU( 5460953070230946410), + KQU( 9703328329366531883), KQU(13166631489188077236), + KQU( 1104768831213675170), KQU( 3447930458553877908), + KQU( 8067172487769945676), KQU( 5445802098190775347), + KQU( 3244840981648973873), KQU(17314668322981950060), + KQU( 5006812527827763807), KQU(18158695070225526260), + KQU( 2824536478852417853), KQU(13974775809127519886), + KQU( 9814362769074067392), KQU(17276205156374862128), + KQU(11361680725379306967), KQU( 3422581970382012542), + KQU(11003189603753241266), KQU(11194292945277862261), + KQU( 6839623313908521348), KQU(11935326462707324634), + KQU( 1611456788685878444), KQU(13112620989475558907), + KQU( 517659108904450427), KQU(13558114318574407624), + KQU(15699089742731633077), KQU( 4988979278862685458), + KQU( 8111373583056521297), KQU( 3891258746615399627), + KQU( 8137298251469718086), KQU(12748663295624701649), + KQU( 4389835683495292062), KQU( 5775217872128831729), + KQU( 9462091896405534927), KQU( 8498124108820263989), + KQU( 8059131278842839525), KQU(10503167994254090892), + KQU(11613153541070396656), KQU(18069248738504647790), + KQU( 570657419109768508), KQU( 3950574167771159665), + KQU( 5514655599604313077), KQU( 2908460854428484165), + KQU(10777722615935663114), KQU(12007363304839279486), + KQU( 9800646187569484767), KQU( 8795423564889864287), + KQU(14257396680131028419), KQU( 6405465117315096498), + KQU( 7939411072208774878), KQU(17577572378528990006), + KQU(14785873806715994850), KQU(16770572680854747390), + KQU(18127549474419396481), KQU(11637013449455757750), + KQU(14371851933996761086), KQU( 3601181063650110280), + KQU( 4126442845019316144), KQU(10198287239244320669), + KQU(18000169628555379659), KQU(18392482400739978269), + KQU( 6219919037686919957), KQU( 3610085377719446052), + KQU( 2513925039981776336), KQU(16679413537926716955), + KQU(12903302131714909434), KQU( 5581145789762985009), + KQU(12325955044293303233), KQU(17216111180742141204), + KQU( 6321919595276545740), KQU( 3507521147216174501), + KQU( 9659194593319481840), KQU(11473976005975358326), + KQU(14742730101435987026), KQU( 492845897709954780), + KQU(16976371186162599676), KQU(17712703422837648655), + KQU( 9881254778587061697), KQU( 8413223156302299551), + KQU( 1563841828254089168), KQU( 9996032758786671975), + KQU( 138877700583772667), KQU(13003043368574995989), + KQU( 4390573668650456587), KQU( 8610287390568126755), + KQU(15126904974266642199), KQU( 6703637238986057662), + KQU( 2873075592956810157), KQU( 6035080933946049418), + KQU(13382846581202353014), KQU( 7303971031814642463), + KQU(18418024405307444267), KQU( 5847096731675404647), + KQU( 4035880699639842500), KQU(11525348625112218478), + KQU( 3041162365459574102), KQU( 2604734487727986558), + KQU(15526341771636983145), KQU(14556052310697370254), + KQU(12997787077930808155), KQU( 9601806501755554499), + KQU(11349677952521423389), KQU(14956777807644899350), + KQU(16559736957742852721), KQU(12360828274778140726), + KQU( 6685373272009662513), KQU(16932258748055324130), + KQU(15918051131954158508), KQU( 1692312913140790144), + KQU( 546653826801637367), KQU( 5341587076045986652), + KQU(14975057236342585662), KQU(12374976357340622412), + KQU(10328833995181940552), KQU(12831807101710443149), + KQU(10548514914382545716), KQU( 2217806727199715993), + KQU(12627067369242845138), KQU( 4598965364035438158), + KQU( 150923352751318171), KQU(14274109544442257283), + KQU( 4696661475093863031), KQU( 1505764114384654516), + KQU(10699185831891495147), KQU( 2392353847713620519), + KQU( 3652870166711788383), KQU( 8640653276221911108), + KQU( 3894077592275889704), KQU( 4918592872135964845), + KQU(16379121273281400789), KQU(12058465483591683656), + KQU(11250106829302924945), KQU( 1147537556296983005), + KQU( 6376342756004613268), KQU(14967128191709280506), + KQU(18007449949790627628), KQU( 9497178279316537841), + KQU( 7920174844809394893), KQU(10037752595255719907), + KQU(15875342784985217697), KQU(15311615921712850696), + KQU( 9552902652110992950), KQU(14054979450099721140), + KQU( 5998709773566417349), KQU(18027910339276320187), + KQU( 8223099053868585554), KQU( 7842270354824999767), + KQU( 4896315688770080292), KQU(12969320296569787895), + KQU( 2674321489185759961), KQU( 4053615936864718439), + KQU(11349775270588617578), KQU( 4743019256284553975), + KQU( 5602100217469723769), KQU(14398995691411527813), + KQU( 7412170493796825470), KQU( 836262406131744846), + KQU( 8231086633845153022), KQU( 5161377920438552287), + KQU( 8828731196169924949), KQU(16211142246465502680), + KQU( 3307990879253687818), KQU( 5193405406899782022), + KQU( 8510842117467566693), KQU( 6070955181022405365), + KQU(14482950231361409799), KQU(12585159371331138077), + KQU( 3511537678933588148), KQU( 2041849474531116417), + KQU(10944936685095345792), KQU(18303116923079107729), + KQU( 2720566371239725320), KQU( 4958672473562397622), + KQU( 3032326668253243412), KQU(13689418691726908338), + KQU( 1895205511728843996), KQU( 8146303515271990527), + KQU(16507343500056113480), KQU( 473996939105902919), + KQU( 9897686885246881481), KQU(14606433762712790575), + KQU( 6732796251605566368), KQU( 1399778120855368916), + KQU( 935023885182833777), KQU(16066282816186753477), + KQU( 7291270991820612055), KQU(17530230393129853844), + KQU(10223493623477451366), KQU(15841725630495676683), + KQU(17379567246435515824), KQU( 8588251429375561971), + KQU(18339511210887206423), KQU(17349587430725976100), + KQU(12244876521394838088), KQU( 6382187714147161259), + KQU(12335807181848950831), KQU(16948885622305460665), + KQU(13755097796371520506), KQU(14806740373324947801), + KQU( 4828699633859287703), KQU( 8209879281452301604), + KQU(12435716669553736437), KQU(13970976859588452131), + KQU( 6233960842566773148), KQU(12507096267900505759), + KQU( 1198713114381279421), KQU(14989862731124149015), + KQU(15932189508707978949), KQU( 2526406641432708722), + KQU( 29187427817271982), KQU( 1499802773054556353), + KQU(10816638187021897173), KQU( 5436139270839738132), + KQU( 6659882287036010082), KQU( 2154048955317173697), + KQU(10887317019333757642), KQU(16281091802634424955), + KQU(10754549879915384901), KQU(10760611745769249815), + KQU( 2161505946972504002), KQU( 5243132808986265107), + KQU(10129852179873415416), KQU( 710339480008649081), + KQU( 7802129453068808528), KQU(17967213567178907213), + KQU(15730859124668605599), KQU(13058356168962376502), + KQU( 3701224985413645909), KQU(14464065869149109264), + KQU( 9959272418844311646), KQU(10157426099515958752), + KQU(14013736814538268528), KQU(17797456992065653951), + KQU(17418878140257344806), KQU(15457429073540561521), + KQU( 2184426881360949378), KQU( 2062193041154712416), + KQU( 8553463347406931661), KQU( 4913057625202871854), + KQU( 2668943682126618425), KQU(17064444737891172288), + KQU( 4997115903913298637), KQU(12019402608892327416), + KQU(17603584559765897352), KQU(11367529582073647975), + KQU( 8211476043518436050), KQU( 8676849804070323674), + KQU(18431829230394475730), KQU(10490177861361247904), + KQU( 9508720602025651349), KQU( 7409627448555722700), + KQU( 5804047018862729008), KQU(11943858176893142594), + KQU(11908095418933847092), KQU( 5415449345715887652), + KQU( 1554022699166156407), KQU( 9073322106406017161), + KQU( 7080630967969047082), KQU(18049736940860732943), + KQU(12748714242594196794), KQU( 1226992415735156741), + KQU(17900981019609531193), KQU(11720739744008710999), + KQU( 3006400683394775434), KQU(11347974011751996028), + KQU( 3316999628257954608), KQU( 8384484563557639101), + KQU(18117794685961729767), KQU( 1900145025596618194), + KQU(17459527840632892676), KQU( 5634784101865710994), + KQU( 7918619300292897158), KQU( 3146577625026301350), + KQU( 9955212856499068767), KQU( 1873995843681746975), + KQU( 1561487759967972194), KQU( 8322718804375878474), + KQU(11300284215327028366), KQU( 4667391032508998982), + KQU( 9820104494306625580), KQU(17922397968599970610), + KQU( 1784690461886786712), KQU(14940365084341346821), + KQU( 5348719575594186181), KQU(10720419084507855261), + KQU(14210394354145143274), KQU( 2426468692164000131), + KQU(16271062114607059202), KQU(14851904092357070247), + KQU( 6524493015693121897), KQU( 9825473835127138531), + KQU(14222500616268569578), KQU(15521484052007487468), + KQU(14462579404124614699), KQU(11012375590820665520), + KQU(11625327350536084927), KQU(14452017765243785417), + KQU( 9989342263518766305), KQU( 3640105471101803790), + KQU( 4749866455897513242), KQU(13963064946736312044), + KQU(10007416591973223791), KQU(18314132234717431115), + KQU( 3286596588617483450), KQU( 7726163455370818765), + KQU( 7575454721115379328), KQU( 5308331576437663422), + KQU(18288821894903530934), KQU( 8028405805410554106), + KQU(15744019832103296628), KQU( 149765559630932100), + KQU( 6137705557200071977), KQU(14513416315434803615), + KQU(11665702820128984473), KQU( 218926670505601386), + KQU( 6868675028717769519), KQU(15282016569441512302), + KQU( 5707000497782960236), KQU( 6671120586555079567), + KQU( 2194098052618985448), KQU(16849577895477330978), + KQU(12957148471017466283), KQU( 1997805535404859393), + KQU( 1180721060263860490), KQU(13206391310193756958), + KQU(12980208674461861797), KQU( 3825967775058875366), + KQU(17543433670782042631), KQU( 1518339070120322730), + KQU(16344584340890991669), KQU( 2611327165318529819), + KQU(11265022723283422529), KQU( 4001552800373196817), + KQU(14509595890079346161), KQU( 3528717165416234562), + KQU(18153222571501914072), KQU( 9387182977209744425), + KQU(10064342315985580021), KQU(11373678413215253977), + KQU( 2308457853228798099), KQU( 9729042942839545302), + KQU( 7833785471140127746), KQU( 6351049900319844436), + KQU(14454610627133496067), KQU(12533175683634819111), + KQU(15570163926716513029), KQU(13356980519185762498) }; TEST_BEGIN(test_gen_rand_32) diff --git a/src/jemalloc/test/unit/hash.c b/src/jemalloc/test/unit/hash.c index abb394ac07719e1a9365ffa1cce527cb20223f04..77a8cede92ad8567d56c62edeac089e7a0df741f 100644 --- a/src/jemalloc/test/unit/hash.c +++ b/src/jemalloc/test/unit/hash.c @@ -64,8 +64,8 @@ hash_variant_verify(hash_variant_t variant) { const size_t hashbytes = hash_variant_bits(variant) / 8; uint8_t key[256]; - uint8_t hashes[hashbytes * 256]; - uint8_t final[hashbytes]; + VARIABLE_ARRAY(uint8_t, hashes, hashbytes * 256); + VARIABLE_ARRAY(uint8_t, final, hashbytes); unsigned i; uint32_t computed, expected; diff --git a/src/jemalloc/test/unit/junk.c b/src/jemalloc/test/unit/junk.c index 85bbf9e2bd35a082462fa7fa1c11d96de3ccf1f4..301428f2cb119eacb6d1bc0c134572a0199a520c 100644 --- a/src/jemalloc/test/unit/junk.c +++ b/src/jemalloc/test/unit/junk.c @@ -92,12 +92,9 @@ test_junk(size_t sz_min, size_t sz_max) s = (char *)rallocx(s, sz+1, 0); assert_ptr_not_null((void *)s, "Unexpected rallocx() failure"); - if (!config_mremap || sz+1 <= arena_maxclass) { - assert_ptr_eq(most_recently_junked, junked, - "Expected region of size %zu to be " - "junk-filled", - sz); - } + assert_ptr_eq(most_recently_junked, junked, + "Expected region of size %zu to be junk-filled", + sz); } } diff --git a/src/jemalloc/test/unit/mallctl.c b/src/jemalloc/test/unit/mallctl.c index 31fb81057641fe1d6cea0bb3b9ea12258e2e2fdc..9c064bddc6cd28d839b7ca567f6d3883cab83303 100644 --- a/src/jemalloc/test/unit/mallctl.c +++ b/src/jemalloc/test/unit/mallctl.c @@ -101,16 +101,32 @@ TEST_END TEST_BEGIN(test_mallctlnametomib_short_mib) { - size_t mib[4]; + size_t mib[6]; size_t miblen; + void *mem; + pool_t *pool; + unsigned npools; + size_t sz = sizeof(npools); - miblen = 3; - mib[3] = 42; - assert_d_eq(mallctlnametomib("arenas.bin.0.nregs", mib, &miblen), 0, + mem = calloc(1, POOL_MINIMAL_SIZE); + assert_ptr_ne(mem, NULL, "Unexpected calloc() failure"); + pool = je_pool_create(mem, POOL_MINIMAL_SIZE, 1); + + assert_ptr_ne((void*)pool, NULL, "Unexpected je_pool_create() failure"); + assert_d_eq(mallctl("pools.npools", &npools, &sz, NULL, 0), 0, + "Unexpected mallctl() failure"); + assert_u_eq(npools, 2, "Unexpected number of pools"); + + miblen = 5; + mib[5] = 42; + assert_d_eq(mallctlnametomib("pool.1.arenas.bin.0.nregs", mib, &miblen), 0, "Unexpected mallctlnametomib() failure"); - assert_zu_eq(miblen, 3, "Unexpected mib output length"); - assert_zu_eq(mib[3], 42, + assert_zu_eq(miblen, 5, "Unexpected mib output length"); + assert_zu_eq(mib[5], 42, "mallctlnametomib() wrote past the end of the input mib"); + + je_pool_delete(pool); + free(mem); } TEST_END @@ -127,10 +143,8 @@ TEST_BEGIN(test_mallctl_config) } while (0) TEST_MALLCTL_CONFIG(debug); - TEST_MALLCTL_CONFIG(dss); TEST_MALLCTL_CONFIG(fill); TEST_MALLCTL_CONFIG(lazy_lock); - TEST_MALLCTL_CONFIG(mremap); TEST_MALLCTL_CONFIG(munmap); TEST_MALLCTL_CONFIG(prof); TEST_MALLCTL_CONFIG(prof_libgcc); @@ -171,7 +185,6 @@ TEST_BEGIN(test_mallctl_opt) TEST_MALLCTL_OPT(bool, redzone, fill); TEST_MALLCTL_OPT(bool, zero, fill); TEST_MALLCTL_OPT(bool, utrace, utrace); - TEST_MALLCTL_OPT(bool, valgrind, valgrind); TEST_MALLCTL_OPT(bool, xmalloc, xmalloc); TEST_MALLCTL_OPT(bool, tcache, tcache); TEST_MALLCTL_OPT(size_t, lg_tcache_max, tcache); @@ -189,23 +202,74 @@ TEST_BEGIN(test_mallctl_opt) } TEST_END + +/* + * create a couple of pools and check their size + * using mib feature + */ +TEST_BEGIN(test_mallctl_with_multiple_pools) +{ +#define NPOOLS 4 + pool_t *pools[NPOOLS]; + void *mem; + unsigned npools; + int i; + size_t sz = sizeof(npools); + size_t mib[4], miblen; + + mem = calloc(NPOOLS, POOL_MINIMAL_SIZE); + assert_ptr_ne(mem, NULL, "Unexpected calloc() failure"); + + for (i = 0; i < NPOOLS; ++i) { + pools[i] = je_pool_create( mem + (i*POOL_MINIMAL_SIZE), POOL_MINIMAL_SIZE, 1); + assert_ptr_ne( (void*)pools[i], NULL, "Unexpected je_pool_create() failure"); + } + + assert_d_eq(mallctl("pools.npools", &npools, &sz, NULL, 0), 0, + "Unexpected mallctl() failure"); + assert_u_eq(npools, NPOOLS+1, "Unexpected number of pools"); + + miblen = 4; + assert_d_eq(mallctlnametomib("pool.0.arenas.narenas", mib, &miblen), 0, + "Unexpected mallctlnametomib() failure"); + + /* + * This loop does not use local variable pools. + * Moreover we ommit pool[0]. + */ + for (i = 1; i <= NPOOLS; ++i) { + unsigned narenas; + mib[1] = i; + sz = sizeof(narenas); + assert_d_eq(mallctlbymib(mib, miblen, &narenas, &sz, NULL, 0), + 0, "Unexpected mallctlbymib() failure"); + } + + for (i = 0; i < NPOOLS; ++i) { + je_pool_delete( pools[i]); + } + free(mem); +#undef NPOOLS +} +TEST_END + TEST_BEGIN(test_manpage_example) { unsigned nbins, i; - size_t mib[4]; + size_t mib[6]; size_t len, miblen; len = sizeof(nbins); - assert_d_eq(mallctl("arenas.nbins", &nbins, &len, NULL, 0), 0, + assert_d_eq(mallctl("pool.0.arenas.nbins", &nbins, &len, NULL, 0), 0, "Unexpected mallctl() failure"); - miblen = 4; - assert_d_eq(mallctlnametomib("arenas.bin.0.size", mib, &miblen), 0, + miblen = 6; + assert_d_eq(mallctlnametomib("pool.0.arenas.bin.0.size", mib, &miblen), 0, "Unexpected mallctlnametomib() failure"); for (i = 0; i < nbins; i++) { size_t bin_size; - mib[2] = i; + mib[4] = i; len = sizeof(bin_size); assert_d_eq(mallctlbymib(mib, miblen, &bin_size, &len, NULL, 0), 0, "Unexpected mallctlbymib() failure"); @@ -219,14 +283,14 @@ TEST_BEGIN(test_thread_arena) unsigned arena_old, arena_new, narenas; size_t sz = sizeof(unsigned); - assert_d_eq(mallctl("arenas.narenas", &narenas, &sz, NULL, 0), 0, + assert_d_eq(mallctl("pool.0.arenas.narenas", &narenas, &sz, NULL, 0), 0, "Unexpected mallctl() failure"); assert_u_eq(narenas, opt_narenas, "Number of arenas incorrect"); arena_new = narenas - 1; - assert_d_eq(mallctl("thread.arena", &arena_old, &sz, &arena_new, + assert_d_eq(mallctl("thread.pool.0.arena", &arena_old, &sz, &arena_new, sizeof(unsigned)), 0, "Unexpected mallctl() failure"); arena_new = 0; - assert_d_eq(mallctl("thread.arena", &arena_old, &sz, &arena_new, + assert_d_eq(mallctl("thread.pool.0.arena", &arena_old, &sz, &arena_new, sizeof(unsigned)), 0, "Unexpected mallctl() failure"); } TEST_END @@ -234,20 +298,35 @@ TEST_END TEST_BEGIN(test_arena_i_purge) { unsigned narenas; + unsigned npools; size_t sz = sizeof(unsigned); - size_t mib[3]; - size_t miblen = 3; + size_t mib[5]; + size_t miblen = 5; + void *mem; + pool_t *pool; - assert_d_eq(mallctl("arena.0.purge", NULL, NULL, NULL, 0), 0, + mem = calloc(1, POOL_MINIMAL_SIZE); + assert_ptr_ne(mem, NULL, "Unexpected calloc() failure"); + pool = je_pool_create(mem, POOL_MINIMAL_SIZE, 1); + + assert_ptr_ne( (void*)pool, NULL, "Unexpected je_pool_create() failure"); + assert_d_eq(mallctl("pools.npools", &npools, &sz, NULL, 0), 0, "Unexpected mallctl() failure"); + assert_u_eq(npools, 2, "Unexpected number of pools"); - assert_d_eq(mallctl("arenas.narenas", &narenas, &sz, NULL, 0), 0, + assert_d_eq(mallctl("pool.1.arena.0.purge", NULL, NULL, NULL, 0), 0, + "Unexpected mallctl() failure"); + assert_d_eq(mallctl("pool.1.arenas.narenas", &narenas, &sz, NULL, 0), 0, "Unexpected mallctl() failure"); - assert_d_eq(mallctlnametomib("arena.0.purge", mib, &miblen), 0, + + assert_d_eq(mallctlnametomib("pool.1.arena.0.purge", mib, &miblen), 0, "Unexpected mallctlnametomib() failure"); - mib[1] = narenas; + mib[3] = narenas; assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, NULL, 0), 0, "Unexpected mallctlbymib() failure"); + + je_pool_delete(pool); + free(mem); } TEST_END @@ -255,27 +334,28 @@ TEST_BEGIN(test_arena_i_dss) { const char *dss_prec_old, *dss_prec_new; size_t sz = sizeof(dss_prec_old); + size_t mib[5]; + size_t miblen; - dss_prec_new = "primary"; - assert_d_eq(mallctl("arena.0.dss", &dss_prec_old, &sz, &dss_prec_new, + miblen = sizeof(mib)/sizeof(size_t); + assert_d_eq(mallctlnametomib("pool.0.arena.0.dss", mib, &miblen), 0, + "Unexpected mallctlnametomib() error"); + + dss_prec_new = "disabled"; + assert_d_eq(mallctlbymib(mib, miblen, &dss_prec_old, &sz, &dss_prec_new, sizeof(dss_prec_new)), 0, "Unexpected mallctl() failure"); assert_str_ne(dss_prec_old, "primary", "Unexpected default for dss precedence"); - assert_d_eq(mallctl("arena.0.dss", &dss_prec_new, &sz, &dss_prec_old, + assert_d_eq(mallctlbymib(mib, miblen, &dss_prec_new, &sz, &dss_prec_old, sizeof(dss_prec_old)), 0, "Unexpected mallctl() failure"); -} -TEST_END - -TEST_BEGIN(test_arenas_purge) -{ - unsigned arena = 0; - - assert_d_eq(mallctl("arenas.purge", NULL, NULL, &arena, sizeof(arena)), - 0, "Unexpected mallctl() failure"); - assert_d_eq(mallctl("arenas.purge", NULL, NULL, NULL, 0), 0, - "Unexpected mallctl() failure"); + mib[3] = narenas_total_get(pools[0]); + dss_prec_new = "disabled"; + assert_d_eq(mallctlbymib(mib, miblen, &dss_prec_old, &sz, &dss_prec_new, + sizeof(dss_prec_new)), 0, "Unexpected mallctl() failure"); + assert_str_ne(dss_prec_old, "primary", + "Unexpected default for dss precedence"); } TEST_END @@ -284,13 +364,13 @@ TEST_BEGIN(test_arenas_initialized) unsigned narenas; size_t sz = sizeof(narenas); - assert_d_eq(mallctl("arenas.narenas", &narenas, &sz, NULL, 0), 0, + assert_d_eq(mallctl("pool.0.arenas.narenas", &narenas, &sz, NULL, 0), 0, "Unexpected mallctl() failure"); { - bool initialized[narenas]; + VARIABLE_ARRAY(bool, initialized, narenas); sz = narenas * sizeof(bool); - assert_d_eq(mallctl("arenas.initialized", initialized, &sz, + assert_d_eq(mallctl("pool.0.arenas.initialized", initialized, &sz, NULL, 0), 0, "Unexpected mallctl() failure"); } } @@ -302,7 +382,7 @@ TEST_BEGIN(test_arenas_constants) #define TEST_ARENAS_CONSTANT(t, name, expected) do { \ t name; \ size_t sz = sizeof(t); \ - assert_d_eq(mallctl("arenas."#name, &name, &sz, NULL, 0), 0, \ + assert_d_eq(mallctl("pool.0.arenas."#name, &name, &sz, NULL, 0), 0, \ "Unexpected mallctl() failure"); \ assert_zu_eq(name, expected, "Incorrect "#name" size"); \ } while (0) @@ -322,11 +402,10 @@ TEST_BEGIN(test_arenas_bin_constants) #define TEST_ARENAS_BIN_CONSTANT(t, name, expected) do { \ t name; \ size_t sz = sizeof(t); \ - assert_d_eq(mallctl("arenas.bin.0."#name, &name, &sz, NULL, 0), \ + assert_d_eq(mallctl("pool.0.arenas.bin.0."#name, &name, &sz, NULL, 0), \ 0, "Unexpected mallctl() failure"); \ assert_zu_eq(name, expected, "Incorrect "#name" size"); \ } while (0) - TEST_ARENAS_BIN_CONSTANT(size_t, size, arena_bin_info[0].reg_size); TEST_ARENAS_BIN_CONSTANT(uint32_t, nregs, arena_bin_info[0].nregs); TEST_ARENAS_BIN_CONSTANT(size_t, run_size, arena_bin_info[0].run_size); @@ -341,32 +420,71 @@ TEST_BEGIN(test_arenas_lrun_constants) #define TEST_ARENAS_LRUN_CONSTANT(t, name, expected) do { \ t name; \ size_t sz = sizeof(t); \ - assert_d_eq(mallctl("arenas.lrun.0."#name, &name, &sz, NULL, \ + assert_d_eq(mallctl("pool.0.arenas.lrun.0."#name, &name, &sz, NULL, \ 0), 0, "Unexpected mallctl() failure"); \ assert_zu_eq(name, expected, "Incorrect "#name" size"); \ } while (0) - TEST_ARENAS_LRUN_CONSTANT(size_t, size, (1 << LG_PAGE)); #undef TEST_ARENAS_LRUN_CONSTANT } TEST_END +/* + * create a couple of pools and extend their arenas + */ TEST_BEGIN(test_arenas_extend) { - unsigned narenas_before, arena, narenas_after; - size_t sz = sizeof(unsigned); +#define NPOOLS 4 + pool_t *pools[NPOOLS]; + void *mem; + unsigned npools, narenas_before, arena, narenas_after; + int i; + size_t mib_narenas[4], + mib_extend[4], + miblen = sizeof(mib_narenas), + sz = sizeof(unsigned); + + mem = calloc(NPOOLS, POOL_MINIMAL_SIZE); + assert_ptr_ne(mem, NULL, "Unexpected calloc() failure"); + + for (i = 0; i < NPOOLS; ++i) { + pools[i] = je_pool_create(mem + (i*POOL_MINIMAL_SIZE), POOL_MINIMAL_SIZE, 0); + assert_ptr_ne((void *)pools[i], NULL, "Unexpected je_pool_create() failure"); + } - assert_d_eq(mallctl("arenas.narenas", &narenas_before, &sz, NULL, 0), 0, - "Unexpected mallctl() failure"); - assert_d_eq(mallctl("arenas.extend", &arena, &sz, NULL, 0), 0, - "Unexpected mallctl() failure"); - assert_d_eq(mallctl("arenas.narenas", &narenas_after, &sz, NULL, 0), 0, + assert_d_eq(mallctl("pools.npools", &npools, &sz, NULL, 0), 0, "Unexpected mallctl() failure"); + assert_u_eq(npools, NPOOLS+1, "Unexpected number of pools"); + + assert_d_eq(mallctlnametomib("pool.0.arenas.narenas", mib_narenas, &miblen), 0, + "Unexpected mallctlnametomib() failure"); + assert_d_eq(mallctlnametomib("pool.0.arenas.extend", mib_extend, &miblen), 0, + "Unexpected mallctlnametomib() failure"); - assert_u_eq(narenas_before+1, narenas_after, - "Unexpected number of arenas before versus after extension"); - assert_u_eq(arena, narenas_after-1, "Unexpected arena index"); + /* + * This loop does not use local variable pools. + * Moreover we ommit pool[0]. + */ + for (i = 1; i <= NPOOLS; ++i) { + mib_narenas[1] = i; + mib_extend[1] = i; + assert_d_eq(mallctlbymib(mib_narenas, miblen, &narenas_before, &sz, NULL, 0), + 0, "Unexpected mallctlbymib() failure"); + assert_d_eq(mallctlbymib(mib_extend, miblen, &arena, &sz, NULL, 0), + 0, "Unexpected mallctlbymib() failure"); + assert_d_eq(mallctlbymib(mib_narenas, miblen, &narenas_after, &sz, NULL, 0), + 0, "Unexpected mallctlbymib() failure"); + + assert_u_eq(narenas_before+1, narenas_after, + "Unexpected number of arenas before versus after extension"); + assert_u_eq(arena, narenas_after-1, "Unexpected arena index"); + } + for (i = 0; i < NPOOLS; ++i) { + je_pool_delete( pools[i]); + } + free(mem); +#undef NPOOLS } TEST_END @@ -376,7 +494,7 @@ TEST_BEGIN(test_stats_arenas) #define TEST_STATS_ARENAS(t, name) do { \ t name; \ size_t sz = sizeof(t); \ - assert_d_eq(mallctl("stats.arenas.0."#name, &name, &sz, NULL, \ + assert_d_eq(mallctl("pool.0.stats.arenas.0."#name, &name, &sz, NULL, \ 0), 0, "Unexpected mallctl() failure"); \ } while (0) @@ -401,11 +519,11 @@ main(void) test_mallctlnametomib_short_mib, test_mallctl_config, test_mallctl_opt, + test_mallctl_with_multiple_pools, test_manpage_example, test_thread_arena, test_arena_i_purge, test_arena_i_dss, - test_arenas_purge, test_arenas_initialized, test_arenas_constants, test_arenas_bin_constants, diff --git a/src/jemalloc/test/unit/math.c b/src/jemalloc/test/unit/math.c index a1b288ea19c08c45e30c17c1d6eb400871387475..ebec77a62d52c54cb104383e20952ac6c9275f03 100644 --- a/src/jemalloc/test/unit/math.c +++ b/src/jemalloc/test/unit/math.c @@ -3,6 +3,12 @@ #define MAX_REL_ERR 1.0e-9 #define MAX_ABS_ERR 1.0e-9 +#include <float.h> + +#ifndef INFINITY +#define INFINITY (DBL_MAX + DBL_MAX) +#endif + static bool double_eq_rel(double a, double b, double max_rel_err, double max_abs_err) { diff --git a/src/jemalloc/test/unit/mq.c b/src/jemalloc/test/unit/mq.c index f57e96af1cb42d59d445018e3ba49ffa5990b097..bd289c54d6b86800580c0ce5e67edec3a9c0faa0 100644 --- a/src/jemalloc/test/unit/mq.c +++ b/src/jemalloc/test/unit/mq.c @@ -54,7 +54,7 @@ thd_sender_start(void *arg) mq_msg_t *msg; void *p; p = mallocx(sizeof(mq_msg_t), 0); - assert_ptr_not_null(p, "Unexpected allocm() failure"); + assert_ptr_not_null(p, "Unexpected mallocx() failure"); msg = (mq_msg_t *)p; mq_put(mq, msg); } diff --git a/src/jemalloc/test/unit/pool.h b/src/jemalloc/test/unit/pool.h new file mode 100644 index 0000000000000000000000000000000000000000..8e3a8be4ba840e06c34d9df464d97dfd2da382e0 --- /dev/null +++ b/src/jemalloc/test/unit/pool.h @@ -0,0 +1,448 @@ +#include "test/jemalloc_test.h" + +#define TEST_POOL_SIZE (16L * 1024L * 1024L) +#define TEST_TOO_SMALL_POOL_SIZE (2L * 1024L * 1024L) +#define TEST_VALUE 123456 +#define TEST_MALLOC_FREE_LOOPS 2 +#define TEST_MALLOC_SIZE 1024 +#define TEST_ALLOCS_SIZE (TEST_POOL_SIZE / 8) +#define TEST_BUFFOR_CMP_SIZE (4L * 1024L * 1024L) + +static char mem_pool[TEST_POOL_SIZE]; +static char mem_extend_ok[TEST_POOL_SIZE]; +static void* allocs[TEST_ALLOCS_SIZE]; + +static int custom_allocs; +static int exp_base_pool; + +TEST_BEGIN(test_pool_create_errors) { + pool_t *pool; + memset(mem_pool, 1, TEST_POOL_SIZE); + pool = pool_create(mem_pool, 0, 0); + assert_ptr_null(pool, "pool_create() should return NULL for size 0"); + + pool = pool_create(NULL, TEST_POOL_SIZE, 0); + assert_ptr_null(pool, "pool_create() should return NULL for input addr NULL"); +} +TEST_END + +TEST_BEGIN(test_pool_create) { + pool_t *pool; + custom_allocs = 0; + memset(mem_pool, 0, TEST_POOL_SIZE); + pool = pool_create(mem_pool, TEST_POOL_SIZE, 1); + assert_ptr_eq(pool, mem_pool, "pool_create() should return addr with valid input"); + pool_delete(pool); + + assert_d_eq(custom_allocs, 0, "memory leak when use custom allocator"); + if (exp_base_pool) { + assert_ptr_not_null(pools[0], "not create base pool"); + } else { + assert_ptr_null(pools[0], "create base pool"); + } +} +TEST_END + +TEST_BEGIN(test_pool_malloc) { + pool_t *pool; + custom_allocs = 0; + memset(mem_pool, 0, TEST_POOL_SIZE); + pool = pool_create(mem_pool, TEST_POOL_SIZE, 1); + + int *test = pool_malloc(pool, sizeof(int)); + assert_ptr_not_null(test, "pool_malloc should return valid ptr"); + + *test = TEST_VALUE; + assert_x_eq(*test, TEST_VALUE, "ptr should be usable"); + + assert_lu_gt((uintptr_t)test, (uintptr_t)mem_pool, + "pool_malloc() should return pointer to memory from pool"); + assert_lu_lt((uintptr_t)test, (uintptr_t)mem_pool+TEST_POOL_SIZE, + "pool_malloc() should return pointer to memory from pool"); + + pool_free(pool, test); + + pool_delete(pool); + + assert_d_eq(custom_allocs, 0, "memory leak when use custom allocator"); + if (exp_base_pool) { + assert_ptr_not_null(pools[0], "not create base pool"); + } else { + assert_ptr_null(pools[0], "create base pool"); + } +} +TEST_END + +TEST_BEGIN(test_pool_free) { + pool_t *pool; + int i, j, s = 0, prev_s = 0; + int allocs = TEST_POOL_SIZE/TEST_MALLOC_SIZE; + void *arr[allocs]; + custom_allocs = 0; + memset(mem_pool, 0, TEST_POOL_SIZE); + pool = pool_create(mem_pool, TEST_POOL_SIZE, 1); + + for (i = 0; i < TEST_MALLOC_FREE_LOOPS; ++i) { + for (j = 0; j < allocs; ++j) { + arr[j] = pool_malloc(pool, TEST_MALLOC_SIZE); + if (arr[j] != NULL) { + s++; + } + } + for (j = 0; j < allocs; ++j) { + if (arr[j] != NULL) { + pool_free(pool, arr[j]); + } + } + if (prev_s != 0) { + assert_x_eq(s, prev_s, + "pool_free() should record back used chunks"); + } + + prev_s = s; + s = 0; + } + + pool_delete(pool); + + assert_d_eq(custom_allocs, 0, "memory leak when use custom allocator"); + if (exp_base_pool) { + assert_ptr_not_null(pools[0], "not create base pool"); + } else { + assert_ptr_null(pools[0], "create base pool"); + } +} +TEST_END + +TEST_BEGIN(test_pool_calloc) { + pool_t *pool; + custom_allocs = 0; + memset(mem_pool, 1, TEST_POOL_SIZE); + pool = pool_create(mem_pool, TEST_POOL_SIZE, 0); + + int *test = pool_calloc(pool, 1, sizeof(int)); + assert_ptr_not_null(test, "pool_calloc should return valid ptr"); + + assert_x_eq(*test, 0, "pool_calloc should return zeroed memory"); + + pool_free(pool, test); + + pool_delete(pool); + + assert_d_eq(custom_allocs, 0, "memory leak when use custom allocator"); + if (exp_base_pool) { + assert_ptr_not_null(pools[0], "not create base pool"); + } else { + assert_ptr_null(pools[0], "create base pool"); + } +} +TEST_END + +TEST_BEGIN(test_pool_realloc) { + pool_t *pool; + custom_allocs = 0; + memset(mem_pool, 0, TEST_POOL_SIZE); + pool = pool_create(mem_pool, TEST_POOL_SIZE, 1); + + int *test = pool_ralloc(pool, NULL, sizeof(int)); + assert_ptr_not_null(test, "pool_ralloc with NULL addr should return valid ptr"); + + int *test2 = pool_ralloc(pool, test, sizeof(int)*2); + assert_ptr_not_null(test, "pool_ralloc should return valid ptr"); + test2[0] = TEST_VALUE; + test2[1] = TEST_VALUE; + + assert_x_eq(test[1], TEST_VALUE, "ptr should be usable"); + + pool_free(pool, test2); + + pool_delete(pool); + + assert_d_eq(custom_allocs, 0, "memory leak when use custom allocator"); + if (exp_base_pool) { + assert_ptr_not_null(pools[0], "not create base pool"); + } else { + assert_ptr_null(pools[0], "create base pool"); + } +} +TEST_END + +TEST_BEGIN(test_pool_aligned_alloc) { + pool_t *pool; + custom_allocs = 0; + memset(mem_pool, 0, TEST_POOL_SIZE); + pool = pool_create(mem_pool, TEST_POOL_SIZE, 1); + + int *test = pool_aligned_alloc(pool, 1024, 1024); + assert_ptr_not_null(test, "pool_aligned_alloc should return valid ptr"); + assert_x_eq(((uintptr_t)(test) & 1023), 0, "ptr should be aligned"); + + assert_lu_gt((uintptr_t)test, (uintptr_t)mem_pool, + "pool_aligned_alloc() should return pointer to memory from pool"); + assert_lu_lt((uintptr_t)test, (uintptr_t)mem_pool+TEST_POOL_SIZE, + "pool_aligned_alloc() should return pointer to memory from pool"); + + *test = TEST_VALUE; + assert_x_eq(*test, TEST_VALUE, "ptr should be usable"); + + pool_free(pool, test); + + pool_delete(pool); + + assert_d_eq(custom_allocs, 0, "memory leak when use custom allocator"); + if (exp_base_pool) { + assert_ptr_not_null(pools[0], "not create base pool"); + } else { + assert_ptr_null(pools[0], "create base pool"); + } +} +TEST_END + +TEST_BEGIN(test_pool_reuse_pool) { + pool_t *pool; + size_t pool_num = 0; + custom_allocs = 0; + + /* create and destroy pool multiple times */ + for (; pool_num<100; ++pool_num) { + pool = pool_create(mem_pool, TEST_POOL_SIZE, 0); + assert_ptr_not_null(pool, "Can not create pool!!!"); + if (pool == NULL) { + break; + } + + void *prev = NULL; + size_t i = 0; + + /* allocate memory from pool */ + for (; i<100; ++i) { + void **next = pool_malloc(pool, sizeof (void *)); + + assert_lu_gt((uintptr_t)next, (uintptr_t)mem_pool, + "pool_malloc() should return pointer to memory from pool"); + assert_lu_lt((uintptr_t)next, (uintptr_t)mem_pool+TEST_POOL_SIZE, + "pool_malloc() should return pointer to memory from pool"); + + *next = prev; + prev = next; + } + + /* free all allocated memory from pool */ + while (prev != NULL) { + void **act = prev; + prev = *act; + pool_free(pool, act); + } + pool_delete(pool); + } + + assert_d_eq(custom_allocs, 0, "memory leak when use custom allocator"); + if (exp_base_pool) { + assert_ptr_not_null(pools[0], "not create base pool"); + } else { + assert_ptr_null(pools[0], "create base pool"); + } +} +TEST_END + +TEST_BEGIN(test_pool_check_memory) { + pool_t *pool; + size_t pool_size = POOL_MINIMAL_SIZE; + assert_lu_lt(POOL_MINIMAL_SIZE, TEST_POOL_SIZE, "Too small pool size"); + + size_t object_size; + size_t size_allocated; + size_t i; + size_t j; + + for (object_size = 8; object_size <= TEST_BUFFOR_CMP_SIZE ; object_size *= 2) { + custom_allocs = 0; + pool = pool_create(mem_pool, pool_size, 0); + assert_ptr_not_null(pool, "Can not create pool!!!"); + size_allocated = 0; + memset(allocs, 0, TEST_ALLOCS_SIZE); + + for (i = 0; i < TEST_ALLOCS_SIZE;++i) { + allocs[i] = pool_malloc(pool, object_size); + if (allocs[i] == NULL) { + /* out of memory in pool */ + break; + } + assert_lu_gt((uintptr_t)allocs[i], (uintptr_t)mem_pool, + "pool_malloc() should return pointer to memory from pool"); + assert_lu_lt((uintptr_t)allocs[i], (uintptr_t)mem_pool+pool_size, + "pool_malloc() should return pointer to memory from pool"); + + size_allocated += object_size; + + /* fill each allocation with a unique value */ + memset(allocs[i], (char)i, object_size); + } + + assert_ptr_not_null(allocs[0], "pool_malloc should return valid ptr"); + assert_lu_lt(i + 1, TEST_ALLOCS_SIZE, "All memory should be used"); + + /* check for unexpected modifications of prepare data */ + for (i = 0; i < TEST_ALLOCS_SIZE && allocs[i] != NULL; ++i) { + char *buffer = allocs[i]; + for (j = 0; j < object_size; ++j) + if (buffer[j] != (char)i) { + assert_true(0, "Content of data object was modified unexpectedly" + " for object size: %zu, id: %zu", object_size, j); + break; + } + } + + pool_delete(pool); + + assert_d_eq(custom_allocs, 0, "memory leak when use custom allocator"); + if (exp_base_pool) { + assert_ptr_not_null(pools[0], "not create base pool"); + } else { + assert_ptr_null(pools[0], "create base pool"); + } + } + +} +TEST_END + +TEST_BEGIN(test_pool_use_all_memory) { + pool_t *pool; + size_t size = 0; + size_t pool_size = POOL_MINIMAL_SIZE; + assert_lu_lt(POOL_MINIMAL_SIZE, TEST_POOL_SIZE, "Too small pool size"); + custom_allocs = 0; + pool = pool_create(mem_pool, pool_size, 0); + assert_ptr_not_null(pool, "Can not create pool!!!"); + + void *prev = NULL; + for (;;) { + void **next = pool_malloc(pool, sizeof (void *)); + if (next == NULL) { + /* Out of memory in pool, test end */ + break; + } + size += sizeof (void *); + + assert_ptr_not_null(next, "pool_malloc should return valid ptr"); + + assert_lu_gt((uintptr_t)next, (uintptr_t)mem_pool, + "pool_malloc() should return pointer to memory from pool"); + assert_lu_lt((uintptr_t)next, (uintptr_t)mem_pool+pool_size, + "pool_malloc() should return pointer to memory from pool"); + + *next = prev; + assert_x_eq((uintptr_t)(*next), (uintptr_t)(prev), "ptr should be usable"); + prev = next; + + } + + assert_lu_gt(size, 0, "Can not alloc any memory from pool"); + + /* Free all allocated memory from pool */ + while (prev != NULL) { + void **act = prev; + prev = *act; + pool_free(pool, act); + } + + pool_delete(pool); + + assert_d_eq(custom_allocs, 0, "memory leak when use custom allocator"); + if (exp_base_pool) { + assert_ptr_not_null(pools[0], "not create base pool"); + } else { + assert_ptr_null(pools[0], "create base pool"); + } +} +TEST_END + +TEST_BEGIN(test_pool_extend_errors) { + pool_t *pool; + custom_allocs = 0; + memset(mem_pool, 0, TEST_POOL_SIZE); + pool = pool_create(mem_pool, TEST_POOL_SIZE, 1); + + memset(mem_extend_ok, 0, TEST_TOO_SMALL_POOL_SIZE); + size_t usable_size = pool_extend(pool, mem_extend_ok, TEST_TOO_SMALL_POOL_SIZE, 0); + + assert_zu_eq(usable_size, 0, "pool_extend() should return 0" + " when provided with memory size smaller then chunksize"); + + pool_delete(pool); + + assert_d_eq(custom_allocs, 0, "memory leak when use custom allocator"); + if (exp_base_pool) { + assert_ptr_not_null(pools[0], "not create base pool"); + } else { + assert_ptr_null(pools[0], "create base pool"); + } +} +TEST_END + +TEST_BEGIN(test_pool_extend) { + pool_t *pool; + custom_allocs = 0; + memset(mem_pool, 0, TEST_POOL_SIZE); + pool = pool_create(mem_pool, TEST_POOL_SIZE, 1); + + memset(mem_extend_ok, 0, TEST_POOL_SIZE); + size_t usable_size = pool_extend(pool, mem_extend_ok, TEST_POOL_SIZE, 0); + + assert_zu_ne(usable_size, 0, "pool_extend() should return value" + " after alignment when provided with enough memory"); + + pool_delete(pool); + + assert_d_eq(custom_allocs, 0, "memory leak when use custom allocator"); + if (exp_base_pool) { + assert_ptr_not_null(pools[0], "not create base pool"); + } else { + assert_ptr_null(pools[0], "create base pool"); + } +} +TEST_END + +TEST_BEGIN(test_pool_extend_after_out_of_memory) { + pool_t *pool; + custom_allocs = 0; + memset(mem_pool, 0, TEST_POOL_SIZE); + pool = pool_create(mem_pool, TEST_POOL_SIZE, 1); + + /* use the all memory from pool and from base allocator */ + while (pool_malloc(pool, sizeof (void *))); + pool->base_next_addr = pool->base_past_addr; + + memset(mem_extend_ok, 0, TEST_POOL_SIZE); + size_t usable_size = pool_extend(pool, mem_extend_ok, TEST_POOL_SIZE, 0); + + assert_zu_ne(usable_size, 0, "pool_extend() should return value" + " after alignment when provided with enough memory"); + + pool_delete(pool); + + assert_d_eq(custom_allocs, 0, "memory leak when use custom allocator"); + if (exp_base_pool) { + assert_ptr_not_null(pools[0], "not create base pool"); + } else { + assert_ptr_null(pools[0], "create base pool"); + } +} +TEST_END + +#define POOL_TEST_CASES\ + test_pool_create_errors, \ + test_pool_create, \ + test_pool_malloc, \ + test_pool_free, \ + test_pool_calloc, \ + test_pool_realloc, \ + test_pool_aligned_alloc, \ + test_pool_reuse_pool, \ + test_pool_check_memory, \ + test_pool_use_all_memory, \ + test_pool_extend_errors, \ + test_pool_extend, \ + test_pool_extend_after_out_of_memory + + diff --git a/src/jemalloc/test/unit/pool_base_alloc.c b/src/jemalloc/test/unit/pool_base_alloc.c new file mode 100644 index 0000000000000000000000000000000000000000..80913ccaf21d476da730f60a18c5e268f515332a --- /dev/null +++ b/src/jemalloc/test/unit/pool_base_alloc.c @@ -0,0 +1,9 @@ +#include "pool.h" + +int +main(void) +{ + exp_base_pool = 1; + + return test_not_init(POOL_TEST_CASES); +} diff --git a/src/jemalloc/test/unit/pool_custom_alloc.c b/src/jemalloc/test/unit/pool_custom_alloc.c new file mode 100644 index 0000000000000000000000000000000000000000..fbda621163cf39b60446a24eb0abe293a571b131 --- /dev/null +++ b/src/jemalloc/test/unit/pool_custom_alloc.c @@ -0,0 +1,29 @@ +#include "pool.h" + +static char buff_alloc[4*1024]; +static char *buff_ptr = buff_alloc; + +void * +malloc_test(size_t size) { + custom_allocs++; + void *ret = buff_ptr; + buff_ptr = buff_ptr + size; + return ret; +} + +void +free_test(void *ptr) { + custom_allocs--; + if(custom_allocs == 0) { + buff_ptr = buff_alloc; + } +} + +int +main(void) +{ + exp_base_pool = 0; + je_pool_set_alloc_funcs(malloc_test, free_test); + + return test_not_init(POOL_TEST_CASES); +} diff --git a/src/jemalloc/test/unit/pool_custom_alloc_internal.c b/src/jemalloc/test/unit/pool_custom_alloc_internal.c new file mode 100644 index 0000000000000000000000000000000000000000..fd47da0f699cf7ea21621209051cde0e4b2ea4ee --- /dev/null +++ b/src/jemalloc/test/unit/pool_custom_alloc_internal.c @@ -0,0 +1,30 @@ +#include "pool.h" + +void * +malloc_test(size_t size) { + custom_allocs++; + return malloc(size); +} + +void +free_test(void *ptr) { + custom_allocs--; + free(ptr); +} + +int +main(void) +{ + /* + * Initialize custom allocator who call malloc from jemalloc. + */ + if (nallocx(1, 0) == 0) { + malloc_printf("Initialization error"); + return (test_status_fail); + } + + exp_base_pool = 1; + je_pool_set_alloc_funcs(malloc_test, free_test); + + return test_not_init(POOL_TEST_CASES); +} diff --git a/src/jemalloc/test/unit/rtree.c b/src/jemalloc/test/unit/rtree.c index 5463055fe92a4cbd8c4b5447deff8ee874aef550..a59c7e9917d24c806529392a3c9eb4e6d1fbc2ed 100644 --- a/src/jemalloc/test/unit/rtree.c +++ b/src/jemalloc/test/unit/rtree.c @@ -1,11 +1,23 @@ #include "test/jemalloc_test.h" +void * +rtree_malloc(pool_t *pool, size_t size) +{ + return imalloc(size); +} + +void +rtree_free(pool_t *pool, void *ptr) +{ + return idalloc(ptr); +} + TEST_BEGIN(test_rtree_get_empty) { unsigned i; for (i = 1; i <= (sizeof(uintptr_t) << 3); i++) { - rtree_t *rtree = rtree_new(i, imalloc, idalloc); + rtree_t *rtree = rtree_new(i, rtree_malloc, rtree_free, pools[0]); assert_u_eq(rtree_get(rtree, 0), 0, "rtree_get() should return NULL for empty tree"); rtree_delete(rtree); @@ -18,7 +30,7 @@ TEST_BEGIN(test_rtree_extrema) unsigned i; for (i = 1; i <= (sizeof(uintptr_t) << 3); i++) { - rtree_t *rtree = rtree_new(i, imalloc, idalloc); + rtree_t *rtree = rtree_new(i, rtree_malloc, rtree_free, pools[0]); rtree_set(rtree, 0, 1); assert_u_eq(rtree_get(rtree, 0), 1, @@ -40,7 +52,7 @@ TEST_BEGIN(test_rtree_bits) for (i = 1; i < (sizeof(uintptr_t) << 3); i++) { uintptr_t keys[] = {0, 1, (((uintptr_t)1) << (sizeof(uintptr_t)*8-i)) - 1}; - rtree_t *rtree = rtree_new(i, imalloc, idalloc); + rtree_t *rtree = rtree_new(i, rtree_malloc, rtree_free, pools[0]); for (j = 0; j < sizeof(keys)/sizeof(uintptr_t); j++) { rtree_set(rtree, keys[j], 1); @@ -73,7 +85,7 @@ TEST_BEGIN(test_rtree_random) sfmt = init_gen_rand(SEED); for (i = 1; i <= (sizeof(uintptr_t) << 3); i++) { - rtree_t *rtree = rtree_new(i, imalloc, idalloc); + rtree_t *rtree = rtree_new(i, rtree_malloc, rtree_free, pools[0]); uintptr_t keys[NSET]; unsigned j; diff --git a/src/jemalloc/test/unit/stats.c b/src/jemalloc/test/unit/stats.c index 03a55c7fdce911ee109f73fd8bf2d82489a23e26..0105c4ba06c2eb199ccc10104a4a2071145ece73 100644 --- a/src/jemalloc/test/unit/stats.c +++ b/src/jemalloc/test/unit/stats.c @@ -7,15 +7,15 @@ TEST_BEGIN(test_stats_summary) int expected = config_stats ? 0 : ENOENT; sz = sizeof(cactive); - assert_d_eq(mallctl("stats.cactive", &cactive, &sz, NULL, 0), expected, + assert_d_eq(mallctl("pool.0.stats.cactive", &cactive, &sz, NULL, 0), expected, "Unexpected mallctl() result"); sz = sizeof(size_t); - assert_d_eq(mallctl("stats.allocated", &allocated, &sz, NULL, 0), + assert_d_eq(mallctl("pool.0.stats.allocated", &allocated, &sz, NULL, 0), expected, "Unexpected mallctl() result"); - assert_d_eq(mallctl("stats.active", &active, &sz, NULL, 0), expected, + assert_d_eq(mallctl("pool.0.stats.active", &active, &sz, NULL, 0), expected, "Unexpected mallctl() result"); - assert_d_eq(mallctl("stats.mapped", &mapped, &sz, NULL, 0), expected, + assert_d_eq(mallctl("pool.0.stats.mapped", &mapped, &sz, NULL, 0), expected, "Unexpected mallctl() result"); if (config_stats) { @@ -37,13 +37,13 @@ TEST_BEGIN(test_stats_chunks) int expected = config_stats ? 0 : ENOENT; sz = sizeof(size_t); - assert_d_eq(mallctl("stats.chunks.current", ¤t, &sz, NULL, 0), + assert_d_eq(mallctl("pool.0.stats.chunks.current", ¤t, &sz, NULL, 0), expected, "Unexpected mallctl() result"); sz = sizeof(uint64_t); - assert_d_eq(mallctl("stats.chunks.total", &total, &sz, NULL, 0), + assert_d_eq(mallctl("pool.0.stats.chunks.total", &total, &sz, NULL, 0), expected, "Unexpected mallctl() result"); sz = sizeof(size_t); - assert_d_eq(mallctl("stats.chunks.high", &high, &sz, NULL, 0), expected, + assert_d_eq(mallctl("pool.0.stats.chunks.high", &high, &sz, NULL, 0), expected, "Unexpected mallctl() result"); if (config_stats) { @@ -60,7 +60,7 @@ TEST_BEGIN(test_stats_huge) void *p; uint64_t epoch; size_t allocated; - uint64_t nmalloc, ndalloc; + uint64_t nmalloc, ndalloc, nrequests; size_t sz; int expected = config_stats ? 0 : ENOENT; @@ -71,19 +71,23 @@ TEST_BEGIN(test_stats_huge) "Unexpected mallctl() failure"); sz = sizeof(size_t); - assert_d_eq(mallctl("stats.huge.allocated", &allocated, &sz, NULL, 0), - expected, "Unexpected mallctl() result"); + assert_d_eq(mallctl("pool.0.stats.arenas.0.huge.allocated", &allocated, &sz, + NULL, 0), expected, "Unexpected mallctl() result"); sz = sizeof(uint64_t); - assert_d_eq(mallctl("stats.huge.nmalloc", &nmalloc, &sz, NULL, 0), - expected, "Unexpected mallctl() result"); - assert_d_eq(mallctl("stats.huge.ndalloc", &ndalloc, &sz, NULL, 0), - expected, "Unexpected mallctl() result"); + assert_d_eq(mallctl("pool.0.stats.arenas.0.huge.nmalloc", &nmalloc, &sz, NULL, + 0), expected, "Unexpected mallctl() result"); + assert_d_eq(mallctl("pool.0.stats.arenas.0.huge.ndalloc", &ndalloc, &sz, NULL, + 0), expected, "Unexpected mallctl() result"); + assert_d_eq(mallctl("pool.0.stats.arenas.0.huge.nrequests", &nrequests, &sz, + NULL, 0), expected, "Unexpected mallctl() result"); if (config_stats) { assert_zu_gt(allocated, 0, "allocated should be greater than zero"); assert_u64_ge(nmalloc, ndalloc, "nmalloc should be at least as large as ndalloc"); + assert_u64_le(nmalloc, nrequests, + "nmalloc should no larger than nrequests"); } dallocx(p, 0); @@ -93,7 +97,7 @@ TEST_END TEST_BEGIN(test_stats_arenas_summary) { unsigned arena; - void *small, *large; + void *little, *large; uint64_t epoch; size_t sz; int expected = config_stats ? 0 : ENOENT; @@ -101,29 +105,29 @@ TEST_BEGIN(test_stats_arenas_summary) uint64_t npurge, nmadvise, purged; arena = 0; - assert_d_eq(mallctl("thread.arena", NULL, NULL, &arena, sizeof(arena)), + assert_d_eq(mallctl("thread.pool.0.arena", NULL, NULL, &arena, sizeof(arena)), 0, "Unexpected mallctl() failure"); - small = mallocx(SMALL_MAXCLASS, 0); - assert_ptr_not_null(small, "Unexpected mallocx() failure"); + little = mallocx(SMALL_MAXCLASS, 0); + assert_ptr_not_null(little, "Unexpected mallocx() failure"); large = mallocx(arena_maxclass, 0); assert_ptr_not_null(large, "Unexpected mallocx() failure"); - assert_d_eq(mallctl("arena.0.purge", NULL, NULL, NULL, 0), 0, + assert_d_eq(mallctl("pool.0.arena.0.purge", NULL, NULL, NULL, 0), 0, "Unexpected mallctl() failure"); assert_d_eq(mallctl("epoch", NULL, NULL, &epoch, sizeof(epoch)), 0, "Unexpected mallctl() failure"); sz = sizeof(size_t); - assert_d_eq(mallctl("stats.arenas.0.mapped", &mapped, &sz, NULL, 0), + assert_d_eq(mallctl("pool.0.stats.arenas.0.mapped", &mapped, &sz, NULL, 0), expected, "Unexepected mallctl() result"); sz = sizeof(uint64_t); - assert_d_eq(mallctl("stats.arenas.0.npurge", &npurge, &sz, NULL, 0), + assert_d_eq(mallctl("pool.0.stats.arenas.0.npurge", &npurge, &sz, NULL, 0), expected, "Unexepected mallctl() result"); - assert_d_eq(mallctl("stats.arenas.0.nmadvise", &nmadvise, &sz, NULL, 0), + assert_d_eq(mallctl("pool.0.stats.arenas.0.nmadvise", &nmadvise, &sz, NULL, 0), expected, "Unexepected mallctl() result"); - assert_d_eq(mallctl("stats.arenas.0.purged", &purged, &sz, NULL, 0), + assert_d_eq(mallctl("pool.0.stats.arenas.0.purged", &purged, &sz, NULL, 0), expected, "Unexepected mallctl() result"); if (config_stats) { @@ -133,7 +137,7 @@ TEST_BEGIN(test_stats_arenas_summary) "nmadvise should be no greater than purged"); } - dallocx(small, 0); + dallocx(little, 0); dallocx(large, 0); } TEST_END @@ -165,7 +169,7 @@ TEST_BEGIN(test_stats_arenas_small) no_lazy_lock(); /* Lazy locking would dodge tcache testing. */ arena = 0; - assert_d_eq(mallctl("thread.arena", NULL, NULL, &arena, sizeof(arena)), + assert_d_eq(mallctl("thread.pool.0.arena", NULL, NULL, &arena, sizeof(arena)), 0, "Unexpected mallctl() failure"); p = mallocx(SMALL_MAXCLASS, 0); @@ -178,14 +182,14 @@ TEST_BEGIN(test_stats_arenas_small) "Unexpected mallctl() failure"); sz = sizeof(size_t); - assert_d_eq(mallctl("stats.arenas.0.small.allocated", &allocated, &sz, + assert_d_eq(mallctl("pool.0.stats.arenas.0.small.allocated", &allocated, &sz, NULL, 0), expected, "Unexpected mallctl() result"); sz = sizeof(uint64_t); - assert_d_eq(mallctl("stats.arenas.0.small.nmalloc", &nmalloc, &sz, + assert_d_eq(mallctl("pool.0.stats.arenas.0.small.nmalloc", &nmalloc, &sz, NULL, 0), expected, "Unexpected mallctl() result"); - assert_d_eq(mallctl("stats.arenas.0.small.ndalloc", &ndalloc, &sz, + assert_d_eq(mallctl("pool.0.stats.arenas.0.small.ndalloc", &ndalloc, &sz, NULL, 0), expected, "Unexpected mallctl() result"); - assert_d_eq(mallctl("stats.arenas.0.small.nrequests", &nrequests, &sz, + assert_d_eq(mallctl("pool.0.stats.arenas.0.small.nrequests", &nrequests, &sz, NULL, 0), expected, "Unexpected mallctl() result"); if (config_stats) { @@ -212,7 +216,7 @@ TEST_BEGIN(test_stats_arenas_large) int expected = config_stats ? 0 : ENOENT; arena = 0; - assert_d_eq(mallctl("thread.arena", NULL, NULL, &arena, sizeof(arena)), + assert_d_eq(mallctl("thread.pool.0.arena", NULL, NULL, &arena, sizeof(arena)), 0, "Unexpected mallctl() failure"); p = mallocx(arena_maxclass, 0); @@ -222,14 +226,14 @@ TEST_BEGIN(test_stats_arenas_large) "Unexpected mallctl() failure"); sz = sizeof(size_t); - assert_d_eq(mallctl("stats.arenas.0.large.allocated", &allocated, &sz, + assert_d_eq(mallctl("pool.0.stats.arenas.0.large.allocated", &allocated, &sz, NULL, 0), expected, "Unexpected mallctl() result"); sz = sizeof(uint64_t); - assert_d_eq(mallctl("stats.arenas.0.large.nmalloc", &nmalloc, &sz, + assert_d_eq(mallctl("pool.0.stats.arenas.0.large.nmalloc", &nmalloc, &sz, NULL, 0), expected, "Unexpected mallctl() result"); - assert_d_eq(mallctl("stats.arenas.0.large.ndalloc", &ndalloc, &sz, + assert_d_eq(mallctl("pool.0.stats.arenas.0.large.ndalloc", &ndalloc, &sz, NULL, 0), expected, "Unexpected mallctl() result"); - assert_d_eq(mallctl("stats.arenas.0.large.nrequests", &nrequests, &sz, + assert_d_eq(mallctl("pool.0.stats.arenas.0.large.nrequests", &nrequests, &sz, NULL, 0), expected, "Unexpected mallctl() result"); if (config_stats) { @@ -257,7 +261,7 @@ TEST_BEGIN(test_stats_arenas_bins) int expected = config_stats ? 0 : ENOENT; arena = 0; - assert_d_eq(mallctl("thread.arena", NULL, NULL, &arena, sizeof(arena)), + assert_d_eq(mallctl("thread.pool.0.arena", NULL, NULL, &arena, sizeof(arena)), 0, "Unexpected mallctl() failure"); p = mallocx(arena_bin_info[0].reg_size, 0); @@ -270,29 +274,29 @@ TEST_BEGIN(test_stats_arenas_bins) "Unexpected mallctl() failure"); sz = sizeof(size_t); - assert_d_eq(mallctl("stats.arenas.0.bins.0.allocated", &allocated, &sz, + assert_d_eq(mallctl("pool.0.stats.arenas.0.bins.0.allocated", &allocated, &sz, NULL, 0), expected, "Unexpected mallctl() result"); sz = sizeof(uint64_t); - assert_d_eq(mallctl("stats.arenas.0.bins.0.nmalloc", &nmalloc, &sz, + assert_d_eq(mallctl("pool.0.stats.arenas.0.bins.0.nmalloc", &nmalloc, &sz, NULL, 0), expected, "Unexpected mallctl() result"); - assert_d_eq(mallctl("stats.arenas.0.bins.0.ndalloc", &ndalloc, &sz, + assert_d_eq(mallctl("pool.0.stats.arenas.0.bins.0.ndalloc", &ndalloc, &sz, NULL, 0), expected, "Unexpected mallctl() result"); - assert_d_eq(mallctl("stats.arenas.0.bins.0.nrequests", &nrequests, &sz, + assert_d_eq(mallctl("pool.0.stats.arenas.0.bins.0.nrequests", &nrequests, &sz, NULL, 0), expected, "Unexpected mallctl() result"); - assert_d_eq(mallctl("stats.arenas.0.bins.0.nfills", &nfills, &sz, + assert_d_eq(mallctl("pool.0.stats.arenas.0.bins.0.nfills", &nfills, &sz, NULL, 0), config_tcache ? expected : ENOENT, "Unexpected mallctl() result"); - assert_d_eq(mallctl("stats.arenas.0.bins.0.nflushes", &nflushes, &sz, + assert_d_eq(mallctl("pool.0.stats.arenas.0.bins.0.nflushes", &nflushes, &sz, NULL, 0), config_tcache ? expected : ENOENT, "Unexpected mallctl() result"); - assert_d_eq(mallctl("stats.arenas.0.bins.0.nruns", &nruns, &sz, + assert_d_eq(mallctl("pool.0.stats.arenas.0.bins.0.nruns", &nruns, &sz, NULL, 0), expected, "Unexpected mallctl() result"); - assert_d_eq(mallctl("stats.arenas.0.bins.0.nreruns", &nreruns, &sz, + assert_d_eq(mallctl("pool.0.stats.arenas.0.bins.0.nreruns", &nreruns, &sz, NULL, 0), expected, "Unexpected mallctl() result"); sz = sizeof(size_t); - assert_d_eq(mallctl("stats.arenas.0.bins.0.curruns", &curruns, &sz, + assert_d_eq(mallctl("pool.0.stats.arenas.0.bins.0.curruns", &curruns, &sz, NULL, 0), expected, "Unexpected mallctl() result"); if (config_stats) { @@ -329,7 +333,7 @@ TEST_BEGIN(test_stats_arenas_lruns) int expected = config_stats ? 0 : ENOENT; arena = 0; - assert_d_eq(mallctl("thread.arena", NULL, NULL, &arena, sizeof(arena)), + assert_d_eq(mallctl("thread.pool.0.arena", NULL, NULL, &arena, sizeof(arena)), 0, "Unexpected mallctl() failure"); p = mallocx(SMALL_MAXCLASS+1, 0); @@ -339,14 +343,14 @@ TEST_BEGIN(test_stats_arenas_lruns) "Unexpected mallctl() failure"); sz = sizeof(uint64_t); - assert_d_eq(mallctl("stats.arenas.0.lruns.0.nmalloc", &nmalloc, &sz, + assert_d_eq(mallctl("pool.0.stats.arenas.0.lruns.0.nmalloc", &nmalloc, &sz, NULL, 0), expected, "Unexpected mallctl() result"); - assert_d_eq(mallctl("stats.arenas.0.lruns.0.ndalloc", &ndalloc, &sz, + assert_d_eq(mallctl("pool.0.stats.arenas.0.lruns.0.ndalloc", &ndalloc, &sz, NULL, 0), expected, "Unexpected mallctl() result"); - assert_d_eq(mallctl("stats.arenas.0.lruns.0.nrequests", &nrequests, &sz, + assert_d_eq(mallctl("pool.0.stats.arenas.0.lruns.0.nrequests", &nrequests, &sz, NULL, 0), expected, "Unexpected mallctl() result"); sz = sizeof(size_t); - assert_d_eq(mallctl("stats.arenas.0.lruns.0.curruns", &curruns, &sz, + assert_d_eq(mallctl("pool.0.stats.arenas.0.lruns.0.curruns", &curruns, &sz, NULL, 0), expected, "Unexpected mallctl() result"); if (config_stats) { diff --git a/src/jemalloc/test/unit/util.c b/src/jemalloc/test/unit/util.c index dc3cfe8a9db14ffcbd34f7519559938c32f61390..8ab39a4581935ba391ade45059dbb50d2cf48673 100644 --- a/src/jemalloc/test/unit/util.c +++ b/src/jemalloc/test/unit/util.c @@ -52,8 +52,8 @@ TEST_BEGIN(test_malloc_strtoumax) const char *expected_errno_name; uintmax_t expected_x; }; -#define ERR(e) e, #e -#define UMAX(x) ((uintmax_t)x##ULL) +#define ERR(e) e, #e +#define KUMAX(x) ((uintmax_t)x##ULL) struct test_s tests[] = { {"0", "0", -1, ERR(EINVAL), UINTMAX_MAX}, {"0", "0", 1, ERR(EINVAL), UINTMAX_MAX}, @@ -64,51 +64,51 @@ TEST_BEGIN(test_malloc_strtoumax) {"++3", "++3", 0, ERR(EINVAL), UINTMAX_MAX}, {"-", "-", 0, ERR(EINVAL), UINTMAX_MAX}, - {"42", "", 0, ERR(0), UMAX(42)}, - {"+42", "", 0, ERR(0), UMAX(42)}, - {"-42", "", 0, ERR(0), UMAX(-42)}, - {"042", "", 0, ERR(0), UMAX(042)}, - {"+042", "", 0, ERR(0), UMAX(042)}, - {"-042", "", 0, ERR(0), UMAX(-042)}, - {"0x42", "", 0, ERR(0), UMAX(0x42)}, - {"+0x42", "", 0, ERR(0), UMAX(0x42)}, - {"-0x42", "", 0, ERR(0), UMAX(-0x42)}, - - {"0", "", 0, ERR(0), UMAX(0)}, - {"1", "", 0, ERR(0), UMAX(1)}, - - {"42", "", 0, ERR(0), UMAX(42)}, - {" 42", "", 0, ERR(0), UMAX(42)}, - {"42 ", " ", 0, ERR(0), UMAX(42)}, - {"0x", "x", 0, ERR(0), UMAX(0)}, - {"42x", "x", 0, ERR(0), UMAX(42)}, - - {"07", "", 0, ERR(0), UMAX(7)}, - {"010", "", 0, ERR(0), UMAX(8)}, - {"08", "8", 0, ERR(0), UMAX(0)}, - {"0_", "_", 0, ERR(0), UMAX(0)}, - - {"0x", "x", 0, ERR(0), UMAX(0)}, - {"0X", "X", 0, ERR(0), UMAX(0)}, - {"0xg", "xg", 0, ERR(0), UMAX(0)}, - {"0XA", "", 0, ERR(0), UMAX(10)}, - - {"010", "", 10, ERR(0), UMAX(10)}, - {"0x3", "x3", 10, ERR(0), UMAX(0)}, - - {"12", "2", 2, ERR(0), UMAX(1)}, - {"78", "8", 8, ERR(0), UMAX(7)}, - {"9a", "a", 10, ERR(0), UMAX(9)}, - {"9A", "A", 10, ERR(0), UMAX(9)}, - {"fg", "g", 16, ERR(0), UMAX(15)}, - {"FG", "G", 16, ERR(0), UMAX(15)}, - {"0xfg", "g", 16, ERR(0), UMAX(15)}, - {"0XFG", "G", 16, ERR(0), UMAX(15)}, - {"z_", "_", 36, ERR(0), UMAX(35)}, - {"Z_", "_", 36, ERR(0), UMAX(35)} + {"42", "", 0, ERR(0), KUMAX(42)}, + {"+42", "", 0, ERR(0), KUMAX(42)}, + {"-42", "", 0, ERR(0), KUMAX(-42)}, + {"042", "", 0, ERR(0), KUMAX(042)}, + {"+042", "", 0, ERR(0), KUMAX(042)}, + {"-042", "", 0, ERR(0), KUMAX(-042)}, + {"0x42", "", 0, ERR(0), KUMAX(0x42)}, + {"+0x42", "", 0, ERR(0), KUMAX(0x42)}, + {"-0x42", "", 0, ERR(0), KUMAX(-0x42)}, + + {"0", "", 0, ERR(0), KUMAX(0)}, + {"1", "", 0, ERR(0), KUMAX(1)}, + + {"42", "", 0, ERR(0), KUMAX(42)}, + {" 42", "", 0, ERR(0), KUMAX(42)}, + {"42 ", " ", 0, ERR(0), KUMAX(42)}, + {"0x", "x", 0, ERR(0), KUMAX(0)}, + {"42x", "x", 0, ERR(0), KUMAX(42)}, + + {"07", "", 0, ERR(0), KUMAX(7)}, + {"010", "", 0, ERR(0), KUMAX(8)}, + {"08", "8", 0, ERR(0), KUMAX(0)}, + {"0_", "_", 0, ERR(0), KUMAX(0)}, + + {"0x", "x", 0, ERR(0), KUMAX(0)}, + {"0X", "X", 0, ERR(0), KUMAX(0)}, + {"0xg", "xg", 0, ERR(0), KUMAX(0)}, + {"0XA", "", 0, ERR(0), KUMAX(10)}, + + {"010", "", 10, ERR(0), KUMAX(10)}, + {"0x3", "x3", 10, ERR(0), KUMAX(0)}, + + {"12", "2", 2, ERR(0), KUMAX(1)}, + {"78", "8", 8, ERR(0), KUMAX(7)}, + {"9a", "a", 10, ERR(0), KUMAX(9)}, + {"9A", "A", 10, ERR(0), KUMAX(9)}, + {"fg", "g", 16, ERR(0), KUMAX(15)}, + {"FG", "G", 16, ERR(0), KUMAX(15)}, + {"0xfg", "g", 16, ERR(0), KUMAX(15)}, + {"0XFG", "G", 16, ERR(0), KUMAX(15)}, + {"z_", "_", 36, ERR(0), KUMAX(35)}, + {"Z_", "_", 36, ERR(0), KUMAX(35)} }; #undef ERR -#undef UMAX +#undef KUMAX unsigned i; for (i = 0; i < sizeof(tests)/sizeof(struct test_s); i++) { @@ -141,8 +141,8 @@ TEST_BEGIN(test_malloc_snprintf_truncated) char buf[BUFLEN]; int result; size_t len; -#define TEST(expected_str_untruncated, fmt...) do { \ - result = malloc_snprintf(buf, len, fmt); \ +#define TEST(expected_str_untruncated, ...) do { \ + result = malloc_snprintf(buf, len, __VA_ARGS__); \ assert_d_eq(strncmp(buf, expected_str_untruncated, len-1), 0, \ "Unexpected string inequality (\"%s\" vs \"%s\")", \ buf, expected_str_untruncated); \ @@ -173,8 +173,8 @@ TEST_BEGIN(test_malloc_snprintf) #define BUFLEN 128 char buf[BUFLEN]; int result; -#define TEST(expected_str, fmt...) do { \ - result = malloc_snprintf(buf, sizeof(buf), fmt); \ +#define TEST(expected_str, ...) do { \ + result = malloc_snprintf(buf, sizeof(buf), __VA_ARGS__); \ assert_str_eq(buf, expected_str, "Unexpected output"); \ assert_d_eq(result, strlen(expected_str), "Unexpected result"); \ } while (0) diff --git a/src/libpmem.c b/src/libpmem.c new file mode 100644 index 0000000000000000000000000000000000000000..6fedae7eed502600026feb4bd2713ba1048bc75e --- /dev/null +++ b/src/libpmem.c @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * libpmem.c -- basic libpmem functions + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/mman.h> +#include <unistd.h> +#include <stdint.h> +#include <libpmem.h> +#include "pmem.h" +#include "util.h" +#include "out.h" + +/* + * libpmem_init -- load-time initialization for libpmem + * + * Called automatically by the run-time loader. + */ +__attribute__((constructor)) +static void +libpmem_init(void) +{ + out_init(LOG_PREFIX, LOG_LEVEL_VAR, LOG_FILE_VAR); + LOG(3, NULL); + util_init(); +} + +/* + * pmem_check_version -- see if library meets application version requirements + */ +const char * +pmem_check_version(unsigned major_required, unsigned minor_required) +{ + LOG(3, "major_required %u minor_required %u", + major_required, minor_required); + + static char errstr[] = + "libpmem major version mismatch (need XXXX, found YYYY)"; + + if (major_required != PMEM_MAJOR_VERSION) { + sprintf(errstr, + "libpmem major version mismatch (need %d, found %d)", + major_required, PMEM_MAJOR_VERSION); + LOG(1, "%s", errstr); + return errstr; + } + + if (minor_required > PMEM_MINOR_VERSION) { + sprintf(errstr, + "libpmem minor version mismatch (need %d, found %d)", + minor_required, PMEM_MINOR_VERSION); + LOG(1, "%s", errstr); + return errstr; + } + + return NULL; +} + +/* + * pmem_set_funcs -- allow overriding libpmem's call to malloc, etc. + */ +void +pmem_set_funcs( + void *(*malloc_func)(size_t size), + void (*free_func)(void *ptr), + void *(*realloc_func)(void *ptr, size_t size), + char *(*strdup_func)(const char *s), + void (*print_func)(const char *s), + void (*persist_func)(void *addr, size_t len, int flags)) +{ + LOG(3, NULL); + + util_set_alloc_funcs(malloc_func, free_func, + realloc_func, strdup_func); + out_set_print_func(print_func); + pmem_set_persist_func(persist_func); +} + +/* + * libpmem_persist -- libpmem's central routine for flushing to persistence + * + * This routine calls msync() or Persist(), depending on the is_pmem flag. + */ +void +libpmem_persist(int is_pmem, void *addr, size_t len) +{ + LOG(5, "is_pmem %d addr %p len %zu", is_pmem, addr, len); + + if (is_pmem) { + Persist(addr, len, 0); + return; + } + + uintptr_t uptr; + + /* + * msync requires len to be a multiple of pagesize, so + * adjust addr and len to represent the full 4k chunks + * covering the given range. + */ + + /* increase len by the amount we gain when we round addr down */ + len += (uintptr_t)addr & (Pagesize - 1); + + /* round addr down to page boundary */ + uptr = (uintptr_t)addr & ~(Pagesize - 1); + + if (msync((void *)uptr, len, MS_SYNC) < 0) + LOG(1, "!msync"); +} diff --git a/src/libpmem.map b/src/libpmem.map new file mode 100644 index 0000000000000000000000000000000000000000..7734ab817dc55c78b00ad2c2fc0ea9dd2e1d02e5 --- /dev/null +++ b/src/libpmem.map @@ -0,0 +1,68 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# +# src/libpmem.map -- linker map file for libpmem +# +libpmem.so { + global: + pmem_is_pmem; + pmem_persist; + pmem_flush; + pmem_fence; + pmem_drain; + pmemtrn_map; + pmemtrn_unmap; + # XXX rest of pmemtrn API goes here + pmemblk_map; + pmemblk_unmap; + pmemblk_nblock; + pmemblk_read; + pmemblk_write; + pmemblk_set_zero; + pmemblk_set_error; + pmemlog_map; + pmemlog_unmap; + pmemlog_nbyte; + pmemlog_append; + pmemlog_appendv; + pmemlog_tell; + pmemlog_rewind; + pmemlog_walk; + pmem_check_version; + pmem_set_funcs; + pmemtrn_check; + pmemblk_check; + pmemlog_check; + + local: + *; +}; diff --git a/src/libvmem.c b/src/libvmem.c new file mode 100644 index 0000000000000000000000000000000000000000..bc8825e9920d315a96f848e49d202176b3975e9a --- /dev/null +++ b/src/libvmem.c @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * libvmem.c -- basic libvmem functions + */ + +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <unistd.h> +#include <libvmem.h> +#include "jemalloc.h" +#include "util.h" +#include "out.h" +#include "vmem.h" + + +/* + * libvmem_init -- load-time initialization for libvmem + * + * Called automatically by the run-time loader. + */ +__attribute__((constructor)) +static void +libvmem_init(void) +{ + out_init(LOG_PREFIX, LOG_LEVEL_VAR, LOG_FILE_VAR); + LOG(3, NULL); + util_init(); +} + +/* + * vmem_check_version -- see if library meets application version requirements + */ +const char * +vmem_check_version(unsigned major_required, unsigned minor_required) +{ + LOG(3, "major_required %u minor_required %u", + major_required, minor_required); + + static char errstr[] = + "libvmem major version mismatch (need XXXX, found YYYY)"; + + if (major_required != VMEM_MAJOR_VERSION) { + sprintf(errstr, + "libvmem major version mismatch (need %d, found %d)", + major_required, VMEM_MAJOR_VERSION); + LOG(1, "%s", errstr); + return errstr; + } + + if (minor_required > VMEM_MINOR_VERSION) { + sprintf(errstr, + "libvmem minor version mismatch (need %d, found %d)", + minor_required, VMEM_MINOR_VERSION); + LOG(1, "%s", errstr); + return errstr; + } + + return NULL; +} + +/* + * vmem_set_funcs -- allow overriding libvmem's call to malloc, etc. + */ +void +vmem_set_funcs( + void *(*malloc_func)(size_t size), + void (*free_func)(void *ptr), + void *(*realloc_func)(void *ptr, size_t size), + char *(*strdup_func)(const char *s), + void (*print_func)(const char *s)) +{ + LOG(3, NULL); + + util_set_alloc_funcs(malloc_func, free_func, + realloc_func, strdup_func); + out_set_print_func(print_func); + je_vmem_pool_set_alloc_funcs(malloc_func, free_func); +} diff --git a/src/libvmem.map b/src/libvmem.map new file mode 100644 index 0000000000000000000000000000000000000000..1853d1a13361739252d8bd3b649229aea67b7c3e --- /dev/null +++ b/src/libvmem.map @@ -0,0 +1,54 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# +# src/libvmem.map -- linker map file for libvmem +# +libvmem.so { + global: + vmem_pool_create; + vmem_pool_create_in_region; + vmem_pool_delete; + vmem_pool_check; + vmem_pool_freespace; + vmem_pool_stats_print; + vmem_malloc; + vmem_free; + vmem_calloc; + vmem_realloc; + vmem_aligned_alloc; + vmem_strdup; + vmem_check_version; + vmem_set_funcs; + + local: + *; +}; diff --git a/src/log.c b/src/log.c new file mode 100644 index 0000000000000000000000000000000000000000..fe16888e8cea04ce32dd7502975f9f6bfd3de6bd --- /dev/null +++ b/src/log.c @@ -0,0 +1,637 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY LOG OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * log.c -- log memory pool entry points for libpmem + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/param.h> +#include <sys/stat.h> +#include <signal.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> +#include <time.h> +#include <stdint.h> +#include <pthread.h> +#include <uuid/uuid.h> +#include <endian.h> +#include <libpmem.h> + +#include "pmem.h" +#include "util.h" +#include "out.h" +#include "log.h" + +/* + * log_init -- load-time initialization for log + * + * Called automatically by the run-time loader. + */ +__attribute__((constructor)) +static void +log_init(void) +{ + out_init(LOG_PREFIX, LOG_LEVEL_VAR, LOG_FILE_VAR); + LOG(3, NULL); + util_init(); +} + +/* + * pmemlog_map_common -- (internal) map a log memory pool + * + * This routine does all the work, but takes a rdonly flag so internal + * calls can map a read-only pool if required. + */ +static PMEMlog * +pmemlog_map_common(int fd, int rdonly) +{ + LOG(3, "fd %d rdonly %d", fd, rdonly); + + struct stat stbuf; + if (fstat(fd, &stbuf) < 0) { + LOG(1, "!fstat"); + return NULL; + } + + if (stbuf.st_size < PMEMLOG_MIN_POOL) { + LOG(1, "size %zu smaller than %zu", + stbuf.st_size, PMEMLOG_MIN_POOL); + errno = EINVAL; + return NULL; + } + + void *addr; + if ((addr = util_map(fd, stbuf.st_size, rdonly)) == NULL) + return NULL; /* util_map() set errno, called LOG */ + + /* check if the mapped region is located in persistent memory */ + int is_pmem = pmem_is_pmem(addr, stbuf.st_size); + + /* opaque info lives at the beginning of mapped memory pool */ + struct pmemlog *plp = addr; + struct pool_hdr hdr; + + memcpy(&hdr, &plp->hdr, sizeof (hdr)); + + if (util_convert_hdr(&hdr)) { + /* + * valid header found + */ + if (strncmp(hdr.signature, LOG_HDR_SIG, POOL_HDR_SIG_LEN)) { + LOG(1, "wrong pool type: \"%s\"", hdr.signature); + errno = EINVAL; + goto err; + } + + if (hdr.major != LOG_FORMAT_MAJOR) { + LOG(1, "log pool version %d (library expects %d)", + hdr.major, LOG_FORMAT_MAJOR); + errno = EINVAL; + goto err; + } + + uint64_t hdr_start = le64toh(plp->start_offset); + uint64_t hdr_end = le64toh(plp->end_offset); + uint64_t hdr_write = le64toh(plp->write_offset); + + if ((hdr_start != roundup(sizeof (*plp), + LOG_FORMAT_DATA_ALIGN)) || + (hdr_end != stbuf.st_size) || (hdr_start > hdr_end)) { + LOG(1, "wrong start/end offsets (start: %zu end: %zu), " + "pool size %zu", + hdr_start, hdr_end, stbuf.st_size); + errno = EINVAL; + goto err; + } + + if ((hdr_write > hdr_end) || (hdr_write < hdr_start)) { + LOG(1, "wrong write offset " + "(start: %zu end: %zu write: %zu)", + hdr_start, hdr_end, hdr_write); + errno = EINVAL; + goto err; + } + + LOG(3, "start: %zu, end: %zu, write: %zu", + hdr_start, hdr_end, hdr_write); + + int retval = util_feature_check(&hdr, LOG_FORMAT_INCOMPAT, + LOG_FORMAT_RO_COMPAT, + LOG_FORMAT_COMPAT); + if (retval < 0) + goto err; + else if (retval == 0) + rdonly = 1; + } else { + /* + * no valid header was found + */ + if (rdonly) { + LOG(1, "read-only and no header found"); + errno = EROFS; + goto err; + } + LOG(3, "creating new log memory pool"); + + struct pool_hdr *hdrp = &plp->hdr; + + memset(hdrp, '\0', sizeof (*hdrp)); + strncpy(hdrp->signature, LOG_HDR_SIG, POOL_HDR_SIG_LEN); + hdrp->major = htole32(LOG_FORMAT_MAJOR); + hdrp->compat_features = htole32(LOG_FORMAT_COMPAT); + hdrp->incompat_features = htole32(LOG_FORMAT_INCOMPAT); + hdrp->ro_compat_features = htole32(LOG_FORMAT_RO_COMPAT); + uuid_generate(hdrp->uuid); + hdrp->crtime = htole64((uint64_t)time(NULL)); + util_checksum(hdrp, sizeof (*hdrp), &hdrp->checksum, 1); + hdrp->checksum = htole64(hdrp->checksum); + + /* store pool's header */ + libpmem_persist(is_pmem, hdrp, sizeof (*hdrp)); + + /* create rest of required metadata */ + plp->start_offset = htole64(roundup(sizeof (*plp), + LOG_FORMAT_DATA_ALIGN)); + plp->end_offset = htole64(stbuf.st_size); + plp->write_offset = plp->start_offset; + + /* store non-volatile part of pool's descriptor */ + libpmem_persist(is_pmem, &plp->start_offset, + 3 * sizeof (uint64_t)); + } + + /* + * Use some of the memory pool area for run-time info. This + * run-time state is never loaded from the file, it is always + * created here, so no need to worry about byte-order. + */ + plp->addr = addr; + plp->size = stbuf.st_size; + plp->rdonly = rdonly; + plp->is_pmem = is_pmem; + + if ((plp->rwlockp = Malloc(sizeof (*plp->rwlockp))) == NULL) { + LOG(1, "!Malloc for a RW lock"); + goto err; + } + + if (pthread_rwlock_init(plp->rwlockp, NULL)) { + LOG(1, "!pthread_rwlock_init"); + goto err_free; + } + + /* + * If possible, turn off all permissions on the pool header page. + * + * The prototype PMFS doesn't allow this when large pages are in + * use not it is not considered an error if this fails. + */ + util_range_none(addr, sizeof (struct pool_hdr)); + + /* the rest should be kept read-only (debug version only) */ + RANGE_RO(addr + sizeof (struct pool_hdr), + stbuf.st_size - sizeof (struct pool_hdr)); + + LOG(3, "plp %p", plp); + return plp; + +err_free: + Free((void *)plp->rwlockp); +err: + LOG(4, "error clean up"); + int oerrno = errno; + util_unmap(addr, stbuf.st_size); + errno = oerrno; + return NULL; +} + +/* + * pmemlog_map -- map a log memory pool + */ +PMEMlog * +pmemlog_map(int fd) +{ + LOG(3, "fd %d", fd); + + return pmemlog_map_common(fd, 0); +} + +/* + * pmemlog_unmap -- unmap a log memory pool + */ +void +pmemlog_unmap(PMEMlog *plp) +{ + LOG(3, "plp %p", plp); + + if (pthread_rwlock_destroy(plp->rwlockp)) + LOG(1, "!pthread_rwlock_destroy"); + Free((void *)plp->rwlockp); + util_unmap(plp->addr, plp->size); +} + +/* + * pmemlog_nbyte -- return usable size of a log memory pool + */ +size_t +pmemlog_nbyte(PMEMlog *plp) +{ + LOG(3, "plp %p", plp); + + if (pthread_rwlock_rdlock(plp->rwlockp)) { + LOG(1, "!pthread_rwlock_rdlock"); + return (size_t)-1; + } + + size_t size = le64toh(plp->end_offset) - le64toh(plp->start_offset); + LOG(4, "plp %p nbyte %zu", plp, size); + + if (pthread_rwlock_unlock(plp->rwlockp)) + LOG(1, "!pthread_rwlock_unlock"); + + return size; +} + +/* + * pmemlog_persist -- (internal) persist data, then metadata + * + * On entry, the write lock should be held. + */ +static void +pmemlog_persist(PMEMlog *plp, uint64_t new_write_offset) +{ + uint64_t old_write_offset = le64toh(plp->write_offset); + size_t length = new_write_offset - old_write_offset; + + /* unprotect the log space range (debug version only) */ + RANGE_RW(plp->addr + old_write_offset, length); + + /* persist the data */ + libpmem_persist(plp->is_pmem, plp->addr + old_write_offset, length); + + /* protect the log space range (debug version only) */ + RANGE_RO(plp->addr + old_write_offset, length); + + /* unprotect the pool descriptor (debug version only) */ + RANGE_RW(plp->addr + sizeof (struct pool_hdr), LOG_FORMAT_DATA_ALIGN); + + /* write the metadata */ + plp->write_offset = htole64(new_write_offset); + + /* persist the metadata */ + libpmem_persist(plp->is_pmem, &plp->write_offset, + sizeof (plp->write_offset)); + + /* set the write-protection again (debug version only) */ + RANGE_RO(plp->addr + sizeof (struct pool_hdr), LOG_FORMAT_DATA_ALIGN); +} + +/* + * pmemlog_append -- add data to a log memory pool + */ +int +pmemlog_append(PMEMlog *plp, const void *buf, size_t count) +{ + int ret = 0; + + LOG(3, "plp %p buf %p count %zu", plp, buf, count); + + if (plp->rdonly) { + LOG(1, "can't append to read-only log"); + errno = EROFS; + return -1; + } + + if (pthread_rwlock_wrlock(plp->rwlockp)) { + LOG(1, "!pthread_rwlock_wrlock"); + return -1; + } + + /* get the current values */ + uint64_t end_offset = le64toh(plp->end_offset); + uint64_t write_offset = le64toh(plp->write_offset); + + if (write_offset >= end_offset) { + /* no space left */ + errno = ENOSPC; + ret = -1; + } else { + /* make sure we don't write past the available space */ + if (count > (end_offset - write_offset)) { + errno = ENOSPC; + ret = -1; + } else { + char *data = plp->addr; + + /* + * unprotect the log space range, + * where the new data will be stored + * (debug version only) + */ + RANGE_RW(&data[write_offset], count); + + memcpy(&data[write_offset], buf, count); + + /* protect the log space range (debug version only) */ + RANGE_RO(&data[write_offset], count); + + write_offset += count; + } + } + + /* persist the data and the metadata only if there was no error */ + if (ret == 0) + pmemlog_persist(plp, write_offset); + + int oerrno = errno; + if (pthread_rwlock_unlock(plp->rwlockp)) + LOG(1, "!pthread_rwlock_unlock"); + errno = oerrno; + + return ret; +} + +/* + * pmemlog_appendv -- add gathered data to a log memory pool + */ +int +pmemlog_appendv(PMEMlog *plp, const struct iovec *iov, int iovcnt) +{ + LOG(3, "plp %p iovec %p iovcnt %d", plp, iov, iovcnt); + + int ret = 0; // success + int i; + + if (plp->rdonly) { + LOG(1, "can't append to read-only log"); + errno = EROFS; + return -1; + } + + if (pthread_rwlock_wrlock(plp->rwlockp)) { + LOG(1, "!pthread_rwlock_wrlock"); + return -1; + } + + /* get the current values */ + uint64_t end_offset = le64toh(plp->end_offset); + uint64_t write_offset = le64toh(plp->write_offset); + + if (write_offset >= end_offset) { + /* no space left */ + errno = ENOSPC; + ret = -1; + } else { + char *data = plp->addr; + uint64_t count = 0; + char *buf; + + /* calculate required space */ + for (i = 0; i < iovcnt; ++i) + count += iov[i].iov_len; + + /* check if there is enough free space */ + if (count > (end_offset - write_offset)) { + errno = ENOSPC; + ret = -1; + } else { + /* append the data */ + for (i = 0; i < iovcnt; ++i) { + buf = iov[i].iov_base; + count = iov[i].iov_len; + + /* + * unprotect the log space range, + * where the new data will be stored + * (debug version only) + */ + RANGE_RW(&data[write_offset], count); + + memcpy(&data[write_offset], buf, count); + + /* + * protect the log space range + * (debug version only) + */ + RANGE_RO(&data[write_offset], count); + + write_offset += count; + } + } + } + + /* persist the data and the metadata only if there was no error */ + if (ret == 0) + pmemlog_persist(plp, write_offset); + + int oerrno = errno; + if (pthread_rwlock_unlock(plp->rwlockp)) + LOG(1, "!pthread_rwlock_unlock"); + errno = oerrno; + + return ret; +} + +/* + * pmemlog_tell -- return current write point in a log memory pool + */ +off_t +pmemlog_tell(PMEMlog *plp) +{ + LOG(3, "plp %p", plp); + + if (pthread_rwlock_rdlock(plp->rwlockp)) { + LOG(1, "!pthread_rwlock_rdlock"); + return (off_t)-1; + } + + off_t wp = le64toh(plp->write_offset) - le64toh(plp->start_offset); + LOG(4, "write offset %zu", wp); + + if (pthread_rwlock_unlock(plp->rwlockp)) + LOG(1, "!pthread_rwlock_unlock"); + + return wp; +} + +/* + * pmemlog_rewind -- discard all data, resetting a log memory pool to empty + */ +void +pmemlog_rewind(PMEMlog *plp) +{ + LOG(3, "plp %p", plp); + + if (plp->rdonly) { + LOG(1, "can't rewind read-only log"); + errno = EROFS; + return; + } + + if (pthread_rwlock_wrlock(plp->rwlockp)) { + LOG(1, "!pthread_rwlock_wrlock"); + return; + } + + /* unprotect the pool descriptor (debug version only) */ + RANGE_RW(plp->addr + sizeof (struct pool_hdr), LOG_FORMAT_DATA_ALIGN); + + plp->write_offset = plp->start_offset; + libpmem_persist(plp->is_pmem, &plp->write_offset, sizeof (uint64_t)); + + /* set the write-protection again (debug version only) */ + RANGE_RO(plp->addr + sizeof (struct pool_hdr), LOG_FORMAT_DATA_ALIGN); + + if (pthread_rwlock_unlock(plp->rwlockp)) + LOG(1, "!pthread_rwlock_unlock"); +} + +/* + * pmemlog_walk -- walk through all data in a log memory pool + * + * chunksize of 0 means process_chunk gets called once for all data + * as a single chunk. + */ +void +pmemlog_walk(PMEMlog *plp, size_t chunksize, + int (*process_chunk)(const void *buf, size_t len, void *arg), void *arg) +{ + LOG(3, "plp %p chunksize %zu", plp, chunksize); + + /* + * We are assuming that the walker doesn't change the data it's reading + * in place. We prevent everyone from changing the data behind our back + * until we are done with processing it. + */ + if (pthread_rwlock_rdlock(plp->rwlockp)) { + LOG(1, "!pthread_rwlock_rdlock"); + return; + } + + char *data = plp->addr; + uint64_t write_offset = le64toh(plp->write_offset); + uint64_t data_offset = le64toh(plp->start_offset); + size_t len; + + if (chunksize == 0) { + /* most common case: process everything at once */ + len = write_offset - data_offset; + LOG(3, "length %zu", len); + (*process_chunk)(&data[data_offset], len, arg); + } else { + /* + * Walk through the complete record, chunk by chunk. + * The callback returns 0 to terminate the walk. + */ + while (data_offset < write_offset) { + len = MIN(chunksize, write_offset - data_offset); + if (!(*process_chunk)(&data[data_offset], len, arg)) + break; + data_offset += chunksize; + } + } + + if (pthread_rwlock_unlock(plp->rwlockp)) + LOG(1, "!pthread_rwlock_unlock"); +} + +/* + * pmemlog_check -- log memory pool consistency check + * + * Returns true if consistent, zero if inconsistent, -1/error if checking + * cannot happen due to other errors. + */ +int +pmemlog_check(const char *path) +{ + LOG(3, "path \"%s\"", path); + + int fd = open(path, O_RDWR); + + if (fd < 0) { + LOG(1, "!open"); + return -1; + } + + /* open the pool read-only */ + PMEMlog *plp = pmemlog_map_common(fd, 1); + int oerrno = errno; + close(fd); + errno = oerrno; + + if (plp == NULL) + return -1; /* errno set by pmemlog_map_common() */ + + int consistent = 1; + + /* validate pool descriptor */ + uint64_t hdr_start = le64toh(plp->start_offset); + uint64_t hdr_end = le64toh(plp->end_offset); + uint64_t hdr_write = le64toh(plp->write_offset); + + if (hdr_start != roundup(sizeof (*plp), LOG_FORMAT_DATA_ALIGN)) { + LOG(1, "wrong value of start_offset"); + consistent = 0; + } + + if (hdr_end != plp->size) { + LOG(1, "wrong value of end_offset"); + consistent = 0; + } + + if (hdr_start > hdr_end) { + LOG(1, "start_offset greater than end_offset"); + consistent = 0; + } + + if (hdr_start > hdr_write) { + LOG(1, "start_offset greater than write_offset"); + consistent = 0; + } + + if (hdr_write > hdr_end) { + LOG(1, "write_offset greater than end_offset"); + consistent = 0; + } + + pmemlog_unmap(plp); + + if (consistent) + LOG(4, "pool consistency check OK"); + + return consistent; +} diff --git a/src/log.h b/src/log.h new file mode 100644 index 0000000000000000000000000000000000000000..f1ea5f72d9d14b80815d4032440d6ac45c672261 --- /dev/null +++ b/src/log.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * log.h -- internal definitions for libpmem log module + */ + +/* attributes of the log memory pool format for the pool header */ +#define LOG_HDR_SIG "PMEMLOG" /* must be 8 bytes including '\0' */ +#define LOG_FORMAT_MAJOR 1 +#define LOG_FORMAT_COMPAT 0x0000 +#define LOG_FORMAT_INCOMPAT 0x0000 +#define LOG_FORMAT_RO_COMPAT 0x0000 + +struct pmemlog { + struct pool_hdr hdr; /* memory pool header */ + + /* root info for on-media format... */ + uint64_t start_offset; /* start offset of the usable log space */ + uint64_t end_offset; /* maximum offset of the usable log space */ + uint64_t write_offset; /* current write point for the log */ + + /* some run-time state, allocated out of memory pool... */ + void *addr; /* mapped region */ + size_t size; /* size of mapped region */ + int is_pmem; /* true if pool is PMEM */ + int rdonly; /* true if pool is opened read-only */ + pthread_rwlock_t *rwlockp; /* pointer to RW lock */ +}; + +/* data area starts at this alignement after the struct pmemlog above */ +#define LOG_FORMAT_DATA_ALIGN 4096 diff --git a/src/nondebug/Makefile b/src/nondebug/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..b29e373e0aee15615b51f1de87d51496a0ed6fce --- /dev/null +++ b/src/nondebug/Makefile @@ -0,0 +1,37 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/nondebug/Makefile -- build the nondebug versions of the NVM Library +# + +include ../Makefile.inc diff --git a/src/nondebug/README b/src/nondebug/README new file mode 100644 index 0000000000000000000000000000000000000000..df58b8a9591c235297948ad9beb41714e020e0d9 --- /dev/null +++ b/src/nondebug/README @@ -0,0 +1,9 @@ +Linux NVM Library + +This is src/nondebug/README. + +This directory is where nondebug versions of the object files and +the targets end up. To build just the nondebug version of the +library, use "make all" from this directory. To build both +the debug and nondebug version, use "make all" from the parent +directory. diff --git a/src/out.c b/src/out.c new file mode 100644 index 0000000000000000000000000000000000000000..8c3664c5e8af423fbdde2cf4c3dfa5df8f14fad5 --- /dev/null +++ b/src/out.c @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * out.c -- support for logging, tracing, and assertion output + * + * Macros like LOG(), OUT, ASSERT(), etc. end up here. + */ + +#include <stdio.h> +#include <stdarg.h> +#include <stdlib.h> +#include <sys/types.h> +#include <unistd.h> +#include <dirent.h> +#include <string.h> +#include <errno.h> +#include <libvmem.h> +#include "out.h" + +char nvml_src_version[] = "SRCVERSION:" SRCVERSION; + +static const char *Log_prefix; +static int Log_level; +static FILE *Out_fp; + +#ifdef DEBUG +/* + * getexecname -- return name of current executable + * + * This function is only used when logging is enabled, to make + * it more clear in the log which program was running. + */ +static const char * +getexecname(void) +{ + char procpath[PATH_MAX]; + static char namepath[PATH_MAX]; + int cc; + + snprintf(procpath, PATH_MAX, "/proc/%d/exe", getpid()); + + if ((cc = readlink(procpath, namepath, PATH_MAX)) < 0) + strcpy(namepath, "unknown"); + else + namepath[cc] = '\0'; + + return namepath; +} +#endif /* DEBUG */ + +/* + * out_init -- initialize the log + * + * This is called from the library initialization code. + */ +void +out_init(const char *log_prefix, const char *log_level_var, + const char *log_file_var) +{ + static int once; + + /* only need to initialize the out module once */ + if (once) + return; + once++; + + Log_prefix = log_prefix; + +#ifdef DEBUG + char *log_level; + char *log_file; + + if ((log_level = getenv(log_level_var)) != NULL) { + Log_level = atoi(log_level); + if (Log_level < 0) { + Log_level = 0; + } + } + + if ((log_file = getenv(log_file_var)) != NULL && + ((Out_fp = fopen(log_file, "w")) == NULL)) { + fprintf(stderr, "Error: %s=%s: %s\n", + log_file_var, log_file, strerror(errno)); + exit(1); + } +#endif /* DEBUG */ + + if (Out_fp == NULL) + Out_fp = stderr; + else + setlinebuf(Out_fp); + + LOG(1, "pid %d: program: %s", getpid(), getexecname()); + LOG(1, "version %d.%d", VMEM_MAJOR_VERSION, VMEM_MINOR_VERSION); + LOG(1, "src version %s", nvml_src_version); +} + +/* + * out_fini -- close the log file + * + * This is called to close log file before process stop. + */ +void +out_fini() +{ + if (Out_fp != NULL && Out_fp != stderr) { + fclose(Out_fp); + Out_fp = stderr; + } +} + +/* + * out_print_func -- default print_func, goes to stderr or Out_fp + */ +static void +out_print_func(const char *s) +{ + fputs(s, Out_fp); +} + +/* + * calling Print(s) calls the current print_func... + */ +typedef void (*Print_func)(const char *s); +static Print_func Print = out_print_func; + +/* + * out_set_print_func -- allow override of print_func used by out module + */ +void +out_set_print_func(void (*print_func)(const char *s)) +{ + LOG(3, "print %p", print_func); + + Print = (print_func == NULL) ? out_print_func : print_func; +} + +/* + * out_common -- common output code, all output goes through here + */ +#define MAXPRINT 8192 /* maximum expected log line */ +static void +out_common(const char *file, int line, const char *func, int level, + const char *suffix, const char *fmt, va_list ap) +{ + int oerrno = errno; + char buf[MAXPRINT]; + int cc = 0; + const char *sep = ""; + const char *errstr = ""; + + if (file) + cc += snprintf(&buf[cc], MAXPRINT - cc, + "<%s>: <%d> [%s:%d %s] ", + Log_prefix, level, file, line, func); + + if (fmt) { + if (*fmt == '!') { + fmt++; + sep = ": "; + errstr = strerror(errno); + } + cc += vsnprintf(&buf[cc], MAXPRINT - cc, fmt, ap); + } + + snprintf(&buf[cc], MAXPRINT - cc, "%s%s%s", sep, errstr, suffix); + + Print(buf); + errno = oerrno; +} + +/* + * out -- output a line, newline added automatically + */ +void +out(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + + out_common(NULL, 0, NULL, 0, "\n", fmt, ap); + + va_end(ap); +} + +/* + * out_nonl -- output a line, no newline added automatically + */ +void +out_nonl(int level, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + + out_common(NULL, 0, NULL, level, "", fmt, ap); + + va_end(ap); +} + +/* + * out_log -- output a log line if Log_level >= level + */ +void +out_log(const char *file, int line, const char *func, int level, + const char *fmt, ...) +{ + va_list ap; + + if (Log_level < level) + return; + + va_start(ap, fmt); + out_common(file, line, func, level, "\n", fmt, ap); + + va_end(ap); +} + +/* + * out_fatal -- output a fatal error & die (i.e. assertion failure) + */ +void +out_fatal(const char *file, int line, const char *func, + const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + + out_common(file, line, func, 1, "\n", fmt, ap); + + va_end(ap); + + exit(1); +} diff --git a/src/out.h b/src/out.h new file mode 100644 index 0000000000000000000000000000000000000000..59d56811bcbab90168ab7d6ed0307f79faabe961 --- /dev/null +++ b/src/out.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * out.h -- definitions for "out" module + */ + +#ifdef DEBUG + +/* produce debug/trace output */ +#define LOG(level, ...)\ + out_log(__FILE__, __LINE__, __func__, level, __VA_ARGS__) + +/* produce debug/trace output without prefix and new line */ +#define LOG_NONL(level, ...)\ + out_nonl(level, __VA_ARGS__) + +/* produce output and exit */ +#define FATAL(...)\ + out_fatal(__FILE__, __LINE__, __func__, __VA_ARGS__) + +/* assert a condition is true */ +#define ASSERT(cnd)\ + ((void)((cnd) || (out_fatal(__FILE__, __LINE__, __func__,\ + "assertion failure: %s", #cnd), 0))) + +/* assertion with extra info printed if assertion fails */ +#define ASSERTinfo(cnd, info)\ + ((void)((cnd) || (out_fatal(__FILE__, __LINE__, __func__,\ + "assertion failure: %s (%s = %s)", #cnd, #info, info), 0))) + +/* assert two integer values are equal */ +#define ASSERTeq(lhs, rhs)\ + ((void)(((lhs) == (rhs)) || (out_fatal(__FILE__, __LINE__, __func__,\ + "assertion failure: %s (0x%llx) == %s (0x%llx)", #lhs,\ + (unsigned long long)(lhs), #rhs, (unsigned long long)(rhs)), 0))) + +/* assert two integer values are not equal */ +#define ASSERTne(lhs, rhs)\ + ((void)(((lhs) != (rhs)) || (out_fatal(__FILE__, __LINE__, __func__,\ + "assertion failure: %s (0x%llx) != %s (0x%llx)", #lhs,\ + (unsigned long long)(lhs), #rhs, (unsigned long long)(rhs)), 0))) + +#else + +/* + * nondebug versions... + */ +#define LOG(level, ...) +#define LOG_NONL(level, ...) +#define ASSERT(cnd) +#define ASSERTinfo(cnd, info) +#define ASSERTeq(lhs, rhs) +#define ASSERTne(lhs, rhs) + +/* shouldn't get called, but if it does, don't continue to run */ +#define FATAL(...) abort() + +#endif /* DEBUG */ + +void out_init(const char *log_prefix, const char *log_level_var, + const char *log_file_var); +void out_fini(); +void out(const char *fmt, ...) __attribute__((format(printf, 1, 2))); +void out_nonl(int level, const char *fmt, + ...) __attribute__((format(printf, 2, 3))); +void out_log(const char *file, int line, const char *func, int level, + const char *fmt, ...) + __attribute__((format(printf, 5, 6))); +void out_fatal(const char *file, int line, const char *func, + const char *fmt, ...) + __attribute__((format(printf, 4, 5))); +void out_set_print_func(void (*print_func)(const char *s)); diff --git a/src/pmem.c b/src/pmem.c new file mode 100644 index 0000000000000000000000000000000000000000..da99d28d293808e9b83fb737fe7891aa0d8bbbdd --- /dev/null +++ b/src/pmem.c @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2013, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * pmem.c -- pmem entry points for libpmem + */ + +#include <sys/types.h> +#include <sys/mman.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <string.h> + +#include "libpmem.h" +#include "pmem.h" +#include "util.h" +#include "out.h" + +#define FLUSH_ALIGN 64 + +/* default persist function is pmem_persist() */ +Persist_func Persist = pmem_persist; + +/* + * pmem_set_persist_func -- allow override of persist_func used libpmem + */ +void +pmem_set_persist_func(void (*persist_func)(void *addr, size_t len, int flags)) +{ + LOG(3, "persist %p", persist_func); + + Persist = (persist_func == NULL) ? pmem_persist : persist_func; +} + +/* + * pmem_drain -- wait for any PM stores to drain from HW buffers + */ +void +pmem_drain(void) +{ + /* + * Nothing to do here -- assumes an auto-drain feature like ADR. + * + * XXX handle drain for other platforms + */ +} + +/* + * pmem_flush -- flush processor cache for the given range + */ +void +pmem_flush(void *addr, size_t len, int flags) +{ + uintptr_t uptr; + + /* loop through 64B-aligned chunks covering the given range */ + for (uptr = (uintptr_t)addr & ~(FLUSH_ALIGN - 1); + uptr < (uintptr_t)addr + len; uptr += 64) + __builtin_ia32_clflush((void *)uptr); +} + +/* + * pmem_persist -- make any cached changes to a range of PMEM persistent + */ +void +pmem_persist(void *addr, size_t len, int flags) +{ + pmem_flush(addr, len, flags); + __builtin_ia32_sfence(); + pmem_drain(); +} + +/* + * is_pmem_always -- debug/test version of pmem_is_pmem(), always true + */ +static int +is_pmem_always(void *addr, size_t len) +{ + LOG(3, "always true"); + return 1; +} + +/* + * is_pmem_never -- debug/test version of pmem_is_pmem(), never true + */ +static int +is_pmem_never(void *addr, size_t len) +{ + LOG(3, "never true"); + return 0; +} + +/* + * is_pmem_proc -- use /proc to implement pmem_is_pmem() + * + * This function returns true only if the entire range can be confirmed + * as being direct access persistent memory. Finding any part of the + * range is not direct access, or failing to look up the information + * because it is unmapped or because any sort of error happens, just + * results in returning false. + * + * This function works by lookup up the range in /proc/self/smaps and + * verifying the "mixed map" vmflag is set for that range. While this + * isn't exactly the same as direct access, there is no DAX flag in + * the vmflags and the mixed map flag is only true on regular files when + * DAX is in-use, so it serves the purpose. + * + * The range passed in may overlap with multiple entries in the smaps list + * so this function loops through the smaps entries until the entire range + * is verified as direct access, or until it is clear the answer is false + * in which case it stops the loop and returns immediately. + */ +static int +is_pmem_proc(void *addr, size_t len) +{ + char *caddr = addr; + + FILE *fp; + if ((fp = fopen("/proc/self/smaps", "r")) == NULL) { + LOG(1, "!/proc/self/smaps"); + return 0; + } + + int retval = 0; /* assume false until proven otherwise */ + char *line = NULL; /* for getline() */ + size_t linelen; /* for getline() */ + char *lo = NULL; /* beginning of current range in smaps file */ + char *hi = NULL; /* end of current range in smaps file */ + int needmm = 0; /* looking for mm flag for current range */ + while (getline(&line, &linelen, fp) != -1) { + static const char vmflags[] = "VmFlags:"; + static const char mm[] = " mm"; + + /* check for range line */ + if (sscanf(line, "%p-%p", &lo, &hi) == 2) { + if (needmm) { + /* last range matched, but no mm flag found */ + LOG(4, "never found mm flag"); + break; + } else if (caddr < lo) { + /* never found the range for caddr */ + LOG(4, "no match for addr %p", caddr); + break; + } else if (caddr < hi) { + /* start address is in this range */ + size_t rangelen = hi - caddr; + + /* remember that matching has started */ + needmm = 1; + + /* calculate remaining range to search for */ + if (len > rangelen) { + len -= rangelen; + caddr += rangelen; + LOG(4, "matched %zu bytes in range " + "%p-%p, %zu left over", + rangelen, lo, hi, len); + } else { + len = 0; + LOG(4, "matched all bytes in range " + "%p-%p", lo, hi); + } + } + } else if (needmm && strncmp(line, vmflags, + sizeof (vmflags) - 1) == 0) { + if (strstr(&line[sizeof (vmflags) - 1], mm) != NULL) { + LOG(4, "mm flag found"); + if (len == 0) { + /* entire range matched */ + retval = 1; + break; + } + needmm = 0; /* saw what was needed */ + } else { + /* mm flag not set for some or all of range */ + LOG(4, "range has no mm flag"); + break; + } + } + } + + Free(line); + fclose(fp); + + LOG(3, "returning %d", retval); + return retval; +} + +/* pmem_is_pmem() calls this function to do the work */ +static int (*is_pmem_func)(void *addr, size_t len) = is_pmem_proc; + +/* + * pmem_init -- load-time initialization for pmem.c + * + * Called automatically by the run-time loader. + */ +__attribute__((constructor)) +static void +pmem_init(void) +{ + out_init(LOG_PREFIX, LOG_LEVEL_VAR, LOG_FILE_VAR); + LOG(3, NULL); + util_init(); + + /* + * For debugging/testing, allow pmem_is_pmem() to be forced + * to always true or never true using environment variable + * PMEM_IS_PMEM_FORCE values of zero or one. + * + * This isn't #ifdef DEBUG because it has a trivial performance + * impact and it may turn out to be useful as a "chicken bit" for + * systems where pmem_is_pmem() isn't correctly detecting true + * persistent memory. + */ + char *ptr = getenv("PMEM_IS_PMEM_FORCE"); + if (ptr) { + int val = atoi(ptr); + + if (val == 0) + is_pmem_func = is_pmem_never; + else if (val == 1) + is_pmem_func = is_pmem_always; + } +} + +/* + * pmem_is_pmem -- return true if entire range is persistent Memory + */ +int +pmem_is_pmem(void *addr, size_t len) +{ + LOG(3, "addr %p len %zu", addr, len); + + return (*is_pmem_func)(addr, len); +} diff --git a/src/pmem.h b/src/pmem.h new file mode 100644 index 0000000000000000000000000000000000000000..dfaf817f79511792cae5932db516a5c031e46bbd --- /dev/null +++ b/src/pmem.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * pmem.h -- internal definitions for libpmem + */ + +#define LOG_PREFIX "libpmem" +#define LOG_LEVEL_VAR "PMEM_LOG_LEVEL" +#define LOG_FILE_VAR "PMEM_LOG_FILE" + +extern unsigned long Pagesize; + +typedef void (*Persist_func)(void *addr, size_t len, int flags); + +Persist_func Persist; + +void pmem_set_persist_func(void (*persist_func)(void *addr, + size_t len, int flags)); + +void libpmem_persist(int is_pmem, void *addr, size_t len); diff --git a/src/test/.gitignore b/src/test/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..f34c476ebd95a91d93c2391ff86d229f2ba82b2f --- /dev/null +++ b/src/test/.gitignore @@ -0,0 +1,9 @@ +# testconfig.sh should not be checked into git .it describes the configuration +# of the local machine where the local copy of the source tree is being tested. +testconfig.sh +# ignore files generated during test runs (left around for analysis) +*.log +testfile* +# ignore static binaries generated for testing +*.static-debug +*.static-nondebug diff --git a/src/test/Makefile b/src/test/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..9f127cbbca6c4148a5a5a6435642f647d1149c0d --- /dev/null +++ b/src/test/Makefile @@ -0,0 +1,84 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/Makefile -- build all unit tests +# +# Makefile -- build all unit tests +# +TEST = blk_nblock\ + blk_recovery\ + blk_rw\ + blk_rw_mt\ + checksum\ + log_basic\ + log_recovery\ + log_walker\ + scope\ + traces\ + traces_custom_function\ + pmem_is_pmem\ + pmem_is_pmem_proc\ + pmem_map\ + vmem_check_version\ + vmem_custom_alloc\ + vmem_malloc\ + vmem_calloc\ + vmem_realloc\ + vmem_aligned_alloc\ + vmem_mix_allocations\ + vmem_strdup\ + vmem_multiple_pools\ + vmem_out_of_memory\ + vmem_check_allocations\ + vmem_pool_create_error\ + vmem_pool_create\ + vmem_pool_create_in_region\ + vmem_valgrind\ + vmem_stats + + +all : TARGET = all +clean : TARGET = clean +clobber : TARGET = clobber +test : TARGET = test +cstyle : TARGET = cstyle + +all clean clobber test cstyle: $(TEST) + +$(TEST): unittest + $(MAKE) -C $@ $(TARGET) + +unittest: + $(MAKE) -C $@ $(TARGET) + +.PHONY: all clean clobber test cstyle unittest $(TEST) diff --git a/src/test/Makefile.inc b/src/test/Makefile.inc new file mode 100644 index 0000000000000000000000000000000000000000..1383facbf8a5c0e396f7e4945306c0bc1588d883 --- /dev/null +++ b/src/test/Makefile.inc @@ -0,0 +1,66 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/Makefile.inc -- common Makefile defs for unit tests +# +# These defaults apply to most unit tests. The individual Makefile +# for each unit test overrides the defaults as necessary. +# +LIBS = ../unittest/libut.a -L../../debug -luuid -pthread +STATIC_DEBUG_LIBS = ../unittest/libut.a ../../debug/libpmem.a -luuid -pthread +STATIC_NONDEBUG_LIBS = ../unittest/libut.a ../../nondebug/libpmem.a -luuid -pthread +INCS = -I../unittest -I../../include +CFLAGS = -ggdb -Wall -Werror -std=gnu99 + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(CC) -o $@ $(OBJS) $(LIBS) + $(CC) -o $@.static-debug $(OBJS) $(STATIC_DEBUG_LIBS) + $(CC) -o $@.static-nondebug $(OBJS) $(STATIC_NONDEBUG_LIBS) + +.c.o: + $(CC) -c $(CFLAGS) $(INCS) $< -o $@ + +clean: + $(RM) *.o */*.o core a.out *.log testfile* + +clobber: clean + $(RM) $(TARGET) $(TARGET).static-debug $(TARGET).static-nondebug + +cstyle: + ../../../utils/cstyle -pP *.c + +.PHONY: all clean clobber cstyle + +$(OBJS): ../unittest/unittest.h diff --git a/src/test/README b/src/test/README new file mode 100644 index 0000000000000000000000000000000000000000..0d3a18738f42038cb8992f0aca457146174abea4 --- /dev/null +++ b/src/test/README @@ -0,0 +1,221 @@ +Linux NVM Library + +This is src/test/README. + +This directory contains the unit tests for the NVM Library. + +Unit tests require a config file, testconfig.sh, to exist in this directory. +That file describes the local machine configuration (where to find persistent +memory, for example) and must be created by hand in each repo as it makes no +sense to check in that configuration description to the main repo. + +testconfig.sh.example provides more detail. The script RUNTESTS, when run with +no arguments, will run all unit tests through all the combinations of fs-types +and build-types, running the "check" level test. + + +DETAILS ON HOW TO RUN UNIT TESTS + +See the top-level README for instructions on building, installing, running +tests for the entire tree. Here are some additional details on running tests. + +Once the libraries are built, tests may be built from this directory using: + $ make test + +A testconfig.sh must exist to run these tests! + $ cp testconfig.sh.example testconfig.sh + $ ...edit testconfig.sh and modify as appropriate... + +Tests may be run using the RUNTESTS script: + $ RUNTESTS (runs them all) + $ RUNTESTS testname (runs just the named test) + +Each test script (named something like "TEST0") is potentially run multiple +times with a different set of environment variables so run the test with +different target file systems or different versions of the libraries. To see +how RUNTESTS will run a test, use the -n option. For example: + + $ RUNTESTS -n blk_nblock + RUNTESTS: test-type: check + (in ./blk_nblock) TEST=check FS=local BUILD=debug ./TEST0 + (in ./blk_nblock) TEST=check FS=local BUILD=nondebug ./TEST0 + (in ./blk_nblock) TEST=check FS=local BUILD=static-debug ./TEST0 + (in ./blk_nblock) TEST=check FS=local BUILD=static-nondebug ./TEST0 + (in ./blk_nblock) TEST=check FS=pmem BUILD=debug ./TEST0 + (in ./blk_nblock) TEST=check FS=pmem BUILD=nondebug ./TEST0 + (in ./blk_nblock) TEST=check FS=pmem BUILD=static-debug ./TEST0 + (in ./blk_nblock) TEST=check FS=pmem BUILD=static-nondebug ./TEST0 + (in ./blk_nblock) TEST=check FS=non-pmem BUILD=debug ./TEST0 + (in ./blk_nblock) TEST=check FS=non-pmem BUILD=nondebug ./TEST0 + (in ./blk_nblock) TEST=check FS=non-pmem BUILD=static-debug ./TEST0 + (in ./blk_nblock) TEST=check FS=non-pmem BUILD=static-nondebug ./TEST0 + +Notice how the TEST0 script is run repeatedly with different settings for +the three environment variables TEST, FS, and BUILD, providing the test type, +file system type, and build type to test. + +RUNTESTS takes options to limit what it runs. The usage is: + + RUNTEST [ -nv ] [ -b build-type ] [ -t test-type ] [ -f fs-type ] [test...] + + Build types are: debug, nondebug, static-debug, static-nondebug, all (default) + Test types are: check (default), short, long + File system types are: local, pmem, non-pmem, all (default) + +For example: + + $ RUNTESTS -b debug blk_nblock + RUNTESTS: test-type: check + blk_nblock/TEST0: SETUP (check/local/debug) + blk_nblock/TEST0: START: blk_nblock + blk_nblock/TEST0: PASS + blk_nblock/TEST0: SKIP fs-type pmem (not configured) + blk_nblock/TEST0: SKIP fs-type non-pmem (local required) + RUNTESTS: No failures. + +Since the "-b debug" option was given, the RUNTESTS run above only executes +the test for the debug version of the library and skips the other variants. + +Running the TEST* scripts directly is also common, especially when debugging +an issue. Just running the script, like this: + + $ cd blk_nblock + $ ./TEST0 + +will use default values for the environment, namely: + + TEST=check FS=local BUILD=debug + +these defaults can be overridden on the command line: + + $ cd blk_nblock + $ TEST=check FS=local BUILD=nondebug ./TEST0 + +The above example runs TEST0 with the nondebug library, just as using +RUNTESTS with "-b nondebug" would from the parent directory. + +In addition to overriding TEST, FS, and BUILD environment variables, the +unit test framework also looks for several other variables: + + For tests that run a local program, insert the word "echo" in front + of the program execution so the full command being run is displayed. + This is useful to modify the command for debugging. + + $ ECHO=echo ./TEST0 + + Insert the word "strace" in front of the local command execution: + + $ TRACE=strace ./TEST0 + + Override the LD_LIBRARY_PATH provided by the unit test framework. This + is useful for running a test against another source tree or against the + libraries installed on the system: + + $ TEST_LD_LIBRARY_PATH=/usr/lib ./TEST0 + + +DETAILS ON HOW TO WRITE UNIT TESTS + +A minimal unit test consists of a sub-directory here with an executable called +TEST0 in it that exits normally when the test passes. Mosts tests, however, +source the file unittest/unittest.sh to use the utility functions for setting +up and checking tests. Additionally, most unit tests build a local test +program and call it from the TEST* scripts. + +In additional to TEST0, there can be as many TEST<num> scripts as desired, and +RUNTESTS will execute them in numeric order for each of the test runs it +executes. + +If a test only makes sense using the local directory, meaning it does not need +an external file system or persistent memory, the script uses this line: + + require_fs_type local + +Similarly, if the test only makes sense for pmem or non-pmem: + + require_fs_type pmem + or + require_fs_type non-pmem + +The above two are often combined to indicate the test should run once for pmem +and once for non-pmem, but never with the local directory: + + require_fs_type pmem non-pmem + +Similar to the above, tests can require a specific build types: + + require_build_type debug + +Most tests are short "make check" tests, designed to run quickly when +smoke-checking a build. Two other test types are available: short and long. A +test script can indicate it should only run during a long test run, for +example, using: + + require_test_type long + +Using the unittest library, the C programs run during unit testing get their +output and tracing information logged to various files. These are named with +the test number embedded in them, so a script called TEST0 would commonly +produce: + + err0.log log of stderr + out0.log log of stdout + trace0.log trace points from unittest library + pmem0.log trace from libpmem (PMEM_LOG_FILE points here) + vmem0.log trace from libvmem (VMEM_LOG_FILE points here) + +Although the above log files are the common case, the TEST* scripts are free to +create any files. It is recommended, however, that the script creates files +that are listed in .gitignore so they don't accidentally get committed to the +repo. + +The TEST* scripts typically use the shell function "check" to check their +results. That function calls the perl script "match" for any .match files +found. For example, to check out0.log contains the expected output, the test +author creates a file called out0.log.match and commits that into the repo. +The match script provides several pattern-matching macros that allow for normal +variation in the test output: + + $(N) an integer (i.e. one or more decimal digits) + $(FP) a floating point number + $(S) ascii string + $(X) hex number + $(W) whitespace + $(*) any string + $(DD) output of a "dd" run + $(OPT) the entire line is optional + +The small C programs used for unit testing are designed to not worry about the +return values for things not under test. This is done with the all-caps +versions of many common libc calls, for example: + + fd = OPEN(fname, O_RDRW); + +The above call is just like calling open(2), expect the framework checks for +unexpected errors and halts the unit test if those happen. The result is +usually a very short, compact unit test where most of the code is the +interesting code under test. A full list of unit test macros is in +unittest/inittest.h. + +The best way to create a new unit test is to start with an existing one. The +test: + + blk_rw + +makes an excellent starting point for new tests. It illustrates the common +idioms used in the TEST* scripts, how the small C program is usually +command-line driven to create multiple cases, and the use of unit test macros +like START, OUT, FATAL, and DONE. Every case is different, but a common +pattern for creating new unit tests is to follow steps like these: + + $ cp blk_rw new_test_name + $ ...edit Makefile to add new_test_name to TEST list... + $ cd new_test_name + $ mv blk_rw.c to new_test_name.c + $ ...edit .gitignore, README, Makefile, new_test_name.c... + $ ...edit TEST0 to create first test case & get it working... + $ ...add more TEST* scripts as appropriate... + +When a "check" type test is run (the default), each test should try to limit +the real execution time to a couple minutes or less. "short" and "long" +versions of the tests are encourages, especially for stress testing. diff --git a/src/test/RUNTESTS b/src/test/RUNTESTS new file mode 100755 index 0000000000000000000000000000000000000000..93cd170f9a85da2b624beabf941ce854361a7a6f --- /dev/null +++ b/src/test/RUNTESTS @@ -0,0 +1,231 @@ +#!/bin/sh +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# RUNTESTS -- setup the environment and run each test +# + +# make sure we have a well defined locale for string operations here +export LC_ALL="C" + +# +# usage -- print usage message and exit +# +usage() +{ + [ "$1" ] && echo Error: $1 + cat <<EOF +Usage: $0 [ -nv ] [ -b build-type ] [ -t test-type ] [ -f fs-type ] [tests...] + build-types: debug, nondebug, static-debug, static-nondebug, all (default) + test-types: check (default), short, long + fs-types: local, pmem, non-pmem, all (default) +EOF + exit 1 +} + +# +# runtest -- given the test directory name, run tests found inside it +# +runtest() { + export UNITTEST_QUIET=1 + [ -x "$1/TEST0" ] || { + echo FAIL: $1: test not found. + exit 1 + } + + cd $1 + + # + # make list of fs-types and build-types to test + # + fss=$fstype + [ "$fss" = all ] && fss="local pmem non-pmem" + builds=$buildtype + [ "$builds" = all ] && builds="debug nondebug static-debug static-nondebug" + + # for each fs-type being tested... + for fs in $fss + do + # don't bother trying when fs-type isn't available... + [ "$fs" = local -a -z "$LOCAL_FS_DIR" ] && { + local_skip=1 + continue + } + [ "$fs" = pmem -a -z "$PMEM_FS_DIR" ] && { + pmem_skip=1 + continue + } + [ "$fs" = non-pmem -a -z "$NON_PMEM_FS_DIR" ] && { + non_pmem_skip=1 + continue + } + + [ "$verbose"] && echo RUNTESTS: Testing fs-type: $fs... + # for each build-type being tested... + for build in $builds + do + [ "$verbose"] && echo RUNTESTS: Testing build-type: $build... + # for each TEST script found... + for runscript in `ls -1 TEST* | sort -V` + do + if [ "$dryrun" ] + then + echo "(in ./$1) TEST=$testtype FS=$fs BUILD=$build ./$runscript" + else + [ "$verbose"] && echo "RUNTESTS: Running: (in ./$1) TEST=$testtype FS=$fs BUILD=$build ./$runscript" + TEST=$testtype FS=$fs BUILD=$build ./$runscript + fi + + [ $? != 0 ] && { + echo RUNTESTS: stopping: + echo " $1/$runscript failed" + echo " TEST=$testtype FS=$fs BUILD=$build" + exit 1 + } + done + done + done + + cd .. +} + +[ -f testconfig.sh ] || { + cat <<EOF +RUNTESTS: stopping because no testconfig.sh is found. + to create one: + cp testconfig.sh.example testconfig.sh + and edit testconfig.sh to describe the local machine configuration. +EOF + exit 1 +} + +. ./testconfig.sh + +# +# defaults... +# +buildtype=all +testtype=check +fstype=all + +# +# command-line argument processing... +# +args=`getopt nvb:t:f: $*` +[ $? != 0 ] && usage +set -- $args +for arg +do + case "$arg" + in + + -n) + dryrun=1 + shift + ;; + -v) + verbose=1 + shift + ;; + -b) + buildtype="$2" + shift 2 + case "$buildtype" + in + debug|nondebug|static-debug|static-nondebug|all) + ;; + *) + usage "bad build-type: $buildtype" + ;; + esac + ;; + -t) + testtype="$2" + shift 2 + case "$testtype" + in + check|short|long) + ;; + *) + usage "bad test-type: $testtype" + ;; + esac + ;; + -f) + fstype="$2" + shift 2 + case "$fstype" + in + local|pmem|non-pmem|all) + ;; + *) + usage "bad fs-type: $fstype" + ;; + esac + ;; + --) + shift + break + ;; + esac +done +[ "$verbose" ] && { + echo -n Options: + [ "$dryrun" ] && echo -n ' -n' + [ "$verbose" ] && echo -n ' -v' + echo + echo " build-type: $buildtype" + echo " test-type: $testtype" + echo " fs-type: $fstype" + echo Tests: $* +} + +echo RUNTESTS: test-type: $testtype + +if [ "$1" ]; then + for test in $* + do + runtest $test + done +else + # no arguments means run them all + for testdir in */TEST0 + do + runtest `dirname $testdir` + done +fi +[ "$local_skip" ] && echo "SKIPPED fs-type \"local\" runs: testconfig.sh doesn't set LOCAL_FS_DIR" +[ "$pmem_skip" ] && echo "SKIPPED fs-type \"pmem\" runs: testconfig.sh doesn't set PMEM_FS_DIR" +[ "$non_pmem_skip" ] && echo "SKIPPED fs-type \"non-pmem\" runs: testconfig.sh doesn't set NON_PMEM_FS_DIR" +[ "$dryrun" ] || echo RUNTESTS: No failures. +exit 0 diff --git a/src/test/blk_nblock/.gitignore b/src/test/blk_nblock/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..c87f12a90443a27dbc001bdb32e8236cb4d5730e --- /dev/null +++ b/src/test/blk_nblock/.gitignore @@ -0,0 +1 @@ +blk_nblock diff --git a/src/test/blk_nblock/Makefile b/src/test/blk_nblock/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..a029aaba0546afcaec2a07fc20303d1915fd56d4 --- /dev/null +++ b/src/test/blk_nblock/Makefile @@ -0,0 +1,45 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/blk_nblock/Makefile -- build blk_nblock unit test +# +TARGET = blk_nblock +OBJS = blk_nblock.o + +include ../Makefile.inc + +LIBS += -lpmem -lpthread -ldl +STATIC_DEBUG_LIBS += -ldl +STATIC_NONDEBUG_LIBS += -ldl + +blk_nblock.o: blk_nblock.c diff --git a/src/test/blk_nblock/README b/src/test/blk_nblock/README new file mode 100644 index 0000000000000000000000000000000000000000..3ae26b1644abbc867230119f369dc850623069af --- /dev/null +++ b/src/test/blk_nblock/README @@ -0,0 +1,13 @@ +Linux NVM Library + +This is src/test/blk_nblock/README. + +This directory contains a unit test for pmemblk_nblock(). + +The program in blk_nblock.c takes a list of block size file pairs. +For example: + + ./blk_nblock 4096:file1 + +this will call pmemblk_map() on file1 and then report what pmemblk_nblock() +reports back as the usable size. diff --git a/src/test/blk_nblock/TEST0 b/src/test/blk_nblock/TEST0 new file mode 100755 index 0000000000000000000000000000000000000000..4b32f70f51a5fc55c9df6fffa8624364e5b14593 --- /dev/null +++ b/src/test/blk_nblock/TEST0 @@ -0,0 +1,129 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/blk_nblock/TEST0 -- unit test for pmemblk_nblock +# +export UNITTEST_NAME=blk_nblock/TEST0 +export UNITTEST_NUM=0 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local + +setup + +# +# Create a gajillion files, each file size created +# has six versions for the six block sizes being tested. +# Except for testfile1, since that should fail because +# it is too small. +# +# These are holey files, so they actually don't take up +# any significant space. +# +rm -f $DIR/testfile1 +truncate -s 2M $DIR/testfile1 +truncate -s 2G $DIR/testfile2.512 +truncate -s 2G $DIR/testfile2.520 +truncate -s 2G $DIR/testfile2.528 +truncate -s 2G $DIR/testfile2.4096 +truncate -s 2G $DIR/testfile2.4160 +truncate -s 2G $DIR/testfile2.4224 +truncate -s 512G $DIR/testfile3.512 +truncate -s 512G $DIR/testfile3.520 +truncate -s 512G $DIR/testfile3.528 +truncate -s 512G $DIR/testfile3.4096 +truncate -s 512G $DIR/testfile3.4160 +truncate -s 512G $DIR/testfile3.4224 +truncate -s 549755822080 $DIR/testfile4.512 +truncate -s 549755822080 $DIR/testfile4.520 +truncate -s 549755822080 $DIR/testfile4.528 +truncate -s 549755822080 $DIR/testfile4.4096 +truncate -s 549755822080 $DIR/testfile4.4160 +truncate -s 549755822080 $DIR/testfile4.4224 +truncate -s 513G $DIR/testfile5.512 +truncate -s 513G $DIR/testfile5.520 +truncate -s 513G $DIR/testfile5.528 +truncate -s 513G $DIR/testfile5.4096 +truncate -s 513G $DIR/testfile5.4160 +truncate -s 513G $DIR/testfile5.4224 +truncate -s 514G $DIR/testfile6.512 +truncate -s 514G $DIR/testfile6.520 +truncate -s 514G $DIR/testfile6.528 +truncate -s 514G $DIR/testfile6.4096 +truncate -s 514G $DIR/testfile6.4160 +truncate -s 514G $DIR/testfile6.4224 + +# should fail: +# 512:$DIR/testfile1 (file is too small) +# 4096:$DIR/testfile2.512 (bsize doesn't match pool) +expect_normal_exit ./blk_nblock$EXESUFFIX\ + 512:$DIR/testfile1\ + 512:$DIR/testfile2.512\ + 4096:$DIR/testfile2.512\ + 520:$DIR/testfile2.520\ + 528:$DIR/testfile2.528\ + 4096:$DIR/testfile2.4096\ + 4160:$DIR/testfile2.4160\ + 4224:$DIR/testfile2.4224\ + 512:$DIR/testfile3.512\ + 520:$DIR/testfile3.520\ + 528:$DIR/testfile3.528\ + 4096:$DIR/testfile3.4096\ + 4160:$DIR/testfile3.4160\ + 4224:$DIR/testfile3.4224\ + 512:$DIR/testfile4.512\ + 520:$DIR/testfile4.520\ + 528:$DIR/testfile4.528\ + 4096:$DIR/testfile4.4096\ + 4160:$DIR/testfile4.4160\ + 4224:$DIR/testfile4.4224\ + 512:$DIR/testfile5.512\ + 520:$DIR/testfile5.520\ + 528:$DIR/testfile5.528\ + 4096:$DIR/testfile5.4096\ + 4160:$DIR/testfile5.4160\ + 4224:$DIR/testfile5.4224\ + 512:$DIR/testfile6.512\ + 520:$DIR/testfile6.520\ + 528:$DIR/testfile6.528\ + 4096:$DIR/testfile6.4096\ + 4160:$DIR/testfile6.4160\ + 4224:$DIR/testfile6.4224 +rm $DIR/testfile1 $DIR/testfile[23456].* + +check + +pass diff --git a/src/test/blk_nblock/blk_nblock.c b/src/test/blk_nblock/blk_nblock.c new file mode 100644 index 0000000000000000000000000000000000000000..38b319519745f4e9a960081fb1996d4a8d121db1 --- /dev/null +++ b/src/test/blk_nblock/blk_nblock.c @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * blk_nblock.c -- unit test for pmemblk_nblock() + * + * usage: blk_nblock bsize:file... + * + */ +#define _GNU_SOURCE +#include "unittest.h" +#include <dlfcn.h> + +#define MMAP_MAX_SIZE (1024L * 1024L * 1024L) + +static void *mapped_addr; +static size_t mapped_size; +static uint64_t min_addr; +static uint64_t max_addr; + +/* + * mmap -- interpose on libc mmap() + * + * This catches mmap and reduces mapped size up to 1GB. + * Code under test doesn’t actually write outside first 1GB of mapped region. + * This limit is necessary to work on machines without overcommit. + */ +void * +mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off) +{ + static void *(*mmap_ptr)(void *addr, size_t len, int prot, int flags, + int fildes, off_t off); + if (mmap_ptr == NULL) + mmap_ptr = dlsym(RTLD_NEXT, "mmap"); + + if (len > MMAP_MAX_SIZE) + len = MMAP_MAX_SIZE; + + ASSERTeq(mapped_addr, NULL); + mapped_addr = mmap_ptr(addr, len, prot, flags, fildes, off); + mapped_size = len; + min_addr = (uint64_t)(mapped_addr); + max_addr = (uint64_t)(mapped_addr + len); + return mapped_addr; +} + +/* + * munmap -- interpose on libc munmap() + * + * This catches munmap and changes length to size used inside interpose mmap. + */ +int +munmap(void *addr, size_t len) +{ + static int(*munmap_ptr)(void *addr, size_t len); + if (munmap_ptr == NULL) + munmap_ptr = dlsym(RTLD_NEXT, "munmap"); + + if (addr == mapped_addr) { + len = mapped_size; + mapped_addr = NULL; + } + + return munmap_ptr(addr, len); +} + +/* + * mprotect -- interpose on libc mprotect() + * + * This catches mprotect and adjusts length to max_addr + * set inside interposed mmap. + */ +int +mprotect(void *addr, size_t len, int prot) +{ + static int (*mprotect_ptr)(void *addr, size_t len, int prot); + uint64_t addr_int = (uint64_t)addr; + + if (mprotect_ptr == NULL) + mprotect_ptr = dlsym(RTLD_NEXT, "mprotect"); + + if (addr_int >= min_addr && addr_int <= max_addr && + addr_int + len > max_addr) { + + /* unit tests are not supposed to write beyond the 1GB range */ + ASSERTeq(prot & PROT_WRITE, 0); + + len = max_addr - addr_int; + } + + return mprotect_ptr(addr, len, prot); +} + +int +main(int argc, char *argv[]) +{ + START(argc, argv, "blk_nblock"); + + if (argc < 2) + FATAL("usage: %s bsize:file...", argv[0]); + + /* map each file argument with the given map type */ + for (int arg = 1; arg < argc; arg++) { + char *fname; + size_t bsize = strtoul(argv[arg], &fname, 0); + if (bsize == 0 || *fname != ':') + FATAL("usage: %s bsize:file...", argv[0]); + fname++; + + int fd = OPEN(fname, O_RDWR); + + PMEMblk *handle; + if ((handle = pmemblk_map(fd, bsize)) == NULL) + OUT("!%s: pmemblk_map", fname); + else { + OUT("%s: block size %zu usable blocks: %zu", + fname, bsize, pmemblk_nblock(handle)); + pmemblk_unmap(handle); + int result = pmemblk_check(fname); + if (result < 0) + OUT("!%s: pmemblk_check", fname); + else if (result == 0) + OUT("%s: pmemblk_check: not consistent", fname); + } + + close(fd); + } + + DONE(NULL); +} diff --git a/src/test/blk_nblock/err0.log.match b/src/test/blk_nblock/err0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/blk_nblock/out0.log.match b/src/test/blk_nblock/out0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..f9bf1030dafb423d3c7690b7cc194083d82df18a --- /dev/null +++ b/src/test/blk_nblock/out0.log.match @@ -0,0 +1,35 @@ +blk_nblock/TEST0: START: blk_nblock + ./blk_nblock$(*) 512:$(*)/testfile1 512:$(*)/testfile2.512 4096:$(*)/testfile2.512 520:$(*)/testfile2.520 528:$(*)/testfile2.528 4096:$(*)/testfile2.4096 4160:$(*)/testfile2.4160 4224:$(*)/testfile2.4224 512:$(*)/testfile3.512 520:$(*)/testfile3.520 528:$(*)/testfile3.528 4096:$(*)/testfile3.4096 4160:$(*)/testfile3.4160 4224:$(*)/testfile3.4224 512:$(*)/testfile4.512 520:$(*)/testfile4.520 528:$(*)/testfile4.528 4096:$(*)/testfile4.4096 4160:$(*)/testfile4.4160 4224:$(*)/testfile4.4224 512:$(*)/testfile5.512 520:$(*)/testfile5.520 528:$(*)/testfile5.528 4096:$(*)/testfile5.4096 4160:$(*)/testfile5.4160 4224:$(*)/testfile5.4224 512:$(*)/testfile6.512 520:$(*)/testfile6.520 528:$(*)/testfile6.528 4096:$(*)/testfile6.4096 4160:$(*)/testfile6.4160 4224:$(*)/testfile6.4224 +$(*)/testfile1: pmemblk_map: Invalid argument +$(*)/testfile2.512: block size 512 usable blocks: 4161478 +$(*)/testfile2.512: pmemblk_map: Invalid argument +$(*)/testfile2.520: block size 520 usable blocks: 2781421 +$(*)/testfile2.528: block size 528 usable blocks: 2781421 +$(*)/testfile2.4096: block size 4096 usable blocks: 523513 +$(*)/testfile2.4160: block size 4160 usable blocks: 492731 +$(*)/testfile2.4224: block size 4224 usable blocks: 492731 +$(*)/testfile3.512: block size 512 usable blocks: 1065417932 +$(*)/testfile3.520: block size 520 usable blocks: 712118636 +$(*)/testfile3.528: block size 528 usable blocks: 712118636 +$(*)/testfile3.4096: block size 4096 usable blocks: 134086520 +$(*)/testfile3.4160: block size 4160 usable blocks: 126206306 +$(*)/testfile3.4224: block size 4224 usable blocks: 126206306 +$(*)/testfile4.512: block size 512 usable blocks: 1065417948 +$(*)/testfile4.520: block size 520 usable blocks: 712118647 +$(*)/testfile4.528: block size 528 usable blocks: 712118647 +$(*)/testfile4.4096: block size 4096 usable blocks: 134086522 +$(*)/testfile4.4160: block size 4160 usable blocks: 126206308 +$(*)/testfile4.4224: block size 4224 usable blocks: 126206308 +$(*)/testfile5.512: block size 512 usable blocks: 1067498531 +$(*)/testfile5.520: block size 520 usable blocks: 713509211 +$(*)/testfile5.528: block size 528 usable blocks: 713509211 +$(*)/testfile5.4096: block size 4096 usable blocks: 134348147 +$(*)/testfile5.4160: block size 4160 usable blocks: 126452542 +$(*)/testfile5.4224: block size 4224 usable blocks: 126452542 +$(*)/testfile6.512: block size 512 usable blocks: 1069579426 +$(*)/testfile6.520: block size 520 usable blocks: 714900068 +$(*)/testfile6.528: block size 528 usable blocks: 714900068 +$(*)/testfile6.4096: block size 4096 usable blocks: 134610035 +$(*)/testfile6.4160: block size 4160 usable blocks: 126699039 +$(*)/testfile6.4224: block size 4224 usable blocks: 126699039 +blk_nblock/TEST0: Done diff --git a/src/test/blk_recovery/.gitignore b/src/test/blk_recovery/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..4431b0205e3b5472aa2ea0b307697c785ef2041a --- /dev/null +++ b/src/test/blk_recovery/.gitignore @@ -0,0 +1 @@ +blk_recovery diff --git a/src/test/blk_recovery/Makefile b/src/test/blk_recovery/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..e061f366de9f4c909348992ea6a33428aa74894d --- /dev/null +++ b/src/test/blk_recovery/Makefile @@ -0,0 +1,45 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/blk_recovery/Makefile -- build blk_recovery unit test +# +vpath %.h ../.. +TARGET = blk_recovery +OBJS = blk_recovery.o + +include ../Makefile.inc +CFLAGS += -I../.. + +LIBS += -lpmem -lpthread + +blk_recovery.o: blk_recovery.c diff --git a/src/test/blk_recovery/README b/src/test/blk_recovery/README new file mode 100644 index 0000000000000000000000000000000000000000..2152eb65ae8849404874ce4b45bd5f1cc29fad33 --- /dev/null +++ b/src/test/blk_recovery/README @@ -0,0 +1,22 @@ +Linux NVM Library + +This is src/test/blk_recovery/README. + +This directory contains a unit test for pmemblk recovery + +The program in blk_recovery.c takes a block size, file and two LBAs. +A write to the first LBA is performed, then the arena map data structure +protections are modified to be read-only, then the remaining LBA is written. + +For example: + + ./blk_recovery 4096 file1 5 10 + +this will call pmemblk_map() on file1, call pmemblk_write() for LBA 5 +(causing all the layout to be written), then it will change the memory +protection on the arean map area to read-only. Next, pmemblk_write() +is called for for LBA 10 and SIGSEGV is caught and reported. Finally, +pmemblk_check() is called. + +This is not a perfect simulation of a system interruption, but does allow +creating a file where a write was interrupted before updating the map. diff --git a/src/test/blk_recovery/TEST0 b/src/test/blk_recovery/TEST0 new file mode 100755 index 0000000000000000000000000000000000000000..0a2c2e12691eddf3cfbea584bc5f212111b675c2 --- /dev/null +++ b/src/test/blk_recovery/TEST0 @@ -0,0 +1,61 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/blk_recovery/TEST0 -- unit test for pmemblk recovery +# +export UNITTEST_NAME=blk_recovery/TEST0 +export UNITTEST_NUM=0 + +# standard unit test setup +. ../unittest/unittest.sh + +# doesn't make sense to run in local directory +require_fs_type pmem non-pmem + +setup + +# single arena case +rm -f $DIR/testfile1 +truncate -s 2G $DIR/testfile1 + +# +# Simple case, one write interrupted. pmemblk_check() should note +# that testfile1 is consistent (after recovery steps were taken). +# +expect_normal_exit ./blk_recovery$EXESUFFIX 4096 $DIR/testfile1 5 10 +rm $DIR/testfile1 + +check + +pass diff --git a/src/test/blk_recovery/blk_recovery.c b/src/test/blk_recovery/blk_recovery.c new file mode 100644 index 0000000000000000000000000000000000000000..65091b78eed0f954d03a2e08af49ebc513658151 --- /dev/null +++ b/src/test/blk_recovery/blk_recovery.c @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * blk_recovery.c -- unit test for pmemblk recovery + * + * usage: blk_recovery bsize file first_lba lba + * + */ + +#include "unittest.h" + +#include <sys/param.h> + +#include "util.h" +#include "blk.h" +#include "btt_layout.h" + +size_t Bsize; + +/* + * construct -- build a buffer for writing + */ +void +construct(unsigned char *buf) +{ + static int ord = 1; + + for (int i = 0; i < Bsize; i++) + buf[i] = ord; + + ord++; + + if (ord > 255) + ord = 1; +} + +/* + * ident -- identify what a buffer holds + */ +char * +ident(unsigned char *buf) +{ + static char descr[100]; + unsigned val = *buf; + + for (int i = 1; i < Bsize; i++) + if (buf[i] != val) { + sprintf(descr, "{%u} TORN at byte %d", val, i); + return descr; + } + + sprintf(descr, "{%u}", val); + return descr; +} + +sigjmp_buf Jmp; + +/* + * signal_handler -- called on SIGSEGV + */ +void +signal_handler(int sig) +{ + OUT("signal: %s", strsignal(sig)); + + siglongjmp(Jmp, 1); +} + +int +main(int argc, char *argv[]) +{ + START(argc, argv, "blk_recovery"); + + if (argc != 5) + FATAL("usage: %s bsize file first_lba lba", argv[0]); + + Bsize = strtoul(argv[1], NULL, 0); + + int fd = OPEN(argv[2], O_RDWR); + + PMEMblk *handle; + if ((handle = pmemblk_map(fd, Bsize)) == NULL) + FATAL("!%s: pmemblk_map", argv[2]); + + close(fd); + + OUT("%s block size %zu usable blocks %zu", + argv[1], Bsize, pmemblk_nblock(handle)); + + /* write the first lba */ + off_t lba = strtoul(argv[3], NULL, 0); + unsigned char buf[Bsize]; + + construct(buf); + if (pmemblk_write(handle, buf, lba) < 0) + FATAL("!write lba %zu", lba); + + OUT("write lba %zu: %s", lba, ident(buf)); + + /* reach into the layout and write-protect the map */ + struct btt_info *infop = (void *)handle + + roundup(sizeof (struct pmemblk), BLK_FORMAT_DATA_ALIGN); + + void *mapaddr = (void *)infop + le32toh(infop->mapoff); + void *flogaddr = (void *)infop + le32toh(infop->flogoff); + + OUT("write-protecting map, length %zu", (size_t)(flogaddr - mapaddr)); + MPROTECT(mapaddr, (size_t)(flogaddr - mapaddr), PROT_READ); + + /* arrange to catch SEGV */ + struct sigvec v = { 0 }; + v.sv_handler = signal_handler; + SIGVEC(SIGSEGV, &v, NULL); + + /* map each file argument with the given map type */ + lba = strtoul(argv[4], NULL, 0); + + construct(buf); + + if (!sigsetjmp(Jmp, 1)) { + if (pmemblk_write(handle, buf, lba) < 0) + FATAL("!write lba %zu", lba); + else + FATAL("write lba %zu: %s", lba, ident(buf)); + } + + pmemblk_unmap(handle); + + int result = pmemblk_check(argv[2]); + if (result < 0) + OUT("!%s: pmemblk_check", argv[2]); + else if (result == 0) + OUT("%s: pmemblk_check: not consistent", argv[2]); + else + OUT("%s: consistent", argv[2]); + + DONE(NULL); +} diff --git a/src/test/blk_recovery/out0.log.match b/src/test/blk_recovery/out0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..3e907fd6f330d0ffdd6fa299cf228653513b8cf9 --- /dev/null +++ b/src/test/blk_recovery/out0.log.match @@ -0,0 +1,8 @@ +blk_recovery/TEST0: START: blk_recovery + ./blk_recovery$(*) 4096 $(*)/testfile1 5 10 +4096 block size 4096 usable blocks 523513 +write lba 5: {1} +write-protecting map, length 2097152 +signal: Segmentation fault +$(*)/testfile1: consistent +blk_recovery/TEST0: Done diff --git a/src/test/blk_rw/.gitignore b/src/test/blk_rw/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..25eb07ae885bf0b198ed665587a0b7d8fe084793 --- /dev/null +++ b/src/test/blk_rw/.gitignore @@ -0,0 +1 @@ +blk_rw diff --git a/src/test/blk_rw/Makefile b/src/test/blk_rw/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..c40f87fc2c3714c25c9927cd7a56a9937cc029f9 --- /dev/null +++ b/src/test/blk_rw/Makefile @@ -0,0 +1,45 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/blk_rw/Makefile -- build blk_rw unit test +# +TARGET = blk_rw +OBJS = blk_rw.o + +include ../Makefile.inc + +LIBS += -lpmem -lpthread -ldl +STATIC_DEBUG_LIBS += -ldl +STATIC_NONDEBUG_LIBS += -ldl + +blk_rw.o: blk_rw.c diff --git a/src/test/blk_rw/README b/src/test/blk_rw/README new file mode 100644 index 0000000000000000000000000000000000000000..373918f4a4a3f5656dee272b17e6deee0f91a7b4 --- /dev/null +++ b/src/test/blk_rw/README @@ -0,0 +1,19 @@ +Linux NVM Library + +This is src/test/blk_rw/README. + +This directory contains a unit test for pmemblk_read/write/set_zero/set_error. + +The program in blk_rw.c takes a block size, file and a list of +operation:LBA pairs. For example: + + ./blk_rw 4096 file1 r:0 w:5 z:9 e:100 + +this will call pmemblk_map() on file1 and then pmemblk_read() for LBA 0, +pmemblk_write() for LBA 5, pmemblk_set_zero() for LBA 9, and pmem_set_error() +for LAB 100. + +Each block written is filled up with the ordinal number of the write +operation (a block full of 8-bit 1s, then a block filled with 8-bit 2s, +etc.). When a block is read, the number it was filled with is reported +(and the program verifies the entire block is filled with that number). diff --git a/src/test/blk_rw/TEST0 b/src/test/blk_rw/TEST0 new file mode 100755 index 0000000000000000000000000000000000000000..e8aefc5e90d134fdf5521f01cb63b3499091fc61 --- /dev/null +++ b/src/test/blk_rw/TEST0 @@ -0,0 +1,62 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/blk_rw/TEST0 -- unit test for pmemblk_read/write/set_zero/set_error +# +export UNITTEST_NAME=blk_rw/TEST0 +export UNITTEST_NUM=0 + +# standard unit test setup +. ../unittest/unittest.sh + +# doesn't make sense to run in local directory +require_fs_type pmem non-pmem + +setup + +# single arena case +rm -f $DIR/testfile1 +truncate -s 2G $DIR/testfile1 +# +# All reads to an unwritten block pool should return zeros. +# Block 4161478 is out of range and should return EINVAL. +# Attempts to zero uninitialized blocks are nops (should succeed). +# +expect_normal_exit ./blk_rw$EXESUFFIX 512 $DIR/testfile1\ + r:0 r:1 r:4161477 r:4161478 z:0 z:1 r:0 +rm $DIR/testfile1 + +check + +pass diff --git a/src/test/blk_rw/TEST1 b/src/test/blk_rw/TEST1 new file mode 100755 index 0000000000000000000000000000000000000000..2832edabd4cfd4878ea21e0e9d5cde371c6997c0 --- /dev/null +++ b/src/test/blk_rw/TEST1 @@ -0,0 +1,62 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/blk_rw/TEST1 -- unit test for pmemblk_read/write/set_zero/set_error +# +export UNITTEST_NAME=blk_rw/TEST1 +export UNITTEST_NUM=1 + +# standard unit test setup +. ../unittest/unittest.sh + +# doesn't make sense to run in local directory +require_fs_type pmem non-pmem + +setup + +# multi-arena case +rm -f $DIR/testfile1 +truncate -s 1026G $DIR/testfile1 +# +# All reads to an unwritten block pool should return zeros. +# Block 2134997374 is out of range and should return EINVAL. +# Attempts to zero uninitialized blocks are nops (should succeed). +# +expect_normal_exit ./blk_rw$EXESUFFIX 512 $DIR/testfile1\ + r:0 r:1 r:4161480 r:2134997373 r:2134997374 z:0 z:4161480 +rm $DIR/testfile1 + +check + +pass diff --git a/src/test/blk_rw/TEST2 b/src/test/blk_rw/TEST2 new file mode 100755 index 0000000000000000000000000000000000000000..fa494e960fcf5fe9e2621bcf1779328d31859f20 --- /dev/null +++ b/src/test/blk_rw/TEST2 @@ -0,0 +1,62 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/blk_rw/TEST2 -- unit test for pmemblk_read/write/set_zero/set_error +# +export UNITTEST_NAME=blk_rw/TEST2 +export UNITTEST_NUM=2 + +# standard unit test setup +. ../unittest/unittest.sh + +# doesn't make sense to run in local directory +require_fs_type pmem non-pmem + +setup + +# multi-arena case +rm -f $DIR/testfile1 +truncate -s 1026G $DIR/testfile1 +# +# All reads to an unwritten block pool should return zeros. +# Block 268696557 is out of range and should return EINVAL. +# Attempts to zero uninitialized blocks are nops (should succeed). +# +expect_normal_exit ./blk_rw$EXESUFFIX 4096 $DIR/testfile1\ + r:0 r:1 r:4161480 r:268696556 r:268696557 z:0 z:4161480 +rm $DIR/testfile1 + +check + +pass diff --git a/src/test/blk_rw/TEST3 b/src/test/blk_rw/TEST3 new file mode 100755 index 0000000000000000000000000000000000000000..e72333332a21ecede03ce47265b07ce950e253f4 --- /dev/null +++ b/src/test/blk_rw/TEST3 @@ -0,0 +1,56 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/blk_rw/TEST3 -- unit test for pmemblk_read/write/set_zero/set_error +# +export UNITTEST_NAME=blk_rw/TEST3 +export UNITTEST_NUM=3 + +# standard unit test setup +. ../unittest/unittest.sh + +# doesn't make sense to run in local directory +require_fs_type pmem non-pmem + +setup + +# single arena write case +rm -f $DIR/testfile1 +truncate -s 1G $DIR/testfile1 +expect_normal_exit ./blk_rw$EXESUFFIX 512 $DIR/testfile1 w:0 r:1 r:0 w:1 r:0 r:1 r:2 +rm $DIR/testfile1 + +check + +pass diff --git a/src/test/blk_rw/TEST4 b/src/test/blk_rw/TEST4 new file mode 100755 index 0000000000000000000000000000000000000000..d11de6bb4a426b83753272bfcc8c1989e64be58b --- /dev/null +++ b/src/test/blk_rw/TEST4 @@ -0,0 +1,59 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/blk_rw/TEST4 -- unit test for pmemblk_read/write/set_zero/set_error +# +export UNITTEST_NAME=blk_rw/TEST4 +export UNITTEST_NUM=4 + +# standard unit test setup +. ../unittest/unittest.sh + +# doesn't make sense to run in local directory +require_fs_type pmem non-pmem + +setup + +# write re-use test case +rm -f $DIR/testfile1 +truncate -s 1G $DIR/testfile1 +expect_normal_exit ./blk_rw$EXESUFFIX 512 $DIR/testfile1\ + w:0 w:1 w:2 w:3 w:4 r:4 r:3 r:2 r:1 r:0 +expect_normal_exit ./blk_rw$EXESUFFIX 512 $DIR/testfile1\ + w:0 r:4 r:3 r:2 r:1 r:0 w:0 r:0 +rm $DIR/testfile1 + +check + +pass diff --git a/src/test/blk_rw/TEST5 b/src/test/blk_rw/TEST5 new file mode 100755 index 0000000000000000000000000000000000000000..efbfac3421ae59dd29b8d47a1a48b2bb2b3b0ff8 --- /dev/null +++ b/src/test/blk_rw/TEST5 @@ -0,0 +1,62 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/blk_rw/TEST5 -- unit test for pmemblk_read/write/set_zero/set_error +# +export UNITTEST_NAME=blk_rw/TEST5 +export UNITTEST_NUM=5 + +# standard unit test setup +. ../unittest/unittest.sh + +# doesn't make sense to run in local directory +require_fs_type pmem non-pmem + +setup + +# mix writes with set_zero and set_error and check results +rm -f $DIR/testfile1 +truncate -s 1G $DIR/testfile1 +expect_normal_exit ./blk_rw$EXESUFFIX 512 $DIR/testfile1\ + w:100 w:200 w:300 w:400\ + r:100 r:200 r:300 r:400\ + w:100 z:200 w:300 z:400\ + r:100 r:200 r:300 r:400\ + e:100 w:200 e:300 w:400\ + r:100 r:200 r:300 r:400 +rm $DIR/testfile1 + +check + +pass diff --git a/src/test/blk_rw/blk_rw.c b/src/test/blk_rw/blk_rw.c new file mode 100644 index 0000000000000000000000000000000000000000..fde46db7cfaab8f2a0bd32db9a46562d275fd9ea --- /dev/null +++ b/src/test/blk_rw/blk_rw.c @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * blk_rw.c -- unit test for pmemblk_read/write/set_zero/set_error + * + * usage: blk_rw bsize file operation:lba... + * + * operations are 'r' or 'w' or 'z' or 'e' + * + */ +#define _GNU_SOURCE +#include "unittest.h" +#include <dlfcn.h> + +#define MMAP_MAX_SIZE (1024L * 1024L * 1024L) + +size_t Bsize; +static void *mapped_addr; +static size_t mapped_size; +static uint64_t min_addr; +static uint64_t max_addr; + +/* + * mmap -- interpose on libc mmap() + * + * This catches mmap and reduces mapped size up to 1GB. + * Code under test doesn’t actually write outside first 1GB of mapped region. + * This limit is necessary to work on machines without overcommit. + */ +void * +mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off) +{ + static void *(*mmap_ptr)(void *addr, size_t len, int prot, int flags, + int fildes, off_t off); + if (mmap_ptr == NULL) + mmap_ptr = dlsym(RTLD_NEXT, "mmap"); + + if (len > MMAP_MAX_SIZE) + len = MMAP_MAX_SIZE; + + ASSERTeq(mapped_addr, NULL); + mapped_addr = mmap_ptr(addr, len, prot, flags, fildes, off); + mapped_size = len; + min_addr = (uint64_t)(mapped_addr); + max_addr = (uint64_t)(mapped_addr + len); + return mapped_addr; +} + +/* + * munmap -- interpose on libc munmap() + * + * This catches munmap and changes length to size used inside interpose mmap. + */ +int +munmap(void *addr, size_t len) +{ + static int(*munmap_ptr)(void *addr, size_t len); + if (munmap_ptr == NULL) + munmap_ptr = dlsym(RTLD_NEXT, "munmap"); + + if (addr == mapped_addr) { + len = mapped_size; + mapped_addr = NULL; + } + + return munmap_ptr(addr, len); +} + +/* + * mprotect -- interpose on libc mprotect() + * + * This catches mprotect and adjusts length to max_addr + * set inside interposed mmap. + */ +int +mprotect(void *addr, size_t len, int prot) +{ + static int (*mprotect_ptr)(void *addr, size_t len, int prot); + uint64_t addr_int = (uint64_t)addr; + + if (mprotect_ptr == NULL) + mprotect_ptr = dlsym(RTLD_NEXT, "mprotect"); + + if (addr_int >= min_addr && addr_int <= max_addr && + addr_int + len > max_addr) { + + /* unit tests are not supposed to write beyond the 1GB range */ + ASSERTeq(prot & PROT_WRITE, 0); + + len = max_addr - addr_int; + } + + return mprotect_ptr(addr, len, prot); +} + +/* + * construct -- build a buffer for writing + */ +void +construct(unsigned char *buf) +{ + static int ord = 1; + + for (int i = 0; i < Bsize; i++) + buf[i] = ord; + + ord++; + + if (ord > 255) + ord = 1; +} + +/* + * ident -- identify what a buffer holds + */ +char * +ident(unsigned char *buf) +{ + static char descr[100]; + unsigned val = *buf; + + for (int i = 1; i < Bsize; i++) + if (buf[i] != val) { + sprintf(descr, "{%u} TORN at byte %d", val, i); + return descr; + } + + sprintf(descr, "{%u}", val); + return descr; +} + +int +main(int argc, char *argv[]) +{ + START(argc, argv, "blk_rw"); + + if (argc < 4) + FATAL("usage: %s bsize file op:lba...", argv[0]); + + Bsize = strtoul(argv[1], NULL, 0); + + int fd = OPEN(argv[2], O_RDWR); + + PMEMblk *handle; + if ((handle = pmemblk_map(fd, Bsize)) == NULL) + FATAL("!%s: pmemblk_map", argv[2]); + + close(fd); + + OUT("%s block size %zu usable blocks %zu", + argv[1], Bsize, pmemblk_nblock(handle)); + + /* map each file argument with the given map type */ + for (int arg = 3; arg < argc; arg++) { + if (strchr("rwze", argv[arg][0]) == NULL || argv[arg][1] != ':') + FATAL("op must be r: or w: or z: or e:"); + off_t lba = strtoul(&argv[arg][2], NULL, 0); + + unsigned char buf[Bsize]; + + switch (argv[arg][0]) { + case 'r': + if (pmemblk_read(handle, buf, lba) < 0) + OUT("!read lba %zu", lba); + else + OUT("read lba %zu: %s", lba, ident(buf)); + break; + + case 'w': + construct(buf); + if (pmemblk_write(handle, buf, lba) < 0) + OUT("!write lba %zu", lba); + else + OUT("write lba %zu: %s", lba, ident(buf)); + break; + + case 'z': + if (pmemblk_set_zero(handle, lba) < 0) + OUT("!set_zero lba %zu", lba); + else + OUT("set_zero lba %zu", lba); + break; + + case 'e': + if (pmemblk_set_error(handle, lba) < 0) + OUT("!set_error lba %zu", lba); + else + OUT("set_error lba %zu", lba); + break; + } + } + + pmemblk_unmap(handle); + + int result = pmemblk_check(argv[2]); + if (result < 0) + OUT("!%s: pmemblk_check", argv[2]); + else if (result == 0) + OUT("%s: pmemblk_check: not consistent", argv[2]); + + DONE(NULL); +} diff --git a/src/test/blk_rw/err0.log.match b/src/test/blk_rw/err0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/blk_rw/err1.log.match b/src/test/blk_rw/err1.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/blk_rw/err2.log.match b/src/test/blk_rw/err2.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/blk_rw/err3.log.match b/src/test/blk_rw/err3.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/blk_rw/err4.log.match b/src/test/blk_rw/err4.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/blk_rw/err5.log.match b/src/test/blk_rw/err5.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/blk_rw/out0.log.match b/src/test/blk_rw/out0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..f2bf377e9ff846a88c55f1af95dad99d0daa5d7a --- /dev/null +++ b/src/test/blk_rw/out0.log.match @@ -0,0 +1,11 @@ +blk_rw/TEST0: START: blk_rw + ./blk_rw$(*) 512 $(*)/testfile1 r:0 r:1 r:4161477 r:4161478 z:0 z:1 r:0 +512 block size 512 usable blocks 4161478 +read lba 0: {0} +read lba 1: {0} +read lba 4161477: {0} +read lba 4161478: Invalid argument +set_zero lba 0 +set_zero lba 1 +read lba 0: {0} +blk_rw/TEST0: Done diff --git a/src/test/blk_rw/out2.log.match b/src/test/blk_rw/out2.log.match new file mode 100644 index 0000000000000000000000000000000000000000..61ae6272be97713e901497aa3c19f10e9bb87cb9 --- /dev/null +++ b/src/test/blk_rw/out2.log.match @@ -0,0 +1,11 @@ +blk_rw/TEST2: START: blk_rw + ./blk_rw$(*) 4096 $(*)/testfile1 r:0 r:1 r:4161480 r:268696556 r:268696557 z:0 z:4161480 +4096 block size 4096 usable blocks 268696557 +read lba 0: {0} +read lba 1: {0} +read lba 4161480: {0} +read lba 268696556: {0} +read lba 268696557: Invalid argument +set_zero lba 0 +set_zero lba 4161480 +blk_rw/TEST2: Done diff --git a/src/test/blk_rw/out3.log.match b/src/test/blk_rw/out3.log.match new file mode 100644 index 0000000000000000000000000000000000000000..b5093801cecb32d0b1df6d897fb0fd9c982d2a10 --- /dev/null +++ b/src/test/blk_rw/out3.log.match @@ -0,0 +1,11 @@ +blk_rw/TEST3: START: blk_rw + ./blk_rw$(*) 512 $(*)/testfile1 w:0 r:1 r:0 w:1 r:0 r:1 r:2 +512 block size 512 usable blocks 2080583 +write lba 0: {1} +read lba 1: {0} +read lba 0: {1} +write lba 1: {2} +read lba 0: {1} +read lba 1: {2} +read lba 2: {0} +blk_rw/TEST3: Done diff --git a/src/test/blk_rw/out4.log.match b/src/test/blk_rw/out4.log.match new file mode 100644 index 0000000000000000000000000000000000000000..5d56181b0c915e36a97d47e8b897015c6074def6 --- /dev/null +++ b/src/test/blk_rw/out4.log.match @@ -0,0 +1,12 @@ +blk_rw/TEST4: START: blk_rw + ./blk_rw$(*) 512 $(*)/testfile1 w:0 r:4 r:3 r:2 r:1 r:0 w:0 r:0 +512 block size 512 usable blocks 2080583 +write lba 0: {1} +read lba 4: {5} +read lba 3: {4} +read lba 2: {3} +read lba 1: {2} +read lba 0: {1} +write lba 0: {2} +read lba 0: {2} +blk_rw/TEST4: Done diff --git a/src/test/blk_rw/out5.log.match b/src/test/blk_rw/out5.log.match new file mode 100644 index 0000000000000000000000000000000000000000..b8dfaa7da86532f6568474a1c89165c088306931 --- /dev/null +++ b/src/test/blk_rw/out5.log.match @@ -0,0 +1,28 @@ +blk_rw/TEST5: START: blk_rw + ./blk_rw$(*) 512 $(*)/testfile1 w:100 w:200 w:300 w:400 r:100 r:200 r:300 r:400 w:100 z:200 w:300 z:400 r:100 r:200 r:300 r:400 e:100 w:200 e:300 w:400 r:100 r:200 r:300 r:400 +512 block size 512 usable blocks 2080583 +write lba 100: {1} +write lba 200: {2} +write lba 300: {3} +write lba 400: {4} +read lba 100: {1} +read lba 200: {2} +read lba 300: {3} +read lba 400: {4} +write lba 100: {5} +set_zero lba 200 +write lba 300: {6} +set_zero lba 400 +read lba 100: {5} +read lba 200: {0} +read lba 300: {6} +read lba 400: {0} +set_error lba 100 +write lba 200: {7} +set_error lba 300 +write lba 400: {8} +read lba 100: Input/output error +read lba 200: {7} +read lba 300: Input/output error +read lba 400: {8} +blk_rw/TEST5: Done diff --git a/src/test/blk_rw_mt/.gitignore b/src/test/blk_rw_mt/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..c9a111b2e56f70f19e1fe2267358249ac1c91b86 --- /dev/null +++ b/src/test/blk_rw_mt/.gitignore @@ -0,0 +1 @@ +blk_rw_mt diff --git a/src/test/blk_rw_mt/Makefile b/src/test/blk_rw_mt/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..b54e2756971385556be1180d54b99242ec697452 --- /dev/null +++ b/src/test/blk_rw_mt/Makefile @@ -0,0 +1,43 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/blk_rw_mt/Makefile -- build blk_rw_mt unit test +# +TARGET = blk_rw_mt +OBJS = blk_rw_mt.o + +include ../Makefile.inc + +LIBS += -lpmem -lpthread + +blk_rw_mt.o: blk_rw_mt.c diff --git a/src/test/blk_rw_mt/README b/src/test/blk_rw_mt/README new file mode 100644 index 0000000000000000000000000000000000000000..1808350658c482d9be63053cc56ad581cf22defa --- /dev/null +++ b/src/test/blk_rw_mt/README @@ -0,0 +1,14 @@ +Linux NVM Library + +This is src/test/blk_rw_mt/README. + +This directory contains a unit test for MT reads & writes. + +The program in blk_rw_mt.c takes a block size, a file, a random number +generator seed (to make the results repeatable), a thread count, and the +numer of I/Os to do per thread. For example: + + ./blk_rw_mt 4096 file1 123 300 500 + +this will create a pool in file1 with block size 4096, fork 300 threads, +and each thread will do 500 random I/Os (50/50 reads/writes). diff --git a/src/test/blk_rw_mt/TEST0 b/src/test/blk_rw_mt/TEST0 new file mode 100755 index 0000000000000000000000000000000000000000..3d9909e75dd72a9161974a96092d0a6acacfd0cc --- /dev/null +++ b/src/test/blk_rw_mt/TEST0 @@ -0,0 +1,56 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/blk_rw_mt/TEST0 -- unit test for MT I/O on blk pool +# +export UNITTEST_NAME=blk_rw_mt/TEST0 +export UNITTEST_NUM=0 + +# standard unit test setup +. ../unittest/unittest.sh + +# doesn't make sense to run in local directory +require_fs_type pmem non-pmem + +setup + +rm -f $DIR/testfile1 +truncate -s 1G $DIR/testfile1 +# 5 threads, each doing 80 random I/Os +expect_normal_exit ./blk_rw_mt$EXESUFFIX 4096 $DIR/testfile1 123 5 80 +rm $DIR/testfile1 + +check + +pass diff --git a/src/test/blk_rw_mt/TEST1 b/src/test/blk_rw_mt/TEST1 new file mode 100755 index 0000000000000000000000000000000000000000..b842897e00129350db09ca4f4dd549d94a25b8a7 --- /dev/null +++ b/src/test/blk_rw_mt/TEST1 @@ -0,0 +1,59 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/blk_rw_mt/TEST1 -- unit test for MT I/O on blk pool +# +export UNITTEST_NAME=blk_rw_mt/TEST1 +export UNITTEST_NUM=1 + +# standard unit test setup +. ../unittest/unittest.sh + +# this is the short version of the test +require_test_type short + +# doesn't make sense to run in local directory +require_fs_type pmem non-pmem + +setup + +rm -f $DIR/testfile1 +truncate -s 1G $DIR/testfile1 +# 100 threads, each doing 100 random I/Os +expect_normal_exit ./blk_rw_mt$EXESUFFIX 4096 $DIR/testfile1 456 100 100 +rm $DIR/testfile1 + +check + +pass diff --git a/src/test/blk_rw_mt/TEST2 b/src/test/blk_rw_mt/TEST2 new file mode 100755 index 0000000000000000000000000000000000000000..11b5dca8391bf9b9561461b4cca1d60453fde7c8 --- /dev/null +++ b/src/test/blk_rw_mt/TEST2 @@ -0,0 +1,59 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/blk_rw_mt/TEST2 -- unit test for MT I/O on blk pool +# +export UNITTEST_NAME=blk_rw_mt/TEST2 +export UNITTEST_NUM=2 + +# standard unit test setup +. ../unittest/unittest.sh + +# this is the long version of the test +require_test_type long + +# doesn't make sense to run in local directory +require_fs_type pmem non-pmem + +setup + +rm -f $DIR/testfile1 +truncate -s 1G $DIR/testfile1 +# 300 threads, each doing 100000 random I/Os +expect_normal_exit ./blk_rw_mt$EXESUFFIX 4096 $DIR/testfile1 789 300 100000 +rm $DIR/testfile1 + +check + +pass diff --git a/src/test/blk_rw_mt/blk_rw_mt.c b/src/test/blk_rw_mt/blk_rw_mt.c new file mode 100644 index 0000000000000000000000000000000000000000..184325f6d8062d9f5fac0b94da28cd1026c6efbe --- /dev/null +++ b/src/test/blk_rw_mt/blk_rw_mt.c @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * blk_rw_mt.c -- unit test for multi-threaded random I/O + * + * usage: blk_rw_mt bsize file seed nthread nops + * + */ + +#include "unittest.h" + +size_t Bsize; +size_t Nblock = 100; /* all I/O below this LBA (increases collisions) */ +unsigned Seed; +unsigned Nthread; +unsigned Nops; +PMEMblk *Handle; + +/* + * construct -- build a buffer for writing + */ +void +construct(int *ordp, unsigned char *buf) +{ + for (int i = 0; i < Bsize; i++) + buf[i] = *ordp; + + (*ordp)++; + + if (*ordp > 255) + *ordp = 1; +} + +/* + * check -- check for torn buffers + */ +void +check(unsigned char *buf) +{ + unsigned val = *buf; + + for (int i = 1; i < Bsize; i++) + if (buf[i] != val) { + OUT("{%u} TORN at byte %d", val, i); + break; + } +} + +/* + * worker -- the work each thread performs + */ +void * +worker(void *arg) +{ + long mytid = (long)arg; + unsigned myseed = Seed + mytid; + unsigned char buf[Bsize]; + int ord = 1; + + for (int i = 0; i < Nops; i++) { + off_t lba = rand_r(&myseed) % Nblock; + + if (rand_r(&myseed) % 2) { + /* read */ + if (pmemblk_read(Handle, buf, lba) < 0) + OUT("!read lba %zu", lba); + else + check(buf); + } else { + /* write */ + construct(&ord, buf); + if (pmemblk_write(Handle, buf, lba) < 0) + OUT("!write lba %zu", lba); + } + } + + return NULL; +} + +int +main(int argc, char *argv[]) +{ + START(argc, argv, "blk_rw_mt"); + + if (argc != 6) + FATAL("usage: %s bsize file seed nthread nops", argv[0]); + + Bsize = strtoul(argv[1], NULL, 0); + + int fd = OPEN(argv[2], O_RDWR); + + if ((Handle = pmemblk_map(fd, Bsize)) == NULL) + FATAL("!%s: pmemblk_map", argv[2]); + + close(fd); + + if (Nblock == 0) + Nblock = pmemblk_nblock(Handle); + Seed = strtoul(argv[3], NULL, 0); + Nthread = strtoul(argv[4], NULL, 0); + Nops = strtoul(argv[5], NULL, 0); + + OUT("%s block size %zu usable blocks %zu", argv[1], Bsize, Nblock); + + pthread_t threads[Nthread]; + + /* kick off nthread threads */ + for (int i = 0; i < Nthread; i++) + PTHREAD_CREATE(&threads[i], NULL, worker, (void *)(long)i); + + /* wait for all the threads to complete */ + for (int i = 0; i < Nthread; i++) + PTHREAD_JOIN(threads[i], NULL); + + pmemblk_unmap(Handle); + + /* XXX not ready to pass this part of the test yet */ + int result = pmemblk_check(argv[2]); + if (result < 0) + OUT("!%s: pmemblk_check", argv[2]); + else if (result == 0) + OUT("%s: pmemblk_check: not consistent", argv[2]); + + DONE(NULL); +} diff --git a/src/test/blk_rw_mt/err0.log.match b/src/test/blk_rw_mt/err0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/blk_rw_mt/err1.log.match b/src/test/blk_rw_mt/err1.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/blk_rw_mt/err2.log.match b/src/test/blk_rw_mt/err2.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/blk_rw_mt/out0.log.match b/src/test/blk_rw_mt/out0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..0c5231edab9d88a52e8d9471ac9bc6b056adfa08 --- /dev/null +++ b/src/test/blk_rw_mt/out0.log.match @@ -0,0 +1,4 @@ +blk_rw_mt/TEST0: START: blk_rw_mt + ./blk_rw_mt$(*) 4096 $(*)/testfile1 123 5 80 +4096 block size 4096 usable blocks 100 +blk_rw_mt/TEST0: Done diff --git a/src/test/blk_rw_mt/out1.log.match b/src/test/blk_rw_mt/out1.log.match new file mode 100644 index 0000000000000000000000000000000000000000..9e57646f44f783f55a11a3ccf50272b114b4cd1d --- /dev/null +++ b/src/test/blk_rw_mt/out1.log.match @@ -0,0 +1,4 @@ +blk_rw_mt/TEST1: START: blk_rw_mt + ./blk_rw_mt$(*) 4096 $(*)/testfile1 456 100 100 +4096 block size 4096 usable blocks 100 +blk_rw_mt/TEST1: Done diff --git a/src/test/blk_rw_mt/out2.log.match b/src/test/blk_rw_mt/out2.log.match new file mode 100644 index 0000000000000000000000000000000000000000..3db5383c55bf81eb4e5decc237de2eabaf8133a0 --- /dev/null +++ b/src/test/blk_rw_mt/out2.log.match @@ -0,0 +1,4 @@ +blk_rw_mt/TEST2: START: blk_rw_mt + ./blk_rw_mt$(*) 4096 $(*)/testfile1 789 300 100000 +4096 block size 4096 usable blocks 100 +blk_rw_mt/TEST2: Done diff --git a/src/test/checksum/.gitignore b/src/test/checksum/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..c5c2772a3214061ef7a4382b4c6b11ea961c9c53 --- /dev/null +++ b/src/test/checksum/.gitignore @@ -0,0 +1 @@ +checksum diff --git a/src/test/checksum/Makefile b/src/test/checksum/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..66fdfcf81b75f83dae39af6bc0d7d5990b02f662 --- /dev/null +++ b/src/test/checksum/Makefile @@ -0,0 +1,50 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/checksum/Makefile -- build checksum unit test +# +vpath %.c ../.. +vpath %.h ../.. ../../include +TARGET = checksum +OBJS = checksum.o util.o out.o + +out.o: CFLAGS += -DSRCVERSION=\"utversion\" + +include ../Makefile.inc +INCS += -I../.. -I../../include + +checksum.o: checksum.c util.h out.h + +util.o: util.c util.h out.h + +out.o: out.c out.h diff --git a/src/test/checksum/TEST0 b/src/test/checksum/TEST0 new file mode 100755 index 0000000000000000000000000000000000000000..02d6321ce7588d905bf9f2431e798de90f5944a7 --- /dev/null +++ b/src/test/checksum/TEST0 @@ -0,0 +1,51 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/checksum/TEST0 -- unit test for checksum +# +export UNITTEST_NAME=checksum/TEST0 +export UNITTEST_NUM=0 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local + +setup + +expect_normal_exit ./checksum$EXESUFFIX ./file? + +check + +pass diff --git a/src/test/checksum/checksum.c b/src/test/checksum/checksum.c new file mode 100644 index 0000000000000000000000000000000000000000..d6c9666580f7ed34f1060ad5a8f61e79068988f7 --- /dev/null +++ b/src/test/checksum/checksum.c @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * checksum.c -- unit test for library internal checksum routine + * + * usage: checksum files... + */ + +#include "unittest.h" + +#include "util.h" + +/* + * fletcher64 -- compute a Fletcher64 checksum + * + * Gold standard implementation used to compare to the + * util_checksum() being unit tested. + */ +uint64_t +fletcher64(void *addr, size_t len) +{ + uint32_t *p32 = addr; + uint32_t *p32end = addr + len; + uint32_t lo32 = 0; + uint32_t hi32 = 0; + + while (p32 < p32end) { + lo32 += *p32++; + hi32 += lo32; + } + + return (uint64_t)hi32 << 32 | lo32; +} + +int +main(int argc, char *argv[]) +{ + START(argc, argv, "checksum"); + + if (argc < 2) + FATAL("usage: %s files...", argv[0]); + + for (int arg = 1; arg < argc; arg++) { + int fd = OPEN(argv[arg], O_RDONLY); + + struct stat stbuf; + FSTAT(fd, &stbuf); + + void *addr = + MMAP(0, stbuf.st_size, PROT_READ|PROT_WRITE, + MAP_PRIVATE, fd, 0); + + close(fd); + + uint64_t *ptr = addr; + + /* + * Loop through, selecting successive locations + * where the checksum lives in this block, and + * let util_checksum() insert it so it can be + * verified against the gold standard fletcher64 + * routine in this file. + */ + while ((void *)(ptr + 1) < addr + stbuf.st_size) { + /* save whatever was at *ptr */ + uint64_t oldval = *ptr; + + /* mess with it */ + *ptr = 0x123; + + /* + * calc a checksum and have it installed + */ + util_checksum(addr, stbuf.st_size, ptr, 1); + + uint64_t csum = *ptr; + + /* + * verify inserted checksum checks out + */ + ASSERT(util_checksum(addr, stbuf.st_size, ptr, 0)); + + /* put a zero where the checksum was installed */ + *ptr = 0; + + /* calculate a checksum */ + uint64_t gold_csum = fletcher64(addr, stbuf.st_size); + + /* put the old value back */ + *ptr = oldval; + + /* + * verify checksum now fails + */ + ASSERT(!util_checksum(addr, stbuf.st_size, ptr, 0)); + + /* + * verify the checksum matched the gold version + */ + ASSERTeq(csum, gold_csum); + + OUT("%s:%lu 0x%lx", argv[arg], + (void *)ptr - addr, csum); + + ptr++; + } + } + + DONE(NULL); +} diff --git a/src/test/checksum/err0.log.match b/src/test/checksum/err0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/checksum/file1 b/src/test/checksum/file1 new file mode 100644 index 0000000000000000000000000000000000000000..afadc1197b01d8390dd62d62ca739d53b3f5bfd8 --- /dev/null +++ b/src/test/checksum/file1 @@ -0,0 +1,2 @@ +Hello. This is a simple text file with a known checksum. +The checksum unit test is run on this file to check for regressions. diff --git a/src/test/checksum/file2 b/src/test/checksum/file2 new file mode 100644 index 0000000000000000000000000000000000000000..b1098e404119cecd4c21e5cfdb0f2ee6c916ca2e --- /dev/null +++ b/src/test/checksum/file2 @@ -0,0 +1,2 @@ +Iello. This is a simple text file with a known checksum. +The checksum unit test is run on this file to check for regressions. diff --git a/src/test/checksum/file3 b/src/test/checksum/file3 new file mode 100644 index 0000000000000000000000000000000000000000..abf394bb384d017112227e0cd2c1944a5d0d72b3 --- /dev/null +++ b/src/test/checksum/file3 @@ -0,0 +1,2 @@ +Hello. This is a simple text file with a known checksum. +The checksum unit test is run on this file to check for regressions/ diff --git a/src/test/checksum/file4 b/src/test/checksum/file4 new file mode 100644 index 0000000000000000000000000000000000000000..9736630dc7cd5d2c1851d4d9a311d1f8d650985c Binary files /dev/null and b/src/test/checksum/file4 differ diff --git a/src/test/checksum/file5 b/src/test/checksum/file5 new file mode 100644 index 0000000000000000000000000000000000000000..959b118626907fa8644dd3281a88ccf1ff4b6f48 Binary files /dev/null and b/src/test/checksum/file5 differ diff --git a/src/test/checksum/out0.log.match b/src/test/checksum/out0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..51126218b9d1d4e1cf9fcfab407463e7f8a3a152 --- /dev/null +++ b/src/test/checksum/out0.log.match @@ -0,0 +1,1582 @@ +checksum/TEST0: START: checksum + ./checksum$(*) ./file1 ./file2 ./file3 ./file4 ./file5 +./file1:0 0xe8f920bff5e5614 +./file1:8 0x4c94b804f80e1857 +./file1:16 0x44fa7461bd0b58fd +./file1:24 0xfabae3e8aa1f5537 +./file1:32 0x6b95e2edf4620ff6 +./file1:40 0x59bd460bfd1151fb +./file1:48 0x9c5e21cfbb100dfd +./file1:56 0x3b83fc8bbb33bf38 +./file1:64 0x6c653a51a35f18f1 +./file1:72 0xcfc7ef94f7031ae9 +./file1:80 0x95d9e1164b090b39 +./file1:88 0xd2aed57ef75711f4 +./file1:96 0x7192626c060f0c45 +./file1:104 0xfea2c613b91f60fd +./file1:112 0x9009017fb31356f2 +./file2:0 0xe8f920bff5e5614 +./file2:8 0x4c94b824f80e1858 +./file2:16 0x44fa7481bd0b58fe +./file2:24 0xfabae408aa1f5538 +./file2:32 0x6b95e30df4620ff7 +./file2:40 0x59bd462bfd1151fc +./file2:48 0x9c5e21efbb100dfe +./file2:56 0x3b83fcabbb33bf39 +./file2:64 0x6c653a71a35f18f2 +./file2:72 0xcfc7efb4f7031aea +./file2:80 0x95d9e1364b090b3a +./file2:88 0xd2aed59ef75711f5 +./file2:96 0x7192628c060f0c46 +./file2:104 0xfea2c633b91f60fe +./file2:112 0x9009019fb31356f3 +./file3:0 0xe8f930bff5e5714 +./file3:8 0x4c94b904f80e1957 +./file3:16 0x44fa7561bd0b59fd +./file3:24 0xfabae4e8aa1f5637 +./file3:32 0x6b95e3edf46210f6 +./file3:40 0x59bd470bfd1152fb +./file3:48 0x9c5e22cfbb100efd +./file3:56 0x3b83fd8bbb33c038 +./file3:64 0x6c653b51a35f19f1 +./file3:72 0xcfc7f094f7031be9 +./file3:80 0x95d9e2164b090c39 +./file3:88 0xd2aed67ef75712f4 +./file3:96 0x7192636c060f0d45 +./file3:104 0xfea2c713b91f61fd +./file3:112 0x9009027fb31357f2 +./file4:0 0x2561ad3cf87a50ce +./file4:8 0x8edb19ce24a063e0 +./file4:16 0x7f1970877964c0af +./file4:24 0x54e98c05652d0546 +./file4:32 0x575e710add2ba5c +./file4:40 0x9650a602f50c7dfa +./file4:48 0xc172efa8a33676f4 +./file4:56 0xabc0022b1ea13cd2 +./file4:64 0x4848cfbb59b955cb +./file4:72 0xd931ee5fc956cb8e +./file4:80 0xa4d7779d5bb7eb42 +./file4:88 0xd0529e5aa11956a6 +./file4:96 0xf6f9d075125a6c5d +./file4:104 0x4c34f03ea0de829b +./file4:112 0x4779f4055c85f790 +./file4:120 0x61c0edaa55b1ab3e +./file4:128 0x560eeb74cc447437 +./file4:136 0xc3ebd96f43342752 +./file4:144 0x373008b2bd3c45fd +./file4:152 0xf150801f877746c4 +./file4:160 0x26baeadd2dfc143b +./file4:168 0x324bf9758f9d0f88 +./file4:176 0x9167168029b30a43 +./file4:184 0x38c559629a484230 +./file4:192 0x31d7c7fe1c49de57 +./file4:200 0xa8e9ed8b4e62440f +./file4:208 0xcfdc63aeb9e5e1c1 +./file4:216 0xadc43abf0dc765bc +./file4:224 0x5ad799b39539a4d0 +./file4:232 0x38a77e3e9d4e5714 +./file4:240 0x80c276769d7652aa +./file4:248 0xd49554961c120fa0 +./file4:256 0x97b845201a38588b +./file4:264 0xbc9840a145f96ec2 +./file4:272 0x3d859068ca328a35 +./file4:280 0x834ae784ceeb684b +./file4:288 0xe0b0eadd2d00bbfa +./file4:296 0x776492824c0bc45a +./file4:304 0xe8a232bdce16222e +./file4:312 0xadc10a6b6f1fff56 +./file4:320 0x6393d4d7076e264d +./file4:328 0x2826a70eaf2d172e +./file4:336 0xfe05c4481cdba323 +./file4:344 0xfdf1e3f8b29074f1 +./file4:352 0xa80e16be305affed +./file4:360 0xb0c0a95ff763fd99 +./file4:368 0x3015d880e53de748 +./file4:376 0x5fff3fd9cb1c7b5a +./file4:384 0xb0576a16c695e2f5 +./file4:392 0x51ae125168e7d448 +./file4:400 0x319ce8f3cc06a03e +./file4:408 0x1f87f7ec1ed57107 +./file4:416 0x5ff31ea32c67fe70 +./file4:424 0x475827e8530e2aff +./file4:432 0x80c4213292402e1 +./file4:440 0xdbb6a2a0adb1eab2 +./file4:448 0x28c2e3dd95b73d90 +./file4:456 0x2d50afeaabc5095a +./file4:464 0xbd99f80597995f74 +./file4:472 0xd29f167b0230b28 +./file4:480 0xe42c835e9fc09418 +./file4:488 0xeac82037973b218b +./file4:496 0xb58957a39b3c85c9 +./file4:504 0xb415a67034c7a40f +./file4:512 0xeb0a7ec1334d926f +./file4:520 0xe8df60a8d80c1e39 +./file4:528 0xe217276915bfa72b +./file4:536 0xe15a06fd6a92d663 +./file4:544 0x8e68a547d6dea130 +./file4:552 0x8750422e14292697 +./file4:560 0xa243063069d0eb1f +./file4:568 0x3f18d75b0f9752dd +./file4:576 0x12c1e976c9ec5b54 +./file4:584 0x28e8c165b20320ae +./file4:592 0x4ee0a609ce81a14c +./file4:600 0xc1f567b752e7be82 +./file4:608 0x7f1fe9676b06f67e +./file4:616 0xa5cfd147695aea6b +./file4:624 0x1882a45cd9c643cc +./file4:632 0x36e7a7d8545c4f89 +./file4:640 0x4f00168b9f990d9 +./file4:648 0xfd1bde0b92eb6830 +./file4:656 0x5a3fb5fe14efa63c +./file4:664 0x98b2f1b5c668329a +./file4:672 0xd43c4804401c4613 +./file4:680 0xd10d3bc5c8a29915 +./file4:688 0x663abf2c448150cc +./file4:696 0xa9430b288a3735b4 +./file4:704 0x6c7a3481518a6e5c +./file4:712 0x86845fdbeadd1dd +./file4:720 0x80bef6c3f1fe150f +./file4:728 0x5887a47b5da2eb01 +./file4:736 0x28b62145423358f9 +./file4:744 0xbeebb4a6799c7fb5 +./file4:752 0x3d5e80d41856f517 +./file4:760 0x172748b51323a265 +./file4:768 0xe095b813ebe9261e +./file4:776 0xd185b0038c0ad9f0 +./file4:784 0x90e7376078599618 +./file4:792 0xf052469a1b537650 +./file4:800 0x166f7ead4d96e48a +./file4:808 0xcd1a417a44c59d81 +./file4:816 0x184f0382d0420bd8 +./file4:824 0x8bb915d1c2361703 +./file4:832 0x5bd3f67159c8ecd1 +./file4:840 0xb618cd51dd184098 +./file4:848 0x6fd183a8eda46d2c +./file4:856 0x632b5698e7e6799c +./file4:864 0x520c652d39f70dfd +./file4:872 0x64504ac8cc6a8517 +./file4:880 0xed2e03dc8e51528c +./file4:888 0x6a3cb8310a6dc600 +./file4:896 0xaa748e669f9489bd +./file4:904 0xb9f3630ccb519542 +./file4:912 0x6f32638d94ab9220 +./file4:920 0xb1e8708350787ef +./file4:928 0x9fe3c7d8d406a1a2 +./file4:936 0x8250a20fb0e6f10a +./file4:944 0x2a7fb2d89b04f6bc +./file4:952 0x605bfa2d8a035a79 +./file4:960 0x731a05f5f6e29da6 +./file4:968 0xf4f07c378bedf96 +./file4:976 0xc2b65810208c8c33 +./file4:984 0x3e815a4cc7b46e10 +./file4:992 0xbc91513fe81f58e0 +./file4:1000 0xd03eac3eb276e020 +./file4:1008 0x32454164d84a6112 +./file4:1016 0xfc45cd5d805b7727 +./file4:1024 0x653fc959cd0e5c6d +./file4:1032 0xe47c7b39ece7b70c +./file4:1040 0xda311bd25e59576f +./file4:1048 0x1602c539ba0ce49c +./file4:1056 0xeabad19f49b6e723 +./file4:1064 0xaea55636b2736368 +./file4:1072 0xb026532f1d034c4c +./file4:1080 0x5b9684541e8b9ba0 +./file4:1088 0x9b9f4d94053da74b +./file4:1096 0xb649bded4d811866 +./file4:1104 0xd6a47a4ce461b5fd +./file4:1112 0x38c6b45f94e66e20 +./file4:1120 0xc55f44f9469be49a +./file4:1128 0xb5ab46b0dffce05a +./file4:1136 0x3a8a83e0acdf7465 +./file4:1144 0x52065d529926e9d8 +./file4:1152 0xe44f8538ae630def +./file4:1160 0x4a6851abf3ac1ef3 +./file4:1168 0x1cf9fac709fcfd9b +./file4:1176 0x179ffbfd295f744e +./file4:1184 0x2bf44768040cfd80 +./file4:1192 0x7d05d1946a55ba9d +./file4:1200 0xeca9727a2886a8a +./file4:1208 0xdb8ce1cdf8ded080 +./file4:1216 0x7ac7236b250ce8c4 +./file4:1224 0xbd759832273cff1c +./file4:1232 0x8b4c6e899a33a7df +./file4:1240 0x18daa9852d978408 +./file4:1248 0x7567948a7d72a06a +./file4:1256 0xcf5b54534519faa0 +./file4:1264 0xd8e4a617bdfced6f +./file4:1272 0x174827be07babf8d +./file4:1280 0x79ed16baf1cc57ba +./file4:1288 0x2d65f648be7b2a0e +./file4:1296 0x33d210dd29ad1380 +./file4:1304 0xe2efa49375cb7bf5 +./file4:1312 0x898af3cfe98ed89d +./file4:1320 0x658c7de6b53fe839 +./file4:1328 0xa43973f179032876 +./file4:1336 0x3d196ec7bd8916a1 +./file4:1344 0x8707718bd35c8479 +./file4:1352 0x1d9e46167d62d783 +./file4:1360 0xfc854e74d8bbbd03 +./file4:1368 0x77526e84a397a2b0 +./file4:1376 0xb73612f24240f791 +./file4:1384 0x7e498274f63e7678 +./file4:1392 0x15a74a9447da3b8b +./file4:1400 0x88d176f4452f7dc8 +./file4:1408 0x7acb712582f70295 +./file4:1416 0x5edacd41c3f22c1b +./file4:1424 0xd5371b0c28b39c6c +./file4:1432 0xc952316c52a3ca33 +./file4:1440 0xadc8cf4282f1e0cb +./file4:1448 0x3f382e98bbc08179 +./file4:1456 0x2f138d53da1467bd +./file4:1464 0xc0df1218ecb52481 +./file4:1472 0x85368a7b77b383e1 +./file4:1480 0x4495014398c85ac7 +./file4:1488 0xd9540524a566057c +./file4:1496 0xa925b940688c2506 +./file4:1504 0x93b08cfe6889910b +./file4:1512 0xf778decebb55d40a +./file4:1520 0xb167d8b46347372a +./file4:1528 0xf18f08c437be523d +./file4:1536 0x840d88edb5842f5b +./file4:1544 0x65eeaf6e74142720 +./file4:1552 0xa450713698f4f658 +./file4:1560 0x2fc45d42521e64ec +./file4:1568 0x6ed7e574c06e507f +./file4:1576 0x5ed7b4c749c7c124 +./file4:1584 0x59eb47945351218f +./file4:1592 0x6ebec54db928d838 +./file4:1600 0x354409aacd6dd46 +./file4:1608 0x1799795d193ad873 +./file4:1616 0x9aada3e436ed20d9 +./file4:1624 0xfc63ff8e0bc05ab3 +./file4:1632 0x4b6852084df285d3 +./file4:1640 0xcf4563c8cdfdd1d1 +./file4:1648 0x3ac5bb2799c4680c +./file4:1656 0xfd8a870e4cf41382 +./file4:1664 0x2eb295f902ca87f2 +./file4:1672 0x336d1901eac6e181 +./file4:1680 0x98b8d710054e2787 +./file4:1688 0x72a0ad0262e3340 +./file4:1696 0x35732d36b1861725 +./file4:1704 0x9d53c44898b83116 +./file4:1712 0x5f022d2b356d5a60 +./file4:1720 0xb42298f15953856a +./file4:1728 0xc9f6e20365b32c37 +./file4:1736 0x2c16ae69b54a2ff5 +./file4:1744 0x633d22bef1f3ef86 +./file4:1752 0xb0c54b0fcd968b15 +./file4:1760 0x6a1a035893bc1c +./file4:1768 0xa1ce6f501f9b2117 +./file4:1776 0xebe7e253e7ba3dd6 +./file4:1784 0x8c15a12ce0506109 +./file4:1792 0x2e3dcad1597d1234 +./file4:1800 0x484b632b13b6692b +./file4:1808 0xe25fb1021fba0f3f +./file4:1816 0x928c49ddb60f470e +./file4:1824 0xc57633f286018f2e +./file4:1832 0x38ccbe5d518110ae +./file4:1840 0x95495188afe975aa +./file4:1848 0x207f8e222e8641da +./file4:1856 0xf96fa24cafac1962 +./file4:1864 0xbc2d6723a98840e6 +./file4:1872 0x10d8d488380c2ff4 +./file4:1880 0x44b63aae94e4d7cc +./file4:1888 0xae5265b76d02a36c +./file4:1896 0xed4c7e03108e92c +./file4:1904 0xe815d0a62722e72d +./file4:1912 0xbd8c6d1adb20fd95 +./file4:1920 0x8df0adb258085599 +./file4:1928 0x88a50a33666f064 +./file4:1936 0xc7d24fe026d8120a +./file4:1944 0x553523aa95c762d +./file4:1952 0x54bc3ed67964ab5a +./file4:1960 0x4463ec1c2c660997 +./file4:1968 0xfa1f1a15510a48b2 +./file4:1976 0x687c991acfa5fc0e +./file4:1984 0x4bab0d8c1f67d512 +./file4:1992 0x49b29cf0af23a2f0 +./file4:2000 0xd100f0f5089e5814 +./file4:2008 0x5fb60d2474aa95 +./file4:2016 0x1a67f652585c4280 +./file4:2024 0xde0a3fd51e115520 +./file4:2032 0xcaec44329ecb5cfa +./file4:2040 0x59e9f108d49bae9 +./file4:2048 0xc8e244272224742e +./file4:2056 0xa83d585bae11b02b +./file4:2064 0x73af688d27bf0178 +./file4:2072 0xe576d1afeed3d5b0 +./file4:2080 0xf766a5aac5d6d335 +./file4:2088 0x6b487383aaf517e4 +./file4:2096 0x4bd08725a0723b33 +./file4:2104 0x3573c97227b01d54 +./file4:2112 0xe69b7672e86ada5b +./file4:2120 0x938eea56f73381b7 +./file4:2128 0x2f74d5afc2994d7 +./file4:2136 0xbf2738c3825ebedf +./file4:2144 0x685d74314b9a87ae +./file4:2152 0x30fe4dba8f1396fb +./file4:2160 0x15c261ae3a46bd9c +./file4:2168 0xe41e7dfb25fa9991 +./file4:2176 0xa5ba578848cc6115 +./file4:2184 0x1e461d940ae8f517 +./file4:2192 0xd78c5bc8c802e07e +./file4:2200 0x8f31ab99cd20830a +./file4:2208 0x2de0355d47b155c9 +./file4:2216 0x1d989049090eaa6c +./file4:2224 0x68b34686109a88ac +./file4:2232 0x69ab35a7d6ec226d +./file4:2240 0x9a424c7777eb130e +./file4:2248 0x40ffec491621ee12 +./file4:2256 0x1025f738c0607631 +./file4:2264 0x11056c64bb12272 +./file4:2272 0x83dc086f38992422 +./file4:2280 0x1ad8ff6c0b0ff8b4 +./file4:2288 0x11372c8ed8665ae1 +./file4:2296 0xa6843c5580e948a8 +./file4:2304 0xd208737130f70fc6 +./file4:2312 0x98163e9fb4f438bd +./file4:2320 0x628d7ef832a8fda9 +./file4:2328 0x7f4e20b22e21ee0d +./file4:2336 0xcb0d239f530edd29 +./file4:2344 0xda778e8795e9ca7e +./file4:2352 0x23e1d506e26c9bdb +./file4:2360 0x64c12ad96f0e3acf +./file4:2368 0x62cc3de62ee86f12 +./file4:2376 0xb455ab747c601400 +./file4:2384 0xa5630a8be8be0f7 +./file4:2392 0xd173f2b1c04ee85d +./file4:2400 0xec88927dd4d00499 +./file4:2408 0xe87d8b589316107f +./file4:2416 0xf55e1a011966dea7 +./file4:2424 0x4b52f729ac167355 +./file4:2432 0xd8e1a73bfab5ad81 +./file4:2440 0x5a4c39ae0e3e576e +./file4:2448 0x5b44609fdcbdeb30 +./file4:2456 0xf71846c557012893 +./file4:2464 0xdd92b34e6d2751ef +./file4:2472 0xcfa76fa58823440f +./file4:2480 0x5ec337ee82726987 +./file4:2488 0xf3b4e7fc0af51b7 +./file4:2496 0xa156bd02654d5a4f +./file4:2504 0x5955299e6d0cb4af +./file4:2512 0x9dd741e4ba67e5d1 +./file4:2520 0xb89f994fd5d515a0 +./file4:2528 0x39a61c066b50bca1 +./file4:2536 0x204d9711c09d4e9 +./file4:2544 0xa41df6dd1cdab0ea +./file4:2552 0xb73dc0cde3fa4411 +./file4:2560 0xdfcf3f71b76265c6 +./file4:2568 0x5eaf16449362f2f9 +./file4:2576 0x70ee3610912d4f10 +./file4:2584 0x334114ba3029ef31 +./file4:2592 0x54f200ca129f201c +./file4:2600 0xf3ea66d3212dc231 +./file4:2608 0x939231850cad1d52 +./file4:2616 0x66d7ce6e4dd3e613 +./file4:2624 0xe8baa57cf3a959e +./file4:2632 0xc4a0671351701e6f +./file4:2640 0x8a6b86749302c4fa +./file4:2648 0xe872bb845019a349 +./file4:2656 0xd91c3bd299eb6e0b +./file4:2664 0x749ad075193d3650 +./file4:2672 0xc82e7fff7492098 +./file4:2680 0x6a12bdbe67bc5867 +./file4:2688 0x4a66bf6197f2651a +./file4:2696 0x48c1a03214a23c2d +./file4:2704 0xef30baf23ab12816 +./file4:2712 0x8526ebedf30f6524 +./file4:2720 0x273579806915f52 +./file4:2728 0xf3ad8aca36f053eb +./file4:2736 0x58eb5cc576af690 +./file4:2744 0x5f2aa6ff9c57f194 +./file4:2752 0xe3b6ae284a50b2d4 +./file4:2760 0xe1838b83d3aed8c5 +./file4:2768 0x548c6e7026d017c1 +./file4:2776 0x975639db4c483b5d +./file4:2784 0xc56f8849687b2c0e +./file4:2792 0xed33269a623bed5a +./file4:2800 0x216587ca7ce0664d +./file4:2808 0xc9e71ce50cfc6f3c +./file4:2816 0xcff97d78109f6376 +./file4:2824 0xd3f756ec1497194c +./file4:2832 0x1701ea2fe911f4d9 +./file4:2840 0x74d18b1c0439d813 +./file4:2848 0xfca8a710c286d6da +./file4:2856 0x9a07a57ddb70f932 +./file4:2864 0xa4a0c51fd2438d11 +./file4:2872 0xef857b94339999da +./file4:2880 0x5c012d54d5f01fde +./file4:2888 0x817671d641916027 +./file4:2896 0x7207b54241a4c55c +./file4:2904 0x256505ecde0a042e +./file4:2912 0x3756ae337c9139b5 +./file4:2920 0x77a137c1d145693f +./file4:2928 0x4c3790307036ebcf +./file4:2936 0x3ef92e07bb00cd20 +./file4:2944 0x9e39d5d0d8d14f2a +./file4:2952 0x26931030f32d4d3b +./file4:2960 0x8fa4fb819a972a78 +./file4:2968 0x9e6ae96ce56706e5 +./file4:2976 0xe5b647d182d3934a +./file4:2984 0x7ba80ec14bf23992 +./file4:2992 0x702e0f360a9ecf8c +./file4:3000 0x28af93eaa48e5bf8 +./file4:3008 0x9cd95c87f6bd90d6 +./file4:3016 0xcc119668de2ecb4c +./file4:3024 0x6d40530d498ae768 +./file4:3032 0x9462d2796c4e7729 +./file4:3040 0xc20bfea2ce6ba994 +./file4:3048 0x8a820d72e8200ec4 +./file4:3056 0xe176b4089fdbfdd8 +./file4:3064 0xd888cab9123ce3f0 +./file4:3072 0xaf353679d065fd8c +./file4:3080 0x5cb35856f4e78c74 +./file4:3088 0xec3754d7f272b470 +./file4:3096 0x9f49e0fbbb4ab151 +./file4:3104 0x2f46497ad9098bc5 +./file4:3112 0xc4c903bd8a467670 +./file4:3120 0x81c370c2c7e69b5d +./file4:3128 0xa7bec1ef355a6567 +./file4:3136 0x64f9889ee6ad47e1 +./file4:3144 0x9f394b647ac98d88 +./file4:3152 0x6717be501d11d713 +./file4:3160 0xf52de0c01a2bf5b4 +./file4:3168 0x77cc9a5b7e0d56e1 +./file4:3176 0x2a2fb006ebf5f8cf +./file4:3184 0xd31b24ea4d68ed53 +./file4:3192 0xfbedc6a320810f2e +./file4:3200 0xa65634d272487fb2 +./file4:3208 0xe00700998211e3a7 +./file4:3216 0x7d151d8e89da5610 +./file4:3224 0x2204a5cfb2106e40 +./file4:3232 0x4ef3c0c005ef96d6 +./file4:3240 0xf8f14b853932f93 +./file4:3248 0xeabea58efa57a5e7 +./file4:3256 0x407c91b1a0904c19 +./file4:3264 0x1419a70e60674c6a +./file4:3272 0x7ed48febb72004ef +./file4:3280 0x71c44d3ec01cb706 +./file4:3288 0x3c8c7bcfca0f38ab +./file4:3296 0x7f033faf7d789429 +./file4:3304 0x57899e656023a177 +./file4:3312 0xe18a69a1781cac84 +./file4:3320 0x3e4849f59a69c51c +./file4:3328 0x8d7f238f0a46df62 +./file4:3336 0x626a30165eba869d +./file4:3344 0x2d2c8aa245591841 +./file4:3352 0x789324faacd60043 +./file4:3360 0xbfcada1ca647c47 +./file4:3368 0xae707fe874b1f1e +./file4:3376 0xe62381f797b8271e +./file4:3384 0xf36e7165c324d560 +./file4:3392 0xcc8691113e694c77 +./file4:3400 0x9235282a5e00bae4 +./file4:3408 0xa95ca398487c2c33 +./file4:3416 0x16e735030ce3ade4 +./file4:3424 0x85d33080d84476ba +./file4:3432 0xed039be2e0315eaa +./file4:3440 0x32e6e3f23331f778 +./file4:3448 0x2fa694bfbb96c862 +./file4:3456 0x77e591839e21f6c8 +./file4:3464 0xdc6e98e37c2c9dad +./file4:3472 0x8bc8636979ad1e2b +./file4:3480 0xe904e6cd6836d141 +./file4:3488 0xc19d5153c7331c40 +./file4:3496 0x2971ba9de45e4ae7 +./file4:3504 0x423bba68818c73b6 +./file4:3512 0x98011ed03c826f64 +./file4:3520 0x5b6a802b7b1caeb6 +./file4:3528 0x672236e6c58d9e2 +./file4:3536 0x8e7eedae30e3fdf9 +./file4:3544 0xc4076e5cba0eebbb +./file4:3552 0xb918429db58f1156 +./file4:3560 0x418e04ac97d7b385 +./file4:3568 0x80ff2d732ea8294e +./file4:3576 0x66f0f566128afd0 +./file4:3584 0xbf1863ad435bd0fc +./file4:3592 0x114ed2834d90e780 +./file4:3600 0x9b7a309c8c9493ec +./file4:3608 0x69dca39efa8d84fd +./file4:3616 0x55f12613443b5c32 +./file4:3624 0xbedd50c4de0607a +./file4:3632 0x9d020d58d61a3d85 +./file4:3640 0xb8f24704bbb4485f +./file4:3648 0x5581075080078215 +./file4:3656 0x4e1d30158ef16570 +./file4:3664 0xb86e1c5ed4468513 +./file4:3672 0x2277230da6134fc5 +./file4:3680 0xde28cafdf91693d0 +./file4:3688 0xa871cc8b7631a18d +./file4:3696 0xbbd31a3b9967a562 +./file4:3704 0x90f44722dc137d65 +./file4:3712 0xfdb5bf16499c300c +./file4:3720 0x70caf67fa9145fa7 +./file4:3728 0x848f632f82c75a02 +./file4:3736 0xef3e815b760c1ba +./file4:3744 0x3a158ec30574c6ce +./file4:3752 0x4eadc505497d419f +./file4:3760 0x6f1bdda85db3865b +./file4:3768 0x1309b624a0ef93b9 +./file4:3776 0x77e3551ea4277635 +./file4:3784 0xca478ce26e0ec677 +./file4:3792 0xafbd4b4842c8c2ce +./file4:3800 0xe45c2c76b2c9cd64 +./file4:3808 0xef01896d693c2cfc +./file4:3816 0x524a2faef87c3dda +./file4:3824 0x526e758f2460900b +./file4:3832 0x8b685afbc02d10f6 +./file4:3840 0xa577aaa5509a3ea8 +./file4:3848 0x9509db27663a3977 +./file4:3856 0x9b1482295be011ec +./file4:3864 0x46a837a9e2d80d07 +./file4:3872 0x23395cbc4d527120 +./file4:3880 0x9a141da17afd0c81 +./file4:3888 0x869b9c91897e0ffb +./file4:3896 0x7b44b4874f1601d0 +./file4:3904 0xba53b10e526b9a6e +./file4:3912 0xe4e3bc3273c162d1 +./file4:3920 0xc6b983f2c0d10ef9 +./file4:3928 0x34c85743c980ee51 +./file4:3936 0x79b5ec4e95326a15 +./file4:3944 0x72409df55806ae44 +./file4:3952 0x68ca9c3506531f76 +./file4:3960 0x8c7fef5f347d0d1e +./file4:3968 0xc90bb738a136e41 +./file4:3976 0x903051c3baeca817 +./file4:3984 0xec316f76c269409b +./file4:3992 0x1808c782c7fa2cf5 +./file4:4000 0xd7ad09c63858a06a +./file4:4008 0xef246ed72a68cc05 +./file4:4016 0x6cfd8aeee337df6f +./file4:4024 0x6e1d17b297c97200 +./file4:4032 0xcb983fd775f0a790 +./file4:4040 0x9bada27956e652b9 +./file4:4048 0xa00f0b8d6fc97014 +./file4:4056 0x2e074b618bc71877 +./file4:4064 0xf9241400c6f8e0c0 +./file4:4072 0xae27a55e0b7eee50 +./file4:4080 0xdbccac4364d30d28 +./file5:0 0x699e38778f3ef3ba +./file5:8 0xf059add994b795bb +./file5:16 0x5d660f6fcbf7a8c9 +./file5:24 0xe3bf0d5eab830623 +./file5:32 0x6762e4ddd8db9d61 +./file5:40 0xc166cd61691ef20 +./file5:48 0xc48517402e71a5e1 +./file5:56 0x468cbee9a7bf165b +./file5:64 0x5c0ec6cdd770e86b +./file5:72 0x80709502787617cf +./file5:80 0xa277dbe7fd1273f0 +./file5:88 0x533756395aa7c8a7 +./file5:96 0x745917c2c62e072f +./file5:104 0x95e6798e4ecdd92c +./file5:112 0x285d19051a690a83 +./file5:120 0xbe9b0baff26734d7 +./file5:128 0x290336b5ef28cf9c +./file5:136 0x5193b5ab80dc0e19 +./file5:144 0xbce1b986b22e39d9 +./file5:152 0x3c3b324553a0b80a +./file5:160 0xbebc9ec7b7e4b53a +./file5:168 0x84164052759e1835 +./file5:176 0xb3bc4901b2c3d32d +./file5:184 0x388c555111c50b07 +./file5:192 0x1baad97ff05fb0ce +./file5:200 0x9f1577dea1702611 +./file5:208 0x42ebb3b29e5c4573 +./file5:216 0xa0f54848f74fde5d +./file5:224 0x3c045e5ebdba553a +./file5:232 0x5fef4d4abce8e312 +./file5:240 0xd2d33241e4fe483b +./file5:248 0x4631568659dca419 +./file5:256 0x8a4fe6d521c42d4f +./file5:264 0xa46210c35d2e6fc8 +./file5:272 0x86d84b21e320fb31 +./file5:280 0xa93cc8f6354fb4be +./file5:288 0x73ebf38e6a41911a +./file5:296 0x9a9de51f9f29f9a4 +./file5:304 0x7bf4041b5e89a711 +./file5:312 0x3ec169d6d935771b +./file5:320 0x8e6e1d4a08805d6d +./file5:328 0x360dd8cd50184e70 +./file5:336 0x3ab4e9421244e4db +./file5:344 0xd229d58ce714a8a0 +./file5:352 0x71f72d56dad342c0 +./file5:360 0xf608748aed95d219 +./file5:368 0xf5f53c1d7c04698c +./file5:376 0x7db60764955b1443 +./file5:384 0x4b1985bf2786017b +./file5:392 0x912bd9c3ead3f31c +./file5:400 0x5c2ddf875afcf064 +./file5:408 0xcda540c6c5b1a283 +./file5:416 0xc62e4859afa5e2c +./file5:424 0xf4c348522efad2de +./file5:432 0x59c4354945c4e744 +./file5:440 0xf2dc8915bd97e1a8 +./file5:448 0x3992db927d218861 +./file5:456 0xb730204e6d115898 +./file5:464 0xe39695eb9e06309 +./file5:472 0x4748d76b9c37489e +./file5:480 0x1e4e23f97723d683 +./file5:488 0xe564f5e9ebdf6beb +./file5:496 0x411cc15b1812ac53 +./file5:504 0xfc86b704fd9d9497 +./file5:512 0xe7e86f4445b99697 +./file5:520 0xd613a855020a1bd9 +./file5:528 0x124de973f03f087f +./file5:536 0x2d38fdd6d5b387b0 +./file5:544 0xa88ff12ea4abb0b8 +./file5:552 0xcd18adfadd0dd6e8 +./file5:560 0xc6a7bae97f197d57 +./file5:568 0x66fcb7926a6fb0cf +./file5:576 0x7f9e8691e6852c4e +./file5:584 0x6ce3f230f10c993a +./file5:592 0x2d94705667834d5b +./file5:600 0x5c98ffab74d63592 +./file5:608 0x8e919d0daf50f530 +./file5:616 0x7c9312b1ee9ffbc9 +./file5:624 0xe6ec6076be8f38a8 +./file5:632 0x5d22cefb87a8f364 +./file5:640 0xe508fbcc2a2b130d +./file5:648 0x54727149baa4a3c0 +./file5:656 0xd8247802dbe86912 +./file5:664 0x2d49dab1d2eb4c9c +./file5:672 0xc16baea2fb9a925a +./file5:680 0x8db68762ec33d948 +./file5:688 0xb331c64b4c6e81f0 +./file5:696 0xa29988fba06f8992 +./file5:704 0x6f95693fa919c4c8 +./file5:712 0x511b77ad8c450d1c +./file5:720 0xe174ed2eff5c07e6 +./file5:728 0xb6fcc990b3e79b19 +./file5:736 0xf2ab711f7ee43ec1 +./file5:744 0xb8cd0d8d0ab7c306 +./file5:752 0x7a749195e925c912 +./file5:760 0xb4b6cffbe32c0f2c +./file5:768 0x265934aabda98500 +./file5:776 0x17d1cd19b4e33b6c +./file5:784 0x5cd8709a67702b2 +./file5:792 0x668e136615f588a9 +./file5:800 0xd9772f6fc9ce857 +./file5:808 0xbc16100958613427 +./file5:816 0xbcbf11a59b6dc902 +./file5:824 0xc4d639ba80a315d8 +./file5:832 0x168d1587e3452e9c +./file5:840 0x1704147fe224a174 +./file5:848 0x2b17cee262f0db4d +./file5:856 0xb23a0db0f7ec2975 +./file5:864 0xa6ae815602a88df8 +./file5:872 0xcb20a65512c541a5 +./file5:880 0x15e67b7a96873f3b +./file5:888 0xb499043af2fa4df0 +./file5:896 0x75076dd3f6262a96 +./file5:904 0x5feef6870dd1a94d +./file5:912 0x28501fff0b82aa25 +./file5:920 0x52fcacdca39f3e0b +./file5:928 0x8dd5e673bb867db5 +./file5:936 0xd1a0a409286aacdc +./file5:944 0xb9a1f62e0d147ae3 +./file5:952 0x3c64474307a752e3 +./file5:960 0xc39953e5d39de643 +./file5:968 0xcc892a98b36fa13f +./file5:976 0x84cd8208f3171e63 +./file5:984 0x4d6bbd25777ee73c +./file5:992 0x60112f7ea8f3380f +./file5:1000 0xe41dcbcb158faf36 +./file5:1008 0xa2d22d2515c6f9ac +./file5:1016 0x70557529d94cd79 +./file5:1024 0xa9f771c31be4bfca +./file5:1032 0xe13f6cf3f7c1387e +./file5:1040 0x4a3dcee1a78ba6b8 +./file5:1048 0xcad6abecca0982b4 +./file5:1056 0xd28581e24ca866bd +./file5:1064 0x2569941c281c9a34 +./file5:1072 0xe99c4b798c69cb74 +./file5:1080 0x3feefaee327fc875 +./file5:1088 0x7ff1ffb82373d071 +./file5:1096 0x630dddc7eb95bf3c +./file5:1104 0x3eaef151dc64c91d +./file5:1112 0xf935708c263b4c98 +./file5:1120 0xa4b52da5d604ba83 +./file5:1128 0x1956bf7ca228eccc +./file5:1136 0xfa6ee1863e06069f +./file5:1144 0xfcbd8025d5825010 +./file5:1152 0xf70fc0ffdfedc069 +./file5:1160 0xd08948a486d6619d +./file5:1168 0x8c5e340f27eb85f +./file5:1176 0x4aa8688df8d4231e +./file5:1184 0x884622a52f98b3c1 +./file5:1192 0xd3422895caad095a +./file5:1200 0x4c9a8bf6ec447db0 +./file5:1208 0xbbf83ecfb9156fc5 +./file5:1216 0xe585bef252f8cadd +./file5:1224 0x55025e954db65e86 +./file5:1232 0xde23f060bb1f0dfc +./file5:1240 0xda16c98d8a5f1786 +./file5:1248 0x6cad83eacd74392a +./file5:1256 0x8d4e3869c96b8f2c +./file5:1264 0x6905ed6af73757cc +./file5:1272 0x74a6235d2ccfc4f2 +./file5:1280 0xc51d533186785c71 +./file5:1288 0xbf469dc9aad28268 +./file5:1296 0xc52b23fabc4ab4ab +./file5:1304 0xf9c6a158fe740a7f +./file5:1312 0xb06db9fc162f6623 +./file5:1320 0x88c4d07699c8404d +./file5:1328 0x486d760c690b656b +./file5:1336 0x143452846ed16152 +./file5:1344 0x72ea0cd2ab4e863 +./file5:1352 0x5e1a3081fe583e9e +./file5:1360 0x2d34f4a0674c6175 +./file5:1368 0x17671f8c00bd4ee5 +./file5:1376 0x3b440d2032b8612c +./file5:1384 0xa86706193d6a4bc1 +./file5:1392 0x1ba4f5238a2a1492 +./file5:1400 0x299836d6b024fda5 +./file5:1408 0xdbd58668635f5339 +./file5:1416 0xed6c6d3bfd30409 +./file5:1424 0x966d049da01fed27 +./file5:1432 0xbbcd16c15d4987b9 +./file5:1440 0xa7ae6cc592f2aee3 +./file5:1448 0x5a9450f273870e38 +./file5:1456 0x59b0f75b22fa4ebb +./file5:1464 0x38cac5e38fee8039 +./file5:1472 0xdb93c54b760d4303 +./file5:1480 0x4d31e5b4703ad043 +./file5:1488 0x2401e9c24838a0fa +./file5:1496 0xad3030cb3998a436 +./file5:1504 0x826d05b47dc2c48 +./file5:1512 0x99112c0efd3a780b +./file5:1520 0x26e8a70760a5551c +./file5:1528 0xa515948d490aaf5 +./file5:1536 0x72ca477024ec8f4c +./file5:1544 0xcf1236679c1fbf35 +./file5:1552 0x98c71fdbc63570d2 +./file5:1560 0xfce57878eb41dd04 +./file5:1568 0x9d95d2d0b5f4bbd9 +./file5:1576 0xdc62871e3acc2cce +./file5:1584 0x2741c7ff4d6df954 +./file5:1592 0xae42314a9f059404 +./file5:1600 0x942b600fbf7c142f +./file5:1608 0xd87fc76db5ef9fc9 +./file5:1616 0xf413ddee1bf31f75 +./file5:1624 0xc8ccc1215e71322d +./file5:1632 0x6e51651e608dea03 +./file5:1640 0xaf4e2aeb24735803 +./file5:1648 0x23aa19e21c5b1eca +./file5:1656 0x1edcdfc75878bd8e +./file5:1664 0xe24e932930e488c +./file5:1672 0x29c57a30ce08c6b5 +./file5:1680 0x4a66957e32c22726 +./file5:1688 0xc01a2f94a0e1d12d +./file5:1696 0x193967879dadec8c +./file5:1704 0xae174ab28fd5b7fc +./file5:1712 0x63b944fa056dce75 +./file5:1720 0xac0580bf7074763 +./file5:1728 0x9dd1790bddc4639b +./file5:1736 0x37b0b210051e579d +./file5:1744 0x9a59415bb5c76826 +./file5:1752 0xc1678c37469180c9 +./file5:1760 0x489709125e1e81d4 +./file5:1768 0xdc699f5f0193c43 +./file5:1776 0x423b799009d651d +./file5:1784 0x5389e5295f61d333 +./file5:1792 0xc463c4ba6f40427c +./file5:1800 0xc43dd1c243752d87 +./file5:1808 0x3e2872ebd67ec7b8 +./file5:1816 0x1645a49c99bd34cf +./file5:1824 0x8c66e5994c484459 +./file5:1832 0x4aced71ac0d14d0c +./file5:1840 0x6c131c9fa431ce92 +./file5:1848 0xb33cb58ddf2655be +./file5:1856 0xeb15788d0147c20 +./file5:1864 0x5c72bb1600649094 +./file5:1872 0x9c0d4497d55c12e8 +./file5:1880 0xd19a9fa0ee1d8608 +./file5:1888 0x482a546c71df5002 +./file5:1896 0x27efdd3691b957f8 +./file5:1904 0xc4f7d48f0be179be +./file5:1912 0x3a29197f8410eb67 +./file5:1920 0xee9719184807f779 +./file5:1928 0x9b0fa145c4d261d0 +./file5:1936 0x1c64d1c6e99ade31 +./file5:1944 0xc14d2388a8211b2f +./file5:1952 0xdfb1aacd1f24b973 +./file5:1960 0xb85b970d488c4be3 +./file5:1968 0xc3f95e50174ab298 +./file5:1976 0x3f95011b2516dbd3 +./file5:1984 0xcfea911fcd424da1 +./file5:1992 0x7abcd12817683e8e +./file5:2000 0x1ddee5f0a8d986bc +./file5:2008 0xa16a29165766109e +./file5:2016 0x3b158f69bd47a5e0 +./file5:2024 0xb7cee6673f28fe1 +./file5:2032 0xdc95ddd1b6f59d8a +./file5:2040 0x2ab601ea2b692d65 +./file5:2048 0x234f0dcaf4defd1b +./file5:2056 0x1310e1d653289424 +./file5:2064 0xe3be030ed8b16cd6 +./file5:2072 0xee178a0706f02289 +./file5:2080 0xbb4038182cd2007b +./file5:2088 0x87bd1f669f5547e6 +./file5:2096 0xbf0a6132258aab16 +./file5:2104 0xf8da20a6c0ff902e +./file5:2112 0x30d6b27bac5f8cec +./file5:2120 0x476491f7d393c678 +./file5:2128 0x49e964f74fd503cd +./file5:2136 0x23b9c22bda2f2e4f +./file5:2144 0xd3f6b29ec70fc9d6 +./file5:2152 0xdcc7c390bbad9177 +./file5:2160 0xec2dcc51a674a38b +./file5:2168 0x3b77dd2ce1adcccd +./file5:2176 0xb49bfea2bcfca662 +./file5:2184 0x3cd3c516d807de0e +./file5:2192 0x33e4c155926fbc9b +./file5:2200 0x5e8d8181bbe5ecfb +./file5:2208 0xb3291a5452637acf +./file5:2216 0xd115838ba2b7c916 +./file5:2224 0x39a32260f9806265 +./file5:2232 0x3135cee466f06c7c +./file5:2240 0xf7dd403094a272 +./file5:2248 0x7e8a8a52297afd23 +./file5:2256 0x8bff5d70691ea1fd +./file5:2264 0x81f8942773993e60 +./file5:2272 0x8e883ff76284fdce +./file5:2280 0xa3bdc6ea71a2e2e4 +./file5:2288 0x57d974f20e5022b2 +./file5:2296 0xa5f831dabb8e2d88 +./file5:2304 0xb6c62121b4306498 +./file5:2312 0xa3a73468c6f7c1c0 +./file5:2320 0x55f7a979da067440 +./file5:2328 0xe245257416aa57f2 +./file5:2336 0xa1f8bc61b27ea37 +./file5:2344 0xea6aa45ba2f3e0ac +./file5:2352 0x4528f196c27fd5c1 +./file5:2360 0x53a712e134670b68 +./file5:2368 0x28f4bee119836a3a +./file5:2376 0x7840be017d72c636 +./file5:2384 0xb7eb40831cc6419 +./file5:2392 0x192c90222e29cb6a +./file5:2400 0xd6794d2a71b1f4bf +./file5:2408 0x6c6550b418c0e7b4 +./file5:2416 0xf0e3a890247af748 +./file5:2424 0xebcd1aa9c9dab12a +./file5:2432 0x38fb56ebdfa669a2 +./file5:2440 0xfa1b5d6bb618b336 +./file5:2448 0x2cd852706fb82978 +./file5:2456 0xbd00997eebc8f1b1 +./file5:2464 0x4a13bcf44112c5c4 +./file5:2472 0x32a9a8a59a6caea0 +./file5:2480 0xd07b6aa758a2df51 +./file5:2488 0x4924bd9b4545671d +./file5:2496 0x43c4d542d21ed71d +./file5:2504 0xfef6b7191ca4ad86 +./file5:2512 0x50e61d850886d6ef +./file5:2520 0xb5daef44fffd5e25 +./file5:2528 0xde4eebeeb0d216bc +./file5:2536 0x8cce38a5f836ff0d +./file5:2544 0x4a998686125ad28a +./file5:2552 0x965f76deabaac3b3 +./file5:2560 0x49c2db520d9c596e +./file5:2568 0xfa8c7f8bf647ac43 +./file5:2576 0x8c384cbce5b71363 +./file5:2584 0x6ac9e6dbd677ed40 +./file5:2592 0x8da3bdbcbebcb2d7 +./file5:2600 0x8a9ab1af9afb2fc +./file5:2608 0x14c020c6261040aa +./file5:2616 0x4f089589ef6177f +./file5:2624 0x76256f0585200743 +./file5:2632 0x4f2fbd4e90718c99 +./file5:2640 0x152c1a893267a690 +./file5:2648 0x373d3381649608de +./file5:2656 0xa8d4014c8f6cb163 +./file5:2664 0x849bf2fc316cecb9 +./file5:2672 0x21b7f0bac620862d +./file5:2680 0xb9e9983614d8e0b7 +./file5:2688 0xa62ff4a9710ce28b +./file5:2696 0x4392fa92bc069278 +./file5:2704 0xbaee27e23de46185 +./file5:2712 0x76108e1f35d2a5ba +./file5:2720 0x85dc7b59c213bf63 +./file5:2728 0x1dd4fc8e008a3096 +./file5:2736 0xb56286d9a523c06e +./file5:2744 0xedaad2aafa39eb91 +./file5:2752 0xf34dd8fa9b89832 +./file5:2760 0x5b6f97131de4993f +./file5:2768 0x39d1df4667cd703f +./file5:2776 0x487be471445d416b +./file5:2784 0x319ca18747dd8e93 +./file5:2792 0xadb0cdc1c5e80938 +./file5:2800 0x42cc53b288f15d2e +./file5:2808 0xe3c7b6656ffe179 +./file5:2816 0xafe19bb8341e7844 +./file5:2824 0xbec9bc92a704086d +./file5:2832 0x99d35a5a342835eb +./file5:2840 0xa8cac18e23de182b +./file5:2848 0xfd47b0870e7e011b +./file5:2856 0xf080a6f6a0c2ce7 +./file5:2864 0x5b9548584ed7213c +./file5:2872 0x944cdb328f617cee +./file5:2880 0x8dc793f171e6a5d8 +./file5:2888 0x3308de98fda1a07e +./file5:2896 0xccb1ebea2e1ccb7a +./file5:2904 0xcb72d50c71a2421b +./file5:2912 0x3b5895101fa18df5 +./file5:2920 0xb0c64d250e39884e +./file5:2928 0x9170a914a728f7ac +./file5:2936 0x3718b6c6f1db6a7d +./file5:2944 0x416746d6df3e1359 +./file5:2952 0x2ee79568e76d9678 +./file5:2960 0xfa0586f9dd551c1c +./file5:2968 0xb1c540642ffd0ed7 +./file5:2976 0xe079aa02ab87ef34 +./file5:2984 0x4b1a6f49b10a2cc4 +./file5:2992 0xf35ca412f5c12457 +./file5:3000 0x6ba020cab63cd028 +./file5:3008 0xa84e033020904fa2 +./file5:3016 0x7bc09486db54a9d7 +./file5:3024 0x637a763e671e6f54 +./file5:3032 0x94b935129c09395a +./file5:3040 0x44ee9e52cf39e190 +./file5:3048 0x78d8d314238f8394 +./file5:3056 0x9bdaafd5afd7dab0 +./file5:3064 0x6d0f3dc4baa3f8b +./file5:3072 0x58c7f79ca6b26fd6 +./file5:3080 0x2db497cb72a59b3a +./file5:3088 0xba82aad0bd83a69b +./file5:3096 0x83ee8c4a2a27b5f7 +./file5:3104 0x7d05509b83755e48 +./file5:3112 0x86d54d54548f0364 +./file5:3120 0x749da894837a3fa +./file5:3128 0x310450dbe5f4015e +./file5:3136 0x95c994a5a47a98d9 +./file5:3144 0x87325ea2185cbf50 +./file5:3152 0x629b9d1690b4bdb6 +./file5:3160 0xffdbc6c60cf3b1cd +./file5:3168 0x6704f4ee44d8888b +./file5:3176 0xd229447b47a2adbe +./file5:3184 0xc85bf76da376a7f0 +./file5:3192 0xcd4829046859d60d +./file5:3200 0x5699d6464de6581a +./file5:3208 0x79f15f05cef68ca +./file5:3216 0x6b0e2b25a1cff976 +./file5:3224 0x3f7df3484933749b +./file5:3232 0x30430c3e24ac7b9c +./file5:3240 0x910252093d0a7e01 +./file5:3248 0x524d715061a98dab +./file5:3256 0x1ed7c6258c6c2ec9 +./file5:3264 0xe47334042ee697dc +./file5:3272 0x8b7dc2eda4eca14 +./file5:3280 0xcecb8eac77b00cdf +./file5:3288 0xced4a11f46561a11 +./file5:3296 0xb641ca59a2278c14 +./file5:3304 0x8d364dd8241eec6c +./file5:3312 0x8f94973d6d9a2422 +./file5:3320 0x71a14cec067eb8b2 +./file5:3328 0x42c647824f5c1f8c +./file5:3336 0xce0b0d1f02d7af55 +./file5:3344 0x35e1ac79f175e4cf +./file5:3352 0x2ca5c1405df53030 +./file5:3360 0x5bc3e6b8fa2a28d6 +./file5:3368 0x4b38eabbbfe61b4c +./file5:3376 0x2efdb930afdd89c3 +./file5:3384 0x84163e4688c72ae5 +./file5:3392 0xa17407476d5eda23 +./file5:3400 0x2da07b2bd6c0bac5 +./file5:3408 0xe04337a60d0ef93d +./file5:3416 0xf04342a37cf07514 +./file5:3424 0x7afe92c1ea35582c +./file5:3432 0x8d2ceb5c5b94185a +./file5:3440 0x5cd0a334171eff0f +./file5:3448 0x7b7627636d870bf8 +./file5:3456 0xd33ed6b491bbb521 +./file5:3464 0x54efb3793401b77 +./file5:3472 0x2681ca607463ecd7 +./file5:3480 0x3ab142d2e60a6193 +./file5:3488 0x2138e4d5814d4619 +./file5:3496 0x37aa0bb7c7071198 +./file5:3504 0x4147685a6e8c201c +./file5:3512 0x24ce785f1b08de43 +./file5:3520 0xec6736d9f11daa4e +./file5:3528 0xa2e6302f81886753 +./file5:3536 0xbeaf049ac9faf452 +./file5:3544 0xd1f028b8d65dfc3a +./file5:3552 0x20080369f352c603 +./file5:3560 0x400713ddd7e761f3 +./file5:3568 0x6ef7afc96025a6fc +./file5:3576 0x8d5ae3ba1e04c86c +./file5:3584 0x618781fdd7e7de01 +./file5:3592 0xae46a420dcfe721f +./file5:3600 0xda198664f40657c5 +./file5:3608 0xc471f061b1b4816d +./file5:3616 0x40dc34a96c20d6fd +./file5:3624 0x445ad7eab1e3a577 +./file5:3632 0x38ee74b94dde6ff6 +./file5:3640 0xf1f06f6f5f84a84b +./file5:3648 0x8b551145b57c93dd +./file5:3656 0x4b84b34fded09101 +./file5:3664 0xb938cb68511a9a69 +./file5:3672 0xa39ed1d5fcbef83b +./file5:3680 0xd49b810aaaaaa136 +./file5:3688 0x9f914e41bbd39032 +./file5:3696 0x3ee9126b9925dd42 +./file5:3704 0x8866e844ab298591 +./file5:3712 0xea0586008d3616ed +./file5:3720 0xdfe7ba9c428d070f +./file5:3728 0x98e6189bfa80bd30 +./file5:3736 0xb2b3df58c745d841 +./file5:3744 0x80b68393ec1b9a70 +./file5:3752 0xefdfb8719e789ecc +./file5:3760 0x43ac58b5d372933b +./file5:3768 0xe074077aadc68fe9 +./file5:3776 0x49a8f8e6f9e150ce +./file5:3784 0xfbce5a5450cd52c5 +./file5:3792 0x9045345161c530d +./file5:3800 0x82559f9d767457ad +./file5:3808 0xecbc371e1f014120 +./file5:3816 0xbcea789a42cf37b +./file5:3824 0xc86d87197ef1ea3d +./file5:3832 0xe4479e1c77c5b9ca +./file5:3840 0x739177a7c45cd604 +./file5:3848 0xe00dc6dd18e9aab +./file5:3856 0xe9b843132832a43f +./file5:3864 0x5becdee6f5dafaa6 +./file5:3872 0x2ea956d9ce1d0384 +./file5:3880 0x85e563249bd0ecf +./file5:3888 0x32882273489a0024 +./file5:3896 0xb15fbb8cbad95558 +./file5:3904 0x6477e2f26f3e6178 +./file5:3912 0xc13e6ce478d2f540 +./file5:3920 0x5b79fd712ce6c140 +./file5:3928 0xa76c951d7b196c0e +./file5:3936 0xd7e0de08008d6930 +./file5:3944 0x4c6e33f32c0a6400 +./file5:3952 0x43fb36b85b38d1f3 +./file5:3960 0xf06c82643d16097a +./file5:3968 0x84b4a98131dcf314 +./file5:3976 0x5cad55f2e744c7b8 +./file5:3984 0xabf3f1abf734bbd3 +./file5:3992 0xa52a0137c7b075e7 +./file5:4000 0x1cb96e6d3c2849e2 +./file5:4008 0xfdd8dda810625f27 +./file5:4016 0x2bce6864df693ba7 +./file5:4024 0x36140d9f996f6c16 +./file5:4032 0xc2444927102d9801 +./file5:4040 0x4d8b759a87d24634 +./file5:4048 0xc5b3ad865f63f477 +./file5:4056 0xedb95fe6605a35d6 +./file5:4064 0x8702022a0eb511e5 +./file5:4072 0xe98d106834d8a7f5 +./file5:4080 0xdbc17373b20f0bf7 +./file5:4088 0xc0a1f9ae83b44b36 +./file5:4096 0xf1e70387c908b610 +./file5:4104 0xe7884cf2bc494996 +./file5:4112 0xee6bdcc2b928a133 +./file5:4120 0xfaed60a336cace04 +./file5:4128 0xd0a873feab20a441 +./file5:4136 0xe335e25661b91e9 +./file5:4144 0xd7ad304e62df3bb0 +./file5:4152 0xbd741e2b455b7189 +./file5:4160 0xb3dc1bdc4a49ff6b +./file5:4168 0x1816f8b14a841240 +./file5:4176 0xa0cb7a3299d06375 +./file5:4184 0x7eef7ab957a0af59 +./file5:4192 0xf6786c70ff35e596 +./file5:4200 0x29737a4943d8a3c +./file5:4208 0x9c055fd45c72560c +./file5:4216 0xcc51ae755b04bab1 +./file5:4224 0xd76ed03a66b83d7c +./file5:4232 0x3805e761d9dc25e3 +./file5:4240 0xb4b54993e7ded488 +./file5:4248 0x5b9423356407bce3 +./file5:4256 0xa51df1aaa01934b2 +./file5:4264 0xd5ce0933d5b5c244 +./file5:4272 0xfa08efc81a9a170b +./file5:4280 0x18bfcc0bd3a943f6 +./file5:4288 0xecbfefdd65803e25 +./file5:4296 0xdbf7bfdbd02fc10f +./file5:4304 0x459748ec7a6c34ad +./file5:4312 0xef6e2af8a5de10b5 +./file5:4320 0x33f907423b8646fd +./file5:4328 0xb6408e7a9c887192 +./file5:4336 0xf9a245728fb3040d +./file5:4344 0x639f677ad8b85073 +./file5:4352 0xa2dfd5863045dc05 +./file5:4360 0x4b85de2d8adea985 +./file5:4368 0x3632a81e79d7f427 +./file5:4376 0x8f9879a1bc94c47b +./file5:4384 0x44ab711398a37c62 +./file5:4392 0x92435f1132957e24 +./file5:4400 0x36efb745bf83a2ba +./file5:4408 0x619465353ff1b670 +./file5:4416 0x65ad462763faebe1 +./file5:4424 0xd37e943dac793a2a +./file5:4432 0xb59055ddd461f18 +./file5:4440 0x2586951cb7383189 +./file5:4448 0xfb7b6e167f144f1 +./file5:4456 0xa5066621cc209a97 +./file5:4464 0x29d6c6467aa88934 +./file5:4472 0x71dad1291c61b2e5 +./file5:4480 0xc6a6acf3791a18f8 +./file5:4488 0xc0fe30df72973bc9 +./file5:4496 0x7655d1a718ab0b37 +./file5:4504 0x794745f1983d7672 +./file5:4512 0x584f68a7ee4f78ea +./file5:4520 0x7d9862e4002dd5e9 +./file5:4528 0xd0b48eb9557e918c +./file5:4536 0xde39c9d793ba1281 +./file5:4544 0xf00f79b3806988ee +./file5:4552 0x2eb0ecb661184d2c +./file5:4560 0x131b89374cabfbef +./file5:4568 0x7901438f8795fb65 +./file5:4576 0x72ce7b63e4fb4e9b +./file5:4584 0x6113cf89dec583bd +./file5:4592 0xba51b110b97b6ec9 +./file5:4600 0xc7a23fc5611a0231 +./file5:4608 0xb05b922708252a43 +./file5:4616 0x387cade774079990 +./file5:4624 0x3b4e2c9520ca95 +./file5:4632 0xe8ceedc2105aab88 +./file5:4640 0xd5e8bdc709b23f61 +./file5:4648 0xe9e17b207d533a09 +./file5:4656 0xc669f436979af94e +./file5:4664 0xd8579e34b0b198d9 +./file5:4672 0x2af241cb4eda0e74 +./file5:4680 0x9be766df4b54efc3 +./file5:4688 0x39f34b6059cbf50e +./file5:4696 0xc3584db7bc55c9d0 +./file5:4704 0x4dd10e1974b5d808 +./file5:4712 0x2db72895ebbc152c +./file5:4720 0xbf3fd4052033c31e +./file5:4728 0xd3d19545ca7c9dff +./file5:4736 0xfcad8e29cc23c989 +./file5:4744 0xe1c530adabebe0dd +./file5:4752 0xd406b893b9d64f8d +./file5:4760 0x78bef35ffa66a454 +./file5:4768 0x8d1d4adc3916775a +./file5:4776 0xf190f2421ecbc9fc +./file5:4784 0x8c2625721514a792 +./file5:4792 0xe441a1ffebe9cc72 +./file5:4800 0x9a356c9266423313 +./file5:4808 0xcdc5ce8fa6649a69 +./file5:4816 0x6a9f205be8f06c56 +./file5:4824 0xc4f4558e615f893c +./file5:4832 0x1c7b7e9fa9dc7df1 +./file5:4840 0xfbdba6c6421b0c6d +./file5:4848 0xac2ca2d5576369f1 +./file5:4856 0x525e665b7262d731 +./file5:4864 0xdc1ca0a2cc75e8a1 +./file5:4872 0x605bbde985b8efd +./file5:4880 0xcbbeb694d0687e57 +./file5:4888 0x8e15640f02c9fdaa +./file5:4896 0x3a9a6dcc4f07629d +./file5:4904 0x7cd4b18b8a8982b3 +./file5:4912 0xf2059838337f5887 +./file5:4920 0x649e1e2460cab66f +./file5:4928 0x71bd8d8a7c779e49 +./file5:4936 0x3a3a448f0bb327c +./file5:4944 0x7e251ca02d5b30eb +./file5:4952 0x33ad9e7758a1c707 +./file5:4960 0xc179f07104a93871 +./file5:4968 0xf3178fb4f84239d +./file5:4976 0x96b67fb567adc60 +./file5:4984 0x31ed86bf4d275133 +./file5:4992 0xe263147e1195ba90 +./file5:5000 0xe90080df83f585a3 +./file5:5008 0xd3a24478a4c95337 +./file5:5016 0x10fbbc69a6cf5a44 +./file5:5024 0x6c49209368649300 +./file5:5032 0x1db1eb5249aaefaa +./file5:5040 0x352034b816e6a1ff +./file5:5048 0x94dd2e3bbc4f6929 +./file5:5056 0x9561781a12a27b73 +./file5:5064 0x370bfa5b195ea2ed +./file5:5072 0x82124cc4025f83cb +./file5:5080 0xab40463a8533d481 +./file5:5088 0xd88a6dec53ec2b0c +./file5:5096 0x2adbece6447150dc +./file5:5104 0x7b504e10632fc7f8 +./file5:5112 0x484cf8dda77286e8 +./file5:5120 0xf46662b5d23c63db +./file5:5128 0xae805bfddec168e7 +./file5:5136 0xadc46afd945521c0 +./file5:5144 0x804b7b8e7a034324 +./file5:5152 0xb0f960d7f12ba67e +./file5:5160 0x45fff74c7d9ac48c +./file5:5168 0xf4025a404b3e190e +./file5:5176 0xcb32be8e0c3a6f9b +./file5:5184 0x1f00157bd35494b8 +./file5:5192 0x487133726be43292 +./file5:5200 0x9faca015c603ea0c +./file5:5208 0x7a06e464dfcc51f0 +./file5:5216 0x4844301960d79370 +./file5:5224 0x73684469a9ff35d8 +./file5:5232 0xad266c1c7874c450 +./file5:5240 0xfeb1aab6489a9d08 +./file5:5248 0x9d7579a5bfebbed6 +./file5:5256 0x507dbaa92f136ca5 +./file5:5264 0x6d0c8bd04de31559 +./file5:5272 0x4f5820e946e06264 +./file5:5280 0x7775726f40876267 +./file5:5288 0x54e586464314a65d +./file5:5296 0x4b47b5dfcff179bb +./file5:5304 0x7b2c9b87ae4f4db2 +./file5:5312 0x8e7fe8e87780a324 +./file5:5320 0xf92a7697cd694ac3 +./file5:5328 0x158ab2c3c2d602a4 +./file5:5336 0x7fec4a05562be79f +./file5:5344 0xbee0c35bb6413591 +./file5:5352 0x3c51842240569e93 +./file5:5360 0xd2895af7e8bcae20 +./file5:5368 0x70d2135a01f12913 +./file5:5376 0xdc831b7b0d38fb75 +./file5:5384 0x62df401087339562 +./file5:5392 0x3e5e670ce5b12e8c +./file5:5400 0x588ed2f2cb81431 +./file5:5408 0xc1a12cd40975f867 +./file5:5416 0x5c16b023d9502315 +./file5:5424 0xe6b567ef43ced83a +./file5:5432 0x7872e8ca5733e719 +./file5:5440 0xc0d0a64fa86ba77e +./file5:5448 0x333e4a47b07c62b5 +./file5:5456 0x96356a8e687491df +./file5:5464 0xc4b98b37cad666d7 +./file5:5472 0x32aa246f50bdb750 +./file5:5480 0x47ba410c07e6431d +./file5:5488 0x202464b12483e7d3 +./file5:5496 0x4d86bd075ea430d4 +./file5:5504 0x6242e74ebca069ea +./file5:5512 0xc770ac771fdbb94 +./file5:5520 0x4ad02a33c4d5dd03 +./file5:5528 0x18756d4c096a2996 +./file5:5536 0xbfe55e00ca71acd +./file5:5544 0xd172126c1635ffc +./file5:5552 0x4a74bbaeee58d9b2 +./file5:5560 0x5b533ce4c828393c +./file5:5568 0x85cbec1786043013 +./file5:5576 0xf3f3f50b2e7b3441 +./file5:5584 0x3cf554ebd29a0347 +./file5:5592 0x88ed518ac8833500 +./file5:5600 0x1b76685785a0d167 +./file5:5608 0xf991dc7869a8db78 +./file5:5616 0xbdc08dbeb8673c0d +./file5:5624 0x17a0120f9ef6cf4e +./file5:5632 0xc07ff8d2d24ddef1 +./file5:5640 0x88af9eeee01aea2c +./file5:5648 0xf67ef58b35395161 +./file5:5656 0x5a2f88e929457339 +./file5:5664 0xbc2049a5f2f88f12 +./file5:5672 0x63a744ab2ae516d9 +./file5:5680 0x98db27147f2a1138 +./file5:5688 0x4a9a92cd857485bb +./file5:5696 0x31ecbc960266b4d4 +./file5:5704 0x5eea24117c3cddea +./file5:5712 0x7d7c47912fbe5081 +./file5:5720 0x8b250fd183ff2482 +./file5:5728 0xb4ebd4acf0de4d5d +./file5:5736 0x53bc85903b06f288 +./file5:5744 0x8d44ea25e67cfd66 +./file5:5752 0xce0a56ecd19feb6d +./file5:5760 0x158469ea48b99706 +./file5:5768 0x55dc4b8cb69125d1 +./file5:5776 0xd812747a97d10d1c +./file5:5784 0x8db6403f355884b7 +./file5:5792 0xae42f079d363ebf0 +./file5:5800 0x3cdac3a543930941 +./file5:5808 0x50498c6d0e46dd1f +./file5:5816 0x9804703a3f93a882 +./file5:5824 0x47b1a2364997c528 +./file5:5832 0x607612b3edb17320 +./file5:5840 0xcbc5ef825951e054 +./file5:5848 0xaa6e2b08dd5bbd2e +./file5:5856 0x3066d78c4ee7bc91 +./file5:5864 0x1e4d1a998fc46b93 +./file5:5872 0x638f4929c362ed81 +./file5:5880 0x492e0084052478a9 +./file5:5888 0x3427adbf74047973 +./file5:5896 0x347f1ffbe450b1af +./file5:5904 0x64d87aca2ddf071d +./file5:5912 0xb0c6dd300cca78d7 +./file5:5920 0xe37db96cd1c0885a +./file5:5928 0x31acf651cf5791b5 +./file5:5936 0x7088d8504c42cbc4 +./file5:5944 0x463416f05d20e410 +./file5:5952 0x8d1090a191246fa5 +./file5:5960 0xfae40d0ae309b6cb +./file5:5968 0x2824a79d0c5e73b2 +./file5:5976 0x85096d8c6f8d44eb +./file5:5984 0x38251b534c2448f4 +./file5:5992 0xcf7231bdf7cf28db +./file5:6000 0x43a5f18110ede9ce +./file5:6008 0xb51583ce3ccec3ef +./file5:6016 0xfba1c52311e377e8 +./file5:6024 0xda85782b90a852f5 +./file5:6032 0x2ee6ad3846913057 +./file5:6040 0xaf091f046977c868 +./file5:6048 0x5eed96004c9f1892 +./file5:6056 0x4523faecf2d8b7bc +./file5:6064 0xaf9496b29a29a546 +./file5:6072 0xa32b507f7986886f +./file5:6080 0xeecf7f8f01b048b7 +./file5:6088 0x866002e79a9a33ba +./file5:6096 0xf0e6b6e8b09ea0cf +./file5:6104 0xe3859ff7013ca097 +./file5:6112 0x87612c1cd1896ae3 +./file5:6120 0xca65c510e2183d8 +./file5:6128 0xab3cecd624dea6f7 +./file5:6136 0x45c3702308cfa963 +./file5:6144 0x2b889972acd046ca +./file5:6152 0x7f0e4d740fc3e0f6 +./file5:6160 0xce0214442b2b8802 +./file5:6168 0x3f7307014621c292 +./file5:6176 0x7d1c5562f3785e36 +./file5:6184 0xaff4bc08f5b34813 +./file5:6192 0x70d6065467429167 +./file5:6200 0x6649f0b450763544 +./file5:6208 0x6b59b82523360c21 +./file5:6216 0x256bb58b8d02dc86 +./file5:6224 0x3e120fba0be2407 +./file5:6232 0x54828005678c50e8 +./file5:6240 0xada9489b8826204b +./file5:6248 0x71eb79ccd1b909bf +./file5:6256 0xd65ee28a0f6f8fbb +./file5:6264 0x8db6f7c04f24592f +./file5:6272 0xa615d41828aeb90c +./file5:6280 0x9b3f148a3dfe3b9d +./file5:6288 0x16f82c38dd4870e2 +./file5:6296 0x50ce1c9c5333837c +./file5:6304 0xe52f80ddd782c6b6 +./file5:6312 0x11d0cd14fb43f327 +./file5:6320 0xefd9b85a82b90a3a +./file5:6328 0x4363c12532f4b354 +./file5:6336 0x8d687a088896519 +./file5:6344 0x1dd001cf1648dc2f +./file5:6352 0xa114dffd4272cdad +./file5:6360 0x1d7f39793471b95 +./file5:6368 0x62b0c221413286c0 +./file5:6376 0x14c6609a1445d43d +./file5:6384 0xfe5606d08b4cb7be +./file5:6392 0xded4f18791391fe4 +./file5:6400 0x9907f104febeeaf8 +./file5:6408 0xf76af82fc6882b44 +./file5:6416 0x5e2b113ada90d9f7 +./file5:6424 0xb2a813215061c0ae +./file5:6432 0xba2c73bf6da9a6d7 +./file5:6440 0x1eb4594d3ca0245c +./file5:6448 0x8bbee3bb7739d880 +./file5:6456 0x2530b6dcbdc146fa +./file5:6464 0xd1817c2100c7db6b +./file5:6472 0xcc0a4ebf148c1b2e +./file5:6480 0xa32491a25deab4f +./file5:6488 0x93e277883f1b6eb +./file5:6496 0xada0947542ddd181 +./file5:6504 0xed4c3ee7d61de70b +./file5:6512 0x2c7a12ddbc0e9a +./file5:6520 0xe296bd0e0e2b6da5 +./file5:6528 0xb92a3e7cbfd7a0d9 +./file5:6536 0x2cee7b14a85313b3 +./file5:6544 0xba5e9f5450175052 +./file5:6552 0x854860b60da58643 +./file5:6560 0x428546123da32641 +./file5:6568 0xa1c374833dd105a5 +./file5:6576 0x861a90d77e5f5cf7 +./file5:6584 0x9093567be142399d +./file5:6592 0x6c185be7d192ec48 +./file5:6600 0xabcaf8f29bb0fd2e +./file5:6608 0x3e32f6b640359e88 +./file5:6616 0xc712a5f514db467c +./file5:6624 0xcfc994cde120311 +./file5:6632 0xeea3f899f8c4da1d +./file5:6640 0xd6f3f39a7acdb85c +./file5:6648 0x542917827163ee86 +./file5:6656 0xde4c26c0aea6a6e8 +./file5:6664 0xdaa935d612f44fa2 +./file5:6672 0x7e860d97bdcd0c1c +./file5:6680 0x28c43be683edadc5 +./file5:6688 0x37e4b6ba84c8d4f7 +./file5:6696 0xd76839b77963c0d6 +./file5:6704 0xbff01bbedb1e14f2 +./file5:6712 0xa89912c20d378fd6 +./file5:6720 0x71fce32992979801 +./file5:6728 0x738632b56644737b +./file5:6736 0x4c0a32b4a155e81d +./file5:6744 0x47e47944f12ecc14 +./file5:6752 0xf3346d603a5cf410 +./file5:6760 0x2cd5c764a3c1896b +./file5:6768 0x799b174f424f1355 +./file5:6776 0x636522da53de0ed9 +./file5:6784 0xd5984de60f2776c7 +./file5:6792 0x919bef1217f6b81a +./file5:6800 0xc24525fffb790b29 +./file5:6808 0xc9035a1ab0001323 +./file5:6816 0x732220792265cef4 +./file5:6824 0xf4a27fc64a7cd076 +./file5:6832 0x43f551573c0c7ac6 +./file5:6840 0x8a9e27f0ae6a2e6d +./file5:6848 0x1336482e6e4fec2b +./file5:6856 0x38d93be5f58a2d7b +./file5:6864 0x32221bfb94cc089f +./file5:6872 0x3eff3a215ed0be92 +./file5:6880 0xb5d03019a41c4f4f +./file5:6888 0xf28343fbe52c974e +./file5:6896 0xfc7eb500cdaf4f3 +./file5:6904 0xe916bbcebed713cb +./file5:6912 0xb0131acaa9b201a1 +./file5:6920 0xdfcd6b014d2ecf0d +./file5:6928 0x8e85aa99c1d10e51 +./file5:6936 0x9fc2e1c1824a0c69 +./file5:6944 0x11e6d953ce004d43 +./file5:6952 0xe18aa994ab22674f +./file5:6960 0x2a800a966583e6b7 +./file5:6968 0x56c4bc647051ddd7 +./file5:6976 0x3d2d61969a85663e +./file5:6984 0xed86c0e6903f9f6 +./file5:6992 0x790c12c1b6e14608 +./file5:7000 0x4530b07e86dba71a +./file5:7008 0x7df79eb462f328c0 +./file5:7016 0x20e8cf57e2c77820 +./file5:7024 0x101f18234fc99da8 +./file5:7032 0x2d2b1749266a3a58 +./file5:7040 0x77c6dd9dd4b822e1 +./file5:7048 0xc27e9a51acaf2c3f +./file5:7056 0x591da459d61704ea +./file5:7064 0x3e733aae77450d26 +./file5:7072 0xe494c31f4b17f1f8 +./file5:7080 0xc114074cb4fdbd94 +./file5:7088 0xa50ccd7690ffe525 +./file5:7096 0x2a1f74d1df4e929a +./file5:7104 0x8702a904aba23f04 +./file5:7112 0x85882656725790ea +./file5:7120 0xe48b2ea4dd73625b +./file5:7128 0xbdc92cf738a27050 +./file5:7136 0x67be68d8470ce948 +./file5:7144 0x4ee5f57d4bf48e9d +./file5:7152 0x665156ca15c52659 +./file5:7160 0x9dd39d9db61fc4cd +./file5:7168 0x65ff0475bc0b3926 +./file5:7176 0xccd72cb6e90f1b95 +./file5:7184 0x1cb1c8ada74d1cd +./file5:7192 0x62708b19f30e1d41 +./file5:7200 0x7c6cd623ae820dc8 +./file5:7208 0x4c3e42d9b71aeb75 +./file5:7216 0xb6e9af8aa8c0ae72 +./file5:7224 0xb2a2560c8385b0df +./file5:7232 0x8cb6084c4f088f37 +./file5:7240 0x7791ebf66ed54bc8 +./file5:7248 0xf638aa71f6665d72 +./file5:7256 0xc443953cb3977d39 +./file5:7264 0x4fae24f0c4876210 +./file5:7272 0x37f790ab10daffaf +./file5:7280 0xd437430b17245ff6 +./file5:7288 0x8931b60d766760e8 +./file5:7296 0x1885db4fec214c1f +./file5:7304 0xb1265e06aa329a55 +./file5:7312 0x75fe0e6becea07ae +./file5:7320 0xbf30d61e0bb9bbbd +./file5:7328 0xe17bc278433a4979 +./file5:7336 0xb04a6b649d854529 +./file5:7344 0xd7a1a84f8ba79f84 +./file5:7352 0x9b098eb1f3eb4789 +./file5:7360 0x988c950b8e1fc006 +./file5:7368 0x60d5ceef074f05da +./file5:7376 0x812c2965ded15cff +./file5:7384 0xd6a630f400cfb3c1 +./file5:7392 0xac1e42b3ccc77948 +./file5:7400 0x4dc8627409ac45e5 +./file5:7408 0xe719584cec2c9c39 +./file5:7416 0x3001a5ad05cac003 +./file5:7424 0xd36372390269eeb7 +./file5:7432 0xd10cd8a7b0342d8f +./file5:7440 0xd2662f99a061c58a +./file5:7448 0xb3bcaad5d243d60d +./file5:7456 0xeab6e0f6ed495ad8 +./file5:7464 0x70efe962594757cd +./file5:7472 0x1f8f7d38ebe84b17 +./file5:7480 0x7d434f8a3f3f1b14 +./file5:7488 0x8143ff1dd778e27e +./file5:7496 0xd42663b3f612b34 +./file5:7504 0x4f1e649460b0c846 +./file5:7512 0x41d165d5f1fea17e +./file5:7520 0xc5b6192670b81aec +./file5:7528 0x9c6d9792da84a62f +./file5:7536 0x75f7fe5a52b5ed04 +./file5:7544 0xac80bb39adea8a8a +./file5:7552 0x929d981c0d0180be +./file5:7560 0x40cb5768f96834a3 +./file5:7568 0x3e0069c4335b5fd5 +./file5:7576 0x8ccc31e07d120b80 +./file5:7584 0x78bb1cbe8f0dfadc +./file5:7592 0x292a97fcf1d040ec +./file5:7600 0x64fe1ed1cf97c00c +./file5:7608 0xbc456588e43e923a +./file5:7616 0x8044681921e7c1b9 +./file5:7624 0x504d065297868779 +./file5:7632 0x58dd67e07e4a4773 +./file5:7640 0x33478fc73f996ae8 +./file5:7648 0x20faf62a43a03420 +./file5:7656 0xee539201708f5963 +./file5:7664 0x2b5419c56217db97 +./file5:7672 0xad259abbc31889ec +./file5:7680 0x41471f3e402bf510 +./file5:7688 0x36e59a7a797b5d3b +./file5:7696 0xd7057dded397b46a +./file5:7704 0xa3d7c86704329f76 +./file5:7712 0x6b6d6131616dbebb +./file5:7720 0x75207cd3f2a46d66 +./file5:7728 0x42c6022c6da52c57 +./file5:7736 0xb029506293c8cec7 +./file5:7744 0xd73b2c5297d7caa7 +./file5:7752 0xb90381caaf2866bf +./file5:7760 0xd941f0f8c84492be +./file5:7768 0x22ce06a90ab83093 +./file5:7776 0xe9b3b1ca4b6f013 +./file5:7784 0x21072492c3440575 +./file5:7792 0x2a2b6fe696952fc5 +./file5:7800 0xbed481736fea7c49 +./file5:7808 0xb837c0f4e7a7aac4 +./file5:7816 0x88c4713724380553 +./file5:7824 0x865ebfa874814741 +./file5:7832 0x7534b82f7c990094 +./file5:7840 0xe454e0131e971381 +./file5:7848 0x54229db5a96fa5d0 +./file5:7856 0x4202496fe3c60574 +./file5:7864 0xa37263eb57e84ddf +./file5:7872 0x3da52022361e3c50 +./file5:7880 0x1f01f59c8c60c123 +./file5:7888 0xa3a80fc6d3d18334 +./file5:7896 0x1b6fbe7fa74f9678 +./file5:7904 0x66e20e8a7c3d3876 +./file5:7912 0xaf4be10f02e4795c +./file5:7920 0x35e97f1a765dc9ca +./file5:7928 0xcd9946edc280315c +./file5:7936 0x8ea4674c6f95e09e +./file5:7944 0xe42604dddcfb92e6 +./file5:7952 0xfc288c7f748baf7a +./file5:7960 0xa17f0d86a87f912b +./file5:7968 0xa569337f19111442 +./file5:7976 0x11820a665d6bbbf4 +./file5:7984 0x2227a771ec80f81a +./file5:7992 0xa74e7589940bf36b +./file5:8000 0x27cbe8f5cfb5b965 +./file5:8008 0x9d257015248849c9 +./file5:8016 0xad524c05a244c608 +./file5:8024 0x27e3f92527763937 +./file5:8032 0xc44342fe75a183ff +./file5:8040 0xb5a586ef23907543 +./file5:8048 0xe0cdf945a2bb1d3d +./file5:8056 0xadf3227374bd75e3 +./file5:8064 0x5d0e533328d77d38 +./file5:8072 0x7c02bff0cc7a0abd +./file5:8080 0x8b0c32d2496d0326 +./file5:8088 0x10e9227436cae1e8 +./file5:8096 0x970aed6e47c0093d +./file5:8104 0xc6d11123e5e7433c +./file5:8112 0x833ff8f14da59671 +./file5:8120 0x21b0365e2824cf4c +./file5:8128 0xd77b0a554efa2206 +./file5:8136 0xe20630e758c21625 +./file5:8144 0x8b7cf773d263c075 +./file5:8152 0xd0bc479bbb9427f1 +./file5:8160 0x5700267143f12756 +./file5:8168 0xbba39237fce953d9 +./file5:8176 0x1af59e6d6d05f49d +checksum/TEST0: Done diff --git a/src/test/log_basic/.gitignore b/src/test/log_basic/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..260ef90418a63d11356ec2e5fb08ba113e41a075 --- /dev/null +++ b/src/test/log_basic/.gitignore @@ -0,0 +1 @@ +log_basic diff --git a/src/test/log_basic/Makefile b/src/test/log_basic/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..c62008130d37720bc7ea79d0a7b70d5e48448271 --- /dev/null +++ b/src/test/log_basic/Makefile @@ -0,0 +1,43 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/log_basic/Makefile -- build log_basic unit test +# +TARGET = log_basic +OBJS = log_basic.o + +include ../Makefile.inc + +LIBS += -lpmem -lpthread + +log_basic.o: log_basic.c diff --git a/src/test/log_basic/README b/src/test/log_basic/README new file mode 100644 index 0000000000000000000000000000000000000000..5f9b9895835fb390c688f208efa94af0be828c2c --- /dev/null +++ b/src/test/log_basic/README @@ -0,0 +1,34 @@ +Linux NVM Library + +This is src/test/log_basic/README. + +This directory contains a unit test for: +- pmemlog_map +- pmemlog_unmap +- pmemlog_nbyte +- pmemlog_append +- pmemlog_appendv +- pmemlog_tell +- pmemlog_rewind +- pmemlog_walk +- pmemlog_check + + +The program in pmemlog.c takes a filename and a list of +operations encoded as characters as arugments. For example: + + ./log_basic file1 a v r w t n + +this will call a series of log iterations with some hardcoded arguments +as described in the table below: + + a - pmemlog_append + v - pmemlog_appendv + t - pmemlog_tell + r - pmemlog_rewind + w - pmemlog_walk + n - pmemlog_nbyte + + + + diff --git a/src/test/log_basic/TEST0 b/src/test/log_basic/TEST0 new file mode 100755 index 0000000000000000000000000000000000000000..744bf864eb54bee60912b5139645430100f01f6d --- /dev/null +++ b/src/test/log_basic/TEST0 @@ -0,0 +1,62 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/log_basic/TEST0 -- unit test for: +# - pmemlog_nbyte +# - pmemlog_tell +# - pmemlog_walk +# - pmemlog_rewind +# in case of empty pool and: +# - pmemlog_check +# - pmemlog_map +# - pmemlog_unmap +# +export UNITTEST_NAME=log_basic/TEST0 +export UNITTEST_NUM=0 + +# standard unit test setup +. ../unittest/unittest.sh + +setup + +rm -f $DIR/testfile1 +touch $DIR/testfile1 + +expect_normal_exit ./log_basic$EXESUFFIX $DIR/testfile1 n t w r + +rm $DIR/testfile1 + +check + +pass diff --git a/src/test/log_basic/TEST1 b/src/test/log_basic/TEST1 new file mode 100755 index 0000000000000000000000000000000000000000..a97587fa6681a5421aa4129abfd9365c4f8745b6 --- /dev/null +++ b/src/test/log_basic/TEST1 @@ -0,0 +1,65 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/log_basic/TEST1 -- unit test for: +# - pmemlog_append +# and: +# - pmemlog_nbyte +# - pmemlog_tell +# - pmemlog_walk +# - pmemlog_rewind +# in case of non-empty pool and +# - pmemlog_check +# - pmemlog_map +# - pmemlog_unmap +# +export UNITTEST_NAME=log_basic/TEST1 +export UNITTEST_NUM=1 + +# standard unit test setup +. ../unittest/unittest.sh + +setup + +rm -f $DIR/testfile1 +touch $DIR/testfile1 + +expect_normal_exit ./log_basic$EXESUFFIX $DIR/testfile1 a n t w r t w + +rm $DIR/testfile1 + +check + +pass + diff --git a/src/test/log_basic/TEST2 b/src/test/log_basic/TEST2 new file mode 100755 index 0000000000000000000000000000000000000000..5f813c192307d0642b22e610c01dc859e5a9403d --- /dev/null +++ b/src/test/log_basic/TEST2 @@ -0,0 +1,65 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/log_basic/TEST2 -- unit test for: +# - pmemlog_appendv +# and: +# - pmemlog_nbyte +# - pmemlog_tell +# - pmemlog_walk +# - pmemlog_rewind +# in case of non-empty pool and +# - pmemlog_check +# - pmemlog_map +# - pmemlog_unmap +# +export UNITTEST_NAME=log_basic/TEST2 +export UNITTEST_NUM=2 + +# standard unit test setup +. ../unittest/unittest.sh + +setup + +rm -f $DIR/testfile1 +touch $DIR/testfile1 + +expect_normal_exit ./log_basic$EXESUFFIX $DIR/testfile1 v n t w r t w + +rm $DIR/testfile1 + +check + +pass + diff --git a/src/test/log_basic/TEST3 b/src/test/log_basic/TEST3 new file mode 100755 index 0000000000000000000000000000000000000000..e4c504fb92c04932a3764e482951b021e021f4c1 --- /dev/null +++ b/src/test/log_basic/TEST3 @@ -0,0 +1,66 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/log_basic/TEST3 -- unit test for: +# - pmemlog_append +# - pmemlog_appendv +# and: +# - pmemlog_nbyte +# - pmemlog_tell +# - pmemlog_walk +# - pmemlog_rewind +# in case of non-empty pool and +# - pmemlog_check +# - pmemlog_map +# - pmemlog_unmap +# +export UNITTEST_NAME=log_basic/TEST3 +export UNITTEST_NUM=3 + +# standard unit test setup +. ../unittest/unittest.sh + +setup + +rm -f $DIR/testfile1 +touch $DIR/testfile1 + +expect_normal_exit ./log_basic$EXESUFFIX $DIR/testfile1 a n t w r t w v n t w r t w + +rm $DIR/testfile1 + +check + +pass + diff --git a/src/test/log_basic/log_basic.c b/src/test/log_basic/log_basic.c new file mode 100644 index 0000000000000000000000000000000000000000..3c16fc8444454aab85c815856c690112f93b2bf8 --- /dev/null +++ b/src/test/log_basic/log_basic.c @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * log_basic.c -- unit test for pmemlog_* + * + * usage: log_basic file operation:... + * + * operations are 'n' or 'a' or 'v' or 't' or 'r' or 'w' + * + */ + +#include "unittest.h" + +/* + * do_nbyte -- call pmemlog_nbyte() & print result + */ +void +do_nbyte(PMEMlog *plp) +{ + size_t nbyte = pmemlog_nbyte(plp); + OUT("usable size: %zu", nbyte); +} + +/* + * do_append -- call pmemlog_append() & print result + */ +void +do_append(PMEMlog *plp) +{ + const char *str[6] = { + "1st test string\n", + "2nd test string\n", + "3rd test string\n", + "4th test string\n", + "5th test string\n", + "6th test string\n" + }; + + for (int i = 0; i < 6; ++i) { + int rv = pmemlog_append(plp, str[i], strlen(str[i])); + switch (rv) { + case 0: + OUT("append str[%i] %s", i, str[i]); + break; + case -1: + OUT("!append str[%i] %s", i, str[i]); + break; + default: + OUT("!append: wrong return value"); + break; + } + } +} + +/* + * do_appendv -- call pmemlog_appendv() & print result + */ +void +do_appendv(PMEMlog *plp) +{ + struct iovec iov[9] = { + { + .iov_base = "1st test string\n", + .iov_len = 16 + }, + { + .iov_base = "2nd test string\n", + .iov_len = 16 + }, + { + .iov_base = "3rd test string\n", + .iov_len = 16 + }, + { + .iov_base = "4th test string\n", + .iov_len = 16 + }, + { + .iov_base = "5th test string\n", + .iov_len = 16 + }, + { + .iov_base = "6th test string\n", + .iov_len = 16 + }, + { + .iov_base = "7th test string\n", + .iov_len = 16 + }, + { + .iov_base = "8th test string\n", + .iov_len = 16 + }, + { + .iov_base = "9th test string\n", + .iov_len = 16 + } + }; + + int rv = pmemlog_appendv(plp, iov, 9); + switch (rv) { + case 0: + OUT("appendv"); + break; + case -1: + OUT("!appendv"); + break; + default: + OUT("!appendv: wrong return value"); + break; + } +} + +/* + * do_tell -- call pmemlog_tell() & print result + */ +void +do_tell(PMEMlog *plp) +{ + off_t tell = pmemlog_tell(plp); + OUT("tell %zu", tell); +} + +/* + * do_rewind -- call pmemlog_rewind() & print result + */ +void +do_rewind(PMEMlog *plp) +{ + pmemlog_rewind(plp); + OUT("rewind"); +} + +/* + * printit -- print out the 'buf' of length 'len'. + * + * It is a walker function for pmemlog_walk + */ +int +printit(const void *buf, size_t len, void *arg) +{ + char *str = alloca(len + 1); + + strncpy(str, buf, len); + str[len] = '\0'; + OUT("%s", str); + + return 1; +} + +/* + * do_walk -- call pmemlog_walk() & print result + * + * pmemlog_walk() is called twice: for chunk size 0 and 16 + */ +void +do_walk(PMEMlog *plp) +{ + pmemlog_walk(plp, 0, printit, NULL); + OUT("walk all at once"); + pmemlog_walk(plp, 16, printit, NULL); + OUT("walk by 16"); +} + +int +main(int argc, char *argv[]) +{ + PMEMlog *plp; + int result; + + START(argc, argv, "log_basic"); + + if (argc < 3) + FATAL("usage: %s file-name op:n|a|v|t|r|w", argv[0]); + + /* check consistency */ + result = pmemlog_check(argv[1]); + if (result < 0) + OUT("!%s: pmemlog_check", argv[1]); + else if (result == 0) + OUT("%s: pmemlog_check: not consistent", argv[1]); + + int fd = OPEN(argv[1], O_RDWR); + + /* pre-allocate 2MB of persistent memory */ + errno = posix_fallocate(fd, (off_t)0, (size_t)(2 * 1024 * 1024)); + if (errno != 0) + FATAL("!posix_fallocate"); + + if ((plp = pmemlog_map(fd)) == NULL) + FATAL("!pmemlog_map: %s", argv[1]); + + close(fd); + + /* go through all arguments one by one */ + for (int arg = 2; arg < argc; arg++) { + /* Scan the character of each argument. */ + if (strchr("navtrw", argv[arg][0]) == NULL || + argv[arg][1] != '\0') + FATAL("op must be n or a or v or t or r or w"); + + switch (argv[arg][0]) { + case 'n': + do_nbyte(plp); + break; + + case 'a': + do_append(plp); + break; + + case 'v': + do_appendv(plp); + break; + + case 't': + do_tell(plp); + break; + + case 'r': + do_rewind(plp); + break; + + case 'w': + do_walk(plp); + break; + } + } + + pmemlog_unmap(plp); + + /* check consistency again */ + result = pmemlog_check(argv[1]); + if (result < 0) + OUT("!%s: pmemlog_check", argv[1]); + else if (result == 0) + OUT("%s: pmemlog_check: not consistent", argv[1]); + + DONE(NULL); +} diff --git a/src/test/log_basic/out0.log.match b/src/test/log_basic/out0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..b21758a451415d1e153a8e1405f41455ee0f1fe3 --- /dev/null +++ b/src/test/log_basic/out0.log.match @@ -0,0 +1,10 @@ +log_basic/TEST0: START: log_basic + ./log_basic$(*) $(*)/testfile1 n t w r +$(*)/testfile1: pmemlog_check: Invalid argument +usable size: 2088960 +tell 0 + +walk all at once +walk by 16 +rewind +log_basic/TEST0: Done diff --git a/src/test/log_basic/out1.log.match b/src/test/log_basic/out1.log.match new file mode 100644 index 0000000000000000000000000000000000000000..57ddee3aa7105a0b54eba06b2af57cb090f7f799 --- /dev/null +++ b/src/test/log_basic/out1.log.match @@ -0,0 +1,44 @@ +log_basic/TEST1: START: log_basic + ./log_basic$(*) $(*)/testfile1 a n t w r t w +$(*)/testfile1: pmemlog_check: Invalid argument +append str[0] 1st test string + +append str[1] 2nd test string + +append str[2] 3rd test string + +append str[3] 4th test string + +append str[4] 5th test string + +append str[5] 6th test string + +usable size: 2088960 +tell 96 +1st test string +2nd test string +3rd test string +4th test string +5th test string +6th test string + +walk all at once +1st test string + +2nd test string + +3rd test string + +4th test string + +5th test string + +6th test string + +walk by 16 +rewind +tell 0 + +walk all at once +walk by 16 +log_basic/TEST1: Done diff --git a/src/test/log_basic/out2.log.match b/src/test/log_basic/out2.log.match new file mode 100644 index 0000000000000000000000000000000000000000..ac8e1fb835ca3822c7ffddf73e2bc602c7382653 --- /dev/null +++ b/src/test/log_basic/out2.log.match @@ -0,0 +1,42 @@ +log_basic/TEST2: START: log_basic + ./log_basic$(*) $(*)/testfile1 v n t w r t w +$(*)/testfile1: pmemlog_check: Invalid argument +appendv +usable size: 2088960 +tell 144 +1st test string +2nd test string +3rd test string +4th test string +5th test string +6th test string +7th test string +8th test string +9th test string + +walk all at once +1st test string + +2nd test string + +3rd test string + +4th test string + +5th test string + +6th test string + +7th test string + +8th test string + +9th test string + +walk by 16 +rewind +tell 0 + +walk all at once +walk by 16 +log_basic/TEST2: Done diff --git a/src/test/log_basic/out3.log.match b/src/test/log_basic/out3.log.match new file mode 100644 index 0000000000000000000000000000000000000000..d05683a077a503d79660506db4861cae913b55c0 --- /dev/null +++ b/src/test/log_basic/out3.log.match @@ -0,0 +1,82 @@ +log_basic/TEST3: START: log_basic + ./log_basic$(*) $(*)/testfile1 a n t w r t w v n t w r t w +$(*)/testfile1: pmemlog_check: Invalid argument +append str[0] 1st test string + +append str[1] 2nd test string + +append str[2] 3rd test string + +append str[3] 4th test string + +append str[4] 5th test string + +append str[5] 6th test string + +usable size: 2088960 +tell 96 +1st test string +2nd test string +3rd test string +4th test string +5th test string +6th test string + +walk all at once +1st test string + +2nd test string + +3rd test string + +4th test string + +5th test string + +6th test string + +walk by 16 +rewind +tell 0 + +walk all at once +walk by 16 +appendv +usable size: 2088960 +tell 144 +1st test string +2nd test string +3rd test string +4th test string +5th test string +6th test string +7th test string +8th test string +9th test string + +walk all at once +1st test string + +2nd test string + +3rd test string + +4th test string + +5th test string + +6th test string + +7th test string + +8th test string + +9th test string + +walk by 16 +rewind +tell 0 + +walk all at once +walk by 16 +log_basic/TEST3: Done diff --git a/src/test/log_recovery/.gitignore b/src/test/log_recovery/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..af57d6618b0051494647c5d6451249f202b5e544 --- /dev/null +++ b/src/test/log_recovery/.gitignore @@ -0,0 +1 @@ +log_recovery diff --git a/src/test/log_recovery/Makefile b/src/test/log_recovery/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..820df40fcbe2266db99c663ec87e6100fdf1dc6b --- /dev/null +++ b/src/test/log_recovery/Makefile @@ -0,0 +1,45 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/log_recovery/Makefile -- build log_recovery unit test +# +vpath %.h ../.. +TARGET = log_recovery +OBJS = log_recovery.o + +include ../Makefile.inc +CFLAGS += -I../.. + +LIBS += -lpmem -lpthread + +log_recovery.o: log_recovery.c diff --git a/src/test/log_recovery/README b/src/test/log_recovery/README new file mode 100644 index 0000000000000000000000000000000000000000..56ee83115b14e0f57495b58092681b6bce89e6ec --- /dev/null +++ b/src/test/log_recovery/README @@ -0,0 +1,20 @@ +Linux NVM Library + +This is src/test/log_recovery/README. + +This directory contains a unit test for pmemlog recovery. It works only +in non-debug mode. + +The program in log_recovery.c takes a filename and an operation as arugments. +An operation is encoded as a character 'a' or 'v'. The first one means that +pmemlog_append() will be used to append data and the second one means that +pmemlog_appendv() will be used to do that. For example: + + ./log_recovery file1 a + +this will call pmemlog_map() on file1, call pmemlog_append() to append +six strings to the log and pmemlog_tell() to check the current write point, +then it will change the memory protection on the metadata area to read-only. +Next, pmemlog_append() is called again and SIGSEGV is caught and reported. +Finally, pmemblk_check() and pmemlog_tell() are called to make sure +there are no partial log entries. diff --git a/src/test/log_recovery/TEST0 b/src/test/log_recovery/TEST0 new file mode 100755 index 0000000000000000000000000000000000000000..e001eef3d1033e3c8bac74f130155a1947c021bc --- /dev/null +++ b/src/test/log_recovery/TEST0 @@ -0,0 +1,57 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/log_recovery/TEST0 -- unit test for pmemlog recovery +# pmemlog_append() is used to append data +# +export UNITTEST_NAME=log_recovery/TEST0 +export UNITTEST_NUM=0 + +# standard unit test setup +. ../unittest/unittest.sh + +require_build_type nondebug static-nondebug + +setup + +rm -f $DIR/testfile1 +touch $DIR/testfile1 + +expect_normal_exit ./log_recovery$EXESUFFIX $DIR/testfile1 a + +rm $DIR/testfile1 + +check + +pass diff --git a/src/test/log_recovery/TEST1 b/src/test/log_recovery/TEST1 new file mode 100755 index 0000000000000000000000000000000000000000..4dc8757f408c97e5d2b31af3acf3dc95326a422f --- /dev/null +++ b/src/test/log_recovery/TEST1 @@ -0,0 +1,57 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/log_recovery/TEST0 -- unit test for pmemlog recovery +# pmemlog_appendv() is used to append data +# +export UNITTEST_NAME=log_recovery/TEST1 +export UNITTEST_NUM=1 + +# standard unit test setup +. ../unittest/unittest.sh + +require_build_type nondebug static-nondebug + +setup + +rm -f $DIR/testfile1 +touch $DIR/testfile1 + +expect_normal_exit ./log_recovery$EXESUFFIX $DIR/testfile1 v + +rm $DIR/testfile1 + +check + +pass diff --git a/src/test/log_recovery/log_recovery.c b/src/test/log_recovery/log_recovery.c new file mode 100644 index 0000000000000000000000000000000000000000..be9818cd453679f5d0dea70f5d81ec1a2f2d3514 --- /dev/null +++ b/src/test/log_recovery/log_recovery.c @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * log_recovery.c -- unit test for pmemlog recovery + * + * usage: log_recovery file operation:... + * + * operation has to be 'a' or 'v' + * + */ + +#include <sys/param.h> +#include "unittest.h" +#include "util.h" +#include "log.h" + +/* + * do_append -- call pmemlog_append() & print result + */ +void +do_append(PMEMlog *plp) +{ + const char *str[6] = { + "1st append string\n", + "2nd append string\n", + "3rd append string\n", + "4th append string\n", + "5th append string\n", + "6th append string\n" + }; + + for (int i = 0; i < 6; ++i) { + int rv = pmemlog_append(plp, str[i], strlen(str[i])); + switch (rv) { + case 0: + OUT("append str[%i] %s", i, str[i]); + break; + case -1: + OUT("!append str[%i] %s", i, str[i]); + break; + default: + OUT("!append: wrong return value"); + break; + } + } +} + +/* + * do_appendv -- call pmemlog_appendv() & print result + */ +void +do_appendv(PMEMlog *plp) +{ + struct iovec iov[9] = { + { + .iov_base = "1st appendv string\n", + .iov_len = 19 + }, + { + .iov_base = "2nd appendv string\n", + .iov_len = 19 + }, + { + .iov_base = "3rd appendv string\n", + .iov_len = 19 + }, + { + .iov_base = "4th appendv string\n", + .iov_len = 19 + }, + { + .iov_base = "5th appendv string\n", + .iov_len = 19 + }, + { + .iov_base = "6th appendv string\n", + .iov_len = 19 + }, + { + .iov_base = "7th appendv string\n", + .iov_len = 19 + }, + { + .iov_base = "8th appendv string\n", + .iov_len = 19 + }, + { + .iov_base = "9th appendv string\n", + .iov_len = 19 + } + }; + + int rv = pmemlog_appendv(plp, iov, 9); + switch (rv) { + case 0: + OUT("appendv"); + break; + case -1: + OUT("!appendv"); + break; + default: + OUT("!appendv: wrong return value"); + break; + } +} + +/* + * do_tell -- call pmemlog_tell() & print result + */ +void +do_tell(PMEMlog *plp) +{ + off_t tell = pmemlog_tell(plp); + OUT("tell %zu", tell); +} + +/* + * printit -- print out the 'buf' of length 'len'. + * + * It is a walker function for pmemlog_walk + */ +int +printit(const void *buf, size_t len, void *arg) +{ + char *str = alloca(len + 1); + + strncpy(str, buf, len); + str[len] = '\0'; + OUT("%s", str); + + return 0; +} + +/* + * do_walk -- call pmemlog_walk() & print result + */ +void +do_walk(PMEMlog *plp) +{ + pmemlog_walk(plp, 0, printit, NULL); + OUT("walk all at once"); +} + +sigjmp_buf Jmp; + +/* + * signal_handler -- called on SIGSEGV + */ +void +signal_handler(int sig) +{ + OUT("signal: %s", strsignal(sig)); + + siglongjmp(Jmp, 1); +} + +int +main(int argc, char *argv[]) +{ + PMEMlog *plp; + int result; + + START(argc, argv, "log_recovery"); + + if (argc != 3) + FATAL("usage: %s file-name op:a|v", argv[0]); + + if (strchr("av", argv[2][0]) == NULL || argv[2][1] != '\0') + FATAL("op must be a or v"); + + int fd = OPEN(argv[1], O_RDWR); + + /* pre-allocate 2MB of persistent memory */ + errno = posix_fallocate(fd, (off_t)0, (size_t)(2 * 1024 * 1024)); + if (errno != 0) + FATAL("!posix_fallocate"); + + if ((plp = pmemlog_map(fd)) == NULL) + FATAL("!pmemlog_map: %s", argv[1]); + + /* append some data */ + if (argv[2][0] == 'a') + do_append(plp); + else + do_appendv(plp); + + /* print out current write point */ + do_tell(plp); + + size_t len = roundup(sizeof (*plp), LOG_FORMAT_DATA_ALIGN); + OUT("write-protecting the metadata, length %zu", len); + MPROTECT(plp, len, PROT_READ); + + /* arrange to catch SEGV */ + struct sigvec v = { 0 }; + v.sv_handler = signal_handler; + SIGVEC(SIGSEGV, &v, NULL); + + if (!sigsetjmp(Jmp, 1)) { + /* try to append more data */ + if (argv[2][0] == 'a') + do_append(plp); + else + do_appendv(plp); + } + + pmemlog_unmap(plp); + + /* check consistency */ + result = pmemlog_check(argv[1]); + if (result < 0) + OUT("!%s: pmemlog_check", argv[1]); + else if (result == 0) + OUT("%s: pmemlog_check: not consistent", argv[1]); + else + OUT("%s: consistent", argv[1]); + + /* map again to print out whole log */ + if ((plp = pmemlog_map(fd)) == NULL) + FATAL("!pmemlog_map: %s", argv[1]); + + /* print out current write point */ + do_tell(plp); + + /* print out whole log */ + do_walk(plp); + + pmemlog_unmap(plp); + + close(fd); + + DONE(NULL); +} diff --git a/src/test/log_recovery/out0.log.match b/src/test/log_recovery/out0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..f64def65485df74bb1a2264914bb931ff2c4a89f --- /dev/null +++ b/src/test/log_recovery/out0.log.match @@ -0,0 +1,28 @@ +log_recovery/TEST0: START: log_recovery + ./log_recovery$(*) $(*)/testfile1 a +append str[0] 1st append string + +append str[1] 2nd append string + +append str[2] 3rd append string + +append str[3] 4th append string + +append str[4] 5th append string + +append str[5] 6th append string + +tell 108 +write-protecting the metadata, length 8192 +signal: Segmentation fault +$(*)/testfile1: consistent +tell 108 +1st append string +2nd append string +3rd append string +4th append string +5th append string +6th append string + +walk all at once +log_recovery/TEST0: Done diff --git a/src/test/log_recovery/out1.log.match b/src/test/log_recovery/out1.log.match new file mode 100644 index 0000000000000000000000000000000000000000..9f6dbf2af51762845ff2c26e1f4bef8eabbed0a7 --- /dev/null +++ b/src/test/log_recovery/out1.log.match @@ -0,0 +1,20 @@ +log_recovery/TEST1: START: log_recovery + ./log_recovery$(*) $(*)/testfile1 v +appendv +tell 171 +write-protecting the metadata, length 8192 +signal: Segmentation fault +$(*)/testfile1: consistent +tell 171 +1st appendv string +2nd appendv string +3rd appendv string +4th appendv string +5th appendv string +6th appendv string +7th appendv string +8th appendv string +9th appendv string + +walk all at once +log_recovery/TEST1: Done diff --git a/src/test/log_walker/.gitignore b/src/test/log_walker/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..110dbec30b559de8b98f9f63d320a27b971747ca --- /dev/null +++ b/src/test/log_walker/.gitignore @@ -0,0 +1 @@ +log_walker diff --git a/src/test/log_walker/Makefile b/src/test/log_walker/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..09b8b112b79dae92a6e60e8a2d63e8b876c634de --- /dev/null +++ b/src/test/log_walker/Makefile @@ -0,0 +1,43 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/log_walker/Makefile -- build log_walker unit test +# +TARGET = log_walker +OBJS = log_walker.o + +include ../Makefile.inc + +LIBS += -lpmem -lpthread + +log_walker.o: log_walker.c diff --git a/src/test/log_walker/README b/src/test/log_walker/README new file mode 100644 index 0000000000000000000000000000000000000000..86ebebb99aa19a9bde78c0daaa23617ca63501bc --- /dev/null +++ b/src/test/log_walker/README @@ -0,0 +1,14 @@ +Linux NVM Library + +This is src/test/log_walker/README. + +This directory contains a unit test to verify pool's write-protection +in debug mode. It works only in debug mode. + +The program in log_walker.c takes only a filename as an arugment. For example: + + ./log_walker file1 + +this calls pmemlog_map() on file1 and pmemlog_append() to append six strings +to the log. Next pmemlog_walk() is called and the walk handler tries to store +to the buffer and SIGSEGV is caught and reported. diff --git a/src/test/log_walker/TEST0 b/src/test/log_walker/TEST0 new file mode 100755 index 0000000000000000000000000000000000000000..5d6165bf8acff1cd288e72edf5ab31259132491b --- /dev/null +++ b/src/test/log_walker/TEST0 @@ -0,0 +1,57 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/log_walker/TEST0 -- unit test to verify pool's write-protection +# in debug mode +# +export UNITTEST_NAME=log_walker/TEST0 +export UNITTEST_NUM=0 + +# standard unit test setup +. ../unittest/unittest.sh + +require_build_type debug static-debug + +setup + +rm -f $DIR/testfile1 +touch $DIR/testfile1 + +expect_normal_exit ./log_walker$EXESUFFIX $DIR/testfile1 + +rm $DIR/testfile1 + +check + +pass diff --git a/src/test/log_walker/log_walker.c b/src/test/log_walker/log_walker.c new file mode 100644 index 0000000000000000000000000000000000000000..a685167f51f23c3eee5c49e24c6c682ad521015a --- /dev/null +++ b/src/test/log_walker/log_walker.c @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * log_walker.c -- unit test to verify pool's write-protection in debug mode + * + * usage: log_walker file + * + */ + +#include <sys/param.h> +#include "unittest.h" + +/* + * do_append -- call pmemlog_append() & print result + */ +void +do_append(PMEMlog *plp) +{ + const char *str[6] = { + "1st append string\n", + "2nd append string\n", + "3rd append string\n", + "4th append string\n", + "5th append string\n", + "6th append string\n" + }; + + for (int i = 0; i < 6; ++i) { + int rv = pmemlog_append(plp, str[i], strlen(str[i])); + switch (rv) { + case 0: + OUT("append str[%i] %s", i, str[i]); + break; + case -1: + OUT("!append str[%i] %s", i, str[i]); + break; + default: + OUT("!append: wrong return value"); + break; + } + } +} + +/* + * try_to_store -- try to store to the buffer 'buf' + * + * It is a walker function for pmemlog_walk + */ +int +try_to_store(const void *buf, size_t len, void *arg) +{ + memset((void *)buf, 0, len); + return 0; +} + +/* + * do_walk -- call pmemlog_walk() & print result + */ +void +do_walk(PMEMlog *plp) +{ + pmemlog_walk(plp, 0, try_to_store, NULL); + OUT("walk all at once"); +} + +sigjmp_buf Jmp; + +/* + * signal_handler -- called on SIGSEGV + */ +void +signal_handler(int sig) +{ + OUT("signal: %s", strsignal(sig)); + + siglongjmp(Jmp, 1); +} + +int +main(int argc, char *argv[]) +{ + PMEMlog *plp; + + START(argc, argv, "log_walker"); + + if (argc != 2) + FATAL("usage: %s file-name", argv[0]); + + int fd = OPEN(argv[1], O_RDWR); + + /* pre-allocate 2MB of persistent memory */ + errno = posix_fallocate(fd, (off_t)0, (size_t)(2 * 1024 * 1024)); + if (errno != 0) + FATAL("!posix_fallocate"); + + if ((plp = pmemlog_map(fd)) == NULL) + FATAL("!pmemlog_map: %s", argv[1]); + + close(fd); + + /* append some data */ + do_append(plp); + + /* arrange to catch SEGV */ + struct sigvec v = { 0 }; + v.sv_handler = signal_handler; + SIGVEC(SIGSEGV, &v, NULL); + + if (!sigsetjmp(Jmp, 1)) { + do_walk(plp); + } + + pmemlog_unmap(plp); + + DONE(NULL); +} diff --git a/src/test/log_walker/out0.log.match b/src/test/log_walker/out0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..a15b486ec09df3f0bedebc138b60a8e002533137 --- /dev/null +++ b/src/test/log_walker/out0.log.match @@ -0,0 +1,16 @@ +log_walker/TEST0: START: log_walker + ./log_walker$(*) $(*)/testfile1 +append str[0] 1st append string + +append str[1] 2nd append string + +append str[2] 3rd append string + +append str[3] 4th append string + +append str[4] 5th append string + +append str[5] 6th append string + +signal: Segmentation fault +log_walker/TEST0: Done diff --git a/src/test/match b/src/test/match new file mode 100755 index 0000000000000000000000000000000000000000..64f8d300f62a51381564842f3d19991f88071e4f --- /dev/null +++ b/src/test/match @@ -0,0 +1,200 @@ +#!/usr/bin/perl -w +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# match -- compare an output file with expected results +# +# usage: match [-adqv] [match-file]... +# +# this script compares the output from a test run, stored in a file, with +# the expected output. comparison is done line-by-line until either all +# lines compare correctly (exit code 0) or a miscompare is found (exit +# code nonzero). +# +# expected output is stored in a ".match" file, which contains a copy of +# the expected output with embedded tokens for things that should not be +# exact matches. the supported tokens are: +# +# $(N) an integer (i.e. one or more decimal digits) +# $(FP) a floating point number +# $(S) ascii string +# $(X) hex number +# $(W) whitespace +# $(*) any string +# $(DD) output of a "dd" run +# $(OPT) line is optional (may be missing, matched if found) +# +# arguments are: +# +# -a find all files of the form "X.match" in the current +# directory and match them again the corresponding file "X". +# +# -d debug -- show lots of debug output +# +# -q don't print any output on mismatch (just exit with result code) +# +# -v verbose -- show every line as it is being matched +# + +use strict; +use Getopt::Std; + +my $Me = $0; +$Me =~ s,.*/,,; + +our ($opt_a, $opt_d, $opt_q, $opt_v); + +$SIG{HUP} = $SIG{INT} = $SIG{TERM} = $SIG{__DIE__} = sub { + die @_ if $^S; + my $errstr = shift; + die "FAIL: $Me: $errstr"; +}; + +sub usage { + my $msg = shift; + + warn "$Me: $msg\n" if $msg; + warn "Usage: $Me [-adqv] [match-file]...\n"; + exit 1; +} + +getopts('adqv') or usage; + +my %match2file; + +if ($opt_a) { + usage("-a and filename arguments are mutually exclusive") + if $#ARGV != -1; + opendir(DIR, '.') or die "opendir: .: $!\n"; + my @matchfiles = grep { /(.*)\.match$/ && -f $1 } readdir(DIR); + closedir(DIR); + die "no files found to process\n" unless @matchfiles; + foreach my $mfile (@matchfiles) { + die "$mfile: $!\n" unless open(F, $mfile); + close(F); + my $ofile = $mfile; + $ofile =~ s/\.match$//; + die "$mfile found but cannot open $ofile: $!\n" + unless open(F, $ofile); + close(F); + $match2file{$mfile} = $ofile; + } +} else { + usage("no match-file arguments found") if $#ARGV == -1; + + # to improve the failure case, check all filename args exist and + # are provided in pairs now, before going through and processing them + foreach my $mfile (@ARGV) { + my $ofile = $mfile; + usage("$mfile: not a .match file") unless + $ofile =~ s/\.match$//; + usage("$mfile: $!") unless open(F, $mfile); + close(F); + usage("$ofile: $!") unless open(F, $ofile); + close(F); + $match2file{$mfile} = $ofile; + } +} + +my $mfile; +my $ofile; +print "Files to be processed:\n" if $opt_v; +foreach $mfile (sort keys %match2file) { + $ofile = $match2file{$mfile}; + print " match-file \"$mfile\" output-file \"$ofile\"\n" + if $opt_v; + match($mfile, $ofile); +} + +exit 0; + +# +# match -- process a match-file, output-file pair +# +sub match { + my ($mfile, $ofile) = @_; + my $pat; + my $output = snarf($ofile); + my $line = 0; + my $opt = 0; + + open(F, $mfile) or die "$mfile: $!\n"; + while (<F>) { + $pat = $_; + $line++; + s/([*+?|{}.\\^\$\[()])/\\$1/g; + s/\\\$\\\(FP\\\)/[-+]?\\d*\\.?\\d+([eE][-+]?\\d+)?/g; + s/\\\$\\\(N\\\)/\\d+/g; + s/\\\$\\\(\\\*\\\)/.*/g; + s/\\\$\\\(S\\\)/\\P{IsC}+/g; + s/\\\$\\\(X\\\)/\\p{IsXDigit}+/g; + s/\\\$\\\(W\\\)/\\s*[^\n]/g; + s/\\\$\\\(DD\\\)/\\d+\\+\\d+ records in\n\\d+\\+\\d+ records out\n\\d+ bytes \\\(\\d+ .B\\\) copied, [.0-9e-]+[^,]*, [.0-9]+ .B.s/g; + if (s/\\\$\\\(OPT\\\)//) { + $opt = 1; + } + print "$mfile:$line matching /$pat/\n" if $opt_v; + print " => /$_/\n" if $opt_d; + print " [$output]\n" if $opt_d; + unless ($output =~ s/^$_//) { + if ($opt) { + print "$mfile:$line skipping optional /$pat/\n" if $opt_v; + $opt = 0; + } else { + die "$mfile:$line did not match pattern: /$pat/\n"; + } + } + } + + if ($output ne '') { + # make it a little more print-friendly... + $output =~ s/\n/\\n/g; + die "line $line: unexpected output: \"$output\"\n"; + } +} + + +# +# snarf -- slurp an entire file into memory +# +sub snarf { + my ($fname) = @_; + local $/; + my $contents; + + open(R, $fname) or die "$fname: $!\n"; + $contents = <R>; + close(R); + + return $contents; +} diff --git a/src/test/pmem_is_pmem/.gitignore b/src/test/pmem_is_pmem/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..7f0a40cb8990126e0aca484e33eaf56c21ebaea0 --- /dev/null +++ b/src/test/pmem_is_pmem/.gitignore @@ -0,0 +1 @@ +pmem_is_pmem diff --git a/src/test/pmem_is_pmem/Makefile b/src/test/pmem_is_pmem/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..46a323f121abc3377c129cd281b0f94527f05462 --- /dev/null +++ b/src/test/pmem_is_pmem/Makefile @@ -0,0 +1,43 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/pmem_is_pmem/Makefile -- build pmem_is_pmem unit test +# +TARGET = pmem_is_pmem +OBJS = pmem_is_pmem.o + +include ../Makefile.inc + +LIBS += -lpmem + +pmem_is_pmem.o: pmem_is_pmem.c diff --git a/src/test/pmem_is_pmem/README b/src/test/pmem_is_pmem/README new file mode 100644 index 0000000000000000000000000000000000000000..423a9200594dbc434d77ee59bbc9f3d2edd0ad95 --- /dev/null +++ b/src/test/pmem_is_pmem/README @@ -0,0 +1,14 @@ +Linux NVM Library + +This is src/test/pmem_is_pmem/README. + +This directory contains a unit test for pmem_is_pmem(). + +The program in pmem_is_pmem.c takes a file as an argument, memory +maps that file, and prints out the return value from pmem_is_pmem() +on the resulting range. For true persistent memory, 1 is the expected +output. 0 is the expected output for everything else. + +The tests in this directory also check that the PMEM_IS_PMEM_FORCE +environment variable can be used to force a specific return value +from pmem_is_pmem(). diff --git a/src/test/pmem_is_pmem/TEST0 b/src/test/pmem_is_pmem/TEST0 new file mode 100755 index 0000000000000000000000000000000000000000..b078038b84521efef323a3ee3cf483c3f00b457b --- /dev/null +++ b/src/test/pmem_is_pmem/TEST0 @@ -0,0 +1,54 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/pmem_is_pmem/TEST0 -- unit test for pmem_is_pmem +# +export UNITTEST_NAME=pmem_is_pmem/TEST0 +export UNITTEST_NUM=0 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type non-pmem + +setup + +rm -f $DIR/testfile1 +truncate -s 2G $DIR/testfile1 +expect_normal_exit ./pmem_is_pmem$EXESUFFIX $DIR/testfile1 +rm $DIR/testfile1 + +check + +pass diff --git a/src/test/pmem_is_pmem/TEST1 b/src/test/pmem_is_pmem/TEST1 new file mode 100755 index 0000000000000000000000000000000000000000..0f1f41c1da5da3070dd6905925649329270aebce --- /dev/null +++ b/src/test/pmem_is_pmem/TEST1 @@ -0,0 +1,54 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/pmem_is_pmem/TEST1 -- unit test for pmem_is_pmem +# +export UNITTEST_NAME=pmem_is_pmem/TEST1 +export UNITTEST_NUM=1 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type pmem + +setup + +rm -f $DIR/testfile1 +truncate -s 2G $DIR/testfile1 +expect_normal_exit ./pmem_is_pmem$EXESUFFIX $DIR/testfile1 +rm $DIR/testfile1 + +check + +pass diff --git a/src/test/pmem_is_pmem/TEST2 b/src/test/pmem_is_pmem/TEST2 new file mode 100755 index 0000000000000000000000000000000000000000..582e8196fd51b7ab35706ddde63a2d8889d152a0 --- /dev/null +++ b/src/test/pmem_is_pmem/TEST2 @@ -0,0 +1,55 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/pmem_is_pmem/TEST2 -- unit test for pmem_is_pmem +# +export UNITTEST_NAME=pmem_is_pmem/TEST2 +export UNITTEST_NUM=2 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type non-pmem + +setup + +rm -f $DIR/testfile1 +truncate -s 2G $DIR/testfile1 +export PMEM_IS_PMEM_FORCE=1 +expect_normal_exit ./pmem_is_pmem$EXESUFFIX $DIR/testfile1 +rm $DIR/testfile1 + +check + +pass diff --git a/src/test/pmem_is_pmem/TEST3 b/src/test/pmem_is_pmem/TEST3 new file mode 100755 index 0000000000000000000000000000000000000000..98ce9434a31e3110cdbfd66b0e0657d643d58e88 --- /dev/null +++ b/src/test/pmem_is_pmem/TEST3 @@ -0,0 +1,55 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/pmem_is_pmem/TEST3 -- unit test for pmem_is_pmem +# +export UNITTEST_NAME=pmem_is_pmem/TEST3 +export UNITTEST_NUM=3 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type pmem + +setup + +rm -f $DIR/testfile1 +truncate -s 2G $DIR/testfile1 +export PMEM_IS_PMEM_FORCE=0 +expect_normal_exit ./pmem_is_pmem$EXESUFFIX $DIR/testfile1 +rm $DIR/testfile1 + +check + +pass diff --git a/src/test/pmem_is_pmem/err0.log.match b/src/test/pmem_is_pmem/err0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/pmem_is_pmem/err1.log.match b/src/test/pmem_is_pmem/err1.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/pmem_is_pmem/err2.log.match b/src/test/pmem_is_pmem/err2.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/pmem_is_pmem/err3.log.match b/src/test/pmem_is_pmem/err3.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/pmem_is_pmem/out0.log.match b/src/test/pmem_is_pmem/out0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..883bd4807db3b39a2888ec03e080a3fab4df366e --- /dev/null +++ b/src/test/pmem_is_pmem/out0.log.match @@ -0,0 +1,4 @@ +pmem_is_pmem/TEST0: START: pmem_is_pmem + ./pmem_is_pmem$(*) $(*)/testfile1 +0 +pmem_is_pmem/TEST0: Done diff --git a/src/test/pmem_is_pmem/out1.log.match b/src/test/pmem_is_pmem/out1.log.match new file mode 100644 index 0000000000000000000000000000000000000000..fa90d11ff99b947b8c297d997321af3e9713d01f --- /dev/null +++ b/src/test/pmem_is_pmem/out1.log.match @@ -0,0 +1,4 @@ +pmem_is_pmem/TEST1: START: pmem_is_pmem + ./pmem_is_pmem$(*) $(*)/testfile1 +1 +pmem_is_pmem/TEST1: Done diff --git a/src/test/pmem_is_pmem/out2.log.match b/src/test/pmem_is_pmem/out2.log.match new file mode 100644 index 0000000000000000000000000000000000000000..3aeb0b58189a2408099c9dfda3527e72674adf99 --- /dev/null +++ b/src/test/pmem_is_pmem/out2.log.match @@ -0,0 +1,4 @@ +pmem_is_pmem/TEST2: START: pmem_is_pmem + ./pmem_is_pmem$(*) $(*)/testfile1 +1 +pmem_is_pmem/TEST2: Done diff --git a/src/test/pmem_is_pmem/out3.log.match b/src/test/pmem_is_pmem/out3.log.match new file mode 100644 index 0000000000000000000000000000000000000000..ce4d0b7046051c571f46dfd421d536595cca1e99 --- /dev/null +++ b/src/test/pmem_is_pmem/out3.log.match @@ -0,0 +1,4 @@ +pmem_is_pmem/TEST3: START: pmem_is_pmem + ./pmem_is_pmem$(*) $(*)/testfile1 +0 +pmem_is_pmem/TEST3: Done diff --git a/src/test/pmem_is_pmem/pmem_is_pmem.c b/src/test/pmem_is_pmem/pmem_is_pmem.c new file mode 100644 index 0000000000000000000000000000000000000000..c20c4f2956cde498b8441c444110e086ce82140c --- /dev/null +++ b/src/test/pmem_is_pmem/pmem_is_pmem.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * pmem_is_pmem.c -- unit test for pmem_is_pmem() + * + * usage: pmem_is_pmem file + */ + +#include "unittest.h" + +int +main(int argc, char *argv[]) +{ + START(argc, argv, "pmem_is_pmem"); + + if (argc != 2) + FATAL("usage: %s file", argv[0]); + + int fd = OPEN(argv[1], O_RDWR); + + struct stat stbuf; + FSTAT(fd, &stbuf); + + void *addr = + MMAP(0, stbuf.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + + close(fd); + + OUT("%d", pmem_is_pmem(addr, stbuf.st_size)); + + DONE(NULL); +} diff --git a/src/test/pmem_is_pmem_proc/.gitignore b/src/test/pmem_is_pmem_proc/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..807dc9d798d07a04e9cc6a4737b72d2712c86971 --- /dev/null +++ b/src/test/pmem_is_pmem_proc/.gitignore @@ -0,0 +1 @@ +pmem_is_pmem_proc diff --git a/src/test/pmem_is_pmem_proc/Makefile b/src/test/pmem_is_pmem_proc/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..c3e3d6f203940babb146bfcb83432bfb6f6c6e26 --- /dev/null +++ b/src/test/pmem_is_pmem_proc/Makefile @@ -0,0 +1,45 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/pmem_is_pmem_proc/Makefile -- build pmem_is_pmem_proc unit test +# +TARGET = pmem_is_pmem_proc +OBJS = pmem_is_pmem_proc.o + +include ../Makefile.inc + +LIBS += -lpmem -ldl +STATIC_DEBUG_LIBS += -ldl +STATIC_NONDEBUG_LIBS += -ldl + +pmem_is_pmem_proc.o: pmem_is_pmem_proc.c diff --git a/src/test/pmem_is_pmem_proc/README b/src/test/pmem_is_pmem_proc/README new file mode 100644 index 0000000000000000000000000000000000000000..101fe8b7a6825e444373e0b737394d138f276183 --- /dev/null +++ b/src/test/pmem_is_pmem_proc/README @@ -0,0 +1,14 @@ +Linux NVM Library + +This is src/test/pmem_is_pmem_proc/README. + +This directory contains a unit test for pmem_is_pmem(). + +The program in pmem_is_pmem_proc.c takes a fake /proc/self/smaps file +as an argument, along with an address and a length. It arranges for +pmem_is_pmem() to open the fake /proc file when looking up the range. + + usage: pmem_is_pmem_proc smaps-file addr len [addr len]... + +addr is interpreted as a hex value, len as a decimal value unless it +starts with 0x. Each addr/len pair is tested against the given smaps-file. diff --git a/src/test/pmem_is_pmem_proc/TEST0 b/src/test/pmem_is_pmem_proc/TEST0 new file mode 100755 index 0000000000000000000000000000000000000000..fa530f960626bfad299edf00b5b0fbc9162d32bc --- /dev/null +++ b/src/test/pmem_is_pmem_proc/TEST0 @@ -0,0 +1,66 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/pmem_is_pmem_proc/TEST0 -- unit test for pmem_is_pmem /proc parsing +# +export UNITTEST_NAME=pmem_is_pmem_proc/TEST0 +export UNITTEST_NUM=0 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local + +setup + +# 7fff77424000 2147479552 +# exactly matches smaps second mm entry, should produce: 1 +# 7fff77424000 2147479553 +# extends past smaps second mm entry, should produce: 0 +# 7fff77424000 8192 +# entirely encompassed by smaps second mm entry, should produce: 1 +# 7fff77423000 8192 +# start at smaps first mm entry, extends into second: should produce: 1 +# 7fff77423000 2147483648 +# exactly matches sum of both mm entries: should produce 1 +expect_normal_exit ./pmem_is_pmem_proc$EXESUFFIX smaps_mm_both\ + 7fff77424000 2147479552\ + 7fff77424000 2147479553\ + 7fff77424000 8192\ + 7fff77423000 8192\ + 7fff77423000 2147483648 + +check + +pass diff --git a/src/test/pmem_is_pmem_proc/TEST1 b/src/test/pmem_is_pmem_proc/TEST1 new file mode 100755 index 0000000000000000000000000000000000000000..65387da1cbbad6fe8377647199c9df579aac45a9 --- /dev/null +++ b/src/test/pmem_is_pmem_proc/TEST1 @@ -0,0 +1,60 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/pmem_is_pmem_proc/TEST1 -- unit test for pmem_is_pmem /proc parsing +# +export UNITTEST_NAME=pmem_is_pmem_proc/TEST1 +export UNITTEST_NUM=1 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local + +setup + +# 7fff77424000 2147479552 +# exactly matches smaps second non-mm entry, should produce: 0 +# 7fff77423000 8192 +# start at smaps first mm entry, extends into second: should produce: 0 +# 7fff77423000 4096 +# exactly matches smaps first mm entry, should produce: 1 +expect_normal_exit ./pmem_is_pmem_proc$EXESUFFIX smaps_mm_first\ + 7fff77424000 2147479552\ + 7fff77423000 8192\ + 7fff77423000 4096 + +check + +pass diff --git a/src/test/pmem_is_pmem_proc/TEST2 b/src/test/pmem_is_pmem_proc/TEST2 new file mode 100755 index 0000000000000000000000000000000000000000..aa1237126b6d0365ea83c90be0d34e235eee2d68 --- /dev/null +++ b/src/test/pmem_is_pmem_proc/TEST2 @@ -0,0 +1,63 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/pmem_is_pmem_proc/TEST2 -- unit test for pmem_is_pmem /proc parsing +# +export UNITTEST_NAME=pmem_is_pmem_proc/TEST2 +export UNITTEST_NUM=2 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local + +setup + +# 7fff77424000 2147479552 +# exactly matches smaps second mm entry, should produce: 1 +# 7fff77428000 10240 +# subset of smaps second mm entry, should produce: 1 +# 7fff77424000 2147479553 +# extends past smaps second mm entry, should produce: 0 +# 7fff77423000 8192 +# start at smaps first mm entry, extends into second: should produce: 0 +expect_normal_exit ./pmem_is_pmem_proc$EXESUFFIX smaps_mm_second\ + 7fff77424000 2147479552\ + 7fff77428000 10240\ + 7fff77424000 2147479553\ + 7fff77423000 8192 + +check + +pass diff --git a/src/test/pmem_is_pmem_proc/TEST3 b/src/test/pmem_is_pmem_proc/TEST3 new file mode 100755 index 0000000000000000000000000000000000000000..ade862e4d56878b7a131255acc07597a25494a8f --- /dev/null +++ b/src/test/pmem_is_pmem_proc/TEST3 @@ -0,0 +1,63 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/pmem_is_pmem_proc/TEST3 -- unit test for pmem_is_pmem /proc parsing +# +export UNITTEST_NAME=pmem_is_pmem_proc/TEST3 +export UNITTEST_NUM=3 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local + +setup + +# 7fff77424000 2147479552 +# exactly matches smaps second mm entry, should produce: 0 +# 7fff77424000 8192 +# entirely encompassed by smaps second mm entry, should produce: 0 +# 7fff77423000 8192 +# start at smaps first mm entry, extends into second: should produce: 0 +# 7fff77423000 4096 +# exactly matches smaps first mm entry, should produce: 0 +expect_normal_exit ./pmem_is_pmem_proc$EXESUFFIX smaps_no_mm\ + 7fff77424000 2147479552\ + 7fff77424000 8192\ + 7fff77423000 8192\ + 7fff77423000 4096 + +check + +pass diff --git a/src/test/pmem_is_pmem_proc/TEST4 b/src/test/pmem_is_pmem_proc/TEST4 new file mode 100755 index 0000000000000000000000000000000000000000..1da91154a52b76ead291c37e9e44ef2144d6f76b --- /dev/null +++ b/src/test/pmem_is_pmem_proc/TEST4 @@ -0,0 +1,63 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/pmem_is_pmem_proc/TEST4 -- unit test for pmem_is_pmem /proc parsing +# +export UNITTEST_NAME=pmem_is_pmem_proc/TEST4 +export UNITTEST_NUM=4 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local + +setup + +# 7fff77424000 2147479552 +# exactly matches smaps second mm entry, should produce: 0 +# 7fff77424000 8192 +# entirely encompassed by smaps second mm entry, should produce: 0 +# 7fff77423000 8192 +# start at smaps first mm entry, extends into second: should produce: 0 +# 7fff77423000 4096 +# exactly matches smaps first mm entry, should produce: 0 +expect_normal_exit ./pmem_is_pmem_proc$EXESUFFIX smaps_no_vmflags\ + 7fff77424000 2147479552\ + 7fff77424000 8192\ + 7fff77423000 8192\ + 7fff77423000 4096 + +check + +pass diff --git a/src/test/pmem_is_pmem_proc/TEST5 b/src/test/pmem_is_pmem_proc/TEST5 new file mode 100755 index 0000000000000000000000000000000000000000..7261abd07af7ac2879b7e3431185f9f4ce5ee348 --- /dev/null +++ b/src/test/pmem_is_pmem_proc/TEST5 @@ -0,0 +1,63 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/pmem_is_pmem_proc/TEST5 -- unit test for pmem_is_pmem /proc parsing +# +export UNITTEST_NAME=pmem_is_pmem_proc/TEST5 +export UNITTEST_NUM=5 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local + +setup + +# 7fff77424000 2147479552 +# exactly matches smaps second mm entry, should produce: 1 +# 7fff77424000 8192 +# entirely encompassed by smaps second mm entry, should produce: 1 +# 7fff77423000 8192 +# start at smaps first mm entry, extends into second: should produce: 0 +# 7fff77423000 4096 +# exactly matches smaps first mm entry, should produce: 0 +expect_normal_exit ./pmem_is_pmem_proc$EXESUFFIX smaps_unexp_vmflags\ + 7fff77424000 2147479552\ + 7fff77424000 8192\ + 7fff77423000 8192\ + 7fff77423000 4096 + +check + +pass diff --git a/src/test/pmem_is_pmem_proc/err0.log.match b/src/test/pmem_is_pmem_proc/err0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/pmem_is_pmem_proc/err1.log.match b/src/test/pmem_is_pmem_proc/err1.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/pmem_is_pmem_proc/err2.log.match b/src/test/pmem_is_pmem_proc/err2.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/pmem_is_pmem_proc/err3.log.match b/src/test/pmem_is_pmem_proc/err3.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/pmem_is_pmem_proc/err4.log.match b/src/test/pmem_is_pmem_proc/err4.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/pmem_is_pmem_proc/err5.log.match b/src/test/pmem_is_pmem_proc/err5.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/pmem_is_pmem_proc/out0.log.match b/src/test/pmem_is_pmem_proc/out0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..db4a821242739e8ad6ad5f8d5014a5ae164c3947 --- /dev/null +++ b/src/test/pmem_is_pmem_proc/out0.log.match @@ -0,0 +1,13 @@ +pmem_is_pmem_proc/TEST0: START: pmem_is_pmem_proc + ./pmem_is_pmem_proc$(*) smaps_mm_both 7fff77424000 2147479552 7fff77424000 2147479553 7fff77424000 8192 7fff77423000 8192 7fff77423000 2147483648 +redirecting /proc/self/smaps to smaps_mm_both +addr 0x7fff77424000, len 2147479552: 1 +redirecting /proc/self/smaps to smaps_mm_both +addr 0x7fff77424000, len 2147479553: 0 +redirecting /proc/self/smaps to smaps_mm_both +addr 0x7fff77424000, len 8192: 1 +redirecting /proc/self/smaps to smaps_mm_both +addr 0x7fff77423000, len 8192: 1 +redirecting /proc/self/smaps to smaps_mm_both +addr 0x7fff77423000, len 2147483648: 1 +pmem_is_pmem_proc/TEST0: Done diff --git a/src/test/pmem_is_pmem_proc/out1.log.match b/src/test/pmem_is_pmem_proc/out1.log.match new file mode 100644 index 0000000000000000000000000000000000000000..8260536e4067df7783396f58b05fdad6a5ba8767 --- /dev/null +++ b/src/test/pmem_is_pmem_proc/out1.log.match @@ -0,0 +1,9 @@ +pmem_is_pmem_proc/TEST1: START: pmem_is_pmem_proc + ./pmem_is_pmem_proc$(*) smaps_mm_first 7fff77424000 2147479552 7fff77423000 8192 7fff77423000 4096 +redirecting /proc/self/smaps to smaps_mm_first +addr 0x7fff77424000, len 2147479552: 0 +redirecting /proc/self/smaps to smaps_mm_first +addr 0x7fff77423000, len 8192: 0 +redirecting /proc/self/smaps to smaps_mm_first +addr 0x7fff77423000, len 4096: 1 +pmem_is_pmem_proc/TEST1: Done diff --git a/src/test/pmem_is_pmem_proc/out2.log.match b/src/test/pmem_is_pmem_proc/out2.log.match new file mode 100644 index 0000000000000000000000000000000000000000..970f6ff4689f3223224bf7e4f9f6ed12e54ffe22 --- /dev/null +++ b/src/test/pmem_is_pmem_proc/out2.log.match @@ -0,0 +1,11 @@ +pmem_is_pmem_proc/TEST2: START: pmem_is_pmem_proc + ./pmem_is_pmem_proc$(*) smaps_mm_second 7fff77424000 2147479552 7fff77428000 10240 7fff77424000 2147479553 7fff77423000 8192 +redirecting /proc/self/smaps to smaps_mm_second +addr 0x7fff77424000, len 2147479552: 1 +redirecting /proc/self/smaps to smaps_mm_second +addr 0x7fff77428000, len 10240: 1 +redirecting /proc/self/smaps to smaps_mm_second +addr 0x7fff77424000, len 2147479553: 0 +redirecting /proc/self/smaps to smaps_mm_second +addr 0x7fff77423000, len 8192: 0 +pmem_is_pmem_proc/TEST2: Done diff --git a/src/test/pmem_is_pmem_proc/out3.log.match b/src/test/pmem_is_pmem_proc/out3.log.match new file mode 100644 index 0000000000000000000000000000000000000000..678df21bc7f8e3a2711576d0b7d89d0d89e25082 --- /dev/null +++ b/src/test/pmem_is_pmem_proc/out3.log.match @@ -0,0 +1,11 @@ +pmem_is_pmem_proc/TEST3: START: pmem_is_pmem_proc + ./pmem_is_pmem_proc$(*) smaps_no_mm 7fff77424000 2147479552 7fff77424000 8192 7fff77423000 8192 7fff77423000 4096 +redirecting /proc/self/smaps to smaps_no_mm +addr 0x7fff77424000, len 2147479552: 0 +redirecting /proc/self/smaps to smaps_no_mm +addr 0x7fff77424000, len 8192: 0 +redirecting /proc/self/smaps to smaps_no_mm +addr 0x7fff77423000, len 8192: 0 +redirecting /proc/self/smaps to smaps_no_mm +addr 0x7fff77423000, len 4096: 0 +pmem_is_pmem_proc/TEST3: Done diff --git a/src/test/pmem_is_pmem_proc/out4.log.match b/src/test/pmem_is_pmem_proc/out4.log.match new file mode 100644 index 0000000000000000000000000000000000000000..261ccee7db35df8037e9ec1f8905069887ef8b9a --- /dev/null +++ b/src/test/pmem_is_pmem_proc/out4.log.match @@ -0,0 +1,11 @@ +pmem_is_pmem_proc/TEST4: START: pmem_is_pmem_proc + ./pmem_is_pmem_proc$(*) smaps_no_vmflags 7fff77424000 2147479552 7fff77424000 8192 7fff77423000 8192 7fff77423000 4096 +redirecting /proc/self/smaps to smaps_no_vmflags +addr 0x7fff77424000, len 2147479552: 0 +redirecting /proc/self/smaps to smaps_no_vmflags +addr 0x7fff77424000, len 8192: 0 +redirecting /proc/self/smaps to smaps_no_vmflags +addr 0x7fff77423000, len 8192: 0 +redirecting /proc/self/smaps to smaps_no_vmflags +addr 0x7fff77423000, len 4096: 0 +pmem_is_pmem_proc/TEST4: Done diff --git a/src/test/pmem_is_pmem_proc/out5.log.match b/src/test/pmem_is_pmem_proc/out5.log.match new file mode 100644 index 0000000000000000000000000000000000000000..289a73340d7ed8b94d9a64159aba9686b236512e --- /dev/null +++ b/src/test/pmem_is_pmem_proc/out5.log.match @@ -0,0 +1,11 @@ +pmem_is_pmem_proc/TEST5: START: pmem_is_pmem_proc + ./pmem_is_pmem_proc$(*) smaps_unexp_vmflags 7fff77424000 2147479552 7fff77424000 8192 7fff77423000 8192 7fff77423000 4096 +redirecting /proc/self/smaps to smaps_unexp_vmflags +addr 0x7fff77424000, len 2147479552: 1 +redirecting /proc/self/smaps to smaps_unexp_vmflags +addr 0x7fff77424000, len 8192: 1 +redirecting /proc/self/smaps to smaps_unexp_vmflags +addr 0x7fff77423000, len 8192: 0 +redirecting /proc/self/smaps to smaps_unexp_vmflags +addr 0x7fff77423000, len 4096: 0 +pmem_is_pmem_proc/TEST5: Done diff --git a/src/test/pmem_is_pmem_proc/pmem_is_pmem_proc.c b/src/test/pmem_is_pmem_proc/pmem_is_pmem_proc.c new file mode 100644 index 0000000000000000000000000000000000000000..80bc291ec590c7fc48bd6039b84965fb9561eaae --- /dev/null +++ b/src/test/pmem_is_pmem_proc/pmem_is_pmem_proc.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * pmem_is_pmem_proc.c -- unit test for pmem_is_pmem() /proc parsing + * + * usage: pmem_is_pmem_proc file addr len [addr len]... + */ + +#define _GNU_SOURCE +#include "unittest.h" + +#include <dlfcn.h> + +char *Sfile; + +/* + * fopen -- interpose on libc fopen() + * + * This catches opens to /proc/self/smaps and sends them to the fake smaps + * file being tested. + */ +FILE * +fopen(const char *path, const char *mode) +{ + static FILE *(*fopen_ptr)(const char *path, const char *mode); + + if (strcmp(path, "/proc/self/smaps") == 0) { + OUT("redirecting /proc/self/smaps to %s", Sfile); + path = Sfile; + } + + if (fopen_ptr == NULL) + fopen_ptr = dlsym(RTLD_NEXT, "fopen"); + + return (*fopen_ptr)(path, mode); +} + +int +main(int argc, char *argv[]) +{ + START(argc, argv, "pmem_is_pmem_proc"); + + if (argc < 4 || argc % 2) + FATAL("usage: %s file addr len [addr len]...", argv[0]); + + Sfile = argv[1]; + + for (int arg = 2; arg < argc; arg += 2) { + void *addr; + size_t len; + + addr = (void *)strtoull(argv[arg], NULL, 16); + len = (size_t)strtoull(argv[arg + 1], NULL, 10); + OUT("addr %p, len %zu: %d", addr, len, pmem_is_pmem(addr, len)); + } + + DONE(NULL); +} diff --git a/src/test/pmem_is_pmem_proc/smaps_mm_both b/src/test/pmem_is_pmem_proc/smaps_mm_both new file mode 100644 index 0000000000000000000000000000000000000000..85c1a3551fa44df80b80aea9c968e9e5811cac22 --- /dev/null +++ b/src/test/pmem_is_pmem_proc/smaps_mm_both @@ -0,0 +1,482 @@ +00400000-00406000 r-xp 00000000 08:01 2366593 /some/path/src/test/pmem_map/pmem_map +Size: 24 kB +Rss: 20 kB +Pss: 20 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 16 kB +Private_Dirty: 4 kB +Referenced: 20 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +00605000-00606000 rw-p 00005000 08:01 2366593 /some/path/src/test/pmem_map/pmem_map +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +00606000-00627000 rw-p 00000000 00:00 0 [heap] +Size: 132 kB +Rss: 8 kB +Pss: 8 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 8 kB +Referenced: 8 kB +Anonymous: 8 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7fff77423000-7fff77424000 ---s 00000000 08:01 2366604 /some/path/src/test/pmem_map/testfile1 +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 4 kB +Private_Dirty: 0 kB +Referenced: 4 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +VmFlags: rd ex mm mr mw me dw sd +7fff77424000-7ffff7423000 r--s 00001000 08:01 2366604 /some/path/src/test/pmem_map/testfile1 +Size: 2097148 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 4 kB +Private_Dirty: 0 kB +Referenced: 4 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +VmFlags: rd ex mm mr mw me dw sd +7ffff7423000-7ffff75a5000 r-xp 00000000 08:01 1844444 /lib/x86_64-linux-gnu/libc-2.13.so +Size: 1544 kB +Rss: 364 kB +Pss: 53 kB +Shared_Clean: 360 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 364 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff75a5000-7ffff77a4000 ---p 00182000 08:01 1844444 /lib/x86_64-linux-gnu/libc-2.13.so +Size: 2044 kB +Rss: 0 kB +Pss: 0 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 0 kB +Referenced: 0 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff77a4000-7ffff77a8000 r--p 00181000 08:01 1844444 /lib/x86_64-linux-gnu/libc-2.13.so +Size: 16 kB +Rss: 16 kB +Pss: 16 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 16 kB +Referenced: 16 kB +Anonymous: 16 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff77a8000-7ffff77a9000 rw-p 00185000 08:01 1844444 /lib/x86_64-linux-gnu/libc-2.13.so +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff77a9000-7ffff77ae000 rw-p 00000000 00:00 0 +Size: 20 kB +Rss: 16 kB +Pss: 16 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 16 kB +Referenced: 16 kB +Anonymous: 16 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff77ae000-7ffff77c5000 r-xp 00000000 08:01 1845832 /lib/x86_64-linux-gnu/libpthread-2.13.so +Size: 92 kB +Rss: 52 kB +Pss: 14 kB +Shared_Clean: 44 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 8 kB +Referenced: 52 kB +Anonymous: 8 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff77c5000-7ffff79c4000 ---p 00017000 08:01 1845832 /lib/x86_64-linux-gnu/libpthread-2.13.so +Size: 2044 kB +Rss: 0 kB +Pss: 0 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 0 kB +Referenced: 0 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff79c4000-7ffff79c5000 r--p 00016000 08:01 1845832 /lib/x86_64-linux-gnu/libpthread-2.13.so +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff79c5000-7ffff79c6000 rw-p 00017000 08:01 1845832 /lib/x86_64-linux-gnu/libpthread-2.13.so +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff79c6000-7ffff79ca000 rw-p 00000000 00:00 0 +Size: 16 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff79ca000-7ffff79d7000 r-xp 00000000 08:01 2366292 /some/path/src/debug/libpmem.so +Size: 52 kB +Rss: 28 kB +Pss: 28 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 28 kB +Private_Dirty: 0 kB +Referenced: 28 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff79d7000-7ffff7bd6000 ---p 0000d000 08:01 2366292 /some/path/src/debug/libpmem.so +Size: 2044 kB +Rss: 0 kB +Pss: 0 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 0 kB +Referenced: 0 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7bd6000-7ffff7bd7000 rw-p 0000c000 08:01 2366292 /some/path/src/debug/libpmem.so +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7bd7000-7ffff7bd8000 rw-p 00000000 00:00 0 +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7bd8000-7ffff7bdc000 r-xp 00000000 08:01 1835968 /lib/x86_64-linux-gnu/libuuid.so.1.3.0 +Size: 16 kB +Rss: 12 kB +Pss: 12 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 12 kB +Private_Dirty: 0 kB +Referenced: 12 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7bdc000-7ffff7ddb000 ---p 00004000 08:01 1835968 /lib/x86_64-linux-gnu/libuuid.so.1.3.0 +Size: 2044 kB +Rss: 0 kB +Pss: 0 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 0 kB +Referenced: 0 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ddb000-7ffff7ddc000 r--p 00003000 08:01 1835968 /lib/x86_64-linux-gnu/libuuid.so.1.3.0 +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ddc000-7ffff7ddd000 rw-p 00004000 08:01 1835968 /lib/x86_64-linux-gnu/libuuid.so.1.3.0 +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ddd000-7ffff7dfd000 r-xp 00000000 08:01 1844132 /lib/x86_64-linux-gnu/ld-2.13.so +Size: 128 kB +Rss: 108 kB +Pss: 33 kB +Shared_Clean: 104 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 108 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7fe3000-7ffff7fe7000 rw-p 00000000 00:00 0 +Size: 16 kB +Rss: 16 kB +Pss: 16 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 16 kB +Referenced: 16 kB +Anonymous: 16 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ff6000-7ffff7ffb000 rw-p 00000000 00:00 0 +Size: 20 kB +Rss: 20 kB +Pss: 20 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 20 kB +Referenced: 20 kB +Anonymous: 20 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ffb000-7ffff7ffc000 r-xp 00000000 00:00 0 [vdso] +Size: 4 kB +Rss: 4 kB +Pss: 0 kB +Shared_Clean: 4 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 0 kB +Referenced: 4 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ffc000-7ffff7ffd000 r--p 0001f000 08:01 1844132 /lib/x86_64-linux-gnu/ld-2.13.so +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ffd000-7ffff7ffe000 rw-p 00020000 08:01 1844132 /lib/x86_64-linux-gnu/ld-2.13.so +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ffe000-7ffff7fff000 rw-p 00000000 00:00 0 +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffffffde000-7ffffffff000 rw-p 00000000 00:00 0 [stack] +Size: 136 kB +Rss: 24 kB +Pss: 24 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 24 kB +Referenced: 24 kB +Anonymous: 24 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall] +Size: 4 kB +Rss: 0 kB +Pss: 0 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 0 kB +Referenced: 0 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB diff --git a/src/test/pmem_is_pmem_proc/smaps_mm_first b/src/test/pmem_is_pmem_proc/smaps_mm_first new file mode 100644 index 0000000000000000000000000000000000000000..e9e385982ab8b61d2754057c35f43a0b745ee7ff --- /dev/null +++ b/src/test/pmem_is_pmem_proc/smaps_mm_first @@ -0,0 +1,482 @@ +00400000-00406000 r-xp 00000000 08:01 2366593 /some/path/src/test/pmem_map/pmem_map +Size: 24 kB +Rss: 20 kB +Pss: 20 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 16 kB +Private_Dirty: 4 kB +Referenced: 20 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +00605000-00606000 rw-p 00005000 08:01 2366593 /some/path/src/test/pmem_map/pmem_map +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +00606000-00627000 rw-p 00000000 00:00 0 [heap] +Size: 132 kB +Rss: 8 kB +Pss: 8 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 8 kB +Referenced: 8 kB +Anonymous: 8 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7fff77423000-7fff77424000 ---s 00000000 08:01 2366604 /some/path/src/test/pmem_map/testfile1 +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 4 kB +Private_Dirty: 0 kB +Referenced: 4 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +VmFlags: rd ex mm mr mw me dw sd +7fff77424000-7ffff7423000 r--s 00001000 08:01 2366604 /some/path/src/test/pmem_map/testfile1 +Size: 2097148 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 4 kB +Private_Dirty: 0 kB +Referenced: 4 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +VmFlags: rd ex mr mw me dw sd +7ffff7423000-7ffff75a5000 r-xp 00000000 08:01 1844444 /lib/x86_64-linux-gnu/libc-2.13.so +Size: 1544 kB +Rss: 364 kB +Pss: 53 kB +Shared_Clean: 360 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 364 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff75a5000-7ffff77a4000 ---p 00182000 08:01 1844444 /lib/x86_64-linux-gnu/libc-2.13.so +Size: 2044 kB +Rss: 0 kB +Pss: 0 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 0 kB +Referenced: 0 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff77a4000-7ffff77a8000 r--p 00181000 08:01 1844444 /lib/x86_64-linux-gnu/libc-2.13.so +Size: 16 kB +Rss: 16 kB +Pss: 16 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 16 kB +Referenced: 16 kB +Anonymous: 16 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff77a8000-7ffff77a9000 rw-p 00185000 08:01 1844444 /lib/x86_64-linux-gnu/libc-2.13.so +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff77a9000-7ffff77ae000 rw-p 00000000 00:00 0 +Size: 20 kB +Rss: 16 kB +Pss: 16 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 16 kB +Referenced: 16 kB +Anonymous: 16 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff77ae000-7ffff77c5000 r-xp 00000000 08:01 1845832 /lib/x86_64-linux-gnu/libpthread-2.13.so +Size: 92 kB +Rss: 52 kB +Pss: 14 kB +Shared_Clean: 44 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 8 kB +Referenced: 52 kB +Anonymous: 8 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff77c5000-7ffff79c4000 ---p 00017000 08:01 1845832 /lib/x86_64-linux-gnu/libpthread-2.13.so +Size: 2044 kB +Rss: 0 kB +Pss: 0 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 0 kB +Referenced: 0 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff79c4000-7ffff79c5000 r--p 00016000 08:01 1845832 /lib/x86_64-linux-gnu/libpthread-2.13.so +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff79c5000-7ffff79c6000 rw-p 00017000 08:01 1845832 /lib/x86_64-linux-gnu/libpthread-2.13.so +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff79c6000-7ffff79ca000 rw-p 00000000 00:00 0 +Size: 16 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff79ca000-7ffff79d7000 r-xp 00000000 08:01 2366292 /some/path/src/debug/libpmem.so +Size: 52 kB +Rss: 28 kB +Pss: 28 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 28 kB +Private_Dirty: 0 kB +Referenced: 28 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff79d7000-7ffff7bd6000 ---p 0000d000 08:01 2366292 /some/path/src/debug/libpmem.so +Size: 2044 kB +Rss: 0 kB +Pss: 0 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 0 kB +Referenced: 0 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7bd6000-7ffff7bd7000 rw-p 0000c000 08:01 2366292 /some/path/src/debug/libpmem.so +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7bd7000-7ffff7bd8000 rw-p 00000000 00:00 0 +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7bd8000-7ffff7bdc000 r-xp 00000000 08:01 1835968 /lib/x86_64-linux-gnu/libuuid.so.1.3.0 +Size: 16 kB +Rss: 12 kB +Pss: 12 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 12 kB +Private_Dirty: 0 kB +Referenced: 12 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7bdc000-7ffff7ddb000 ---p 00004000 08:01 1835968 /lib/x86_64-linux-gnu/libuuid.so.1.3.0 +Size: 2044 kB +Rss: 0 kB +Pss: 0 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 0 kB +Referenced: 0 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ddb000-7ffff7ddc000 r--p 00003000 08:01 1835968 /lib/x86_64-linux-gnu/libuuid.so.1.3.0 +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ddc000-7ffff7ddd000 rw-p 00004000 08:01 1835968 /lib/x86_64-linux-gnu/libuuid.so.1.3.0 +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ddd000-7ffff7dfd000 r-xp 00000000 08:01 1844132 /lib/x86_64-linux-gnu/ld-2.13.so +Size: 128 kB +Rss: 108 kB +Pss: 33 kB +Shared_Clean: 104 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 108 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7fe3000-7ffff7fe7000 rw-p 00000000 00:00 0 +Size: 16 kB +Rss: 16 kB +Pss: 16 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 16 kB +Referenced: 16 kB +Anonymous: 16 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ff6000-7ffff7ffb000 rw-p 00000000 00:00 0 +Size: 20 kB +Rss: 20 kB +Pss: 20 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 20 kB +Referenced: 20 kB +Anonymous: 20 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ffb000-7ffff7ffc000 r-xp 00000000 00:00 0 [vdso] +Size: 4 kB +Rss: 4 kB +Pss: 0 kB +Shared_Clean: 4 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 0 kB +Referenced: 4 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ffc000-7ffff7ffd000 r--p 0001f000 08:01 1844132 /lib/x86_64-linux-gnu/ld-2.13.so +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ffd000-7ffff7ffe000 rw-p 00020000 08:01 1844132 /lib/x86_64-linux-gnu/ld-2.13.so +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ffe000-7ffff7fff000 rw-p 00000000 00:00 0 +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffffffde000-7ffffffff000 rw-p 00000000 00:00 0 [stack] +Size: 136 kB +Rss: 24 kB +Pss: 24 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 24 kB +Referenced: 24 kB +Anonymous: 24 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall] +Size: 4 kB +Rss: 0 kB +Pss: 0 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 0 kB +Referenced: 0 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB diff --git a/src/test/pmem_is_pmem_proc/smaps_mm_second b/src/test/pmem_is_pmem_proc/smaps_mm_second new file mode 100644 index 0000000000000000000000000000000000000000..41240eb25c65248fe63601361e331c99ceaff6ab --- /dev/null +++ b/src/test/pmem_is_pmem_proc/smaps_mm_second @@ -0,0 +1,482 @@ +00400000-00406000 r-xp 00000000 08:01 2366593 /some/path/src/test/pmem_map/pmem_map +Size: 24 kB +Rss: 20 kB +Pss: 20 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 16 kB +Private_Dirty: 4 kB +Referenced: 20 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +00605000-00606000 rw-p 00005000 08:01 2366593 /some/path/src/test/pmem_map/pmem_map +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +00606000-00627000 rw-p 00000000 00:00 0 [heap] +Size: 132 kB +Rss: 8 kB +Pss: 8 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 8 kB +Referenced: 8 kB +Anonymous: 8 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7fff77423000-7fff77424000 ---s 00000000 08:01 2366604 /some/path/src/test/pmem_map/testfile1 +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 4 kB +Private_Dirty: 0 kB +Referenced: 4 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +VmFlags: rd ex mr mw me dw sd +7fff77424000-7ffff7423000 r--s 00001000 08:01 2366604 /some/path/src/test/pmem_map/testfile1 +Size: 2097148 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 4 kB +Private_Dirty: 0 kB +Referenced: 4 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +VmFlags: rd ex mm mr mw me dw sd +7ffff7423000-7ffff75a5000 r-xp 00000000 08:01 1844444 /lib/x86_64-linux-gnu/libc-2.13.so +Size: 1544 kB +Rss: 364 kB +Pss: 53 kB +Shared_Clean: 360 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 364 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff75a5000-7ffff77a4000 ---p 00182000 08:01 1844444 /lib/x86_64-linux-gnu/libc-2.13.so +Size: 2044 kB +Rss: 0 kB +Pss: 0 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 0 kB +Referenced: 0 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff77a4000-7ffff77a8000 r--p 00181000 08:01 1844444 /lib/x86_64-linux-gnu/libc-2.13.so +Size: 16 kB +Rss: 16 kB +Pss: 16 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 16 kB +Referenced: 16 kB +Anonymous: 16 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff77a8000-7ffff77a9000 rw-p 00185000 08:01 1844444 /lib/x86_64-linux-gnu/libc-2.13.so +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff77a9000-7ffff77ae000 rw-p 00000000 00:00 0 +Size: 20 kB +Rss: 16 kB +Pss: 16 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 16 kB +Referenced: 16 kB +Anonymous: 16 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff77ae000-7ffff77c5000 r-xp 00000000 08:01 1845832 /lib/x86_64-linux-gnu/libpthread-2.13.so +Size: 92 kB +Rss: 52 kB +Pss: 14 kB +Shared_Clean: 44 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 8 kB +Referenced: 52 kB +Anonymous: 8 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff77c5000-7ffff79c4000 ---p 00017000 08:01 1845832 /lib/x86_64-linux-gnu/libpthread-2.13.so +Size: 2044 kB +Rss: 0 kB +Pss: 0 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 0 kB +Referenced: 0 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff79c4000-7ffff79c5000 r--p 00016000 08:01 1845832 /lib/x86_64-linux-gnu/libpthread-2.13.so +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff79c5000-7ffff79c6000 rw-p 00017000 08:01 1845832 /lib/x86_64-linux-gnu/libpthread-2.13.so +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff79c6000-7ffff79ca000 rw-p 00000000 00:00 0 +Size: 16 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff79ca000-7ffff79d7000 r-xp 00000000 08:01 2366292 /some/path/src/debug/libpmem.so +Size: 52 kB +Rss: 28 kB +Pss: 28 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 28 kB +Private_Dirty: 0 kB +Referenced: 28 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff79d7000-7ffff7bd6000 ---p 0000d000 08:01 2366292 /some/path/src/debug/libpmem.so +Size: 2044 kB +Rss: 0 kB +Pss: 0 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 0 kB +Referenced: 0 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7bd6000-7ffff7bd7000 rw-p 0000c000 08:01 2366292 /some/path/src/debug/libpmem.so +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7bd7000-7ffff7bd8000 rw-p 00000000 00:00 0 +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7bd8000-7ffff7bdc000 r-xp 00000000 08:01 1835968 /lib/x86_64-linux-gnu/libuuid.so.1.3.0 +Size: 16 kB +Rss: 12 kB +Pss: 12 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 12 kB +Private_Dirty: 0 kB +Referenced: 12 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7bdc000-7ffff7ddb000 ---p 00004000 08:01 1835968 /lib/x86_64-linux-gnu/libuuid.so.1.3.0 +Size: 2044 kB +Rss: 0 kB +Pss: 0 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 0 kB +Referenced: 0 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ddb000-7ffff7ddc000 r--p 00003000 08:01 1835968 /lib/x86_64-linux-gnu/libuuid.so.1.3.0 +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ddc000-7ffff7ddd000 rw-p 00004000 08:01 1835968 /lib/x86_64-linux-gnu/libuuid.so.1.3.0 +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ddd000-7ffff7dfd000 r-xp 00000000 08:01 1844132 /lib/x86_64-linux-gnu/ld-2.13.so +Size: 128 kB +Rss: 108 kB +Pss: 33 kB +Shared_Clean: 104 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 108 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7fe3000-7ffff7fe7000 rw-p 00000000 00:00 0 +Size: 16 kB +Rss: 16 kB +Pss: 16 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 16 kB +Referenced: 16 kB +Anonymous: 16 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ff6000-7ffff7ffb000 rw-p 00000000 00:00 0 +Size: 20 kB +Rss: 20 kB +Pss: 20 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 20 kB +Referenced: 20 kB +Anonymous: 20 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ffb000-7ffff7ffc000 r-xp 00000000 00:00 0 [vdso] +Size: 4 kB +Rss: 4 kB +Pss: 0 kB +Shared_Clean: 4 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 0 kB +Referenced: 4 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ffc000-7ffff7ffd000 r--p 0001f000 08:01 1844132 /lib/x86_64-linux-gnu/ld-2.13.so +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ffd000-7ffff7ffe000 rw-p 00020000 08:01 1844132 /lib/x86_64-linux-gnu/ld-2.13.so +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ffe000-7ffff7fff000 rw-p 00000000 00:00 0 +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffffffde000-7ffffffff000 rw-p 00000000 00:00 0 [stack] +Size: 136 kB +Rss: 24 kB +Pss: 24 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 24 kB +Referenced: 24 kB +Anonymous: 24 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall] +Size: 4 kB +Rss: 0 kB +Pss: 0 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 0 kB +Referenced: 0 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB diff --git a/src/test/pmem_is_pmem_proc/smaps_no_mm b/src/test/pmem_is_pmem_proc/smaps_no_mm new file mode 100644 index 0000000000000000000000000000000000000000..b05a0825e3eb70de90812ed4f262c8e018c7fae0 --- /dev/null +++ b/src/test/pmem_is_pmem_proc/smaps_no_mm @@ -0,0 +1,482 @@ +00400000-00406000 r-xp 00000000 08:01 2366593 /some/path/src/test/pmem_map/pmem_map +Size: 24 kB +Rss: 20 kB +Pss: 20 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 16 kB +Private_Dirty: 4 kB +Referenced: 20 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +00605000-00606000 rw-p 00005000 08:01 2366593 /some/path/src/test/pmem_map/pmem_map +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +00606000-00627000 rw-p 00000000 00:00 0 [heap] +Size: 132 kB +Rss: 8 kB +Pss: 8 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 8 kB +Referenced: 8 kB +Anonymous: 8 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7fff77423000-7fff77424000 ---s 00000000 08:01 2366604 /some/path/src/test/pmem_map/testfile1 +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 4 kB +Private_Dirty: 0 kB +Referenced: 4 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +VmFlags: rd ex mr mw me dw sd +7fff77424000-7ffff7423000 r--s 00001000 08:01 2366604 /some/path/src/test/pmem_map/testfile1 +Size: 2097148 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 4 kB +Private_Dirty: 0 kB +Referenced: 4 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +VmFlags: rd ex mr mw me dw sd +7ffff7423000-7ffff75a5000 r-xp 00000000 08:01 1844444 /lib/x86_64-linux-gnu/libc-2.13.so +Size: 1544 kB +Rss: 364 kB +Pss: 53 kB +Shared_Clean: 360 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 364 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff75a5000-7ffff77a4000 ---p 00182000 08:01 1844444 /lib/x86_64-linux-gnu/libc-2.13.so +Size: 2044 kB +Rss: 0 kB +Pss: 0 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 0 kB +Referenced: 0 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff77a4000-7ffff77a8000 r--p 00181000 08:01 1844444 /lib/x86_64-linux-gnu/libc-2.13.so +Size: 16 kB +Rss: 16 kB +Pss: 16 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 16 kB +Referenced: 16 kB +Anonymous: 16 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff77a8000-7ffff77a9000 rw-p 00185000 08:01 1844444 /lib/x86_64-linux-gnu/libc-2.13.so +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff77a9000-7ffff77ae000 rw-p 00000000 00:00 0 +Size: 20 kB +Rss: 16 kB +Pss: 16 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 16 kB +Referenced: 16 kB +Anonymous: 16 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff77ae000-7ffff77c5000 r-xp 00000000 08:01 1845832 /lib/x86_64-linux-gnu/libpthread-2.13.so +Size: 92 kB +Rss: 52 kB +Pss: 14 kB +Shared_Clean: 44 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 8 kB +Referenced: 52 kB +Anonymous: 8 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff77c5000-7ffff79c4000 ---p 00017000 08:01 1845832 /lib/x86_64-linux-gnu/libpthread-2.13.so +Size: 2044 kB +Rss: 0 kB +Pss: 0 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 0 kB +Referenced: 0 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff79c4000-7ffff79c5000 r--p 00016000 08:01 1845832 /lib/x86_64-linux-gnu/libpthread-2.13.so +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff79c5000-7ffff79c6000 rw-p 00017000 08:01 1845832 /lib/x86_64-linux-gnu/libpthread-2.13.so +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff79c6000-7ffff79ca000 rw-p 00000000 00:00 0 +Size: 16 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff79ca000-7ffff79d7000 r-xp 00000000 08:01 2366292 /some/path/src/debug/libpmem.so +Size: 52 kB +Rss: 28 kB +Pss: 28 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 28 kB +Private_Dirty: 0 kB +Referenced: 28 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff79d7000-7ffff7bd6000 ---p 0000d000 08:01 2366292 /some/path/src/debug/libpmem.so +Size: 2044 kB +Rss: 0 kB +Pss: 0 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 0 kB +Referenced: 0 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7bd6000-7ffff7bd7000 rw-p 0000c000 08:01 2366292 /some/path/src/debug/libpmem.so +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7bd7000-7ffff7bd8000 rw-p 00000000 00:00 0 +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7bd8000-7ffff7bdc000 r-xp 00000000 08:01 1835968 /lib/x86_64-linux-gnu/libuuid.so.1.3.0 +Size: 16 kB +Rss: 12 kB +Pss: 12 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 12 kB +Private_Dirty: 0 kB +Referenced: 12 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7bdc000-7ffff7ddb000 ---p 00004000 08:01 1835968 /lib/x86_64-linux-gnu/libuuid.so.1.3.0 +Size: 2044 kB +Rss: 0 kB +Pss: 0 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 0 kB +Referenced: 0 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ddb000-7ffff7ddc000 r--p 00003000 08:01 1835968 /lib/x86_64-linux-gnu/libuuid.so.1.3.0 +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ddc000-7ffff7ddd000 rw-p 00004000 08:01 1835968 /lib/x86_64-linux-gnu/libuuid.so.1.3.0 +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ddd000-7ffff7dfd000 r-xp 00000000 08:01 1844132 /lib/x86_64-linux-gnu/ld-2.13.so +Size: 128 kB +Rss: 108 kB +Pss: 33 kB +Shared_Clean: 104 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 108 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7fe3000-7ffff7fe7000 rw-p 00000000 00:00 0 +Size: 16 kB +Rss: 16 kB +Pss: 16 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 16 kB +Referenced: 16 kB +Anonymous: 16 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ff6000-7ffff7ffb000 rw-p 00000000 00:00 0 +Size: 20 kB +Rss: 20 kB +Pss: 20 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 20 kB +Referenced: 20 kB +Anonymous: 20 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ffb000-7ffff7ffc000 r-xp 00000000 00:00 0 [vdso] +Size: 4 kB +Rss: 4 kB +Pss: 0 kB +Shared_Clean: 4 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 0 kB +Referenced: 4 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ffc000-7ffff7ffd000 r--p 0001f000 08:01 1844132 /lib/x86_64-linux-gnu/ld-2.13.so +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ffd000-7ffff7ffe000 rw-p 00020000 08:01 1844132 /lib/x86_64-linux-gnu/ld-2.13.so +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ffe000-7ffff7fff000 rw-p 00000000 00:00 0 +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffffffde000-7ffffffff000 rw-p 00000000 00:00 0 [stack] +Size: 136 kB +Rss: 24 kB +Pss: 24 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 24 kB +Referenced: 24 kB +Anonymous: 24 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall] +Size: 4 kB +Rss: 0 kB +Pss: 0 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 0 kB +Referenced: 0 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB diff --git a/src/test/pmem_is_pmem_proc/smaps_no_vmflags b/src/test/pmem_is_pmem_proc/smaps_no_vmflags new file mode 100644 index 0000000000000000000000000000000000000000..c2727741ee9452ce4473ec2b551810323869fa4a --- /dev/null +++ b/src/test/pmem_is_pmem_proc/smaps_no_vmflags @@ -0,0 +1,480 @@ +00400000-00406000 r-xp 00000000 08:01 2366593 /some/path/src/test/pmem_map/pmem_map +Size: 24 kB +Rss: 20 kB +Pss: 20 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 16 kB +Private_Dirty: 4 kB +Referenced: 20 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +00605000-00606000 rw-p 00005000 08:01 2366593 /some/path/src/test/pmem_map/pmem_map +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +00606000-00627000 rw-p 00000000 00:00 0 [heap] +Size: 132 kB +Rss: 8 kB +Pss: 8 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 8 kB +Referenced: 8 kB +Anonymous: 8 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7fff77423000-7fff77424000 ---s 00000000 08:01 2366604 /some/path/src/test/pmem_map/testfile1 +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 4 kB +Private_Dirty: 0 kB +Referenced: 4 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7fff77424000-7ffff7423000 r--s 00001000 08:01 2366604 /some/path/src/test/pmem_map/testfile1 +Size: 2097148 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 4 kB +Private_Dirty: 0 kB +Referenced: 4 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7423000-7ffff75a5000 r-xp 00000000 08:01 1844444 /lib/x86_64-linux-gnu/libc-2.13.so +Size: 1544 kB +Rss: 364 kB +Pss: 53 kB +Shared_Clean: 360 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 364 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff75a5000-7ffff77a4000 ---p 00182000 08:01 1844444 /lib/x86_64-linux-gnu/libc-2.13.so +Size: 2044 kB +Rss: 0 kB +Pss: 0 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 0 kB +Referenced: 0 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff77a4000-7ffff77a8000 r--p 00181000 08:01 1844444 /lib/x86_64-linux-gnu/libc-2.13.so +Size: 16 kB +Rss: 16 kB +Pss: 16 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 16 kB +Referenced: 16 kB +Anonymous: 16 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff77a8000-7ffff77a9000 rw-p 00185000 08:01 1844444 /lib/x86_64-linux-gnu/libc-2.13.so +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff77a9000-7ffff77ae000 rw-p 00000000 00:00 0 +Size: 20 kB +Rss: 16 kB +Pss: 16 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 16 kB +Referenced: 16 kB +Anonymous: 16 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff77ae000-7ffff77c5000 r-xp 00000000 08:01 1845832 /lib/x86_64-linux-gnu/libpthread-2.13.so +Size: 92 kB +Rss: 52 kB +Pss: 14 kB +Shared_Clean: 44 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 8 kB +Referenced: 52 kB +Anonymous: 8 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff77c5000-7ffff79c4000 ---p 00017000 08:01 1845832 /lib/x86_64-linux-gnu/libpthread-2.13.so +Size: 2044 kB +Rss: 0 kB +Pss: 0 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 0 kB +Referenced: 0 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff79c4000-7ffff79c5000 r--p 00016000 08:01 1845832 /lib/x86_64-linux-gnu/libpthread-2.13.so +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff79c5000-7ffff79c6000 rw-p 00017000 08:01 1845832 /lib/x86_64-linux-gnu/libpthread-2.13.so +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff79c6000-7ffff79ca000 rw-p 00000000 00:00 0 +Size: 16 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff79ca000-7ffff79d7000 r-xp 00000000 08:01 2366292 /some/path/src/debug/libpmem.so +Size: 52 kB +Rss: 28 kB +Pss: 28 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 28 kB +Private_Dirty: 0 kB +Referenced: 28 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff79d7000-7ffff7bd6000 ---p 0000d000 08:01 2366292 /some/path/src/debug/libpmem.so +Size: 2044 kB +Rss: 0 kB +Pss: 0 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 0 kB +Referenced: 0 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7bd6000-7ffff7bd7000 rw-p 0000c000 08:01 2366292 /some/path/src/debug/libpmem.so +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7bd7000-7ffff7bd8000 rw-p 00000000 00:00 0 +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7bd8000-7ffff7bdc000 r-xp 00000000 08:01 1835968 /lib/x86_64-linux-gnu/libuuid.so.1.3.0 +Size: 16 kB +Rss: 12 kB +Pss: 12 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 12 kB +Private_Dirty: 0 kB +Referenced: 12 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7bdc000-7ffff7ddb000 ---p 00004000 08:01 1835968 /lib/x86_64-linux-gnu/libuuid.so.1.3.0 +Size: 2044 kB +Rss: 0 kB +Pss: 0 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 0 kB +Referenced: 0 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ddb000-7ffff7ddc000 r--p 00003000 08:01 1835968 /lib/x86_64-linux-gnu/libuuid.so.1.3.0 +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ddc000-7ffff7ddd000 rw-p 00004000 08:01 1835968 /lib/x86_64-linux-gnu/libuuid.so.1.3.0 +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ddd000-7ffff7dfd000 r-xp 00000000 08:01 1844132 /lib/x86_64-linux-gnu/ld-2.13.so +Size: 128 kB +Rss: 108 kB +Pss: 33 kB +Shared_Clean: 104 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 108 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7fe3000-7ffff7fe7000 rw-p 00000000 00:00 0 +Size: 16 kB +Rss: 16 kB +Pss: 16 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 16 kB +Referenced: 16 kB +Anonymous: 16 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ff6000-7ffff7ffb000 rw-p 00000000 00:00 0 +Size: 20 kB +Rss: 20 kB +Pss: 20 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 20 kB +Referenced: 20 kB +Anonymous: 20 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ffb000-7ffff7ffc000 r-xp 00000000 00:00 0 [vdso] +Size: 4 kB +Rss: 4 kB +Pss: 0 kB +Shared_Clean: 4 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 0 kB +Referenced: 4 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ffc000-7ffff7ffd000 r--p 0001f000 08:01 1844132 /lib/x86_64-linux-gnu/ld-2.13.so +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ffd000-7ffff7ffe000 rw-p 00020000 08:01 1844132 /lib/x86_64-linux-gnu/ld-2.13.so +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ffe000-7ffff7fff000 rw-p 00000000 00:00 0 +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffffffde000-7ffffffff000 rw-p 00000000 00:00 0 [stack] +Size: 136 kB +Rss: 24 kB +Pss: 24 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 24 kB +Referenced: 24 kB +Anonymous: 24 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall] +Size: 4 kB +Rss: 0 kB +Pss: 0 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 0 kB +Referenced: 0 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB diff --git a/src/test/pmem_is_pmem_proc/smaps_unexp_vmflags b/src/test/pmem_is_pmem_proc/smaps_unexp_vmflags new file mode 100644 index 0000000000000000000000000000000000000000..6c683aa2d5277cdcbe46818f0176f88ae1af1b3d --- /dev/null +++ b/src/test/pmem_is_pmem_proc/smaps_unexp_vmflags @@ -0,0 +1,481 @@ +00400000-00406000 r-xp 00000000 08:01 2366593 /some/path/src/test/pmem_map/pmem_map +Size: 24 kB +Rss: 20 kB +Pss: 20 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 16 kB +Private_Dirty: 4 kB +Referenced: 20 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +00605000-00606000 rw-p 00005000 08:01 2366593 /some/path/src/test/pmem_map/pmem_map +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +00606000-00627000 rw-p 00000000 00:00 0 [heap] +Size: 132 kB +Rss: 8 kB +Pss: 8 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 8 kB +Referenced: 8 kB +Anonymous: 8 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7fff77423000-7fff77424000 ---s 00000000 08:01 2366604 /some/path/src/test/pmem_map/testfile1 +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 4 kB +Private_Dirty: 0 kB +Referenced: 4 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7fff77424000-7ffff7423000 r--s 00001000 08:01 2366604 /some/path/src/test/pmem_map/testfile1 +Size: 2097148 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 4 kB +Private_Dirty: 0 kB +Referenced: 4 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +VmFlags: rd ex mm mr mw me dw sd +7ffff7423000-7ffff75a5000 r-xp 00000000 08:01 1844444 /lib/x86_64-linux-gnu/libc-2.13.so +Size: 1544 kB +Rss: 364 kB +Pss: 53 kB +Shared_Clean: 360 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 364 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff75a5000-7ffff77a4000 ---p 00182000 08:01 1844444 /lib/x86_64-linux-gnu/libc-2.13.so +Size: 2044 kB +Rss: 0 kB +Pss: 0 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 0 kB +Referenced: 0 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff77a4000-7ffff77a8000 r--p 00181000 08:01 1844444 /lib/x86_64-linux-gnu/libc-2.13.so +Size: 16 kB +Rss: 16 kB +Pss: 16 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 16 kB +Referenced: 16 kB +Anonymous: 16 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff77a8000-7ffff77a9000 rw-p 00185000 08:01 1844444 /lib/x86_64-linux-gnu/libc-2.13.so +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff77a9000-7ffff77ae000 rw-p 00000000 00:00 0 +Size: 20 kB +Rss: 16 kB +Pss: 16 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 16 kB +Referenced: 16 kB +Anonymous: 16 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff77ae000-7ffff77c5000 r-xp 00000000 08:01 1845832 /lib/x86_64-linux-gnu/libpthread-2.13.so +Size: 92 kB +Rss: 52 kB +Pss: 14 kB +Shared_Clean: 44 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 8 kB +Referenced: 52 kB +Anonymous: 8 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff77c5000-7ffff79c4000 ---p 00017000 08:01 1845832 /lib/x86_64-linux-gnu/libpthread-2.13.so +Size: 2044 kB +Rss: 0 kB +Pss: 0 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 0 kB +Referenced: 0 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff79c4000-7ffff79c5000 r--p 00016000 08:01 1845832 /lib/x86_64-linux-gnu/libpthread-2.13.so +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff79c5000-7ffff79c6000 rw-p 00017000 08:01 1845832 /lib/x86_64-linux-gnu/libpthread-2.13.so +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff79c6000-7ffff79ca000 rw-p 00000000 00:00 0 +Size: 16 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff79ca000-7ffff79d7000 r-xp 00000000 08:01 2366292 /some/path/src/debug/libpmem.so +Size: 52 kB +Rss: 28 kB +Pss: 28 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 28 kB +Private_Dirty: 0 kB +Referenced: 28 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff79d7000-7ffff7bd6000 ---p 0000d000 08:01 2366292 /some/path/src/debug/libpmem.so +Size: 2044 kB +Rss: 0 kB +Pss: 0 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 0 kB +Referenced: 0 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7bd6000-7ffff7bd7000 rw-p 0000c000 08:01 2366292 /some/path/src/debug/libpmem.so +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7bd7000-7ffff7bd8000 rw-p 00000000 00:00 0 +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7bd8000-7ffff7bdc000 r-xp 00000000 08:01 1835968 /lib/x86_64-linux-gnu/libuuid.so.1.3.0 +Size: 16 kB +Rss: 12 kB +Pss: 12 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 12 kB +Private_Dirty: 0 kB +Referenced: 12 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7bdc000-7ffff7ddb000 ---p 00004000 08:01 1835968 /lib/x86_64-linux-gnu/libuuid.so.1.3.0 +Size: 2044 kB +Rss: 0 kB +Pss: 0 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 0 kB +Referenced: 0 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ddb000-7ffff7ddc000 r--p 00003000 08:01 1835968 /lib/x86_64-linux-gnu/libuuid.so.1.3.0 +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ddc000-7ffff7ddd000 rw-p 00004000 08:01 1835968 /lib/x86_64-linux-gnu/libuuid.so.1.3.0 +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ddd000-7ffff7dfd000 r-xp 00000000 08:01 1844132 /lib/x86_64-linux-gnu/ld-2.13.so +Size: 128 kB +Rss: 108 kB +Pss: 33 kB +Shared_Clean: 104 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 108 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7fe3000-7ffff7fe7000 rw-p 00000000 00:00 0 +Size: 16 kB +Rss: 16 kB +Pss: 16 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 16 kB +Referenced: 16 kB +Anonymous: 16 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ff6000-7ffff7ffb000 rw-p 00000000 00:00 0 +Size: 20 kB +Rss: 20 kB +Pss: 20 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 20 kB +Referenced: 20 kB +Anonymous: 20 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ffb000-7ffff7ffc000 r-xp 00000000 00:00 0 [vdso] +Size: 4 kB +Rss: 4 kB +Pss: 0 kB +Shared_Clean: 4 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 0 kB +Referenced: 4 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ffc000-7ffff7ffd000 r--p 0001f000 08:01 1844132 /lib/x86_64-linux-gnu/ld-2.13.so +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ffd000-7ffff7ffe000 rw-p 00020000 08:01 1844132 /lib/x86_64-linux-gnu/ld-2.13.so +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffff7ffe000-7ffff7fff000 rw-p 00000000 00:00 0 +Size: 4 kB +Rss: 4 kB +Pss: 4 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 4 kB +Referenced: 4 kB +Anonymous: 4 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +7ffffffde000-7ffffffff000 rw-p 00000000 00:00 0 [stack] +Size: 136 kB +Rss: 24 kB +Pss: 24 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 24 kB +Referenced: 24 kB +Anonymous: 24 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB +ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall] +Size: 4 kB +Rss: 0 kB +Pss: 0 kB +Shared_Clean: 0 kB +Shared_Dirty: 0 kB +Private_Clean: 0 kB +Private_Dirty: 0 kB +Referenced: 0 kB +Anonymous: 0 kB +AnonHugePages: 0 kB +Swap: 0 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Locked: 0 kB diff --git a/src/test/pmem_map/.gitignore b/src/test/pmem_map/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..e293c6e0ab8be8d21bae243c60a5af6674620946 --- /dev/null +++ b/src/test/pmem_map/.gitignore @@ -0,0 +1 @@ +pmem_map diff --git a/src/test/pmem_map/Makefile b/src/test/pmem_map/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..745925fa46c0e8d1535dee79686bdbe785437e11 --- /dev/null +++ b/src/test/pmem_map/Makefile @@ -0,0 +1,43 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/pmem_map/Makefile -- build pmem_map unit test +# +TARGET = pmem_map +OBJS = pmem_map.o + +include ../Makefile.inc + +LIBS += -lpmem + +pmem_map.o: pmem_map.c diff --git a/src/test/pmem_map/README b/src/test/pmem_map/README new file mode 100644 index 0000000000000000000000000000000000000000..9a623e2d658f49569fcdcdbeaf4532dc5167c2fd --- /dev/null +++ b/src/test/pmem_map/README @@ -0,0 +1,33 @@ +Linux NVM Library + +This is src/test/pmem_map/README. + +This directory contains a unit test for pmem{trn,blk,log}_map(). + +The program in pmem_map.c takes a list of files with a pool type +prefix on them. For example: + + ./pmem_map t:file1 b:file2 l:file3 + +will call pmemtrn_map() on file1, pmemblk_map() on file2, and +pmemlog_map() on file3. + +The first 4k of the file is captured before and after the map calls +are done, and the program reports if the first 4k changed. This can +be used to determine if a new memory pool was created (so the header +was generated and the program reports a change), or an existing pool +was found (so the header was left alone and the program reports no +change). + +Finally, the program then tried to dereference the opaque pool handle +and prints a message is a SEGV signal results (which it should). + +By passing the same file multiple times, more interesting scenarios +can be tested. For example: + + ./pmem_map t:file1 t:file1 b:file1 + +can be used to test that the first argument causes a new pool to be +created, the second argument causes an existing pool to be found, and +the third argument causes EINVAL due to opening a pmemtrn pool with +pmemblk_map(). diff --git a/src/test/pmem_map/TEST0 b/src/test/pmem_map/TEST0 new file mode 100755 index 0000000000000000000000000000000000000000..0feb956037ea03160fa03cc61aca3147c5951a7f --- /dev/null +++ b/src/test/pmem_map/TEST0 @@ -0,0 +1,64 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/pmem_map/TEST0 -- unit test for pmem{trn,blk,log}_map +# +export UNITTEST_NAME=pmem_map/TEST0 +export UNITTEST_NUM=0 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local + +setup + +rm -f $DIR/testfile1 +truncate -s 2G $DIR/testfile1 +# +# pass the same file multiple times +# the first time the file is new, so the pool is created +# (and the test program will report the first 4k changed) +# the second time the file has a pool in it +# (and the test program will report the first 4k didn't change) +# the third time we pass the pool to the wrong map function +# (and the test program will report the map function failed) +# +expect_normal_exit ./pmem_map$EXESUFFIX\ + t:$DIR/testfile1 t:$DIR/testfile1 b:$DIR/testfile1 +rm $DIR/testfile1 + +check + +pass diff --git a/src/test/pmem_map/TEST1 b/src/test/pmem_map/TEST1 new file mode 100755 index 0000000000000000000000000000000000000000..b17cd9be4bab34b85c32ad25f92bc7e7e12c3743 --- /dev/null +++ b/src/test/pmem_map/TEST1 @@ -0,0 +1,64 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/pmem_map/TEST1 -- unit test for pmem{trn,blk,log}_map +# +export UNITTEST_NAME=pmem_map/TEST1 +export UNITTEST_NUM=1 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local + +setup + +rm -f $DIR/testfile1 +truncate -s 2G $DIR/testfile1 +# +# pass the same file multiple times +# the first time the file is new, so the pool is created +# (and the test program will report the first 4k changed) +# the second time the file has a pool in it +# (and the test program will report the first 4k didn't change) +# the third time we pass the pool to the wrong map function +# (and the test program will report the map function failed) +# +expect_normal_exit ./pmem_map$EXESUFFIX\ + b:$DIR/testfile1 b:$DIR/testfile1 l:$DIR/testfile1 +rm $DIR/testfile1 + +check + +pass diff --git a/src/test/pmem_map/TEST2 b/src/test/pmem_map/TEST2 new file mode 100755 index 0000000000000000000000000000000000000000..adb82dd13c53b3ad7376152118c24232042d1761 --- /dev/null +++ b/src/test/pmem_map/TEST2 @@ -0,0 +1,64 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/pmem_map/TEST2 -- unit test for pmem{trn,blk,log}_map +# +export UNITTEST_NAME=pmem_map/TEST2 +export UNITTEST_NUM=2 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local + +setup + +rm -f $DIR/testfile1 +truncate -s 2G $DIR/testfile1 +# +# pass the same file multiple times +# the first time the file is new, so the pool is created +# (and the test program will report the first 4k changed) +# the second time the file has a pool in it +# (and the test program will report the first 4k didn't change) +# the third time we pass the pool to the wrong map function +# (and the test program will report the map function failed) +# +expect_normal_exit ./pmem_map$EXESUFFIX\ + l:$DIR/testfile1 l:$DIR/testfile1 t:$DIR/testfile1 +rm $DIR/testfile1 + +check + +pass diff --git a/src/test/pmem_map/err0.log.match b/src/test/pmem_map/err0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/pmem_map/err1.log.match b/src/test/pmem_map/err1.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/pmem_map/err2.log.match b/src/test/pmem_map/err2.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/pmem_map/out0.log.match b/src/test/pmem_map/out0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..eadc5cd1e8ce025204865d715b341e79c25786b5 --- /dev/null +++ b/src/test/pmem_map/out0.log.match @@ -0,0 +1,9 @@ +pmem_map/TEST0: START: pmem_map + ./pmem_map$(*) t:$(*)/testfile1 t:$(*)/testfile1 b:$(*)/testfile1 +t:$(*)/testfile1: first 4096 bytes changed during map +signal: Segmentation fault +t:$(*)/testfile1: first 4096 bytes unchanged during map +signal: Segmentation fault +b:$(*)/testfile1: first 4096 bytes unchanged during map +pmemblk_map: Invalid argument +pmem_map/TEST0: Done diff --git a/src/test/pmem_map/out1.log.match b/src/test/pmem_map/out1.log.match new file mode 100644 index 0000000000000000000000000000000000000000..15a110af9d8ca125f23803a80d4a6fe4d9424ffc --- /dev/null +++ b/src/test/pmem_map/out1.log.match @@ -0,0 +1,9 @@ +pmem_map/TEST1: START: pmem_map + ./pmem_map$(*) b:$(*)/testfile1 b:$(*)/testfile1 l:$(*)/testfile1 +b:$(*)/testfile1: first 4096 bytes changed during map +signal: Segmentation fault +b:$(*)/testfile1: first 4096 bytes unchanged during map +signal: Segmentation fault +l:$(*)/testfile1: first 4096 bytes unchanged during map +pmemlog_map: Invalid argument +pmem_map/TEST1: Done diff --git a/src/test/pmem_map/out2.log.match b/src/test/pmem_map/out2.log.match new file mode 100644 index 0000000000000000000000000000000000000000..f2ae5c2ce492fd523f65876c7f1134c366463216 --- /dev/null +++ b/src/test/pmem_map/out2.log.match @@ -0,0 +1,9 @@ +pmem_map/TEST2: START: pmem_map + ./pmem_map$(*) l:$(*)/testfile1 l:$(*)/testfile1 t:$(*)/testfile1 +l:$(*)/testfile1: first 4096 bytes changed during map +signal: Segmentation fault +l:$(*)/testfile1: first 4096 bytes unchanged during map +signal: Segmentation fault +t:$(*)/testfile1: first 4096 bytes unchanged during map +pmemtrn_map: Invalid argument +pmem_map/TEST2: Done diff --git a/src/test/pmem_map/pmem_map.c b/src/test/pmem_map/pmem_map.c new file mode 100644 index 0000000000000000000000000000000000000000..b1b5543284f1cc427f3e43ed238b8689b9bdac6b --- /dev/null +++ b/src/test/pmem_map/pmem_map.c @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * pmem_map.c -- unit test for mapping different types of pmem pools + * + * usage: pmem_map <type>:file ... + * + * each file is mapped with: + * pmemtrn_map() if the filename starts with t: + * pmemblk_map() if the filename starts with b: + * pmemlog_map() if the filename starts with l: + * and the handle returned is dereferenced to force a SEGV. + */ + +#include "unittest.h" + +#define CHECK_BYTES 4096 /* bytes to compare before/after map call */ + +sigjmp_buf Jmp; + +/* + * signal_handler -- called on SIGSEGV + */ +void +signal_handler(int sig) +{ + OUT("signal: %s", strsignal(sig)); + + siglongjmp(Jmp, 1); +} + +int +main(int argc, char *argv[]) +{ + START(argc, argv, "pmem_map"); + + if (argc < 2) + FATAL("usage: %s <type>:file ...", argv[0]); + + /* arrange to catch SEGV */ + struct sigvec v = { 0 }; + v.sv_handler = signal_handler; + SIGVEC(SIGSEGV, &v, NULL); + + /* map each file argument with the given map type */ + for (int arg = 1; arg < argc; arg++) { + if (strchr("tbl", argv[arg][0]) == NULL || argv[arg][1] != ':') + FATAL("type must be t: or b: or l:"); + + int fd = OPEN(&argv[arg][2], O_RDWR); + + char before[CHECK_BYTES]; + char after[CHECK_BYTES]; + + READ(fd, before, CHECK_BYTES); + + void *handle = NULL; + switch (argv[arg][0]) { + case 't': + handle = pmemtrn_map(fd); + break; + + case 'b': + handle = pmemblk_map(fd, 4096); + break; + + case 'l': + handle = pmemlog_map(fd); + break; + + default: + FATAL(NULL); /* can't happen */ + } + + LSEEK(fd, (off_t)0, SEEK_SET); + + if (READ(fd, after, CHECK_BYTES) == CHECK_BYTES) { + if (memcmp(before, after, CHECK_BYTES)) + OUT("%s: first %d bytes changed during map", + argv[arg], CHECK_BYTES); + else + OUT("%s: first %d bytes unchanged during map", + argv[arg], CHECK_BYTES); + } + + close(fd); + + if (handle == NULL) { + switch (argv[arg][0]) { + case 't': + OUT("!pmemtrn_map"); + break; + + case 'b': + OUT("!pmemblk_map"); + break; + + case 'l': + OUT("!pmemlog_map"); + break; + + default: + FATAL(NULL); /* can't happen */ + } + } else if (!sigsetjmp(Jmp, 1)) { + /* try to deref the opaque handle */ + char x = *(char *)handle; + + OUT("x = %c", x); /* shouldn't get here */ + } else { + /* back from signal handler, unmap the pool */ + switch (argv[arg][0]) { + case 't': + pmemtrn_unmap(handle); + break; + + case 'b': + pmemblk_unmap(handle); + break; + + case 'l': + pmemlog_unmap(handle); + break; + + default: + FATAL(NULL); /* can't happen */ + } + } + } + + DONE(NULL); +} diff --git a/src/test/scope/Makefile b/src/test/scope/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..effaac5488b9c65a25d42bb2ba301172c72b15cf --- /dev/null +++ b/src/test/scope/Makefile @@ -0,0 +1,47 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/scope/Makefile -- build scope unit test +# +# This Makefile doesn't use ../Makefile.inc since there's no C to build. +# +all: + +clean: + $(RM) *.o */*.o core a.out *.log testfile* + +clobber: clean + +cstyle: + +.PHONY: all clean clobber diff --git a/src/test/scope/TEST0 b/src/test/scope/TEST0 new file mode 100755 index 0000000000000000000000000000000000000000..75be0fa43bc792fe6d0c9dc90d20bfbe171544c2 --- /dev/null +++ b/src/test/scope/TEST0 @@ -0,0 +1,54 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/scope/TEST0 -- scope test to check libpmem symbols +# +export UNITTEST_NAME=scope/TEST0 +export UNITTEST_NUM=0 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local +require_build_type debug + +setup + +(nm -g ../../debug/libpmem.so |\ + perl -ne 'print if s/^[0-9a-z]+ T (\w+)/$1/' |\ + sort > out0.log) 2> err0.log + +check + +pass diff --git a/src/test/scope/TEST1 b/src/test/scope/TEST1 new file mode 100755 index 0000000000000000000000000000000000000000..c861ef43364b25eef16e5983aaf8931287c13b75 --- /dev/null +++ b/src/test/scope/TEST1 @@ -0,0 +1,54 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/scope/TEST1 -- scope test to check libvmem symbols +# +export UNITTEST_NAME=scope/TEST1 +export UNITTEST_NUM=1 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local +require_build_type debug + +setup + +(nm -g ../../debug/libvmem.so |\ + perl -ne 'print if s/^[0-9a-z]+ T (\w+)/$1/' |\ + sort > out1.log) 2> err1.log + +check + +pass diff --git a/src/test/scope/TEST2 b/src/test/scope/TEST2 new file mode 100755 index 0000000000000000000000000000000000000000..d032ab07ef0ea30c94d585e25e07e5c470725761 --- /dev/null +++ b/src/test/scope/TEST2 @@ -0,0 +1,54 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/scope/TEST2 -- scope test to check libpmem symbols (nondebug) +# +export UNITTEST_NAME=scope/TEST2 +export UNITTEST_NUM=2 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local +require_build_type nondebug + +setup + +(nm -g ../../nondebug/libpmem.so |\ + perl -ne 'print if s/^[0-9a-z]+ T (\w+)/$1/' |\ + sort > out2.log) 2> err2.log + +check + +pass diff --git a/src/test/scope/TEST3 b/src/test/scope/TEST3 new file mode 100755 index 0000000000000000000000000000000000000000..802099b9f4ac70bfc50f67d9249d745f3c83a45e --- /dev/null +++ b/src/test/scope/TEST3 @@ -0,0 +1,54 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/scope/TEST3 -- scope test to check libvmem symbols (nondebug) +# +export UNITTEST_NAME=scope/TEST3 +export UNITTEST_NUM=3 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local +require_build_type nondebug + +setup + +(nm -g ../../nondebug/libvmem.so |\ + perl -ne 'print if s/^[0-9a-z]+ T (\w+)/$1/' |\ + sort > out3.log) 2> err3.log + +check + +pass diff --git a/src/test/scope/TEST4 b/src/test/scope/TEST4 new file mode 100755 index 0000000000000000000000000000000000000000..9b1586dca818a83af91db7227b6a524153650d93 --- /dev/null +++ b/src/test/scope/TEST4 @@ -0,0 +1,54 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/scope/TEST4 -- scope test to check libpmem symbols +# +export UNITTEST_NAME=scope/TEST4 +export UNITTEST_NUM=4 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local +require_build_type debug + +setup + +(nm -g ../../debug/libpmem.a |\ + perl -ne 'print if s/^[0-9a-z]+ T (\w+)/$1/' |\ + sort > out4.log) 2> err4.log + +check + +pass diff --git a/src/test/scope/TEST5 b/src/test/scope/TEST5 new file mode 100755 index 0000000000000000000000000000000000000000..21eeb9d18668eb84790f23a68cd2d0876e3276a4 --- /dev/null +++ b/src/test/scope/TEST5 @@ -0,0 +1,54 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/scope/TEST5 -- scope test to check libvmem symbols +# +export UNITTEST_NAME=scope/TEST5 +export UNITTEST_NUM=5 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local +require_build_type debug + +setup + +(nm -g ../../debug/libvmem.a |\ + perl -ne 'print if s/^[0-9a-z]+ T (\w+)/$1/' |\ + sort > out5.log) 2> err5.log + +check + +pass diff --git a/src/test/scope/TEST6 b/src/test/scope/TEST6 new file mode 100755 index 0000000000000000000000000000000000000000..702377e0feefe45ffa5e96e62eec56eea0c026a2 --- /dev/null +++ b/src/test/scope/TEST6 @@ -0,0 +1,54 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/scope/TEST6 -- scope test to check libpmem symbols (nondebug) +# +export UNITTEST_NAME=scope/TEST6 +export UNITTEST_NUM=6 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local +require_build_type nondebug + +setup + +(nm -g ../../nondebug/libpmem.a |\ + perl -ne 'print if s/^[0-9a-z]+ T (\w+)/$1/' |\ + sort > out6.log) 2> err6.log + +check + +pass diff --git a/src/test/scope/TEST7 b/src/test/scope/TEST7 new file mode 100755 index 0000000000000000000000000000000000000000..cd80b4c0b39c9021d2d674916abdd5407b0998d1 --- /dev/null +++ b/src/test/scope/TEST7 @@ -0,0 +1,54 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/scope/TEST7 -- scope test to check libvmem symbols (nondebug) +# +export UNITTEST_NAME=scope/TEST7 +export UNITTEST_NUM=7 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local +require_build_type nondebug + +setup + +(nm -g ../../nondebug/libvmem.a |\ + perl -ne 'print if s/^[0-9a-z]+ T (\w+)/$1/' |\ + sort > out7.log) 2> err7.log + +check + +pass diff --git a/src/test/scope/err0.log.match b/src/test/scope/err0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/scope/err1.log.match b/src/test/scope/err1.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/scope/err2.log.match b/src/test/scope/err2.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/scope/err3.log.match b/src/test/scope/err3.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/scope/err4.log.match b/src/test/scope/err4.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/scope/err5.log.match b/src/test/scope/err5.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/scope/err6.log.match b/src/test/scope/err6.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/scope/err7.log.match b/src/test/scope/err7.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/scope/out0.log.match b/src/test/scope/out0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..bbd5d0d4c45274adc5c52edacd8686c407908599 --- /dev/null +++ b/src/test/scope/out0.log.match @@ -0,0 +1,26 @@ +pmem_check_version +pmem_drain +pmem_flush +pmem_is_pmem +pmem_persist +pmem_set_funcs +pmemblk_check +pmemblk_map +pmemblk_nblock +pmemblk_read +pmemblk_set_error +pmemblk_set_zero +pmemblk_unmap +pmemblk_write +pmemlog_append +pmemlog_appendv +pmemlog_check +pmemlog_map +pmemlog_nbyte +pmemlog_rewind +pmemlog_tell +pmemlog_unmap +pmemlog_walk +pmemtrn_check +pmemtrn_map +pmemtrn_unmap diff --git a/src/test/scope/out1.log.match b/src/test/scope/out1.log.match new file mode 100644 index 0000000000000000000000000000000000000000..723c105c692af66385e7cca2d75cca14720ceae3 --- /dev/null +++ b/src/test/scope/out1.log.match @@ -0,0 +1,14 @@ +vmem_aligned_alloc +vmem_calloc +vmem_check_version +vmem_free +vmem_malloc +vmem_pool_check +vmem_pool_create +vmem_pool_create_in_region +vmem_pool_delete +vmem_pool_freespace +vmem_pool_stats_print +vmem_realloc +vmem_set_funcs +vmem_strdup diff --git a/src/test/scope/out4.log.match b/src/test/scope/out4.log.match new file mode 100644 index 0000000000000000000000000000000000000000..bbd5d0d4c45274adc5c52edacd8686c407908599 --- /dev/null +++ b/src/test/scope/out4.log.match @@ -0,0 +1,26 @@ +pmem_check_version +pmem_drain +pmem_flush +pmem_is_pmem +pmem_persist +pmem_set_funcs +pmemblk_check +pmemblk_map +pmemblk_nblock +pmemblk_read +pmemblk_set_error +pmemblk_set_zero +pmemblk_unmap +pmemblk_write +pmemlog_append +pmemlog_appendv +pmemlog_check +pmemlog_map +pmemlog_nbyte +pmemlog_rewind +pmemlog_tell +pmemlog_unmap +pmemlog_walk +pmemtrn_check +pmemtrn_map +pmemtrn_unmap diff --git a/src/test/scope/out5.log.match b/src/test/scope/out5.log.match new file mode 100644 index 0000000000000000000000000000000000000000..723c105c692af66385e7cca2d75cca14720ceae3 --- /dev/null +++ b/src/test/scope/out5.log.match @@ -0,0 +1,14 @@ +vmem_aligned_alloc +vmem_calloc +vmem_check_version +vmem_free +vmem_malloc +vmem_pool_check +vmem_pool_create +vmem_pool_create_in_region +vmem_pool_delete +vmem_pool_freespace +vmem_pool_stats_print +vmem_realloc +vmem_set_funcs +vmem_strdup diff --git a/src/test/testconfig.sh.example b/src/test/testconfig.sh.example new file mode 100644 index 0000000000000000000000000000000000000000..01533eeba7c30ee55381f616a288a6f2f12297ee --- /dev/null +++ b/src/test/testconfig.sh.example @@ -0,0 +1,28 @@ +# +# src/test/testconfig.sh -- local configuration for unit tests +# +# This file tells the script unittest/unittest.sh which file system +# locations are to be used for testing. +# + +# +# For tests that use trivial space and don't care what type of file system, +# just putting the files in the same directory as the test is usually most +# convenient. But if there's some reason to put these small testfiles +# elsewhere, set the path here. +# +LOCAL_FS_DIR=. + +# +# For tests that require true persistent memory, set the path to a directory +# on a PMEM-aware file system here. Comment this line out if there's no +# actual persistent memory available on this system. +# +#PMEM_FS_DIR=/mnt/pmem + +# +# For tests that require true a non-persitent memory aware file system (i.e. +# to verify something works on traditional page-cache based memory-mapped +# files) set the path to a directory on a normal file system here. +# +NON_PMEM_FS_DIR=/tmp diff --git a/src/test/traces/.gitignore b/src/test/traces/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..9f58dd630b40f862d9f8b56b802091d02b527487 --- /dev/null +++ b/src/test/traces/.gitignore @@ -0,0 +1 @@ +traces diff --git a/src/test/traces/Makefile b/src/test/traces/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..12c59e58965aa961f14070c7205dc410c94789f4 --- /dev/null +++ b/src/test/traces/Makefile @@ -0,0 +1,51 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/traces/Makefile -- build traces unit test +# +vpath %.c ../.. +vpath %.h ../.. + +TARGET = traces +OBJS = traces.o out.o + +out.o: CFLAGS += -DSRCVERSION=\"utversion\" + +include ../Makefile.inc + +#Test debug output +CFLAGS += -DDEBUG -I../.. + +traces.o: traces.c + +out.o: out.c diff --git a/src/test/traces/TEST0 b/src/test/traces/TEST0 new file mode 100755 index 0000000000000000000000000000000000000000..f703d2b3f821555383fb45177715f72bbb711e35 --- /dev/null +++ b/src/test/traces/TEST0 @@ -0,0 +1,55 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/traces/TEST0 -- unit test for traces +# +export UNITTEST_NAME=traces/TEST0 +export UNITTEST_NUM=0 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local +require_build_type debug + +setup + +export TRACE_LOG_LEVEL=4 +export TRACE_LOG_FILE=./custom_file.log +expect_normal_exit ./traces$EXESUFFIX + +# check results +../match custom_file.log.match + +pass diff --git a/src/test/traces/TEST1 b/src/test/traces/TEST1 new file mode 100755 index 0000000000000000000000000000000000000000..fb6ea154d2d4fee5182478967129287c9b9178d8 --- /dev/null +++ b/src/test/traces/TEST1 @@ -0,0 +1,54 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/traces/TEST1 -- unit test for traces +# +export UNITTEST_NAME=traces/TEST1 +export UNITTEST_NUM=1 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local +require_build_type debug + +setup + +export TRACE_LOG_LEVEL=0 +expect_normal_exit ./traces$EXESUFFIX 2>redir_stderr$UNITTEST_NUM.log + +# check results +../match redir_stderr$UNITTEST_NUM.log.match + +pass diff --git a/src/test/traces/TEST2 b/src/test/traces/TEST2 new file mode 100755 index 0000000000000000000000000000000000000000..17e193e4559522f64fc2b8b7fb2f88b4b2be57bd --- /dev/null +++ b/src/test/traces/TEST2 @@ -0,0 +1,54 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/traces/TEST2 -- unit test for traces +# +export UNITTEST_NAME=traces/TEST2 +export UNITTEST_NUM=2 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local +require_build_type debug + +setup + +export TRACE_LOG_LEVEL=1 +expect_normal_exit ./traces$EXESUFFIX 2>redir_stderr$UNITTEST_NUM.log + +# check results +../match redir_stderr$UNITTEST_NUM.log.match + +pass diff --git a/src/test/traces/TEST3 b/src/test/traces/TEST3 new file mode 100755 index 0000000000000000000000000000000000000000..50b9c9b7b6666f5c4b2d99b0b4ce7cdd809e3818 --- /dev/null +++ b/src/test/traces/TEST3 @@ -0,0 +1,54 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/traces/TEST3 -- unit test for traces +# +export UNITTEST_NAME=traces/TEST3 +export UNITTEST_NUM=3 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local +require_build_type debug + +setup + +export TRACE_LOG_LEVEL=2 +expect_normal_exit ./traces$EXESUFFIX 2>redir_stderr$UNITTEST_NUM.log + +# check results +../match redir_stderr$UNITTEST_NUM.log.match + +pass diff --git a/src/test/traces/TEST4 b/src/test/traces/TEST4 new file mode 100755 index 0000000000000000000000000000000000000000..4108e12882d6be7587761e2f35c7183aff0f51dd --- /dev/null +++ b/src/test/traces/TEST4 @@ -0,0 +1,54 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/traces/TEST4 -- unit test for traces +# +export UNITTEST_NAME=traces/TEST4 +export UNITTEST_NUM=4 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local +require_build_type debug + +setup + +export TRACE_LOG_LEVEL=3 +expect_normal_exit ./traces$EXESUFFIX 2>redir_stderr$UNITTEST_NUM.log + +# check results +../match redir_stderr$UNITTEST_NUM.log.match + +pass diff --git a/src/test/traces/TEST5 b/src/test/traces/TEST5 new file mode 100755 index 0000000000000000000000000000000000000000..7cfee0c54dcb09a1d716366e41e03a6e56dd6afd --- /dev/null +++ b/src/test/traces/TEST5 @@ -0,0 +1,54 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/traces/TEST5 -- unit test for traces +# +export UNITTEST_NAME=traces/TEST5 +export UNITTEST_NUM=5 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local +require_build_type debug + +setup + +export TRACE_LOG_LEVEL=4 +expect_normal_exit ./traces$EXESUFFIX 2>redir_stderr$UNITTEST_NUM.log + +# check results +../match redir_stderr$UNITTEST_NUM.log.match + +pass diff --git a/src/test/traces/TEST6 b/src/test/traces/TEST6 new file mode 100755 index 0000000000000000000000000000000000000000..1d348c99d4fcd3a811014d1caa7d057f7205ff35 --- /dev/null +++ b/src/test/traces/TEST6 @@ -0,0 +1,54 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/traces/TEST6 -- unit test for traces +# +export UNITTEST_NAME=traces/TEST6 +export UNITTEST_NUM=6 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local +require_build_type debug + +setup + +export TRACE_LOG_LEVEL=4 +expect_normal_exit ./traces$EXESUFFIX 2>redir_stderr$UNITTEST_NUM.log + +# check results +../match redir_stderr$UNITTEST_NUM.log.match + +pass diff --git a/src/test/traces/custom_file.log.match b/src/test/traces/custom_file.log.match new file mode 100644 index 0000000000000000000000000000000000000000..cdaca7d494cd943dbda5458be5172bb079182759 --- /dev/null +++ b/src/test/traces/custom_file.log.match @@ -0,0 +1,8 @@ +$(*) +$(*) +$(*) +$(*)Log level NONE +$(*)Log level ERROR +$(*)Log level WARNING +$(*)Log level INFO +$(*)Log level DEBUG diff --git a/src/test/traces/redir_stderr1.log.match b/src/test/traces/redir_stderr1.log.match new file mode 100644 index 0000000000000000000000000000000000000000..3d739c871d840f4250bfa2f7d1a8244f5ae2d362 --- /dev/null +++ b/src/test/traces/redir_stderr1.log.match @@ -0,0 +1 @@ +$(*)Log level NONE diff --git a/src/test/traces/redir_stderr2.log.match b/src/test/traces/redir_stderr2.log.match new file mode 100644 index 0000000000000000000000000000000000000000..0dd45c902a00e1fa49c9568253dd8746ddfa19ff --- /dev/null +++ b/src/test/traces/redir_stderr2.log.match @@ -0,0 +1,5 @@ +$(*) +$(*) +$(*) +$(*)Log level NONE +$(*)Log level ERROR diff --git a/src/test/traces/redir_stderr3.log.match b/src/test/traces/redir_stderr3.log.match new file mode 100644 index 0000000000000000000000000000000000000000..7d6fc0c11491b065bb309c0780e1c55fea60757d --- /dev/null +++ b/src/test/traces/redir_stderr3.log.match @@ -0,0 +1,6 @@ +$(*) +$(*) +$(*) +$(*)Log level NONE +$(*)Log level ERROR +$(*)Log level WARNING diff --git a/src/test/traces/redir_stderr4.log.match b/src/test/traces/redir_stderr4.log.match new file mode 100644 index 0000000000000000000000000000000000000000..833b18b0c8c77a560d5ebb0b29c381c7b30be22d --- /dev/null +++ b/src/test/traces/redir_stderr4.log.match @@ -0,0 +1,7 @@ +$(*) +$(*) +$(*) +$(*)Log level NONE +$(*)Log level ERROR +$(*)Log level WARNING +$(*)Log level INFO diff --git a/src/test/traces/redir_stderr5.log.match b/src/test/traces/redir_stderr5.log.match new file mode 100644 index 0000000000000000000000000000000000000000..cdaca7d494cd943dbda5458be5172bb079182759 --- /dev/null +++ b/src/test/traces/redir_stderr5.log.match @@ -0,0 +1,8 @@ +$(*) +$(*) +$(*) +$(*)Log level NONE +$(*)Log level ERROR +$(*)Log level WARNING +$(*)Log level INFO +$(*)Log level DEBUG diff --git a/src/test/traces/redir_stderr6.log.match b/src/test/traces/redir_stderr6.log.match new file mode 100644 index 0000000000000000000000000000000000000000..ddcd4f2cf55368ed36360f3144d658cd6becb5a4 --- /dev/null +++ b/src/test/traces/redir_stderr6.log.match @@ -0,0 +1,8 @@ +$(*) +$(*) +$(*) +<trace>: <0> [traces.c:$(*) main] Log level NONE +<trace>: <1> [traces.c:$(*) main] Log level ERROR +<trace>: <2> [traces.c:$(*) main] Log level WARNING +<trace>: <3> [traces.c:$(*) main] Log level INFO +<trace>: <4> [traces.c:$(*) main] Log level DEBUG diff --git a/src/test/traces/traces.c b/src/test/traces/traces.c new file mode 100644 index 0000000000000000000000000000000000000000..fc65fbddcdb2a9179958616fa0d77b5c8e5901d1 --- /dev/null +++ b/src/test/traces/traces.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * traces.c -- unit test for traces + */ + +#define LOG_PREFIX "trace" +#define LOG_LEVEL_VAR "TRACE_LOG_LEVEL" +#define LOG_FILE_VAR "TRACE_LOG_FILE" + +#include "out.h" +#undef FATAL +#undef ASSERT +#undef ASSERTinfo +#undef ASSERTeq +#undef ASSERTne +#include "unittest.h" + +int +main(int argc, char *argv[]) +{ + START(argc, argv, "traces"); + + /* Execute test */ + out_init(LOG_PREFIX, LOG_LEVEL_VAR, LOG_FILE_VAR); + LOG(0, "Log level NONE"); + LOG(1, "Log level ERROR"); + LOG(2, "Log level WARNING"); + LOG(3, "Log level INFO"); + LOG(4, "Log level DEBUG"); + + /* Cleanup */ + out_fini(); + + DONE(NULL); +} diff --git a/src/test/traces_custom_function/.gitignore b/src/test/traces_custom_function/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..47a458e48921da7e98bf9e2e6d0c2f1c16b681fd --- /dev/null +++ b/src/test/traces_custom_function/.gitignore @@ -0,0 +1 @@ +traces_custom_function diff --git a/src/test/traces_custom_function/Makefile b/src/test/traces_custom_function/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..27c47ae18021fe18cd1b9c720a7af8a550c45aff --- /dev/null +++ b/src/test/traces_custom_function/Makefile @@ -0,0 +1,51 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/traces_custom_function/Makefile -- build traces unit test +# +vpath %.c ../.. +vpath %.h ../.. + +TARGET = traces_custom_function +OBJS = traces_custom_function.o out.o + +out.o: CFLAGS += -DSRCVERSION=\"utversion\" + +include ../Makefile.inc + +#Test debug output +CFLAGS += -DDEBUG -I../.. + +traces_custom_function.o: traces_custom_function.c + +out.o: out.c diff --git a/src/test/traces_custom_function/TEST0 b/src/test/traces_custom_function/TEST0 new file mode 100755 index 0000000000000000000000000000000000000000..491a5c14dde8870350ffdaaafea75fe379b771db --- /dev/null +++ b/src/test/traces_custom_function/TEST0 @@ -0,0 +1,53 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/traces_custom_function/TEST0 -- unit test for traces custom function +# +export UNITTEST_NAME=traces_custom_function/TEST0 +export UNITTEST_NUM=0 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local +require_build_type debug + +setup + +export TRACE_LOG_LEVEL=4 +expect_normal_exit ./traces_custom_function$EXESUFFIX + +check + +pass diff --git a/src/test/traces_custom_function/out0.log.match b/src/test/traces_custom_function/out0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..38451d7c9405c705d2c52897fda5ef0b3958257e --- /dev/null +++ b/src/test/traces_custom_function/out0.log.match @@ -0,0 +1,19 @@ +traces_custom_function/TEST0: START: traces_custom_function + ./traces_custom_function$(*) +CUSTOM_PRINT:$(*) + +CUSTOM_PRINT:$(*) + +CUSTOM_PRINT:$(*) + +CUSTOM_PRINT:$(*)Log level NONE + +CUSTOM_PRINT:$(*)Log level ERROR + +CUSTOM_PRINT:$(*)Log level WARNING + +CUSTOM_PRINT:$(*)Log level INFO + +CUSTOM_PRINT:$(*)Log level DEBUG + +traces_custom_function/TEST0: Done diff --git a/src/test/traces_custom_function/traces_custom_function.c b/src/test/traces_custom_function/traces_custom_function.c new file mode 100644 index 0000000000000000000000000000000000000000..55de3841ceb7ec14946c18ac2fe22e58c758286f --- /dev/null +++ b/src/test/traces_custom_function/traces_custom_function.c @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * traces_custom_function.c -- unit test for traces with custom print function + */ + +#define LOG_PREFIX "trace_func" +#define LOG_LEVEL_VAR "TRACE_LOG_LEVEL" +#define LOG_FILE_VAR "TRACE_LOG_FILE" + +#include "out.h" +#undef FATAL +#undef ASSERT +#undef ASSERTinfo +#undef ASSERTeq +#undef ASSERTne +#include "unittest.h" + +/* + * print_custom_function -- Custom function to handle output + * + * This is called from the library to print text instead of output to stderr. + */ +void +print_custom_function(const char *s) +{ + if (s) { + OUT("CUSTOM_PRINT: %s", s); + } else { + OUT("CUSTOM_PRINT(NULL)"); + } +} + +int +main(int argc, char *argv[]) +{ + START(argc, argv, "traces_custom_function"); + + /* Prepare environment */ + out_set_print_func(print_custom_function); + + /* Execute test */ + out_init(LOG_PREFIX, LOG_LEVEL_VAR, LOG_FILE_VAR); + LOG(0, "Log level NONE"); + LOG(1, "Log level ERROR"); + LOG(2, "Log level WARNING"); + LOG(3, "Log level INFO"); + LOG(4, "Log level DEBUG"); + + /* Cleanup */ + out_fini(); + + DONE(NULL); +} diff --git a/src/test/unittest/.gitignore b/src/test/unittest/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..6a8058883039fb613fc9fcd76dc781a64aef509b --- /dev/null +++ b/src/test/unittest/.gitignore @@ -0,0 +1 @@ +libut.a diff --git a/src/test/unittest/Makefile b/src/test/unittest/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..426797120c4d3404f4f6853a2727b8097e5a726c --- /dev/null +++ b/src/test/unittest/Makefile @@ -0,0 +1,67 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/unittest/Makefile -- build unittest support library +# +TARGET = libut.a +OBJS = ut.o ut_alloc.o ut_file.o ut_pthread.o ut_signal.o +CFLAGS = -I../../include -ggdb -Wall -Werror -std=gnu99 + +all test: $(TARGET) + +$(TARGET): $(OBJS) + $(AR) rv $@ $(OBJS) + +.c.o: + $(CC) -c $(CFLAGS) $(INCS) $(COMMONINCS) $< -o $@ + +clean: + $(RM) *.o core a.out + +cstyle: + ../../../utils/cstyle -pP *.c *.h + +clobber: clean + $(RM) $(TARGET) + +.PHONY: clean clobber + +ut.o: ut.c unittest.h + +ut_alloc.o: ut_alloc.c unittest.h + +ut_file.o: ut_file.c unittest.h + +ut_pthread.o: ut_pthread.c unittest.h + +ut_signal.o: ut_file.c unittest.h diff --git a/src/test/unittest/README b/src/test/unittest/README new file mode 100644 index 0000000000000000000000000000000000000000..6b174a34859b6422c6ce9a3b4d63256771ffd687 --- /dev/null +++ b/src/test/unittest/README @@ -0,0 +1,6 @@ +Linux NVM Library + +This is src/test/unittest/README. + +This directory contains the unit test framework used by +the NVM Library unit tests. diff --git a/src/test/unittest/unittest.h b/src/test/unittest/unittest.h new file mode 100644 index 0000000000000000000000000000000000000000..08912f1e36ce49a588ab02333aa2f6ec9643ef35 --- /dev/null +++ b/src/test/unittest/unittest.h @@ -0,0 +1,469 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * unittest.h -- the mundane stuff shared by all unit tests + * + * we want unit tests to be very thorough and check absolutely everything + * in order to nail down the test case as precisely as possible and flag + * anything at all unexpected. as a result, most unit tests are 90% code + * checking stuff that isn't really interesting to what is being tested. + * to help address this, the macros defined here include all the boilerplate + * error checking which prints information and exits on unexpected errors. + * + * the result changes this code: + * + * if ((buf = malloc(size)) == NULL) { + * fprintf(stderr, "cannot allocate %d bytes for buf\n", size); + * exit(1); + * } + * + * into this code: + * + * buf = MALLOC(size); + * + * and the error message includes the calling context information (file:line). + * in general, using the all-caps version of a call means you're using the + * unittest.h version which does the most common checking for you. so + * calling VMEM_POOL_CREATE() instead of vmem_pool_create() returns the same + * thing, but can never return an error since the unit test library checks for + * it. * for routines like vmem_pool_delete() there is no corresponding + * VMEM_POOL_DELETE() because there's no error to check for. + * + * all unit tests should use the same initialization: + * + * START(argc, argv, "brief test description", ...); + * + * all unit tests should use these exit calls: + * + * DONE("message", ...); + * FATAL("message", ...); + * + * uniform stderr and stdout messages: + * + * OUT("message", ...); + * ERR("message", ...); + * + * in all cases above, the message is printf-like, taking variable args. + * the message can be NULL. it can start with "!" in which case the "!" is + * skipped and the message gets the errno string appended to it, like this: + * + * if (somesyscall(..) < 0) + * FATAL("!my message"); + */ + +#ifndef _UNITTEST_H +#define _UNITTEST_H 1 + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <stdarg.h> +#include <stdint.h> +#include <string.h> +#include <strings.h> +#include <setjmp.h> +#include <time.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <sys/file.h> +#include <sys/mount.h> +#include <uuid/uuid.h> +#include <fcntl.h> +#include <signal.h> +#include <errno.h> +#include <dirent.h> +#include <pthread.h> + +#include <libpmem.h> +#include <libvmem.h> + + +/* + * unit test support... + */ +void ut_start(const char *file, int line, const char *func, + int argc, char * const argv[], const char *fmt, ...) + __attribute__((format(printf, 6, 7))); +void ut_done(const char *file, int line, const char *func, + const char *fmt, ...) + __attribute__((format(printf, 4, 5))); +void ut_fatal(const char *file, int line, const char *func, + const char *fmt, ...) + __attribute__((format(printf, 4, 5))); +void ut_out(const char *file, int line, const char *func, + const char *fmt, ...) + __attribute__((format(printf, 4, 5))); +void ut_err(const char *file, int line, const char *func, + const char *fmt, ...) + __attribute__((format(printf, 4, 5))); + +/* indicate the start of the test */ +#define START(argc, argv, ...)\ + ut_start(__FILE__, __LINE__, __func__, argc, argv, __VA_ARGS__) + +/* normal exit from test */ +#define DONE(...)\ + ut_done(__FILE__, __LINE__, __func__, __VA_ARGS__) + +/* fatal error detected */ +#define FATAL(...)\ + ut_fatal(__FILE__, __LINE__, __func__, __VA_ARGS__) + +/* normal output */ +#define OUT(...)\ + ut_out(__FILE__, __LINE__, __func__, __VA_ARGS__) + +/* error output */ +#define ERR(...)\ + ut_err(__FILE__, __LINE__, __func__, __VA_ARGS__) + + +/* + * assertions... + */ + +/* assert a condition is true */ +#define ASSERT(cnd)\ + ((void)((cnd) || (ut_fatal(__FILE__, __LINE__, __func__,\ + "assertion failure: %s", #cnd), 0))) + +/* assertion with extra info printed if assertion fails */ +#define ASSERTinfo(cnd, info) \ + ((void)((cnd) || (ut_fatal(__FILE__, __LINE__, __func__,\ + "assertion failure: %s (%s = %s)", #cnd, #info, info), 0))) + +/* assert two integer values are equal */ +#define ASSERTeq(lhs, rhs)\ + ((void)(((lhs) == (rhs)) || (ut_fatal(__FILE__, __LINE__, __func__,\ + "assertion failure: %s (0x%llx) == %s (0x%llx)", #lhs,\ + (unsigned long long)(lhs), #rhs, (unsigned long long)(rhs)), 0))) + +/* assert two integer values are not equal */ +#define ASSERTne(lhs, rhs)\ + ((void)(((lhs) != (rhs)) || (ut_fatal(__FILE__, __LINE__, __func__,\ + "assertion failure: %s (0x%llx) != %s (0x%llx)", #lhs,\ + (unsigned long long)(lhs), #rhs, (unsigned long long)(rhs)), 0))) + +/* assert pointer is fits range of [start, start + size) */ +#define ASSERTrange(ptr, start, size)\ + ((void)(((uintptr_t)(ptr) >= (uintptr_t)(start) &&\ + (uintptr_t)(ptr) < (uintptr_t)(start) + (uintptr_t)(size)) ||\ + (ut_fatal(__FILE__, __LINE__, __func__,\ + "assert failure: %s (%p) is outside range [%s (%p), %s (%p))", #ptr,\ + (void *)(ptr), #start, (void *)(start), #start"+"#size,\ + (void *)((uintptr_t)(start) + (uintptr_t)(size))), 0))) + +/* + * memory allocation... + */ +void *ut_malloc(const char *file, int line, const char *func, size_t size); +void *ut_calloc(const char *file, int line, const char *func, + size_t nmemb, size_t size); +void ut_free(const char *file, int line, const char *func, void *ptr); +void *ut_realloc(const char *file, int line, const char *func, + void *ptr, size_t size); +char *ut_strdup(const char *file, int line, const char *func, + const char *str); +void *ut_pagealignmalloc(const char *file, int line, const char *func, + size_t size); +void *ut_memalign(const char *file, int line, const char *func, + size_t alignment, size_t size); + +/* a malloc() that can't return NULL */ +#define MALLOC(size)\ + ut_malloc(__FILE__, __LINE__, __func__, size) + +/* a calloc() that can't return NULL */ +#define CALLOC(nmemb, size)\ + ut_calloc(__FILE__, __LINE__, __func__, nmemb, size) + +/* a malloc() of zeroed memory */ +#define ZALLOC(size)\ + ut_calloc(__FILE__, __LINE__, __func__, 1, size) + +#define FREE(ptr)\ + ut_free(__FILE__, __LINE__, __func__, ptr) + +/* a realloc() that can't return NULL */ +#define REALLOC(ptr, size)\ + ut_realloc(__FILE__, __LINE__, __func__, ptr, size) + +/* a strdup() that can't return NULL */ +#define STRDUP(str)\ + ut_strdup(__FILE__, __LINE__, __func__, str) + +/* a malloc() that only returns page aligned memory */ +#define PAGEALIGNMALLOC(size)\ + ut_pagealignmalloc(__FILE__, __LINE__, __func__, size) + +/* a malloc() that returns memory with given alignment */ +#define MEMALIGN(alignment, size)\ + ut_memalign(__FILE__, __LINE__, __func__, alignment, size) + + +/* + * file operations + */ +int ut_open(const char *file, int line, const char *func, char *path, + int flags, ...); + +int ut_close(const char *file, int line, const char *func, int fd); + +int ut_unlink(const char *file, int line, const char *func, const char *path); + +int ut_access(const char *file, int line, const char *func, const char *path, + int mode); + +int ut_write(const char *file, int line, const char *func, int fd, + const void *buf, size_t len); + +int ut_read(const char *file, int line, const char *func, int fd, + void *buf, size_t len); + +int ut_readlink(const char *file, int line, const char *func, const char *path, + void *buf, size_t len); + +int ut_fcntl(const char *file, int line, const char *func, int fd, + int cmd, int num, ...); + +off_t ut_lseek(const char *file, int line, const char *func, int fd, + off_t offset, int whence); + +int ut_posix_fallocate(const char *file, int line, const char *func, int fd, + off_t offset, off_t len); + +int ut_stat(const char *file, int line, const char *func, const char *path, + struct stat *st_bufp); + +int ut_fstat(const char *file, int line, const char *func, int fd, + struct stat *st_bufp); + +int ut_flock(const char *file, int line, const char *func, int fd, int op); + +void *ut_mmap(const char *file, int line, const char *func, void *addr, + size_t length, int prot, int flags, int fd, off_t offset); + +int ut_munmap(const char *file, int line, const char *func, void *addr, + size_t length); + +int ut_mprotect(const char *file, int line, const char *func, void *addr, + size_t len, int prot); + +int ut_symlink(const char *file, int line, const char *func, + const char *oldpath, const char *newpath); + +int ut_link(const char *file, int line, const char *func, + const char *oldpath, const char *newpath); + +int ut_mkdir(const char *file, int line, const char *func, + const char *pathname, mode_t mode); + +int ut_rmdir(const char *file, int line, const char *func, + const char *pathname); + +int ut_rename(const char *file, int line, const char *func, + const char *oldpath, const char *newpath); + +int ut_mount(const char *file, int line, const char *func, const char *src, + const char *tar, const char *fstype, unsigned long flags, + const void *data); + +int ut_umount(const char *file, int line, const char *func, const char *tar); + +int ut_pselect(const char *file, int line, const char *func, int nfds, + fd_set *rfds, fd_set *wfds, fd_set *efds, const struct timespec *tv, + const sigset_t *sigmask); + +int ut_mknod(const char *file, int line, const char *func, + const char *pathname, mode_t mode, dev_t dev); + +int utstat(const char *file, int line, const char *func, const char *path, + struct stat *st_bufp); + +int ut_truncate(const char *file, int line, const char *func, + const char *path, off_t length); + +int ut_ftruncate(const char *file, int line, const char *func, + int fd, off_t length); + +int ut_chmod(const char *file, int line, const char *func, + const char *path, mode_t mode); + +DIR *ut_opendir(const char *file, int line, const char *func, const char *name); + +int ut_dirfd(const char *file, int line, const char *func, DIR *dirp); + +int ut_closedir(const char *file, int line, const char *func, DIR *dirp); + +/* an open() that can't return < 0 */ +#define OPEN(path, ...)\ + ut_open(__FILE__, __LINE__, __func__, path, __VA_ARGS__) + +/* a close() that can't return -1 */ +#define CLOSE(fd)\ + ut_close(__FILE__, __LINE__, __func__, fd) + +/* an unlink() that can't return -1 */ +#define UNLINK(path)\ + ut_unlink(__FILE__, __LINE__, __func__, path) + +/* an access() that can't return -1 */ +#define ACCESS(path, mode)\ + ut_access(__FILE__, __LINE__, __func__, path, mode) + +/* a write() that can't return -1 */ +#define WRITE(fd, buf, len)\ + ut_write(__FILE__, __LINE__, __func__, fd, buf, len) + +/* a read() that can't return -1 */ +#define READ(fd, buf, len)\ + ut_read(__FILE__, __LINE__, __func__, fd, buf, len) + +/* a readlink() that can't return -1 */ +#define READLINK(path, buf, len)\ + ut_readlink(__FILE__, __LINE__, __func__, path, buf, len) + +/* a lseek() that can't return -1 */ +#define LSEEK(fd, offset, whence)\ + ut_lseek(__FILE__, __LINE__, __func__, fd, offset, whence) +/* + * The C Standard specifies that at least one argument must be passed to + * the ellipsis, to ensure that the macro does not resolve to an expression + * with a trailing comma. So, when calling this macro if num = 0 + * pass in a 0 for the argument. + */ +#define FCNTL(fd, cmd, num, ...)\ + ut_fcntl(__FILE__, __LINE__, __func__, fd, cmd, num, __VA_ARGS__) + +#define POSIX_FALLOCATE(fd, off, len)\ + ut_posix_fallocate(__FILE__, __LINE__, __func__, fd, off, len) + +#define FSTAT(fd, st_bufp)\ + ut_fstat(__FILE__, __LINE__, __func__, fd, st_bufp) + +#define FLOCK(fd, op)\ + ut_flock(__FILE__, __LINE__, __func__, fd, op) + +/* a mmap() that can't return MAP_FAILED */ +#define MMAP(addr, len, prot, flags, fd, offset)\ + ut_mmap(__FILE__, __LINE__, __func__, addr, len, prot, flags, fd, offset); + +/* a munmap() that can't return -1 */ +#define MUNMAP(addr, length)\ + ut_munmap(__FILE__, __LINE__, __func__, addr, length); + +/* a mprotect() that can't return -1 */ +#define MPROTECT(addr, len, prot)\ + ut_mprotect(__FILE__, __LINE__, __func__, addr, len, prot); + +#define STAT(path, st_bufp)\ + ut_stat(__FILE__, __LINE__, __func__, path, st_bufp) + +#define SYMLINK(oldpath, newpath)\ + ut_symlink(__FILE__, __LINE__, __func__, oldpath, newpath) + +#define LINK(oldpath, newpath)\ + ut_link(__FILE__, __LINE__, __func__, oldpath, newpath) + +#define MKDIR(pathname, mode)\ + ut_mkdir(__FILE__, __LINE__, __func__, pathname, mode) + +#define RMDIR(pathname)\ + ut_rmdir(__FILE__, __LINE__, __func__, pathname) + +#define RENAME(oldpath, newpath)\ + ut_rename(__FILE__, __LINE__, __func__, oldpath, newpath) + +#define MOUNT(src, tar, fstype, flags, data)\ + ut_mount(__FILE__, __LINE__, __func__, src, tar, fstype, flags, data) + +#define UMOUNT(tar)\ + ut_umount(__FILE__, __LINE__, __func__, tar) + +#define PSELECT(nfds, rfds, wfds, efds, tv, sigmask)\ + ut_pselect(__FILE__, __LINE__, __func__, nfds, rfds, wfds, efds,\ + tv, sigmask) + +#define MKNOD(pathname, mode, dev)\ + ut_mknod(__FILE__, __LINE__, __func__, pathname, mode, dev) + +#define TRUNCATE(path, length)\ + ut_truncate(__FILE__, __LINE__, __func__, path, length) + +#define FTRUNCATE(fd, length)\ + ut_ftruncate(__FILE__, __LINE__, __func__, fd, length) + +#define CHMOD(path, mode)\ + ut_chmod(__FILE__, __LINE__, __func__, path, mode) + +#define OPENDIR(name)\ + ut_opendir(__FILE__, __LINE__, __func__, name) + +#define DIRFD(dirp)\ + ut_dirfd(__FILE__, __LINE__, __func__, dirp) + +#define CLOSEDIR(dirp)\ + ut_closedir(__FILE__, __LINE__, __func__, dirp) + +/* + * signals... + */ +int ut_sigvec(const char *file, int line, const char *func, + int sig, struct sigvec *vec, struct sigvec *ovec); + +/* a sigvec() that can't return an error */ +#define SIGVEC(sig, vec, ovec)\ + ut_sigvec(__FILE__, __LINE__, __func__, sig, vec, ovec) + +/* + * pthreads... + */ +int ut_pthread_create(const char *file, int line, const char *func, + pthread_t *restrict thread, + const pthread_attr_t *restrict attr, + void *(*start_routine)(void *), void *restrict arg); +int ut_pthread_join(const char *file, int line, const char *func, + pthread_t thread, void **value_ptr); + +/* a pthread_create() that can't return an error */ +#define PTHREAD_CREATE(thread, attr, start_routine, arg)\ + ut_pthread_create(__FILE__, __LINE__, __func__,\ + thread, attr, start_routine, arg) + +/* a pthread_join() that can't return an error */ +#define PTHREAD_JOIN(thread, value_ptr)\ + ut_pthread_join(__FILE__, __LINE__, __func__, thread, value_ptr) + +#endif /* unittest.h */ diff --git a/src/test/unittest/unittest.sh b/src/test/unittest/unittest.sh new file mode 100644 index 0000000000000000000000000000000000000000..48d74eded6a107b29f8764b76681eb65f004771b --- /dev/null +++ b/src/test/unittest/unittest.sh @@ -0,0 +1,215 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +. ../testconfig.sh + +# defaults +[ "$TEST" ] || export TEST=check +[ "$FS" ] || export FS=local +[ "$BUILD" ] || export BUILD=debug + +# force globs to fail if they don't match +shopt -s failglob + +# +# For non-static build testing, the variable TEST_LD_LIBRARY_PATH is +# constructed so the test pulls in the appropriate library from this +# source tree. To override this behavior (i.e. to force the test to +# use the libraries installed elsewhere on the system), set +# TEST_LD_LIBRARY_PATH and this script will not override it. +# +# For example, in a test directory, run: +# TEST_LD_LIBRARY_PATH=/usr/lib ./TEST0 +# +[ "$TEST_LD_LIBRARY_PATH" ] || { + case "$BUILD" + in + debug) + TEST_LD_LIBRARY_PATH=../../debug + ;; + nondebug) + TEST_LD_LIBRARY_PATH=../../nondebug + ;; + esac +} + +# +# When running static binary tests, append the build type to the binary +# +case "$BUILD" +in + static-*) + EXESUFFIX=.$BUILD + ;; +esac + +# +# The variable DIR is constructed so the test uss that directory when +# constructing test files. DIR is chosen based on the fs-type for +# this test, and if the appropriate fs-type doesn't have a directory +# defined in testconfig.sh, the test is skipped. +# +# This behavior can be overridden by setting DIR. For example: +# DIR=/force/test/dir ./TEST0 +# +[ "$DIR" ] || { + case "$FS" + in + local) + DIR=$LOCAL_FS_DIR + ;; + pmem) + DIR=$PMEM_FS_DIR + ;; + non-pmem) + DIR=$NON_PMEM_FS_DIR + ;; + esac + [ "$DIR" ] || { + [ "$UNITTEST_QUIET" ] || echo "$UNITTEST_NAME: SKIP fs-type $FS (not configured)" + exit 0 + } +} + +# +# The default is to turn on library logging to level 3 and save it to local files. +# Tests that don't want it on, should override these environment variables. +# +export VMEM_LOG_LEVEL=3 +export VMEM_LOG_FILE=vmem$UNITTEST_NUM.log +export PMEM_LOG_LEVEL=3 +export PMEM_LOG_FILE=pmem$UNITTEST_NUM.log + +# +# create_file -- create zeroed out files of a given length in megs +# +# example, to create two files, each 1GB in size: +# create_file 1024 testfile1 testfile2 +# +function create_file() { + size=$1 + shift + for file in $* + do + dd if=/dev/zero of=$file bs=1M count=$size >> prep$UNITTEST_NUM.log + done +} + +# +# create_holey_file -- create holey files of a given length in megs +# +# example, to create two files, each 1GB in size: +# create_holey_file 1024 testfile1 testfile2 +# +function create_holey_file() { + size=$1 + shift + for file in $* + do + truncate -s ${size}M $file >> prep$UNITTEST_NUM.log + done +} + +# +# expect_normal_exit -- run a given command, expect it to exit 0 +# +function expect_normal_exit() { + eval $ECHO LD_LIBRARY_PATH=$TEST_LD_LIBRARY_PATH \ + $TRACE $* +} + +# +# expect_abnormal_exit -- run a given command, expect it to exit non-zero +# +function expect_abnormal_exit() { + set +e + eval $ECHO LD_LIBRARY_PATH=$TEST_LD_LIBRARY_PATH \ + $TRACE $* + set -e +} + +# +# require_test_type -- only allow script to continue for a certain test type +# +function require_test_type() { + for type in $* + do + [ "$type" = "$TEST" ] && return + done + [ "$UNITTEST_QUIET" ] || echo "$UNITTEST_NAME: SKIP test-type $TEST ($* required)" + exit 0 +} + +# +# require_fs_type -- only allow script to continue for a certain fs type +# +function require_fs_type() { + for type in $* + do + [ "$type" = "$FS" ] && return + done + [ "$UNITTEST_QUIET" ] || echo "$UNITTEST_NAME: SKIP fs-type $FS ($* required)" + exit 0 +} + +# +# require_build_type -- only allow script to continue for a certain build type +# +function require_build_type() { + for type in $* + do + [ "$type" = "$BUILD" ] && return + done + [ "$UNITTEST_QUIET" ] || echo "$UNITTEST_NAME: SKIP build-type $BUILD ($* required)" + exit 0 +} + +# +# setup -- print message that test setup is commencing +# +function setup() { + echo "$UNITTEST_NAME: SETUP ($TEST/$FS/$BUILD)" +} + +# +# check -- check test results (using .match files) +# +function check() { + ../match *$UNITTEST_NUM.log.match +} + +# +# pass -- print message that the test has passed +# +function pass() { + echo $UNITTEST_NAME: PASS +} diff --git a/src/test/unittest/ut.c b/src/test/unittest/ut.c new file mode 100644 index 0000000000000000000000000000000000000000..a6eb5cbc2b7ddc38fa77651331c99a35111d3a7e --- /dev/null +++ b/src/test/unittest/ut.c @@ -0,0 +1,468 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * ut.c -- unit test support routines + * + * some of these functions look at errno, but none of them + * change errno -- it is preserved across these calls. + * + * ut_done() and ut_fatal() never return. + */ + +#include "unittest.h" + +/* RHEL5 seems to be missing decls, even though libc supports them */ +extern DIR *fdopendir(int fd); +extern ssize_t readlinkat(int, const char *restrict, char *restrict, size_t); + +#define MAXLOGNAME 100 /* maximum expected .log file name length */ +#define MAXPRINT 8192 /* maximum expected single print length */ + +/* + * output gets replicated to these files + */ +static FILE *Outfp; +static FILE *Errfp; +static FILE *Tracefp; + +static int Quiet; /* set by UNITTEST_QUIET env variable */ +static char *Testname; /* set by UNITTEST_NAME env variable */ + +/* + * flags that control output + */ +#define OF_NONL 1 /* do not append newline */ +#define OF_ERR 2 /* output is error output */ +#define OF_TRACE 4 /* output to trace file only */ +#define OF_LOUD 8 /* output even in Quiet mode */ +#define OF_NAME 16 /* include Testname in the output */ + +/* + * vout -- common output code, all output happens here + */ +static void +vout(int flags, const char *prepend, const char *fmt, va_list ap) +{ + char buf[MAXPRINT]; + int cc = 0; + int quiet = Quiet; + const char *sep = ""; + const char *errstr = ""; + const char *nl = "\n"; + + if (flags & OF_LOUD) + quiet = 0; + + if (flags & OF_NONL) + nl = ""; + + if (flags & OF_NAME && Testname) + cc += snprintf(&buf[cc], MAXPRINT - cc, "%s: ", Testname); + + if (prepend) { + const char *colon = ""; + + if (fmt) + colon = ": "; + + cc += snprintf(&buf[cc], MAXPRINT - cc, "%s%s", prepend, colon); + } + + if (fmt) { + if (*fmt == '!') { + fmt++; + sep = ": "; + errstr = strerror(errno); + } + cc += vsnprintf(&buf[cc], MAXPRINT - cc, fmt, ap); + } + + snprintf(&buf[cc], MAXPRINT - cc, "%s%s%s", sep, errstr, nl); + + /* buf has the fully-baked output, send it everywhere it goes... */ + fputs(buf, Tracefp); + if (flags & OF_ERR) { + fputs(buf, Errfp); + if (!quiet) + fputs(buf, stderr); + } else if ((flags & OF_TRACE) == 0) { + fputs(buf, Outfp); + if (!quiet) + fputs(buf, stdout); + } +} + +/* + * out -- printf-like output controlled by flags + */ +static void +out(int flags, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + + vout(flags, NULL, fmt, ap); + + va_end(ap); +} + +/* + * prefix -- emit the trace line prefix + */ +static void +prefix(const char *file, int line, const char *func) +{ + out(OF_NONL|OF_TRACE, "{%s:%d %s} ", file, line, func); +} + +/* + * lookup table for open files + */ +static struct fd_lut { + struct fd_lut *left; + struct fd_lut *right; + int fdnum; + char *fdfile; +} *Fd_lut; +int Fd_errcount; + +/* + * open_file_add -- add an open file to the lut + */ +static struct fd_lut * +open_file_add(struct fd_lut *root, int fdnum, const char *fdfile) +{ + if (root == NULL) { + root = ZALLOC(sizeof (*root)); + root->fdnum = fdnum; + root->fdfile = STRDUP(fdfile); + } else if (root->fdnum == fdnum) + FATAL("duplicate fdnum: %d", fdnum); + else if (root->fdnum < fdnum) + root->left = open_file_add(root->left, fdnum, fdfile); + else + root->right = open_file_add(root->right, fdnum, fdfile); + return root; +} + +/* + * open_file_remove -- find exact match & remove it from lut + * + * prints error if exact match not found, increments Fd_errcount + */ +static void +open_file_remove(struct fd_lut *root, int fdnum, const char *fdfile) +{ + if (root == NULL) { + ERR("unexpected open file: fd %d => \"%s\"", fdnum, fdfile); + Fd_errcount++; + } else if (root->fdnum == fdnum) { + if (root->fdfile == NULL) { + ERR("open file dup: fd %d => \"%s\"", fdnum, fdfile); + Fd_errcount++; + } else if (strcmp(root->fdfile, fdfile) == 0) { + /* found exact match */ + FREE(root->fdfile); + root->fdfile = NULL; + } else { + ERR("open file changed: fd %d was \"%s\" now \"%s\"", + fdnum, root->fdfile, fdfile); + Fd_errcount++; + } + } else if (root->fdnum < fdnum) + open_file_remove(root->left, fdnum, fdfile); + else + open_file_remove(root->right, fdnum, fdfile); +} + +/* + * open_file_walk -- walk lut for any left-overs + * + * prints error if any found, increments Fd_errcount + */ +static void +open_file_walk(struct fd_lut *root) +{ + if (root) { + open_file_walk(root->left); + if (root->fdfile) { + ERR("open file missing: fd %d => \"%s\"", + root->fdnum, root->fdfile); + Fd_errcount++; + } + open_file_walk(root->right); + } +} + +/* + * open_file_free -- free the lut + */ +static void +open_file_free(struct fd_lut *root) +{ + if (root) { + open_file_free(root->left); + open_file_free(root->right); + if (root->fdfile) + FREE(root->fdfile); + FREE(root); + } +} + +/* + * record_open_files -- make a list of open files (used at START() time) + */ +static void +record_open_files() +{ + int dirfd; + DIR *dirp = NULL; + struct dirent *dp; + + if ((dirfd = open("/proc/self/fd", O_RDONLY)) < 0 || + (dirp = fdopendir(dirfd)) == NULL) + FATAL("!/proc/self/fd"); + while ((dp = readdir(dirp)) != NULL) { + int fdnum; + char fdfile[PATH_MAX]; + int cc; + + if (*dp->d_name == '.') + continue; + if ((cc = readlinkat(dirfd, dp->d_name, fdfile, PATH_MAX)) < 0) + FATAL("!readlinkat: /proc/self/fd/%s", dp->d_name); + fdfile[cc] = '\0'; + fdnum = atoi(dp->d_name); + if (dirfd == fdnum) + continue; + Fd_lut = open_file_add(Fd_lut, fdnum, fdfile); + } + closedir(dirp); +} + +/* + * check_open_files -- verify open files match recorded open files + */ +static void +check_open_files() +{ + int dirfd; + DIR *dirp = NULL; + struct dirent *dp; + + if ((dirfd = open("/proc/self/fd", O_RDONLY)) < 0 || + (dirp = fdopendir(dirfd)) == NULL) + FATAL("!/proc/self/fd"); + while ((dp = readdir(dirp)) != NULL) { + int fdnum; + char fdfile[PATH_MAX]; + int cc; + + if (*dp->d_name == '.') + continue; + if ((cc = readlinkat(dirfd, dp->d_name, fdfile, PATH_MAX)) < 0) + FATAL("!readlinkat: /proc/self/fd/%s", dp->d_name); + fdfile[cc] = '\0'; + fdnum = atoi(dp->d_name); + if (dirfd == fdnum) + continue; + open_file_remove(Fd_lut, fdnum, fdfile); + } + closedir(dirp); + open_file_walk(Fd_lut); + if (Fd_errcount) + FATAL("open file list changed between START() and DONE()"); + open_file_free(Fd_lut); +} + +/* + * ut_start -- initialize unit test framework, indicate test started + */ +void +ut_start(const char *file, int line, const char *func, + int argc, char * const argv[], const char *fmt, ...) +{ + va_list ap; + int saveerrno = errno; + char logname[MAXLOGNAME]; + char *logsuffix; + + va_start(ap, fmt); + + if (getenv("UNITTEST_QUIET") != NULL) + Quiet++; + + Testname = getenv("UNITTEST_NAME"); + + if ((logsuffix = getenv("UNITTEST_NUM")) == NULL) + logsuffix = ""; + + snprintf(logname, MAXLOGNAME, "out%s.log", logsuffix); + if ((Outfp = fopen(logname, "w")) == NULL) { + perror(logname); + exit(1); + } + + snprintf(logname, MAXLOGNAME, "err%s.log", logsuffix); + if ((Errfp = fopen(logname, "w")) == NULL) { + perror(logname); + exit(1); + } + + snprintf(logname, MAXLOGNAME, "trace%s.log", logsuffix); + if ((Tracefp = fopen(logname, "w")) == NULL) { + perror(logname); + exit(1); + } + + setlinebuf(Outfp); + setlinebuf(Errfp); + setlinebuf(Tracefp); + setlinebuf(stdout); + + prefix(file, line, func); + vout(OF_LOUD|OF_NAME, "START", fmt, ap); + + out(OF_NONL, 0, " args:"); + for (int i = 0; i < argc; i++) + out(OF_NONL, " %s", argv[i]); + out(0, NULL); + + va_end(ap); + + /* generate a uuid so the leaked fd gets recorded */ + uuid_t u; + uuid_generate(u); + + record_open_files(); + + errno = saveerrno; +} + +/* + * ut_done -- indicate test is done, exit program + */ +void +ut_done(const char *file, int line, const char *func, + const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + + check_open_files(); + + prefix(file, line, func); + vout(OF_NAME, "Done", fmt, ap); + + va_end(ap); + + if (Outfp != NULL) + fclose(Outfp); + + if (Errfp != NULL) + fclose(Errfp); + + if (Tracefp != NULL) + fclose(Tracefp); + + exit(0); +} + +/* + * ut_fatal -- indicate fatal error, exit program + */ +void +ut_fatal(const char *file, int line, const char *func, + const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + + prefix(file, line, func); + vout(OF_ERR|OF_NAME, "Error", fmt, ap); + + va_end(ap); + + if (Outfp != NULL) + fclose(Outfp); + + if (Errfp != NULL) + fclose(Errfp); + + if (Tracefp != NULL) + fclose(Tracefp); + + exit(1); +} + +/* + * ut_out -- output to stdout + */ +void +ut_out(const char *file, int line, const char *func, + const char *fmt, ...) +{ + va_list ap; + int saveerrno = errno; + + va_start(ap, fmt); + + prefix(file, line, func); + vout(0, NULL, fmt, ap); + + va_end(ap); + + errno = saveerrno; +} + +/* + * ut_err -- output to stderr + */ +void +ut_err(const char *file, int line, const char *func, + const char *fmt, ...) +{ + va_list ap; + int saveerrno = errno; + + va_start(ap, fmt); + + prefix(file, line, func); + vout(OF_ERR|OF_NAME, NULL, fmt, ap); + + va_end(ap); + + errno = saveerrno; +} diff --git a/src/test/unittest/ut_alloc.c b/src/test/unittest/ut_alloc.c new file mode 100644 index 0000000000000000000000000000000000000000..649a98483b9b2ec3d096cd630d884baa73776a17 --- /dev/null +++ b/src/test/unittest/ut_alloc.c @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * ut_alloc.c -- unit test memory allocation routines + */ + +#include "unittest.h" + +/* + * ut_malloc -- a malloc that cannot return NULL + */ +void * +ut_malloc(const char *file, int line, const char *func, size_t size) +{ + void *retval = malloc(size); + + if (retval == NULL) + ut_fatal(file, line, func, "cannot malloc %zu bytes", size); + + return retval; +} + +/* + * ut_calloc -- a calloc that cannot return NULL + */ +void * +ut_calloc(const char *file, int line, const char *func, + size_t nmemb, size_t size) +{ + void *retval = calloc(nmemb, size); + + if (retval == NULL) + ut_fatal(file, line, func, "cannot calloc %zu bytes", size); + + return retval; +} + +/* + * ut_free -- wrapper for free + * + * technically we don't need to wrap free since there's no return to + * check. using this wrapper to add memory allocation tracking later. + */ +void +ut_free(const char *file, int line, const char *func, void *ptr) +{ + free(ptr); +} + +/* + * ut_realloc -- a realloc that cannot return NULL + */ +void * +ut_realloc(const char *file, int line, const char *func, + void *ptr, size_t size) +{ + void *retval = realloc(ptr, size); + + if (retval == NULL) + ut_fatal(file, line, func, "cannot realloc %zu bytes", size); + + return retval; +} + +/* + * ut_strdup -- a strdup that cannot return NULL + */ +char * +ut_strdup(const char *file, int line, const char *func, + const char *str) +{ + char *retval = strdup(str); + + if (retval == NULL) + ut_fatal(file, line, func, "cannot strdup %zu bytes", + strlen(str)); + + return retval; +} + +/* + * ut_pagealignmalloc -- like malloc but page-aligned memory + */ +void * +ut_pagealignmalloc(const char *file, int line, const char *func, + size_t size) +{ + static long pagesize; + + if (pagesize == 0) + pagesize = sysconf(_SC_PAGESIZE); + + return ut_memalign(file, line, func, (size_t)pagesize, size); +} + +/* + * ut_memalign -- like malloc but page-aligned memory + */ +void * +ut_memalign(const char *file, int line, const char *func, size_t alignment, + size_t size) +{ + void *retval; + + if ((errno = posix_memalign(&retval, alignment, size)) != 0) + ut_fatal(file, line, func, + "!memalign %zu bytes (%zu alignment)", size, alignment); + + return retval; +} diff --git a/src/test/unittest/ut_file.c b/src/test/unittest/ut_file.c new file mode 100644 index 0000000000000000000000000000000000000000..8e9352289f353b70b4856f29a4dbaa5aa9c79b08 --- /dev/null +++ b/src/test/unittest/ut_file.c @@ -0,0 +1,531 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * ut_file.c -- unit test file operations + */ + +#include "unittest.h" + +/* + * ut_open -- an open that cannot return < 0 + */ +int +ut_open(const char *file, int line, const char *func, char *path, + int flags, ...) +{ + va_list ap; + int mode; + + va_start(ap, flags); + mode = va_arg(ap, int); + int retval = open(path, flags, mode); + va_end(ap); + + if (retval < 0) + ut_fatal(file, line, func, "!open: %s", path); + + return retval; +} + +/* + * ut_close -- a close that cannot return -1 + */ +int +ut_close(const char *file, int line, const char *func, int fd) +{ + int retval = close(fd); + + if (retval != 0) + ut_fatal(file, line, func, "!close: %d", fd); + + return retval; +} + +/* + * ut_unlink -- an unlink that cannot return -1 + */ +int +ut_unlink(const char *file, int line, const char *func, const char *path) +{ + int retval = unlink(path); + + if (retval != 0) + ut_fatal(file, line, func, "!unlink: %s", path); + + return retval; +} + +/* + * ut_posix_fallocate -- a posix_fallocate that cannot return -1 + */ +int +ut_posix_fallocate(const char *file, int line, const char *func, int fd, + off_t offset, off_t len) +{ + int retval = posix_fallocate(fd, offset, len); + + if (retval != 0) { + errno = retval; + ut_fatal(file, line, func, + "!fallocate: fd %d offset 0x%llx len %llu", + fd, (unsigned long long)offset, (unsigned long long)len); + } + + return retval; +} + +/* + * ut_access -- an access that cannot return -1 + */ +int +ut_access(const char *file, int line, const char *func, const char *path, + int mode) +{ + int retval = access(path, mode); + + if (retval != 0) + ut_fatal(file, line, func, "!access: %s: %d", path, mode); + + return retval; +} + +/* + * ut_write -- a write that can't return -1 + */ +int +ut_write(const char *file, int line, const char *func, int fd, + const void *buf, size_t count) +{ + int retval = write(fd, buf, count); + + if (retval < 0) + ut_fatal(file, line, func, "!write: %d", fd); + + return retval; +} + +/* + * ut_read -- a read that can't return -1 + */ +int +ut_read(const char *file, int line, const char *func, int fd, + void *buf, size_t count) +{ + int retval = read(fd, buf, count); + + if (retval < 0) + ut_fatal(file, line, func, "!read: %d", fd); + + return retval; +} + +/* + * ut_readlink -- a readlink that can't return -1 + */ +int +ut_readlink(const char *file, int line, const char *func, const char *path, + void *buf, size_t count) +{ + int retval = readlink(path, buf, count); + + if (retval < 0) + ut_fatal(file, line, func, "!readlink: %s", path); + + return retval; +} + +/* + * ut_lseek -- an lseek that can't return -1 + */ +off_t +ut_lseek(const char *file, int line, const char *func, int fd, + off_t offset, int whence) +{ + int retval = lseek(fd, offset, whence); + + if (retval == (off_t)-1) + ut_fatal(file, line, func, "!lseek: %d", fd); + + return retval; +} + +int +ut_fcntl(const char *file, int line, const char *func, int fd, + int cmd, int num, ...) +{ + + int retval; + va_list args; + uint64_t arg = 0; + + /* + * In the case of fcntl, num is always 0 or 1 + */ + if (num != 0) { + va_start(args, num); + arg = va_arg(args, uint64_t); + retval = fcntl(fd, cmd, arg); + va_end(args); + } else + retval = fcntl(fd, cmd); + + if (retval < 0) + ut_fatal(file, line, func, "!fcntl: %d", fd); + + return retval; +} + +/* + * ut_fstat -- a fstat that cannot return -1 + */ +int +ut_fstat(const char *file, int line, const char *func, int fd, + struct stat *st_bufp) +{ + int retval = fstat(fd, st_bufp); + + if (retval < 0) + ut_fatal(file, line, func, "!fstat: %d", fd); + + return retval; +} + +/* + * ut_flock -- a flock that cannot return -1 + */ +int +ut_flock(const char *file, int line, const char *func, int fd, int op) +{ + int retval = flock(fd, op); + + if (retval != 0) + ut_fatal(file, line, func, "!flock: %d", fd); + + return retval; +} + +/* + * ut_stat -- a stat that cannot return -1 + */ +int +ut_stat(const char *file, int line, const char *func, const char *path, + struct stat *st_bufp) +{ + int retval = stat(path, st_bufp); + + if (retval < 0) + ut_fatal(file, line, func, "!stat: %s", path); + + return retval; +} + +/* + * ut_mmap -- a mmap call that cannot return MAP_FAILED + */ +void * +ut_mmap(const char *file, int line, const char *func, void *addr, + size_t length, int prot, int flags, int fd, off_t offset) +{ + void *ret_addr = mmap(addr, length, prot, flags, fd, offset); + + if (ret_addr == MAP_FAILED) + ut_fatal(file, line, func, + "!mmap: addr=0x%llx length=0x%zx prot=%d flags=%d fd=%d " + "offset=0x%llx", (unsigned long long)addr, + length, prot, flags, fd, (unsigned long long)offset); + + return ret_addr; +} + +/* + * ut_munmap -- a munmap call that cannot return -1 + */ +int +ut_munmap(const char *file, int line, const char *func, void *addr, + size_t length) +{ + int retval = munmap(addr, length); + + if (retval < 0) + ut_fatal(file, line, func, "!munmap: addr=0x%llx length=0x%zx", + (unsigned long long)addr, length); + + return retval; +} + +/* + * ut_mprotect -- a mprotect call that cannot return -1 + */ +int +ut_mprotect(const char *file, int line, const char *func, void *addr, + size_t len, int prot) +{ + int retval = mprotect(addr, len, prot); + + if (retval < 0) + ut_fatal(file, line, func, + "!mprotect: addr=0x%llx length=0x%zx prot=0x%x", + (unsigned long long)addr, len, prot); + + return retval; +} + +/* + * ut_symlink -- a symlink that cannot return -1 + */ +int +ut_symlink(const char *file, int line, const char *func, const char *oldpath, + const char *newpath) +{ + int retval = symlink(oldpath, newpath); + + if (retval < 0) + ut_fatal(file, line, func, "!symlink: %s %s", oldpath, newpath); + + return retval; +} + +/* + * ut_link -- a link that cannot return -1 + */ +int +ut_link(const char *file, int line, const char *func, const char *oldpath, + const char *newpath) +{ + int retval = link(oldpath, newpath); + + if (retval < 0) + ut_fatal(file, line, func, "!link: %s %s", oldpath, + newpath); + + return retval; +} + +/* + * ut_mkdir -- a mkdir that cannot return -1 + */ +int +ut_mkdir(const char *file, int line, const char *func, + const char *pathname, mode_t mode) +{ + int retval = mkdir(pathname, mode); + + if (retval < 0) + ut_fatal(file, line, func, "!mkdir: %s", pathname); + + return retval; +} + +/* + * ut_rmdir -- a rmdir that cannot return -1 + */ +int +ut_rmdir(const char *file, int line, const char *func, + const char *pathname) +{ + int retval = rmdir(pathname); + + if (retval < 0) + ut_fatal(file, line, func, "!rmdir: %s", pathname); + + return retval; +} + +/* + * ut_rename -- a rename that cannot return -1 + */ +int +ut_rename(const char *file, int line, const char *func, + const char *oldpath, const char *newpath) +{ + int retval = rename(oldpath, newpath); + + if (retval < 0) + ut_fatal(file, line, func, "!rename: %s %s", oldpath, newpath); + + return retval; +} + +/* + * ut_mount -- a mount that cannot return -1 + */ +int +ut_mount(const char *file, int line, const char *func, const char *src, + const char *tar, const char *fstype, unsigned long flags, + const void *data) +{ + int retval = mount(src, tar, fstype, flags, data); + + if (retval < 0) + ut_fatal(file, line, func, "!mount: %s %s %s %lx", + src, tar, fstype, flags); + + return retval; +} + +/* + * ut_umount -- a umount that cannot return -1 + */ +int +ut_umount(const char *file, int line, const char *func, const char *tar) +{ + int retval = umount(tar); + + if (retval < 0) + ut_fatal(file, line, func, "!umount: %s", tar); + + return retval; +} + + +/* + * ut_truncate -- a truncate that cannot return -1 + */ +int +ut_truncate(const char *file, int line, const char *func, const char *path, + off_t length) +{ + int retval = truncate(path, length); + + if (retval < 0) + ut_fatal(file, line, func, "!truncate: %s %llu", + path, (unsigned long long)length); + + return retval; +} + +/* + * ut_ftruncate -- a ftruncate that cannot return -1 + */ +int +ut_ftruncate(const char *file, int line, const char *func, int fd, + off_t length) +{ + int retval = ftruncate(fd, length); + + if (retval < 0) + ut_fatal(file, line, func, "!ftruncate: %d %llu", + fd, (unsigned long long)length); + + return retval; +} + +/* + * ut_chmod -- a chmod that cannot return -1 + */ +int +ut_chmod(const char *file, int line, const char *func, const char *path, + mode_t mode) +{ + int retval = chmod(path, mode); + + if (retval < 0) + ut_fatal(file, line, func, "!mode: %s %o", path, mode); + + return retval; +} + +/* + * ut_mknod -- a mknod that cannot return -1 + */ +int +ut_mknod(const char *file, int line, const char *func, const char *pathname, + mode_t mode, dev_t dev) +{ + int retval = mknod(pathname, mode, dev); + + if (retval < 0) + ut_fatal(file, line, func, "!mknod: %s", pathname); + + return retval; +} + +/* + * ut_pselect -- a pselect that cannot return -1 + */ +int +ut_pselect(const char *file, int line, const char *func, int nfds, + fd_set *rfds, fd_set *wfds, fd_set *efds, const struct timespec *tv, + const sigset_t *sigmask) +{ + int retval = pselect(nfds, rfds, wfds, efds, tv, sigmask); + + if (retval < 0) + ut_fatal(file, line, func, "!pselect"); + + return retval; +} + +/* + * ut_opendir -- an opendir that cannot return NULL + */ +DIR * +ut_opendir(const char *file, int line, const char *func, + const char *name) +{ + DIR *retval = opendir(name); + + if (retval == NULL) + ut_fatal(file, line, func, "!opendir: %s", name); + + return retval; +} + +/* + * ut_dirfd -- a dirfd that cannot return -1 + */ +int +ut_dirfd(const char *file, int line, const char *func, + DIR *dirp) +{ + int retval = dirfd(dirp); + + if (retval < 0) + ut_fatal(file, line, func, "!dirfd: %p", dirp); + + return retval; +} + +/* + * ut_closedir -- a closedir that cannot return -1 + */ +int +ut_closedir(const char *file, int line, const char *func, DIR *dirp) +{ + int retval = closedir(dirp); + + if (retval < 0) + ut_fatal(file, line, func, "!closedir: %p", dirp); + + return retval; +} diff --git a/src/test/unittest/ut_pthread.c b/src/test/unittest/ut_pthread.c new file mode 100644 index 0000000000000000000000000000000000000000..68e534cf326a41588098cf5df382a21c686e3498 --- /dev/null +++ b/src/test/unittest/ut_pthread.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * ut_pthread.c -- unit test wrappers for pthread routines + */ + +#include "unittest.h" + +/* + * ut_pthread_create -- a pthread_create that cannot return an error + */ +int +ut_pthread_create(const char *file, int line, const char *func, + pthread_t *restrict thread, + const pthread_attr_t *restrict attr, + void *(*start_routine)(void *), void *restrict arg) +{ + if ((errno = pthread_create(thread, attr, start_routine, arg)) != 0) + ut_fatal(file, line, func, "!pthread_create"); + + return 0; +} + +/* + * ut_pthread_join -- a pthread_join that cannot return an error + */ +int +ut_pthread_join(const char *file, int line, const char *func, + pthread_t thread, void **value_ptr) +{ + if ((errno = pthread_join(thread, value_ptr)) != 0) + ut_fatal(file, line, func, "!pthread_join"); + + return 0; +} diff --git a/src/test/unittest/ut_signal.c b/src/test/unittest/ut_signal.c new file mode 100644 index 0000000000000000000000000000000000000000..17bd6760938dab7fd702a71205867acce23c102e --- /dev/null +++ b/src/test/unittest/ut_signal.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * ut_signal.c -- unit test signal operations + */ + +#include "unittest.h" + +/* + * ut_sigvec -- a sigvec that cannot return < 0 + */ +int +ut_sigvec(const char *file, int line, const char *func, + int sig, struct sigvec *vec, struct sigvec *ovec) +{ + int retval = sigvec(sig, vec, ovec); + + if (retval != 0) + ut_fatal(file, line, func, "!sigvec: %s", strsignal(sig)); + + return retval; +} diff --git a/src/test/vmem_aligned_alloc/.gitignore b/src/test/vmem_aligned_alloc/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..ab9ed3eb38a68804fa810055ea6025f4e7c7eb50 --- /dev/null +++ b/src/test/vmem_aligned_alloc/.gitignore @@ -0,0 +1 @@ +vmem_aligned_alloc diff --git a/src/test/vmem_aligned_alloc/Makefile b/src/test/vmem_aligned_alloc/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..1ee8040946b9ed3276d4f99748063831cbd470fc --- /dev/null +++ b/src/test/vmem_aligned_alloc/Makefile @@ -0,0 +1,45 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_aligned_alloc/Makefile -- build vmem_aligned_alloc unit test +# +TARGET = vmem_aligned_alloc +OBJS = vmem_aligned_alloc.o + +include ../Makefile.inc +STATIC_DEBUG_LIBS = ../unittest/libut.a ../../debug/libvmem.a -luuid -pthread +STATIC_NONDEBUG_LIBS = ../unittest/libut.a ../../nondebug/libvmem.a -luuid -pthread + +LIBS += -lvmem + +vmem_aligned_alloc.o: vmem_aligned_alloc.c diff --git a/src/test/vmem_aligned_alloc/TEST0 b/src/test/vmem_aligned_alloc/TEST0 new file mode 100755 index 0000000000000000000000000000000000000000..624b7f4bd1d6061d691561c019d059cd2cc96ed8 --- /dev/null +++ b/src/test/vmem_aligned_alloc/TEST0 @@ -0,0 +1,51 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_aligned_alloc/TEST0 -- unit test for vmem_aligned_alloc +# +export UNITTEST_NAME=vmem_aligned_alloc/TEST0 +export UNITTEST_NUM=0 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local + +setup + +expect_normal_exit ./vmem_aligned_alloc$EXESUFFIX + +check + +pass diff --git a/src/test/vmem_aligned_alloc/TEST1 b/src/test/vmem_aligned_alloc/TEST1 new file mode 100755 index 0000000000000000000000000000000000000000..f889608228c6a95ebd340d063133daca46f0d0bc --- /dev/null +++ b/src/test/vmem_aligned_alloc/TEST1 @@ -0,0 +1,51 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_aligned_alloc/TEST1 -- unit test for vmem_aligned_alloc +# +export UNITTEST_NAME=vmem_aligned_alloc/TEST1 +export UNITTEST_NUM=1 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type pmem + +setup + +expect_normal_exit ./vmem_aligned_alloc$EXESUFFIX $DIR + +check + +pass diff --git a/src/test/vmem_aligned_alloc/err0.log.match b/src/test/vmem_aligned_alloc/err0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/vmem_aligned_alloc/err1.log.match b/src/test/vmem_aligned_alloc/err1.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/vmem_aligned_alloc/out0.log.match b/src/test/vmem_aligned_alloc/out0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e329d2e1e40a66ff5c5fa6301e6f947d083afaab --- /dev/null +++ b/src/test/vmem_aligned_alloc/out0.log.match @@ -0,0 +1,3 @@ +vmem_aligned_alloc/TEST0: START: vmem_aligned_alloc + ./vmem_aligned_alloc$(*) +vmem_aligned_alloc/TEST0: Done diff --git a/src/test/vmem_aligned_alloc/out1.log.match b/src/test/vmem_aligned_alloc/out1.log.match new file mode 100644 index 0000000000000000000000000000000000000000..a994d1c2a5940d3572f9d198c3baccb4e3fc1a07 --- /dev/null +++ b/src/test/vmem_aligned_alloc/out1.log.match @@ -0,0 +1,3 @@ +vmem_aligned_alloc/TEST1: START: vmem_aligned_alloc + ./vmem_aligned_alloc$(*) +vmem_aligned_alloc/TEST1: Done diff --git a/src/test/vmem_aligned_alloc/vmem_aligned_alloc.c b/src/test/vmem_aligned_alloc/vmem_aligned_alloc.c new file mode 100644 index 0000000000000000000000000000000000000000..275f18c9575400e1caa620bf9e12b10a434939c2 --- /dev/null +++ b/src/test/vmem_aligned_alloc/vmem_aligned_alloc.c @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * vmem_aligned_alloc.c -- unit test for vmem_aligned_alloc + * + * usage: vmem_aligned_alloc [directory] + */ + +#include "unittest.h" + +#define MAX_ALLOCS (100) + +static char mem_pool[VMEM_MIN_POOL]; + + +static int custom_allocs; +static int custom_alloc_calls; + +/* + * malloc_custom -- custom malloc function + * + * This function updates statistics about custom alloc functions, + * and returns allocated memory. + */ +void * +malloc_custom(size_t size) +{ + ++custom_alloc_calls; + ++custom_allocs; + return malloc(size); +} + +/* + * free_custom -- custom free function + * + * This function updates statistics about custom alloc functions, + * and frees allocated memory. + */ +void +free_custom(void *ptr) +{ + ++custom_alloc_calls; + --custom_allocs; + free(ptr); +} + +/* + * realloc_custom -- custom realloc function + * + * This function updates statistics about custom alloc functions, + * and returns reallocated memory. + */ +void * +realloc_custom(void *ptr, size_t size) +{ + ++custom_alloc_calls; + return realloc(ptr, size); +} + +/* + * strdup_custom -- custom strdup function + * + * This function updates statistics about custom alloc functions, + * and returns allocated memory with a duplicated string. + */ +char * +strdup_custom(const char *s) +{ + ++custom_alloc_calls; + ++custom_allocs; + return strdup(s); +} + +int +main(int argc, char *argv[]) +{ + const int test_value = 123456; + char *dir = NULL; + VMEM *vmp; + size_t alignment; + unsigned i; + int *ptr; + + START(argc, argv, "vmem_aligned_alloc"); + + if (argc == 2) { + dir = argv[1]; + } else if (argc > 2) { + FATAL("usage: %s [directory]", argv[0]); + } + + /* use custom alloc functions to check for memory leaks */ + vmem_set_funcs(malloc_custom, free_custom, + realloc_custom, strdup_custom, NULL); + + /* test with address alignment from 2B to 4MB */ + for (alignment = 2; alignment <= 4 * 1024 * 1024; alignment *= 2) { + + custom_alloc_calls = 0; + if (dir == NULL) { + vmp = vmem_pool_create_in_region(mem_pool, + VMEM_MIN_POOL); + if (vmp == NULL) + FATAL("!vmem_pool_create_in_region"); + } else { + vmp = vmem_pool_create(dir, VMEM_MIN_POOL); + if (vmp == NULL) + FATAL("!vmem_pool_create"); + } + + for (i = 0; i < MAX_ALLOCS; ++i) { + ptr = vmem_aligned_alloc(vmp, alignment, sizeof (int)); + + /* at least one allocation must succeed */ + ASSERT(i != 0 || ptr != NULL); + if (ptr == NULL) + break; + + /* ptr should be usable */ + *ptr = test_value; + ASSERTeq(*ptr, test_value); + + /* check for correct address alignment */ + ASSERTeq((uintptr_t)(ptr) & (alignment - 1), 0); + + /* check that pointer came from mem_pool */ + if (dir == NULL) { + ASSERTrange(ptr, mem_pool, VMEM_MIN_POOL); + } + } + + vmem_pool_delete(vmp); + + /* check memory leaks */ + ASSERTne(custom_alloc_calls, 0); + ASSERTeq(custom_allocs, 0); + } + + + DONE(NULL); +} diff --git a/src/test/vmem_calloc/.gitignore b/src/test/vmem_calloc/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..47e8c1e79502e11f75c603632622cd0b54dd6202 --- /dev/null +++ b/src/test/vmem_calloc/.gitignore @@ -0,0 +1 @@ +vmem_calloc diff --git a/src/test/vmem_calloc/Makefile b/src/test/vmem_calloc/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..93649ed8c9273c9d1fe7473d96f7f8efbb984f93 --- /dev/null +++ b/src/test/vmem_calloc/Makefile @@ -0,0 +1,45 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_calloc/Makefile -- build vmem_calloc unit test +# +TARGET = vmem_calloc +OBJS = vmem_calloc.o + +include ../Makefile.inc +STATIC_DEBUG_LIBS = ../unittest/libut.a ../../debug/libvmem.a -luuid -pthread +STATIC_NONDEBUG_LIBS = ../unittest/libut.a ../../nondebug/libvmem.a -luuid -pthread + +LIBS += -lvmem + +vmem_calloc.o: vmem_calloc.c diff --git a/src/test/vmem_calloc/TEST0 b/src/test/vmem_calloc/TEST0 new file mode 100755 index 0000000000000000000000000000000000000000..a4ae3510853f48e58889815161fbb958bbff318c --- /dev/null +++ b/src/test/vmem_calloc/TEST0 @@ -0,0 +1,51 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_calloc/TEST0 -- unit test for vmem_calloc +# +export UNITTEST_NAME=vmem_calloc/TEST0 +export UNITTEST_NUM=0 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local + +setup + +expect_normal_exit ./vmem_calloc$EXESUFFIX + +check + +pass diff --git a/src/test/vmem_calloc/TEST1 b/src/test/vmem_calloc/TEST1 new file mode 100755 index 0000000000000000000000000000000000000000..5e5a420cc84ba5564cd7e7d98727ad4bb2ffe358 --- /dev/null +++ b/src/test/vmem_calloc/TEST1 @@ -0,0 +1,51 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_calloc/TEST1 -- unit test for vmem_calloc +# +export UNITTEST_NAME=vmem_calloc/TEST1 +export UNITTEST_NUM=1 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type pmem + +setup + +expect_normal_exit ./vmem_calloc$EXESUFFIX $DIR + +check + +pass diff --git a/src/test/vmem_calloc/err0.log.match b/src/test/vmem_calloc/err0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/vmem_calloc/err1.log.match b/src/test/vmem_calloc/err1.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/vmem_calloc/out0.log.match b/src/test/vmem_calloc/out0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..fdb4c562f05bf135ff0c04ace83b3849fa246c02 --- /dev/null +++ b/src/test/vmem_calloc/out0.log.match @@ -0,0 +1,3 @@ +vmem_calloc/TEST0: START: vmem_calloc + ./vmem_calloc$(*) +vmem_calloc/TEST0: Done diff --git a/src/test/vmem_calloc/out1.log.match b/src/test/vmem_calloc/out1.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e09228590c8e5bf7433849ebeac11832db5cb7be --- /dev/null +++ b/src/test/vmem_calloc/out1.log.match @@ -0,0 +1,3 @@ +vmem_calloc/TEST1: START: vmem_calloc + ./vmem_calloc$(*) +vmem_calloc/TEST1: Done diff --git a/src/test/vmem_calloc/vmem_calloc.c b/src/test/vmem_calloc/vmem_calloc.c new file mode 100644 index 0000000000000000000000000000000000000000..36eff308a89266a360b164446b8e93ec3894dbe0 --- /dev/null +++ b/src/test/vmem_calloc/vmem_calloc.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * vmem_calloc.c -- unit test for vmem_calloc + * + * usage: vmem_calloc [directory] + */ + +#include "unittest.h" + +static char mem_pool[VMEM_MIN_POOL]; + +int +main(int argc, char *argv[]) +{ + const int test_value = 123456; + char *dir = NULL; + VMEM *vmp; + + START(argc, argv, "vmem_calloc"); + + if (argc == 2) { + dir = argv[1]; + } else if (argc > 2) { + FATAL("usage: %s [directory]", argv[0]); + } + + if (dir == NULL) { + vmp = vmem_pool_create_in_region(mem_pool, VMEM_MIN_POOL); + if (vmp == NULL) + FATAL("!vmem_pool_create_in_region"); + } else { + vmp = vmem_pool_create(dir, VMEM_MIN_POOL); + if (vmp == NULL) + FATAL("!vmem_pool_create"); + } + + int *test = vmem_calloc(vmp, 1, sizeof (int)); + ASSERTne(test, NULL); + + /* pool_calloc should return zeroed memory */ + ASSERTeq(*test, 0); + + *test = test_value; + ASSERTeq(*test, test_value); + + /* check that pointer came from mem_pool */ + if (dir == NULL) { + ASSERTrange(test, mem_pool, VMEM_MIN_POOL); + } + + vmem_free(vmp, test); + + vmem_pool_delete(vmp); + + DONE(NULL); +} diff --git a/src/test/vmem_check_allocations/.gitignore b/src/test/vmem_check_allocations/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..aded80d9167adf30b5239e231515537de4757e05 --- /dev/null +++ b/src/test/vmem_check_allocations/.gitignore @@ -0,0 +1 @@ +vmem_check_allocations diff --git a/src/test/vmem_check_allocations/Makefile b/src/test/vmem_check_allocations/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..18149fdba1d9f098ee28f58080645e89f6fad778 --- /dev/null +++ b/src/test/vmem_check_allocations/Makefile @@ -0,0 +1,45 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_check_allocations/Makefile -- build vmem_check_allocations unit test +# +TARGET = vmem_check_allocations +OBJS = vmem_check_allocations.o + +include ../Makefile.inc +STATIC_DEBUG_LIBS = ../unittest/libut.a ../../debug/libvmem.a -luuid -pthread +STATIC_NONDEBUG_LIBS = ../unittest/libut.a ../../nondebug/libvmem.a -luuid -pthread + +LIBS += -lvmem + +vmem_check_allocations.o: vmem_check_allocations.c diff --git a/src/test/vmem_check_allocations/TEST0 b/src/test/vmem_check_allocations/TEST0 new file mode 100755 index 0000000000000000000000000000000000000000..160ac93ec0b910824efecc91eb6f62ac0c524f61 --- /dev/null +++ b/src/test/vmem_check_allocations/TEST0 @@ -0,0 +1,55 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_check_allocations/TEST0 -- unit test for vmem_check_allocations +# +export UNITTEST_NAME=vmem_check_allocations/TEST0 +export UNITTEST_NUM=0 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local +require_build_type debug nondebug + +setup + +#limit output for file vmem*.log to reduce time of execution test +export VMEM_LOG_LEVEL=2 + +expect_normal_exit ./vmem_check_allocations$EXESUFFIX + +check + +pass diff --git a/src/test/vmem_check_allocations/TEST1 b/src/test/vmem_check_allocations/TEST1 new file mode 100755 index 0000000000000000000000000000000000000000..e92f6056409082600503b0af2905720de4a640ea --- /dev/null +++ b/src/test/vmem_check_allocations/TEST1 @@ -0,0 +1,55 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_check_allocations/TEST1 -- unit test for vmem_check_allocations +# +export UNITTEST_NAME=vmem_check_allocations/TEST1 +export UNITTEST_NUM=1 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type pmem +require_build_type debug nondebug + +setup + +#limit output for file vmem*.log to reduce time of test execution +export VMEM_LOG_LEVEL=2 + +expect_normal_exit ./vmem_check_allocations$EXESUFFIX $DIR + +check + +pass diff --git a/src/test/vmem_check_allocations/err0.log.match b/src/test/vmem_check_allocations/err0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/vmem_check_allocations/err1.log.match b/src/test/vmem_check_allocations/err1.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/vmem_check_allocations/out0.log.match b/src/test/vmem_check_allocations/out0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..53e996178da4c6e35d7f9be75c9a3480143dfb35 --- /dev/null +++ b/src/test/vmem_check_allocations/out0.log.match @@ -0,0 +1,3 @@ +vmem_check_allocations/TEST0: START: vmem_check_allocations + ./vmem_check_allocations$(*) +vmem_check_allocations/TEST0: Done diff --git a/src/test/vmem_check_allocations/out1.log.match b/src/test/vmem_check_allocations/out1.log.match new file mode 100644 index 0000000000000000000000000000000000000000..a81b41e2e38cc9f67b9ed36b2778b9c9a7896617 --- /dev/null +++ b/src/test/vmem_check_allocations/out1.log.match @@ -0,0 +1,3 @@ +vmem_check_allocations/TEST1: START: vmem_check_allocations + ./vmem_check_allocations$(*) +vmem_check_allocations/TEST1: Done diff --git a/src/test/vmem_check_allocations/vmem_check_allocations.c b/src/test/vmem_check_allocations/vmem_check_allocations.c new file mode 100644 index 0000000000000000000000000000000000000000..d9168a98d3e2fb375642923be0e57a6f3d933c3a --- /dev/null +++ b/src/test/vmem_check_allocations/vmem_check_allocations.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * vmem_check_allocations -- unit test for vmem_check_allocations + * + * usage: vmem_check_allocations [directory] + */ + +#include "unittest.h" + +#define TEST_MAX_ALLOCATION_SIZE (4L * 1024L * 1024L) +#define TEST_ALLOCS_SIZE (VMEM_MIN_POOL / 8) + +static char mem_pool[VMEM_MIN_POOL]; + +/* buffer for all allocations */ +static void *allocs[TEST_ALLOCS_SIZE]; + +int +main(int argc, char *argv[]) +{ + char *dir = NULL; + VMEM *vmp; + + START(argc, argv, "vmem_check_allocations"); + + if (argc == 2) { + dir = argv[1]; + } else if (argc > 2) { + FATAL("usage: %s [directory]", argv[0]); + } + + size_t object_size; + for (object_size = 8; object_size <= TEST_MAX_ALLOCATION_SIZE; + object_size *= 2) { + size_t i; + size_t j; + + if (dir == NULL) { + vmp = vmem_pool_create_in_region(mem_pool, + VMEM_MIN_POOL); + if (vmp == NULL) + FATAL("!vmem_pool_create_in_region"); + } else { + vmp = vmem_pool_create(dir, VMEM_MIN_POOL); + if (vmp == NULL) + FATAL("!vmem_pool_create"); + } + + memset(allocs, 0, TEST_ALLOCS_SIZE); + + for (i = 0; i < TEST_ALLOCS_SIZE; ++i) { + allocs[i] = vmem_malloc(vmp, object_size); + if (allocs[i] == NULL) { + /* out of memory in pool */ + break; + } + + /* check that pointer came from mem_pool */ + if (dir == NULL) { + ASSERTrange(allocs[i], + mem_pool, VMEM_MIN_POOL); + } + + /* fill each allocation with a unique value */ + memset(allocs[i], (char)i, object_size); + } + + ASSERT((i > 0) && (i + 1 < TEST_MAX_ALLOCATION_SIZE)); + + /* check for unexpected modifications of the data */ + for (i = 0; i < TEST_ALLOCS_SIZE && allocs[i] != NULL; ++i) { + char *buffer = allocs[i]; + for (j = 0; j < object_size; ++j) { + if (buffer[j] != (char)i) + FATAL("Content of data object was " + "modified unexpectedly for " + "object size: %zu, id: %zu", + object_size, j); + } + } + + vmem_pool_delete(vmp); + } + + DONE(NULL); +} diff --git a/src/test/vmem_check_version/.gitignore b/src/test/vmem_check_version/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..374742a23fec7196300b8695d42120d0ea27cbf2 --- /dev/null +++ b/src/test/vmem_check_version/.gitignore @@ -0,0 +1 @@ +vmem_check_version diff --git a/src/test/vmem_check_version/Makefile b/src/test/vmem_check_version/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..4ea13af9d1a7a288489a0595d38b7dab596eb36c --- /dev/null +++ b/src/test/vmem_check_version/Makefile @@ -0,0 +1,45 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_check_version/Makefile -- build vmem_check_version unit test +# +TARGET = vmem_check_version +OBJS = vmem_check_version.o + +include ../Makefile.inc +STATIC_DEBUG_LIBS = ../unittest/libut.a ../../debug/libvmem.a -luuid -pthread +STATIC_NONDEBUG_LIBS = ../unittest/libut.a ../../nondebug/libvmem.a -luuid -pthread + +LIBS += -lvmem + +vmem_check_version.o: vmem_check_version.c diff --git a/src/test/vmem_check_version/TEST0 b/src/test/vmem_check_version/TEST0 new file mode 100755 index 0000000000000000000000000000000000000000..4fa99851899260b192dbf78999b06b67b4c0ea59 --- /dev/null +++ b/src/test/vmem_check_version/TEST0 @@ -0,0 +1,51 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_check_version/TEST0 -- unit test for vmem_check_version +# +export UNITTEST_NAME=vmem_check_version/TEST0 +export UNITTEST_NUM=0 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local + +setup + +expect_normal_exit ./vmem_check_version$EXESUFFIX + +check + +pass diff --git a/src/test/vmem_check_version/out0.log.match b/src/test/vmem_check_version/out0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..b39e92bb37fde329c5902983055176e0ef5788f5 --- /dev/null +++ b/src/test/vmem_check_version/out0.log.match @@ -0,0 +1,5 @@ +vmem_check_version/TEST0: START: vmem_check_version + ./vmem_check_version$(*) +compile-time libvmem version is 1.0 +for major version 2, vmem_check_version returned: libvmem major version mismatch (need 2, found 1) +vmem_check_version/TEST0: Done diff --git a/src/test/vmem_check_version/vmem_check_version.c b/src/test/vmem_check_version/vmem_check_version.c new file mode 100644 index 0000000000000000000000000000000000000000..b2054304c353be4bb6b0cb62fde61125f2166c54 --- /dev/null +++ b/src/test/vmem_check_version/vmem_check_version.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * vmem_check_version.c -- unit test for vmem_check_version + */ + +#include "unittest.h" + +int +main(int argc, char *argv[]) +{ + START(argc, argv, "vmem_check_version"); + + OUT("compile-time libvmem version is %d.%d", + VMEM_MAJOR_VERSION, VMEM_MINOR_VERSION); + + const char *errstr = vmem_check_version(VMEM_MAJOR_VERSION, + VMEM_MINOR_VERSION); + + ASSERTinfo(errstr == NULL, errstr); + + errstr = vmem_check_version(VMEM_MAJOR_VERSION + 1, VMEM_MINOR_VERSION); + + ASSERT(errstr != NULL); + + OUT("for major version %d, vmem_check_version returned: %s", + VMEM_MAJOR_VERSION + 1, errstr); + + DONE(NULL); +} diff --git a/src/test/vmem_custom_alloc/.gitignore b/src/test/vmem_custom_alloc/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..fd421c1c7cde54e8ec9aa4a4bc813d8e17a195d9 --- /dev/null +++ b/src/test/vmem_custom_alloc/.gitignore @@ -0,0 +1 @@ +vmem_custom_alloc diff --git a/src/test/vmem_custom_alloc/Makefile b/src/test/vmem_custom_alloc/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..f1617418b257a92cb45c6ab4c4fbd2ead6e700bc --- /dev/null +++ b/src/test/vmem_custom_alloc/Makefile @@ -0,0 +1,45 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_custom_alloc/Makefile -- build vmem_custom_alloc unit test +# +TARGET = vmem_custom_alloc +OBJS = vmem_custom_alloc.o + +include ../Makefile.inc +STATIC_DEBUG_LIBS = ../unittest/libut.a ../../debug/libvmem.a -luuid -pthread +STATIC_NONDEBUG_LIBS = ../unittest/libut.a ../../nondebug/libvmem.a -luuid -pthread + +LIBS += -lvmem + +vmem_custom_alloc.o: vmem_custom_alloc.c diff --git a/src/test/vmem_custom_alloc/TEST0 b/src/test/vmem_custom_alloc/TEST0 new file mode 100755 index 0000000000000000000000000000000000000000..9542a14560d9392085faa1210d432928db2c6cfb --- /dev/null +++ b/src/test/vmem_custom_alloc/TEST0 @@ -0,0 +1,49 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_custom_alloc/TEST0 -- unit test for vmem_custom_alloc +# +export UNITTEST_NAME=vmem_custom_alloc/TEST0 +export UNITTEST_NUM=0 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local + +setup + +expect_normal_exit ./vmem_custom_alloc$EXESUFFIX 0 + +pass diff --git a/src/test/vmem_custom_alloc/TEST1 b/src/test/vmem_custom_alloc/TEST1 new file mode 100755 index 0000000000000000000000000000000000000000..e09e463c8934af19ffa96f1a30bd2b5ce9915f02 --- /dev/null +++ b/src/test/vmem_custom_alloc/TEST1 @@ -0,0 +1,49 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_custom_alloc/TEST1 -- unit test for vmem_custom_alloc +# +export UNITTEST_NAME=vmem_custom_alloc/TEST1 +export UNITTEST_NUM=1 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local + +setup + +expect_normal_exit ./vmem_custom_alloc$EXESUFFIX 1 + +pass diff --git a/src/test/vmem_custom_alloc/TEST2 b/src/test/vmem_custom_alloc/TEST2 new file mode 100755 index 0000000000000000000000000000000000000000..ccfc17e42feae2bfa25d0e49035b33af7aa5248f --- /dev/null +++ b/src/test/vmem_custom_alloc/TEST2 @@ -0,0 +1,49 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_custom_alloc/TEST2 -- unit test for vmem_custom_alloc +# +export UNITTEST_NAME=vmem_custom_alloc/TEST2 +export UNITTEST_NUM=2 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local + +setup + +expect_normal_exit ./vmem_custom_alloc$EXESUFFIX 2 + +pass diff --git a/src/test/vmem_custom_alloc/TEST3 b/src/test/vmem_custom_alloc/TEST3 new file mode 100755 index 0000000000000000000000000000000000000000..af01239f266969050a972820c7154e49b3dc4d48 --- /dev/null +++ b/src/test/vmem_custom_alloc/TEST3 @@ -0,0 +1,49 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_custom_alloc/TEST3 -- unit test for vmem_custom_alloc +# +export UNITTEST_NAME=vmem_custom_alloc/TEST3 +export UNITTEST_NUM=3 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local + +setup + +expect_normal_exit ./vmem_custom_alloc$EXESUFFIX 0 $DIR + +pass diff --git a/src/test/vmem_custom_alloc/TEST4 b/src/test/vmem_custom_alloc/TEST4 new file mode 100755 index 0000000000000000000000000000000000000000..cabdb521368a8b0952da2309064a8a0d37a88f13 --- /dev/null +++ b/src/test/vmem_custom_alloc/TEST4 @@ -0,0 +1,49 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_custom_alloc/TEST4 -- unit test for vmem_custom_alloc +# +export UNITTEST_NAME=vmem_custom_alloc/TEST4 +export UNITTEST_NUM=4 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local + +setup + +expect_normal_exit ./vmem_custom_alloc$EXESUFFIX 1 $DIR + +pass diff --git a/src/test/vmem_custom_alloc/TEST5 b/src/test/vmem_custom_alloc/TEST5 new file mode 100755 index 0000000000000000000000000000000000000000..94a511fefadd0274b9652cc26f732e6688744084 --- /dev/null +++ b/src/test/vmem_custom_alloc/TEST5 @@ -0,0 +1,49 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_custom_alloc/TEST5 -- unit test for vmem_custom_alloc +# +export UNITTEST_NAME=vmem_custom_alloc/TEST5 +export UNITTEST_NUM=5 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local + +setup + +expect_normal_exit ./vmem_custom_alloc$EXESUFFIX 2 $DIR + +pass diff --git a/src/test/vmem_custom_alloc/vmem_custom_alloc.c b/src/test/vmem_custom_alloc/vmem_custom_alloc.c new file mode 100644 index 0000000000000000000000000000000000000000..2ab5b44bda82287f81a5f88fdb7b13e57841dafc --- /dev/null +++ b/src/test/vmem_custom_alloc/vmem_custom_alloc.c @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * vmem_custom_alloc.c -- unit test for vmem_custom_alloc + * + * usage: vmem_custom_alloc (0-2) [directory] + */ + +#include "unittest.h" + +#define TEST_STRING_VALUE "Some test text, to check memory" +#define TEST_REPEAT_CREATE_POOLS (20) + +static char mem_pool[VMEM_MIN_POOL]; + +static int custom_allocs; +static int custom_alloc_calls; +static int expect_create_pool; + +/* + * malloc_null -- custom malloc function with error + * + * This function updates statistics about custom alloc functions, + * and returns NULL. + */ +void * +malloc_null(size_t size) +{ + ++custom_alloc_calls; + return NULL; +} + +/* + * malloc_custom -- custom malloc function + * + * This function updates statistics about custom alloc functions, + * and returns allocated memory. + */ +void * +malloc_custom(size_t size) +{ + ++custom_alloc_calls; + ++custom_allocs; + return malloc(size); +} + +/* + * free_custom -- custom free function + * + * This function updates statistics about custom alloc functions, + * and frees allocated memory. + */ +void +free_custom(void *ptr) +{ + ++custom_alloc_calls; + --custom_allocs; + free(ptr); +} + +/* + * realloc_custom -- custom realloc function + * + * This function updates statistics about custom alloc functions, + * and returns reallocated memory. + */ +void * +realloc_custom(void *ptr, size_t size) +{ + ++custom_alloc_calls; + return realloc(ptr, size); +} + +/* + * strdup_custom -- custom strdup function + * + * This function updates statistics about custom alloc functions, + * and returns allocated memory with a duplicated string. + */ +char * +strdup_custom(const char *s) +{ + ++custom_alloc_calls; + ++custom_allocs; + return strdup(s); +} + +/* + * pool_test -- test pool + * + * This function creates a memory pool in a file (if dir is not NULL), + * or in RAM (if dir is NULL) and allocates memory for the test. + */ +void +pool_test(const char *dir) +{ + VMEM *vmp = NULL; + + if (dir != NULL) { + vmp = vmem_pool_create(dir, VMEM_MIN_POOL); + } else { + vmp = vmem_pool_create_in_region(mem_pool, VMEM_MIN_POOL); + } + + if (expect_create_pool == 0) { + ASSERTeq(vmp, NULL); + DONE(NULL); + } else { + if (vmp == NULL) { + if (dir == NULL) { + FATAL("!vmem_pool_create_in_region"); + } else { + FATAL("!vmem_pool_create"); + } + } + } + + char *test = vmem_malloc(vmp, strlen(TEST_STRING_VALUE) + 1); + ASSERTne(test, NULL); + + strcpy(test, TEST_STRING_VALUE); + ASSERTeq(strcmp(test, TEST_STRING_VALUE), 0); + + vmem_free(vmp, test); + + vmem_pool_delete(vmp); +} + +int +main(int argc, char *argv[]) +{ + int expect_custom_alloc = 0; + + START(argc, argv, "vmem_custom_alloc"); + + if (argc < 2 || argc > 3 || strlen(argv[1]) != 1) + FATAL("usage: %s (0-2) [directory]", argv[0]); + + switch (argv[1][0]) { + case '0': { + /* use default allocator */ + expect_custom_alloc = 0; + expect_create_pool = 1; + break; + } + case '1': { + /* error in custom malloc function */ + expect_custom_alloc = 1; + expect_create_pool = 0; + vmem_set_funcs(malloc_null, free_custom, + realloc_custom, strdup_custom, NULL); + break; + } + case '2': { + /* use custom alloc functions */ + expect_custom_alloc = 1; + expect_create_pool = 1; + vmem_set_funcs(malloc_custom, free_custom, + realloc_custom, strdup_custom, NULL); + break; + } + default: { + FATAL("usage: %s (0-2) [directory]", argv[0]); + break; + } + } + + if (argc == 3) { + pool_test(argv[2]); + } else { + int i; + /* repeat create pool */ + for (i = 0; i < TEST_REPEAT_CREATE_POOLS; ++i) + pool_test(NULL); + } + + /* check memory leak in custom allocator */ + ASSERTeq(custom_allocs, 0); + + if (expect_custom_alloc == 0) { + ASSERTeq(custom_alloc_calls, 0); + } else { + ASSERTne(custom_alloc_calls, 0); + } + + DONE(NULL); +} diff --git a/src/test/vmem_malloc/.gitignore b/src/test/vmem_malloc/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..50ae73f3c496bd9a627377a0c107925ac6b89bef --- /dev/null +++ b/src/test/vmem_malloc/.gitignore @@ -0,0 +1 @@ +vmem_malloc diff --git a/src/test/vmem_malloc/Makefile b/src/test/vmem_malloc/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..5f85a48f00030dcaa0ace94497893492e88b29b4 --- /dev/null +++ b/src/test/vmem_malloc/Makefile @@ -0,0 +1,45 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_malloc/Makefile -- build vmem_malloc unit test +# +TARGET = vmem_malloc +OBJS = vmem_malloc.o + +include ../Makefile.inc +STATIC_DEBUG_LIBS = ../unittest/libut.a ../../debug/libvmem.a -luuid -pthread +STATIC_NONDEBUG_LIBS = ../unittest/libut.a ../../nondebug/libvmem.a -luuid -pthread + +LIBS += -lvmem + +vmem_malloc.o: vmem_malloc.c diff --git a/src/test/vmem_malloc/TEST0 b/src/test/vmem_malloc/TEST0 new file mode 100755 index 0000000000000000000000000000000000000000..67560fccc3b692ec9f13f1ee8f81335d98244b5f --- /dev/null +++ b/src/test/vmem_malloc/TEST0 @@ -0,0 +1,51 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_malloc/TEST0 -- unit test for vmem_malloc +# +export UNITTEST_NAME=vmem_malloc/TEST0 +export UNITTEST_NUM=0 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local + +setup + +expect_normal_exit ./vmem_malloc$EXESUFFIX + +check + +pass diff --git a/src/test/vmem_malloc/TEST1 b/src/test/vmem_malloc/TEST1 new file mode 100755 index 0000000000000000000000000000000000000000..d187cb28e0bda265007f576026be23e0941014e5 --- /dev/null +++ b/src/test/vmem_malloc/TEST1 @@ -0,0 +1,51 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_malloc/TEST1 -- unit test for vmem_malloc +# +export UNITTEST_NAME=vmem_malloc/TEST1 +export UNITTEST_NUM=1 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type pmem + +setup + +expect_normal_exit ./vmem_malloc$EXESUFFIX $DIR + +check + +pass diff --git a/src/test/vmem_malloc/err0.log.match b/src/test/vmem_malloc/err0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/vmem_malloc/err1.log.match b/src/test/vmem_malloc/err1.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/vmem_malloc/out0.log.match b/src/test/vmem_malloc/out0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e43c104a9487a8993869297c002d7935737535b7 --- /dev/null +++ b/src/test/vmem_malloc/out0.log.match @@ -0,0 +1,3 @@ +vmem_malloc/TEST0: START: vmem_malloc + ./vmem_malloc$(*) +vmem_malloc/TEST0: Done diff --git a/src/test/vmem_malloc/out1.log.match b/src/test/vmem_malloc/out1.log.match new file mode 100644 index 0000000000000000000000000000000000000000..27636b7a9a5af055ee8a81db50a55f7a14fb3293 --- /dev/null +++ b/src/test/vmem_malloc/out1.log.match @@ -0,0 +1,3 @@ +vmem_malloc/TEST1: START: vmem_malloc + ./vmem_malloc$(*) +vmem_malloc/TEST1: Done diff --git a/src/test/vmem_malloc/vmem_malloc.c b/src/test/vmem_malloc/vmem_malloc.c new file mode 100644 index 0000000000000000000000000000000000000000..0023afc3da8c343b6eed04008a403023badd1e19 --- /dev/null +++ b/src/test/vmem_malloc/vmem_malloc.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * vmem_malloc.c -- unit test for vmem_malloc + * + * usage: vmem_malloc [directory] + */ + +#include "unittest.h" + +static char mem_pool[VMEM_MIN_POOL]; + +int +main(int argc, char *argv[]) +{ + const int test_value = 123456; + char *dir = NULL; + VMEM *vmp; + + START(argc, argv, "vmem_malloc"); + + if (argc == 2) { + dir = argv[1]; + } else if (argc > 2) { + FATAL("usage: %s [directory]", argv[0]); + } + + if (dir == NULL) { + vmp = vmem_pool_create_in_region(mem_pool, VMEM_MIN_POOL); + if (vmp == NULL) + FATAL("!vmem_pool_create_in_region"); + } else { + vmp = vmem_pool_create(dir, VMEM_MIN_POOL); + if (vmp == NULL) + FATAL("!vmem_pool_create"); + } + + int *test = vmem_malloc(vmp, sizeof (int)); + ASSERTne(test, NULL); + *test = test_value; + ASSERTeq(*test, test_value); + + /* check that pointer came from mem_pool */ + if (dir == NULL) { + ASSERTrange(test, mem_pool, VMEM_MIN_POOL); + } + + vmem_free(vmp, test); + + vmem_pool_delete(vmp); + + DONE(NULL); +} diff --git a/src/test/vmem_mix_allocations/.gitignore b/src/test/vmem_mix_allocations/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..593aa0f5f7035e7b275891beb7053a33a6c9c7a5 --- /dev/null +++ b/src/test/vmem_mix_allocations/.gitignore @@ -0,0 +1 @@ +vmem_mix_allocations diff --git a/src/test/vmem_mix_allocations/Makefile b/src/test/vmem_mix_allocations/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..779fc62faf18ac916f179f33b9e90ca2768fbf1f --- /dev/null +++ b/src/test/vmem_mix_allocations/Makefile @@ -0,0 +1,45 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_mix_allocations/Makefile -- build vmem_mix_allocations unit test +# +TARGET = vmem_mix_allocations +OBJS = vmem_mix_allocations.o + +include ../Makefile.inc +STATIC_DEBUG_LIBS = ../unittest/libut.a ../../debug/libvmem.a -luuid -pthread +STATIC_NONDEBUG_LIBS = ../unittest/libut.a ../../nondebug/libvmem.a -luuid -pthread + +LIBS += -lvmem + +vmem_mix_allocations.o: vmem_mix_allocations.c diff --git a/src/test/vmem_mix_allocations/TEST0 b/src/test/vmem_mix_allocations/TEST0 new file mode 100755 index 0000000000000000000000000000000000000000..ced26532158570af3009b53da6fed34982d632c4 --- /dev/null +++ b/src/test/vmem_mix_allocations/TEST0 @@ -0,0 +1,52 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_mix_allocations/TEST0 -- unit test for vmem_mix_allocations +# +export UNITTEST_NAME=vmem_mix_allocations/TEST0 +export UNITTEST_NUM=0 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local +require_build_type debug nondebug + +setup + +expect_normal_exit ./vmem_mix_allocations$EXESUFFIX + +check + +pass diff --git a/src/test/vmem_mix_allocations/TEST1 b/src/test/vmem_mix_allocations/TEST1 new file mode 100755 index 0000000000000000000000000000000000000000..7114668c01a31d3d73e98da48a612621acbf450f --- /dev/null +++ b/src/test/vmem_mix_allocations/TEST1 @@ -0,0 +1,52 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_mix_allocations/TEST1 -- unit test for vmem_mix_allocations +# +export UNITTEST_NAME=vmem_mix_allocations/TEST1 +export UNITTEST_NUM=1 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type pmem +require_build_type debug nondebug + +setup + +expect_normal_exit ./vmem_mix_allocations$EXESUFFIX $DIR + +check + +pass diff --git a/src/test/vmem_mix_allocations/err0.log.match b/src/test/vmem_mix_allocations/err0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/vmem_mix_allocations/err1.log.match b/src/test/vmem_mix_allocations/err1.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/vmem_mix_allocations/out0.log.match b/src/test/vmem_mix_allocations/out0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..1d1d9a67987871e258433c0e5e0ed6a8435dac1e --- /dev/null +++ b/src/test/vmem_mix_allocations/out0.log.match @@ -0,0 +1,3 @@ +vmem_mix_allocations/TEST0: START: vmem_mix_allocations + ./vmem_mix_allocations$(*) +vmem_mix_allocations/TEST0: Done diff --git a/src/test/vmem_mix_allocations/out1.log.match b/src/test/vmem_mix_allocations/out1.log.match new file mode 100644 index 0000000000000000000000000000000000000000..17dc000014348a9239332baac8be20fee0e5898e --- /dev/null +++ b/src/test/vmem_mix_allocations/out1.log.match @@ -0,0 +1,3 @@ +vmem_mix_allocations/TEST1: START: vmem_mix_allocations + ./vmem_mix_allocations$(*) +vmem_mix_allocations/TEST1: Done diff --git a/src/test/vmem_mix_allocations/vmem_mix_allocations.c b/src/test/vmem_mix_allocations/vmem_mix_allocations.c new file mode 100644 index 0000000000000000000000000000000000000000..a6cba08939c7eceb057ee72bc32afc416d2c7864 --- /dev/null +++ b/src/test/vmem_mix_allocations/vmem_mix_allocations.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * vmem_mix_allocations.c -- unit test for vmem_mix_allocations + * + * usage: vmem_mix_allocations [directory] + */ + +#include "unittest.h" + +static char mem_pool[VMEM_MIN_POOL]; + +int +main(int argc, char *argv[]) +{ + char *dir = NULL; + VMEM *vmp; + size_t object_size; + int *ptr; + size_t sum_alloc = 0; + + START(argc, argv, "vmem_mix_allocations"); + + if (argc == 2) { + dir = argv[1]; + } else if (argc > 2) { + FATAL("usage: %s [directory]", argv[0]); + } + + if (dir == NULL) { + vmp = vmem_pool_create_in_region(mem_pool, VMEM_MIN_POOL); + if (vmp == NULL) + FATAL("!vmem_pool_create_in_region"); + } else { + vmp = vmem_pool_create(dir, VMEM_MIN_POOL); + if (vmp == NULL) + FATAL("!vmem_pool_create"); + } + + /* test with multiple size of allocations from 4MB to 2B */ + for (object_size = 4 * 1024 * 1024; object_size >= 4; object_size /= 2) + do { + ptr = vmem_malloc(vmp, object_size); + + if (ptr == NULL) + break; + + sum_alloc += object_size; + + /* check that pointer came from mem_pool */ + if (dir == NULL) { + ASSERTrange(ptr, mem_pool, VMEM_MIN_POOL); + } + } while (object_size == 2); + + /* allocate more than half of pool size */ + ASSERT(sum_alloc * 2 > VMEM_MIN_POOL); + + vmem_pool_delete(vmp); + + DONE(NULL); +} diff --git a/src/test/vmem_multiple_pools/.gitignore b/src/test/vmem_multiple_pools/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..6030f2e823a66d4f45b733d8d28473c0b37ebeb6 --- /dev/null +++ b/src/test/vmem_multiple_pools/.gitignore @@ -0,0 +1 @@ +vmem_multiple_pools diff --git a/src/test/vmem_multiple_pools/Makefile b/src/test/vmem_multiple_pools/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..a9e57e3fbe66586f9eefe541b63c4c6d2d15b4a1 --- /dev/null +++ b/src/test/vmem_multiple_pools/Makefile @@ -0,0 +1,45 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_multiple_pools/Makefile -- build vmem_multiple_pools unit test +# +TARGET = vmem_multiple_pools +OBJS = vmem_multiple_pools.o + +include ../Makefile.inc +STATIC_DEBUG_LIBS = ../unittest/libut.a ../../debug/libvmem.a -luuid -pthread +STATIC_NONDEBUG_LIBS = ../unittest/libut.a ../../nondebug/libvmem.a -luuid -pthread + +LIBS += -lvmem + +vmem_multiple_pools.o: vmem_multiple_pools.c diff --git a/src/test/vmem_multiple_pools/TEST0 b/src/test/vmem_multiple_pools/TEST0 new file mode 100755 index 0000000000000000000000000000000000000000..177ed85fc311e96ead9f921e8e55a67db2528e01 --- /dev/null +++ b/src/test/vmem_multiple_pools/TEST0 @@ -0,0 +1,52 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_multiple_pools/TEST0 -- unit test for vmem_multiple_pools +# +export UNITTEST_NAME=vmem_multiple_pools/TEST0 +export UNITTEST_NUM=0 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local +require_build_type debug nondebug + +setup + +expect_normal_exit ./vmem_multiple_pools$EXESUFFIX $DIR + +check + +pass diff --git a/src/test/vmem_multiple_pools/err0.log.match b/src/test/vmem_multiple_pools/err0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/vmem_multiple_pools/out0.log.match b/src/test/vmem_multiple_pools/out0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..b3fc582abb309c1671d1325cc2887bb9c9bd6f48 --- /dev/null +++ b/src/test/vmem_multiple_pools/out0.log.match @@ -0,0 +1,3 @@ +vmem_multiple_pools/TEST0: START: vmem_multiple_pools + ./vmem_multiple_pools$(*) +vmem_multiple_pools/TEST0: Done diff --git a/src/test/vmem_multiple_pools/vmem_multiple_pools.c b/src/test/vmem_multiple_pools/vmem_multiple_pools.c new file mode 100644 index 0000000000000000000000000000000000000000..1432bceab6427fd8bed5ac3f52e7ed9d78f0a123 --- /dev/null +++ b/src/test/vmem_multiple_pools/vmem_multiple_pools.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * vmem_multiple_pools.c -- unit test for vmem_multiple_pools + * + * usage: vmem_multiple_pools directory + */ + +#include "unittest.h" + +#define TEST_POOLS_MAX (9) +#define TEST_REPEAT_CREATE_POOLS (30) + +static char mem_pools[TEST_POOLS_MAX/2][VMEM_MIN_POOL]; + +VMEM *pools[TEST_POOLS_MAX]; + +int +main(int argc, char *argv[]) +{ + START(argc, argv, "vmem_multiple_pools"); + + if (argc < 2 || argc > 3) + FATAL("usage: %s directory", argv[0]); + + const char *dir = argv[1]; + + /* create and destroy pools multiple times */ + size_t repeat; + size_t pool_id; + for (repeat = 0; repeat < TEST_REPEAT_CREATE_POOLS; ++repeat) { + for (pool_id = 0; pool_id < TEST_POOLS_MAX; ++pool_id) { + + /* delete old pool with this same id if exist */ + if (pools[pool_id] != NULL) { + vmem_pool_delete(pools[pool_id]); + pools[pool_id] = NULL; + } + + if (pool_id % 2 == 0) { + /* for even pool_id, create in region */ + pools[pool_id] = vmem_pool_create_in_region( + mem_pools[pool_id % 2], VMEM_MIN_POOL); + if (pools[pool_id] == NULL) + FATAL("!vmem_pool_create_in_region"); + } else { + /* for odd pool_id, create in file */ + pools[pool_id] = vmem_pool_create(dir, + VMEM_MIN_POOL); + if (pools[pool_id] == NULL) + FATAL("!vmem_pool_create"); + } + + void *test = vmem_malloc(pools[pool_id], + sizeof (void *)); + + ASSERTne(test, NULL); + vmem_free(pools[pool_id], test); + } + } + + for (pool_id = 0; pool_id < TEST_POOLS_MAX; ++pool_id) { + if (pools[pool_id] != NULL) { + vmem_pool_delete(pools[pool_id]); + pools[pool_id] = NULL; + } + } + + DONE(NULL); +} diff --git a/src/test/vmem_out_of_memory/.gitignore b/src/test/vmem_out_of_memory/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..56b02bb3d55a6d390a1e708fcd13a12cbfb295bf --- /dev/null +++ b/src/test/vmem_out_of_memory/.gitignore @@ -0,0 +1 @@ +vmem_out_of_memory diff --git a/src/test/vmem_out_of_memory/Makefile b/src/test/vmem_out_of_memory/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..cd08c646a830572aaf1e50754c1fdf40082113dd --- /dev/null +++ b/src/test/vmem_out_of_memory/Makefile @@ -0,0 +1,45 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_out_of_memory/Makefile -- build vmem_out_of_memory unit test +# +TARGET = vmem_out_of_memory +OBJS = vmem_out_of_memory.o + +include ../Makefile.inc +STATIC_DEBUG_LIBS = ../unittest/libut.a ../../debug/libvmem.a -luuid -pthread +STATIC_NONDEBUG_LIBS = ../unittest/libut.a ../../nondebug/libvmem.a -luuid -pthread + +LIBS += -lvmem + +vmem_out_of_memory.o: vmem_out_of_memory.c diff --git a/src/test/vmem_out_of_memory/TEST0 b/src/test/vmem_out_of_memory/TEST0 new file mode 100755 index 0000000000000000000000000000000000000000..bfe454a7c0866f1618c5d37331948fba6a09f683 --- /dev/null +++ b/src/test/vmem_out_of_memory/TEST0 @@ -0,0 +1,55 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_out_of_memory/TEST0 -- unit test for vmem_out_of_memory +# +export UNITTEST_NAME=vmem_out_of_memory/TEST0 +export UNITTEST_NUM=0 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local +require_build_type debug nondebug + +setup + +#limit output for file vmem*.log to reduce time of test execution +export VMEM_LOG_LEVEL=2 + +expect_normal_exit ./vmem_out_of_memory$EXESUFFIX + +check + +pass diff --git a/src/test/vmem_out_of_memory/TEST1 b/src/test/vmem_out_of_memory/TEST1 new file mode 100755 index 0000000000000000000000000000000000000000..3d46693e45dcf9718a1ec2bd6e1b9664c4edd24e --- /dev/null +++ b/src/test/vmem_out_of_memory/TEST1 @@ -0,0 +1,55 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_out_of_memory/TEST1 -- unit test for vmem_out_of_memory +# +export UNITTEST_NAME=vmem_out_of_memory/TEST1 +export UNITTEST_NUM=1 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type pmem +require_build_type debug nondebug + +setup + +#limit output for file vmem*.log to reduce time of test execution +export VMEM_LOG_LEVEL=2 + +expect_normal_exit ./vmem_out_of_memory$EXESUFFIX $DIR + +check + +pass diff --git a/src/test/vmem_out_of_memory/err0.log.match b/src/test/vmem_out_of_memory/err0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/vmem_out_of_memory/err1.log.match b/src/test/vmem_out_of_memory/err1.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/vmem_out_of_memory/out0.log.match b/src/test/vmem_out_of_memory/out0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..233b29cc92ee2bfca9523e40fb301138ad7bb913 --- /dev/null +++ b/src/test/vmem_out_of_memory/out0.log.match @@ -0,0 +1,3 @@ +vmem_out_of_memory/TEST0: START: vmem_out_of_memory + ./vmem_out_of_memory$(*) +vmem_out_of_memory/TEST0: Done diff --git a/src/test/vmem_out_of_memory/out1.log.match b/src/test/vmem_out_of_memory/out1.log.match new file mode 100644 index 0000000000000000000000000000000000000000..b6ba4431f7b5eb6c45cfcd17be3c8241880289e5 --- /dev/null +++ b/src/test/vmem_out_of_memory/out1.log.match @@ -0,0 +1,3 @@ +vmem_out_of_memory/TEST1: START: vmem_out_of_memory + ./vmem_out_of_memory$(*) +vmem_out_of_memory/TEST1: Done diff --git a/src/test/vmem_out_of_memory/vmem_out_of_memory.c b/src/test/vmem_out_of_memory/vmem_out_of_memory.c new file mode 100644 index 0000000000000000000000000000000000000000..ce98abd2cf5dafe609ebf2ebda08152c2a8948dc --- /dev/null +++ b/src/test/vmem_out_of_memory/vmem_out_of_memory.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * vmem_out_of_memory -- unit test for vmem_out_of_memory + * + * usage: vmem_out_of_memory [directory] + */ + +#include "unittest.h" + +static char mem_pool[VMEM_MIN_POOL]; + +int +main(int argc, char *argv[]) +{ + char *dir = NULL; + VMEM *vmp; + START(argc, argv, "vmem_out_of_memory"); + + if (argc == 2) { + dir = argv[1]; + } else if (argc > 2) { + FATAL("usage: %s [directory]", argv[0]); + } + + if (dir == NULL) { + vmp = vmem_pool_create_in_region(mem_pool, VMEM_MIN_POOL); + if (vmp == NULL) + FATAL("!vmem_pool_create_in_region"); + } else { + vmp = vmem_pool_create(dir, VMEM_MIN_POOL); + if (vmp == NULL) + FATAL("!vmem_pool_create"); + } + + /* allocate all memory */ + void *prev = NULL; + for (;;) { + void **next = vmem_malloc(vmp, sizeof (void *)); + if (next == NULL) { + /* out of memory */ + break; + } + + /* check that pointer came from mem_pool */ + if (dir == NULL) { + ASSERTrange(next, mem_pool, VMEM_MIN_POOL); + } + + *next = prev; + prev = next; + } + + ASSERTne(prev, NULL); + + /* free all allocations */ + while (prev != NULL) { + void **act = prev; + prev = *act; + vmem_free(vmp, act); + } + + vmem_pool_delete(vmp); + + DONE(NULL); +} diff --git a/src/test/vmem_pool_create/.gitignore b/src/test/vmem_pool_create/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..431dc90aadfd173660199a5e786a240bd74405b3 --- /dev/null +++ b/src/test/vmem_pool_create/.gitignore @@ -0,0 +1 @@ +vmem_pool_create diff --git a/src/test/vmem_pool_create/Makefile b/src/test/vmem_pool_create/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..fcdc92ff3a4db151e5fa629f7c8408bb6551a923 --- /dev/null +++ b/src/test/vmem_pool_create/Makefile @@ -0,0 +1,45 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_pool_create/Makefile -- build vmem_pool_create unit test +# +TARGET = vmem_pool_create +OBJS = vmem_pool_create.o + +include ../Makefile.inc +STATIC_DEBUG_LIBS = ../unittest/libut.a ../../debug/libvmem.a -luuid -pthread +STATIC_NONDEBUG_LIBS = ../unittest/libut.a ../../nondebug/libvmem.a -luuid -pthread + +LIBS += -lvmem + +vmem_pool_create.o: vmem_pool_create.c diff --git a/src/test/vmem_pool_create/TEST0 b/src/test/vmem_pool_create/TEST0 new file mode 100755 index 0000000000000000000000000000000000000000..37695ff538b55a543cf96d8e6af59017b2fc4972 --- /dev/null +++ b/src/test/vmem_pool_create/TEST0 @@ -0,0 +1,51 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_pool_create/TEST0 -- unit test for vmem_pool_create +# +export UNITTEST_NAME=vmem_pool_create/TEST0 +export UNITTEST_NUM=0 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local + +setup + +expect_normal_exit ./vmem_pool_create$EXESUFFIX $DIR + +check + +pass diff --git a/src/test/vmem_pool_create/err0.log.match b/src/test/vmem_pool_create/err0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/vmem_pool_create/out0.log.match b/src/test/vmem_pool_create/out0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..70f089e0db8532f925a348c50bc2e409c97f19b3 --- /dev/null +++ b/src/test/vmem_pool_create/out0.log.match @@ -0,0 +1,4 @@ +vmem_pool_create/TEST0: START: vmem_pool_create + ./vmem_pool_create$(*) +signal: Segmentation fault +vmem_pool_create/TEST0: Done diff --git a/src/test/vmem_pool_create/vmem_pool_create.c b/src/test/vmem_pool_create/vmem_pool_create.c new file mode 100644 index 0000000000000000000000000000000000000000..5b1b47471bc96ddc1c12004ff6695a6ca55f1395 --- /dev/null +++ b/src/test/vmem_pool_create/vmem_pool_create.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * vmem_pool_create.c -- unit test for vmem_pool_create + * + * usage: vmem_pool_create directory + */ + +#include "unittest.h" + +VMEM *Vmp; + +/* + * signal_handler -- called on SIGSEGV + */ +void +signal_handler(int sig) +{ + OUT("signal: %s", strsignal(sig)); + + vmem_pool_delete(Vmp); + + DONE(NULL); +} + +int +main(int argc, char *argv[]) +{ + START(argc, argv, "vmem_pool_create"); + + if (argc < 2 || argc > 3) + FATAL("usage: %s directory", argv[0]); + + Vmp = vmem_pool_create(argv[1], VMEM_MIN_POOL); + + if (Vmp == NULL) + OUT("!vmem_pool_create"); + else { + struct sigvec v = { 0 }; + + v.sv_handler = signal_handler; + if (sigvec(SIGSEGV, &v, NULL) < 0) + FATAL("!sigvec"); + + /* try to deref the opaque handle */ + char x = *(char *)Vmp; + OUT("x = %c", x); + } + + FATAL("no signal received"); +} diff --git a/src/test/vmem_pool_create_error/.gitignore b/src/test/vmem_pool_create_error/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..16c79c8dd56cb86a7a2fb159ec27c9c210f33c91 --- /dev/null +++ b/src/test/vmem_pool_create_error/.gitignore @@ -0,0 +1 @@ +vmem_pool_create_error diff --git a/src/test/vmem_pool_create_error/Makefile b/src/test/vmem_pool_create_error/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..78f96e11d4521600bd3288e888ed3af6e6a227f4 --- /dev/null +++ b/src/test/vmem_pool_create_error/Makefile @@ -0,0 +1,45 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_pool_create_error/Makefile -- build vmem_pool_create_error unit test +# +TARGET = vmem_pool_create_error +OBJS = vmem_pool_create_error.o + +include ../Makefile.inc +STATIC_DEBUG_LIBS = ../unittest/libut.a ../../debug/libvmem.a -luuid -pthread +STATIC_NONDEBUG_LIBS = ../unittest/libut.a ../../nondebug/libvmem.a -luuid -pthread + +LIBS += -lvmem + +vmem_pool_create_error.o: vmem_pool_create_error.c diff --git a/src/test/vmem_pool_create_error/TEST0 b/src/test/vmem_pool_create_error/TEST0 new file mode 100755 index 0000000000000000000000000000000000000000..1f4797eacee71eab7e3fa1b9199ec2a682597a0f --- /dev/null +++ b/src/test/vmem_pool_create_error/TEST0 @@ -0,0 +1,52 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_pool_create_error/TEST0 -- unit test for vmem_pool_create_error +# +export UNITTEST_NAME=vmem_pool_create_error/TEST0 +export UNITTEST_NUM=0 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local +require_build_type debug nondebug + +setup + +expect_normal_exit ./vmem_pool_create_error$EXESUFFIX + +check + +pass diff --git a/src/test/vmem_pool_create_error/err0.log.match b/src/test/vmem_pool_create_error/err0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/vmem_pool_create_error/out0.log.match b/src/test/vmem_pool_create_error/out0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..1760759a7b379dccd0a31d29ead9b9b84f5e1904 --- /dev/null +++ b/src/test/vmem_pool_create_error/out0.log.match @@ -0,0 +1,3 @@ +vmem_pool_create_error/TEST0: START: vmem_pool_create_error + ./vmem_pool_create_error$(*) +vmem_pool_create_error/TEST0: Done diff --git a/src/test/vmem_pool_create_error/vmem_pool_create_error.c b/src/test/vmem_pool_create_error/vmem_pool_create_error.c new file mode 100644 index 0000000000000000000000000000000000000000..f470bd5e336d5733a78ac813198d515cbfc6781f --- /dev/null +++ b/src/test/vmem_pool_create_error/vmem_pool_create_error.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * vmem_pool_create_error.c -- unit test for vmem_pool_create_error + * + * usage: vmem_pool_create_error + */ + +#include "unittest.h" + +static char mem_pool[VMEM_MIN_POOL]; + +int +main(int argc, char *argv[]) +{ + VMEM *vmp; + + START(argc, argv, "vmem_pool_create_error"); + + if (argc > 1) + FATAL("usage: %s", argv[0]); + + errno = 0; + vmp = vmem_pool_create_in_region(mem_pool, 0); + ASSERTeq(vmp, NULL); + ASSERTeq(errno, EINVAL); + + errno = 0; + vmp = vmem_pool_create("./", 0); + ASSERTeq(vmp, NULL); + ASSERTeq(errno, EINVAL); + + errno = 0; + vmp = vmem_pool_create("invalid dir !@#$%^&*()=", VMEM_MIN_POOL); + ASSERTeq(vmp, NULL); + ASSERTne(errno, 0); + + DONE(NULL); +} diff --git a/src/test/vmem_pool_create_in_region/.gitignore b/src/test/vmem_pool_create_in_region/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..6e0c9297bdcd166c8ee9e0b01cab8934ca446d6b --- /dev/null +++ b/src/test/vmem_pool_create_in_region/.gitignore @@ -0,0 +1 @@ +vmem_pool_create_in_region diff --git a/src/test/vmem_pool_create_in_region/Makefile b/src/test/vmem_pool_create_in_region/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..4aa37fcd528c8f59ffbce7657f52581f55c6e395 --- /dev/null +++ b/src/test/vmem_pool_create_in_region/Makefile @@ -0,0 +1,45 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_pool_create_in_region/Makefile -- build vmem_pool_create_in_region unit test +# +TARGET = vmem_pool_create_in_region +OBJS = vmem_pool_create_in_region.o + +include ../Makefile.inc +STATIC_DEBUG_LIBS = ../unittest/libut.a ../../debug/libvmem.a -luuid -pthread +STATIC_NONDEBUG_LIBS = ../unittest/libut.a ../../nondebug/libvmem.a -luuid -pthread + +LIBS += -lvmem + +vmem_pool_create_in_region.o: vmem_pool_create_in_region.c diff --git a/src/test/vmem_pool_create_in_region/TEST0 b/src/test/vmem_pool_create_in_region/TEST0 new file mode 100755 index 0000000000000000000000000000000000000000..f3267ab701ccb06ae85ba6d5aa8de9c7fc71c1da --- /dev/null +++ b/src/test/vmem_pool_create_in_region/TEST0 @@ -0,0 +1,51 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_pool_create_in_region/TEST0 -- unit test for vmem_pool_create_in_region +# +export UNITTEST_NAME=vmem_pool_create_in_region/TEST0 +export UNITTEST_NUM=0 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local + +setup + +expect_normal_exit ./vmem_pool_create_in_region$EXESUFFIX + +check + +pass diff --git a/src/test/vmem_pool_create_in_region/err0.log.match b/src/test/vmem_pool_create_in_region/err0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/vmem_pool_create_in_region/out0.log.match b/src/test/vmem_pool_create_in_region/out0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..90811d75763352cbc79906152c2eeb41891525ab --- /dev/null +++ b/src/test/vmem_pool_create_in_region/out0.log.match @@ -0,0 +1,3 @@ +vmem_pool_create_in_region/TEST0: START: vmem_pool_create_in_region + ./vmem_pool_create_in_region$(*) +vmem_pool_create_in_region/TEST0: Done diff --git a/src/test/vmem_pool_create_in_region/vmem_pool_create_in_region.c b/src/test/vmem_pool_create_in_region/vmem_pool_create_in_region.c new file mode 100644 index 0000000000000000000000000000000000000000..31f4a892bc7f15f60944e7369a07526214698d8e --- /dev/null +++ b/src/test/vmem_pool_create_in_region/vmem_pool_create_in_region.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * vmem_pool_create_in_region.c -- unit test for vmem_pool_create_in_region + * + * usage: vmem_pool_create_in_region + */ + +#include "unittest.h" + +#define TEST_ALLOCATIONS (300) + +static char mem_pool[VMEM_MIN_POOL]; +static void *allocs[TEST_ALLOCATIONS]; + +int +main(int argc, char *argv[]) +{ + VMEM *vmp; + size_t i; + + START(argc, argv, "vmem_pool_create_in_region"); + + if (argc > 1) + FATAL("usage: %s", argv[0]); + + vmp = vmem_pool_create_in_region(mem_pool, VMEM_MIN_POOL); + + if (vmp == NULL) + FATAL("!vmem_pool_create_in_region"); + + for (i = 0; i < TEST_ALLOCATIONS; ++i) { + allocs[i] = vmem_malloc(vmp, sizeof (int)); + + ASSERTne(allocs[i], NULL); + + /* check that pointer came from mem_pool */ + ASSERTrange(allocs[i], mem_pool, VMEM_MIN_POOL); + } + + for (i = 0; i < TEST_ALLOCATIONS; ++i) { + vmem_free(vmp, allocs[i]); + } + + vmem_pool_delete(vmp); + + DONE(NULL); +} diff --git a/src/test/vmem_realloc/.gitignore b/src/test/vmem_realloc/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..74acfc67fc40a78ad170f08e28154afaafa8690c --- /dev/null +++ b/src/test/vmem_realloc/.gitignore @@ -0,0 +1 @@ +vmem_realloc diff --git a/src/test/vmem_realloc/Makefile b/src/test/vmem_realloc/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..eeb7022ffe975cd0993d98671f05ee31f295a0f2 --- /dev/null +++ b/src/test/vmem_realloc/Makefile @@ -0,0 +1,45 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_realloc/Makefile -- build vmem_realloc unit test +# +TARGET = vmem_realloc +OBJS = vmem_realloc.o + +include ../Makefile.inc +STATIC_DEBUG_LIBS = ../unittest/libut.a ../../debug/libvmem.a -luuid -pthread +STATIC_NONDEBUG_LIBS = ../unittest/libut.a ../../nondebug/libvmem.a -luuid -pthread + +LIBS += -lvmem + +vmem_realloc.o: vmem_realloc.c diff --git a/src/test/vmem_realloc/TEST0 b/src/test/vmem_realloc/TEST0 new file mode 100755 index 0000000000000000000000000000000000000000..a3c21f67728c6c520edbed65daa16b2fc6e29a28 --- /dev/null +++ b/src/test/vmem_realloc/TEST0 @@ -0,0 +1,51 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_realloc/TEST0 -- unit test for vmem_realloc +# +export UNITTEST_NAME=vmem_realloc/TEST0 +export UNITTEST_NUM=0 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local + +setup + +expect_normal_exit ./vmem_realloc$EXESUFFIX + +check + +pass diff --git a/src/test/vmem_realloc/TEST1 b/src/test/vmem_realloc/TEST1 new file mode 100755 index 0000000000000000000000000000000000000000..7f1a6871da35a3ef08ec00f66666f93d181da26e --- /dev/null +++ b/src/test/vmem_realloc/TEST1 @@ -0,0 +1,51 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_realloc/TEST1 -- unit test for vmem_realloc +# +export UNITTEST_NAME=vmem_realloc/TEST1 +export UNITTEST_NUM=1 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type pmem + +setup + +expect_normal_exit ./vmem_realloc$EXESUFFIX $DIR + +check + +pass diff --git a/src/test/vmem_realloc/err0.log.match b/src/test/vmem_realloc/err0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/vmem_realloc/err1.log.match b/src/test/vmem_realloc/err1.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/vmem_realloc/out0.log.match b/src/test/vmem_realloc/out0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..848c103835cd5cda7843694c63cf5b67e3788b39 --- /dev/null +++ b/src/test/vmem_realloc/out0.log.match @@ -0,0 +1,3 @@ +vmem_realloc/TEST0: START: vmem_realloc + ./vmem_realloc$(*) +vmem_realloc/TEST0: Done diff --git a/src/test/vmem_realloc/out1.log.match b/src/test/vmem_realloc/out1.log.match new file mode 100644 index 0000000000000000000000000000000000000000..3e6cef7563a1fe6ee3305af13156eac8bbaedc4b --- /dev/null +++ b/src/test/vmem_realloc/out1.log.match @@ -0,0 +1,3 @@ +vmem_realloc/TEST1: START: vmem_realloc + ./vmem_realloc$(*) +vmem_realloc/TEST1: Done diff --git a/src/test/vmem_realloc/vmem_realloc.c b/src/test/vmem_realloc/vmem_realloc.c new file mode 100644 index 0000000000000000000000000000000000000000..c733e02c27e888f849ee17dc340966eb18ee49d1 --- /dev/null +++ b/src/test/vmem_realloc/vmem_realloc.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * vmem_realloc -- unit test for vmem_realloc + * + * usage: vmem_realloc [directory] + */ + +#include "unittest.h" + +static char mem_pool[VMEM_MIN_POOL]; + +int +main(int argc, char *argv[]) +{ + const int test_value = 123456; + char *dir = NULL; + VMEM *vmp; + + START(argc, argv, "vmem_realloc"); + + if (argc == 2) { + dir = argv[1]; + } else if (argc > 2) { + FATAL("usage: %s [directory]", argv[0]); + } + + if (dir == NULL) { + vmp = vmem_pool_create_in_region(mem_pool, VMEM_MIN_POOL); + if (vmp == NULL) + FATAL("!vmem_pool_create_in_region"); + } else { + vmp = vmem_pool_create(dir, VMEM_MIN_POOL); + if (vmp == NULL) + FATAL("!vmem_pool_create"); + } + + int *test = vmem_realloc(vmp, NULL, sizeof (int)); + ASSERTne(test, NULL); + + test[0] = test_value; + ASSERTeq(test[0], test_value); + + /* check that pointer came from mem_pool */ + if (dir == NULL) { + ASSERTrange(test, mem_pool, VMEM_MIN_POOL); + } + + test = vmem_realloc(vmp, test, sizeof (int) * 10); + ASSERTne(test, NULL); + ASSERTeq(test[0], test_value); + test[1] = test_value; + test[9] = test_value; + + /* check that pointer came from mem_pool */ + if (dir == NULL) { + ASSERTrange(test, mem_pool, VMEM_MIN_POOL); + } + + vmem_free(vmp, test); + + vmem_pool_delete(vmp); + + DONE(NULL); +} diff --git a/src/test/vmem_stats/.gitignore b/src/test/vmem_stats/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..423df3395e2152247f95d238c161a1b1fa4de488 --- /dev/null +++ b/src/test/vmem_stats/.gitignore @@ -0,0 +1 @@ +vmem_stats diff --git a/src/test/vmem_stats/Makefile b/src/test/vmem_stats/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..e25b71d458f0ced72b98fcc5764de4d61897dc2d --- /dev/null +++ b/src/test/vmem_stats/Makefile @@ -0,0 +1,45 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_stats/Makefile -- build vmem_stats unit test +# +TARGET = vmem_stats +OBJS = vmem_stats.o + +include ../Makefile.inc +STATIC_DEBUG_LIBS = ../unittest/libut.a ../../debug/libvmem.a -luuid -pthread +STATIC_NONDEBUG_LIBS = ../unittest/libut.a ../../nondebug/libvmem.a -luuid -pthread + +LIBS += -lvmem + +vmem_stats.o: vmem_stats.c diff --git a/src/test/vmem_stats/TEST0 b/src/test/vmem_stats/TEST0 new file mode 100755 index 0000000000000000000000000000000000000000..6817dba47afe1f6f1d82c1970c1cff7237ef6ff6 --- /dev/null +++ b/src/test/vmem_stats/TEST0 @@ -0,0 +1,52 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_stats/TEST0 -- unit test for vmem_stats +# +export UNITTEST_NAME=vmem_stats/TEST0 +export UNITTEST_NUM=0 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local +require_build_type debug + +setup + +expect_normal_exit ./vmem_stats$EXESUFFIX + +check + +pass diff --git a/src/test/vmem_stats/TEST1 b/src/test/vmem_stats/TEST1 new file mode 100755 index 0000000000000000000000000000000000000000..353462ee911357330b5904e3305cd24124983a13 --- /dev/null +++ b/src/test/vmem_stats/TEST1 @@ -0,0 +1,52 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_stats/TEST1 -- unit test for vmem_stats +# +export UNITTEST_NAME=vmem_stats/TEST1 +export UNITTEST_NUM=1 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local +require_build_type debug + +setup + +expect_normal_exit ./vmem_stats$EXESUFFIX g + +check + +pass diff --git a/src/test/vmem_stats/TEST2 b/src/test/vmem_stats/TEST2 new file mode 100755 index 0000000000000000000000000000000000000000..e8baf5da0a2862426194bf641bb0c10e655af4d7 --- /dev/null +++ b/src/test/vmem_stats/TEST2 @@ -0,0 +1,52 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_stats/TEST2 -- unit test for vmem_stats +# +export UNITTEST_NAME=vmem_stats/TEST2 +export UNITTEST_NUM=2 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local +require_build_type debug + +setup + +expect_normal_exit ./vmem_stats$EXESUFFIX gbl + +check + +pass diff --git a/src/test/vmem_stats/TEST3 b/src/test/vmem_stats/TEST3 new file mode 100755 index 0000000000000000000000000000000000000000..b1e5fc57ecfe1f8f3ec01e6902bf669327af2733 --- /dev/null +++ b/src/test/vmem_stats/TEST3 @@ -0,0 +1,52 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_stats/TEST3 -- unit test for vmem_stats +# +export UNITTEST_NAME=vmem_stats/TEST3 +export UNITTEST_NUM=3 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local +require_build_type debug + +setup + +expect_normal_exit ./vmem_stats$EXESUFFIX gbla + +check + +pass diff --git a/src/test/vmem_stats/TEST4 b/src/test/vmem_stats/TEST4 new file mode 100755 index 0000000000000000000000000000000000000000..12caedf65a5ab9c8ad0e342f2614ad4a7572a740 --- /dev/null +++ b/src/test/vmem_stats/TEST4 @@ -0,0 +1,52 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_stats/TEST4 -- unit test for vmem_stats +# +export UNITTEST_NAME=vmem_stats/TEST4 +export UNITTEST_NUM=4 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local +require_build_type debug + +setup + +expect_normal_exit ./vmem_stats$EXESUFFIX gblma + +check + +pass diff --git a/src/test/vmem_stats/vmem0.log.match b/src/test/vmem_stats/vmem0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..f51c5462724202fb5b92a95925b92ed3379659d2 --- /dev/null +++ b/src/test/vmem_stats/vmem0.log.match @@ -0,0 +1,61 @@ +<libvmem>: $(*) +<libvmem>: $(*) +<libvmem>: $(*) +<libvmem>: $(*) +<libvmem>: $(*) +<libvmem>: $(*) +<libvmem>: $(*) +<libvmem>: $(*) +<libvmem>: $(*) +<libvmem>: $(*) +<libvmem>: $(*) +___ Begin jemalloc statistics ___ +Version:$(*) +Assertions enabled +Run-time option settings: + opt.abort: $(*) + opt.lg_chunk: $(*) + opt.dss: $(*) + opt.narenas: $(*) + opt.lg_dirty_mult: $(*) + opt.stats_print: $(*) + opt.junk: $(*) + opt.quarantine: $(*) + opt.redzone: $(*) + opt.zero: $(*) + opt.tcache: $(*) + opt.lg_tcache_max: $(*) +CPUs: $(*) +Arenas: $(*) +Pointer size: $(*) +Quantum size: $(*) +Page size: $(*) +Min active:dirty page ratio per arena: $(*) +Chunk size: $(*) +Allocated: $(*), active: $(*), mapped: $(*) +Current active ceiling: $(*) +chunks: nchunks highchunks curchunks + $(*) $(*) $(*) + +arenas[0]: +assigned threads: $(*) +dss allocation precedence: secondary +dirty pages: $(*):$(*) active:dirty, $(*) sweeps, $(*) madvises, $(*) purged + allocated nmalloc ndalloc nrequests +small: $(*) $(*) $(*) $(*) +large: $(*) $(*) $(*) $(*) +huge: $(*) $(*) $(*) $(*) +total: $(*) $(*) $(*) $(*) +active: $(*) +mapped: $(*) +bins: bin size regs pgs allocated nmalloc ndalloc nrequests nfills nflushes newruns reruns curruns +[0..$(*)] + $(*) $(*) $(*) $(*) $(*) $(*) $(*) $(*) $(*) $(*) $(*) $(*) $(*) +[$(*)..$(*)] +large: size pages nmalloc ndalloc nrequests curruns +[$(*)] + $(*) $(*) $(*) $(*) $(*) $(*) +[$(*)] +--- End jemalloc statistics --- +<libvmem>: $(*) +<libvmem>: $(*) diff --git a/src/test/vmem_stats/vmem1.log.match b/src/test/vmem_stats/vmem1.log.match new file mode 100644 index 0000000000000000000000000000000000000000..66ace582fa80549aefe173bf1b62fdffba7a413e --- /dev/null +++ b/src/test/vmem_stats/vmem1.log.match @@ -0,0 +1,39 @@ +<libvmem>: $(*) +<libvmem>: $(*) +<libvmem>: $(*) +<libvmem>: $(*) +<libvmem>: $(*) +<libvmem>: $(*) +<libvmem>: $(*) +<libvmem>: $(*) +<libvmem>: $(*) +<libvmem>: $(*) +<libvmem>: $(*) +___ Begin jemalloc statistics ___ +Allocated: $(*), active: $(*), mapped: $(*) +Current active ceiling: $(*) +chunks: nchunks highchunks curchunks + $(*) $(*) $(*) + +arenas[0]: +assigned threads: $(*) +dss allocation precedence: secondary +dirty pages: $(*):$(*) active:dirty, $(*) sweeps, $(*) madvises, $(*) purged + allocated nmalloc ndalloc nrequests +small: $(*) $(*) $(*) $(*) +large: $(*) $(*) $(*) $(*) +huge: $(*) $(*) $(*) $(*) +total: $(*) $(*) $(*) $(*) +active: $(*) +mapped: $(*) +bins: bin size regs pgs allocated nmalloc ndalloc nrequests nfills nflushes newruns reruns curruns +[0..$(*)] + $(*) $(*) $(*) $(*) $(*) $(*) $(*) $(*) $(*) $(*) $(*) $(*) $(*) +[$(*)..$(*)] +large: size pages nmalloc ndalloc nrequests curruns +[$(*)] + $(*) $(*) $(*) $(*) $(*) $(*) +[$(*)] +--- End jemalloc statistics --- +<libvmem>: $(*) +<libvmem>: $(*) diff --git a/src/test/vmem_stats/vmem2.log.match b/src/test/vmem_stats/vmem2.log.match new file mode 100644 index 0000000000000000000000000000000000000000..f8566e93d2799f06627d219d6b4af37069beba88 --- /dev/null +++ b/src/test/vmem_stats/vmem2.log.match @@ -0,0 +1,31 @@ +<libvmem>: $(*) +<libvmem>: $(*) +<libvmem>: $(*) +<libvmem>: $(*) +<libvmem>: $(*) +<libvmem>: $(*) +<libvmem>: $(*) +<libvmem>: $(*) +<libvmem>: $(*) +<libvmem>: $(*) +<libvmem>: $(*) +___ Begin jemalloc statistics ___ +Allocated: $(*), active: $(*), mapped: $(*) +Current active ceiling: $(*) +chunks: nchunks highchunks curchunks + $(*) $(*) $(*) + +arenas[0]: +assigned threads: $(*) +dss allocation precedence: secondary +dirty pages: $(*):$(*) active:dirty, $(*) sweeps, $(*) madvises, $(*) purged + allocated nmalloc ndalloc nrequests +small: $(*) $(*) $(*) $(*) +large: $(*) $(*) $(*) $(*) +huge: $(*) $(*) $(*) $(*) +total: $(*) $(*) $(*) $(*) +active: $(*) +mapped: $(*) +--- End jemalloc statistics --- +<libvmem>: $(*) +<libvmem>: $(*) diff --git a/src/test/vmem_stats/vmem3.log.match b/src/test/vmem_stats/vmem3.log.match new file mode 100644 index 0000000000000000000000000000000000000000..6a78ff98450056323e84bf8499db116ba6a21ddc --- /dev/null +++ b/src/test/vmem_stats/vmem3.log.match @@ -0,0 +1,31 @@ +<libvmem>: $(*) +<libvmem>: $(*) +<libvmem>: $(*) +<libvmem>: $(*) +<libvmem>: $(*) +<libvmem>: $(*) +<libvmem>: $(*) +<libvmem>: $(*) +<libvmem>: $(*) +<libvmem>: $(*) +<libvmem>: $(*) +___ Begin jemalloc statistics ___ +Allocated: $(*), active: $(*), mapped: $(*) +Current active ceiling: $(*) +chunks: nchunks highchunks curchunks + $(*) $(*) $(*) + +Merged arenas stats: +assigned threads: $(*) +dss allocation precedence: $(*) +dirty pages: $(*):$(*) active:dirty, $(*) sweeps, $(*) madvises, $(*) purged + allocated nmalloc ndalloc nrequests +small: $(*) $(*) $(*) $(*) +large: $(*) $(*) $(*) $(*) +huge: $(*) $(*) $(*) $(*) +total: $(*) $(*) $(*) $(*) +active: $(*) +mapped: $(*) +--- End jemalloc statistics --- +<libvmem>: $(*) +<libvmem>: $(*) diff --git a/src/test/vmem_stats/vmem4.log.match b/src/test/vmem_stats/vmem4.log.match new file mode 100644 index 0000000000000000000000000000000000000000..46fdb1ec2f81b0e21df756cc92772f6724d989b1 --- /dev/null +++ b/src/test/vmem_stats/vmem4.log.match @@ -0,0 +1,19 @@ +<libvmem>: $(*) +<libvmem>: $(*) +<libvmem>: $(*) +<libvmem>: $(*) +<libvmem>: $(*) +<libvmem>: $(*) +<libvmem>: $(*) +<libvmem>: $(*) +<libvmem>: $(*) +<libvmem>: $(*) +<libvmem>: $(*) +___ Begin jemalloc statistics ___ +Allocated: $(*), active: $(*), mapped: $(*) +Current active ceiling: $(*) +chunks: nchunks highchunks curchunks + $(*) $(*) $(*) +--- End jemalloc statistics --- +<libvmem>: $(*) +<libvmem>: $(*) diff --git a/src/test/vmem_stats/vmem_stats.c b/src/test/vmem_stats/vmem_stats.c new file mode 100644 index 0000000000000000000000000000000000000000..68b85c8f2a8aeca9e4697612cab1345ac363ac72 --- /dev/null +++ b/src/test/vmem_stats/vmem_stats.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * vmem_stats.c -- unit test for vmem_stats + * + * usage: vmem_stats [opts] + */ + +#include "unittest.h" + +static char mem_pool[VMEM_MIN_POOL]; +#define TEST_VALUE 1234 + +int +main(int argc, char *argv[]) +{ + char *opts = ""; + VMEM *vmp; + + START(argc, argv, "vmem_stats"); + + if (argc == 2) { + opts = argv[1]; + } else if (argc > 2) { + FATAL("usage: %s [opts]", argv[0]); + } + + vmp = vmem_pool_create_in_region(mem_pool, VMEM_MIN_POOL); + if (vmp == NULL) + FATAL("!vmem_pool_create_in_region"); + + int *test = vmem_malloc(vmp, sizeof (int)*100); + ASSERTne(test, NULL); + + *test = TEST_VALUE; + ASSERTeq(*test, TEST_VALUE); + + ASSERTrange(test, mem_pool, VMEM_MIN_POOL); + + vmem_pool_stats_print(vmp, opts); + + vmem_free(vmp, test); + + vmem_pool_delete(vmp); + + DONE(NULL); +} diff --git a/src/test/vmem_strdup/.gitignore b/src/test/vmem_strdup/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..bb836d6020bf585f73c018abbb9abe4439e1ffb5 --- /dev/null +++ b/src/test/vmem_strdup/.gitignore @@ -0,0 +1 @@ +vmem_strdup diff --git a/src/test/vmem_strdup/Makefile b/src/test/vmem_strdup/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..c1fc674daed0ce7aa1450f4ac65ad8fc56b479a0 --- /dev/null +++ b/src/test/vmem_strdup/Makefile @@ -0,0 +1,45 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_strdup/Makefile -- build vmem_strdup unit test +# +TARGET = vmem_strdup +OBJS =vmem_strdup.o + +include ../Makefile.inc +STATIC_DEBUG_LIBS = ../unittest/libut.a ../../debug/libvmem.a -luuid -pthread +STATIC_NONDEBUG_LIBS = ../unittest/libut.a ../../nondebug/libvmem.a -luuid -pthread + +LIBS += -lvmem + +vmem_strdup.o: vmem_strdup.c diff --git a/src/test/vmem_strdup/TEST0 b/src/test/vmem_strdup/TEST0 new file mode 100755 index 0000000000000000000000000000000000000000..27d32313e684284e746e90013474c92bf93f032a --- /dev/null +++ b/src/test/vmem_strdup/TEST0 @@ -0,0 +1,51 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_strdup/TEST0 -- unit test for vmem_strdup +# +export UNITTEST_NAME=vmem_strdup/TEST0 +export UNITTEST_NUM=0 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type local + +setup + +expect_normal_exit ./vmem_strdup$EXESUFFIX + +check + +pass diff --git a/src/test/vmem_strdup/TEST1 b/src/test/vmem_strdup/TEST1 new file mode 100755 index 0000000000000000000000000000000000000000..e569b85540fc2d6f9a80502a8a93ec7be4203793 --- /dev/null +++ b/src/test/vmem_strdup/TEST1 @@ -0,0 +1,51 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_strdup/TEST1 -- unit test for vmem_strdup +# +export UNITTEST_NAME=vmem_strdup/TEST1 +export UNITTEST_NUM=1 + +# standard unit test setup +. ../unittest/unittest.sh + +require_fs_type pmem + +setup + +expect_normal_exit ./vmem_strdup$EXESUFFIX $DIR + +check + +pass diff --git a/src/test/vmem_strdup/err0.log.match b/src/test/vmem_strdup/err0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/vmem_strdup/err1.log.match b/src/test/vmem_strdup/err1.log.match new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/vmem_strdup/out0.log.match b/src/test/vmem_strdup/out0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..36520dd812e14e0c8a60847bd85cf85395e4cb2c --- /dev/null +++ b/src/test/vmem_strdup/out0.log.match @@ -0,0 +1,3 @@ +vmem_strdup/TEST0: START: vmem_strdup + ./vmem_strdup$(*) +vmem_strdup/TEST0: Done diff --git a/src/test/vmem_strdup/out1.log.match b/src/test/vmem_strdup/out1.log.match new file mode 100644 index 0000000000000000000000000000000000000000..5cbcb0ad6bc538a2b4517ee2e2955b9bbc0c60aa --- /dev/null +++ b/src/test/vmem_strdup/out1.log.match @@ -0,0 +1,3 @@ +vmem_strdup/TEST1: START: vmem_strdup + ./vmem_strdup$(*) +vmem_strdup/TEST1: Done diff --git a/src/test/vmem_strdup/vmem_strdup.c b/src/test/vmem_strdup/vmem_strdup.c new file mode 100644 index 0000000000000000000000000000000000000000..8eb0bcadd237917904405d832b30cf5da5d0fb95 --- /dev/null +++ b/src/test/vmem_strdup/vmem_strdup.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * vmem_strdup.c -- unit test for vmem_strdup + * + * usage: vmem_strdup [directory] + */ + +#include "unittest.h" + +static char mem_pool[VMEM_MIN_POOL]; + +int +main(int argc, char *argv[]) +{ + const char *text = "Some test text"; + const char *text_empty = ""; + char *dir = NULL; + VMEM *vmp; + + START(argc, argv, "vmem_strdup"); + + if (argc == 2) { + dir = argv[1]; + } else if (argc > 2) { + FATAL("usage: %s [directory]", argv[0]); + } + + if (dir == NULL) { + vmp = vmem_pool_create_in_region(mem_pool, VMEM_MIN_POOL); + if (vmp == NULL) + FATAL("!vmem_pool_create_in_region"); + } else { + vmp = vmem_pool_create(dir, VMEM_MIN_POOL); + if (vmp == NULL) + FATAL("!vmem_pool_create"); + } + + char *str1 = vmem_strdup(vmp, text); + ASSERTne(str1, NULL); + ASSERTeq(strcmp(text, str1), 0); + + /* check that pointer came from mem_pool */ + if (dir == NULL) { + ASSERTrange(str1, mem_pool, VMEM_MIN_POOL); + } + + char *str2 = vmem_strdup(vmp, text_empty); + ASSERTne(str2, NULL); + ASSERTeq(strcmp(text_empty, str2), 0); + + /* check that pointer came from mem_pool */ + if (dir == NULL) { + ASSERTrange(str2, mem_pool, VMEM_MIN_POOL); + } + + vmem_free(vmp, str1); + vmem_free(vmp, str2); + + vmem_pool_delete(vmp); + + DONE(NULL); +} diff --git a/src/test/vmem_valgrind/.gitignore b/src/test/vmem_valgrind/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..c4740f5b7c85cf7f95c8d68db804e201e9906f25 --- /dev/null +++ b/src/test/vmem_valgrind/.gitignore @@ -0,0 +1 @@ +vmem_valgrind diff --git a/src/test/vmem_valgrind/Makefile b/src/test/vmem_valgrind/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..9d76faf181e7f4bf7f9155c53a31ba7d6ade7035 --- /dev/null +++ b/src/test/vmem_valgrind/Makefile @@ -0,0 +1,46 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_valgrind/Makefile -- build vmem_valgrind unit test +# +TARGET = vmem_valgrind +OBJS =vmem_valgrind.o + +include ../Makefile.inc +STATIC_DEBUG_LIBS = ../unittest/libut.a ../../debug/libvmem.a -luuid -pthread +STATIC_NONDEBUG_LIBS = ../unittest/libut.a ../../nondebug/libvmem.a -luuid -pthread + +LIBS += -lvmem + +vmem_valgrind.o: vmem_valgrind.c + diff --git a/src/test/vmem_valgrind/TEST0 b/src/test/vmem_valgrind/TEST0 new file mode 100755 index 0000000000000000000000000000000000000000..c9cb64bd6414731f97a5a0c8ec757ec31ac59693 --- /dev/null +++ b/src/test/vmem_valgrind/TEST0 @@ -0,0 +1,59 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_valgrind/TEST0 -- unit test for vmem_valgrind +# +export UNITTEST_NAME=vmem_valgrind/TEST0 +export UNITTEST_NUM=0 + +# standard unit test setup +. ../unittest/unittest.sh + +. ./valgrind_check.sh + +require_fs_type local pmem +require_build_type debug nondebug +require_valgrind_dev + +setup + +export VMEM_LOG_LEVEL=0 +unset VMEM_LOG_FILE +[ "$FS" == "pmem" ] && DIR_WORK=$DIR + +expect_normal_exit valgrind --leak-check=full --show-reachable=yes --log-file=valgrind$UNITTEST_NUM.log ./vmem_valgrind$EXESUFFIX 0 $DIR_WORK + +check + +pass diff --git a/src/test/vmem_valgrind/TEST1 b/src/test/vmem_valgrind/TEST1 new file mode 100755 index 0000000000000000000000000000000000000000..b376a9537a05ef31c20056c55e2a76b88c07282e --- /dev/null +++ b/src/test/vmem_valgrind/TEST1 @@ -0,0 +1,59 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_valgrind/TEST1 -- unit test for vmem_valgrind +# +export UNITTEST_NAME=vmem_valgrind/TEST1 +export UNITTEST_NUM=1 + +# standard unit test setup +. ../unittest/unittest.sh + +. ./valgrind_check.sh + +require_fs_type local pmem +require_build_type debug nondebug +require_valgrind_dev + +setup + +export VMEM_LOG_LEVEL=0 +unset VMEM_LOG_FILE +[ "$FS" == "pmem" ] && DIR_WORK=$DIR + +expect_normal_exit valgrind --leak-check=full --show-reachable=yes --log-file=valgrind$UNITTEST_NUM.log ./vmem_valgrind$EXESUFFIX 1 $DIR_WORK + +check + +pass diff --git a/src/test/vmem_valgrind/TEST2 b/src/test/vmem_valgrind/TEST2 new file mode 100755 index 0000000000000000000000000000000000000000..cc09a0cd8745092166cc3b158c63d73d76aec8e8 --- /dev/null +++ b/src/test/vmem_valgrind/TEST2 @@ -0,0 +1,59 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_valgrind/TEST2 -- unit test for vmem_valgrind +# +export UNITTEST_NAME=vmem_valgrind/TEST2 +export UNITTEST_NUM=2 + +# standard unit test setup +. ../unittest/unittest.sh + +. ./valgrind_check.sh + +require_fs_type local pmem +require_build_type debug nondebug +require_valgrind_dev + +setup + +export VMEM_LOG_LEVEL=0 +unset VMEM_LOG_FILE +[ "$FS" == "pmem" ] && DIR_WORK=$DIR + +expect_normal_exit valgrind --leak-check=full --show-reachable=yes --log-file=valgrind$UNITTEST_NUM.log ./vmem_valgrind$EXESUFFIX 2 $DIR_WORK + +check + +pass diff --git a/src/test/vmem_valgrind/TEST3 b/src/test/vmem_valgrind/TEST3 new file mode 100755 index 0000000000000000000000000000000000000000..160e7852f284f7d5bc92cbc6a600dc87a3c60e62 --- /dev/null +++ b/src/test/vmem_valgrind/TEST3 @@ -0,0 +1,59 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_valgrind/TEST3 -- unit test for vmem_valgrind +# +export UNITTEST_NAME=vmem_valgrind/TEST3 +export UNITTEST_NUM=3 + +# standard unit test setup +. ../unittest/unittest.sh + +. ./valgrind_check.sh + +require_fs_type local pmem +require_build_type debug nondebug +require_valgrind_dev + +setup + +export VMEM_LOG_LEVEL=0 +unset VMEM_LOG_FILE +[ "$FS" == "pmem" ] && DIR_WORK=$DIR + +expect_normal_exit valgrind --leak-check=full --show-reachable=yes --log-file=valgrind$UNITTEST_NUM.log ./vmem_valgrind$EXESUFFIX 3 + +check + +pass diff --git a/src/test/vmem_valgrind/TEST5 b/src/test/vmem_valgrind/TEST5 new file mode 100755 index 0000000000000000000000000000000000000000..285b0a506861eceef1a88e241a9dd34ccc478334 --- /dev/null +++ b/src/test/vmem_valgrind/TEST5 @@ -0,0 +1,59 @@ +#!/bin/bash -e +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# src/test/vmem_valgrind/TEST5 -- unit test for vmem_valgrind +# +export UNITTEST_NAME=vmem_valgrind/TEST5 +export UNITTEST_NUM=5 + +# standard unit test setup +. ../unittest/unittest.sh + +. ./valgrind_check.sh + +require_fs_type local pmem +require_build_type debug nondebug +require_valgrind_dev + +setup + +export VMEM_LOG_LEVEL=0 +unset VMEM_LOG_FILE +[ "$FS" == "pmem" ] && DIR_WORK=$DIR + +expect_normal_exit valgrind --leak-check=full --show-reachable=yes --log-file=valgrind$UNITTEST_NUM.log ./vmem_valgrind$EXESUFFIX 5 + +check + +pass diff --git a/src/test/vmem_valgrind/valgrind0.log.match b/src/test/vmem_valgrind/valgrind0.log.match new file mode 100644 index 0000000000000000000000000000000000000000..ed8ee1bf99f88f2d64da8ce203fb7b7841bcd016 --- /dev/null +++ b/src/test/vmem_valgrind/valgrind0.log.match @@ -0,0 +1,15 @@ +==$(N)== Memcheck, a memory error detector +==$(N)== Copyright $(*) +==$(N)== Using $(*) +==$(N)== Command:$(*) +$(OPT)==$(N)== Parent PID: $(N) +==$(N)== +==$(N)== +==$(N)== HEAP SUMMARY: +==$(N)== in use at exit: 0 bytes in 0 blocks +==$(N)== total heap usage: $(N) allocs, $(N) frees, $(*) bytes allocated +==$(N)== +==$(N)== All heap blocks were freed -- no leaks are possible +==$(N)== +==$(N)== For counts of detected and suppressed errors, rerun with: -v +==$(N)== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: $(N) from $(N)) diff --git a/src/test/vmem_valgrind/valgrind1.log.match b/src/test/vmem_valgrind/valgrind1.log.match new file mode 100644 index 0000000000000000000000000000000000000000..ed8ee1bf99f88f2d64da8ce203fb7b7841bcd016 --- /dev/null +++ b/src/test/vmem_valgrind/valgrind1.log.match @@ -0,0 +1,15 @@ +==$(N)== Memcheck, a memory error detector +==$(N)== Copyright $(*) +==$(N)== Using $(*) +==$(N)== Command:$(*) +$(OPT)==$(N)== Parent PID: $(N) +==$(N)== +==$(N)== +==$(N)== HEAP SUMMARY: +==$(N)== in use at exit: 0 bytes in 0 blocks +==$(N)== total heap usage: $(N) allocs, $(N) frees, $(*) bytes allocated +==$(N)== +==$(N)== All heap blocks were freed -- no leaks are possible +==$(N)== +==$(N)== For counts of detected and suppressed errors, rerun with: -v +==$(N)== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: $(N) from $(N)) diff --git a/src/test/vmem_valgrind/valgrind2.log.match b/src/test/vmem_valgrind/valgrind2.log.match new file mode 100644 index 0000000000000000000000000000000000000000..a7da59c21e2efeb7dfa8e8da437890c49c2d9a00 --- /dev/null +++ b/src/test/vmem_valgrind/valgrind2.log.match @@ -0,0 +1,25 @@ +==$(N)== Memcheck, a memory error detector +==$(N)== Copyright $(*) +==$(N)== Using $(*) +==$(N)== Command:$(*) +==$(N)== Parent PID: $(N) +==$(N)== +==$(N)== +==$(N)== HEAP SUMMARY: +==$(N)== in use at exit: $(N) bytes in 1 blocks +==$(N)== total heap usage: $(N) allocs, $(N) frees, $(*) bytes allocated +==$(N)== +==$(N)== $(N) bytes in 1 blocks are definitely lost in loss record 1 of 1 +==$(N)== at 0x$(X): je_vmem_pool_malloc (jemalloc.c:$(N)) +$(OPT)==$(N)== by 0x$(X): vmem_malloc (vmem.c:$(N)) +==$(N)== by 0x$(X): main (vmem_valgrind.c:$(N)) +==$(N)== +==$(N)== LEAK SUMMARY: +==$(N)== definitely lost: 8 bytes in 1 blocks +==$(N)== indirectly lost: 0 bytes in 0 blocks +==$(N)== possibly lost: 0 bytes in 0 blocks +==$(N)== still reachable: 0 bytes in 0 blocks +==$(N)== suppressed: 0 bytes in 0 blocks +==$(N)== +==$(N)== For counts of detected and suppressed errors, rerun with: -v +==$(N)== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: $(N) from $(N)) diff --git a/src/test/vmem_valgrind/valgrind3.log.match b/src/test/vmem_valgrind/valgrind3.log.match new file mode 100644 index 0000000000000000000000000000000000000000..6935a309093834fab80820e02cbbfc470eb589f2 --- /dev/null +++ b/src/test/vmem_valgrind/valgrind3.log.match @@ -0,0 +1,25 @@ +==$(N)== Memcheck, a memory error detector +==$(N)== Copyright $(*) +==$(N)== Using $(*) +==$(N)== Command:$(*) +==$(N)== Parent PID: $(N) +==$(N)== +$(OPT)==$(N)== +==$(N)== HEAP SUMMARY: +==$(N)== in use at exit: $(N) bytes in 1 blocks +==$(N)== total heap usage: $(N) allocs, $(N) frees, $(*) bytes allocated +==$(N)== +==$(N)== $(N) bytes in 1 blocks are definitely lost in loss record 1 of 1 +==$(N)== at 0x$(X): je_vmem_pool_malloc (jemalloc.c:$(N)) +$(OPT)==$(N)== by 0x$(X): vmem_malloc (vmem.c:$(N)) +==$(N)== by 0x$(X): main (vmem_valgrind.c:$(N)) +==$(N)== +==$(N)== LEAK SUMMARY: +==$(N)== definitely lost: 8 bytes in 1 blocks +==$(N)== indirectly lost: 0 bytes in 0 blocks +==$(N)== possibly lost: 0 bytes in 0 blocks +==$(N)== still reachable: 0 bytes in 0 blocks +==$(N)== suppressed: 0 bytes in 0 blocks +==$(N)== +==$(N)== For counts of detected and suppressed errors, rerun with: -v +==$(N)== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: $(N) from $(N)) diff --git a/src/test/vmem_valgrind/valgrind4.log.match b/src/test/vmem_valgrind/valgrind4.log.match new file mode 100644 index 0000000000000000000000000000000000000000..c75c203c8c2157eb49cd23fc99ebbc7105406c45 --- /dev/null +++ b/src/test/vmem_valgrind/valgrind4.log.match @@ -0,0 +1,22 @@ +==$(N)== Memcheck, a memory error detector +==$(N)== Copyright $(*) +==$(N)== Using $(*) +==$(N)== Command:$(*) +==$(N)== Parent PID: $(N) +==$(N)== +==$(N)== Invalid write of size 4 +==$(N)== at 0x$(X): main (vmem_valgrind.c:$(N)) +==$(N)== Address 0x$(X) is 0 bytes after a block of size $(N) alloc'd +==$(N)== at 0x$(X): je_vmem_pool_malloc (jemalloc.c:$(N)) +$(OPT)==$(N)== by 0x$(X): vmem_malloc (vmem.c:$(N)) +==$(N)== by 0x$(X): main (vmem_valgrind.c:$(N)) +==$(N)== +==$(N)== +==$(N)== HEAP SUMMARY: +==$(N)== in use at exit: 0 bytes in 0 blocks +==$(N)== total heap usage: $(N) allocs, $(N) frees, $(*) bytes allocated +==$(N)== +==$(N)== All heap blocks were freed -- no leaks are possible +==$(N)== +==$(N)== For counts of detected and suppressed errors, rerun with: -v +==$(N)== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: $(N) from $(N)) diff --git a/src/test/vmem_valgrind/valgrind5.log.match b/src/test/vmem_valgrind/valgrind5.log.match new file mode 100644 index 0000000000000000000000000000000000000000..ed8ee1bf99f88f2d64da8ce203fb7b7841bcd016 --- /dev/null +++ b/src/test/vmem_valgrind/valgrind5.log.match @@ -0,0 +1,15 @@ +==$(N)== Memcheck, a memory error detector +==$(N)== Copyright $(*) +==$(N)== Using $(*) +==$(N)== Command:$(*) +$(OPT)==$(N)== Parent PID: $(N) +==$(N)== +==$(N)== +==$(N)== HEAP SUMMARY: +==$(N)== in use at exit: 0 bytes in 0 blocks +==$(N)== total heap usage: $(N) allocs, $(N) frees, $(*) bytes allocated +==$(N)== +==$(N)== All heap blocks were freed -- no leaks are possible +==$(N)== +==$(N)== For counts of detected and suppressed errors, rerun with: -v +==$(N)== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: $(N) from $(N)) diff --git a/src/test/vmem_valgrind/valgrind_check.c b/src/test/vmem_valgrind/valgrind_check.c new file mode 100644 index 0000000000000000000000000000000000000000..73dadf218ed848eaa2f1b47a7e3f879ba121f7d3 --- /dev/null +++ b/src/test/vmem_valgrind/valgrind_check.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * valgrind_check.c -- compile this to check that we have the correct version + * of Valgrind headers + */ + +#include <valgrind/valgrind.h> +#include <valgrind/memcheck.h> + +/* check valgrind version required by jemalloc */ +#if !defined(VALGRIND_RESIZEINPLACE_BLOCK) +#error "Incompatible Valgrind version" +#endif + +int +main() +{ + ; + return 0; +} diff --git a/src/test/vmem_valgrind/valgrind_check.sh b/src/test/vmem_valgrind/valgrind_check.sh new file mode 100755 index 0000000000000000000000000000000000000000..717b22ea6a62979aaf9a531b7adef1287875816e --- /dev/null +++ b/src/test/vmem_valgrind/valgrind_check.sh @@ -0,0 +1,41 @@ +# +# Copyright (c) 2014, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# require_valgrind_dev -- continue script execution only if correct version +# of valgrind-devel package is installed +# +function require_valgrind_dev() { + gcc valgrind_check.c -o /dev/null 1>/dev/null 2>/dev/null && return + echo "$UNITTEST_NAME: SKIP valgrind-devel package required" + exit 0 +} diff --git a/src/test/vmem_valgrind/vmem_valgrind.c b/src/test/vmem_valgrind/vmem_valgrind.c new file mode 100644 index 0000000000000000000000000000000000000000..350ff1580f5b49bc3082ea48bb35640d15683c88 --- /dev/null +++ b/src/test/vmem_valgrind/vmem_valgrind.c @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * vmem_valgrind.c -- unit test for vmem_valgrind + * + * usage: vmem_valgrind <test-number> [directory] + * + * test-number can be a number from 0 to 9 + */ + +#include "unittest.h" + +static char mem_pool[VMEM_MIN_POOL]; + +static int custom_allocs; +static int custom_alloc_calls; + +/* + * malloc_custom -- custom malloc function + * + * This function updates statistics about custom alloc functions, + * and returns allocated memory. + */ +void * +malloc_custom(size_t size) +{ + ++custom_alloc_calls; + ++custom_allocs; + return malloc(size); +} + +/* + * free_custom -- custom free function + * + * This function updates statistics about custom alloc functions, + * and frees allocated memory. + */ +void +free_custom(void *ptr) +{ + ++custom_alloc_calls; + --custom_allocs; + free(ptr); +} + +/* + * realloc_custom -- custom realloc function + * + * This function updates statistics about custom alloc functions, + * and returns reallocated memory. + */ +void * +realloc_custom(void *ptr, size_t size) +{ + ++custom_alloc_calls; + return realloc(ptr, size); +} + +/* + * strdup_custom -- custom strdup function + * + * This function updates statistics about custom alloc functions, + * and returns allocated memory with a duplicated string. + */ +char * +strdup_custom(const char *s) +{ + ++custom_alloc_calls; + ++custom_allocs; + return strdup(s); +} + +int +main(int argc, char *argv[]) +{ + char *dir = NULL; + VMEM *vmp; + int *ptr; + int test_case = -1; + int expect_custom_alloc = 0; + + START(argc, argv, "vmem_valgrind"); + + if (argc >= 2 && argc <= 3) { + test_case = atoi(argv[1]); + if (test_case > 9) + test_case = -1; + + if (argc > 2) + dir = argv[2]; + } + + if (test_case < 0) + FATAL("usage: %s <test-number from 0 to 9> [directory]", + argv[0]); + + if (test_case < 5) { + OUT("use default allocator"); + expect_custom_alloc = 0; + } else { + OUT("use custom alloc functions"); + test_case -= 5; + expect_custom_alloc = 1; + vmem_set_funcs(malloc_custom, free_custom, + realloc_custom, strdup_custom, NULL); + } + + if (dir == NULL) { + vmp = vmem_pool_create_in_region(mem_pool, VMEM_MIN_POOL); + if (vmp == NULL) + FATAL("!vmem_pool_create_in_region"); + } else { + vmp = vmem_pool_create(dir, VMEM_MIN_POOL); + if (vmp == NULL) + FATAL("!vmem_pool_create"); + } + + switch (test_case) { + case 0: { + OUT("remove all allocations and delete pool"); + ptr = vmem_malloc(vmp, sizeof (int)); + if (ptr == NULL) + FATAL("!vmem_malloc"); + + vmem_free(vmp, ptr); + vmem_pool_delete(vmp); + break; + } + case 1: { + OUT("only remove allocations"); + ptr = vmem_malloc(vmp, sizeof (int)); + if (ptr == NULL) + FATAL("!vmem_malloc"); + + vmem_free(vmp, ptr); + break; + } + case 2: { + OUT("only delete pool"); + ptr = vmem_malloc(vmp, sizeof (int)); + if (ptr == NULL) + FATAL("!vmem_malloc"); + + vmem_pool_delete(vmp); + + /* prevent reporting leaked memory as still reachable */ + ptr = NULL; + break; + } + case 3: { + OUT("memory leaks"); + ptr = vmem_malloc(vmp, sizeof (int)); + if (ptr == NULL) + FATAL("!vmem_malloc"); + + /* prevent reporting leaked memory as still reachable */ + ptr = NULL; + break; + } + case 4: { + OUT("heap block overrun"); + ptr = vmem_malloc(vmp, 12 * sizeof (int)); + if (ptr == NULL) + FATAL("!vmem_malloc"); + + /* heap block overrun */ + ptr[12] = 7; + + vmem_free(vmp, ptr); + vmem_pool_delete(vmp); + break; + } + default: { + FATAL("!unknown test-number"); + } + } + + /* check memory leak in custom allocator */ + ASSERTeq(custom_allocs, 0); + + if (expect_custom_alloc == 0) { + ASSERTeq(custom_alloc_calls, 0); + } else { + ASSERTne(custom_alloc_calls, 0); + } + + DONE(NULL); +} diff --git a/src/trn.c b/src/trn.c new file mode 100644 index 0000000000000000000000000000000000000000..33b1fd62ae4e13a5699008f3e7fc7286eeb9169b --- /dev/null +++ b/src/trn.c @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY LOG OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * trn.c -- transactional memory pool entry points for libpmem + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <signal.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> +#include <stdint.h> +#include <time.h> +#include <uuid/uuid.h> +#include <endian.h> +#include <libpmem.h> +#include "pmem.h" +#include "util.h" +#include "out.h" +#include "trn.h" + +/* + * trn_init -- load-time initialization for trn + * + * Called automatically by the run-time loader. + */ +__attribute__((constructor)) +static void +trn_init(void) +{ + out_init(LOG_PREFIX, LOG_LEVEL_VAR, LOG_FILE_VAR); + LOG(3, NULL); + util_init(); +} + +/* + * pmemtrn_map -- map a transactional memory pool + */ +PMEMtrn * +pmemtrn_map(int fd) +{ + LOG(3, "fd %d", fd); + + struct stat stbuf; + + if (fstat(fd, &stbuf) < 0) { + LOG(1, "!fstat"); + return NULL; + } + + if (stbuf.st_size < PMEMTRN_MIN_POOL) { + LOG(1, "size %zu smaller than %zu", + stbuf.st_size, PMEMTRN_MIN_POOL); + errno = EINVAL; + return NULL; + } + + void *addr; + if ((addr = util_map(fd, stbuf.st_size, 0)) == NULL) + return NULL; /* util_map() set errno, called LOG */ + + /* check if the mapped region is located in persistent memory */ + int is_pmem = pmem_is_pmem(addr, stbuf.st_size); + + /* opaque info lives at the beginning of mapped memory pool */ + struct pmemtrn *ptp = addr; + + struct pool_hdr hdr; + memcpy(&hdr, &ptp->hdr, sizeof (hdr)); + + if (util_convert_hdr(&hdr)) { + /* + * valid header found + */ + if (strncmp(hdr.signature, TRN_HDR_SIG, POOL_HDR_SIG_LEN)) { + LOG(1, "wrong pool type: \"%s\"", hdr.signature); + + errno = EINVAL; + goto err; + } + + if (hdr.major != TRN_FORMAT_MAJOR) { + LOG(1, "trn pool version %d (library expects %d)", + hdr.major, TRN_FORMAT_MAJOR); + + errno = EINVAL; + goto err; + } + + int retval = util_feature_check(&hdr, TRN_FORMAT_INCOMPAT, + TRN_FORMAT_RO_COMPAT, + TRN_FORMAT_COMPAT); + if (retval < 0) + goto err; + else if (retval == 0) { + /* XXX switch to read-only mode */ + } + } else { + /* + * no valid header was found + */ + LOG(3, "creating new trn memory pool"); + + struct pool_hdr *hdrp = &ptp->hdr; + + memset(hdrp, '\0', sizeof (*hdrp)); + strncpy(hdrp->signature, TRN_HDR_SIG, POOL_HDR_SIG_LEN); + hdrp->major = htole32(TRN_FORMAT_MAJOR); + hdrp->compat_features = htole32(TRN_FORMAT_COMPAT); + hdrp->incompat_features = htole32(TRN_FORMAT_INCOMPAT); + hdrp->ro_compat_features = htole32(TRN_FORMAT_RO_COMPAT); + uuid_generate(hdrp->uuid); + hdrp->crtime = htole64((uint64_t)time(NULL)); + util_checksum(hdrp, sizeof (*hdrp), &hdrp->checksum, 1); + hdrp->checksum = htole64(hdrp->checksum); + + /* store pool's header */ + libpmem_persist(is_pmem, hdrp, sizeof (*hdrp)); + + /* XXX create rest of required metadata */ + } + + /* use some of the memory pool area for run-time info */ + ptp->addr = addr; + ptp->size = stbuf.st_size; + + /* + * If possible, turn off all permissions on the pool header page. + * + * The prototype PMFS doesn't allow this when large pages are in + * use not it is not considered an error if this fails. + */ + util_range_none(addr, sizeof (struct pool_hdr)); + + /* the rest should be kept read-only for debug version */ + RANGE_RO(addr + sizeof (struct pool_hdr), + stbuf.st_size - sizeof (struct pool_hdr)); + + LOG(3, "ptp %p", ptp); + return ptp; + +err: + LOG(4, "error clean up"); + int oerrno = errno; + util_unmap(addr, stbuf.st_size); + errno = oerrno; + return NULL; +} + +/* + * pmemtrn_unmap -- unmap a transactional memory pool + */ +void +pmemtrn_unmap(PMEMtrn *ptp) +{ + LOG(3, "ptp %p", ptp); + + util_unmap(ptp->addr, ptp->size); +} + +/* + * pmemtrn_check -- transactional memory pool consistency check + */ +int +pmemtrn_check(const char *path) +{ + LOG(3, "path \"%s\"", path); + + /* XXX stub */ + return 0; +} diff --git a/src/trn.h b/src/trn.h new file mode 100644 index 0000000000000000000000000000000000000000..902a4f161ca5d07aded0bb9edb9ff23dafad9fc2 --- /dev/null +++ b/src/trn.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * trn.h -- internal definitions for libpmem trn module + */ + +/* attributes of the trn memory pool format for the pool header */ +#define TRN_HDR_SIG "PMEMTRN" /* must be 8 bytes including '\0' */ +#define TRN_FORMAT_MAJOR 1 +#define TRN_FORMAT_COMPAT 0x0000 +#define TRN_FORMAT_INCOMPAT 0x0000 +#define TRN_FORMAT_RO_COMPAT 0x0000 + +struct pmemtrn { + struct pool_hdr hdr; /* memory pool header */ + + /* root info for on-media format... */ + + /* some run-time state, allocated out of memory pool... */ + void *addr; /* mapped region */ + size_t size; /* size of mapped region */ +}; diff --git a/src/util.c b/src/util.c new file mode 100644 index 0000000000000000000000000000000000000000..9de00784031da4859481f0e5acda20bacaf1b37a --- /dev/null +++ b/src/util.c @@ -0,0 +1,340 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * util.c -- general utilities used in the library + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/mman.h> +#include <unistd.h> +#include <stdint.h> +#include <endian.h> +#include <errno.h> +#include "util.h" +#include "out.h" + +/* library-wide page size */ +unsigned long Pagesize; + +/* + * our versions of malloc & friends start off pointing to the libc versions + */ +Malloc_func Malloc = malloc; +Free_func Free = free; +Realloc_func Realloc = realloc; +Strdup_func Strdup = strdup; + +/* + * util_init -- initialize the utils + * + * This is called from the library initialization code. + */ +void +util_init(void) +{ + LOG(3, NULL); + if (Pagesize == 0) + Pagesize = (unsigned long) sysconf(_SC_PAGESIZE); +} + +/* + * util_set_alloc_funcs -- allow one to override malloc, etc. + */ +void +util_set_alloc_funcs(void *(*malloc_func)(size_t size), + void (*free_func)(void *ptr), + void *(*realloc_func)(void *ptr, size_t size), + char *(*strdup_func)(const char *s)) +{ + LOG(3, "malloc %p free %p realloc %p strdup %p", + malloc_func, free_func, realloc_func, strdup_func); + + Malloc = (malloc_func == NULL) ? malloc : malloc_func; + Free = (free_func == NULL) ? free : free_func; + Realloc = (realloc_func == NULL) ? realloc : realloc_func; + Strdup = (strdup_func == NULL) ? strdup : strdup_func; +} + +/* + * util_map -- memory map a file + * + * This is just a convenience function that calls mmap() with the + * appropriate arguments and includes our trace points. + * + * If cow is set, the file is mapped copy-on-write. + */ +void * +util_map(int fd, size_t len, int cow) +{ + void *base; + + LOG(3, "fd %d len %zu cow %d", fd, len, cow); + + if ((base = mmap(NULL, len, PROT_READ|PROT_WRITE, + (cow) ? MAP_PRIVATE|MAP_NORESERVE : MAP_SHARED, + fd, 0)) == MAP_FAILED) { + LOG(1, "!mmap %zu bytes", len); + return NULL; + } + + LOG(3, "mapped at %p", base); + + return base; +} + +/* + * util_unmap -- unmap a file + * + * This is just a convenience function that calls munmap() with the + * appropriate arguments and includes our trace points. + */ +int +util_unmap(void *addr, size_t len) +{ + LOG(3, "addr %p len %zu", addr, len); + + int retval = munmap(addr, len); + + if (retval < 0) + LOG(1, "!munmap"); + + return retval; +} + +/* + * util_checksum -- compute Fletcher64 checksum + * + * csump points to where the checksum lives, so that location + * is treated as zeros while calculating the checksum. If + * insert is true, the calculated checksum is inserted into + * the range at *csump. Otherwise the calculated checksum is + * checked against *csump and the result returned (true means + * the range checksummed correctly). + */ +int +util_checksum(void *addr, size_t len, uint64_t *csump, int insert) +{ + uint32_t *p32 = addr; + uint32_t *p32end = addr + len; + uint32_t lo32 = 0; + uint32_t hi32 = 0; + uint64_t csum; + + while (p32 < p32end) + if (p32 == (uint32_t *)csump) { + /* lo32 += 0; treat first 32-bits as zero */ + p32++; + hi32 += lo32; + /* lo32 += 0; treat second 32-bits as zero */ + p32++; + hi32 += lo32; + } else { + lo32 += *p32++; + hi32 += lo32; + } + + csum = (uint64_t)hi32 << 32 | lo32; + + if (insert) { + *csump = csum; + return 1; + } + + return *csump == csum; +} + +/* + * util_convert_hdr -- convert header to host byte order & validate + * + * Returns true if header is valid, and all the integer fields are + * converted to host byte order. If the header is not valid, this + * routine returns false and the header passed in is left in an + * unknown state. + */ +int +util_convert_hdr(struct pool_hdr *hdrp) +{ + LOG(3, "hdrp %p", hdrp); + + /* to be valid, a header must have a major version of at least 1 */ + if ((hdrp->major = le32toh(hdrp->major)) == 0) { + LOG(3, "invalid major version (0)"); + return 0; + } + hdrp->compat_features = le32toh(hdrp->compat_features); + hdrp->incompat_features = le32toh(hdrp->incompat_features); + hdrp->ro_compat_features = le32toh(hdrp->ro_compat_features); + hdrp->crtime = le64toh(hdrp->crtime); + hdrp->checksum = le64toh(hdrp->checksum); + + /* and to be valid, the fields must checksum correctly */ + if (!util_checksum(hdrp, sizeof (*hdrp), &hdrp->checksum, 0)) { + LOG(3, "invalid checksum"); + return 0; + } + + LOG(3, "valid header, signature \"%s\"", hdrp->signature); + return 1; +} + +/* + * util_range_ro -- set a memory range read-only + */ +int +util_range_ro(void *addr, size_t len) +{ + LOG(3, "addr %p len %zu", addr, len); + + uintptr_t uptr; + int retval; + + /* + * mprotect requires addr to be a multiple of pagesize, so + * adjust addr and len to represent the full 4k chunks + * covering the given range. + */ + + /* increase len by the amount we gain when we round addr down */ + len += (uintptr_t)addr & (Pagesize - 1); + + /* round addr down to page boundary */ + uptr = (uintptr_t)addr & ~(Pagesize - 1); + + if ((retval = mprotect((void *)uptr, len, PROT_READ)) < 0) + LOG(1, "!mprotect: PROT_READ"); + + return retval; +} + +/* + * util_range_rw -- set a memory range read-write + */ +int +util_range_rw(void *addr, size_t len) +{ + LOG(3, "addr %p len %zu", addr, len); + + uintptr_t uptr; + int retval; + + /* + * mprotect requires addr to be a multiple of pagesize, so + * adjust addr and len to represent the full 4k chunks + * covering the given range. + */ + + /* increase len by the amount we gain when we round addr down */ + len += (uintptr_t)addr & (Pagesize - 1); + + /* round addr down to page boundary */ + uptr = (uintptr_t)addr & ~(Pagesize - 1); + + if ((retval = mprotect((void *)uptr, len, PROT_READ|PROT_WRITE)) < 0) + LOG(1, "!mprotect: PROT_READ|PROT_WRITE"); + + return retval; +} + +/* + * util_range_none -- set a memory range for no access allowed + */ +int +util_range_none(void *addr, size_t len) +{ + LOG(3, "addr %p len %zu", addr, len); + + uintptr_t uptr; + int retval; + + /* + * mprotect requires addr to be a multiple of pagesize, so + * adjust addr and len to represent the full 4k chunks + * covering the given range. + */ + + /* increase len by the amount we gain when we round addr down */ + len += (uintptr_t)addr & (Pagesize - 1); + + /* round addr down to page boundary */ + uptr = (uintptr_t)addr & ~(Pagesize - 1); + + if ((retval = mprotect((void *)uptr, len, PROT_NONE)) < 0) + LOG(1, "!mprotect: PROT_NONE"); + + return retval; +} + +/* + * util_feature_check -- check features masks + */ +int +util_feature_check(struct pool_hdr *hdrp, uint32_t incompat, + uint32_t ro_compat, uint32_t compat) +{ + LOG(3, "hdrp %p incompat %#x ro_compat %#x compat %#x", + hdrp, incompat, ro_compat, compat); + +#define GET_NOT_MASKED_BITS(x, mask) ((x) & ~(mask)) + + uint32_t ubits; /* unsupported bits */ + + /* check incompatible ("must support") features */ + ubits = GET_NOT_MASKED_BITS(hdrp->incompat_features, incompat); + if (ubits) { + LOG(1, "unsafe to continue due to unknown incompat "\ + "features: %#x", ubits); + errno = EINVAL; + return -1; + } + + /* check RO-compatible features (force RO if unsupported) */ + ubits = GET_NOT_MASKED_BITS(hdrp->ro_compat_features, ro_compat); + if (ubits) { + LOG(1, "switching to read-only mode due to unknown ro_compat "\ + "features: %#x", ubits); + return 0; + } + + /* check compatible ("may") features */ + ubits = GET_NOT_MASKED_BITS(hdrp->compat_features, compat); + if (ubits) { + LOG(3, "ignoring unknown compat features: %#x", ubits); + } + +#undef GET_NOT_MASKED_BITS + + return 1; +} diff --git a/src/util.h b/src/util.h new file mode 100644 index 0000000000000000000000000000000000000000..fc72835ce54bf22cda8cd618dfd84bc4f913e32f --- /dev/null +++ b/src/util.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * util.h -- internal definitions for util module + */ + +/* + * overridable names for malloc & friends used by this library + */ +typedef void *(*Malloc_func)(size_t size); +typedef void (*Free_func)(void *ptr); +typedef void *(*Realloc_func)(void *ptr, size_t size); +typedef char *(*Strdup_func)(const char *s); + +Malloc_func Malloc; +Free_func Free; +Realloc_func Realloc; +Strdup_func Strdup; + +void util_set_alloc_funcs( + void *(*malloc_func)(size_t size), + void (*free_func)(void *ptr), + void *(*realloc_func)(void *ptr, size_t size), + char *(*strdup_func)(const char *s)); +void *util_map(int fd, size_t len, int cow); +int util_unmap(void *addr, size_t len); + +/* + * header used at the beginning of all types of memory pools + * + * for pools build on persistent memory, the integer types + * below are stored in little-endian byte order. + */ +#define POOL_HDR_SIG_LEN 8 +#define POOL_HDR_UUID_LEN 16 +struct pool_hdr { + char signature[POOL_HDR_SIG_LEN]; + uint32_t major; /* format major version number */ + uint32_t compat_features; /* mask: compatible "may" features */ + uint32_t incompat_features; /* mask: "must support" features */ + uint32_t ro_compat_features; /* mask: force RO if unsupported */ + unsigned char uuid[POOL_HDR_UUID_LEN]; + uint64_t crtime; /* when created (seconds since epoch) */ + unsigned char unused[4040]; /* must be zero */ + uint64_t checksum; /* checksum of above fields */ +}; + +int util_checksum(void *addr, size_t len, uint64_t *csump, int insert); +int util_convert_hdr(struct pool_hdr *hdrp); + +/* + * macros for micromanaging range protections for the debug version + */ +#ifdef DEBUG + +#define RANGE_RO(addr, len) ASSERT(util_range_ro(addr, len) >= 0) +#define RANGE_RW(addr, len) ASSERT(util_range_rw(addr, len) >= 0) + +#else + +/* nondebug version */ +#define RANGE_RO(addr, len) +#define RANGE_RW(addr, len) + +#endif /* DEBUG */ + +void util_init(void); + +int util_range_ro(void *addr, size_t len); +int util_range_rw(void *addr, size_t len); +int util_range_none(void *addr, size_t len); + +int util_feature_check(struct pool_hdr *hdrp, uint32_t incompat, + uint32_t ro_compat, uint32_t compat); diff --git a/src/vmem.c b/src/vmem.c new file mode 100644 index 0000000000000000000000000000000000000000..bcc10efaaa9f56677f549fa5126cae2c250a0931 --- /dev/null +++ b/src/vmem.c @@ -0,0 +1,377 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY LOG OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * vmem.c -- memory pool & allocation entry points for libvmem + */ +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/param.h> +#include <signal.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> +#include <stdint.h> +#include <libvmem.h> +#include "jemalloc.h" +#include "util.h" +#include "out.h" +#include "vmem.h" + +/* + * private to this file... + */ +static unsigned Header_size; +static void *vmem_tmpfile(const char *dir, size_t size); + +/* + * print_jemalloc_messages -- custom print function, for jemalloc + * + * Prints traces from jemalloc. All traces from jemalloc + * are considered as error messages. + */ +static void +print_jemalloc_messages(void* ignore, const char *s) +{ + LOG_NONL(1, "%s", s); +} + +/* + * print_jemalloc_stats -- print function, for jemalloc statistics + * + * Prints statistics from jemalloc. All statistics are printed with level 0. + */ +static void +print_jemalloc_stats(void* ignore, const char *s) +{ + LOG_NONL(0, "%s", s); +} + +/* + * vmem_init -- load-time initialization for vmem + * + * Called automatically by the run-time loader. + */ +__attribute__((constructor)) +static void +vmem_init(void) +{ + out_init(LOG_PREFIX, LOG_LEVEL_VAR, LOG_FILE_VAR); + LOG(3, NULL); + util_init(); + Header_size = roundup(sizeof (VMEM), Pagesize); + + /* Set up jemalloc to forward messages to a custom print function */ + je_vmem_malloc_message = print_jemalloc_messages; +} + +/* + * vmem_pool_create -- create a memory pool in a temp file + */ +VMEM * +vmem_pool_create(const char *dir, size_t size) +{ + LOG(3, "dir \"%s\" size %zu", dir, size); + + if (size < VMEM_MIN_POOL) { + LOG(1, "size %zu smaller than %zu", size, VMEM_MIN_POOL); + errno = EINVAL; + return NULL; + } + + /* silently enforce multiple of page size */ + size = roundup(size, Pagesize); + + void *addr; + if ((addr = vmem_tmpfile(dir, size)) == NULL) + return NULL; + + /* store opaque info at beginning of mapped area */ + struct vmem *vmp = addr; + memset(&vmp->hdr, '\0', sizeof (vmp->hdr)); + strncpy(vmp->hdr.signature, VMEM_HDR_SIG, POOL_HDR_SIG_LEN); + vmp->addr = addr; + vmp->size = size; + vmp->caller_mapped = 0; + + /* Prepare pool for jemalloc */ + if (je_vmem_pool_create((void *)((uintptr_t)addr + Header_size), + size - Header_size, 1) == NULL) { + LOG(1, "return NULL"); + util_unmap(vmp->addr, vmp->size); + return NULL; + } + + /* + * If possible, turn off all permissions on the pool header page. + * + * The prototype PMFS doesn't allow this when large pages are in + * use not it is not considered an error if this fails. + */ + util_range_none(addr, sizeof (struct pool_hdr)); + + LOG(3, "vmp %p", vmp); + return vmp; +} + +/* + * vmem_pool_create_in_region -- create a memory pool in a given range + */ +VMEM * +vmem_pool_create_in_region(void *addr, size_t size) +{ + LOG(3, "addr %p size %zu", addr, size); + + if (size < VMEM_MIN_POOL) { + LOG(1, "size %zu smaller than %zu", size, VMEM_MIN_POOL); + errno = EINVAL; + return NULL; + } + + /* store opaque info at beginning of mapped area */ + struct vmem *vmp = addr; + memset(&vmp->hdr, '\0', sizeof (vmp->hdr)); + strncpy(vmp->hdr.signature, VMEM_HDR_SIG, POOL_HDR_SIG_LEN); + vmp->addr = addr; + vmp->size = size; + vmp->caller_mapped = 1; + + /* Prepare pool for jemalloc */ + if (je_vmem_pool_create((void *)((uintptr_t)addr + Header_size), + size - Header_size, 0) == NULL) { + LOG(1, "return NULL"); + return NULL; + } + +#ifdef notdef + /* + * XXX not ready to call aligned util_range_none() yet, + * addr should be aligned to do that. + * + * If possible, turn off all permissions on the pool header page. + * + * The prototype PMFS doesn't allow this when large pages are in + * use not it is not considered an error if this fails. + */ + util_range_none(addr, sizeof (struct pool_hdr)); +#endif /* notdef */ + + LOG(3, "vmp %p", vmp); + return vmp; +} + +/* + * vmem_pool_delete -- delete a memory pool + */ +void +vmem_pool_delete(VMEM *vmp) +{ + LOG(3, "vmp %p", vmp); + + je_vmem_pool_delete((pool_t *)((uintptr_t)vmp + Header_size)); + + if (vmp->caller_mapped == 0) + util_unmap(vmp->addr, vmp->size); +} + +/* + * vmem_pool_check -- memory pool consistency check + */ +int +vmem_pool_check(VMEM *vmp) +{ + LOG(3, "vmp %p", vmp); + + if (strncmp(vmp->hdr.signature, VMEM_HDR_SIG, POOL_HDR_SIG_LEN) != 0) { + return 0; + } + + /* XXX stub */ + return 1; +} + +/* + * vmem_pool_freespace -- return current freespace in memory pool + */ +size_t +vmem_pool_freespace(VMEM *vmp) +{ + LOG(3, "vmp %p", vmp); + + /* XXX stub */ + return vmp->size; +} + +/* + * vmem_pool_stats_print -- spew memory allocator stats for a pool + */ +void +vmem_pool_stats_print(VMEM *vmp, const char *opts) +{ + LOG(3, "vmp %p opts \"%s\"", vmp, opts); + + je_vmem_pool_malloc_stats_print( + (pool_t *)((uintptr_t)vmp + Header_size), + print_jemalloc_stats, NULL, opts); +} + +/* + * vmem_malloc -- allocate memory + */ +void * +vmem_malloc(VMEM *vmp, size_t size) +{ + LOG(3, "vmp %p size %zu", vmp, size); + + return je_vmem_pool_malloc( + (pool_t *)((uintptr_t)vmp + Header_size), size); +} + +/* + * vmem_free -- free memory + */ +void +vmem_free(VMEM *vmp, void *ptr) +{ + LOG(3, "vmp %p ptr %p", vmp, ptr); + + ASSERT(ptr != NULL); + je_vmem_pool_free((pool_t *)((uintptr_t)vmp + Header_size), ptr); +} + +/* + * vmem_calloc -- allocate zeroed memory + */ +void * +vmem_calloc(VMEM *vmp, size_t nmemb, size_t size) +{ + LOG(3, "vmp %p nmemb %zu size %zu", vmp, nmemb, size); + + return je_vmem_pool_calloc((pool_t *)((uintptr_t)vmp + Header_size), + nmemb, size); +} + +/* + * vmem_realloc -- resize a memory allocation + */ +void * +vmem_realloc(VMEM *vmp, void *ptr, size_t size) +{ + LOG(3, "vmp %p ptr %p size %zu", vmp, ptr, size); + + return je_vmem_pool_ralloc((pool_t *)((uintptr_t)vmp + Header_size), + ptr, size); +} + +/* + * vmem_aligned_alloc -- allocate aligned memory + */ +void * +vmem_aligned_alloc(VMEM *vmp, size_t alignment, size_t size) +{ + LOG(3, "vmp %p alignment %zu size %zu", vmp, alignment, size); + + return je_vmem_pool_aligned_alloc( + (pool_t *)((uintptr_t)vmp + Header_size), + alignment, size); +} + +/* + * vmem_strdup -- allocate memory for copy of string + */ +char * +vmem_strdup(VMEM *vmp, const char *s) +{ + LOG(3, "vmp %p s %p", vmp, s); + + size_t size = strlen(s) + 1; + void *retaddr = je_vmem_pool_malloc( + (pool_t *)((uintptr_t)vmp + Header_size), size); + if (retaddr == NULL) + return NULL; + + return (char *)memcpy(retaddr, s, size); +} + +/* + * vmem_tmpfile -- reserve space in an unlinked file and memory-map it + * + * size must be multiple of page size. + */ +static void * +vmem_tmpfile(const char *dir, size_t size) +{ + static char template[] = "/vmem.XXXXXX"; + + char fullname[strlen(dir) + sizeof (template)]; + (void) strcpy(fullname, dir); + (void) strcat(fullname, template); + + sigset_t set, oldset; + sigfillset(&set); + (void) sigprocmask(SIG_BLOCK, &set, &oldset); + + int fd; + if ((fd = mkstemp(fullname)) < 0) { + LOG(1, "!mkstemp"); + goto err; + } + + (void) unlink(fullname); + (void) sigprocmask(SIG_SETMASK, &oldset, NULL); + + LOG(3, "unlinked file is \"%s\"", fullname); + + if ((errno = posix_fallocate(fd, 0, size)) != 0) { + LOG(1, "!posix_fallocate"); + goto err; + } + + void *base; + if ((base = util_map(fd, size, 0)) == NULL) + goto err; + + (void) close(fd); + return base; + +err: + LOG(1, "return NULL"); + int oerrno = errno; + (void) sigprocmask(SIG_SETMASK, &oldset, NULL); + if (fd != -1) + (void) close(fd); + errno = oerrno; + return NULL; +} diff --git a/src/vmem.h b/src/vmem.h new file mode 100644 index 0000000000000000000000000000000000000000..d9fca88dc9f8d000e2cbcc017206a0defdc14c3e --- /dev/null +++ b/src/vmem.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2014, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * vmem.h -- internal definitions for libvmem + */ + +#define LOG_PREFIX "libvmem" +#define LOG_LEVEL_VAR "VMEM_LOG_LEVEL" +#define LOG_FILE_VAR "VMEM_LOG_FILE" + +/* attributes of the vmem memory pool format for the pool header */ +#define VMEM_HDR_SIG "VMEM " /* must be 8 bytes including '\0' */ +#define VMEM_FORMAT_MAJOR 1 +#define VMEM_FORMAT_COMPAT 0x0000 +#define VMEM_FORMAT_INCOMPAT 0x0000 +#define VMEM_FORMAT_RO_COMPAT 0x0000 + +extern unsigned long Pagesize; + +struct vmem { + struct pool_hdr hdr; /* memory pool header */ + + void *addr; /* mapped region */ + size_t size; /* size of mapped region */ + int caller_mapped; +}; diff --git a/utils/README b/utils/README new file mode 100644 index 0000000000000000000000000000000000000000..5c977d11f6e098b91be299c32e863133d3e09d84 --- /dev/null +++ b/utils/README @@ -0,0 +1,5 @@ +Linux NVM Library + +This is utils/README. + +The scripts found here are used during library development. diff --git a/utils/cstyle b/utils/cstyle new file mode 100755 index 0000000000000000000000000000000000000000..d524ddfa458b66e71c5d92e763b754389df774b1 --- /dev/null +++ b/utils/cstyle @@ -0,0 +1,951 @@ +#!/usr/bin/perl -w +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)cstyle 1.58 98/09/09 (from shannon) +#ident "%Z%%M% %I% %E% SMI" +# +# cstyle - check for some common stylistic errors. +# +# cstyle is a sort of "lint" for C coding style. +# It attempts to check for the style used in the +# kernel, sometimes known as "Bill Joy Normal Form". +# +# There's a lot this can't check for, like proper indentation +# of code blocks. There's also a lot more this could check for. +# +# A note to the non perl literate: +# +# perl regular expressions are pretty much like egrep +# regular expressions, with the following special symbols +# +# \s any space character +# \S any non-space character +# \w any "word" character [a-zA-Z0-9_] +# \W any non-word character +# \d a digit [0-9] +# \D a non-digit +# \b word boundary (between \w and \W) +# \B non-word boundary +# + +require 5.0; +use IO::File; +use Getopt::Std; +use strict; + +my $usage = +"usage: cstyle [-chpvCP] [-o constructs] file ... + -c check continuation indentation inside functions + -h perform heuristic checks that are sometimes wrong + -p perform some of the more picky checks + -v verbose + -C don't check anything in header block comments + -P check for use of non-POSIX types + -o constructs + allow a comma-seperated list of optional constructs: + doxygen allow doxygen-style block comments (/** /*!) + splint allow splint-style lint comments (/*@ ... @*/) +"; + +my %opts; + +if (!getopts("cho:pvCP", \%opts)) { + print $usage; + exit 2; +} + +my $check_continuation = $opts{'c'}; +my $heuristic = $opts{'h'}; +my $picky = $opts{'p'}; +my $verbose = $opts{'v'}; +my $ignore_hdr_comment = $opts{'C'}; +my $check_posix_types = $opts{'P'}; + +my $doxygen_comments = 0; +my $splint_comments = 0; + +if (defined($opts{'o'})) { + for my $x (split /,/, $opts{'o'}) { + if ($x eq "doxygen") { + $doxygen_comments = 1; + } elsif ($x eq "splint") { + $splint_comments = 1; + } else { + print "cstyle: unrecognized construct \"$x\"\n"; + print $usage; + exit 2; + } + } +} + +my ($filename, $line, $prev); # shared globals + +my $fmt; +my $hdr_comment_start; + +if ($verbose) { + $fmt = "%s: %d: %s\n%s\n"; +} else { + $fmt = "%s: %d: %s\n"; +} + +if ($doxygen_comments) { + # doxygen comments look like "/*!" or "/**"; allow them. + $hdr_comment_start = qr/^\s*\/\*[\!\*]?$/; +} else { + $hdr_comment_start = qr/^\s*\/\*$/; +} + +# Note, following must be in single quotes so that \s and \w work right. +my $typename = '(int|char|short|long|unsigned|float|double' . + '|\w+_t|struct\s+\w+|union\s+\w+|FILE)'; + +# mapping of old types to POSIX compatible types +my %old2posix = ( + 'unchar' => 'uchar_t', + 'ushort' => 'ushort_t', + 'uint' => 'uint_t', + 'ulong' => 'ulong_t', + 'u_int' => 'uint_t', + 'u_short' => 'ushort_t', + 'u_long' => 'ulong_t', + 'u_char' => 'uchar_t', + 'quad' => 'quad_t' +); + +my $lint_re = qr/\/\*(?: + ARGSUSED[0-9]*|NOTREACHED|LINTLIBRARY|VARARGS[0-9]*| + CONSTCOND|CONSTANTCOND|CONSTANTCONDITION|EMPTY| + FALLTHRU|FALLTHROUGH|LINTED.*?|PRINTFLIKE[0-9]*| + PROTOLIB[0-9]*|SCANFLIKE[0-9]*|CSTYLED.*? + )\*\//x; + +my $splint_re = qr/\/\*@.*?@\*\//x; + +my $warlock_re = qr/\/\*\s*(?: + VARIABLES\ PROTECTED\ BY| + MEMBERS\ PROTECTED\ BY| + ALL\ MEMBERS\ PROTECTED\ BY| + READ-ONLY\ VARIABLES:| + READ-ONLY\ MEMBERS:| + VARIABLES\ READABLE\ WITHOUT\ LOCK:| + MEMBERS\ READABLE\ WITHOUT\ LOCK:| + LOCKS\ COVERED\ BY| + LOCK\ UNNEEDED\ BECAUSE| + LOCK\ NEEDED:| + LOCK\ HELD\ ON\ ENTRY:| + READ\ LOCK\ HELD\ ON\ ENTRY:| + WRITE\ LOCK\ HELD\ ON\ ENTRY:| + LOCK\ ACQUIRED\ AS\ SIDE\ EFFECT:| + READ\ LOCK\ ACQUIRED\ AS\ SIDE\ EFFECT:| + WRITE\ LOCK\ ACQUIRED\ AS\ SIDE\ EFFECT:| + LOCK\ RELEASED\ AS\ SIDE\ EFFECT:| + LOCK\ UPGRADED\ AS\ SIDE\ EFFECT:| + LOCK\ DOWNGRADED\ AS\ SIDE\ EFFECT:| + FUNCTIONS\ CALLED\ THROUGH\ POINTER| + FUNCTIONS\ CALLED\ THROUGH\ MEMBER| + LOCK\ ORDER: + )/x; + +my $err_stat = 0; # exit status + +if ($#ARGV >= 0) { + foreach my $arg (@ARGV) { + my $fh = new IO::File $arg, "r"; + if (!defined($fh)) { + printf "%s: can not open\n", $arg; + } else { + &cstyle($arg, $fh); + close $fh; + } + } +} else { + &cstyle("<stdin>", *STDIN); +} +exit $err_stat; + +my $no_errs = 0; # set for CSTYLED-protected lines + +sub err($) { + my ($error) = @_; + unless ($no_errs) { + printf $fmt, $filename, $., $error, $line; + $err_stat = 1; + } +} + +sub err_prefix($$) { + my ($prevline, $error) = @_; + my $out = $prevline."\n".$line; + unless ($no_errs) { + printf $fmt, $filename, $., $error, $out; + $err_stat = 1; + } +} + +sub err_prev($) { + my ($error) = @_; + unless ($no_errs) { + printf $fmt, $filename, $. - 1, $error, $prev; + $err_stat = 1; + } +} + +sub cstyle($$) { + +my ($fn, $filehandle) = @_; +$filename = $fn; # share it globally + +my $in_cpp = 0; +my $next_in_cpp = 0; + +my $in_comment = 0; +my $in_header_comment = 0; +my $comment_done = 0; +my $in_warlock_comment = 0; +my $in_function = 0; +my $in_function_header = 0; +my $in_declaration = 0; +my $note_level = 0; +my $nextok = 0; +my $nocheck = 0; + +my $in_string = 0; + +my ($okmsg, $comment_prefix); + +$line = ''; +$prev = ''; +reset_indent(); + +line: while (<$filehandle>) { + s/\r?\n$//; # strip return and newline + + # save the original line, then remove all text from within + # double or single quotes, we do not want to check such text. + + $line = $_; + + # + # C allows strings to be continued with a backslash at the end of + # the line. We translate that into a quoted string on the previous + # line followed by an initial quote on the next line. + # + # (we assume that no-one will use backslash-continuation with character + # constants) + # + $_ = '"' . $_ if ($in_string && !$nocheck && !$in_comment); + + # + # normal strings and characters + # + s/'([^\\']|\\[^xX0]|\\0[0-9]*|\\[xX][0-9a-fA-F]*)'/''/g; + s/"([^\\"]|\\.)*"/\"\"/g; + + # + # detect string continuation + # + if ($nocheck || $in_comment) { + $in_string = 0; + } else { + # + # Now that all full strings are replaced with "", we check + # for unfinished strings continuing onto the next line. + # + $in_string = + (s/([^"](?:"")*)"([^\\"]|\\.)*\\$/$1""/ || + s/^("")*"([^\\"]|\\.)*\\$/""/); + } + + # + # figure out if we are in a cpp directive + # + $in_cpp = $next_in_cpp || /^\s*#/; # continued or started + $next_in_cpp = $in_cpp && /\\$/; # only if continued + + # strip off trailing backslashes, which appear in long macros + s/\s*\\$//; + + # an /* END CSTYLED */ comment ends a no-check block. + if ($nocheck) { + if (/\/\* *END *CSTYLED *\*\//) { + $nocheck = 0; + } else { + reset_indent(); + next line; + } + } + + # a /*CSTYLED*/ comment indicates that the next line is ok. + if ($nextok) { + if ($okmsg) { + err($okmsg); + } + $nextok = 0; + $okmsg = 0; + if (/\/\* *CSTYLED.*\*\//) { + /^.*\/\* *CSTYLED *(.*) *\*\/.*$/; + $okmsg = $1; + $nextok = 1; + } + $no_errs = 1; + } elsif ($no_errs) { + $no_errs = 0; + } + + # check length of line. + # first, a quick check to see if there is any chance of being too long. + if (($line =~ tr/\t/\t/) * 7 + length($line) > 80) { + # yes, there is a chance. + # replace tabs with spaces and check again. + my $eline = $line; + 1 while $eline =~ + s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e; + if (length($eline) > 80) { + err("line > 80 characters"); + } + } + + # ignore NOTE(...) annotations (assumes NOTE is on lines by itself). + if ($note_level || /\b_?NOTE\s*\(/) { # if in NOTE or this is NOTE + s/[^()]//g; # eliminate all non-parens + $note_level += s/\(//g - length; # update paren nest level + next; + } + + # a /* BEGIN CSTYLED */ comment starts a no-check block. + if (/\/\* *BEGIN *CSTYLED *\*\//) { + $nocheck = 1; + } + + # a /*CSTYLED*/ comment indicates that the next line is ok. + if (/\/\* *CSTYLED.*\*\//) { + /^.*\/\* *CSTYLED *(.*) *\*\/.*$/; + $okmsg = $1; + $nextok = 1; + } + if (/\/\/ *CSTYLED/) { + /^.*\/\/ *CSTYLED *(.*)$/; + $okmsg = $1; + $nextok = 1; + } + + # universal checks; apply to everything + if (/\t +\t/) { + err("spaces between tabs"); + } + if (/ \t+ /) { + err("tabs between spaces"); + } + if (/\s$/) { + err("space or tab at end of line"); + } + if (/[^ \t(]\/\*/ && !/\w\(\/\*.*\*\/\);/) { + err("comment preceded by non-blank"); + } + + # is this the beginning or ending of a function? + # (not if "struct foo\n{\n") + if (/^{$/ && $prev =~ /\)\s*(const\s*)?(\/\*.*\*\/\s*)?\\?$/) { + $in_function = 1; + $in_declaration = 1; + $in_function_header = 0; + $prev = $line; + next line; + } + if (/^}\s*(\/\*.*\*\/\s*)*$/) { + if ($prev =~ /^\s*return\s*;/) { + err_prev("unneeded return at end of function"); + } + $in_function = 0; + reset_indent(); # we don't check between functions + $prev = $line; + next line; + } + if (/^\w*\($/) { + $in_function_header = 1; + } + + if ($in_warlock_comment && /\*\//) { + $in_warlock_comment = 0; + $prev = $line; + next line; + } + + # a blank line terminates the declarations within a function. + # XXX - but still a problem in sub-blocks. + if ($in_declaration && /^$/) { + $in_declaration = 0; + } + + if ($comment_done) { + $in_comment = 0; + $in_header_comment = 0; + $comment_done = 0; + } + # does this looks like the start of a block comment? + if (/$hdr_comment_start/) { + if (!/^\t*\/\*/) { + err("block comment not indented by tabs"); + } + $in_comment = 1; + /^(\s*)\//; + $comment_prefix = $1; + if ($comment_prefix eq "") { + $in_header_comment = 1; + } + $prev = $line; + next line; + } + # are we still in the block comment? + if ($in_comment) { + if (/^$comment_prefix \*\/$/) { + $comment_done = 1; + } elsif (/\*\//) { + $comment_done = 1; + err("improper block comment close") + unless ($ignore_hdr_comment && $in_header_comment); + } elsif (!/^$comment_prefix \*[ \t]/ && + !/^$comment_prefix \*$/) { + err("improper block comment") + unless ($ignore_hdr_comment && $in_header_comment); + } + } + + if ($in_header_comment && $ignore_hdr_comment) { + $prev = $line; + next line; + } + + # check for errors that might occur in comments and in code. + + # allow spaces to be used to draw pictures in header comments. + if (/[^ ] / && !/".* .*"/ && !$in_header_comment) { + err("spaces instead of tabs"); + } + if (/^ / && !/^ \*[ \t\/]/ && !/^ \*$/ && + (!/^ \w/ || $in_function != 0)) { + err("indent by spaces instead of tabs"); + } + if (/^\t+ [^ \t\*]/ || /^\t+ \S/ || /^\t+ \S/) { + err("continuation line not indented by 4 spaces"); + } + if (/$warlock_re/ && !/\*\//) { + $in_warlock_comment = 1; + $prev = $line; + next line; + } + if (/^\s*\/\*./ && !/^\s*\/\*.*\*\// && !/$hdr_comment_start/) { + err("improper first line of block comment"); + } + + if ($in_comment) { # still in comment, don't do further checks + $prev = $line; + next line; + } + + if ((/[^(]\/\*\S/ || /^\/\*\S/) && + !(/$lint_re/ || ($splint_comments && /$splint_re/))) { + err("missing blank after open comment"); + } + if (/\S\*\/[^)]|\S\*\/$/ && + !(/$lint_re/ || ($splint_comments && /$splint_re/))) { + err("missing blank before close comment"); + } + if (/\/\/\S/) { # C++ comments + err("missing blank after start comment"); + } + # check for unterminated single line comments, but allow them when + # they are used to comment out the argument list of a function + # declaration. + if (/\S.*\/\*/ && !/\S.*\/\*.*\*\// && !/\(\/\*/) { + err("unterminated single line comment"); + } + + if (/^(#else|#endif|#include)(.*)$/) { + $prev = $line; + if ($picky) { + my $directive = $1; + my $clause = $2; + # Enforce ANSI rules for #else and #endif: no noncomment + # identifiers are allowed after #endif or #else. Allow + # C++ comments since they seem to be a fact of life. + if ((($1 eq "#endif") || ($1 eq "#else")) && + ($clause ne "") && + (!($clause =~ /^\s+\/\*.*\*\/$/)) && + (!($clause =~ /^\s+\/\/.*$/))) { + err("non-comment text following " . + "$directive (or malformed $directive " . + "directive)"); + } + } + next line; + } + + # + # delete any comments and check everything else. Note that + # ".*?" is a non-greedy match, so that we don't get confused by + # multiple comments on the same line. + # + s/\/\*.*?\*\///g; + s/\/\/.*$//; # C++ comments + + # delete any trailing whitespace; we have already checked for that. + s/\s*$//; + + # following checks do not apply to text in comments. + + if (/[^<>\s][!<>=]=/ || /[^<>][!<>=]=[^\s,]/ || + (/[^->]>[^,=>\s]/ && !/[^->]>$/) || + (/[^<]<[^,=<\s]/ && !/[^<]<$/) || + /[^<\s]<[^<]/ || /[^->\s]>[^>]/) { + err("missing space around relational operator"); + } + if (/\S>>=/ || /\S<<=/ || />>=\S/ || /<<=\S/ || /\S[-+*\/&|^%]=/ || + (/[^-+*\/&|^%!<>=\s]=[^=]/ && !/[^-+*\/&|^%!<>=\s]=$/) || + (/[^!<>=]=[^=\s]/ && !/[^!<>=]=$/)) { + # XXX - should only check this for C++ code + # XXX - there are probably other forms that should be allowed + if (!/\soperator=/) { + err("missing space around assignment operator"); + } + } + if (/[,;]\S/ && !/\bfor \(;;\)/) { + err("comma or semicolon followed by non-blank"); + } + # allow "for" statements to have empty "while" clauses + if (/\s[,;]/ && !/^[\t]+;$/ && !/^\s*for \([^;]*; ;[^;]*\)/) { + err("comma or semicolon preceded by blank"); + } + if (/^\s*(&&|\|\|)/) { + err("improper boolean continuation"); + } + if (/\S *(&&|\|\|)/ || /(&&|\|\|) *\S/) { + err("more than one space around boolean operator"); + } + if (/\b(for|if|while|switch|sizeof|return|case)\(/) { + err("missing space between keyword and paren"); + } + if (/(\b(for|if|while|switch|return)\b.*){2,}/ && !/^#define/) { + # multiple "case" and "sizeof" allowed + err("more than one keyword on line"); + } + if (/\b(for|if|while|switch|sizeof|return|case)\s\s+\(/ && + !/^#if\s+\(/) { + err("extra space between keyword and paren"); + } + # try to detect "func (x)" but not "if (x)" or + # "#define foo (x)" or "int (*func)();" + if (/\w\s\(/) { + my $s = $_; + # strip off all keywords on the line + s/\b(for|if|while|switch|return|case|sizeof)\s\(/XXX(/g; + s/#elif\s\(/XXX(/g; + s/^#define\s+\w+\s+\(/XXX(/; + # do not match things like "void (*f)();" + # or "typedef void (func_t)();" + s/\w\s\(+\*/XXX(*/g; + s/\b($typename|void)\s+\(+/XXX(/og; + if (/\w\s\(/) { + err("extra space between function name and left paren"); + } + $_ = $s; + } + # try to detect "int foo(x)", but not "extern int foo(x);" + # XXX - this still trips over too many legitimate things, + # like "int foo(x,\n\ty);" +# if (/^(\w+(\s|\*)+)+\w+\(/ && !/\)[;,](\s|)*$/ && +# !/^(extern|static)\b/) { +# err("return type of function not on separate line"); +# } + # this is a close approximation + if (/^(\w+(\s|\*)+)+\w+\(.*\)(\s|)*$/ && + !/^(extern|static)\b/) { + err("return type of function not on separate line"); + } + if (/^#define /) { + err("#define followed by space instead of tab"); + } + # AON C-style doesn't require this. + #if (/^\s*return\W[^;]*;/ && !/^\s*return\s*\(.*\);/) { + # err("unparenthesized return expression"); + #} + if (/\bsizeof\b/ && !/\bsizeof\s*\(.*\)/) { + err("unparenthesized sizeof expression"); + } + if (/\(\s/) { + err("whitespace after left paren"); + } + # allow "for" statements to have empty "continue" clauses + if (/\s\)/ && !/^\s*for \([^;]*;[^;]*; \)/) { + err("whitespace before right paren"); + } + if (/^\s*\(void\)[^ ]/) { + err("missing space after (void) cast"); + } + if (/\S{/ && !/{{/) { + err("missing space before left brace"); + } + if ($in_function && /^\s+{/ && + ($prev =~ /\)\s*$/ || $prev =~ /\bstruct\s+\w+$/)) { + err("left brace starting a line"); + } + if (/}(else|while)/) { + err("missing space after right brace"); + } + if (/}\s\s+(else|while)/) { + err("extra space after right brace"); + } + if (/\b_VOID\b|\bVOID\b|\bSTATIC\b/) { + err("obsolete use of VOID or STATIC"); + } + if (/\b$typename\*/o) { + err("missing space between type name and *"); + } + if (/^\s+#/) { + err("preprocessor statement not in column 1"); + } + if (/^#\s/) { + err("blank after preprocessor #"); + } + if (/!\s*(strcmp|strncmp|bcmp)\s*\(/) { + err("don't use boolean ! with comparison functions"); + } + + # + # We completely ignore, for purposes of indentation: + # * lines outside of functions + # * preprocessor lines + # + if ($check_continuation && $in_function && !$in_cpp) { + process_indent($_); + } + if ($picky) { + # try to detect spaces after casts, but allow (e.g.) + # "sizeof (int) + 1", "void (*funcptr)(int) = foo;", and + # "int foo(int) __NORETURN;" + if ((/^\($typename( \*+)?\)\s/o || + /\W\($typename( \*+)?\)\s/o) && + !/sizeof\s*\($typename( \*)?\)\s/o && + !/\($typename( \*+)?\)\s+=[^=]/o) { + err("space after cast"); + } + if (/\b$typename\s*\*\s/o && + !/\b$typename\s*\*\s+const\b/o) { + err("unary * followed by space"); + } + } + if ($check_posix_types) { + # try to detect old non-POSIX types. + # POSIX requires all non-standard typedefs to end in _t, + # but historically these have been used. + if (/\b(unchar|ushort|uint|ulong|u_int|u_short|u_long|u_char|quad)\b/) { + err("non-POSIX typedef $1 used: use $old2posix{$1} instead"); + } + } + if ($heuristic) { + # cannot check this everywhere due to "struct {\n...\n} foo;" + if ($in_function && !$in_declaration && + /}./ && !/}\s+=/ && !/{.*}[;,]$/ && !/}(\s|)*$/ && + !/} (else|while)/ && !/}}/) { + err("possible bad text following right brace"); + } + # cannot check this because sub-blocks in + # the middle of code are ok + if ($in_function && /^\s+{/) { + err("possible left brace starting a line"); + } + } + if (/^\s*else\W/) { + if ($prev =~ /^\s*}$/) { + err_prefix($prev, + "else and right brace should be on same line"); + } + } + $prev = $line; +} + +if ($prev eq "") { + err("last line in file is blank"); +} + +} + +# +# Continuation-line checking +# +# The rest of this file contains the code for the continuation checking +# engine. It's a pretty simple state machine which tracks the expression +# depth (unmatched '('s and '['s). +# +# Keep in mind that the argument to process_indent() has already been heavily +# processed; all comments have been replaced by control-A, and the contents of +# strings and character constants have been elided. +# + +my $cont_in; # currently inside of a continuation +my $cont_off; # skipping an initializer or definition +my $cont_noerr; # suppress cascading errors +my $cont_start; # the line being continued +my $cont_base; # the base indentation +my $cont_first; # this is the first line of a statement +my $cont_multiseg; # this continuation has multiple segments + +my $cont_special; # this is a C statement (if, for, etc.) +my $cont_macro; # this is a macro +my $cont_case; # this is a multi-line case + +my @cont_paren; # the stack of unmatched ( and [s we've seen + +sub +reset_indent() +{ + $cont_in = 0; + $cont_off = 0; +} + +sub +delabel($) +{ + # + # replace labels with tabs. Note that there may be multiple + # labels on a line. + # + local $_ = $_[0]; + + while (/^(\t*)( *(?:(?:\w+\s*)|(?:case\b[^:]*)): *)(.*)$/) { + my ($pre_tabs, $label, $rest) = ($1, $2, $3); + $_ = $pre_tabs; + while ($label =~ s/^([^\t]*)(\t+)//) { + $_ .= "\t" x (length($2) + length($1) / 8); + } + $_ .= ("\t" x (length($label) / 8)).$rest; + } + + return ($_); +} + +sub +process_indent($) +{ + require strict; + local $_ = $_[0]; # preserve the global $_ + + s///g; # No comments + s/\s+$//; # Strip trailing whitespace + + return if (/^$/); # skip empty lines + + # regexps used below; keywords taking (), macros, and continued cases + my $special = '(?:(?:\}\s*)?else\s+)?(?:if|for|while|switch)\b'; + my $macro = '[A-Z_][A-Z_0-9]*\('; + my $case = 'case\b[^:]*$'; + + # skip over enumerations, array definitions, initializers, etc. + if ($cont_off <= 0 && !/^\s*$special/ && + (/(?:(?:\b(?:enum|struct|union)\s*[^\{]*)|(?:\s+=\s*)){/ || + (/^\s*{/ && $prev =~ /=\s*(?:\/\*.*\*\/\s*)*$/))) { + $cont_in = 0; + $cont_off = tr/{/{/ - tr/}/}/; + return; + } + if ($cont_off) { + $cont_off += tr/{/{/ - tr/}/}/; + return; + } + + if (!$cont_in) { + $cont_start = $line; + + if (/^\t* /) { + err("non-continuation indented 4 spaces"); + $cont_noerr = 1; # stop reporting + } + $_ = delabel($_); # replace labels with tabs + + # check if the statement is complete + return if (/^\s*\}?$/); + return if (/^\s*\}?\s*else\s*\{?$/); + return if (/^\s*do\s*\{?$/); + return if (/{$/); + return if (/}[,;]?$/); + + # Allow macros on their own lines + return if (/^\s*[A-Z_][A-Z_0-9]*$/); + + # cases we don't deal with, generally non-kosher + if (/{/) { + err("stuff after {"); + return; + } + + # Get the base line, and set up the state machine + /^(\t*)/; + $cont_base = $1; + $cont_in = 1; + @cont_paren = (); + $cont_first = 1; + $cont_multiseg = 0; + + # certain things need special processing + $cont_special = /^\s*$special/? 1 : 0; + $cont_macro = /^\s*$macro/? 1 : 0; + $cont_case = /^\s*$case/? 1 : 0; + } else { + $cont_first = 0; + + # Strings may be pulled back to an earlier (half-)tabstop + unless ($cont_noerr || /^$cont_base / || + (/^\t*(?: )?(?:gettext\()?\"/ && !/^$cont_base\t/)) { + err_prefix($cont_start, + "continuation should be indented 4 spaces"); + } + } + + my $rest = $_; # keeps the remainder of the line + + # + # The split matches 0 characters, so that each 'special' character + # is processed separately. Parens and brackets are pushed and + # popped off the @cont_paren stack. For normal processing, we wait + # until a ; or { terminates the statement. "special" processing + # (if/for/while/switch) is allowed to stop when the stack empties, + # as is macro processing. Case statements are terminated with a : + # and an empty paren stack. + # + foreach $_ (split /[^\(\)\[\]\{\}\;\:]*/) { + next if (length($_) == 0); + + # rest contains the remainder of the line + my $rxp = "[^\Q$_\E]*\Q$_\E"; + $rest =~ s/^$rxp//; + + if (/\(/ || /\[/) { + push @cont_paren, $_; + } elsif (/\)/ || /\]/) { + my $cur = $_; + tr/\)\]/\(\[/; + + my $old = (pop @cont_paren); + if (!defined($old)) { + err("unexpected '$cur'"); + $cont_in = 0; + last; + } elsif ($old ne $_) { + err("'$cur' mismatched with '$old'"); + $cont_in = 0; + last; + } + + # + # If the stack is now empty, do special processing + # for if/for/while/switch and macro statements. + # + next if (@cont_paren != 0); + if ($cont_special) { + if ($rest =~ /^\s*{?$/) { + $cont_in = 0; + last; + } + if ($rest =~ /^\s*;$/) { + err("empty if/for/while body ". + "not on its own line"); + $cont_in = 0; + last; + } + if (!$cont_first && $cont_multiseg == 1) { + err_prefix($cont_start, + "multiple statements continued ". + "over multiple lines"); + $cont_multiseg = 2; + } elsif ($cont_multiseg == 0) { + $cont_multiseg = 1; + } + # We've finished this section, start + # processing the next. + goto section_ended; + } + if ($cont_macro) { + if ($rest =~ /^$/) { + $cont_in = 0; + last; + } + } + } elsif (/\;/) { + if ($cont_case) { + err("unexpected ;"); + } elsif (!$cont_special) { + err("unexpected ;") if (@cont_paren != 0); + if (!$cont_first && $cont_multiseg == 1) { + err_prefix($cont_start, + "multiple statements continued ". + "over multiple lines"); + $cont_multiseg = 2; + } elsif ($cont_multiseg == 0) { + $cont_multiseg = 1; + } + if ($rest =~ /^$/) { + $cont_in = 0; + last; + } + if ($rest =~ /^\s*special/) { + err("if/for/while/switch not started ". + "on its own line"); + } + goto section_ended; + } + } elsif (/\{/) { + err("{ while in parens/brackets") if (@cont_paren != 0); + err("stuff after {") if ($rest =~ /[^\s}]/); + $cont_in = 0; + last; + } elsif (/\}/) { + err("} while in parens/brackets") if (@cont_paren != 0); + if (!$cont_special && $rest !~ /^\s*(while|else)\b/) { + if ($rest =~ /^$/) { + err("unexpected }"); + } else { + err("stuff after }"); + } + $cont_in = 0; + last; + } + } elsif (/\:/ && $cont_case && @cont_paren == 0) { + err("stuff after multi-line case") if ($rest !~ /$^/); + $cont_in = 0; + last; + } + next; +section_ended: + # End of a statement or if/while/for loop. Reset + # cont_special and cont_macro based on the rest of the + # line. + $cont_special = ($rest =~ /^\s*$special/)? 1 : 0; + $cont_macro = ($rest =~ /^\s*$macro/)? 1 : 0; + $cont_case = 0; + next; + } + $cont_noerr = 0 if (!$cont_in); +}