diff options
Diffstat (limited to 'vppinfra')
163 files changed, 0 insertions, 55853 deletions
diff --git a/vppinfra/.gitignore b/vppinfra/.gitignore deleted file mode 100644 index b25c15b81fa..00000000000 --- a/vppinfra/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*~ diff --git a/vppinfra/INSTALL b/vppinfra/INSTALL deleted file mode 100644 index 23e5f25d0e5..00000000000 --- a/vppinfra/INSTALL +++ /dev/null @@ -1,236 +0,0 @@ -Installation Instructions -************************* - -Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005 Free -Software Foundation, Inc. - -This file is free documentation; the Free Software Foundation gives -unlimited permission to copy, distribute and modify it. - -Basic Installation -================== - -These are generic installation instructions. - - The `configure' shell script attempts to guess correct values for -various system-dependent variables used during compilation. It uses -those values to create a `Makefile' in each directory of the package. -It may also create one or more `.h' files containing system-dependent -definitions. Finally, it creates a shell script `config.status' that -you can run in the future to recreate the current configuration, and a -file `config.log' containing compiler output (useful mainly for -debugging `configure'). - - It can also use an optional file (typically called `config.cache' -and enabled with `--cache-file=config.cache' or simply `-C') that saves -the results of its tests to speed up reconfiguring. (Caching is -disabled by default to prevent problems with accidental use of stale -cache files.) - - If you need to do unusual things to compile the package, please try -to figure out how `configure' could check whether to do them, and mail -diffs or instructions to the address given in the `README' so they can -be considered for the next release. If you are using the cache, and at -some point `config.cache' contains results you don't want to keep, you -may remove or edit it. - - The file `configure.ac' (or `configure.in') is used to create -`configure' by a program called `autoconf'. You only need -`configure.ac' if you want to change it or regenerate `configure' using -a newer version of `autoconf'. - -The simplest way to compile this package is: - - 1. `cd' to the directory containing the package's source code and type - `./configure' to configure the package for your system. If you're - using `csh' on an old version of System V, you might need to type - `sh ./configure' instead to prevent `csh' from trying to execute - `configure' itself. - - Running `configure' takes awhile. While running, it prints some - messages telling which features it is checking for. - - 2. Type `make' to compile the package. - - 3. Optionally, type `make check' to run any self-tests that come with - the package. - - 4. Type `make install' to install the programs and any data files and - documentation. - - 5. You can remove the program binaries and object files from the - source code directory by typing `make clean'. To also remove the - files that `configure' created (so you can compile the package for - a different kind of computer), type `make distclean'. There is - also a `make maintainer-clean' target, but that is intended mainly - for the package's developers. If you use it, you may have to get - all sorts of other programs in order to regenerate files that came - with the distribution. - -Compilers and Options -===================== - -Some systems require unusual options for compilation or linking that the -`configure' script does not know about. Run `./configure --help' for -details on some of the pertinent environment variables. - - You can give `configure' initial values for configuration parameters -by setting variables in the command line or in the environment. Here -is an example: - - ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix - - *Note Defining Variables::, for more details. - -Compiling For Multiple Architectures -==================================== - -You can compile the package for more than one kind of computer at the -same time, by placing the object files for each architecture in their -own directory. To do this, you must use a version of `make' that -supports the `VPATH' variable, such as GNU `make'. `cd' to the -directory where you want the object files and executables to go and run -the `configure' script. `configure' automatically checks for the -source code in the directory that `configure' is in and in `..'. - - If you have to use a `make' that does not support the `VPATH' -variable, you have to compile the package for one architecture at a -time in the source code directory. After you have installed the -package for one architecture, use `make distclean' before reconfiguring -for another architecture. - -Installation Names -================== - -By default, `make install' installs the package's commands under -`/usr/local/bin', include files under `/usr/local/include', etc. You -can specify an installation prefix other than `/usr/local' by giving -`configure' the option `--prefix=PREFIX'. - - You can specify separate installation prefixes for -architecture-specific files and architecture-independent files. If you -pass the option `--exec-prefix=PREFIX' to `configure', the package uses -PREFIX as the prefix for installing programs and libraries. -Documentation and other data files still use the regular prefix. - - In addition, if you use an unusual directory layout you can give -options like `--bindir=DIR' to specify different values for particular -kinds of files. Run `configure --help' for a list of the directories -you can set and what kinds of files go in them. - - If the package supports it, you can cause programs to be installed -with an extra prefix or suffix on their names by giving `configure' the -option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. - -Optional Features -================= - -Some packages pay attention to `--enable-FEATURE' options to -`configure', where FEATURE indicates an optional part of the package. -They may also pay attention to `--with-PACKAGE' options, where PACKAGE -is something like `gnu-as' or `x' (for the X Window System). The -`README' should mention any `--enable-' and `--with-' options that the -package recognizes. - - For packages that use the X Window System, `configure' can usually -find the X include and library files automatically, but if it doesn't, -you can use the `configure' options `--x-includes=DIR' and -`--x-libraries=DIR' to specify their locations. - -Specifying the System Type -========================== - -There may be some features `configure' cannot figure out automatically, -but needs to determine by the type of machine the package will run on. -Usually, assuming the package is built to be run on the _same_ -architectures, `configure' can figure that out, but if it prints a -message saying it cannot guess the machine type, give it the -`--build=TYPE' option. TYPE can either be a short name for the system -type, such as `sun4', or a canonical name which has the form: - - CPU-COMPANY-SYSTEM - -where SYSTEM can have one of these forms: - - OS KERNEL-OS - - See the file `config.sub' for the possible values of each field. If -`config.sub' isn't included in this package, then this package doesn't -need to know the machine type. - - If you are _building_ compiler tools for cross-compiling, you should -use the option `--target=TYPE' to select the type of system they will -produce code for. - - If you want to _use_ a cross compiler, that generates code for a -platform different from the build platform, you should specify the -"host" platform (i.e., that on which the generated programs will -eventually be run) with `--host=TYPE'. - -Sharing Defaults -================ - -If you want to set default values for `configure' scripts to share, you -can create a site shell script called `config.site' that gives default -values for variables like `CC', `cache_file', and `prefix'. -`configure' looks for `PREFIX/share/config.site' if it exists, then -`PREFIX/etc/config.site' if it exists. Or, you can set the -`CONFIG_SITE' environment variable to the location of the site script. -A warning: not all `configure' scripts look for a site script. - -Defining Variables -================== - -Variables not defined in a site shell script can be set in the -environment passed to `configure'. However, some packages may run -configure again during the build, and the customized values of these -variables may be lost. In order to avoid this problem, you should set -them in the `configure' command line, using `VAR=value'. For example: - - ./configure CC=/usr/local2/bin/gcc - -causes the specified `gcc' to be used as the C compiler (unless it is -overridden in the site shell script). Here is a another example: - - /bin/bash ./configure CONFIG_SHELL=/bin/bash - -Here the `CONFIG_SHELL=/bin/bash' operand causes subsequent -configuration-related scripts to be executed by `/bin/bash'. - -`configure' Invocation -====================== - -`configure' recognizes the following options to control how it operates. - -`--help' -`-h' - Print a summary of the options to `configure', and exit. - -`--version' -`-V' - Print the version of Autoconf used to generate the `configure' - script, and exit. - -`--cache-file=FILE' - Enable the cache: use and save the results of the tests in FILE, - traditionally `config.cache'. FILE defaults to `/dev/null' to - disable caching. - -`--config-cache' -`-C' - Alias for `--cache-file=config.cache'. - -`--quiet' -`--silent' -`-q' - Do not print messages saying which checks are being made. To - suppress all normal output, redirect it to `/dev/null' (any error - messages will still be shown). - -`--srcdir=DIR' - Look for the package's source code in directory DIR. Usually - `configure' can determine that directory automatically. - -`configure' also accepts some other, not widely useful, options. Run -`configure --help' for more details. - diff --git a/vppinfra/Make.defs b/vppinfra/Make.defs deleted file mode 100644 index dcb51e16ab7..00000000000 --- a/vppinfra/Make.defs +++ /dev/null @@ -1,129 +0,0 @@ -# Copyright (c) 2001, 2002 Eliot Dresselhaus -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -# Basic toolchain defines. -CC = $(CROSS_COMPILE)gcc -LD = $(CROSS_COMPILE)ld -AR = $(CROSS_COMPILE)ar -RANLIB = $(CROSS_COMPILE)ranlib -INSTALL = install - -ifneq ($(origin CROSS_COMPILE), undefined) - IS_CROSS_COMPILE=yes -endif - -CLIB_ARCH = $(shell $(CC) -dumpmachine) - -# Where to get linux kernel includes. -# By default get linux includes from /usr/include/linux... -KERNEL_PREFIX ?= /usr - -# Where to find compiler include directory (since we may -# be using -nostdinc). -CC_PREFIX = $(shell dirname `$(CC) --print-libgcc-file-name`) - -# Where to get LIBC includes for cross compiles -LIBC_PREFIX ?= $(CC_PREFIX)/../../../../$(CLIB_ARCH) - -# Where to find CLIB includes/libraries for cross compiles -CLIB_PREFIX ?= /usr/local/$(CLIB_ARCH) - -OBJ = $(CLIB_ARCH).o -SHARED_OBJ = shared.$(OBJ) -KERNEL_OBJ = kernel.$(OBJ) -MODULE_OBJ = module.$(OBJ) - -DEP = $(CLIB_ARCH).d -SHARED_DEP = shared.$(DEP) -KERNEL_DEP = kernel.$(DEP) - -STATIC_LIB = $(CLIB_ARCH).a -SHARED_LIB = $(CLIB_ARCH).so -KERNEL_LIB = kernel.$(CLIB_ARCH).a - -STATIC_CFLAGS = $(DEFAULT_CFLAGS) -SHARED_CFLAGS = $(STATIC_CFLAGS) -fPIC - -# Compile flags common to user/kernel -CLIB_COMMON_CFLAGS += -Wall - -DEBUG ?= no -ifeq ($(DEBUG),yes) - COPTS ?= -g -O0 - CLIB_COMMON_CFLAGS += -DDEBUG -else - COPTS ?= -O2 -endif - -CLIB_COMMON_CFLAGS += $(COPTS) - -CLIB_USER_CFLAGS = $(CLIB_COMMON_CFLAGS) - -ifeq ($(IS_CROSS_COMPILE),yes) - CLIB_USER_CFLAGS += -nostdinc - CLIB_USER_CFLAGS += -idirafter $(CC_PREFIX)/include - CLIB_USER_CFLAGS += -idirafter $(KERNEL_PREFIX)/include - CLIB_USER_CFLAGS += -idirafter $(LIBC_PREFIX)/include - CLIB_COMMON_CFLAGS += -idirafter $(CLIB_PREFIX)/include -endif - -STATIC_CFLAGS = $(CLIB_USER_CFLAGS) -SHARED_CFLAGS = $(STATIC_CFLAGS) -fPIC - -%.$(SHARED_OBJ): %.c - $(CC) -c $(SHARED_CFLAGS) -o $@ $< - -%.$(OBJ): %.c - $(CC) -c $(STATIC_CFLAGS) -o $@ $< - -# Kernel version of clib - -CLIB_KERNEL_CFLAGS = $(CLIB_COMMON_CFLAGS) - -CLIB_KERNEL_CFLAGS += -nostdinc -CLIB_KERNEL_CFLAGS += -idirafter $(CC_PREFIX)/include -CLIB_KERNEL_CFLAGS += -idirafter $(KERNEL_PREFIX)/include - -# Kernel always uses mheap allocator (no malloc) -CLIB_KERNEL_CFLAGS += -DCLIB_MEM_MHEAP - -CLIB_KERNEL_CFLAGS += -D__KERNEL__ -DMODULE -DEXPORT_SYMTAB - -CLIB_KERNEL_CFLAGS += -fno-common -fomit-frame-pointer -fno-strict-aliasing - -ifeq ($(findstring mips,$(CLIB_ARCH)),mips) - CLIB_KERNEL_CFLAGS += -G0 \ - -mno-abicalls -fno-pic -mlong-calls \ - -mcpu=r8000 -mips2 -Wa,--trap -endif - -%.$(KERNEL_OBJ): %.c - $(CC) $(CLIB_KERNEL_CFLAGS) -c -o $@ $< - -# Dependencies -%.$(DEP): %.c - $(CC) $(CLIB_USER_CFLAGS) -c -M $< | sed -e s/.o:/.$(OBJ):/ > $@ - -%.$(SHARED_DEP): %.c - $(CC) $(CLIB_USER_CFLAGS) -c -M $< | sed -e s/.o:/.$(SHARED_OBJ):/ > $@ - -%.$(KERNEL_DEP): %.c - $(CC) $(CLIB_KERNEL_CFLAGS) -c -M $< | sed -e s/.o:/.$(KERNEL_OBJ):/ > $@ diff --git a/vppinfra/Makefile.am b/vppinfra/Makefile.am deleted file mode 100644 index 6183cd7a74e..00000000000 --- a/vppinfra/Makefile.am +++ /dev/null @@ -1,275 +0,0 @@ -# Copyright (c) 2015 Cisco and/or its affiliates. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -AUTOMAKE_OPTIONS = foreign subdir-objects - -AM_CPPFLAGS = -Wall -Werror - -if WITH_UNIX - lib_LTLIBRARIES = libvppinfra.la -endif - -lib_LIBRARIES = - -TESTS = - -if ENABLE_TESTS -TESTS += test_bihash_template \ - test_dlist \ - test_elog \ - test_elf \ - test_fifo \ - test_format \ - test_hash \ - test_heap \ - test_longjmp \ - test_macros \ - test_md5 \ - test_mheap \ - test_pool_iterate \ - test_ptclosure \ - test_random \ - test_random_isaac \ - test_serialize \ - test_slist \ - test_socket \ - test_time \ - test_timing_wheel \ - test_vec \ - test_zvec -endif - -noinst_PROGRAMS = $(TESTS) -check_PROGRAMS = $(TESTS) - -test_bihash_template_SOURCES = vppinfra/test_bihash_template.c -test_dlist_SOURCES = vppinfra/test_dlist.c -test_elog_SOURCES = vppinfra/test_elog.c -test_elf_SOURCES = vppinfra/test_elf.c -test_fifo_SOURCES = vppinfra/test_fifo.c -test_format_SOURCES = vppinfra/test_format.c -test_hash_SOURCES = vppinfra/test_hash.c -test_heap_SOURCES = vppinfra/test_heap.c -test_longjmp_SOURCES = vppinfra/test_longjmp.c -test_macros_SOURCES = vppinfra/test_macros.c -test_md5_SOURCES = vppinfra/test_md5.c -test_mheap_SOURCES = vppinfra/test_mheap.c -test_pool_iterate_SOURCES = vppinfra/test_pool_iterate.c -test_ptclosure_SOURCES = vppinfra/test_ptclosure.c -test_random_SOURCES = vppinfra/test_random.c -test_random_isaac_SOURCES = vppinfra/test_random_isaac.c -test_serialize_SOURCES = vppinfra/test_serialize.c -test_slist_SOURCES = vppinfra/test_slist.c -test_socket_SOURCES = vppinfra/test_socket.c -test_time_SOURCES = vppinfra/test_time.c -test_timing_wheel_SOURCES = vppinfra/test_timing_wheel.c -test_vec_SOURCES = vppinfra/test_vec.c -test_zvec_SOURCES = vppinfra/test_zvec.c - -# All unit tests use ASSERT for failure -# So we'll need -DDEBUG to enable ASSERTs -test_bihash_template_CPPFLAGS = $(AM_CPPFLAGS) -DCLIB_DEBUG -test_dlist_CPPFLAGS = $(AM_CPPFLAGS) -DCLIB_DEBUG -test_elog_CPPFLAGS = $(AM_CPPFLAGS) -DCLIB_DEBUG -test_elf_CPPFLAGS = $(AM_CPPFLAGS) -DCLIB_DEBUG -test_fifo_CPPFLAGS = $(AM_CPPFLAGS) -DCLIB_DEBUG -test_format_CPPFLAGS = $(AM_CPPFLAGS) -DCLIB_DEBUG -test_hash_CPPFLAGS = $(AM_CPPFLAGS) -DCLIB_DEBUG -test_heap_CPPFLAGS = $(AM_CPPFLAGS) -DCLIB_DEBUG -test_longjmp_CPPFLAGS = $(AM_CPPFLAGS) -DCLIB_DEBUG -test_macros_CPPFLAGS = $(AM_CPPFLAGS) -DCLIB_DEBUG -test_md5_CPPFLAGS = $(AM_CPPFLAGS) -DCLIB_DEBUG -test_mheap_CPPFLAGS = $(AM_CPPFLAGS) -DCLIB_DEBUG -test_pool_iterate_CPPFLAGS = $(AM_CPPFLAGS) -DCLIB_DEBUG -test_ptclosure_CPPFLAGS = $(AM_CPPFLAGS) -DCLIB_DEBUG -test_random_CPPFLAGS = $(AM_CPPFLAGS) -DCLIB_DEBUG -test_random_isaac_CPPFLAGS = $(AM_CPPFLAGS) -DCLIB_DEBUG -test_socket_CPPFLAGS = $(AM_CPPFLAGS) -DCLIB_DEBUG -test_serialize_CPPFLAGS = $(AM_CPPFLAGS) -DCLIB_DEBUG -test_slist_CPPFLAGS = $(AM_CPPFLAGS) -DCLIB_DEBUG -test_time_CPPFLAGS = $(AM_CPPFLAGS) -DCLIB_DEBUG -test_timing_wheel_CPPFLAGS = $(AM_CPPFLAGS) -DCLIB_DEBUG -test_vec_CPPFLAGS = $(AM_CPPFLAGS) -DCLIB_DEBUG -test_zvec_CPPFLAGS = $(AM_CPPFLAGS) -DCLIB_DEBUG - -test_bihash_template_LDADD = libvppinfra.la -test_dlist_LDADD = libvppinfra.la -test_elog_LDADD = libvppinfra.la -test_elf_LDADD = libvppinfra.la -test_fifo_LDADD = libvppinfra.la -test_format_LDADD = libvppinfra.la -test_hash_LDADD = libvppinfra.la -test_heap_LDADD = libvppinfra.la -test_longjmp_LDADD = libvppinfra.la -test_macros_LDADD = libvppinfra.la -test_md5_LDADD = libvppinfra.la -test_mheap_LDADD = libvppinfra.la -test_pool_iterate_LDADD = libvppinfra.la -test_ptclosure_LDADD = libvppinfra.la -test_random_LDADD = libvppinfra.la -test_random_isaac_LDADD = libvppinfra.la -test_serialize_LDADD = libvppinfra.la -test_slist_LDADD = libvppinfra.la -test_socket_LDADD = libvppinfra.la -test_time_LDADD = libvppinfra.la -lm -test_timing_wheel_LDADD = libvppinfra.la -lm -test_vec_LDADD = libvppinfra.la -test_zvec_LDADD = libvppinfra.la - -test_bihash_template_LDFLAGS = -static -test_dlist_LDFLAGS = -static -test_elog_LDFLAGS = -static -test_elf_LDFLAGS = -static -test_fifo_LDFLAGS = -static -test_format_LDFLAGS = -static -test_hash_LDFLAGS = -static -test_heap_LDFLAGS = -static -test_longjmp_LDFLAGS = -static -test_macros_LDFLAGS = -static -test_md5_LDFLAGS = -static -test_mheap_LDFLAGS = -static -test_pool_iterate_LDFLAGS = -static -test_ptclosure_LDFLAGS = -static -test_random_LDFLAGS = -static -test_random_isaac_LDFLAGS = -static -test_serialize_LDFLAGS = -static -test_slist_LDFLAGS = -static -test_socket_LDFLAGS = -static -test_time_LDFLAGS = -static -test_timing_wheel_LDFLAGS = -static -test_vec_LDFLAGS = -static -test_zvec_LDFLAGS = -static - -# noinst_PROGRAMS += test_vhash -# test_vhash_SOURCES = vppinfra/test_vhash.c vppinfra/vhash.c -# test_vhash_CPPFLAGS = $(AM_CPPFLAGS) -DCLIB_DEBUG -# test_vhash_LDADD = libvppinfra.la -# test_vhash_LDFLAGS = -static - -nobase_include_HEADERS = \ - vppinfra/asm_mips.h \ - vppinfra/asm_x86.h \ - vppinfra/bihash_8_8.h \ - vppinfra/bihash_24_8.h \ - vppinfra/bihash_template.h \ - vppinfra/bihash_template.c \ - vppinfra/bitmap.h \ - vppinfra/bitops.h \ - vppinfra/byte_order.h \ - vppinfra/cache.h \ - vppinfra/clib.h \ - vppinfra/cpu.h \ - vppinfra/dlist.h \ - vppinfra/elf.h \ - vppinfra/elf_clib.h \ - vppinfra/elog.h \ - vppinfra/fheap.h \ - vppinfra/error.h \ - vppinfra/error_bootstrap.h \ - vppinfra/fifo.h \ - vppinfra/format.h \ - vppinfra/graph.h \ - vppinfra/hash.h \ - vppinfra/heap.h \ - vppinfra/longjmp.h \ - vppinfra/macros.h \ - vppinfra/math.h \ - vppinfra/md5.h \ - vppinfra/mem.h \ - vppinfra/memcpy_sse3.h \ - vppinfra/memcpy_avx.h \ - vppinfra/mhash.h \ - vppinfra/mheap.h \ - vppinfra/mheap_bootstrap.h \ - vppinfra/os.h \ - vppinfra/pipeline.h \ - vppinfra/pool.h \ - vppinfra/ptclosure.h \ - vppinfra/random.h \ - vppinfra/random_buffer.h \ - vppinfra/random_isaac.h \ - vppinfra/serialize.h \ - vppinfra/slist.h \ - vppinfra/smp.h \ - vppinfra/socket.h \ - vppinfra/sparse_vec.h \ - vppinfra/string.h \ - vppinfra/time.h \ - vppinfra/timing_wheel.h \ - vppinfra/timer.h \ - vppinfra/types.h \ - vppinfra/unix.h \ - vppinfra/vec.h \ - vppinfra/vec_bootstrap.h \ - vppinfra/vector.h \ - vppinfra/vector_altivec.h \ - vppinfra/vector_funcs.h \ - vppinfra/vector_iwmmxt.h \ - vppinfra/vector_neon.h \ - vppinfra/vector_sse2.h \ - vppinfra/valgrind.h \ - vppinfra/vm_unix.h \ - vppinfra/xxhash.h \ - vppinfra/xy.h \ - vppinfra/zvec.h - -CLIB_CORE = \ - vppinfra/asm_x86.c \ - vppinfra/backtrace.c \ - vppinfra/bihash_8_8.h \ - vppinfra/bihash_24_8.h \ - vppinfra/bihash_template.h \ - vppinfra/cpu.c \ - vppinfra/elf.c \ - vppinfra/elog.c \ - vppinfra/error.c \ - vppinfra/fifo.c \ - vppinfra/fheap.c \ - vppinfra/format.c \ - vppinfra/graph.c \ - vppinfra/hash.c \ - vppinfra/heap.c \ - vppinfra/longjmp.S \ - vppinfra/macros.c \ - vppinfra/mhash.c \ - vppinfra/mheap.c \ - vppinfra/md5.c \ - vppinfra/mem_mheap.c \ - vppinfra/ptclosure.c \ - vppinfra/random.c \ - vppinfra/random_buffer.c \ - vppinfra/random_isaac.c \ - vppinfra/serialize.c \ - vppinfra/slist.c \ - vppinfra/std-formats.c \ - vppinfra/string.c \ - vppinfra/time.c \ - vppinfra/timing_wheel.c \ - vppinfra/unformat.c \ - vppinfra/vec.c \ - vppinfra/vector.c \ - vppinfra/zvec.c - -# Core plus Unix additions -libvppinfra_la_SOURCES = \ - $(CLIB_CORE) \ - vppinfra/elf_clib.c \ - vppinfra/socket.c \ - vppinfra/timer.c \ - vppinfra/unix-formats.c \ - vppinfra/unix-misc.c - -bin_PROGRAMS = elftool - -elftool_SOURCES = tools/elftool.c -elftool_CPPFLAGS = $(AM_CPPFLAGS) -elftool_LDADD = libvppinfra.la -lpthread -lrt -lm diff --git a/vppinfra/README b/vppinfra/README deleted file mode 100644 index 579696b6e05..00000000000 --- a/vppinfra/README +++ /dev/null @@ -1,43 +0,0 @@ -Welcome to vppinfra a programming library of basic data structures. - -vec.c dynamic vectors -bitmap.h dynamic bitmaps -heap.c allocation heap of objects (sub-objects have variable size) -pool.h allocation pool (like heap with size always 1) -hash.c dynamic hash tables -mheap.c memory allocator (a la dlmalloc) - -format.c extendable printf-like thing built on top of vectors -std-formats.c formats for unix data structures, networking stuff, ... -timer.c arrange for functions to be called at given times. - - -Build, Test, Install, Use... ----------------------------- - If this package came from the distribution tar ball, skip to the - Build Section. If this was a gentoo ebuild, after emerge/ebuild, - skip to the Use Section; otherwise, start with Pre-Build. - -Pre-Build ------------ - 1) svn checkout svn://teaktechnologies.com/fn/trunk/clib clib - 2) autoreconf [-v][-f][-i] # regenerate configuration files - -Build ------ - 1) cd BUILD # which may be different than this SRC dir - 2) ${SRC}/configure [--host=CHOST] - 3) make - -Test ----- - If not cross-compiling (i.e. CBUILD == CHOST), use "make check" to - run the validation programs. - -Install -------- - With the root effective user ID (i.e. su or sudo), run "make install". - -Use ---- - We need to reference man pages and theory of operation. diff --git a/vppinfra/configure.ac b/vppinfra/configure.ac deleted file mode 100644 index 88939383057..00000000000 --- a/vppinfra/configure.ac +++ /dev/null @@ -1,52 +0,0 @@ -# Process this file with autoconf to produce a configure script. -AC_INIT(libvppinfra,1.0,) -AC_CONFIG_AUX_DIR(config) -AC_CONFIG_HEADERS(config/config.h) -AC_CANONICAL_BUILD -AC_CANONICAL_HOST -AM_INIT_AUTOMAKE([gnu no-dist-gzip dist-bzip2]) -AM_SILENT_RULES([yes]) - -# Checks for programs. -AC_PROG_CC -AM_PROG_AS -AM_PROG_LIBTOOL - -###################################################################### - -dnl ------------ -dnl Check CFLAGS, CC -dnl ------------ -AC_ARG_WITH(cc, - AC_HELP_STRING([--with-cc],[Set CC for use as C compiler.]), - [CC="$with_cc"]) - -AC_ARG_WITH(cflags, - AC_HELP_STRING([--with-cflags],[Set CFLAGS for use by C compiler.]), - [CFLAGS="$with_cflags"]) - -AC_ARG_WITH(ldflags, - AC_HELP_STRING([--with-ldflags],[Set LDFLAGS for linking.]), - [LDFLAGS="$with_ldflags"]) - -###################################################################### - -AC_ARG_ENABLE(tests, - AC_HELP_STRING([--enable-tests],[Enable unit tests]), - [enable_tests=1], - [enable_tests=0]) - -AM_CONDITIONAL(ENABLE_TESTS, test "$enable_tests" = "1") - -AC_ARG_WITH(unix, - AC_HELP_STRING([--with-unix],[Compile unix version of clib]), - [], - [case $host_os in - darwin* | linux*) with_unix=yes;; - *) with_unix=no;; - esac]) - -AM_CONDITIONAL(WITH_UNIX, test "$with_unix" = "yes") - -AC_CONFIG_FILES([Makefile]) -AC_OUTPUT diff --git a/vppinfra/dir.dox b/vppinfra/dir.dox deleted file mode 100644 index dee0cd9cd43..00000000000 --- a/vppinfra/dir.dox +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * Copyright (c) 2016 Comcast Cable Communications Management, LLC. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/** @dir - * @brief VPP infrastructure library and tools. - */ diff --git a/vppinfra/mkinstalldirs b/vppinfra/mkinstalldirs deleted file mode 100755 index d2d5f21b611..00000000000 --- a/vppinfra/mkinstalldirs +++ /dev/null @@ -1,111 +0,0 @@ -#! /bin/sh -# mkinstalldirs --- make directory hierarchy -# Author: Noah Friedman <friedman@prep.ai.mit.edu> -# Created: 1993-05-16 -# Public domain - -errstatus=0 -dirmode="" - -usage="\ -Usage: mkinstalldirs [-h] [--help] [-m mode] dir ..." - -# process command line arguments -while test $# -gt 0 ; do - case $1 in - -h | --help | --h*) # -h for help - echo "$usage" 1>&2 - exit 0 - ;; - -m) # -m PERM arg - shift - test $# -eq 0 && { echo "$usage" 1>&2; exit 1; } - dirmode=$1 - shift - ;; - --) # stop option processing - shift - break - ;; - -*) # unknown option - echo "$usage" 1>&2 - exit 1 - ;; - *) # first non-opt arg - break - ;; - esac -done - -for file -do - if test -d "$file"; then - shift - else - break - fi -done - -case $# in - 0) exit 0 ;; -esac - -case $dirmode in - '') - if mkdir -p -- . 2>/dev/null; then - echo "mkdir -p -- $*" - exec mkdir -p -- "$@" - fi - ;; - *) - if mkdir -m "$dirmode" -p -- . 2>/dev/null; then - echo "mkdir -m $dirmode -p -- $*" - exec mkdir -m "$dirmode" -p -- "$@" - fi - ;; -esac - -for file -do - set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` - shift - - pathcomp= - for d - do - pathcomp="$pathcomp$d" - case $pathcomp in - -*) pathcomp=./$pathcomp ;; - esac - - if test ! -d "$pathcomp"; then - echo "mkdir $pathcomp" - - mkdir "$pathcomp" || lasterr=$? - - if test ! -d "$pathcomp"; then - errstatus=$lasterr - else - if test ! -z "$dirmode"; then - echo "chmod $dirmode $pathcomp" - lasterr="" - chmod "$dirmode" "$pathcomp" || lasterr=$? - - if test ! -z "$lasterr"; then - errstatus=$lasterr - fi - fi - fi - fi - - pathcomp="$pathcomp/" - done -done - -exit $errstatus - -# Local Variables: -# mode: shell-script -# sh-indentation: 2 -# End: -# mkinstalldirs ends here diff --git a/vppinfra/tools/dir.dox b/vppinfra/tools/dir.dox deleted file mode 100644 index 40426e04df7..00000000000 --- a/vppinfra/tools/dir.dox +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * Copyright (c) 2016 Comcast Cable Communications Management, LLC. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/** @dir - * @brief VPP instrastructure tools. - */ diff --git a/vppinfra/tools/elftool.c b/vppinfra/tools/elftool.c deleted file mode 100644 index d9d3704b4a3..00000000000 --- a/vppinfra/tools/elftool.c +++ /dev/null @@ -1,464 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2008 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include <vppinfra/elf.h> - -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> - -#ifndef CLIB_UNIX -#error "unix only" -#endif - -typedef struct { - elf_main_t elf_main; - char * input_file; - char * output_file; - char * set_interpreter; - char * set_rpath; - int unset_rpath; - int verbose; - int quiet; - int allow_elf_shared; - /* for use in the optimized / simplified case */ - u64 file_size; - u64 interpreter_offset; - u64 rpath_offset; -} elf_tool_main_t; - -static clib_error_t * elf_set_interpreter (elf_main_t * em, - elf_tool_main_t * tm) -{ - elf_segment_t * g; - elf_section_t * s; - clib_error_t * error; - char * interp = tm->set_interpreter; - - switch (em->first_header.file_type) - { - case ELF_EXEC: - break; - - case ELF_SHARED: - if (tm->allow_elf_shared) - break; - /* Note flowthrough */ - default: - return clib_error_return (0, "unacceptable file_type"); - } - - vec_foreach (g, em->segments) - { - if (g->header.type == ELF_SEGMENT_INTERP) - break; - } - - if (g >= vec_end (em->segments)) - return clib_error_return (0, "interpreter not found"); - - if (g->header.memory_size < 1 + strlen (interp)) - return clib_error_return (0, "given interpreter does not fit; must be less than %d bytes (`%s' given)", - g->header.memory_size, interp); - - error = elf_get_section_by_start_address (em, g->header.virtual_address, &s); - if (error) - return error; - - /* Put in new null terminated string. */ - memset (s->contents, 0, vec_len (s->contents)); - clib_memcpy (s->contents, interp, strlen (interp)); - - return 0; -} - -static void -delete_rpath_for_section (elf_main_t * em, elf_section_t * s) -{ - elf64_dynamic_entry_t * e; - elf64_dynamic_entry_t * new_es = 0; - - vec_foreach (e, em->dynamic_entries) - { - switch (e->type) - { - case ELF_DYNAMIC_ENTRY_RPATH: - case ELF_DYNAMIC_ENTRY_RUN_PATH: - break; - - default: - vec_add1 (new_es, e[0]); - break; - } - } - - /* Pad so as to keep section size constant. */ - { - elf64_dynamic_entry_t e_end; - e_end.type = ELF_DYNAMIC_ENTRY_END; - e_end.data = 0; - while (vec_len (new_es) < vec_len (em->dynamic_entries)) - vec_add1 (new_es, e_end); - } - - vec_free (em->dynamic_entries); - em->dynamic_entries = new_es; - - elf_set_dynamic_entries (em); -} - -static void delete_rpath (elf_main_t * em) -{ - elf_section_t * s; - - vec_foreach (s, em->sections) - { - switch (s->header.type) - { - case ELF_SECTION_DYNAMIC: - delete_rpath_for_section (em, s); - break; - - default: - break; - } - } -} - -static clib_error_t * -set_rpath_for_section (elf_main_t * em, elf_section_t * s, char * new_rpath) -{ - elf64_dynamic_entry_t * e; - char * old_rpath; - int old_len, new_len = strlen (new_rpath); - u8 * new_string_table = vec_dup (em->dynamic_string_table); - - vec_foreach (e, em->dynamic_entries) - { - switch (e->type) - { - case ELF_DYNAMIC_ENTRY_RPATH: - case ELF_DYNAMIC_ENTRY_RUN_PATH: - old_rpath = (char *) new_string_table + e->data; - old_len = strlen (old_rpath); - if (old_len < new_len) - return clib_error_return (0, "rpath of `%s' does not fit (old rpath `%s')", - new_rpath, old_rpath); - strcpy (old_rpath, new_rpath); - break; - - default: - break; - } - } - - elf_set_section_contents (em, em->dynamic_string_table_section_index, - new_string_table, - vec_bytes (new_string_table)); - - return 0; -} - -static clib_error_t * -set_rpath (elf_main_t * em, char * rpath) -{ - clib_error_t * error = 0; - elf_section_t * s; - - vec_foreach (s, em->sections) - { - switch (s->header.type) - { - case ELF_SECTION_DYNAMIC: - error = set_rpath_for_section (em, s, rpath); - if (error) - return error; - break; - - default: - break; - } - } - - return error; -} - -static clib_error_t * -set_interpreter_rpath (elf_tool_main_t * tm) -{ - int ifd = -1, ofd = -1; - struct stat fd_stat; - u8 *idp = 0; /* warning be gone */ - u64 mmap_length = 0, i; - u32 run_length; - u8 in_run; - u64 offset0 = 0, offset1 = 0; - clib_error_t * error = 0; - int fix_in_place = 0; - - if (!strcmp (tm->input_file, tm->output_file)) - fix_in_place = 1; - - ifd = open (tm->input_file, O_RDWR); - if (ifd < 0) - { - error = clib_error_return_unix (0, "open `%s'", tm->input_file); - goto done; - } - - if (fstat (ifd, &fd_stat) < 0) - { - error = clib_error_return_unix (0, "fstat `%s'", tm->input_file); - goto done; - } - - if (!(fd_stat.st_mode & S_IFREG)) - { - error = clib_error_return (0, "%s is not a regular file", tm->input_file); - goto done; - } - - mmap_length = fd_stat.st_size; - if (mmap_length < 4) - { - error = clib_error_return (0, "%s too short", tm->input_file); - goto done; - } - - /* COW-mapping, since we intend to write the fixups */ - if (fix_in_place) - idp = mmap (0, mmap_length, PROT_READ | PROT_WRITE, MAP_SHARED, - ifd, /* offset */ 0); - else - idp = mmap (0, mmap_length, PROT_READ | PROT_WRITE, MAP_PRIVATE, - ifd, /* offset */ 0); - if (~pointer_to_uword (idp) == 0) - { - mmap_length = 0; - error = clib_error_return_unix (0, "mmap `%s'", tm->input_file); - goto done; - } - - if (idp[0] != 0x7f || idp[1] != 'E' || idp[2] != 'L' || idp[3] != 'F') - { - error = clib_error_return (0, "not an ELF file '%s'", tm->input_file); - goto done; - } - - in_run = 0; - run_length = 0; - - for (i = 0; i < mmap_length; i++) - { - if (idp[i] == '/') - { - if (in_run) - run_length++; - else - { - in_run = 1; - run_length = 1; - } - } - else - { - if (in_run && run_length >= 16) - { - if (offset0 == 0) - offset0 = (i - run_length); - else if (offset1 == 0) - { - offset1 = (i - run_length); - goto found_both; - } - } - in_run = 0; - run_length = 0; - } - } - - if (offset0 == 0) - { - error = clib_error_return (0, "no fixup markers in %s", - tm->input_file); - goto done; - } - - found_both: - if (0) - clib_warning ("offset0 %lld (0x%llx), offset1 %lld (0x%llx)", - offset0, offset0, offset1, offset1); - - /* Executable file case */ - if (offset0 && offset1) - { - tm->interpreter_offset = offset0; - tm->rpath_offset = offset1; - } - else /* shared library case */ - { - tm->interpreter_offset = 0; - tm->rpath_offset = offset0; - } - - if (tm->interpreter_offset) - clib_memcpy (&idp[tm->interpreter_offset], tm->set_interpreter, - strlen (tm->set_interpreter)+1); - - if (tm->rpath_offset) - clib_memcpy (&idp[tm->rpath_offset], tm->set_rpath, - strlen (tm->set_rpath)+1); - - /* Write the output file... */ - if (fix_in_place == 0) - { - ofd = open (tm->output_file, O_RDWR | O_CREAT | O_TRUNC, 0644); - if (ofd < 0) - { - error = clib_error_return_unix (0, "create `%s'", tm->output_file); - goto done; - } - - if (write (ofd, idp, mmap_length) != mmap_length) - error = clib_error_return_unix (0, "write `%s'", tm->output_file); - } - - done: - if (mmap_length > 0 && idp) - munmap (idp, mmap_length); - if (ifd >= 0) - close (ifd); - if (ofd >= 0) - close (ofd); - return error; -} - - -int main (int argc, char * argv[]) -{ - elf_tool_main_t _tm, * tm = &_tm; - elf_main_t * em = &tm->elf_main; - unformat_input_t i; - clib_error_t * error = 0; - - memset (tm, 0, sizeof (tm[0])); - unformat_init_command_line (&i, argv); - - while (unformat_check_input (&i) != UNFORMAT_END_OF_INPUT) - { - if (unformat (&i, "in %s", &tm->input_file)) - ; - else if (unformat (&i, "out %s", &tm->output_file)) - ; - else if (unformat (&i, "set-interpreter %s", &tm->set_interpreter)) - ; - else if (unformat (&i, "set-rpath %s", &tm->set_rpath)) - ; - else if (unformat (&i, "unset-rpath")) - tm->unset_rpath = 1; - else if (unformat (&i, "verbose")) - tm->verbose = ~0; - else if (unformat (&i, "verbose-symbols")) - tm->verbose |= FORMAT_ELF_MAIN_SYMBOLS; - else if (unformat (&i, "verbose-relocations")) - tm->verbose |= FORMAT_ELF_MAIN_RELOCATIONS; - else if (unformat (&i, "verbose-dynamic")) - tm->verbose |= FORMAT_ELF_MAIN_DYNAMIC; - else if (unformat (&i, "quiet")) - tm->quiet = 1; - else if (unformat (&i, "allow-elf-shared")) - tm->allow_elf_shared = 1; - else - { - error = unformat_parse_error (&i); - goto done; - } - } - - if (! tm->input_file) - { - error = clib_error_return (0, "no input file"); - goto done; - } - - /* Do the typical case a stone-simple way... */ - if (tm->quiet && tm->set_interpreter && tm->set_rpath && tm->output_file) - { - error = set_interpreter_rpath (tm); - goto done; - } - - error = elf_read_file (em, tm->input_file); - - if (error) - goto done; - - if (tm->verbose) - fformat (stdout, "%U", format_elf_main, em, tm->verbose); - - if (tm->set_interpreter) - { - error = elf_set_interpreter (em, tm); - if (error) - goto done; - } - - if (tm->set_rpath) - { - error = set_rpath (em, tm->set_rpath); - if (error) - goto done; - } - - if (tm->unset_rpath) - delete_rpath (em); - - if (tm->output_file) - error = elf_write_file (em, tm->output_file); - - elf_main_free (em); - - done: - if (error) - { - if (tm->quiet == 0) - clib_error_report (error); - return 1; - } - else - return 0; -} diff --git a/vppinfra/unix_error.def b/vppinfra/unix_error.def deleted file mode 100644 index 76633dbb4b1..00000000000 --- a/vppinfra/unix_error.def +++ /dev/null @@ -1,145 +0,0 @@ -/* - Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -_ (EPERM, "Operation not permitted") -_ (ENOENT, "No such file or directory") -_ (ESRCH, "No such process") -_ (EINTR, "Interrupted system call") -_ (EIO, "I/O error") -_ (ENXIO, "No such device or address") -_ (E2BIG, "Arg list too long") -_ (ENOEXEC, "Exec format error") -_ (EBADF, "Bad file number") -_ (ECHILD, "No child processes") -_ (ENOMEM, "Out of memory") -_ (EACCES, "Permission denied") -_ (EFAULT, "Bad address") -_ (ENOTBLK, "Block device required") -_ (EBUSY, "Device or resource busy") -_ (EEXIST, "File exists") -_ (EXDEV, "Cross-device link") -_ (ENODEV, "No such device") -_ (ENOTDIR, "Not a directory") -_ (EISDIR, "Is a directory") -_ (EINVAL, "Invalid argument") -_ (ENFILE, "File table overflow") -_ (EMFILE, "Too many open files") -_ (ENOTTY, "Not a typewriter") -_ (ETXTBSY, "Text file busy") -_ (EFBIG, "File too large") -_ (ENOSPC, "No space left on device") -_ (ESPIPE, "Illegal seek") -_ (EROFS, "Read-only file system") -_ (EMLINK, "Too many links") -_ (EPIPE, "Broken pipe") -_ (EDOM, "Math argument out of domain of func") -_ (ERANGE, "Math result not representable") -_ (EDEADLK, "Resource deadlock would occur") -_ (ENAMETOOLONG, "File name too long") -_ (ENOLCK, "No record locks available") -_ (ENOSYS, "Function not implemented") -_ (ENOTEMPTY, "Directory not empty") -_ (ELOOP, "Too many symbolic links encountered") -_ (EWOULDBLOCK, "Operation would block") -_ (ENOMSG, "No message of desired type") -_ (EIDRM, "Identifier removed") -_ (ECHRNG, "Channel number out of range") -_ (EL2NSYNC, "Level 2 not synchronized") -_ (EL3HLT, "Level 3 halted") -_ (EL3RST, "Level 3 reset") -_ (ELNRNG, "Link number out of range") -_ (EUNATCH, "Protocol driver not attached") -_ (ENOCSI, "No CSI structure available") -_ (EL2HLT, "Level 2 halted") -_ (EBADE, "Invalid exchange") -_ (EBADR, "Invalid request descriptor") -_ (EXFULL, "Exchange full") -_ (ENOANO, "No anode") -_ (EBADRQC, "Invalid request code") -_ (EBADSLT, "Invalid slot") -_ (EBFONT, "Bad font file format") -_ (ENOSTR, "Device not a stream") -_ (ENODATA, "No data available") -_ (ETIME, "Timer expired") -_ (ENOSR, "Out of streams resources") -_ (ENONET, "Machine is not on the network") -_ (ENOPKG, "Package not installed") -_ (EREMOTE, "Object is remote") -_ (ENOLINK, "Link has been severed") -_ (EADV, "Advertise error") -_ (ESRMNT, "Srmount error") -_ (ECOMM, "Communication error on send") -_ (EPROTO, "Protocol error") -_ (EMULTIHOP, "Multihop attempted") -_ (EDOTDOT, "RFS specific error") -_ (EBADMSG, "Not a data message") -_ (EOVERFLOW, "Value too large for defined data type") -_ (ENOTUNIQ, "Name not unique on network") -_ (EBADFD, "File descriptor in bad state") -_ (EREMCHG, "Remote address changed") -_ (ELIBACC, "Can not access a needed shared library") -_ (ELIBBAD, "Accessing a corrupted shared library") -_ (ELIBSCN, "lib section in a.out corrupted") -_ (ELIBMAX, "Attempting to link in too many shared libraries") -_ (ELIBEXEC, "Cannot exec a shared library directly") -_ (EILSEQ, "Illegal byte sequence") -_ (ERESTART, "Interrupted system call should be restarted") -_ (ESTRPIPE, "Streams pipe error") -_ (EUSERS, "Too many users") -_ (ENOTSOCK, "Socket operation on non-socket") -_ (EDESTADDRREQ, "Destination address required") -_ (EMSGSIZE, "Message too long") -_ (EPROTOTYPE, "Protocol wrong type for socket") -_ (ENOPROTOOPT, "Protocol not available") -_ (EPROTONOSUPPORT, "Protocol not supported") -_ (ESOCKTNOSUPPORT, "Socket type not supported") -_ (EOPNOTSUPP, "Operation not supported on transport endpoint") -_ (EPFNOSUPPORT, "Protocol family not supported") -_ (EAFNOSUPPORT, "Address family not supported by protocol") -_ (EADDRINUSE, "Address already in use") -_ (EADDRNOTAVAIL, "Cannot assign requested address") -_ (ENETDOWN, "Network is down") -_ (ENETUNREACH, "Network is unreachable") -_ (ENETRESET, "Network dropped connection because of reset") -_ (ECONNABORTED, "Software caused connection abort") -_ (ECONNRESET, "Connection reset by peer") -_ (ENOBUFS, "No buffer space available") -_ (EISCONN, "Transport endpoint is already connected") -_ (ENOTCONN, "Transport endpoint is not connected") -_ (ESHUTDOWN, "Cannot send after transport endpoint shutdown") -_ (ETOOMANYREFS, "Too many references: cannot splice") -_ (ETIMEDOUT, "Connection timed out") -_ (ECONNREFUSED, "Connection refused") -_ (EHOSTDOWN, "Host is down") -_ (EHOSTUNREACH, "No route to host") -_ (EALREADY, "Operation already in progress") -_ (EINPROGRESS, "Operation now in progress") -_ (ESTALE, "Stale NFS file handle") -_ (EUCLEAN, "Structure needs cleaning") -_ (ENOTNAM, "Not a XENIX named type file") -_ (ENAVAIL, "No XENIX semaphores available") -_ (EISNAM, "Is a named type file") -_ (EREMOTEIO, "Remote I/O error") -_ (EDQUOT, "Quota exceeded") -_ (ENOMEDIUM, "No medium found") -_ (EMEDIUMTYPE, "Wrong medium type") diff --git a/vppinfra/vppinfra/anneal.c b/vppinfra/vppinfra/anneal.c deleted file mode 100644 index 35d10946482..00000000000 --- a/vppinfra/vppinfra/anneal.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - Copyright (c) 2011 Cisco and/or its affiliates. - - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. -*/ - -#include <vppinfra/anneal.h> - -/* - * Optimize an objective function by simulated annealing - * - * Here are a couple of short, easily-understood - * descriptions of simulated annealing: - * - * http://www.cs.sandia.gov/opt/survey/sa.html - * Numerical Recipes in C, 2nd ed., 444ff - * - * The description in the Wikipedia is not helpful. - * - * The algorithm tries to produce a decent answer to combinatorially - * explosive optimization problems by analogy to slow cooling - * of hot metal, aka annealing. - * - * There are (at least) three problem-dependent annealing parameters - * to consider: - * - * t0, the initial "temperature. Should be set so that the probability - * of accepting a transition to a higher cost configuration is - * initially about 0.8. - * - * ntemps, the number of temperatures to use. Each successive temperature - * is some fraction of the previous temperature. - * - * nmoves_per_temp, the number of configurations to try at each temperature - * - * It is a black art to set ntemps, nmoves_per_temp, and the rate - * at which the temperature drops. Go too fast with too few iterations, - * and the computation falls into a local minimum instead of the - * (desired) global minimum. - */ - -void -clib_anneal (clib_anneal_param_t * p) -{ - f64 t; - f64 cost, prev_cost, delta_cost, initial_cost, best_cost; - f64 random_accept, delta_cost_over_t; - f64 total_increase = 0.0, average_increase; - u32 i, j; - u32 number_of_increases = 0; - u32 accepted_this_temperature; - u32 best_saves_this_temperature; - int accept; - - t = p->initial_temperature; - best_cost = initial_cost = prev_cost = p->anneal_metric (p->opaque); - p->anneal_save_best_configuration (p->opaque); - - if (p->flags & CLIB_ANNEAL_VERBOSE) - fformat (stdout, "Initial cost %.2f\n", initial_cost); - - for (i = 0; i < p->number_of_temperatures; i++) - { - accepted_this_temperature = 0; - best_saves_this_temperature = 0; - - p->anneal_restore_best_configuration (p->opaque); - cost = best_cost; - - for (j = 0; j < p->number_of_configurations_per_temperature; j++) - { - p->anneal_new_configuration (p->opaque); - cost = p->anneal_metric (p->opaque); - - delta_cost = cost - prev_cost; - - /* cost function looks better, accept this move */ - if (p->flags & CLIB_ANNEAL_MINIMIZE) - accept = delta_cost < 0.0; - else - accept = delta_cost > 0.0; - - if (accept) - { - if (p->flags & CLIB_ANNEAL_MINIMIZE) - if (cost < best_cost) - { - if (p->flags & CLIB_ANNEAL_VERBOSE) - fformat (stdout, "New best cost %.2f\n", cost); - best_cost = cost; - p->anneal_save_best_configuration (p->opaque); - best_saves_this_temperature++; - } - - accepted_this_temperature++; - prev_cost = cost; - continue; - } - - /* cost function worse, keep stats to suggest t0 */ - total_increase += (p->flags & CLIB_ANNEAL_MINIMIZE) ? - delta_cost : -delta_cost; - - number_of_increases++; - - /* - * Accept a higher cost with Pr { e^(-(delta_cost / T)) }, - * equivalent to rnd[0,1] < e^(-(delta_cost / T)) - * - * AKA, the Boltzmann factor. - */ - random_accept = random_f64 (&p->random_seed); - - delta_cost_over_t = delta_cost / t; - - if (random_accept < exp (-delta_cost_over_t)) - { - accepted_this_temperature++; - prev_cost = cost; - continue; - } - p->anneal_restore_previous_configuration (p->opaque); - } - - if (p->flags & CLIB_ANNEAL_VERBOSE) - { - fformat (stdout, "Temp %.2f, cost %.2f, accepted %d, bests %d\n", t, - prev_cost, accepted_this_temperature, - best_saves_this_temperature); - fformat (stdout, "Improvement %.2f\n", initial_cost - prev_cost); - fformat (stdout, "-------------\n"); - } - - t = t * p->temperature_step; - } - - /* - * Empirically, one wants the probability of accepting a move - * at the initial temperature to be about 0.8. - */ - average_increase = total_increase / (f64) number_of_increases; - p->suggested_initial_temperature = average_increase / 0.22; /* 0.22 = -ln (0.8) */ - - p->final_temperature = t; - p->final_metric = p->anneal_metric (p->opaque); - - if (p->flags & CLIB_ANNEAL_VERBOSE) - { - fformat (stdout, "Average cost increase from a bad move: %.2f\n", - average_increase); - fformat (stdout, "Suggested t0 = %.2f\n", - p->suggested_initial_temperature); - } -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/anneal.h b/vppinfra/vppinfra/anneal.h deleted file mode 100644 index 148d38ba551..00000000000 --- a/vppinfra/vppinfra/anneal.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - Copyright (c) 2011 Cisco and/or its affiliates. - - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. -*/ - -#ifndef __included_anneal_h__ -#define __included_anneal_h__ - -#include <vppinfra/clib.h> -#include <vppinfra/format.h> -#include <vppinfra/random.h> -#include <math.h> - -typedef struct -{ - /* Initial temperature */ - f64 initial_temperature; - - /* Temperature fraction at each step, 0.95 is reasonable */ - f64 temperature_step; - - /* Number of temperatures used */ - u32 number_of_temperatures; - - /* Number of configurations tried at each temperature */ - u32 number_of_configurations_per_temperature; - - u32 flags; -#define CLIB_ANNEAL_VERBOSE (1<<0) -#define CLIB_ANNEAL_MINIMIZE (1<<1) /* mutually exclusive */ -#define CLIB_ANNEAL_MAXIMIZE (1<<2) /* mutually exclusive */ - - /* Random number seed, set to ensure repeatable results */ - u32 random_seed; - - /* Opaque data passed to callbacks */ - void *opaque; - - /* Final temperature (output) */ - f64 final_temperature; - - /* Final metric (output) */ - f64 final_metric; - - /* Suggested initial temperature (output) */ - f64 suggested_initial_temperature; - - - /*--- Callbacks ---*/ - - /* objective function to minimize */ - f64 (*anneal_metric) (void *opaque); - - /* Generate a new configuration */ - void (*anneal_new_configuration) (void *opaque); - - /* Restore the previous configuration */ - void (*anneal_restore_previous_configuration) (void *opaque); - - /* Save best configuration found e.g at a certain temperature */ - void (*anneal_save_best_configuration) (void *opaque); - - /* restore best configuration found e.g at a certain temperature */ - void (*anneal_restore_best_configuration) (void *opaque); - -} clib_anneal_param_t; - -void clib_anneal (clib_anneal_param_t * p); - -#endif /* __included_anneal_h__ */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/asm_mips.h b/vppinfra/vppinfra/asm_mips.h deleted file mode 100644 index 7c9e69586f4..00000000000 --- a/vppinfra/vppinfra/asm_mips.h +++ /dev/null @@ -1,351 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2004 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_asm_mips_h -#define included_asm_mips_h - -/* Encoding of MIPS instructions. */ -/* Encoding of opcode field (op). */ -#define mips_foreach_opcode \ - _(SPECIAL) _(REGIMM) _(j) _(jal) _(beq) _(bne) _(blez) _(bgtz) \ - _(addi) _(addiu) _(slti) _(sltiu) _(andi) _(ori) _(xori) _(lui) \ - _(COP0) _(COP1) _(COP2) _(COP1X) _(beql) _(bnel) _(blezl) _(bgtzl) \ - _(daddi) _(daddiu) _(ldl) _(ldr) _(SPECIAL2) _(jalx) _(MDMX) _(O37) \ - _(lb) _(lh) _(lwl) _(lw) _(lbu) _(lhu) _(lwr) _(lwu) \ - _(sb) _(sh) _(swl) _(sw) _(sdl) _(sdr) _(swr) _(cache) \ - _(ll) _(lwc1) _(lwc2) _(pref) _(lld) _(ldc1) _(ldc2) _(ld) \ - _(sc) _(swc1) _(swc2) _(o73) _(scd) _(sdc1) _(sdc2) _(sd) - -/* Encoding of funct field. */ -#define mips_foreach_special_funct \ - _(sll) _(MOVCI) _(srl) _(sra) _(sllv) _(o05) _(srlv) _(srav) \ - _(jr) _(jalr) _(movz) _(movn) _(syscall) _(break) _(o16) _(sync) \ - _(mfhi) _(mthi) _(mflo) _(mtlo) _(dsllv) _(o25) _(dsrlv) _(dsrav) \ - _(mult) _(multu) _(div) _(divu) _(dmult) _(dmultu) _(ddiv) _(ddivu) \ - _(add) _(addu) _(sub) _(subu) _(and) _(or) _(xor) _(nor) \ - _(o50) _(o51) _(slt) _(sltu) _(dadd) _(daddu) _(dsub) _(dsubu) \ - _(tge) _(tgeu) _(tlt) _(tltu) _(teq) _(o65) _(tne) _(o67) \ - _(dsll) _(o71) _(dsrl) _(dsra) _(dsll32) _(o75) _(dsrl32) _(dsra32) - -/* SPECIAL2 encoding of funct field. */ -#define mips_foreach_special2_funct \ - _(madd) _(maddu) _(mul) _(o03) _(msub) _(msubu) _(o06) _(o07) \ - _(o10) _(o11) _(o12) _(o13) _(o14) _(o15) _(o16) _(o17) \ - _(o20) _(o21) _(o22) _(o23) _(o24) _(o25) _(o26) _(o27) \ - _(o30) _(o31) _(o32) _(o33) _(o34) _(o35) _(o36) _(o37) \ - _(clz) _(clo) _(o42) _(o43) _(dclz) _(dclo) _(o46) _(o47) \ - _(o50) _(o51) _(o52) _(o53) _(o54) _(o55) _(o56) _(o57) \ - _(o60) _(o61) _(o62) _(o63) _(o64) _(o65) _(o66) _(o67) \ - _(o70) _(o71) _(o72) _(o73) _(o74) _(o75) _(o76) _(sdbbp) - -/* REGIMM encoding of rt field. */ -#define mips_foreach_regimm_rt \ - _(bltz) _(bgez) _(bltzl) _(bgezl) _(o04) _(o05) _(o06) _(o07) \ - _(tgei) _(tgeiu) _(tltiu) _(teqi) _(o14) _(tnei) _(o16) _(o17) \ - _(bltzal) _(bgezal) _(bltzall) _(bgezall) _(o24) _(o25) _(o26) _(o27) \ - _(o30) _(o31) _(o32) _(o33) _(o34) _(o35) _(o36) _(o37) - -/* COP0 encoding of rs field. */ -#define mips_foreach_cop0_rs \ - _(mfc0) _(dmfc0) _(o02) _(o03) _(mtc0) _(dmtc0) _(o06) _(o07) \ - _(o10) _(o11) _(o12) _(o13) _(o14) _(o15) _(o16) _(o17) \ - _(C0) _(o21) _(o22) _(o23) _(o24) _(o25) _(o26) _(o27) \ - _(o30) _(o31) _(o32) _(o33) _(o34) _(o35) _(o36) _(o37) - -/* COP0 encoding of funct when rs == RS_CO */ -#define mips_foreach_cop0_funct \ - _(o00) _(tlbr) _(tlbwi) _(o03) _(o04) _(o05) _(tlbwr) _(o07) \ - _(tlbp) _(o11) _(o12) _(o13) _(o14) _(o15) _(o16) _(o17) \ - _(o20) _(o21) _(o22) _(o23) _(o24) _(o25) _(o26) _(o27) \ - _(eret) _(o31) _(o32) _(o33) _(o34) _(o35) _(o36) _(deret) \ - _(wait) _(o41) _(o42) _(o43) _(o44) _(o45) _(o46) _(o47) \ - _(o50) _(o51) _(o52) _(o53) _(o54) _(o55) _(o56) _(o57) \ - _(o60) _(o61) _(o62) _(o63) _(o64) _(o65) _(o66) _(o67) \ - _(o70) _(o71) _(o72) _(o73) _(o74) _(o75) _(o76) _(o77) - -/* COP1 encoding of rs field. */ -#define mips_foreach_cop1_rs \ - _(mfc1) _(dmfc1) _(cfc1) _(o03) _(mtc1) _(dmtc1) _(ctc1) _(o07) \ - _(BC1) _(o11) _(o12) _(o13) _(o14) _(o15) _(o16) _(o17) \ - _(S) _(D) _(o22) _(o23) _(W) _(L) _(o26) _(o27) \ - _(o30) _(o31) _(o32) _(o33) _(o34) _(o35) _(o36) _(o37) - -/* COP1 encoding of funct for S and D */ -#define mips_foreach_cop1_funct \ - _(add) _(sub) _(mul) _(div) _(sqrt) _(abs) _(mov) _(neg) \ - _(roundl) _(truncl) _(ceill) _(floorl) _(roundw) _(truncw) _(ceilw) _(floorw) \ - _(o20) _(MOVCF) _(movz) _(movn) _(o24) _(recip) _(rsqrt) _(o27) \ - _(o30) _(o31) _(o32) _(o33) _(o34) _(o35) _(o36) _(o37) \ - _(cvts) _(cvtd) _(o42) _(o43) _(cvtw) _(cvtl) _(o46) _(o47) \ - _(o50) _(o51) _(o52) _(o53) _(o54) _(o55) _(o56) _(o57) \ - _(cf) _(cun) _(ceq) _(cueq) _(colt) _(cult) _(cole) _(cule) \ - _(csf) _(cngle) _(cseq) _(cngl) _(clt) _(cnge) _(cle) _(cngt) - -/* COP1X encoding of funct */ -#define mips_foreach_cop1x_funct \ - _(lwxc1) _(ldxc1) _(o02) _(o03) _(o04) _(luxc1) _(o06) _(o07) \ - _(swxc1) _(sdxc1) _(o12) _(o13) _(o14) _(suxc1) _(o16) _(prefx) \ - _(o20) _(o21) _(o22) _(o23) _(o24) _(o25) _(o26) _(o27) \ - _(o30) _(o31) _(o32) _(o33) _(o34) _(o35) _(o36) _(o37) \ - _(madds) _(maddd) _(o42) _(o43) _(o44) _(o45) _(o46) _(o47) \ - _(msubs) _(msubd) _(o52) _(o53) _(o54) _(o55) _(o56) _(o57) \ - _(nmadds) _(nmaddd) _(o62) _(o63) _(o64) _(o65) _(o66) _(o67) \ - _(nmsubs) _(nmsubd) _(o72) _(o73) _(o74) _(o75) _(o76) _(o77) - -#define mips_foreach_mdmx_funct \ - _(msgn) _(ceq) _(pickf) _(pickt) _(clt) _(cle) _(min) _(max) \ - _(o10) _(o11) _(sub) _(add) _(and) _(xor) _(or) _(nor) \ - _(sll) _(o21) _(srl) _(sra) _(o24) _(o25) _(o26) _(o27) \ - _(alniob) _(alnvob) _(alniqh) _(alnvqh) _(o34) _(o35) _(o36) _(shfl) \ - _(rzu) _(rnau) _(rneu) _(o43) _(rzs) _(rnas) _(rnes) _(o47) \ - _(o50) _(o51) _(o52) _(o53) _(o54) _(o55) _(o56) _(o57) \ - _(mul) _(o61) _(muls) _(mula) _(o64) _(o65) _(suba) _(adda) \ - _(o70) _(o71) _(o72) _(o73) _(o74) _(o75) _(wac) _(rac) - -#define _(f) MIPS_OPCODE_##f, -typedef enum -{ - mips_foreach_opcode -} mips_insn_opcode_t; -#undef _ - -#define _(f) MIPS_SPECIAL_FUNCT_##f, -typedef enum -{ - mips_foreach_special_funct -} mips_insn_special_funct_t; -#undef _ - -#define _(f) MIPS_SPECIAL2_FUNCT_##f, -typedef enum -{ - mips_foreach_special2_funct -} mips_insn_special2_funct_t; -#undef _ - -#define _(f) MIPS_REGIMM_RT_##f, -typedef enum -{ - mips_foreach_regimm_rt -} mips_insn_regimm_rt_t; -#undef _ - -#define _(f) MIPS_COP0_RS_##f, -typedef enum -{ - mips_foreach_cop0_rs -} mips_insn_cop0_rs_t; -#undef _ - -#define _(f) MIPS_COP0_FUNCT_##f, -typedef enum -{ - mips_foreach_cop0_funct -} mips_insn_cop0_funct_t; -#undef _ - -#define _(f) MIPS_COP1_RS_##f, -typedef enum -{ - mips_foreach_cop1_rs -} mips_insn_cop1_rs_t; -#undef _ - -#define _(f) MIPS_COP1_FUNCT_##f, -typedef enum -{ - mips_foreach_cop1_funct -} mips_insn_cop1_funct_t; -#undef _ - -#define _(f) MIPS_COP1X_FUNCT_##f, -typedef enum -{ - mips_foreach_cop1x_funct -} mips_insn_cop1x_funct_t; -#undef _ - -#define _(f) MIPS_MDMX_FUNCT_##f, -typedef enum -{ - mips_foreach_mdmx_funct -} mips_insn_mdmx_funct_t; -#undef _ - -always_inline mips_insn_opcode_t -mips_insn_get_op (u32 insn) -{ - return (insn >> 26) & 0x3f; -} - -always_inline u32 -mips_insn_get_rs (u32 insn) -{ - return (insn >> 21) & 0x1f; -} - -always_inline u32 -mips_insn_get_rt (u32 insn) -{ - return (insn >> 16) & 0x1f; -} - -always_inline u32 -mips_insn_get_rd (u32 insn) -{ - return (insn >> 11) & 0x1f; -} - -always_inline u32 -mips_insn_get_sa (u32 insn) -{ - return (insn >> 6) & 0x1f; -} - -always_inline u32 -mips_insn_get_funct (u32 insn) -{ - return (insn >> 0) & 0x3f; -} - -always_inline i32 -mips_insn_get_immediate (u32 insn) -{ - return (((i32) insn) << 16) >> 16; -} - -always_inline u32 -mips_insn_encode_i_type (int op, int rs, int rt, int immediate) -{ - u32 insn; - insn = immediate; - insn |= rt << 16; - insn |= rs << 21; - insn |= op << 26; - - ASSERT (mips_insn_get_immediate (insn) == immediate); - ASSERT (mips_insn_get_rt (insn) == rt); - ASSERT (mips_insn_get_rs (insn) == rt); - ASSERT (mips_insn_get_op (insn) == op); - - return insn; -} - -always_inline u32 -mips_insn_encode_j_type (int op, u32 addr) -{ - u32 insn; - - insn = (addr & ((1 << 28) - 1)) / 4; - insn |= op << 26; - - return insn; -} - -always_inline u32 -mips_insn_encode_r_type (int op, int rs, int rt, int rd, int sa, int funct) -{ - u32 insn; - insn = funct; - insn |= sa << 6; - insn |= rd << 11; - insn |= rt << 16; - insn |= rs << 21; - insn |= op << 26; - - ASSERT (mips_insn_get_funct (insn) == funct); - ASSERT (mips_insn_get_sa (insn) == sa); - ASSERT (mips_insn_get_rd (insn) == rd); - ASSERT (mips_insn_get_rt (insn) == rt); - ASSERT (mips_insn_get_rs (insn) == rt); - ASSERT (mips_insn_get_op (insn) == op); - - return insn; -} - -#define mips_insn_r(op,funct,rd,rs,rt,sa) \ - mips_insn_encode_r_type (MIPS_OPCODE_##op, \ - (rs), (rt), (rd), (sa), \ - MIPS_##op##_FUNCT_##funct) - -#define mips_insn_i(op,rs,rt,imm) \ - mips_insn_encode_i_type (MIPS_OPCODE_##op, (rs), (rt), (imm)) - -#define mips_insn_j(op,target) \ - mips_insn_encode_i_type (MIPS_OPCODE_##op, (rs), (rt), (imm)) - -/* Generate unsigned load instructions of data of various sizes. */ -always_inline u32 -mips_insn_load (u32 rd, i32 offset, u32 base, u32 log2_bytes) -{ - int op; - - ASSERT (log2_bytes < 4); - switch (log2_bytes) - { - case 0: - op = MIPS_OPCODE_lbu; - break; - case 1: - op = MIPS_OPCODE_lhu; - break; - case 2: - op = MIPS_OPCODE_lwu; - break; - case 3: - op = MIPS_OPCODE_ld; - break; - } - - return mips_insn_encode_i_type (op, base, rd, offset); -} - -typedef enum -{ - MIPS_REG_SP = 29, - MIPS_REG_RA = 31, -} mips_reg_t; - -#endif /* included_asm_mips_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/asm_x86.c b/vppinfra/vppinfra/asm_x86.c deleted file mode 100644 index 16e41c249b1..00000000000 --- a/vppinfra/vppinfra/asm_x86.c +++ /dev/null @@ -1,1947 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* FIXME - opcode name remove to save table space; enum - x87 - 3dnow - cbw naming -*/ - -#include <vppinfra/error.h> -#include <vppinfra/byte_order.h> -#include <vppinfra/asm_x86.h> - -#define foreach_x86_gp_register \ - _ (AX) _ (CX) _ (DX) _ (BX) \ - _ (SP) _ (BP) _ (SI) _ (DI) - -typedef enum { -#define _(r) X86_INSN_GP_REG_##r, - foreach_x86_gp_register -#undef _ -} x86_insn_gp_register_t; - -typedef union { - struct { - u8 rm : 3; - u8 reg : 3; - u8 mode : 2; - }; - u8 byte; -} x86_insn_modrm_byte_t; - -typedef union { - struct { - u8 base : 3; - u8 index : 3; - u8 log2_scale : 2; - }; - u8 byte; -} x86_insn_sib_byte_t; - -always_inline uword -x86_insn_has_modrm_byte (x86_insn_t * insn) -{ - int i; - for (i = 0; i < ARRAY_LEN (insn->operands); i++) - switch (insn->operands[i].code) - { - case 'G': case 'E': case 'M': case 'R': - return 1; - } - return 0; -} - -always_inline uword -x86_insn_immediate_type (x86_insn_t * insn) -{ - int i; - for (i = 0; i < ARRAY_LEN (insn->operands); i++) - switch (insn->operands[i].code) - { - case 'J': - case 'I': - case 'O': - return insn->operands[i].type; - } - return 0; -} - -/* Opcode extension in modrm byte reg field. */ -#define foreach_x86_insn_modrm_reg_group \ - _ (1) _ (1a) _ (2) _ (3) _ (4) _ (5) _ (6) _ (7) \ - _ (8) _ (9) _ (10) _ (11) _ (12) _ (13) _ (14) \ - _ (15) _ (16) _ (p) - -#define foreach_x86_insn_sse_group \ - _ (10) _ (28) _ (50) _ (58) _ (60) _ (68) _ (70) _ (78) \ - _ (c0) _ (d0) _ (d8) _ (e0) _ (e8) _ (f0) _ (f8) - -enum { -#define _(x) X86_INSN_MODRM_REG_GROUP_##x, - foreach_x86_insn_modrm_reg_group -#undef _ -#define _(x) X86_INSN_SSE_GROUP_##x, - foreach_x86_insn_sse_group -#undef _ -}; - -enum { -#define _(x) \ - X86_INSN_FLAG_MODRM_REG_GROUP_##x \ - = X86_INSN_FLAG_SET_MODRM_REG_GROUP (1 + X86_INSN_MODRM_REG_GROUP_##x), - foreach_x86_insn_modrm_reg_group -#undef _ - -#define _(x) \ - X86_INSN_FLAG_SSE_GROUP_##x \ - = X86_INSN_FLAG_SET_SSE_GROUP (1 + X86_INSN_SSE_GROUP_##x), - foreach_x86_insn_sse_group -#undef _ -}; - -#define foreach_x86_gp_reg \ - _ (AX) _ (CX) _ (DX) _ (BX) \ - _ (SP) _ (BP) _ (SI) _ (DI) - -#define foreach_x86_condition \ - _ (o) _ (no) _ (b) _ (nb) \ - _ (z) _ (nz) _ (be) _ (nbe) \ - _ (s) _ (ns) _ (p) _ (np) \ - _ (l) _ (nl) _ (le) _ (nle) - -#define _3f(x,f,o0,o1,o2) \ -{ \ - .name = #x, \ - .flags = (f), \ - .operands[0] = { .data = #o0 }, \ - .operands[1] = { .data = #o1 }, \ - .operands[2] = { .data = #o2 }, \ -} - -#define _2f(x,f,o0,o1) _3f(x,f,o0,o1,__) -#define _1f(x,f,o0) _2f(x,f,o0,__) -#define _0f(x,f) _1f(x,f,__) - -#define _3(x,o0,o1,o2) _3f(x,0,o0,o1,o2) -#define _2(x,o0,o1) _2f(x,0,o0,o1) -#define _1(x,o0) _1f(x,0,o0) -#define _0(x) _0f(x,0) - -static x86_insn_t x86_insns_one_byte[256] = { - -#define _(x) \ - _2 (x, Eb, Gb), \ - _2 (x, Ev, Gv), \ - _2 (x, Gb, Eb), \ - _2 (x, Gv, Ev), \ - _2 (x, AL, Ib), \ - _2 (x, AX, Iz) - - /* 0x00 */ - _ (add), - _0 (push_es), - _0 (pop_es), - _ (or), - _0 (push_cs), - _0 (escape_two_byte), - - /* 0x10 */ - _ (adc), - _0 (push_ss), - _0 (pop_ss), - _ (sbb), - _0 (push_ds), - _0 (pop_ds), - - /* 0x20 */ - _ (and), - _0 (segment_es), - _0 (daa), - _ (sub), - _0 (segment_cs), - _0 (das), - - /* 0x30 */ - _ (xor), - _0 (segment_ss), - _0 (aaa), - _ (cmp), - _0 (segment_ds), - _0 (aas), - -#undef _ - - /* 0x40 */ -#define _(r) _1 (inc, r), - foreach_x86_gp_reg -#undef _ -#define _(r) _1 (dec, r), - foreach_x86_gp_reg -#undef _ - - /* 0x50 */ -#define _(r) _1f (push, X86_INSN_FLAG_DEFAULT_64_BIT, r), - foreach_x86_gp_reg -#undef _ -#define _(r) _1f (pop, X86_INSN_FLAG_DEFAULT_64_BIT, r), - foreach_x86_gp_reg -#undef _ - - /* 0x60 */ - _0 (pusha), - _0 (popa), - _2 (bound, Gv, Ma), - _2 (movsxd, Gv, Ed), - _0 (segment_fs), - _0 (segment_gs), - _0 (operand_type), - _0 (address_size), - _1f (push, X86_INSN_FLAG_DEFAULT_64_BIT, Iz), - _3 (imul, Gv, Ev, Iz), - _1f (push, X86_INSN_FLAG_DEFAULT_64_BIT, Ib), - _3 (imul, Gv, Ev, Ib), - _1 (insb, DX), - _1 (insw, DX), - _1 (outsb, DX), - _1 (outsw, DX), - - /* 0x70 */ -#define _(x) _1 (j##x, Jb), - foreach_x86_condition -#undef _ - - /* 0x80 */ - _2f (modrm_group_1, X86_INSN_FLAG_MODRM_REG_GROUP_1, Eb, Ib), - _2f (modrm_group_1, X86_INSN_FLAG_MODRM_REG_GROUP_1, Ev, Iz), - _2f (modrm_group_1, X86_INSN_FLAG_MODRM_REG_GROUP_1, Eb, Ib), - _2f (modrm_group_1, X86_INSN_FLAG_MODRM_REG_GROUP_1, Ev, Ib), - _2 (test, Eb, Gb), - _2 (test, Ev, Gv), - _2 (xchg, Eb, Gb), - _2 (xchg, Ev, Gv), - _2 (mov, Eb, Gb), - _2 (mov, Ev, Gv), - _2 (mov, Gb, Eb), - _2 (mov, Gv, Ev), - _2 (mov, Ev, Sw), - _2 (lea, Gv, Ev), - _2 (mov, Sw, Ew), - _1f (modrm_group_1a, X86_INSN_FLAG_MODRM_REG_GROUP_1a, Ev), - - /* 0x90 */ - _0 (nop), - _1 (xchg, CX), - _1 (xchg, DX), - _1 (xchg, BX), - _1 (xchg, SP), - _1 (xchg, BP), - _1 (xchg, SI), - _1 (xchg, DI), - _0 (cbw), - _0 (cwd), - _1 (call, Ap), - _0 (wait), - _0 (pushf), - _0 (popf), - _0 (sahf), - _0 (lahf), - - /* 0xa0 */ - _2 (mov, AL, Ob), - _2 (mov, AX, Ov), - _2 (mov, Ob, AL), - _2 (mov, Ov, AX), - _0 (movsb), - _0 (movsw), - _0 (cmpsb), - _0 (cmpsw), - _2 (test, AL, Ib), - _2 (test, AX, Iz), - _1 (stosb, AL), - _1 (stosw, AX), - _1 (lodsb, AL), - _1 (lodsw, AX), - _1 (scasb, AL), - _1 (scasw, AX), - - /* 0xb0 */ - _2 (mov, AL, Ib), - _2 (mov, CL, Ib), - _2 (mov, DL, Ib), - _2 (mov, BL, Ib), - _2 (mov, AH, Ib), - _2 (mov, CH, Ib), - _2 (mov, DH, Ib), - _2 (mov, BH, Ib), -#define _(r) _2 (mov, r, Iv), - foreach_x86_gp_reg -#undef _ - - /* 0xc0 */ - _2f (modrm_group_2, X86_INSN_FLAG_MODRM_REG_GROUP_2, Eb, Ib), - _2f (modrm_group_2, X86_INSN_FLAG_MODRM_REG_GROUP_2, Ev, Ib), - _1 (ret, Iw), - _0 (ret), - _2 (les, Gz, Mp), - _2 (lds, Gz, Mp), - _2f (modrm_group_11, X86_INSN_FLAG_MODRM_REG_GROUP_11, Eb, Ib), - _2f (modrm_group_11, X86_INSN_FLAG_MODRM_REG_GROUP_11, Ev, Iz), - _2 (enter, Iw, Ib), - _0 (leave), - _1 (ret, Iw), - _0 (ret), - _0 (int3), - _1 (int, Ib), - _0 (into), - _0 (iret), - - /* 0xd0 */ - _2f (modrm_group_2, X86_INSN_FLAG_MODRM_REG_GROUP_2, Eb, 1b), - _2f (modrm_group_2, X86_INSN_FLAG_MODRM_REG_GROUP_2, Ev, 1b), - _2f (modrm_group_2, X86_INSN_FLAG_MODRM_REG_GROUP_2, Eb, CL), - _2f (modrm_group_2, X86_INSN_FLAG_MODRM_REG_GROUP_2, Ev, CL), - _0 (aam), - _0 (aad), - _0 (salc), - _0 (xlat), - /* FIXME x87 */ - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - - /* 0xe0 */ - _1 (loopnz, Jb), - _1 (loopz, Jb), - _1 (loop, Jb), - _1 (jcxz, Jb), - _2 (in, AL, Ib), - _2 (in, AX, Ib), - _2 (out, Ib, AL), - _2 (out, Ib, AX), - _1f (call, X86_INSN_FLAG_DEFAULT_64_BIT, Jz), - _1f ( jmp, X86_INSN_FLAG_DEFAULT_64_BIT, Jz), - _1 (jmp, Ap), - _1 (jmp, Jb), - _2 (in, AL, DX), - _2 (in, AX, DX), - _2 (out, DX, AL), - _2 (out, DX, AX), - - /* 0xf0 */ - _0 (lock), - _0 (int1), - _0 (repne), - _0 (rep), - _0 (hlt), - _0 (cmc), - _0f (modrm_group_3, X86_INSN_FLAG_MODRM_REG_GROUP_3), - _0f (modrm_group_3, X86_INSN_FLAG_MODRM_REG_GROUP_3), - _0 (clc), - _0 (stc), - _0 (cli), - _0 (sti), - _0 (cld), - _0 (std), - _1f (modrm_group_4, X86_INSN_FLAG_MODRM_REG_GROUP_4, Eb), - _0f (modrm_group_5, X86_INSN_FLAG_MODRM_REG_GROUP_5), -}; - -static x86_insn_t x86_insns_two_byte[256] = { - /* 0x00 */ - _0f (modrm_group_6, X86_INSN_FLAG_MODRM_REG_GROUP_6), - _0f (modrm_group_7, X86_INSN_FLAG_MODRM_REG_GROUP_7), - _2 (lar, Gv, Ew), - _2 (lsl, Gv, Ew), - _0 (bad), - _0 (syscall), - _0 (clts), - _0 (sysret), - _0 (invd), - _0 (wbinvd), - _0 (bad), - _0 (ud2), - _0 (bad), - _0f (modrm_group_p, X86_INSN_FLAG_MODRM_REG_GROUP_p), - _0 (femms), - _0 (escape_3dnow), - - /* 0x10 */ - _2f (movups, X86_INSN_FLAG_SSE_GROUP_10, Gx, Ex), - _2f (movups, X86_INSN_FLAG_SSE_GROUP_10, Ex, Gx), - _2f (movlps, X86_INSN_FLAG_SSE_GROUP_10, Ex, Gx), - _2f (movlps, X86_INSN_FLAG_SSE_GROUP_10, Gx, Ex), - _2f (unpcklps, X86_INSN_FLAG_SSE_GROUP_10, Gx, Ex), - _2f (unpckhps, X86_INSN_FLAG_SSE_GROUP_10, Gx, Ex), - _2f (movhps, X86_INSN_FLAG_SSE_GROUP_10, Ex, Gx), - _2f (movhps, X86_INSN_FLAG_SSE_GROUP_10, Gx, Ex), - _0f (modrm_group_16, X86_INSN_FLAG_MODRM_REG_GROUP_16), - _0 (nop), - _0 (nop), - _0 (nop), - _0 (nop), - _0 (nop), - _0 (nop), - _0 (nop), - - /* 0x20 */ - _2 (mov, Rv, Cv), - _2 (mov, Rv, Dv), - _2 (mov, Cv, Rv), - _2 (mov, Dv, Rv), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _2f (movaps, X86_INSN_FLAG_SSE_GROUP_28, Gx, Ex), - _2f (movaps, X86_INSN_FLAG_SSE_GROUP_28, Ex, Gx), - _2f (cvtpi2ps, X86_INSN_FLAG_SSE_GROUP_28, Gx, Ex), - _2f (movntps, X86_INSN_FLAG_SSE_GROUP_28, Mx, Gx), - _2f (cvttps2pi, X86_INSN_FLAG_SSE_GROUP_28, Gx, Ex), - _2f (cvtps2pi, X86_INSN_FLAG_SSE_GROUP_28, Gx, Ex), - _2f (ucomiss, X86_INSN_FLAG_SSE_GROUP_28, Gx, Ex), - _2f (comiss, X86_INSN_FLAG_SSE_GROUP_28, Gx, Ex), - - /* 0x30 */ - _0 (wrmsr), - _0 (rdtsc), - _0 (rdmsr), - _0 (rdpmc), - _0 (sysenter), - _0 (sysexit), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - - /* 0x40 */ -#define _(x) _2 (cmov##x, Gv, Ev), - foreach_x86_condition -#undef _ - - /* 0x50 */ - _2f (movmskps, X86_INSN_FLAG_SSE_GROUP_50, Gd, Rx), - _2f (sqrtps, X86_INSN_FLAG_SSE_GROUP_50, Gx, Ex), - _2f (rsqrtps, X86_INSN_FLAG_SSE_GROUP_50, Gx, Ex), - _2f (rcpps, X86_INSN_FLAG_SSE_GROUP_50, Gx, Ex), - _2f (andps, X86_INSN_FLAG_SSE_GROUP_50, Gx, Ex), - _2f (andnps, X86_INSN_FLAG_SSE_GROUP_50, Gx, Ex), - _2f (orps, X86_INSN_FLAG_SSE_GROUP_50, Gx, Ex), - _2f (xorps, X86_INSN_FLAG_SSE_GROUP_50, Gx, Ex), - _2f (addps, X86_INSN_FLAG_SSE_GROUP_58, Gx, Ex), - _2f (mulps, X86_INSN_FLAG_SSE_GROUP_58, Gx, Ex), - _2f (cvtps2pd, X86_INSN_FLAG_SSE_GROUP_58, Gx, Ex), - _2f (cvtdq2ps, X86_INSN_FLAG_SSE_GROUP_58, Gx, Ex), - _2f (subps, X86_INSN_FLAG_SSE_GROUP_58, Gx, Ex), - _2f (minps, X86_INSN_FLAG_SSE_GROUP_58, Gx, Ex), - _2f (divps, X86_INSN_FLAG_SSE_GROUP_58, Gx, Ex), - _2f (maxps, X86_INSN_FLAG_SSE_GROUP_58, Gx, Ex), - - /* 0x60 */ - _2f (punpcklbw, X86_INSN_FLAG_SSE_GROUP_60, Gm, Em), - _2f (punpcklwd, X86_INSN_FLAG_SSE_GROUP_60, Gm, Em), - _2f (punpckldq, X86_INSN_FLAG_SSE_GROUP_60, Gm, Em), - _2f (packsswb, X86_INSN_FLAG_SSE_GROUP_60, Gm, Em), - _2f (pcmpgtb, X86_INSN_FLAG_SSE_GROUP_60, Gm, Em), - _2f (pcmpgtw, X86_INSN_FLAG_SSE_GROUP_60, Gm, Em), - _2f (pcmpgtd, X86_INSN_FLAG_SSE_GROUP_60, Gm, Em), - _2f (packuswb, X86_INSN_FLAG_SSE_GROUP_60, Gm, Em), - _2f (punpckhbw, X86_INSN_FLAG_SSE_GROUP_68, Gm, Em), - _2f (punpckhwd, X86_INSN_FLAG_SSE_GROUP_68, Gm, Em), - _2f (punpckhdq, X86_INSN_FLAG_SSE_GROUP_68, Gm, Em), - _2f (packssdw, X86_INSN_FLAG_SSE_GROUP_68, Gm, Em), - _0f (bad, X86_INSN_FLAG_SSE_GROUP_68), - _0f (bad, X86_INSN_FLAG_SSE_GROUP_68), - _2f (movd, X86_INSN_FLAG_SSE_GROUP_68, Gm, Em), - _2f (movq, X86_INSN_FLAG_SSE_GROUP_68, Gm, Em), - - /* 0x70 */ - _3f (pshufw, X86_INSN_FLAG_SSE_GROUP_70, Gm, Em, Ib), - _0f (modrm_group_12, X86_INSN_FLAG_MODRM_REG_GROUP_12), - _0f (modrm_group_13, X86_INSN_FLAG_MODRM_REG_GROUP_13), - _0f (modrm_group_14, X86_INSN_FLAG_MODRM_REG_GROUP_14), - _2f (pcmpeqb, X86_INSN_FLAG_SSE_GROUP_70, Gm, Em), - _2f (pcmpeqw, X86_INSN_FLAG_SSE_GROUP_70, Gm, Em), - _2f (pcmpeqd, X86_INSN_FLAG_SSE_GROUP_70, Gm, Em), - _0f (emms, X86_INSN_FLAG_SSE_GROUP_70), - _0f (bad, X86_INSN_FLAG_SSE_GROUP_78), - _0f (bad, X86_INSN_FLAG_SSE_GROUP_78), - _0f (bad, X86_INSN_FLAG_SSE_GROUP_78), - _0f (bad, X86_INSN_FLAG_SSE_GROUP_78), - _0f (bad, X86_INSN_FLAG_SSE_GROUP_78), - _0f (bad, X86_INSN_FLAG_SSE_GROUP_78), - _2f (movd, X86_INSN_FLAG_SSE_GROUP_78, Em, Gm), - _2f (movq, X86_INSN_FLAG_SSE_GROUP_78, Em, Gm), - - /* 0x80 */ -#define _(x) _1 (jmp##x, Jz), - foreach_x86_condition -#undef _ - - /* 0x90 */ -#define _(x) _1 (set##x, Eb), - foreach_x86_condition -#undef _ - - /* 0xa0 */ - _0 (push_fs), - _0 (pop_fs), - _0 (cpuid), - _2 (bt, Ev, Gv), - _3 (shld, Ev, Gv, Ib), - _3 (shld, Ev, Gv, CL), - _0 (bad), - _0 (bad), - _0 (push_gs), - _0 (pop_gs), - _0 (rsm), - _2 (bts, Ev, Gv), - _3 (shrd, Ev, Gv, Ib), - _3 (shrd, Ev, Gv, CL), - _0f (modrm_group_15, X86_INSN_FLAG_MODRM_REG_GROUP_15), - _2 (imul, Gv, Ev), - - /* 0xb0 */ - _2 (cmpxchg, Eb, Gb), - _2 (cmpxchg, Ev, Gv), - _2 (lss, Gz, Mp), - _2 (btr, Ev, Gv), - _2 (lfs, Gz, Mp), - _2 (lgs, Gz, Mp), - _2 (movzbl, Gv, Eb), - _2 (movzwl, Gv, Ew), - _0 (bad), - _0f (modrm_group_10, X86_INSN_FLAG_MODRM_REG_GROUP_10), - _2f (modrm_group_8, X86_INSN_FLAG_MODRM_REG_GROUP_8, Ev, Ib), - _2 (btc, Ev, Gv), - _2 (bsf, Gv, Ev), - _2 (bsr, Gv, Ev), - _2 (movsx, Gv, Eb), - _2 (movsx, Gv, Ew), - - /* 0xc0 */ - _2 (xadd, Eb, Gb), - _2 (xadd, Ev, Gv), - _3f (cmpps, X86_INSN_FLAG_SSE_GROUP_c0, Gx, Ex, Ib), - _2 (movnti, Mv, Gv), - _3f (pinsrw, X86_INSN_FLAG_SSE_GROUP_c0, Gm, Ew, Ib), - _3f (pextrw, X86_INSN_FLAG_SSE_GROUP_c0, Gd, Rm, Ib), - _3f (shufps, X86_INSN_FLAG_SSE_GROUP_c0, Gx, Ex, Ib), - _1f (modrm_group_9, X86_INSN_FLAG_MODRM_REG_GROUP_9, Mx), -#define _(r) _1 (bswap, r), - foreach_x86_gp_reg -#undef _ - - /* 0xd0 */ - _0f (bad, X86_INSN_FLAG_SSE_GROUP_d0), - _2f (psrlw, X86_INSN_FLAG_SSE_GROUP_d0, Gm, Em), - _2f (psrld, X86_INSN_FLAG_SSE_GROUP_d0, Gm, Em), - _2f (psrlq, X86_INSN_FLAG_SSE_GROUP_d0, Gm, Em), - _2f (paddq, X86_INSN_FLAG_SSE_GROUP_d0, Gm, Em), - _2f (pmullw, X86_INSN_FLAG_SSE_GROUP_d0, Gm, Em), - _0f (bad, X86_INSN_FLAG_SSE_GROUP_d0), - _2f (pmovmskb, X86_INSN_FLAG_SSE_GROUP_d0, Gd, Rm), - _2f (psubusb, X86_INSN_FLAG_SSE_GROUP_d8, Gm, Em), - _2f (psubusw, X86_INSN_FLAG_SSE_GROUP_d8, Gm, Em), - _2f (pminub, X86_INSN_FLAG_SSE_GROUP_d8, Gm, Em), - _2f (pand, X86_INSN_FLAG_SSE_GROUP_d8, Gm, Em), - _2f (paddusb, X86_INSN_FLAG_SSE_GROUP_d8, Gm, Em), - _2f (paddusw, X86_INSN_FLAG_SSE_GROUP_d8, Gm, Em), - _2f (pmaxub, X86_INSN_FLAG_SSE_GROUP_d8, Gm, Em), - _2f (pandn, X86_INSN_FLAG_SSE_GROUP_d8, Gm, Em), - - /* 0xe0 */ - _2f (pavgb, X86_INSN_FLAG_SSE_GROUP_e0, Gm, Em), - _2f (psraw, X86_INSN_FLAG_SSE_GROUP_e0, Gm, Em), - _2f (psrad, X86_INSN_FLAG_SSE_GROUP_e0, Gm, Em), - _2f (pavgw, X86_INSN_FLAG_SSE_GROUP_e0, Gm, Em), - _2f (pmulhuw, X86_INSN_FLAG_SSE_GROUP_e0, Gm, Em), - _2f (pmulhw, X86_INSN_FLAG_SSE_GROUP_e0, Gm, Em), - _2f (bad, X86_INSN_FLAG_SSE_GROUP_e0, Gm, Em), - _2f (movntq, X86_INSN_FLAG_SSE_GROUP_e0, Mm, Gm), - _2f (psubsb, X86_INSN_FLAG_SSE_GROUP_e8, Gm, Em), - _2f (psubsw, X86_INSN_FLAG_SSE_GROUP_e8, Gm, Em), - _2f (pminsw, X86_INSN_FLAG_SSE_GROUP_e8, Gm, Em), - _2f (por, X86_INSN_FLAG_SSE_GROUP_e8, Gm, Em), - _2f (paddsb, X86_INSN_FLAG_SSE_GROUP_e8, Gm, Em), - _2f (paddsw, X86_INSN_FLAG_SSE_GROUP_e8, Gm, Em), - _2f (pmaxsw, X86_INSN_FLAG_SSE_GROUP_e8, Gm, Em), - _2f (pxor, X86_INSN_FLAG_SSE_GROUP_e8, Gm, Em), - - /* 0xf0 */ - _0f (bad, X86_INSN_FLAG_SSE_GROUP_f0), - _2f (psllw, X86_INSN_FLAG_SSE_GROUP_f0, Gm, Em), - _2f (pslld, X86_INSN_FLAG_SSE_GROUP_f0, Gm, Em), - _2f (psllq, X86_INSN_FLAG_SSE_GROUP_f0, Gm, Em), - _2f (pmuludq, X86_INSN_FLAG_SSE_GROUP_f0, Gm, Em), - _2f (pmaddwd, X86_INSN_FLAG_SSE_GROUP_f0, Gm, Em), - _2f (psadbw, X86_INSN_FLAG_SSE_GROUP_f0, Gm, Em), - _2f (maskmovq, X86_INSN_FLAG_SSE_GROUP_f0, Gm, Em), - _2f (psubb, X86_INSN_FLAG_SSE_GROUP_f8, Gm, Em), - _2f (psubw, X86_INSN_FLAG_SSE_GROUP_f8, Gm, Em), - _2f (psubd, X86_INSN_FLAG_SSE_GROUP_f8, Gm, Em), - _2f (psubq, X86_INSN_FLAG_SSE_GROUP_f8, Gm, Em), - _2f (paddb, X86_INSN_FLAG_SSE_GROUP_f8, Gm, Em), - _2f (paddw, X86_INSN_FLAG_SSE_GROUP_f8, Gm, Em), - _2f (paddd, X86_INSN_FLAG_SSE_GROUP_f8, Gm, Em), - _0f (bad, X86_INSN_FLAG_SSE_GROUP_f8), -}; - -typedef struct { - x86_insn_t insns[8]; -} x86_insn_group8_t; - -/* Escape groups are indexed by modrm reg field. */ -static x86_insn_group8_t x86_insn_modrm_reg_groups[] = { - [X86_INSN_MODRM_REG_GROUP_1].insns = { - _0 (add), _0 ( or), _0 (adc), _0 (sbb), - _0 (and), _0 (sub), _0 (xor), _0 (cmp), - }, - - [X86_INSN_MODRM_REG_GROUP_1a].insns = { - _0f (pop, X86_INSN_FLAG_DEFAULT_64_BIT), - _0 (bad), _0 (bad), _0 (bad), - _0 (bad), _0 (bad), _0 (bad), _0 (bad), - }, - - [X86_INSN_MODRM_REG_GROUP_2].insns = { - _0 (rol), _0 (ror), _0 (rcl), _0 (rcr), - _0 (shl), _0 (shr), _0 (sal), _0 (sar), - }, - - [X86_INSN_MODRM_REG_GROUP_3].insns = { - _0 (test), _0 (test), _0 (not), _0 (neg), - _0 (mul), _0 (imul), _0 (div), _0 (idiv), - }, - - [X86_INSN_MODRM_REG_GROUP_4].insns = { - _0 (inc), _0 (dec), _0 (bad), _0 (bad), - _0 (bad), _0 (bad), _0 (bad), _0 (bad), - }, - - [X86_INSN_MODRM_REG_GROUP_5].insns = { - _1 (inc, Ev), - _1 (dec, Ev), - _1f (call, X86_INSN_FLAG_DEFAULT_64_BIT, Ev), - _1 (call, Mp), - _1f (jmp, X86_INSN_FLAG_DEFAULT_64_BIT, Ev), - _1 (jmp, Mp), - _1f (push, X86_INSN_FLAG_DEFAULT_64_BIT, Ev), - _0 (bad), - }, - - [X86_INSN_MODRM_REG_GROUP_6].insns = { - _1 (sldt, Ev), - _1 (str, Ev), - _1 (lldt, Ev), - _1 (ltr, Ev), - _1 (verr, Ev), - _1 (verw, Ev), - _0 (bad), - _0 (bad), - }, - - [X86_INSN_MODRM_REG_GROUP_7].insns = { - _1 (sgdt, Mv), - _1 (sidt, Mv), - _1 (lgdt, Mv), - _1 (lidt, Mv), - _1 (smsw, Ev), - _0 (bad), - _1 (lmsw, Ew), - _1 (invlpg, Mv), - }, - - [X86_INSN_MODRM_REG_GROUP_8].insns = { - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _2 (bt, Ev, Ib), - _2 (bts, Ev, Ib), - _2 (btr, Ev, Ib), - _2 (btc, Ev, Ib), - }, - - [X86_INSN_MODRM_REG_GROUP_9].insns = { - _0 (bad), - _1 (cmpxchg, Mx), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - }, - - [X86_INSN_MODRM_REG_GROUP_10].insns = { - _0 (bad), _0 (bad), _0 (bad), _0 (bad), - _0 (bad), _0 (bad), _0 (bad), _0 (bad), - }, - - [X86_INSN_MODRM_REG_GROUP_11].insns = { - _0 (mov), _0 (bad), _0 (bad), _0 (bad), - _0 (bad), _0 (bad), _0 (bad), _0 (bad), - }, - - [X86_INSN_MODRM_REG_GROUP_12].insns = { - _0 (bad), - _0 (bad), - _2 (psrlw, Rm, Ib), - _0 (bad), - _2 (psraw, Rm, Ib), - _0 (bad), - _2 (psllw, Rm, Ib), - _0 (bad), - }, - - [X86_INSN_MODRM_REG_GROUP_13].insns = { - _0 (bad), - _0 (bad), - _2 (psrld, Rm, Ib), - _0 (bad), - _2 (psrad, Rm, Ib), - _0 (bad), - _2 (pslld, Rm, Ib), - _0 (bad), - }, - - [X86_INSN_MODRM_REG_GROUP_14].insns = { - _0 (bad), - _0 (bad), - _2 (psrlq, Rm, Ib), - _0f (bad, 0), - _0 (bad), - _0 (bad), - _2 (psllq, Rm, Ib), - _0f (bad, 0), - }, - - [X86_INSN_MODRM_REG_GROUP_15].insns = { - _1 (fxsave, Mv), - _1 (fxrstor, Mv), - _1 (ldmxcsr, Mv), - _1 (stmxcsr, Mv), - _0 (bad), - _1 (lfence, Mv), - _1 (mfence, Mv), - _1 (sfence, Mv), - }, - - [X86_INSN_MODRM_REG_GROUP_16].insns = { - _1 (prefetch_nta, Mv), - _1 (prefetch_t0, Mv), - _1 (prefetch_t1, Mv), - _1 (prefetch_t2, Mv), - _1 (prefetch_nop, Mv), - _1 (prefetch_nop, Mv), - _1 (prefetch_nop, Mv), - _1 (prefetch_nop, Mv), - }, - - [X86_INSN_MODRM_REG_GROUP_p].insns = { - _1 (prefetch_exclusive, Mv), - _1 (prefetch_modified, Mv), - _1 (prefetch_nop, Mv), - _1 (prefetch_modified, Mv), - _1 (prefetch_nop, Mv), - _1 (prefetch_nop, Mv), - _1 (prefetch_nop, Mv), - _1 (prefetch_nop, Mv), - }, -}; - -static x86_insn_group8_t x86_insn_sse_groups_repz[] = { - [X86_INSN_SSE_GROUP_10].insns = { - _2 (movss, Gx, Ex), - _2 (movss, Ex, Gx), - _2 (movsldup, Gx, Ex), - _0 (bad), - _0 (bad), - _0 (bad), - _2 (movshdup, Gx, Ex), - _0 (bad), - }, - - [X86_INSN_SSE_GROUP_28].insns = { - _0 (bad), - _0 (bad), - _2 (cvtsi2ss, Gx, Ev), - _0 (bad), - _2 (cvttss2si, Gv, Ex), - _2 (cvtss2si, Gv, Ex), - _0 (bad), - _0 (bad), - }, - - [X86_INSN_SSE_GROUP_50].insns = { - _0 (bad), - _2 (sqrtss, Gx, Ex), - _2 (rsqrtps, Gx, Ex), - _2 (rcpss, Gx, Ex), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - }, - - [X86_INSN_SSE_GROUP_58].insns = { - _2 (addss, Gx, Ex), - _2 (mulss, Gx, Ex), - _2 (cvtss2sd, Gx, Ex), - _2 (cvttps2dq, Gx, Ex), - _2 (subss, Gx, Ex), - _2 (minss, Gx, Ex), - _2 (divss, Gx, Ex), - _2 (maxss, Gx, Ex), - }, - - [X86_INSN_SSE_GROUP_60].insns = { - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - }, - - [X86_INSN_SSE_GROUP_68].insns = { - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _2 (movdqu, Gx, Ex), - }, - - [X86_INSN_SSE_GROUP_70].insns = { - _3 (pshufhw, Gx, Ex, Ib), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - }, - - [X86_INSN_SSE_GROUP_78].insns = { - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _2 (movq, Gx, Ex), - _2 (movdqu, Ex, Gx), - }, - - [X86_INSN_SSE_GROUP_c0].insns = { - _0 (bad), - _0 (bad), - _3 (cmpss, Gx, Ex, Ib), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - }, - - [X86_INSN_SSE_GROUP_d0].insns = { - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _2 (movq2dq, Gx, Em), - _0 (bad), - }, - - [X86_INSN_SSE_GROUP_d8].insns = { - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - }, - - [X86_INSN_SSE_GROUP_e0].insns = { - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _2 (cvtdq2pd, Gx, Ex), - _0 (bad), - }, - - [X86_INSN_SSE_GROUP_e8].insns = { - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - }, - - [X86_INSN_SSE_GROUP_f0].insns = { - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - }, - - [X86_INSN_SSE_GROUP_f8].insns = { - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - }, -}; - -static x86_insn_group8_t x86_insn_sse_groups_operand_size[] = { - [X86_INSN_SSE_GROUP_10].insns = { - _2 (movupd, Gx, Ex), - _2 (movupd, Ex, Gx), - _2 (movlpd, Gx, Ex), - _2 (movlpd, Ex, Gx), - _2 (unpcklpd, Gx, Ex), - _2 (unpckhpd, Gx, Ex), - _2 (movhpd, Gx, Mx), - _2 (movhpd, Mx, Gx), - }, - - [X86_INSN_SSE_GROUP_28].insns = { - _2 (movapd, Gx, Ex), - _2 (movapd, Ex, Gx), - _2 (cvtpi2pd, Gx, Ex), - _2 (movntpd, Mx, Gx), - _2 (cvttpd2pi, Gx, Mx), - _2 (cvtpd2pi, Gx, Mx), - _2 (ucomisd, Gx, Ex), - _2 (comisd, Gx, Ex), - }, - - [X86_INSN_SSE_GROUP_50].insns = { - _2 (movmskpd, Gd, Rx), - _2 (sqrtpd, Gx, Ex), - _0 (bad), - _0 (bad), - _2 (andpd, Gx, Ex), - _2 (andnpd, Gx, Ex), - _2 (orpd, Gx, Ex), - _2 (xorpd, Gx, Ex), - }, - - [X86_INSN_SSE_GROUP_58].insns = { - _2 (addpd, Gx, Ex), - _2 (mulpd, Gx, Ex), - _2 (cvtpd2ps, Gx, Ex), - _2 (cvtps2dq, Gx, Ex), - _2 (subpd, Gx, Ex), - _2 (minpd, Gx, Ex), - _2 (divpd, Gx, Ex), - _2 (maxpd, Gx, Ex), - }, - - [X86_INSN_SSE_GROUP_60].insns = { - _2 (punpcklbw, Gx, Ex), - _2 (punpcklwd, Gx, Ex), - _2 (punpckldq, Gx, Ex), - _2 (packsswb, Gx, Ex), - _2 (pcmpgtb, Gx, Ex), - _2 (pcmpgtw, Gx, Ex), - _2 (pcmpgtd, Gx, Ex), - _2 (packuswb, Gx, Ex), - }, - - [X86_INSN_SSE_GROUP_68].insns = { - _2 (punpckhbw, Gx, Ex), - _2 (punpckhwd, Gx, Ex), - _2 (punpckhdq, Gx, Ex), - _2 (packssdw, Gx, Ex), - _2 (punpcklqdq, Gx, Ex), - _2 (punpckhqdq, Gx, Ex), - _2 (movd, Gx, Ev), - _2 (movdqa, Gx, Ex), - }, - - [X86_INSN_SSE_GROUP_70].insns = { - _3 (pshufd, Gx, Ex, Ib), - _0f (modrm_group_12, X86_INSN_FLAG_MODRM_REG_GROUP_12), - _0f (modrm_group_13, X86_INSN_FLAG_MODRM_REG_GROUP_13), - _0f (modrm_group_14, X86_INSN_FLAG_MODRM_REG_GROUP_14), - _2 (pcmpeqb, Gx, Ex), - _2 (pcmpeqw, Gx, Ex), - _2 (pcmpeqd, Gx, Ex), - _0 (bad), - }, - - [X86_INSN_SSE_GROUP_78].insns = { - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _2 (haddpd, Gx, Ex), - _2 (hsubpd, Gx, Ex), - _2 (movd, Ev, Gx), - _2 (movdqa, Ex, Gx), - }, - - [X86_INSN_SSE_GROUP_c0].insns = { - _0 (bad), - _0 (bad), - _3 (cmppd, Gx, Ex, Ib), - _0 (bad), - _3 (pinsrw, Gx, Ew, Ib), - _3 (pextrw, Gd, Gx, Ib), - _3 (shufpd, Gx, Ex, Ib), - _0 (bad), - }, - - [X86_INSN_SSE_GROUP_d0].insns = { - _2 (addsubpd, Gx, Ex), - _2 (psrlw, Gx, Ex), - _2 (psrld, Gx, Ex), - _2 (psrlq, Gx, Ex), - _2 (paddq, Gx, Ex), - _2 (pmullw, Gx, Ex), - _2 (movq, Ex, Gx), - _2 (pmovmskb, Gd, Rx), - }, - - [X86_INSN_SSE_GROUP_d8].insns = { - _2 (psubusb, Gx, Ex), - _2 (psubusw, Gx, Ex), - _2 (pminub, Gx, Ex), - _2 (pand, Gx, Ex), - _2 (paddusb, Gx, Ex), - _2 (paddusw, Gx, Ex), - _2 (pmaxub, Gx, Ex), - _2 (pandn, Gx, Ex), - }, - - [X86_INSN_SSE_GROUP_e0].insns = { - _2 (pavgb, Gx, Ex), - _2 (psraw, Gx, Ex), - _2 (psrad, Gx, Ex), - _2 (pavgw, Gx, Ex), - _2 (pmulhuw, Gx, Ex), - _2 (pmulhw, Gx, Ex), - _2 (cvttpd2dq, Gx, Ex), - _2 (movntdq, Mx, Gx), - }, - - [X86_INSN_SSE_GROUP_e8].insns = { - _2 (psubsb, Gx, Ex), - _2 (psubsw, Gx, Ex), - _2 (pminsw, Gx, Ex), - _2 (por, Gx, Ex), - _2 (paddsb, Gx, Ex), - _2 (paddsw, Gx, Ex), - _2 (pmaxsw, Gx, Ex), - _2 (pxor, Gx, Ex), - }, - - [X86_INSN_SSE_GROUP_f0].insns = { - _0 (bad), - _2 (psllw, Gx, Ex), - _2 (pslld, Gx, Ex), - _2 (psllq, Gx, Ex), - _2 (pmuludq, Gx, Ex), - _2 (pmaddwd, Gx, Ex), - _2 (psadbw, Gx, Ex), - _2 (maskmovdqu, Gx, Ex), - }, - - [X86_INSN_SSE_GROUP_f8].insns = { - _2 (psubb, Gx, Ex), - _2 (psubw, Gx, Ex), - _2 (psubd, Gx, Ex), - _2 (psubq, Gx, Ex), - _2 (paddb, Gx, Ex), - _2 (paddw, Gx, Ex), - _2 (paddd, Gx, Ex), - _0 (bad), - }, -}; - -static x86_insn_group8_t x86_insn_sse_groups_repnz[] = { - [X86_INSN_SSE_GROUP_10].insns = { - _2 (movsd, Gx, Ex), - _2 (movsd, Ex, Gx), - _2 (movddup, Gx, Ex), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - }, - - [X86_INSN_SSE_GROUP_28].insns = { - _0 (bad), - _0 (bad), - _2 (cvtsi2sd, Gx, Ev), - _0 (bad), - _2 (cvttsd2si, Gv, Ex), - _2 (cvtsd2si, Gv, Ex), - _0 (bad), - _0 (bad), - }, - - [X86_INSN_SSE_GROUP_50].insns = { - _0 (bad), - _2 (sqrtsd, Gx, Ex), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - }, - - [X86_INSN_SSE_GROUP_58].insns = { - _2 (addsd, Gx, Ex), - _2 (mulsd, Gx, Ex), - _2 (cvtsd2ss, Gx, Ex), - _0 (bad), - _2 (subsd, Gx, Ex), - _2 (minsd, Gx, Ex), - _2 (divsd, Gx, Ex), - _2 (maxsd, Gx, Ex), - }, - - [X86_INSN_SSE_GROUP_60].insns = { - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - }, - - [X86_INSN_SSE_GROUP_68].insns = { - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - }, - - [X86_INSN_SSE_GROUP_70].insns = { - _3 (pshuflw, Gx, Ex, Ib), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - }, - - [X86_INSN_SSE_GROUP_78].insns = { - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _2 (haddps, Gx, Ex), - _2 (hsubps, Gx, Ex), - _0 (bad), - _0 (bad), - }, - - [X86_INSN_SSE_GROUP_c0].insns = { - _0 (bad), - _0 (bad), - _3 (cmpsd, Gx, Ex, Ib), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - }, - - [X86_INSN_SSE_GROUP_d0].insns = { - _2 (addsubps, Gx, Ex), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _2 (movdq2q, Gm, Ex), - _0 (bad), - }, - - [X86_INSN_SSE_GROUP_d8].insns = { - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - }, - - [X86_INSN_SSE_GROUP_e0].insns = { - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _2 (cvtpd2dq, Gx, Ex), - _0 (bad), - }, - - [X86_INSN_SSE_GROUP_e8].insns = { - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - }, - - [X86_INSN_SSE_GROUP_f0].insns = { - _2 (lddqu, Gx, Mx), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - }, - - [X86_INSN_SSE_GROUP_f8].insns = { - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - _0 (bad), - }, -}; - -#undef _ - -/* Parses memory displacements and immediates. */ -static u8 * x86_insn_parse_number (u32 log2_n_bytes, - u8 * code, u8 * code_end, - i64 * result) -{ - i64 x = 0; - - if (code + (1 << log2_n_bytes) > code_end) - return 0; - - switch (log2_n_bytes) - { - case 3: - x = clib_little_to_host_unaligned_mem_u64 ((u64 *) code); - break; - - case 2: - x = (i32) clib_little_to_host_unaligned_mem_u32 ((u32 *) code); - break; - - case 1: - x = (i16) clib_little_to_host_unaligned_mem_u16 ((u16 *) code); - break; - - case 0: - x = (i8) code[0]; - break; - - default: - ASSERT (0); - } - - *result = x; - return code + (1 << log2_n_bytes); -} - -static u32 -x86_insn_log2_immediate_bytes (x86_insn_parse_t * p, x86_insn_t * insn) -{ - u32 i = ~0; - switch (x86_insn_immediate_type (insn)) - { - case 'b': i = 0; break; - case 'w': i = 1; break; - case 'd': i = 2; break; - case 'q': i = 3; break; - - case 'z': - i = p->log2_effective_operand_bytes; - if (i > 2) i = 2; - break; - - case 'v': - i = p->log2_effective_operand_bytes; - break; - - default: - i = ~0; - break; - } - - return i; -} - -static u8 * -x86_insn_parse_modrm_byte (x86_insn_parse_t * x, - x86_insn_modrm_byte_t modrm, - u32 parse_flags, - u8 * code, - u8 * code_end) -{ - u8 effective_address_bits; - - if (parse_flags & X86_INSN_PARSE_64_BIT) - effective_address_bits = (x->flags & X86_INSN_ADDRESS_SIZE) ? 32 : 64; - else if (parse_flags & X86_INSN_PARSE_32_BIT) - effective_address_bits = (x->flags & X86_INSN_ADDRESS_SIZE) ? 16 : 32; - else - effective_address_bits = (x->flags & X86_INSN_ADDRESS_SIZE) ? 32 : 16; - - x->log2_effective_address_bytes = 1; - x->log2_effective_address_bytes += effective_address_bits > 16; - x->log2_effective_address_bytes += effective_address_bits > 32; - - x->regs[0] |= modrm.reg; - if (modrm.mode == 3) - x->regs[1] |= modrm.rm; - else - { - u32 log2_disp_bytes = ~0; - - x->flags |= X86_INSN_IS_ADDRESS; - - if (effective_address_bits != 16) - { - u8 has_sib_byte = 0; - - switch (modrm.mode) - { - case 0: - /* When base is bp displacement is present for mode 0. */ - if (modrm.rm == X86_INSN_GP_REG_BP) - { - log2_disp_bytes = x->log2_effective_address_bytes; - break; - } - else if (modrm.rm == X86_INSN_GP_REG_SP - && effective_address_bits != 16) - { - has_sib_byte = 1; - break; - } - /* fall through */ - case 1: - case 2: - x->regs[1] |= modrm.rm; - x->flags |= X86_INSN_HAS_BASE; - if (modrm.mode != 0) - { - log2_disp_bytes = (modrm.mode == 1 - ? 0 - : x->log2_effective_address_bytes); - if (log2_disp_bytes > 2) - log2_disp_bytes = 2; - } - break; - } - - if (has_sib_byte) - { - x86_insn_sib_byte_t sib; - - if (code >= code_end) - return 0; - sib.byte = *code++; - - x->log2_index_scale = 1 << sib.log2_scale; - x->regs[1] |= sib.base; - x->flags |= X86_INSN_HAS_BASE; - - if (sib.index != X86_INSN_GP_REG_SP) - { - x->regs[2] |= sib.index; - x->flags |= X86_INSN_HAS_INDEX; - } - } - } - else - { - /* effective_address_bits == 16 */ - switch (modrm.mode) - { - case 0: - if (modrm.rm == 6) - { - /* [disp16] */ - log2_disp_bytes = 1; - break; - } - /* fall through */ - case 1: - case 2: - switch (modrm.rm) - { - case 0: /* [bx + si/di] */ - case 1: - x->regs[1] = X86_INSN_GP_REG_BX; - x->regs[2] = X86_INSN_GP_REG_SI + (modrm.rm & 1); - x->flags |= X86_INSN_HAS_BASE | X86_INSN_HAS_INDEX; - break; - - case 2: /* [bp + si/di] */ - case 3: - x->regs[1] = X86_INSN_GP_REG_BP; - x->regs[2] = X86_INSN_GP_REG_SI + (modrm.rm & 1); - x->flags |= X86_INSN_HAS_BASE | X86_INSN_HAS_INDEX; - break; - - case 4: /* [si/di] */ - case 5: - x->regs[1] = X86_INSN_GP_REG_SI + (modrm.rm & 1); - x->flags |= X86_INSN_HAS_BASE; - break; - - case 6: /* [bp + disp] */ - x->regs[1] = X86_INSN_GP_REG_BP; - x->flags |= X86_INSN_HAS_BASE; - break; - - case 7: /* [bx + disp] */ - x->regs[1] = X86_INSN_GP_REG_BX; - x->flags |= X86_INSN_HAS_BASE; - break; - } - - if (modrm.mode != 0) - log2_disp_bytes = modrm.mode == 1 ? 0 : 1; - break; - } - } - - if (log2_disp_bytes != ~0) - { - i64 disp; - code = x86_insn_parse_number (log2_disp_bytes, code, code_end, - &disp); - if (code) - x->displacement = disp; - } - } - - return code; -} - -u8 * x86_insn_parse (x86_insn_parse_t * p, u8 * code_start) -{ - u8 i, * code, * code_end; - x86_insn_t * insn, * group_insn; - u8 default_operand_bits, effective_operand_bits; - u32 opcode, parse_flags; - - /* Preserve global parse flags. */ - parse_flags = p->flags & (X86_INSN_PARSE_32_BIT | X86_INSN_PARSE_64_BIT); - memset (p, 0, sizeof (p[0])); - p->flags = parse_flags; - - /* 64 implies 32 bit parsing. */ - if (parse_flags & X86_INSN_PARSE_64_BIT) - parse_flags |= X86_INSN_PARSE_32_BIT; - - /* Instruction must be <= 15 bytes. */ - code = code_start; - code_end = code + 15; - - /* Parse legacy prefixes. */ - while (1) - { - if (code >= code_end) - goto insn_too_long; - i = code[0]; - code++; - switch (i) - { - default: goto prefix_done; - - /* Set flags based on prefix. */ -#define _(x,o) case o: p->flags |= X86_INSN_##x; break; - foreach_x86_legacy_prefix; -#undef _ - } - } - prefix_done: - - /* REX prefix. */ - if ((parse_flags & X86_INSN_PARSE_64_BIT) && i >= 0x40 && i <= 0x4f) - { - p->regs[0] |= ((i & (1 << 2)) != 0) << 3; /* r bit */ - p->regs[1] |= ((i & (1 << 0)) != 0) << 3; /* b bit */ - p->regs[2] |= ((i & (1 << 1)) != 0) << 3; /* x bit */ - p->flags |= ((i & (1 << 3)) /* w bit */ - ? X86_INSN_OPERAND_SIZE_64 : 0); - if (code >= code_end) - goto insn_too_long; - i = *code++; - } - - opcode = i; - if (opcode == 0x0f) - { - /* two byte opcode. */; - if (code >= code_end) - goto insn_too_long; - i = *code++; - opcode = (opcode << 8) | i; - insn = x86_insns_two_byte + i; - } - else - { - static x86_insn_t arpl = { - .name = "arpl", - .operands[0].data = "Ew", - .operands[1].data = "Gw", - }; - - if (PREDICT_FALSE (i == 0x63 - && ! (parse_flags & X86_INSN_PARSE_64_BIT))) - insn = &arpl; - else - insn = x86_insns_one_byte + i; - } - - if ((i = X86_INSN_FLAG_GET_SSE_GROUP (insn->flags)) != 0) - { - x86_insn_group8_t * g8; - - if (p->flags & X86_INSN_OPERAND_SIZE) - g8 = x86_insn_sse_groups_operand_size; - else if (p->flags & X86_INSN_REPZ) - g8 = x86_insn_sse_groups_repz; - else if (p->flags & X86_INSN_REPNZ) - g8 = x86_insn_sse_groups_repnz; - else - g8 = 0; - - /* insn flags have 1 + group so != 0 test above can work. */ - ASSERT ((i - 1) < ARRAY_LEN (x86_insn_sse_groups_operand_size)); - if (g8) - insn = g8[i - 1].insns + (opcode & 7); - } - - /* Parse modrm and displacement if present. */ - if (x86_insn_has_modrm_byte (insn)) - { - x86_insn_modrm_byte_t modrm; - - if (code >= code_end) - goto insn_too_long; - modrm.byte = *code++; - - /* Handle special 0x0f01 and 0x0fae encodings. */ - if (PREDICT_FALSE (modrm.mode == 3 - && (opcode == 0x0f01 - || opcode == 0x0fae))) - { - static x86_insn_t x86_insns_0f01_special[] = { - _0 (swapgs), _0 (rdtscp), _0 (bad), _0 (bad), - _0 (bad), _0 (bad), _0 (bad), _0 (bad), - }; - static x86_insn_t x86_insns_0fae_special[] = { - _0 (vmrun), _0 (vmmcall), _0 (vmload), _0 (vmsave), - _0 (stgi), _0 (clgi), _0 (skinit), _0 (invlpga), - }; - - if (opcode == 0x0f01) - insn = x86_insns_0f01_special; - else - insn = x86_insns_0fae_special; - insn += modrm.rm; - opcode = (opcode << 8) | modrm.byte; - } - else - { - code = x86_insn_parse_modrm_byte (p, modrm, parse_flags, - code, code_end); - if (! code) - goto insn_too_long; - } - } - - group_insn = 0; - if ((i = X86_INSN_FLAG_GET_MODRM_REG_GROUP (insn->flags)) != 0) - { - u32 g = i - 1; - ASSERT (g < ARRAY_LEN (x86_insn_modrm_reg_groups)); - group_insn = x86_insn_modrm_reg_groups[g].insns + (p->regs[0] & 7); - } - - p->insn = insn[0]; - if (group_insn) - { - u32 k; - p->insn.name = group_insn->name; - p->insn.flags |= group_insn->flags; - for (k = 0; k < ARRAY_LEN (group_insn->operands); k++) - if (x86_insn_operand_is_valid (group_insn, k)) - p->insn.operands[k] = group_insn->operands[k]; - } - - default_operand_bits - = ((((parse_flags & X86_INSN_PARSE_32_BIT) != 0) - ^ ((p->flags & X86_INSN_OPERAND_SIZE) != 0)) - ? BITS (u32) : BITS (u16)); - - if ((parse_flags & X86_INSN_PARSE_64_BIT) - && (p->insn.flags & X86_INSN_FLAG_DEFAULT_64_BIT)) - default_operand_bits = BITS (u64); - - effective_operand_bits = default_operand_bits; - if (p->flags & X86_INSN_OPERAND_SIZE_64) - effective_operand_bits = BITS (u64); - - p->log2_effective_operand_bytes = 1; - p->log2_effective_operand_bytes += effective_operand_bits > 16; - p->log2_effective_operand_bytes += effective_operand_bits > 32; - - /* Parse immediate if present. */ - { - u32 l = x86_insn_log2_immediate_bytes (p, insn); - if (l <= 3) - { - code = x86_insn_parse_number (l, code, code_end, &p->immediate); - if (! code) - goto insn_too_long; - } - } - - return code; - - insn_too_long: - return 0; -} - -static u8 * format_x86_gp_reg_operand (u8 * s, va_list * va) -{ - u32 r = va_arg (*va, u32); - u32 log2_n_bytes = va_arg (*va, u32); - - const char names8[8] = "acdbsbsd"; - const char names16[8] = "xxxxppii"; - - ASSERT (r < 16); - - /* Add % register prefix. */ - vec_add1 (s, '%'); - - switch (log2_n_bytes) - { - case 0: - { - - if (r < 8) - s = format (s, "%c%c", names8[r & 3], (r >> 2) ? 'l' : 'h'); - else - s = format (s, "r%db", r); - } - break; - - case 2: - case 3: - s = format (s, "%c", log2_n_bytes == 2 ? 'e' : 'r'); - /* fall through */ - case 1: - if (r < 8) - s = format (s, "%c%c", names8[r], names16[r]); - else - { - s = format (s, "%d", r); - if (log2_n_bytes != 3) - s = format (s, "%c", log2_n_bytes == 1 ? 'w' : 'd'); - } - break; - - default: - ASSERT (0); - } - - return s; -} - -static u8 * format_x86_reg_operand (u8 * s, va_list * va) -{ - u32 reg = va_arg (*va, u32); - u32 log2_n_bytes = va_arg (*va, u32); - u32 type = va_arg (*va, u32); - - switch (type) - { - default: - ASSERT (0); - break; - - case 'x': - ASSERT (reg < 16); - return format (s, "%%xmm%d", reg); - - case 'm': - ASSERT (reg < 8); - return format (s, "%%mm%d", reg); - - /* Explicit byte/word/double-word/quad-word */ - case 'b': log2_n_bytes = 0; break; - case 'w': log2_n_bytes = 1; break; - case 'd': log2_n_bytes = 2; break; - case 'q': log2_n_bytes = 3; break; - - /* Use effective operand size. */ - case 'v': break; - - /* word or double-word depending on effective operand size. */ - case 'z': - log2_n_bytes = clib_min (log2_n_bytes, 2); - break; - } - - s = format (s, "%U", format_x86_gp_reg_operand, reg, log2_n_bytes); - return s; -} - -static u8 * format_x86_mem_operand (u8 * s, va_list * va) -{ - x86_insn_parse_t * p = va_arg (*va, x86_insn_parse_t *); - - if (p->displacement != 0) - s = format (s, "0x%x", p->displacement); - - if (p->flags & X86_INSN_HAS_BASE) - { - s = format (s, "(%U", - format_x86_gp_reg_operand, p->regs[1], - p->log2_effective_address_bytes); - if (p->flags & X86_INSN_HAS_INDEX) - { - s = format (s, ",%U", - format_x86_gp_reg_operand, p->regs[2], - p->log2_effective_address_bytes); - if (p->log2_index_scale != 0) - s = format (s, ",%d", 1 << p->log2_index_scale); - } - s = format (s, ")"); - } - - /* [RIP+disp] PC relative addressing in 64 bit mode. */ - else if (p->flags & X86_INSN_PARSE_64_BIT) - s = format (s, "(%%rip)"); - - return s; -} - -static u8 * format_x86_insn_operand (u8 * s, va_list * va) -{ - x86_insn_parse_t * p = va_arg (*va, x86_insn_parse_t *); - x86_insn_t * insn = &p->insn; - u32 o = va_arg (*va, u32); - u8 c, t; - - ASSERT (o < ARRAY_LEN (insn->operands)); - c = insn->operands[o].code; - t = insn->operands[o].type; - - /* Register encoded in instruction. */ - if (c < 8) - return format (s, "%U", - format_x86_gp_reg_operand, c, - p->log2_effective_operand_bytes); - - switch (c) - { - /* Memory or reg field from modrm byte. */ - case 'M': - ASSERT (p->flags & X86_INSN_IS_ADDRESS); - /* FALLTHROUGH */ - case 'E': - if (p->flags & X86_INSN_IS_ADDRESS) - s = format (s, "%U", format_x86_mem_operand, p); - else - s = format (s, "%U", - format_x86_reg_operand, p->regs[1], - p->log2_effective_operand_bytes, t); - break; - - /* reg field from modrm byte. */ - case 'R': - case 'G': - s = format (s, "%U", - format_x86_reg_operand, p->regs[0], - p->log2_effective_operand_bytes, t); - break; - - case 'I': - { - u32 l = x86_insn_log2_immediate_bytes (p, insn); - i64 mask = pow2_mask (8ULL << l); - s = format (s, "$0x%Lx", p->immediate & mask); - } - break; - - case 'J': - if (p->immediate < 0) - s = format (s, "- 0x%Lx", -p->immediate); - else - s = format (s, "+ 0x%Lx", p->immediate); - break; - - case 'O': - s = format (s, "0x%Lx", p->immediate); - break; - - case 'A': - /* AX/AL */ - s = format (s, "%U", - format_x86_gp_reg_operand, X86_INSN_GP_REG_AX, - t == 'L' ? 0 : p->log2_effective_operand_bytes); - break; - - case 'B': - /* BX/BL/BP */ - s = format (s, "%U", - format_x86_gp_reg_operand, - t == 'P' ? X86_INSN_GP_REG_BP : X86_INSN_GP_REG_BX, - t == 'L' ? 0 : p->log2_effective_operand_bytes); - break; - - case 'C': - /* CX/CL */ - s = format (s, "%U", - format_x86_gp_reg_operand, X86_INSN_GP_REG_CX, - t == 'L' ? 0 : p->log2_effective_operand_bytes); - break; - - case 'D': - /* DX/DL/DI */ - s = format (s, "%U", - format_x86_gp_reg_operand, - t == 'I' ? X86_INSN_GP_REG_DI : X86_INSN_GP_REG_DX, - t == 'L' ? 0 : p->log2_effective_operand_bytes); - break; - - case 'S': - /* SI/SP */ - s = format (s, "%U", - format_x86_gp_reg_operand, - t == 'I' ? X86_INSN_GP_REG_SI : X86_INSN_GP_REG_SP, - p->log2_effective_operand_bytes); - break; - - case '1': - s = format (s, "1"); - break; - - default: - ASSERT (0); - } - - return s; -} - -u8 * format_x86_insn_parse (u8 * s, va_list * va) -{ - x86_insn_parse_t * p = va_arg (*va, x86_insn_parse_t *); - x86_insn_t * insn = &p->insn; - u32 o, i, is_src_dst; - - s = format (s, "%s", insn->name); - - if (! x86_insn_operand_is_valid (insn, 0)) - goto done; - - is_src_dst = x86_insn_operand_is_valid (insn, 1); - - /* If instruction has immediate add suffix to opcode to - indicate operand size. */ - if (is_src_dst) - { - u32 b; - - b = x86_insn_log2_immediate_bytes (p, insn); - if (b < p->log2_effective_operand_bytes - && (p->flags & X86_INSN_IS_ADDRESS)) - s = format (s, "%c", "bwlq"[b]); - } - - for (i = 0; i < ARRAY_LEN (insn->operands); i++) - { - o = is_src_dst + i; - if (! x86_insn_operand_is_valid (insn, o)) - break; - s = format (s, "%s%U", - i == 0 ? " " : ", ", - format_x86_insn_operand, p, o); - } - - if (is_src_dst) - s = format (s, ", %U", - format_x86_insn_operand, p, 0); - - done: - return s; -} diff --git a/vppinfra/vppinfra/asm_x86.h b/vppinfra/vppinfra/asm_x86.h deleted file mode 100644 index dacef61755c..00000000000 --- a/vppinfra/vppinfra/asm_x86.h +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef included_asm_x86_h -#define included_asm_x86_h - -#include <vppinfra/format.h> - -typedef union -{ - struct - { - u8 code; - u8 type; - }; - u8 data[2]; -} x86_insn_operand_t; - -typedef struct -{ - /* Instruction name. */ - char *name; - - /* X86 instructions may have up to 3 operands. */ - x86_insn_operand_t operands[3]; - - u16 flags; -#define X86_INSN_FLAG_DEFAULT_64_BIT (1 << 0) -#define X86_INSN_FLAG_SET_SSE_GROUP(n) ((n) << 5) -#define X86_INSN_FLAG_GET_SSE_GROUP(f) (((f) >> 5) & 0x1f) -#define X86_INSN_FLAG_SET_MODRM_REG_GROUP(n) (((n) & 0x3f) << 10) -#define X86_INSN_FLAG_GET_MODRM_REG_GROUP(f) (((f) >> 10) & 0x3f) -} x86_insn_t; - -always_inline uword -x86_insn_operand_is_valid (x86_insn_t * i, uword o) -{ - ASSERT (o < ARRAY_LEN (i->operands)); - return i->operands[o].code != '_'; -} - -#define foreach_x86_legacy_prefix \ - _ (OPERAND_SIZE, 0x66) \ - _ (ADDRESS_SIZE, 0x67) \ - _ (SEGMENT_CS, 0x2e) \ - _ (SEGMENT_DS, 0x3e) \ - _ (SEGMENT_ES, 0x26) \ - _ (SEGMENT_FS, 0x64) \ - _ (SEGMENT_GS, 0x65) \ - _ (SEGMENT_SS, 0x36) \ - _ (LOCK, 0xf0) \ - _ (REPZ, 0xf3) \ - _ (REPNZ, 0xf2) - -#define foreach_x86_insn_parse_flag \ - /* Parse in 32/64-bit mode. */ \ - _ (PARSE_32_BIT, 0) \ - _ (PARSE_64_BIT, 0) \ - _ (IS_ADDRESS, 0) \ - /* regs[1/2] is a valid base/index register */ \ - _ (HAS_BASE, 0) \ - _ (HAS_INDEX, 0) \ - /* rex w bit */ \ - _ (OPERAND_SIZE_64, 0) - -typedef enum -{ -#define _(f,o) X86_INSN_FLAG_BIT_##f, - foreach_x86_insn_parse_flag foreach_x86_legacy_prefix -#undef _ -} x86_insn_parse_flag_bit_t; - -typedef enum -{ -#define _(f,o) X86_INSN_##f = 1 << X86_INSN_FLAG_BIT_##f, - foreach_x86_insn_parse_flag foreach_x86_legacy_prefix -#undef _ -} x86_insn_parse_flag_t; - -typedef struct -{ - /* Registers in instruction. - [0] is modrm reg field - [1] is base reg - [2] is index reg. */ - u8 regs[3]; - - /* Scale for index register. */ - u8 log2_index_scale:2; - u8 log2_effective_operand_bytes:3; - u8 log2_effective_address_bytes:3; - - i32 displacement; - - /* Parser flags: set of x86_insn_parse_flag_t enums. */ - u32 flags; - - i64 immediate; - - x86_insn_t insn; -} x86_insn_parse_t; - -u8 *x86_insn_parse (x86_insn_parse_t * p, u8 * code_start); -format_function_t format_x86_insn_parse; - -#endif /* included_asm_x86_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/backtrace.c b/vppinfra/vppinfra/backtrace.c deleted file mode 100644 index bbfb792c656..00000000000 --- a/vppinfra/vppinfra/backtrace.c +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2004 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include <vppinfra/clib.h> -#include <vppinfra/error.h> - -#ifdef __mips__ - -/* Let code below know we've defined _clib_backtrace */ -#define clib_backtrace_defined - -#include <vppinfra/asm_mips.h> - -uword -clib_backtrace (uword * callers, uword max_callers, uword n_frames_to_skip) -{ - u32 *pc; - void *sp; - uword i, saved_pc; - - /* Figure current PC, saved PC and stack pointer. */ - asm volatile (".set push\n" - ".set noat\n" "move %[saved_pc], $31\n" "move %[sp], $29\n" - /* Fetches current PC. */ - "la $at, 1f\n" - "jalr %[pc], $at\n" - "nop\n" - "1:\n" - ".set pop\n":[pc] "=r" (pc), - [saved_pc] "=r" (saved_pc),[sp] "=r" (sp)); - - /* Also skip current frame. */ - n_frames_to_skip += 1; - - for (i = 0; i < max_callers + n_frames_to_skip; i++) - { - mips_insn_opcode_t op; - mips_insn_special_funct_t funct; - i32 insn, rs, rt, rd, immediate, found_saved_pc; - u32 *start_pc; - - /* Parse instructions until we reach prologue for this - stack frame. We'll need to figure out where saved - PC is and where previous stack frame lives. */ - start_pc = pc; - found_saved_pc = 0; - while (1) - { - insn = *--pc; - op = mips_insn_get_op (insn); - funct = mips_insn_get_funct (insn); - rs = mips_insn_get_rs (insn); - rt = mips_insn_get_rt (insn); - rd = mips_insn_get_rd (insn); - immediate = mips_insn_get_immediate (insn); - - switch (op) - { - default: - break; - - case MIPS_OPCODE_sd: - case MIPS_OPCODE_sw: - /* Trace stores of return address. */ - if (rt == MIPS_REG_RA) - { - void *addr = sp + immediate; - - /* If RA is stored somewhere other than in the - stack frame, give up. */ - if (rs != MIPS_REG_SP) - goto backtrace_done; - - ASSERT (immediate % 4 == 0); - if (op == MIPS_OPCODE_sw) - saved_pc = ((u32 *) addr)[0]; - else - saved_pc = ((u64 *) addr)[0]; - found_saved_pc = 1; - } - break; - - case MIPS_OPCODE_addiu: - case MIPS_OPCODE_daddiu: - case MIPS_OPCODE_addi: - case MIPS_OPCODE_daddi: - if (rt == MIPS_REG_SP) - { - if (rs != MIPS_REG_SP) - goto backtrace_done; - - ASSERT (immediate % 4 == 0); - - /* Assume positive offset is part of the epilogue. - E.g. - jr ra - add sp,sp,100 - */ - if (immediate > 0) - continue; - - /* Negative offset means allocate stack space. - This could either be the prologue or could be due to - alloca. */ - sp -= immediate; - - /* This frame will not save RA. */ - if (i == 0) - goto found_prologue; - - /* Assume that addiu sp,sp,-N without store of ra means - that we have not found the prologue yet. */ - if (found_saved_pc) - goto found_prologue; - } - break; - - case MIPS_OPCODE_slti: - case MIPS_OPCODE_sltiu: - case MIPS_OPCODE_andi: - case MIPS_OPCODE_ori: - case MIPS_OPCODE_xori: - case MIPS_OPCODE_lui: - case MIPS_OPCODE_ldl: - case MIPS_OPCODE_ldr: - case MIPS_OPCODE_lb: - case MIPS_OPCODE_lh: - case MIPS_OPCODE_lwl: - case MIPS_OPCODE_lw: - case MIPS_OPCODE_lbu: - case MIPS_OPCODE_lhu: - case MIPS_OPCODE_lwr: - case MIPS_OPCODE_lwu: - case MIPS_OPCODE_ld: - /* Give up when we find anyone setting the stack pointer. */ - if (rt == MIPS_REG_SP) - goto backtrace_done; - break; - - case MIPS_OPCODE_SPECIAL: - if (rd == MIPS_REG_SP) - switch (funct) - { - default: - /* Give up when we find anyone setting the stack pointer. */ - goto backtrace_done; - - case MIPS_SPECIAL_FUNCT_break: - case MIPS_SPECIAL_FUNCT_jr: - case MIPS_SPECIAL_FUNCT_sync: - case MIPS_SPECIAL_FUNCT_syscall: - case MIPS_SPECIAL_FUNCT_tge: - case MIPS_SPECIAL_FUNCT_tgeu: - case MIPS_SPECIAL_FUNCT_tlt: - case MIPS_SPECIAL_FUNCT_tltu: - case MIPS_SPECIAL_FUNCT_teq: - case MIPS_SPECIAL_FUNCT_tne: - /* These instructions can validly have rd == MIPS_REG_SP */ - break; - } - break; - } - } - - found_prologue: - /* Check sanity of saved pc. */ - if (saved_pc & 3) - goto backtrace_done; - if (saved_pc == 0) - goto backtrace_done; - - if (i >= n_frames_to_skip) - callers[i - n_frames_to_skip] = saved_pc; - pc = uword_to_pointer (saved_pc, u32 *); - } - -backtrace_done: - if (i < n_frames_to_skip) - return 0; - else - return i - n_frames_to_skip; -} -#endif /* __mips__ */ - -#ifndef clib_backtrace_defined -#define clib_backtrace_defined - -typedef struct clib_generic_stack_frame_t -{ - struct clib_generic_stack_frame_t *prev; - void *return_address; -} clib_generic_stack_frame_t; - -/* This will only work if we have a frame pointer. - Without a frame pointer we have to parse the machine code to - parse the stack frames. */ -uword -clib_backtrace (uword * callers, uword max_callers, uword n_frames_to_skip) -{ - clib_generic_stack_frame_t *f; - uword i; - - f = __builtin_frame_address (0); - - /* Also skip current frame. */ - n_frames_to_skip += 1; - - for (i = 0; i < max_callers + n_frames_to_skip; i++) - { - f = f->prev; - if (!f) - goto backtrace_done; - if (clib_abs ((void *) f - (void *) f->prev) > (64 * 1024)) - goto backtrace_done; - if (i >= n_frames_to_skip) - callers[i - n_frames_to_skip] = pointer_to_uword (f->return_address); - } - -backtrace_done: - if (i < n_frames_to_skip) - return 0; - else - return i - n_frames_to_skip; -} -#endif /* clib_backtrace_defined */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/bihash_24_8.h b/vppinfra/vppinfra/bihash_24_8.h deleted file mode 100644 index 353f06bf11f..00000000000 --- a/vppinfra/vppinfra/bihash_24_8.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#undef BIHASH_TYPE - -#define BIHASH_TYPE _24_8 -#define BIHASH_KVP_PER_PAGE 4 - -#ifndef __included_bihash_24_8_h__ -#define __included_bihash_24_8_h__ - -#include <vppinfra/heap.h> -#include <vppinfra/format.h> -#include <vppinfra/pool.h> -#include <vppinfra/xxhash.h> - -typedef struct -{ - u64 key[3]; - u64 value; -} clib_bihash_kv_24_8_t; - -static inline int -clib_bihash_is_free_24_8 (const clib_bihash_kv_24_8_t * v) -{ - /* Free values are memset to 0xff, check a bit... */ - if (v->key[0] == ~0ULL && v->value == ~0ULL) - return 1; - return 0; -} - -static inline u64 -clib_bihash_hash_24_8 (const clib_bihash_kv_24_8_t * v) -{ -#if __SSE4_2__ - u32 value = 0; - value = _mm_crc32_u64 (value, v->key[0]); - value = _mm_crc32_u64 (value, v->key[1]); - value = _mm_crc32_u64 (value, v->key[2]); - return value; -#else - u64 tmp = v->key[0] ^ v->key[1] ^ v->key[2]; - return clib_xxhash (tmp); -#endif -} - -static inline u8 * -format_bihash_kvp_24_8 (u8 * s, va_list * args) -{ - clib_bihash_kv_24_8_t *v = va_arg (*args, clib_bihash_kv_24_8_t *); - - s = format (s, "key %llu %llu %llu value %llu", - v->key[0], v->key[1], v->key[2], v->value); - return s; -} - -static inline int -clib_bihash_key_compare_24_8 (const u64 * a, const u64 * b) -{ - return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2])) == 0; -} - -#undef __included_bihash_template_h__ -#include <vppinfra/bihash_template.h> - -#endif /* __included_bihash_24_8_h__ */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/bihash_8_8.h b/vppinfra/vppinfra/bihash_8_8.h deleted file mode 100644 index a0d6df2e4c8..00000000000 --- a/vppinfra/vppinfra/bihash_8_8.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#undef BIHASH_TYPE - -#define BIHASH_TYPE _8_8 -#define BIHASH_KVP_PER_PAGE 4 - -#ifndef __included_bihash_8_8_h__ -#define __included_bihash_8_8_h__ - -#include <vppinfra/heap.h> -#include <vppinfra/format.h> -#include <vppinfra/pool.h> -#include <vppinfra/xxhash.h> - -#if __SSE4_2__ -#include <x86intrin.h> -#endif - -/** 8 octet key, 8 octet key value pair */ -typedef struct -{ - u64 key; /**< the key */ - u64 value; /**< the value */ -} clib_bihash_kv_8_8_t; - -/** Decide if a clib_bihash_kv_8_8_t instance is free - @param v- pointer to the (key,value) pair -*/ -static inline int -clib_bihash_is_free_8_8 (clib_bihash_kv_8_8_t * v) -{ - if (v->key == ~0ULL && v->value == ~0ULL) - return 1; - return 0; -} - -/** Hash a clib_bihash_kv_8_8_t instance - @param v - pointer to the (key,value) pair, hash the key (only) -*/ -static inline u64 -clib_bihash_hash_8_8 (clib_bihash_kv_8_8_t * v) -{ -#if __SSE4_2__ - return _mm_crc32_u64 (0, v->key); -#else - return clib_xxhash (v->key); -#endif -} - -/** Format a clib_bihash_kv_8_8_t instance - @param s - u8 * vector under construction - @param args (vararg) - the (key,value) pair to format - @return s - the u8 * vector under construction -*/ -static inline u8 * -format_bihash_kvp_8_8 (u8 * s, va_list * args) -{ - clib_bihash_kv_8_8_t *v = va_arg (*args, clib_bihash_kv_8_8_t *); - - s = format (s, "key %llu value %llu", v->key, v->value); - return s; -} - -/** Compare two clib_bihash_kv_8_8_t instances - @param a - first key - @param b - second key -*/ -static inline int -clib_bihash_key_compare_8_8 (u64 a, u64 b) -{ - return a == b; -} - -#undef __included_bihash_template_h__ -#include <vppinfra/bihash_template.h> - -#endif /* __included_bihash_8_8_h__ */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/bihash_doc.h b/vppinfra/vppinfra/bihash_doc.h deleted file mode 100644 index e6ab9db6d30..00000000000 --- a/vppinfra/vppinfra/bihash_doc.h +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (c) 2014 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. -*/ - -#error do not #include this file! - -/** \file - - Bounded-index extensible hashing. The basic algorithm performs - thread-safe constant-time lookups in the face of a rational number - of hash collisions. The computed hash code h(k) must have - reasonable statistics with respect to the key space. It won't do - to have h(k) = 0 or 1, for all values of k. - - Each bucket in the power-of-two bucket array contains the index - (in a private vppinfra memory heap) of the "backing store" for the - bucket, as well as a size field. The size field (log2_pages) - corresponds to 1, 2, 4, ... contiguous "pages" containing the - (key,value) pairs in the bucket. - - When a single page fills, we allocate two contiguous pages. We - recompute h(k) for each (key,value) pair, using an additional bit - to deal the (key, value) pairs into the "top" and "bottom" pages. - - At lookup time, we compute h(k), using lg(bucket-array-size) to - pick the bucket. We read the bucket to find the base of the - backing pages. We use an additional log2_pages' worth of bits - from h(k) to compute the offset of the page which will contain the - (key,value) pair we're trying to find. -*/ - -/** template key/value backing page structure */ -typedef struct clib_bihash_value -{ - union - { - - clib_bihash_kv kvp[BIHASH_KVP_PER_PAGE]; /**< the actual key/value pairs */ - clib_bihash_value *next_free; /**< used when a KVP page (or block thereof) is on a freelist */ - }; -} clib_bihash_value_t -/** bihash bucket structure */ - typedef struct -{ - union - { - struct - { - u32 offset; /**< backing page offset in the clib memory heap */ - u8 pad[3]; /**< log2 (size of the packing page block) */ - u8 log2_pages; - }; - u64 as_u64; - }; -} clib_bihash_bucket_t; - -/** A bounded index extensible hash table */ -typedef struct -{ - clib_bihash_bucket_t *buckets; /**< Hash bucket vector, power-of-two in size */ - volatile u32 *writer_lock; /**< Writer lock, in its own cache line */ - BVT (clib_bihash_value) ** working_copies; - /**< Working copies (various sizes), to avoid locking against readers */ - clib_bihash_bucket_t saved_bucket; /**< Saved bucket pointer */ - u32 nbuckets; /**< Number of hash buckets */ - u32 log2_nbuckets; /**< lg(nbuckets) */ - u8 *name; /**< hash table name */ - BVT (clib_bihash_value) ** freelists; - /**< power of two freelist vector */ - void *mheap; /**< clib memory heap */ -} clib_bihash_t; - -/** Get pointer to value page given its clib mheap offset */ -static inline void *clib_bihash_get_value (clib_bihash * h, uword offset); - -/** Get clib mheap offset given a pointer */ -static inline uword clib_bihash_get_offset (clib_bihash * h, void *v); - -/** initialize a bounded index extensible hash table - - @param h - the bi-hash table to initialize - @param name - name of the hash table - @param nbuckets - the number of buckets, will be rounded up to -a power of two - @param memory_size - clib mheap size, in bytes -*/ - -void clib_bihash_init - (clib_bihash * h, char *name, u32 nbuckets, uword memory_size); - -/** Destroy a bounded index extensible hash table - @param h - the bi-hash table to free -*/ - -void clib_bihash_free (clib_bihash * h); - -/** Add or delete a (key,value) pair from a bi-hash table - - @param h - the bi-hash table to search - @param add_v - the (key,value) pair to add - @param is_add - add=1, delete=0 - @returns 0 on success, < 0 on error - @note This function will replace an existing (key,value) pair if the - new key matches an existing key -*/ -int clib_bihash_add_del (clib_bihash * h, clib_bihash_kv * add_v, int is_add); - - -/** Search a bi-hash table - - @param h - the bi-hash table to search - @param search_v - (key,value) pair containing the search key - @param return_v - (key,value) pair which matches search_v.key - @returns 0 on success (with return_v set), < 0 on error -*/ -int clib_bihash_search (clib_bihash * h, - clib_bihash_kv * search_v, clib_bihash_kv * return_v); - - -/** Visit active (key,value) pairs in a bi-hash table - - @param h - the bi-hash table to search - @param callback - function to call with each active (key,value) pair - @param arg - arbitrary second argument passed to the callback function - First argument is the (key,value) pair to visit - @note Trying to supply a proper function prototype for the - callback function appears to be a fool's errand. -*/ -void clib_bihash_foreach_key_value_pair (clib_bihash * h, - void *callback, void *arg); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/bihash_template.c b/vppinfra/vppinfra/bihash_template.c deleted file mode 100644 index 4b0b425788a..00000000000 --- a/vppinfra/vppinfra/bihash_template.c +++ /dev/null @@ -1,455 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** @cond DOCUMENTATION_IS_IN_BIHASH_DOC_H */ - -void BV (clib_bihash_init) - (BVT (clib_bihash) * h, char *name, u32 nbuckets, uword memory_size) -{ - void *oldheap; - - nbuckets = 1 << (max_log2 (nbuckets)); - - h->name = (u8 *) name; - h->nbuckets = nbuckets; - h->log2_nbuckets = max_log2 (nbuckets); - - h->mheap = mheap_alloc (0 /* use VM */ , memory_size); - - oldheap = clib_mem_set_heap (h->mheap); - vec_validate_aligned (h->buckets, nbuckets - 1, CLIB_CACHE_LINE_BYTES); - h->writer_lock = clib_mem_alloc_aligned (CLIB_CACHE_LINE_BYTES, - CLIB_CACHE_LINE_BYTES); - - clib_mem_set_heap (oldheap); -} - -void BV (clib_bihash_free) (BVT (clib_bihash) * h) -{ - mheap_free (h->mheap); - memset (h, 0, sizeof (*h)); -} - -static -BVT (clib_bihash_value) * -BV (value_alloc) (BVT (clib_bihash) * h, u32 log2_pages) -{ - BVT (clib_bihash_value) * rv = 0; - void *oldheap; - - ASSERT (h->writer_lock[0]); - if (log2_pages >= vec_len (h->freelists) || h->freelists[log2_pages] == 0) - { - oldheap = clib_mem_set_heap (h->mheap); - - vec_validate (h->freelists, log2_pages); - vec_validate_aligned (rv, (1 << log2_pages) - 1, CLIB_CACHE_LINE_BYTES); - clib_mem_set_heap (oldheap); - goto initialize; - } - rv = h->freelists[log2_pages]; - h->freelists[log2_pages] = rv->next_free; - -initialize: - ASSERT (rv); - ASSERT (vec_len (rv) == (1 << log2_pages)); - /* - * Latest gcc complains that the length arg is zero - * if we replace (1<<log2_pages) with vec_len(rv). - * No clue. - */ - memset (rv, 0xff, sizeof (*rv) * (1 << log2_pages)); - return rv; -} - -static void -BV (value_free) (BVT (clib_bihash) * h, BVT (clib_bihash_value) * v) -{ - u32 log2_pages; - - ASSERT (h->writer_lock[0]); - - log2_pages = min_log2 (vec_len (v)); - - ASSERT (vec_len (h->freelists) > log2_pages); - - v->next_free = h->freelists[log2_pages]; - h->freelists[log2_pages] = v; -} - -static inline void -BV (make_working_copy) (BVT (clib_bihash) * h, clib_bihash_bucket_t * b) -{ - BVT (clib_bihash_value) * v; - clib_bihash_bucket_t working_bucket __attribute__ ((aligned (8))); - void *oldheap; - BVT (clib_bihash_value) * working_copy; - u32 cpu_number = os_get_cpu_number (); - - if (cpu_number >= vec_len (h->working_copies)) - { - oldheap = clib_mem_set_heap (h->mheap); - vec_validate (h->working_copies, cpu_number); - clib_mem_set_heap (oldheap); - } - - /* - * working_copies are per-cpu so that near-simultaneous - * updates from multiple threads will not result in sporadic, spurious - * lookup failures. - */ - working_copy = h->working_copies[cpu_number]; - - h->saved_bucket.as_u64 = b->as_u64; - oldheap = clib_mem_set_heap (h->mheap); - - if ((1 << b->log2_pages) > vec_len (working_copy)) - { - vec_validate_aligned (working_copy, (1 << b->log2_pages) - 1, - sizeof (u64)); - h->working_copies[cpu_number] = working_copy; - } - - _vec_len (working_copy) = 1 << b->log2_pages; - clib_mem_set_heap (oldheap); - - v = BV (clib_bihash_get_value) (h, b->offset); - - clib_memcpy (working_copy, v, sizeof (*v) * (1 << b->log2_pages)); - working_bucket.as_u64 = b->as_u64; - working_bucket.offset = BV (clib_bihash_get_offset) (h, working_copy); - CLIB_MEMORY_BARRIER (); - b->as_u64 = working_bucket.as_u64; - h->working_copies[cpu_number] = working_copy; -} - -static -BVT (clib_bihash_value) * -BV (split_and_rehash) - (BVT (clib_bihash) * h, - BVT (clib_bihash_value) * old_values, u32 new_log2_pages) -{ - BVT (clib_bihash_value) * new_values, *v, *new_v; - int i, j, k; - - new_values = BV (value_alloc) (h, new_log2_pages); - - v = old_values; - for (i = 0; i < vec_len (old_values); i++) - { - u64 new_hash; - - for (j = 0; j < BIHASH_KVP_PER_PAGE; j++) - { - if (BV (clib_bihash_is_free) (&(v->kvp[j])) == 0) - { - new_hash = BV (clib_bihash_hash) (&(v->kvp[j])); - new_hash >>= h->log2_nbuckets; - new_hash &= (1 << new_log2_pages) - 1; - - new_v = &new_values[new_hash]; - - for (k = 0; k < BIHASH_KVP_PER_PAGE; k++) - { - if (BV (clib_bihash_is_free) (&(new_v->kvp[k]))) - { - clib_memcpy (&(new_v->kvp[k]), &(v->kvp[j]), - sizeof (new_v->kvp[k])); - goto doublebreak; - } - } - /* Crap. Tell caller to try again */ - BV (value_free) (h, new_values); - return 0; - } - doublebreak: - ; - } - v++; - } - return new_values; -} - -int BV (clib_bihash_add_del) - (BVT (clib_bihash) * h, BVT (clib_bihash_kv) * add_v, int is_add) -{ - u32 bucket_index; - clib_bihash_bucket_t *b, tmp_b; - BVT (clib_bihash_value) * v, *new_v, *save_new_v, *working_copy; - u32 value_index; - int rv = 0; - int i; - u64 hash, new_hash; - u32 new_log2_pages; - u32 cpu_number = os_get_cpu_number (); - - hash = BV (clib_bihash_hash) (add_v); - - bucket_index = hash & (h->nbuckets - 1); - b = &h->buckets[bucket_index]; - - hash >>= h->log2_nbuckets; - - while (__sync_lock_test_and_set (h->writer_lock, 1)) - ; - - /* First elt in the bucket? */ - if (b->offset == 0) - { - if (is_add == 0) - { - rv = -1; - goto unlock; - } - - v = BV (value_alloc) (h, 0); - *v->kvp = *add_v; - tmp_b.as_u64 = 0; - tmp_b.offset = BV (clib_bihash_get_offset) (h, v); - - b->as_u64 = tmp_b.as_u64; - goto unlock; - } - - BV (make_working_copy) (h, b); - - v = BV (clib_bihash_get_value) (h, h->saved_bucket.offset); - value_index = hash & ((1 << h->saved_bucket.log2_pages) - 1); - v += value_index; - - if (is_add) - { - /* - * For obvious (in hindsight) reasons, see if we're supposed to - * replace an existing key, then look for an empty slot. - */ - for (i = 0; i < BIHASH_KVP_PER_PAGE; i++) - { - if (!memcmp (&(v->kvp[i]), &add_v->key, sizeof (add_v->key))) - { - clib_memcpy (&(v->kvp[i]), add_v, sizeof (*add_v)); - CLIB_MEMORY_BARRIER (); - /* Restore the previous (k,v) pairs */ - b->as_u64 = h->saved_bucket.as_u64; - goto unlock; - } - } - for (i = 0; i < BIHASH_KVP_PER_PAGE; i++) - { - if (BV (clib_bihash_is_free) (&(v->kvp[i]))) - { - clib_memcpy (&(v->kvp[i]), add_v, sizeof (*add_v)); - CLIB_MEMORY_BARRIER (); - b->as_u64 = h->saved_bucket.as_u64; - goto unlock; - } - } - /* no room at the inn... split case... */ - } - else - { - for (i = 0; i < BIHASH_KVP_PER_PAGE; i++) - { - if (!memcmp (&(v->kvp[i]), &add_v->key, sizeof (add_v->key))) - { - memset (&(v->kvp[i]), 0xff, sizeof (*(add_v))); - CLIB_MEMORY_BARRIER (); - b->as_u64 = h->saved_bucket.as_u64; - goto unlock; - } - } - rv = -3; - b->as_u64 = h->saved_bucket.as_u64; - goto unlock; - } - - new_log2_pages = h->saved_bucket.log2_pages + 1; - -expand_again: - working_copy = h->working_copies[cpu_number]; - new_v = BV (split_and_rehash) (h, working_copy, new_log2_pages); - if (new_v == 0) - { - new_log2_pages++; - goto expand_again; - } - - /* Try to add the new entry */ - save_new_v = new_v; - new_hash = BV (clib_bihash_hash) (add_v); - new_hash >>= h->log2_nbuckets; - new_hash &= (1 << min_log2 (vec_len (new_v))) - 1; - new_v += new_hash; - - for (i = 0; i < BIHASH_KVP_PER_PAGE; i++) - { - if (BV (clib_bihash_is_free) (&(new_v->kvp[i]))) - { - clib_memcpy (&(new_v->kvp[i]), add_v, sizeof (*add_v)); - goto expand_ok; - } - } - /* Crap. Try again */ - new_log2_pages++; - BV (value_free) (h, save_new_v); - goto expand_again; - -expand_ok: - tmp_b.log2_pages = min_log2 (vec_len (save_new_v)); - tmp_b.offset = BV (clib_bihash_get_offset) (h, save_new_v); - CLIB_MEMORY_BARRIER (); - b->as_u64 = tmp_b.as_u64; - v = BV (clib_bihash_get_value) (h, h->saved_bucket.offset); - BV (value_free) (h, v); - -unlock: - CLIB_MEMORY_BARRIER (); - h->writer_lock[0] = 0; - return rv; -} - -int BV (clib_bihash_search) - (const BVT (clib_bihash) * h, - BVT (clib_bihash_kv) * search_key, BVT (clib_bihash_kv) * valuep) -{ - u64 hash; - u32 bucket_index; - uword value_index; - BVT (clib_bihash_value) * v; - clib_bihash_bucket_t *b; - int i; - - ASSERT (valuep); - - hash = BV (clib_bihash_hash) (search_key); - - bucket_index = hash & (h->nbuckets - 1); - b = &h->buckets[bucket_index]; - - if (b->offset == 0) - return -1; - - hash >>= h->log2_nbuckets; - - v = BV (clib_bihash_get_value) (h, b->offset); - value_index = hash & ((1 << b->log2_pages) - 1); - v += value_index; - - for (i = 0; i < BIHASH_KVP_PER_PAGE; i++) - { - if (BV (clib_bihash_key_compare) (v->kvp[i].key, search_key->key)) - { - *valuep = v->kvp[i]; - return 0; - } - } - return -1; -} - -u8 *BV (format_bihash) (u8 * s, va_list * args) -{ - BVT (clib_bihash) * h = va_arg (*args, BVT (clib_bihash) *); - int verbose = va_arg (*args, int); - clib_bihash_bucket_t *b; - BVT (clib_bihash_value) * v; - int i, j, k; - u64 active_elements = 0; - - s = format (s, "Hash table %s\n", h->name ? h->name : (u8 *) "(unnamed)"); - - for (i = 0; i < h->nbuckets; i++) - { - b = &h->buckets[i]; - if (b->offset == 0) - { - if (verbose > 1) - s = format (s, "[%d]: empty\n", i); - continue; - } - - if (verbose) - { - s = format (s, "[%d]: heap offset %d, len %d\n", i, - b->offset, (1 << b->log2_pages)); - } - - v = BV (clib_bihash_get_value) (h, b->offset); - for (j = 0; j < (1 << b->log2_pages); j++) - { - for (k = 0; k < BIHASH_KVP_PER_PAGE; k++) - { - if (BV (clib_bihash_is_free) (&v->kvp[k])) - { - if (verbose > 1) - s = format (s, " %d: empty\n", - j * BIHASH_KVP_PER_PAGE + k); - continue; - } - if (verbose) - { - s = format (s, " %d: %U\n", - j * BIHASH_KVP_PER_PAGE + k, - BV (format_bihash_kvp), &(v->kvp[k])); - } - active_elements++; - } - v++; - } - } - - s = format (s, " %lld active elements\n", active_elements); - s = format (s, " %d free lists\n", vec_len (h->freelists)); - - return s; -} - -void BV (clib_bihash_foreach_key_value_pair) - (BVT (clib_bihash) * h, void *callback, void *arg) -{ - int i, j, k; - clib_bihash_bucket_t *b; - BVT (clib_bihash_value) * v; - void (*fp) (BVT (clib_bihash_kv) *, void *) = callback; - - for (i = 0; i < h->nbuckets; i++) - { - b = &h->buckets[i]; - if (b->offset == 0) - continue; - - v = BV (clib_bihash_get_value) (h, b->offset); - for (j = 0; j < (1 << b->log2_pages); j++) - { - for (k = 0; k < BIHASH_KVP_PER_PAGE; k++) - { - if (BV (clib_bihash_is_free) (&v->kvp[k])) - continue; - - (*fp) (&v->kvp[k], arg); - } - v++; - } - } -} - -/** @endcond */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/bihash_template.h b/vppinfra/vppinfra/bihash_template.h deleted file mode 100644 index f70190c63a5..00000000000 --- a/vppinfra/vppinfra/bihash_template.h +++ /dev/null @@ -1,214 +0,0 @@ -/* - Copyright (c) 2014 Cisco and/or its affiliates. - - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. -*/ - -/** @cond DOCUMENTATION_IS_IN_BIHASH_DOC_H */ - -/* - * Note: to instantiate the template multiple times in a single file, - * #undef __included_bihash_template_h__... - */ -#ifndef __included_bihash_template_h__ -#define __included_bihash_template_h__ - -#include <vppinfra/heap.h> -#include <vppinfra/format.h> -#include <vppinfra/pool.h> - -#ifndef BIHASH_TYPE -#error BIHASH_TYPE not defined -#endif - -#define _bv(a,b) a##b -#define __bv(a,b) _bv(a,b) -#define BV(a) __bv(a,BIHASH_TYPE) - -#define _bvt(a,b) a##b##_t -#define __bvt(a,b) _bvt(a,b) -#define BVT(a) __bvt(a,BIHASH_TYPE) - -typedef struct BV (clib_bihash_value) -{ - union - { - BVT (clib_bihash_kv) kvp[BIHASH_KVP_PER_PAGE]; - struct BV (clib_bihash_value) * next_free; - }; -} BVT (clib_bihash_value); - -/* - * This is shared across all uses of the template, so it needs - * a "personal" #include recursion block - */ -#ifndef __defined_clib_bihash_bucket_t__ -#define __defined_clib_bihash_bucket_t__ -typedef struct -{ - union - { - struct - { - u32 offset; - u8 pad[3]; - u8 log2_pages; - }; - u64 as_u64; - }; -} clib_bihash_bucket_t; -#endif /* __defined_clib_bihash_bucket_t__ */ - -typedef struct -{ - BVT (clib_bihash_value) * values; - clib_bihash_bucket_t *buckets; - volatile u32 *writer_lock; - - BVT (clib_bihash_value) ** working_copies; - clib_bihash_bucket_t saved_bucket; - - u32 nbuckets; - u32 log2_nbuckets; - u8 *name; - - BVT (clib_bihash_value) ** freelists; - void *mheap; - -} BVT (clib_bihash); - - -static inline void *BV (clib_bihash_get_value) (const BVT (clib_bihash) * h, - uword offset) -{ - u8 *hp = h->mheap; - u8 *vp = hp + offset; - - return (void *) vp; -} - -static inline uword BV (clib_bihash_get_offset) (const BVT (clib_bihash) * h, - void *v) -{ - u8 *hp, *vp; - - hp = (u8 *) h->mheap; - vp = (u8 *) v; - - ASSERT ((vp - hp) < 0x100000000ULL); - return vp - hp; -} - -void BV (clib_bihash_init) - (BVT (clib_bihash) * h, char *name, u32 nbuckets, uword memory_size); - -void BV (clib_bihash_free) (BVT (clib_bihash) * h); - -int BV (clib_bihash_add_del) (BVT (clib_bihash) * h, - BVT (clib_bihash_kv) * add_v, int is_add); -int BV (clib_bihash_search) (const BVT (clib_bihash) * h, - BVT (clib_bihash_kv) * search_v, - BVT (clib_bihash_kv) * return_v); - -void BV (clib_bihash_foreach_key_value_pair) (BVT (clib_bihash) * h, - void *callback, void *arg); - -format_function_t BV (format_bihash); -format_function_t BV (format_bihash_kvp); - - -static inline int BV (clib_bihash_search_inline) - (const BVT (clib_bihash) * h, BVT (clib_bihash_kv) * kvp) -{ - u64 hash; - u32 bucket_index; - uword value_index; - BVT (clib_bihash_value) * v; - clib_bihash_bucket_t *b; - int i; - - hash = BV (clib_bihash_hash) (kvp); - - bucket_index = hash & (h->nbuckets - 1); - b = &h->buckets[bucket_index]; - - if (b->offset == 0) - return -1; - - hash >>= h->log2_nbuckets; - - v = BV (clib_bihash_get_value) (h, b->offset); - value_index = hash & ((1 << b->log2_pages) - 1); - v += value_index; - - for (i = 0; i < BIHASH_KVP_PER_PAGE; i++) - { - if (BV (clib_bihash_key_compare) (v->kvp[i].key, kvp->key)) - { - *kvp = v->kvp[i]; - return 0; - } - } - return -1; -} - -static inline int BV (clib_bihash_search_inline_2) - (const BVT (clib_bihash) * h, - BVT (clib_bihash_kv) * search_key, BVT (clib_bihash_kv) * valuep) -{ - u64 hash; - u32 bucket_index; - uword value_index; - BVT (clib_bihash_value) * v; - clib_bihash_bucket_t *b; - int i; - - ASSERT (valuep); - - hash = BV (clib_bihash_hash) (search_key); - - bucket_index = hash & (h->nbuckets - 1); - b = &h->buckets[bucket_index]; - - if (b->offset == 0) - return -1; - - hash >>= h->log2_nbuckets; - - v = BV (clib_bihash_get_value) (h, b->offset); - value_index = hash & ((1 << b->log2_pages) - 1); - v += value_index; - - for (i = 0; i < BIHASH_KVP_PER_PAGE; i++) - { - if (BV (clib_bihash_key_compare) (v->kvp[i].key, search_key->key)) - { - *valuep = v->kvp[i]; - return 0; - } - } - return -1; -} - - -#endif /* __included_bihash_template_h__ */ - -/** @endcond */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/bitmap.h b/vppinfra/vppinfra/bitmap.h deleted file mode 100644 index 9e1ae493285..00000000000 --- a/vppinfra/vppinfra/bitmap.h +++ /dev/null @@ -1,774 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001, 2002, 2003, 2005 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_clib_bitmap_h -#define included_clib_bitmap_h - -/** \file - Bitmaps built as vectors of machine words -*/ - -#include <vppinfra/vec.h> -#include <vppinfra/random.h> -#include <vppinfra/error.h> -#include <vppinfra/bitops.h> /* for count_set_bits */ - -typedef uword clib_bitmap_t; - -/** predicate function; is an entire bitmap empty? - @param ai - pointer to a bitmap - @returns 1 if the entire bitmap is zero, 0 otherwise -*/ -always_inline uword -clib_bitmap_is_zero (uword * ai) -{ - uword i; - for (i = 0; i < vec_len (ai); i++) - if (ai[i] != 0) - return 0; - return 1; -} - -/** predicate function; are two bitmaps equal? - @param a - pointer to a bitmap - @param b - pointer to a bitmap - @returns 1 if the bitmaps are equal, 0 otherwise -*/ -always_inline uword -clib_bitmap_is_equal (uword * a, uword * b) -{ - uword i; - if (vec_len (a) != vec_len (b)) - return 0; - for (i = 0; i < vec_len (a); i++) - if (a[i] != b[i]) - return 0; - return 1; -} - -/** Duplicate a bitmap - @param v - pointer to a bitmap - @returns a duplicate of the bitmap -*/ -#define clib_bitmap_dup(v) vec_dup(v) - -/** Free a bitmap - @param v - pointer to the bitmap to free -*/ -#define clib_bitmap_free(v) vec_free(v) - -/** Number of bytes in a bitmap - @param v - pointer to the bitmap -*/ -#define clib_bitmap_bytes(v) vec_bytes(v) - -/** Clear a bitmap - @param v - pointer to the bitmap to clear -*/ -#define clib_bitmap_zero(v) vec_zero(v) - -/** Allocate a bitmap with the supplied number of bits - @param [out] v - the resulting bitmap - @param n_bits - the required number of bits -*/ - -#define clib_bitmap_alloc(v,n_bits) \ - v = vec_new (uword, ((n_bits) + BITS (uword) - 1) / BITS (uword)) - -#define clib_bitmap_vec_validate(v,i) vec_validate_aligned((v),(i),sizeof(uword)) - -/* Make sure that a bitmap is at least n_bits in size */ -#define clib_bitmap_validate(v,n_bits) \ - clib_bitmap_vec_validate ((v), ((n_bits) - 1) / BITS (uword)) - -/* low-level routine to remove trailing zeros from a bitmap */ -always_inline uword * -_clib_bitmap_remove_trailing_zeros (uword * a) -{ - word i; - if (a) - { - for (i = _vec_len (a) - 1; i >= 0; i--) - if (a[i] != 0) - break; - _vec_len (a) = i + 1; - } - return a; -} - -/** Sets the ith bit of a bitmap to new_value. - No sanity checking. Be careful. - @param a - pointer to the bitmap - @param i - the bit position to interrogate - @param new_value - new value for the bit - @returns the old value of the bit -*/ -always_inline uword -clib_bitmap_set_no_check (uword * a, uword i, uword new_value) -{ - uword i0 = i / BITS (a[0]); - uword i1 = i % BITS (a[0]); - uword bit = (uword) 1 << i1; - uword ai, old_value; - - /* Removed ASSERT since uword * a may not be a vector. */ - /* ASSERT (i0 < vec_len (a)); */ - - ai = a[i0]; - old_value = (ai & bit) != 0; - ai &= ~bit; - ai |= ((uword) (new_value != 0)) << i1; - a[i0] = ai; - return old_value; -} - -/** Sets the ith bit of a bitmap to new_value - Removes trailing zeros from the bitmap - @param ai - pointer to the bitmap - @param i - the bit position to interrogate - @param value - new value for the bit - @returns the old value of the bit -*/ -always_inline uword * -clib_bitmap_set (uword * ai, uword i, uword value) -{ - uword i0 = i / BITS (ai[0]); - uword i1 = i % BITS (ai[0]); - uword a; - - /* Check for writing a zero to beyond end of bitmap. */ - if (value == 0 && i0 >= vec_len (ai)) - return ai; /* Implied trailing zeros. */ - - clib_bitmap_vec_validate (ai, i0); - - a = ai[i0]; - a &= ~((uword) 1 << i1); - a |= ((uword) (value != 0)) << i1; - ai[i0] = a; - - /* If bits have been cleared, test for zero. */ - if (a == 0) - ai = _clib_bitmap_remove_trailing_zeros (ai); - - return ai; -} - -/** Gets the ith bit value from a bitmap - @param ai - pointer to the bitmap - @param i - the bit position to interrogate - @returns the indicated bit value -*/ -always_inline uword -clib_bitmap_get (uword * ai, uword i) -{ - uword i0 = i / BITS (ai[0]); - uword i1 = i % BITS (ai[0]); - return i0 < vec_len (ai) && 0 != ((ai[i0] >> i1) & 1); -} - -/** Gets the ith bit value from a bitmap - Does not sanity-check the bit position. Be careful. - @param ai - pointer to the bitmap - @param i - the bit position to interrogate - @returns the indicated bit value, or garbage if the bit position is - out of range. -*/ -always_inline uword -clib_bitmap_get_no_check (uword * ai, uword i) -{ - uword i0 = i / BITS (ai[0]); - uword i1 = i % BITS (ai[0]); - return 0 != ((ai[i0] >> i1) & 1); -} - -always_inline uword -clib_bitmap_get_multiple_no_check (uword * ai, uword i, uword n_bits) -{ - uword i0 = i / BITS (ai[0]); - uword i1 = i % BITS (ai[0]); - ASSERT (i1 + n_bits <= BITS (uword)); - return 0 != ((ai[i0] >> i1) & pow2_mask (n_bits)); -} - -/** Gets the ith through ith + n_bits bit values from a bitmap - @param bitmap - pointer to the bitmap - @param i - the first bit position to retrieve - @param n_bits - the number of bit positions to retrieve - @returns the indicated range of bits -*/ -always_inline uword -clib_bitmap_get_multiple (uword * bitmap, uword i, uword n_bits) -{ - uword i0, i1, result; - uword l = vec_len (bitmap); - - ASSERT (n_bits <= BITS (result)); - - i0 = i / BITS (bitmap[0]); - i1 = i % BITS (bitmap[0]); - - /* Check first word. */ - result = 0; - if (i0 < l) - { - result |= (bitmap[i0] >> i1); - if (n_bits < BITS (bitmap[0])) - result &= (((uword) 1 << n_bits) - 1); - } - - /* Check for overlap into next word. */ - i0++; - if (i1 + n_bits > BITS (bitmap[0]) && i0 < l) - { - n_bits -= BITS (bitmap[0]) - i1; - result |= - (bitmap[i0] & (((uword) 1 << n_bits) - 1)) << (BITS (bitmap[0]) - i1); - } - - return result; -} - -/** sets the ith through ith + n_bits bits in a bitmap - @param bitmap - pointer to the bitmap - @param i - the first bit position to retrieve - @param value - the values to set - @param n_bits - the number of bit positions to set - @returns a pointer to the updated bitmap, which may expand and move -*/ - -always_inline uword * -clib_bitmap_set_multiple (uword * bitmap, uword i, uword value, uword n_bits) -{ - uword i0, i1, l, t, m; - - ASSERT (n_bits <= BITS (value)); - - i0 = i / BITS (bitmap[0]); - i1 = i % BITS (bitmap[0]); - - /* Allocate bitmap. */ - clib_bitmap_vec_validate (bitmap, (i + n_bits) / BITS (bitmap[0])); - l = vec_len (bitmap); - - m = ~0; - if (n_bits < BITS (value)) - m = (((uword) 1 << n_bits) - 1); - value &= m; - - /* Insert into first word. */ - t = bitmap[i0]; - t &= ~(m << i1); - t |= value << i1; - bitmap[i0] = t; - - /* Insert into second word. */ - i0++; - if (i1 + n_bits > BITS (bitmap[0]) && i0 < l) - { - t = BITS (bitmap[0]) - i1; - value >>= t; - n_bits -= t; - t = bitmap[i0]; - m = ((uword) 1 << n_bits) - 1; - t &= ~m; - t |= value; - bitmap[i0] = t; - } - - return bitmap; -} - -always_inline uword * -clfib_bitmap_set_region (uword * bitmap, uword i, uword value, uword n_bits) -{ - uword a0, a1, b0; - uword i_end, mask; - - a0 = i / BITS (bitmap[0]); - a1 = i % BITS (bitmap[0]); - - i_end = i + n_bits; - b0 = i_end / BITS (bitmap[0]); - - clib_bitmap_vec_validate (bitmap, b0); - - /* First word. */ - mask = n_bits < BITS (bitmap[0]) ? pow2_mask (n_bits) : ~0; - mask <<= a1; - - if (value) - bitmap[a0] |= mask; - else - bitmap[a0] &= ~mask; - - for (a0++; a0 < b0; a0++) - bitmap[a0] = value ? ~0 : 0; - - if (a0 == b0) - { - word n_bits_left = n_bits - (BITS (bitmap[0]) - a1); - mask = pow2_mask (n_bits_left); - if (value) - bitmap[a0] |= mask; - else - bitmap[a0] &= ~mask; - } - - return bitmap; -} - -/** Macro to iterate across set bits in a bitmap - - @param i - the current set bit - @param ai - the bitmap - @param body - the expression to evaluate for each set bit -*/ -#define clib_bitmap_foreach(i,ai,body) \ -do { \ - uword __bitmap_i, __bitmap_ai, __bitmap_len, __bitmap_first_set; \ - __bitmap_len = vec_len ((ai)); \ - for (__bitmap_i = 0; __bitmap_i < __bitmap_len; __bitmap_i++) \ - { \ - __bitmap_ai = (ai)[__bitmap_i]; \ - while (__bitmap_ai != 0) \ - { \ - __bitmap_first_set = first_set (__bitmap_ai); \ - (i) = (__bitmap_i * BITS ((ai)[0]) \ - + min_log2 (__bitmap_first_set)); \ - do { body; } while (0); \ - __bitmap_ai ^= __bitmap_first_set; \ - } \ - } \ -} while (0) - - -/** Return the lowest numbered set bit in a bitmap - @param ai - pointer to the bitmap - @returns lowest numbered set bit, or ~0 if the entire bitmap is zero -*/ -always_inline uword -clib_bitmap_first_set (uword * ai) -{ - uword i; - for (i = 0; i < vec_len (ai); i++) - { - uword x = ai[i]; - if (x != 0) - return i * BITS (ai[0]) + log2_first_set (x); - } - return ~0; -} - -/** Return the higest numbered set bit in a bitmap - @param ai - pointer to the bitmap - @returns lowest numbered set bit, or ~0 if the entire bitmap is zero -*/ -always_inline uword -clib_bitmap_last_set (uword * ai) -{ - uword i; - - for (i = vec_len (ai); i > 0; i--) - { - uword x = ai[i - 1]; - if (x != 0) - { - uword first_bit; - count_leading_zeros (first_bit, x); - return (i) * BITS (ai[0]) - first_bit - 1; - } - } - return ~0; -} - -/** Return the lowest numbered clear bit in a bitmap - @param ai - pointer to the bitmap - @returns lowest numbered clear bit -*/ -always_inline uword -clib_bitmap_first_clear (uword * ai) -{ - uword i; - for (i = 0; i < vec_len (ai); i++) - { - uword x = ~ai[i]; - if (x != 0) - return i * BITS (ai[0]) + log2_first_set (x); - } - return i * BITS (ai[0]); -} - -/** Return the number of set bits in a bitmap - @param ai - pointer to the bitmap - @returns the number of set bits in the bitmap -*/ -always_inline uword -clib_bitmap_count_set_bits (uword * ai) -{ - uword i; - uword n_set = 0; - for (i = 0; i < vec_len (ai); i++) - n_set += count_set_bits (ai[i]); - return n_set; -} - -/** Logical operator across two bitmaps - - @param ai - pointer to the destination bitmap - @param bi - pointer to the source bitmap - @returns ai = ai and bi. ai is modified, bi is not modified -*/ -always_inline uword *clib_bitmap_and (uword * ai, uword * bi); - -/** Logical operator across two bitmaps - - @param ai - pointer to the destination bitmap - @param bi - pointer to the source bitmap - @returns ai = ai & ~bi. ai is modified, bi is not modified -*/ -always_inline uword *clib_bitmap_andnot (uword * ai, uword * bi); - -/** Logical operator across two bitmaps - - @param ai - pointer to the destination bitmap - @param bi - pointer to the source bitmap - @returns ai = ai & ~bi. ai is modified, bi is not modified -*/ -always_inline uword *clib_bitmap_or (uword * ai, uword * bi); -/** Logical operator across two bitmaps - - @param ai - pointer to the destination bitmap - @param bi - pointer to the source bitmap - @returns ai = ai or bi. ai is modified, bi is not modified -*/ -always_inline uword *clib_bitmap_or (uword * ai, uword * bi); - -/** Logical operator across two bitmaps - - @param ai - pointer to the destination bitmap - @param bi - pointer to the source bitmap - @returns ai = ai xor bi. ai is modified, bi is not modified -*/ -always_inline uword *clib_bitmap_xor (uword * ai, uword * bi); - -/* ALU function definition macro for functions taking two bitmaps. */ -#define _(name, body, check_zero) \ -always_inline uword * \ -clib_bitmap_##name (uword * ai, uword * bi) \ -{ \ - uword i, a, b, bi_len, n_trailing_zeros; \ - \ - n_trailing_zeros = 0; \ - bi_len = vec_len (bi); \ - if (bi_len > 0) \ - clib_bitmap_vec_validate (ai, bi_len - 1); \ - for (i = 0; i < vec_len (ai); i++) \ - { \ - a = ai[i]; \ - b = i < bi_len ? bi[i] : 0; \ - do { body; } while (0); \ - ai[i] = a; \ - if (check_zero) \ - n_trailing_zeros = a ? 0 : (n_trailing_zeros + 1); \ - } \ - if (check_zero) \ - _vec_len (ai) -= n_trailing_zeros; \ - return ai; \ -} - -/* ALU functions: */ -_(and, a = a & b, 1) -_(andnot, a = a & ~b, 1) _(or, a = a | b, 0) _(xor, a = a ^ b, 1) -#undef _ -/** Logical operator across two bitmaps which duplicates the first bitmap - - @param ai - pointer to the destination bitmap - @param bi - pointer to the source bitmap - @returns aiDup = ai and bi. Neither ai nor bi are modified -*/ - always_inline uword * - clib_bitmap_dup_and (uword * ai, uword * bi); - -/** Logical operator across two bitmaps which duplicates the first bitmap - - @param ai - pointer to the destination bitmap - @param bi - pointer to the source bitmap - @returns aiDup = ai & ~bi. Neither ai nor bi are modified -*/ - always_inline uword * - clib_bitmap_dup_andnot (uword * ai, uword * bi); - -/** Logical operator across two bitmaps which duplicates the first bitmap - - @param ai - pointer to the destination bitmap - @param bi - pointer to the source bitmap - @returns aiDup = ai or bi. Neither ai nor bi are modified -*/ - always_inline uword * - clib_bitmap_dup_or (uword * ai, uword * bi); - -/** Logical operator across two bitmaps which duplicates the first bitmap - - @param ai - pointer to the destination bitmap - @param bi - pointer to the source bitmap - @returns aiDup = ai xor bi. Neither ai nor bi are modified -*/ - always_inline uword * - clib_bitmap_dup_xor (uword * ai, uword * bi); - -#define _(name) \ - always_inline uword * \ - clib_bitmap_dup_##name (uword * ai, uword * bi) \ -{ return clib_bitmap_##name (clib_bitmap_dup (ai), bi); } - -_(and); -_(andnot); -_(or); -_(xor); - -#undef _ - -/* ALU function definition macro for functions taking one bitmap and an immediate. */ -#define _(name, body, check_zero) \ -always_inline uword * \ -clib_bitmap_##name (uword * ai, uword i) \ -{ \ - uword i0 = i / BITS (ai[0]); \ - uword i1 = i % BITS (ai[0]); \ - uword a, b; \ - clib_bitmap_vec_validate (ai, i0); \ - a = ai[i0]; \ - b = (uword) 1 << i1; \ - do { body; } while (0); \ - ai[i0] = a; \ - if (check_zero && a == 0) \ - ai = _clib_bitmap_remove_trailing_zeros (ai); \ - return ai; \ -} - -/* ALU functions immediate: */ -_(andi, a = a & b, 1) -_(andnoti, a = a & ~b, 1) _(ori, a = a | b, 0) _(xori, a = a ^ b, 1) -#undef _ -/** Return a random bitmap of the requested length - @param ai - pointer to the destination bitmap - @param n_bits - number of bits to allocate - @param [in,out] seed - pointer to the random number seed - @returns a reasonably random bitmap based. See random.h. -*/ - always_inline uword * - clib_bitmap_random (uword * ai, uword n_bits, u32 * seed) -{ - vec_reset_length (ai); - - if (n_bits > 0) - { - uword i = n_bits - 1; - uword i0, i1; - uword log2_rand_max; - - log2_rand_max = min_log2 (random_u32_max ()); - - i0 = i / BITS (ai[0]); - i1 = i % BITS (ai[0]); - - clib_bitmap_vec_validate (ai, i0); - for (i = 0; i <= i0; i++) - { - uword n; - for (n = 0; n < BITS (ai[i]); n += log2_rand_max) - ai[i] |= random_u32 (seed) << n; - } - if (i1 + 1 < BITS (ai[0])) - ai[i0] &= (((uword) 1 << (i1 + 1)) - 1); - } - return ai; -} - -/** Return the next set bit in a bitmap starting at bit i - @param ai - pointer to the bitmap - @param i - first bit position to test - @returns first set bit position at or after i, - ~0 if no further set bits are found -*/ -always_inline uword -clib_bitmap_next_set (uword * ai, uword i) -{ - uword i0 = i / BITS (ai[0]); - uword i1 = i % BITS (ai[0]); - uword t; - - if (i0 < vec_len (ai)) - { - t = (ai[i0] >> i1) << i1; - if (t) - return log2_first_set (t) + i0 * BITS (ai[0]); - - for (i0++; i0 < vec_len (ai); i0++) - { - t = ai[i0]; - if (t) - return log2_first_set (t) + i0 * BITS (ai[0]); - } - } - - return ~0; -} - -/** Return the next clear bit in a bitmap starting at bit i - @param ai - pointer to the bitmap - @param i - first bit position to test - @returns first clear bit position at or after i -*/ -always_inline uword -clib_bitmap_next_clear (uword * ai, uword i) -{ - uword i0 = i / BITS (ai[0]); - uword i1 = i % BITS (ai[0]); - uword t; - - if (i0 < vec_len (ai)) - { - t = (~ai[i0] >> i1) << i1; - if (t) - return log2_first_set (t) + i0 * BITS (ai[0]); - - for (i0++; i0 < vec_len (ai); i0++) - { - t = ~ai[i0]; - if (t) - return log2_first_set (t) + i0 * BITS (ai[0]); - } - } - return i; -} - -/** unformat a list of bit ranges into a bitmap (eg "0-3,5-7,11" ) - - uword * bitmap; - rv = unformat ("%U", unformat_bitmap_list, &bitmap); - - Standard unformat_function_t arguments - - @param input - pointer an unformat_input_t - @param va - varargs list comprising a single uword ** - @returns 1 on success, 0 on failure -*/ -static inline uword -unformat_bitmap_list (unformat_input_t * input, va_list * va) -{ - uword **bitmap_return = va_arg (*va, uword **); - uword *bitmap = 0; - - u32 a, b; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - int i; - if (unformat (input, "%u-%u,", &a, &b)) - ; - else if (unformat (input, "%u,", &a)) - b = a; - else if (unformat (input, "%u-%u", &a, &b)) - ; - else if (unformat (input, "%u", &a)) - b = a; - else if (bitmap) - { - unformat_put_input (input); - break; - } - else - goto error; - - if (b < a) - goto error; - - for (i = a; i <= b; i++) - bitmap = clib_bitmap_set (bitmap, i, 1); - } - *bitmap_return = bitmap; - return 1; -error: - clib_bitmap_free (bitmap); - return 0; -} - -/** Format a bitmap as a string of hex bytes - - uword * bitmap; - s = format ("%U", format_bitmap_hex, bitmap); - - Standard format_function_t arguments - - @param s - string under construction - @param args - varargs list comprising a single uword * - @returns string under construction -*/ -static inline u8 * -format_bitmap_hex (u8 * s, va_list * args) -{ - uword *bitmap = va_arg (*args, uword *); - int i, is_trailing_zero = 1; - - if (!bitmap) - return format (s, "0"); - - i = vec_bytes (bitmap) * 2; - - while (i > 0) - { - u8 x = clib_bitmap_get_multiple (bitmap, --i * 4, 4); - - if (x && is_trailing_zero) - is_trailing_zero = 0; - - if (x || !is_trailing_zero) - s = format (s, "%x", x); - } - return s; -} -#endif /* included_clib_bitmap_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/bitops.h b/vppinfra/vppinfra/bitops.h deleted file mode 100644 index ab91b8ae443..00000000000 --- a/vppinfra/vppinfra/bitops.h +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2005 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_clib_bitops_h -#define included_clib_bitops_h - -#include <vppinfra/clib.h> - -/* Population count from Hacker's Delight. */ -always_inline uword -count_set_bits (uword x) -{ -#if uword_bits == 64 - const uword c1 = 0x5555555555555555; - const uword c2 = 0x3333333333333333; - const uword c3 = 0x0f0f0f0f0f0f0f0f; -#else - const uword c1 = 0x55555555; - const uword c2 = 0x33333333; - const uword c3 = 0x0f0f0f0f; -#endif - - /* Sum 1 bit at a time. */ - x = x - ((x >> (uword) 1) & c1); - - /* 2 bits at a time. */ - x = (x & c2) + ((x >> (uword) 2) & c2); - - /* 4 bits at a time. */ - x = (x + (x >> (uword) 4)) & c3; - - /* 8, 16, 32 bits at a time. */ - x = x + (x >> (uword) 8); - x = x + (x >> (uword) 16); -#if uword_bits == 64 - x = x + (x >> (uword) 32); -#endif - - return x & (2 * BITS (uword) - 1); -} - -/* Based on "Hacker's Delight" code from GLS. */ -typedef struct -{ - uword masks[1 + log2_uword_bits]; -} compress_main_t; - -always_inline void -compress_init (compress_main_t * cm, uword mask) -{ - uword q, m, zm, n, i; - - m = ~mask; - zm = mask; - - cm->masks[0] = mask; - for (i = 0; i < log2_uword_bits; i++) - { - q = m; - m ^= m << 1; - m ^= m << 2; - m ^= m << 4; - m ^= m << 8; - m ^= m << 16; -#if uword_bits > 32 - m ^= m << (uword) 32; -#endif - cm->masks[1 + i] = n = (m << 1) & zm; - m = q & ~m; - q = zm & n; - zm = zm ^ q ^ (q >> (1 << i)); - } -} - -always_inline uword -compress_bits (compress_main_t * cm, uword x) -{ - uword q, r; - - r = x & cm->masks[0]; - q = r & cm->masks[1]; - r ^= q ^ (q >> 1); - q = r & cm->masks[2]; - r ^= q ^ (q >> 2); - q = r & cm->masks[3]; - r ^= q ^ (q >> 4); - q = r & cm->masks[4]; - r ^= q ^ (q >> 8); - q = r & cm->masks[5]; - r ^= q ^ (q >> 16); -#if uword_bits > 32 - q = r & cm->masks[6]; - r ^= q ^ (q >> (uword) 32); -#endif - - return r; -} - -always_inline uword -rotate_left (uword x, uword i) -{ - return (x << i) | (x >> (BITS (i) - i)); -} - -always_inline uword -rotate_right (uword x, uword i) -{ - return (x >> i) | (x << (BITS (i) - i)); -} - -/* Returns snoob from Hacker's Delight. Next highest number - with same number of set bits. */ -always_inline uword -next_with_same_number_of_set_bits (uword x) -{ - uword smallest, ripple, ones; - smallest = x & -x; - ripple = x + smallest; - ones = x ^ ripple; - ones = ones >> (2 + log2_first_set (x)); - return ripple | ones; -} - -#define foreach_set_bit(var,mask,body) \ -do { \ - uword _foreach_set_bit_m_##var = (mask); \ - uword _foreach_set_bit_f_##var; \ - while (_foreach_set_bit_m_##var != 0) \ - { \ - _foreach_set_bit_f_##var = first_set (_foreach_set_bit_m_##var); \ - _foreach_set_bit_m_##var ^= _foreach_set_bit_f_##var; \ - (var) = min_log2 (_foreach_set_bit_f_##var); \ - do { body; } while (0); \ - } \ -} while (0) - -#endif /* included_clib_bitops_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/byte_order.h b/vppinfra/vppinfra/byte_order.h deleted file mode 100644 index b263538c6fe..00000000000 --- a/vppinfra/vppinfra/byte_order.h +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2004 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_clib_byte_order_h -#define included_clib_byte_order_h - -#include <vppinfra/clib.h> - -#if (__BYTE_ORDER__)==( __ORDER_LITTLE_ENDIAN__) -#define CLIB_ARCH_IS_BIG_ENDIAN (0) -#define CLIB_ARCH_IS_LITTLE_ENDIAN (1) -#else -/* Default is big endian. */ -#define CLIB_ARCH_IS_BIG_ENDIAN (1) -#define CLIB_ARCH_IS_LITTLE_ENDIAN (0) -#endif - -/* Big/little endian. */ -#define clib_arch_is_big_endian CLIB_ARCH_IS_BIG_ENDIAN -#define clib_arch_is_little_endian CLIB_ARCH_IS_LITTLE_ENDIAN - -always_inline u16 -clib_byte_swap_u16 (u16 x) -{ - return (x >> 8) | (x << 8); -} - -always_inline i16 -clib_byte_swap_i16 (i16 x) -{ - return clib_byte_swap_u16 (x); -} - -always_inline u32 -clib_byte_swap_u32 (u32 x) -{ -#if defined (i386) || defined (__x86_64__) - if (!__builtin_constant_p (x)) - { - asm volatile ("bswap %0":"=r" (x):"0" (x)); - return x; - } -#endif - return ((x << 24) | ((x & 0xff00) << 8) | ((x >> 8) & 0xff00) | (x >> 24)); -} - -always_inline i32 -clib_byte_swap_i32 (i32 x) -{ - return clib_byte_swap_u32 (x); -} - -always_inline u64 -clib_byte_swap_u64 (u64 x) -{ -#if defined (__x86_64__) - if (!__builtin_constant_p (x)) - { - asm volatile ("bswapq %0":"=r" (x):"0" (x)); - return x; - } -#endif -#define _(x,n,i) \ - ((((x) >> (8*(i))) & 0xff) << (8*((n)-(i)-1))) - return (_(x, 8, 0) | _(x, 8, 1) - | _(x, 8, 2) | _(x, 8, 3) - | _(x, 8, 4) | _(x, 8, 5) | _(x, 8, 6) | _(x, 8, 7)); -#undef _ -} - -always_inline i64 -clib_byte_swap_i64 (i64 x) -{ - return clib_byte_swap_u64 (x); -} - -#define _(sex,type) \ -/* HOST -> SEX */ \ -always_inline type \ -clib_host_to_##sex##_##type (type x) \ -{ \ - if (! clib_arch_is_##sex##_endian) \ - x = clib_byte_swap_##type (x); \ - return x; \ -} \ - \ -always_inline type \ -clib_host_to_##sex##_mem_##type (type * x) \ -{ \ - type v = x[0]; \ - return clib_host_to_##sex##_##type (v); \ -} \ - \ -always_inline type \ -clib_host_to_##sex##_unaligned_mem_##type (type * x) \ -{ \ - type v = clib_mem_unaligned (x, type); \ - return clib_host_to_##sex##_##type (v); \ -} \ - \ -/* SEX -> HOST */ \ -always_inline type \ -clib_##sex##_to_host_##type (type x) \ -{ return clib_host_to_##sex##_##type (x); } \ - \ -always_inline type \ -clib_##sex##_to_host_mem_##type (type * x) \ -{ return clib_host_to_##sex##_mem_##type (x); } \ - \ -always_inline type \ -clib_##sex##_to_host_unaligned_mem_##type (type * x) \ -{ return clib_host_to_##sex##_unaligned_mem_##type (x); } - -#ifndef __cplusplus -_(little, u16) -_(little, u32) -_(little, u64) -_(little, i16) -_(little, i32) -_(little, i64) -_(big, u16) _(big, u32) _(big, u64) _(big, i16) _(big, i32) _(big, i64) -#endif -#undef _ -/* Network "net" alias for "big". */ -#define _(type) \ -always_inline type \ -clib_net_to_host_##type (type x) \ -{ return clib_big_to_host_##type (x); } \ - \ -always_inline type \ -clib_net_to_host_mem_##type (type * x) \ -{ return clib_big_to_host_mem_##type (x); } \ - \ -always_inline type \ -clib_net_to_host_unaligned_mem_##type (type * x) \ -{ return clib_big_to_host_unaligned_mem_##type (x); } \ - \ -always_inline type \ -clib_host_to_net_##type (type x) \ -{ return clib_host_to_big_##type (x); } \ - \ -always_inline type \ -clib_host_to_net_mem_##type (type * x) \ -{ return clib_host_to_big_mem_##type (x); } \ - \ -always_inline type \ -clib_host_to_net_unaligned_mem_##type (type * x) \ -{ return clib_host_to_big_unaligned_mem_##type (x); } -#ifndef __cplusplus - _(u16); -_(i16); -_(u32); -_(i32); -_(u64); -_(i64); -#endif - -#undef _ - -#endif /* included_clib_byte_order_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/cache.h b/vppinfra/vppinfra/cache.h deleted file mode 100644 index 8e1f9483bde..00000000000 --- a/vppinfra/vppinfra/cache.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2005 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_clib_cache_h -#define included_clib_cache_h - -#include <vppinfra/error_bootstrap.h> - -/* - * Allow CFLAGS to override the arch-specific cache line size - */ -#ifndef CLIB_LOG2_CACHE_LINE_BYTES - -#if defined(__x86_64__) || defined(__ARM_ARCH_7A__) -#define CLIB_LOG2_CACHE_LINE_BYTES 6 -#endif - -#ifdef __aarch64__ -#define CLIB_LOG2_CACHE_LINE_BYTES 7 -#endif - -/* Default cache line size of 32 bytes. */ -#ifndef CLIB_LOG2_CACHE_LINE_BYTES -#define CLIB_LOG2_CACHE_LINE_BYTES 5 -#endif - -#endif /* CLIB_LOG2_CACHE_LINE_BYTES defined */ - -#if (CLIB_LOG2_CACHE_LINE_BYTES >= 9) -#error Cache line size 512 bytes or greater -#endif - -#define CLIB_CACHE_LINE_BYTES (1 << CLIB_LOG2_CACHE_LINE_BYTES) -#define CLIB_CACHE_LINE_ALIGN_MARK(mark) u8 mark[0] __attribute__((aligned(CLIB_CACHE_LINE_BYTES))) - -/* Read/write arguments to __builtin_prefetch. */ -#define CLIB_PREFETCH_READ 0 -#define CLIB_PREFETCH_LOAD 0 /* alias for read */ -#define CLIB_PREFETCH_WRITE 1 -#define CLIB_PREFETCH_STORE 1 /* alias for write */ - -#define _CLIB_PREFETCH(n,size,type) \ - if ((size) > (n)*CLIB_CACHE_LINE_BYTES) \ - __builtin_prefetch (_addr + (n)*CLIB_CACHE_LINE_BYTES, \ - CLIB_PREFETCH_##type, \ - /* locality */ 3); - -#define CLIB_PREFETCH(addr,size,type) \ -do { \ - void * _addr = (addr); \ - \ - ASSERT ((size) <= 4*CLIB_CACHE_LINE_BYTES); \ - _CLIB_PREFETCH (0, size, type); \ - _CLIB_PREFETCH (1, size, type); \ - _CLIB_PREFETCH (2, size, type); \ - _CLIB_PREFETCH (3, size, type); \ -} while (0) - -#undef _ - -#endif /* included_clib_cache_h */ - - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/clib.h b/vppinfra/vppinfra/clib.h deleted file mode 100644 index 0386c756833..00000000000 --- a/vppinfra/vppinfra/clib.h +++ /dev/null @@ -1,359 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_clib_h -#define included_clib_h - -/* Standalone means to not assume we are running on a Unix box. */ -#if ! defined (CLIB_STANDALONE) && ! defined (CLIB_LINUX_KERNEL) -#define CLIB_UNIX -#endif - -#include <vppinfra/types.h> - -/* Global DEBUG flag. Setting this to 1 or 0 turns off - ASSERT (see vppinfra/error.h) & other debugging code. */ -#ifndef CLIB_DEBUG -#define CLIB_DEBUG 0 -#endif - -#ifndef NULL -#define NULL ((void *) 0) -#endif - -#define BITS(x) (8*sizeof(x)) -#define ARRAY_LEN(x) (sizeof (x)/sizeof (x[0])) - -#define _STRUCT_FIELD(t,f) (((t *) 0)->f) -#define STRUCT_OFFSET_OF(t,f) ((uword) & _STRUCT_FIELD (t, f)) -#define STRUCT_BIT_OFFSET_OF(t,f) (BITS(u8) * (uword) & _STRUCT_FIELD (t, f)) -#define STRUCT_SIZE_OF(t,f) (sizeof (_STRUCT_FIELD (t, f))) -#define STRUCT_BITS_OF(t,f) (BITS (_STRUCT_FIELD (t, f))) -#define STRUCT_ARRAY_LEN(t,f) ARRAY_LEN (_STRUCT_FIELD (t, f)) -#define STRUCT_MARK(mark) u8 mark[0] -#define STRUCT_MARK_PTR(v, f) &(v)->f - -/* Stride in bytes between struct array elements. */ -#define STRUCT_STRIDE_OF(t,f) \ - ( ((uword) & (((t *) 0)[1].f)) \ - - ((uword) & (((t *) 0)[0].f))) - -#define STRUCT_OFFSET_OF_VAR(v,f) ((uword) (&(v)->f) - (uword) (v)) - -/* Used to pack structure elements. */ -#define CLIB_PACKED(x) x __attribute__ ((packed)) -#define CLIB_UNUSED(x) x __attribute__ ((unused)) - -#define never_inline __attribute__ ((__noinline__)) - -#if CLIB_DEBUG > 0 -#define always_inline static inline -#define static_always_inline static inline -#else -#define always_inline static inline __attribute__ ((__always_inline__)) -#define static_always_inline static inline __attribute__ ((__always_inline__)) -#endif - - -/* Reserved (unused) structure element with address offset between - from and to. */ -#define CLIB_PAD_FROM_TO(from,to) u8 pad_##from[(to) - (from)] - -/* Hints to compiler about hot/cold code. */ -#define PREDICT_FALSE(x) __builtin_expect((x),0) -#define PREDICT_TRUE(x) __builtin_expect((x),1) - -/* Full memory barrier (read and write). */ -#define CLIB_MEMORY_BARRIER() __sync_synchronize () - -/* Arranges for function to be called before main. */ -#define INIT_FUNCTION(decl) \ - decl __attribute ((constructor)); \ - decl - -/* Arranges for function to be called before exit. */ -#define EXIT_FUNCTION(decl) \ - decl __attribute ((destructor)); \ - decl - -/* Use __builtin_clz if available. */ -#ifdef __GNUC__ -#include <features.h> -#if __GNUC_PREREQ(3, 4) -#if uword_bits == 64 -#define count_leading_zeros(count,x) count = __builtin_clzll (x) -#define count_trailing_zeros(count,x) count = __builtin_ctzll (x) -#else -#define count_leading_zeros(count,x) count = __builtin_clzl (x) -#define count_trailing_zeros(count,x) count = __builtin_ctzl (x) -#endif -#endif -#endif - -#ifndef count_leading_zeros - -/* Misc. integer arithmetic functions. */ -#if defined (i386) -#define count_leading_zeros(count, x) \ - do { \ - word _clz; \ - __asm__ ("bsrl %1,%0" \ - : "=r" (_clz) : "rm" ((word) (x)));\ - (count) = _clz ^ 31; \ - } while (0) - -#define count_trailing_zeros(count, x) \ - __asm__ ("bsfl %1,%0" : "=r" (count) : "rm" ((word)(x))) -#endif /* i386 */ - -#if defined (__alpha__) && defined (HAVE_CIX) -#define count_leading_zeros(count, x) \ - __asm__ ("ctlz %1,%0" \ - : "=r" ((word) (count)) \ - : "r" ((word) (x))) -#define count_trailing_zeros(count, x) \ - __asm__ ("cttz %1,%0" \ - : "=r" ((word) (count)) \ - : "r" ((word) (x))) -#endif /* alpha && HAVE_CIX */ - -#if __mips >= 4 - -/* Select between 32/64 opcodes. */ -#if uword_bits == 32 -#define count_leading_zeros(_count, _x) \ - __asm__ ("clz %[count],%[x]" \ - : [count] "=r" ((word) (_count)) \ - : [x] "r" ((word) (_x))) -#else -#define count_leading_zeros(_count, _x) \ - __asm__ ("dclz %[count],%[x]" \ - : [count] "=r" ((word) (_count)) \ - : [x] "r" ((word) (_x))) -#endif - -#endif /* __mips >= 4 */ - -#endif /* count_leading_zeros */ - -#if defined (count_leading_zeros) -always_inline uword -min_log2 (uword x) -{ - uword n; - count_leading_zeros (n, x); - return BITS (uword) - n - 1; -} -#else -always_inline uword -min_log2 (uword x) -{ - uword a = x, b = BITS (uword) / 2, c = 0, r = 0; - - /* Reduce x to 4 bit result. */ -#define _ \ -{ \ - c = a >> b; \ - if (c) a = c; \ - if (c) r += b; \ - b /= 2; \ -} - - if (BITS (uword) > 32) - _; - _; - _; - _; -#undef _ - - /* Do table lookup on 4 bit partial. */ - if (BITS (uword) > 32) - { - const u64 table = 0x3333333322221104LL; - uword t = (table >> (4 * a)) & 0xf; - r = t < 4 ? r + t : ~0; - } - else - { - const u32 table = 0x22221104; - uword t = (a & 8) ? 3 : ((table >> (4 * a)) & 0xf); - r = t < 4 ? r + t : ~0; - } - - return r; -} -#endif - -always_inline uword -max_log2 (uword x) -{ - uword l = min_log2 (x); - if (x > ((uword) 1 << l)) - l++; - return l; -} - -always_inline u64 -min_log2_u64 (u64 x) -{ - if (BITS (uword) == 64) - return min_log2 (x); - else - { - uword l, y; - y = x; - l = 0; - if (y == 0) - { - l += 32; - x >>= 32; - } - l += min_log2 (x); - return l; - } -} - -always_inline uword -pow2_mask (uword x) -{ - return ((uword) 1 << x) - (uword) 1; -} - -always_inline uword -max_pow2 (uword x) -{ - word y = (word) 1 << min_log2 (x); - if (x > y) - y *= 2; - return y; -} - -always_inline uword -is_pow2 (uword x) -{ - return 0 == (x & (x - 1)); -} - -always_inline uword -round_pow2 (uword x, uword pow2) -{ - return (x + pow2 - 1) & ~(pow2 - 1); -} - -always_inline u64 -round_pow2_u64 (u64 x, u64 pow2) -{ - return (x + pow2 - 1) & ~(pow2 - 1); -} - -always_inline uword -first_set (uword x) -{ - return x & -x; -} - -always_inline uword -log2_first_set (uword x) -{ - uword result; -#ifdef count_trailing_zeros - count_trailing_zeros (result, x); -#else - result = min_log2 (first_set (x)); -#endif - return result; -} - -always_inline f64 -flt_round_down (f64 x) -{ - return (int) x; -} - -always_inline word -flt_round_nearest (f64 x) -{ - return (word) (x + .5); -} - -always_inline f64 -flt_round_to_multiple (f64 x, f64 f) -{ - return f * flt_round_nearest (x / f); -} - -#define clib_max(x,y) \ -({ \ - __typeof__ (x) _x = (x); \ - __typeof__ (y) _y = (y); \ - _x > _y ? _x : _y; \ -}) - -#define clib_min(x,y) \ -({ \ - __typeof__ (x) _x = (x); \ - __typeof__ (y) _y = (y); \ - _x < _y ? _x : _y; \ -}) - -#define clib_abs(x) \ -({ \ - __typeof__ (x) _x = (x); \ - _x < 0 ? -_x : _x; \ -}) - -/* Standard standalone-only function declarations. */ -#ifndef CLIB_UNIX -void clib_standalone_init (void *memory, uword memory_bytes); - -void qsort (void *base, uword n, uword size, - int (*)(const void *, const void *)); -#endif - -/* Stack backtrace. */ -uword -clib_backtrace (uword * callers, uword max_callers, uword n_frames_to_skip); - -#endif /* included_clib_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/cpu.c b/vppinfra/vppinfra/cpu.c deleted file mode 100644 index a26d5c9ae10..00000000000 --- a/vppinfra/vppinfra/cpu.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include <vppinfra/clib.h> -#include <vppinfra/format.h> -#include <vppinfra/cpu.h> - -#define foreach_x86_cpu_uarch \ - _(0x06, 0x4f, "Broadwell", "Broadwell-EP/EX") \ - _(0x06, 0x3d, "Broadwell", "Broadwell") \ - _(0x06, 0x3f, "Haswell", "Haswell-E") \ - _(0x06, 0x3c, "Haswell", "Haswell") \ - _(0x06, 0x3e, "IvyBridge", "IvyBridge-E/EN/EP") \ - _(0x06, 0x3a, "IvyBridge", "IvyBridge") \ - _(0x06, 0x2a, "SandyBridge", "SandyBridge") \ - _(0x06, 0x2d, "SandyBridge", "SandyBridge-E/EN/EP") \ - _(0x06, 0x25, "Westmere", "Arrandale,Clarksdale") \ - _(0x06, 0x2c, "Westmere", "Westmere-EP/EX,Gulftown") \ - _(0x06, 0x2f, "Westmere", "Westmere-EX") \ - _(0x06, 0x1e, "Nehalem", "Clarksfield,Lynnfield,Jasper Forest") \ - _(0x06, 0x1a, "Nehalem", "Nehalem-EP,Bloomfield)") \ - _(0x06, 0x2e, "Nehalem", "Nehalem-EX") \ - _(0x06, 0x17, "Penryn", "Yorkfield,Wolfdale,Penryn,Harpertown (DP)") \ - _(0x06, 0x1d, "Penryn", "Dunnington (MP)") \ - _(0x06, 0x37, "Atom", "Bay Trail") \ - _(0x06, 0x36, "Atom", "Cedarview") \ - _(0x06, 0x26, "Atom", "Lincroft") \ - _(0x06, 0x1c, "Atom", "Pineview/Silverthorne") - -u8 * -format_cpu_uarch (u8 * s, va_list * args) -{ -#if __x86_64__ - u32 __attribute__ ((unused)) eax, ebx, ecx, edx; - u8 model, family; - - if (__get_cpuid (1, &eax, &ebx, &ecx, &edx) == 0) - return format (s, "unknown (missing cpuid)"); - - model = ((eax >> 4) & 0x0f) | ((eax >> 12) & 0xf0); - family = (eax >> 8) & 0x0f; - -#define _(f,m,a,c) if ((model == m) && (family == f)) return format(s, "%s (%s)", a, c); - foreach_x86_cpu_uarch -#undef _ - return format (s, "unknown (family 0x%02x model 0x%02x)", family, model); - -#else /* ! __x86_64__ */ - return format (s, "unknown"); -#endif -} - -u8 * -format_cpu_model_name (u8 * s, va_list * args) -{ -#if __x86_64__ - u32 __attribute__ ((unused)) eax, ebx, ecx, edx; - u8 *name = 0; - u32 *name_u32; - - if (__get_cpuid (1, &eax, &ebx, &ecx, &edx) == 0) - return format (s, "unknown (missing cpuid)"); - - __get_cpuid (0x80000000, &eax, &ebx, &ecx, &edx); - if (eax < 0x80000004) - return format (s, "unknown (missing ext feature)"); - - vec_validate (name, 48); - name_u32 = (u32 *) name; - - __get_cpuid (0x80000002, &eax, &ebx, &ecx, &edx); - name_u32[0] = eax; - name_u32[1] = ebx; - name_u32[2] = ecx; - name_u32[3] = edx; - - __get_cpuid (0x80000003, &eax, &ebx, &ecx, &edx); - name_u32[4] = eax; - name_u32[5] = ebx; - name_u32[6] = ecx; - name_u32[7] = edx; - - __get_cpuid (0x80000004, &eax, &ebx, &ecx, &edx); - name_u32[8] = eax; - name_u32[9] = ebx; - name_u32[10] = ecx; - name_u32[11] = edx; - - s = format (s, "%s", name); - vec_free (name); - return s; - -#elif defined(__aarch64__) - return format (s, "armv8"); -#else /* ! __x86_64__ */ - return format (s, "unknown"); -#endif -} - -u8 * -format_cpu_flags (u8 * s, va_list * args) -{ -#if defined(__x86_64__) -#define _(flag, func, reg, bit) \ - if (clib_cpu_supports_ ## flag()) \ - s = format (s, #flag " "); - foreach_x86_64_flags return s; -#undef _ -#else /* ! __x86_64__ */ - return format (s, "unknown"); -#endif -} - - - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/cpu.h b/vppinfra/vppinfra/cpu.h deleted file mode 100644 index 9c149f3fa2a..00000000000 --- a/vppinfra/vppinfra/cpu.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef included_clib_cpu_h -#define included_clib_cpu_h - -#include <vppinfra/format.h> - -/* - * multiarchitecture support. Adding new entry will produce - * new graph node function variant optimized for specific cpu - * microarchitecture. - * Order is important for runtime selection, as 1st match wins... - */ - -#if __x86_64__ && CLIB_DEBUG == 0 -#define foreach_march_variant(macro, x) \ - macro(avx2, x, "arch=core-avx2") -#else -#define foreach_march_variant(macro, x) -#endif - - -#if __GNUC__ > 4 && !__clang__ -#define CLIB_CPU_OPTIMIZED __attribute__ ((optimize ("tree-vectorize"))) -#else -#define CLIB_CPU_OPTIMIZED -#endif - - -#define CLIB_MULTIARCH_ARCH_CHECK(arch, fn, tgt) \ - if (clib_cpu_supports_ ## arch()) \ - return & fn ## _ ##arch; - -#define CLIB_MULTIARCH_SELECT_FN(fn,...) \ - __VA_ARGS__ void * fn ## _multiarch_select(void) \ -{ \ - foreach_march_variant(CLIB_MULTIARCH_ARCH_CHECK, fn) \ - return & fn; \ -} - - -#define foreach_x86_64_flags \ -_ (sse3, 1, ecx, 0) \ -_ (ssse3, 1, ecx, 9) \ -_ (sse41, 1, ecx, 19) \ -_ (sse42, 1, ecx, 20) \ -_ (avx, 1, ecx, 28) \ -_ (avx2, 7, ebx, 5) \ -_ (avx512f, 7, ebx, 16) \ -_ (aes, 1, ecx, 25) \ -_ (sha, 7, ebx, 29) \ -_ (invariant_tsc, 0x80000007, edx, 8) - -#if defined(__x86_64__) -#include "cpuid.h" - -static inline int -clib_get_cpuid (const u32 lev, u32 * eax, u32 * ebx, u32 * ecx, u32 * edx) -{ - if ((u32) __get_cpuid_max (0x80000000 & lev, 0) < lev) - return 0; - if (lev == 7) - __cpuid_count (lev, 0, *eax, *ebx, *ecx, *edx); - else - __cpuid (lev, *eax, *ebx, *ecx, *edx); - return 1; -} - - -#define _(flag, func, reg, bit) \ -static inline int \ -clib_cpu_supports_ ## flag() \ -{ \ - u32 __attribute__((unused)) eax, ebx = 0, ecx = 0, edx = 0; \ - clib_get_cpuid (func, &eax, &ebx, &ecx, &edx); \ - \ - return ((reg & (1 << bit)) != 0); \ -} -foreach_x86_64_flags -#undef _ -#else - -#define _(flag, func, reg, bit) \ -static inline int clib_cpu_supports_ ## flag() { return 0; } -foreach_x86_64_flags -#undef _ -#endif -#endif - format_function_t format_cpu_uarch; -format_function_t format_cpu_model_name; -format_function_t format_cpu_flags; - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/dir.dox b/vppinfra/vppinfra/dir.dox deleted file mode 100644 index 440c44e8f56..00000000000 --- a/vppinfra/vppinfra/dir.dox +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * Copyright (c) 2016 Comcast Cable Communications Management, LLC. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/** @dir - * @brief VPP infrastructure library source. - */ diff --git a/vppinfra/vppinfra/dlist.h b/vppinfra/vppinfra/dlist.h deleted file mode 100644 index 7d09b2bbc7e..00000000000 --- a/vppinfra/vppinfra/dlist.h +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. -*/ - -#ifndef included_dlist_h -#define included_dlist_h - -#include <stdarg.h> -#include <vppinfra/clib.h> -#include <vppinfra/vec.h> -#include <vppinfra/pool.h> -#include <vppinfra/error.h> -#include <vppinfra/format.h> -#include <vppinfra/cache.h> - -typedef struct -{ - u32 next; - u32 prev; - u32 value; -} dlist_elt_t; - -static inline void -clib_dlist_init (dlist_elt_t * pool, u32 index) -{ - dlist_elt_t *head = pool_elt_at_index (pool, index); - memset (head, 0xFF, sizeof (*head)); -} - -static inline void -clib_dlist_addtail (dlist_elt_t * pool, u32 head_index, u32 new_index) -{ - dlist_elt_t *head = pool_elt_at_index (pool, head_index); - u32 old_last_index; - dlist_elt_t *old_last; - dlist_elt_t *new; - - ASSERT (head->value == ~0); - - new = pool_elt_at_index (pool, new_index); - - if (PREDICT_FALSE (head->next == ~0)) - { - head->next = head->prev = new_index; - new->next = new->prev = head_index; - return; - } - - old_last_index = head->prev; - old_last = pool_elt_at_index (pool, old_last_index); - - new->next = old_last->next; - new->prev = old_last_index; - old_last->next = new_index; - head->prev = new_index; -} - -static inline void -clib_dlist_addhead (dlist_elt_t * pool, u32 head_index, u32 new_index) -{ - dlist_elt_t *head = pool_elt_at_index (pool, head_index); - dlist_elt_t *old_first; - u32 old_first_index; - dlist_elt_t *new; - - ASSERT (head->value == ~0); - - new = pool_elt_at_index (pool, new_index); - - if (PREDICT_FALSE (head->next == ~0)) - { - head->next = head->prev = new_index; - new->next = new->prev = head_index; - return; - } - - old_first_index = head->next; - old_first = pool_elt_at_index (pool, old_first_index); - - new->next = old_first_index; - new->prev = old_first->prev; - old_first->prev = new_index; - head->next = new_index; -} - -static inline void -clib_dlist_remove (dlist_elt_t * pool, u32 index) -{ - dlist_elt_t *elt = pool_elt_at_index (pool, index); - dlist_elt_t *next_elt, *prev_elt; - - /* listhead, not so much */ - ASSERT (elt->value != ~0); - - next_elt = pool_elt_at_index (pool, elt->next); - prev_elt = pool_elt_at_index (pool, elt->prev); - - next_elt->prev = elt->prev; - prev_elt->next = elt->next; - - elt->prev = elt->next = ~0; -} - -static inline u32 -clib_dlist_remove_head (dlist_elt_t * pool, u32 head_index) -{ - dlist_elt_t *head = pool_elt_at_index (pool, head_index); - u32 rv; - - ASSERT (head->value == ~0); - - if (head->next == ~0) - return ~0; - - rv = head->next; - clib_dlist_remove (pool, rv); - return rv; -} - -static inline u32 -clib_dlist_remove_tail (dlist_elt_t * pool, u32 head_index) -{ - dlist_elt_t *head = pool_elt_at_index (pool, head_index); - u32 rv; - - ASSERT (head->value == ~0); - - if (head->prev == ~0) - return ~0; - - rv = head->prev; - clib_dlist_remove (pool, rv); - return rv; -} - -#endif /* included_dlist_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/elf.c b/vppinfra/vppinfra/elf.c deleted file mode 100644 index 84d6282f1f7..00000000000 --- a/vppinfra/vppinfra/elf.c +++ /dev/null @@ -1,2040 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include <vppinfra/bitmap.h> -#include <vppinfra/byte_order.h> -#include <vppinfra/error.h> -#include <vppinfra/hash.h> -#include <vppinfra/vec.h> -#include <vppinfra/elf.h> - -always_inline void -elf_swap_first_header (elf_main_t * em, elf_first_header_t * h) -{ - h->architecture = elf_swap_u16 (em, h->architecture); - h->file_type = elf_swap_u16 (em, h->file_type); - h->file_version = elf_swap_u32 (em, h->file_version); -} - -always_inline void -elf_swap_verneed (elf_dynamic_version_need_t * n) -{ -#define _(t,f) n->f = clib_byte_swap_##t (n->f); - foreach_elf_dynamic_version_need_field -#undef _ -} - -always_inline void -elf_swap_verneed_aux (elf_dynamic_version_need_aux_t * n) -{ -#define _(t,f) n->f = clib_byte_swap_##t (n->f); - foreach_elf_dynamic_version_need_aux_field -#undef _ -} - -clib_error_t * -elf_get_section_by_name (elf_main_t * em, char *section_name, - elf_section_t ** result) -{ - uword *p; - - p = hash_get_mem (em->section_by_name, section_name); - if (!p) - return clib_error_return (0, "no such section `%s'", section_name); - - *result = vec_elt_at_index (em->sections, p[0]); - return 0; -} - -elf_section_t * -elf_get_section_by_start_address_no_check (elf_main_t * em, - uword start_address) -{ - uword *p = hash_get (em->section_by_start_address, start_address); - return p ? vec_elt_at_index (em->sections, p[0]) : 0; -} - -clib_error_t * -elf_get_section_by_start_address (elf_main_t * em, uword start_address, - elf_section_t ** result) -{ - elf_section_t *s = - elf_get_section_by_start_address_no_check (em, start_address); - if (!s) - return clib_error_return (0, "no section with address 0x%wx", - start_address); - *result = s; - return 0; -} - -static u8 * -format_elf_section_type (u8 * s, va_list * args) -{ - elf_section_type_t type = va_arg (*args, elf_section_type_t); - char *t = 0; - - switch (type) - { -#define _(f,i) case ELF_SECTION_##f: t = #f; break; - foreach_elf_section_type -#undef _ - } - - if (!t) - s = format (s, "unknown 0x%x", type); - else - s = format (s, "%s", t); - return s; -} - -static u8 * -format_elf_section (u8 * s, va_list * args) -{ - elf_main_t *em = va_arg (*args, elf_main_t *); - elf_section_t *es = va_arg (*args, elf_section_t *); - elf64_section_header_t *h = &es->header; - - if (!h) - return format (s, "%=40s%=10s%=20s%=8s%=16s%=16s%=16s", - "Name", "Index", "Type", "Size", "Align", "Address", - "File offset"); - - s = format (s, "%-40s%10d%=20U%8Lx%16d%16Lx %Lx-%Lx", - elf_section_name (em, es), - es->index, - format_elf_section_type, h->type, - h->file_size, - h->align, - h->exec_address, h->file_offset, h->file_offset + h->file_size); - - if (h->flags != 0) - { -#define _(f,i) \ - if (h->flags & ELF_SECTION_FLAG_##f) s = format (s, " %s", #f); - foreach_elf_section_flag; -#undef _ - } - - return s; -} - -static u8 * -format_elf_segment_type (u8 * s, va_list * args) -{ - elf_segment_type_t type = va_arg (*args, elf_segment_type_t); - char *t = 0; - - switch (type) - { -#define _(f,i) case ELF_SEGMENT_##f: t = #f; break; - foreach_elf_segment_type -#undef _ - } - - if (!t) - s = format (s, "unknown 0x%x", type); - else - s = format (s, "%s", t); - return s; -} - -static u8 * -format_elf_segment (u8 * s, va_list * args) -{ - elf_segment_t *es = va_arg (*args, elf_segment_t *); - elf64_segment_header_t *h = &es->header; - - if (!h) - return format (s, "%=16s%=16s%=16s%=16s", - "Type", "Virt. Address", "Phys. Address", "Size"); - - s = format (s, "%=16U%16Lx%16Lx%16Lx%16Lx", - format_elf_segment_type, h->type, - h->virtual_address, - h->physical_address, h->memory_size, h->file_offset); - - if (h->flags != 0) - { -#define _(f,i) \ - if (h->flags & ELF_SEGMENT_FLAG_##f) s = format (s, " %s", #f); - foreach_elf_segment_flag; -#undef _ - } - - return s; -} - -static u8 * -format_elf_symbol_binding_and_type (u8 * s, va_list * args) -{ - int bt = va_arg (*args, int); - int b, t; - char *type_string = 0; - char *binding_string = 0; - - switch ((b = ((bt >> 4) & 0xf))) - { -#define _(f,n) case n: binding_string = #f; break; - foreach_elf_symbol_binding; -#undef _ - default: - break; - } - - switch ((t = ((bt >> 0) & 0xf))) - { -#define _(f,n) case n: type_string = #f; break; - foreach_elf_symbol_type; -#undef _ - default: - break; - } - - if (binding_string) - s = format (s, "%s", binding_string); - else - s = format (s, "binding 0x%x", b); - - if (type_string) - s = format (s, " %s", type_string); - else - s = format (s, " type 0x%x", t); - - return s; -} - -static u8 * -format_elf_symbol_visibility (u8 * s, va_list * args) -{ - int visibility = va_arg (*args, int); - char *t = 0; - - switch (visibility) - { -#define _(f,n) case n: t = #f; break; - foreach_elf_symbol_visibility -#undef _ - } - - if (t) - return format (s, "%s", t); - else - return format (s, "unknown 0x%x", visibility); -} - -static u8 * -format_elf_symbol_section_name (u8 * s, va_list * args) -{ - elf_main_t *em = va_arg (*args, elf_main_t *); - int si = va_arg (*args, int); - char *t = 0; - - if (si < vec_len (em->sections)) - { - elf_section_t *es = vec_elt_at_index (em->sections, si); - return format (s, "%s", elf_section_name (em, es)); - } - - if (si >= ELF_SYMBOL_SECTION_RESERVED_LO - && si <= ELF_SYMBOL_SECTION_RESERVED_HI) - { - switch (si) - { -#define _(f,n) case n: t = #f; break; - foreach_elf_symbol_reserved_section_index -#undef _ - default: - break; - } - } - - if (t) - return format (s, "%s", t); - else - return format (s, "unknown 0x%x", si); -} - -u8 * -format_elf_symbol (u8 * s, va_list * args) -{ - elf_main_t *em = va_arg (*args, elf_main_t *); - elf_symbol_table_t *t = va_arg (*args, elf_symbol_table_t *); - elf64_symbol_t *sym = va_arg (*args, elf64_symbol_t *); - - if (!sym) - return format (s, "%=32s%=16s%=16s%=16s%=16s%=16s", - "Symbol", "Size", "Value", "Type", "Visibility", - "Section"); - - s = format (s, "%-32s%16Ld%16Lx%=16U%=16U%U", - elf_symbol_name (t, sym), - sym->size, sym->value, - format_elf_symbol_binding_and_type, sym->binding_and_type, - format_elf_symbol_visibility, sym->visibility, - format_elf_symbol_section_name, em, sym->section_index); - - return s; -} - -static u8 * -format_elf_relocation_type (u8 * s, va_list * args) -{ - elf_main_t *em = va_arg (*args, elf_main_t *); - int type = va_arg (*args, int); - char *t = 0; - - switch (em->first_header.architecture) - { -#define _(f,i) [i] = #f, - - case ELF_ARCH_X86_64: - { - static char *tab[] = { - foreach_elf_x86_64_relocation_type - }; - -#undef _ - if (type < ARRAY_LEN (tab)) - t = tab[type]; - break; - } - - default: - break; - } - - if (!t) - s = format (s, "0x%02x", type); - else - s = format (s, "%s", t); - - return s; -} - -static u8 * -format_elf_relocation (u8 * s, va_list * args) -{ - elf_main_t *em = va_arg (*args, elf_main_t *); - elf_relocation_with_addend_t *r = - va_arg (*args, elf_relocation_with_addend_t *); - elf_symbol_table_t *t; - elf64_symbol_t *sym; - - if (!r) - return format (s, "%=16s%=16s%=16s", "Address", "Type", "Symbol"); - - t = vec_elt_at_index (em->symbol_tables, 0); - sym = vec_elt_at_index (t->symbols, r->symbol_and_type >> 32); - - s = format (s, "%16Lx%16U", - r->address, - format_elf_relocation_type, em, r->symbol_and_type & 0xff); - - if (sym->section_index != 0) - { - elf_section_t *es; - es = vec_elt_at_index (em->sections, sym->section_index); - s = format (s, " (section %s)", elf_section_name (em, es)); - } - - if (sym->name != 0) - s = format (s, " %s", elf_symbol_name (t, sym)); - - { - i64 a = r->addend; - if (a != 0) - s = format (s, " %c 0x%Lx", a > 0 ? '+' : '-', a > 0 ? a : -a); - } - - return s; -} - -static u8 * -format_elf_dynamic_entry_type (u8 * s, va_list * args) -{ - u32 type = va_arg (*args, u32); - char *t = 0; - switch (type) - { -#define _(f,n) case n: t = #f; break; - foreach_elf_dynamic_entry_type; -#undef _ - default: - break; - } - if (t) - return format (s, "%s", t); - else - return format (s, "unknown 0x%x", type); -} - -static u8 * -format_elf_dynamic_entry (u8 * s, va_list * args) -{ - elf_main_t *em = va_arg (*args, elf_main_t *); - elf64_dynamic_entry_t *e = va_arg (*args, elf64_dynamic_entry_t *); - - if (!e) - return format (s, "%=40s%=16s", "Type", "Data"); - - s = format (s, "%=40U", format_elf_dynamic_entry_type, (u32) e->type); - switch (e->type) - { - case ELF_DYNAMIC_ENTRY_NEEDED_LIBRARY: - case ELF_DYNAMIC_ENTRY_RPATH: - case ELF_DYNAMIC_ENTRY_RUN_PATH: - s = format (s, "%s", em->dynamic_string_table + e->data); - break; - - case ELF_DYNAMIC_ENTRY_INIT_FUNCTION: - case ELF_DYNAMIC_ENTRY_FINI_FUNCTION: - case ELF_DYNAMIC_ENTRY_SYMBOL_HASH: - case ELF_DYNAMIC_ENTRY_GNU_HASH: - case ELF_DYNAMIC_ENTRY_STRING_TABLE: - case ELF_DYNAMIC_ENTRY_SYMBOL_TABLE: - case ELF_DYNAMIC_ENTRY_PLT_GOT: - case ELF_DYNAMIC_ENTRY_PLT_RELOCATION_ADDRESS: - case ELF_DYNAMIC_ENTRY_RELA_ADDRESS: - case ELF_DYNAMIC_ENTRY_VERSION_NEED: - case ELF_DYNAMIC_ENTRY_VERSYM: - { - elf_section_t *es = - elf_get_section_by_start_address_no_check (em, e->data); - if (es) - s = format (s, "section %s", elf_section_name (em, es)); - else - s = format (s, "0x%Lx", e->data); - break; - } - - default: - s = format (s, "0x%Lx", e->data); - break; - } - - return s; -} - -static u8 * -format_elf_architecture (u8 * s, va_list * args) -{ - int a = va_arg (*args, int); - char *t; - - switch (a) - { -#define _(f,n) case n: t = #f; break; - foreach_elf_architecture; -#undef _ - default: - return format (s, "unknown 0x%x", a); - } - - return format (s, "%s", t); -} - -static u8 * -format_elf_abi (u8 * s, va_list * args) -{ - int a = va_arg (*args, int); - char *t; - - switch (a) - { -#define _(f,n) case n: t = #f; break; - foreach_elf_abi; -#undef _ - default: - return format (s, "unknown 0x%x", a); - } - - return format (s, "%s", t); -} - -static u8 * -format_elf_file_class (u8 * s, va_list * args) -{ - int a = va_arg (*args, int); - char *t; - - switch (a) - { -#define _(f) case ELF_##f: t = #f; break; - foreach_elf_file_class; -#undef _ - default: - return format (s, "unknown 0x%x", a); - } - - return format (s, "%s", t); -} - -static u8 * -format_elf_file_type (u8 * s, va_list * args) -{ - int a = va_arg (*args, int); - char *t; - - if (a >= ELF_ARCH_SPECIFIC_LO && a <= ELF_ARCH_SPECIFIC_HI) - return format (s, "arch-specific 0x%x", a - ELF_ARCH_SPECIFIC_LO); - - if (a >= ELF_OS_SPECIFIC_LO && a <= ELF_OS_SPECIFIC_HI) - return format (s, "os-specific 0x%x", a - ELF_OS_SPECIFIC_LO); - - switch (a) - { -#define _(f,n) case n: t = #f; break; - foreach_elf_file_type; -#undef _ - default: - return format (s, "unknown 0x%x", a); - } - - return format (s, "%s", t); -} - -static u8 * -format_elf_data_encoding (u8 * s, va_list * args) -{ - int a = va_arg (*args, int); - char *t; - - switch (a) - { -#define _(f) case ELF_##f: t = #f; break; - foreach_elf_data_encoding; -#undef _ - default: - return format (s, "unknown 0x%x", a); - } - - return format (s, "%s", t); -} - -static int -elf_section_offset_compare (void *a1, void *a2) -{ - elf_section_t *s1 = a1; - elf_section_t *s2 = a2; - - return ((i64) s1->header.file_offset - (i64) s2->header.file_offset); -} - -static int -elf_segment_va_compare (void *a1, void *a2) -{ - elf_segment_t *s1 = a1; - elf_segment_t *s2 = a2; - - return ((i64) s1->header.virtual_address - - (i64) s2->header.virtual_address); -} - -u8 * -format_elf_main (u8 * s, va_list * args) -{ - elf_main_t *em = va_arg (*args, elf_main_t *); - u32 verbose = va_arg (*args, u32); - elf64_file_header_t *fh = &em->file_header; - - s = - format (s, - "File header: machine: %U, file type/class %U/%U, data-encoding: %U, abi: %U version %d\n", - format_elf_architecture, em->first_header.architecture, - format_elf_file_type, em->first_header.file_type, - format_elf_file_class, em->first_header.file_class, - format_elf_data_encoding, em->first_header.data_encoding, - format_elf_abi, em->first_header.abi, - em->first_header.abi_version); - - s = format (s, " entry 0x%Lx, arch-flags 0x%x", - em->file_header.entry_point, em->file_header.flags); - - if (em->interpreter) - s = format (s, "\n interpreter: %s", em->interpreter); - - { - elf_section_t *h, *copy; - - copy = 0; - vec_foreach (h, em->sections) if (h->header.type != ~0) - vec_add1 (copy, h[0]); - - vec_sort_with_function (copy, elf_section_offset_compare); - - s = format (s, "\nSections %d at file offset 0x%Lx-0x%Lx:\n", - fh->section_header_count, - fh->section_header_file_offset, - fh->section_header_file_offset + - (u64) fh->section_header_count * fh->section_header_size); - s = format (s, "%U\n", format_elf_section, em, 0); - vec_foreach (h, copy) s = format (s, "%U\n", format_elf_section, em, h); - - vec_free (copy); - } - - { - elf_segment_t *h, *copy; - - copy = 0; - vec_foreach (h, em->segments) - if (h->header.type != ELF_SEGMENT_UNUSED && h->header.type != ~0) - vec_add1 (copy, h[0]); - - /* Sort segments by address. */ - vec_sort_with_function (copy, elf_segment_va_compare); - - s = format (s, "\nSegments: %d at file offset 0x%Lx-0x%Lx:\n", - fh->segment_header_count, - fh->segment_header_file_offset, - (u64) fh->segment_header_file_offset + - (u64) fh->segment_header_count * - (u64) fh->segment_header_size); - - s = format (s, "%U\n", format_elf_segment, 0); - vec_foreach (h, copy) s = format (s, "%U\n", format_elf_segment, h); - - vec_free (copy); - } - - if ((verbose & FORMAT_ELF_MAIN_SYMBOLS) && vec_len (em->symbol_tables) > 0) - { - elf_symbol_table_t *t; - elf64_symbol_t *sym; - elf_section_t *es; - - vec_foreach (t, em->symbol_tables) - { - es = vec_elt_at_index (em->sections, t->section_index); - s = - format (s, "\nSymbols for section %s:\n", - elf_section_name (em, es)); - - s = format (s, "%U\n", format_elf_symbol, em, 0, 0); - vec_foreach (sym, t->symbols) - s = format (s, "%U\n", format_elf_symbol, em, t, sym); - } - } - - if ((verbose & FORMAT_ELF_MAIN_RELOCATIONS) - && vec_len (em->relocation_tables) > 0) - { - elf_relocation_table_t *t; - elf_relocation_with_addend_t *r; - elf_section_t *es; - - vec_foreach (t, em->relocation_tables) - { - es = vec_elt_at_index (em->sections, t->section_index); - r = t->relocations; - s = format (s, "\nRelocations for section %s:\n", - elf_section_name (em, es)); - - s = format (s, "%U\n", format_elf_relocation, em, 0); - vec_foreach (r, t->relocations) - { - s = format (s, "%U\n", format_elf_relocation, em, r); - } - } - } - - if ((verbose & FORMAT_ELF_MAIN_DYNAMIC) - && vec_len (em->dynamic_entries) > 0) - { - elf64_dynamic_entry_t *es, *e; - s = format (s, "\nDynamic linker information:\n"); - es = vec_dup (em->dynamic_entries); - s = format (s, "%U\n", format_elf_dynamic_entry, em, 0); - vec_foreach (e, es) - s = format (s, "%U\n", format_elf_dynamic_entry, em, e); - } - - return s; -} - -static void -elf_parse_segments (elf_main_t * em, void *data) -{ - void *d = data + em->file_header.segment_header_file_offset; - uword n = em->file_header.segment_header_count; - uword i; - - vec_resize (em->segments, n); - - for (i = 0; i < n; i++) - { - em->segments[i].index = i; - - if (em->first_header.file_class == ELF_64BIT) - { - elf64_segment_header_t *h = d; -#define _(t,f) em->segments[i].header.f = elf_swap_##t (em, h->f); - foreach_elf64_segment_header -#undef _ - d = (h + 1); - } - else - { - elf32_segment_header_t *h = d; -#define _(t,f) em->segments[i].header.f = elf_swap_##t (em, h->f); - foreach_elf32_segment_header -#undef _ - d = (h + 1); - } - } -} - -static void -elf_parse_sections (elf_main_t * em, void *data) -{ - elf64_file_header_t *fh = &em->file_header; - elf_section_t *s; - void *d = data + fh->section_header_file_offset; - uword n = fh->section_header_count; - uword i; - - vec_resize (em->sections, n); - - for (i = 0; i < n; i++) - { - s = em->sections + i; - - s->index = i; - - if (em->first_header.file_class == ELF_64BIT) - { - elf64_section_header_t *h = d; -#define _(t,f) em->sections[i].header.f = elf_swap_##t (em, h->f); - foreach_elf64_section_header -#undef _ - d = (h + 1); - } - else - { - elf32_section_header_t *h = d; -#define _(t,f) em->sections[i].header.f = elf_swap_##t (em, h->f); - foreach_elf32_section_header -#undef _ - d = (h + 1); - } - - if (s->header.type != ELF_SECTION_NO_BITS) - vec_add (s->contents, data + s->header.file_offset, - s->header.file_size); - } - - s = vec_elt_at_index (em->sections, fh->section_header_string_table_index); - - em->section_by_name - = hash_create_string ( /* # elts */ vec_len (em->sections), - /* sizeof of value */ sizeof (uword)); - - vec_foreach (s, em->sections) - { - hash_set_mem (em->section_by_name, - elf_section_name (em, s), s - em->sections); - hash_set (em->section_by_start_address, - s->header.exec_address, s - em->sections); - } -} - -static void -add_symbol_table (elf_main_t * em, elf_section_t * s) -{ - elf_symbol_table_t *tab; - elf32_symbol_t *sym32; - elf64_symbol_t *sym64; - uword i; - - if (s->header.type == ELF_SECTION_DYNAMIC_SYMBOL_TABLE) - em->dynamic_symbol_table_index = vec_len (em->symbol_tables); - - vec_add2 (em->symbol_tables, tab, 1); - - tab->section_index = s->index; - - if (em->first_header.file_class == ELF_64BIT) - { - tab->symbols = - elf_get_section_contents (em, s - em->sections, - sizeof (tab->symbols[0])); - for (i = 0; i < vec_len (tab->symbols); i++) - { -#define _(t,f) tab->symbols[i].f = elf_swap_##t (em, tab->symbols[i].f); - foreach_elf64_symbol_header; -#undef _ - } - } - else - { - sym32 = - elf_get_section_contents (em, s - em->sections, sizeof (sym32[0])); - vec_clone (tab->symbols, sym32); - for (i = 0; i < vec_len (tab->symbols); i++) - { -#define _(t,f) tab->symbols[i].f = elf_swap_##t (em, sym32[i].f); - foreach_elf32_symbol_header; -#undef _ - } - } - - if (s->header.link == 0) - return; - - tab->string_table = - elf_get_section_contents (em, s->header.link, - sizeof (tab->string_table[0])); - tab->symbol_by_name = - hash_create_string ( /* # elts */ vec_len (tab->symbols), - /* sizeof of value */ sizeof (uword)); - - vec_foreach (sym64, tab->symbols) - { - if (sym64->name != 0) - hash_set_mem (tab->symbol_by_name, - tab->string_table + sym64->name, sym64 - tab->symbols); - } -} - -static void -add_relocation_table (elf_main_t * em, elf_section_t * s) -{ - uword has_addend = s->header.type == ELF_SECTION_RELOCATION_ADD; - elf_relocation_table_t *t; - uword i; - - vec_add2 (em->relocation_tables, t, 1); - t->section_index = s - em->sections; - - if (em->first_header.file_class == ELF_64BIT) - { - elf64_relocation_t *r, *rs; - - rs = elf_get_section_contents (em, t->section_index, - sizeof (rs[0]) + - has_addend * sizeof (rs->addend[0])); - - if (em->need_byte_swap) - { - r = rs; - for (i = 0; i < vec_len (r); i++) - { - r->address = elf_swap_u64 (em, r->address); - r->symbol_and_type = elf_swap_u32 (em, r->symbol_and_type); - if (has_addend) - r->addend[0] = elf_swap_u64 (em, r->addend[0]); - r = elf_relocation_next (r, s->header.type); - } - } - - vec_resize (t->relocations, vec_len (rs)); - clib_memcpy (t->relocations, rs, vec_bytes (t->relocations)); - vec_free (rs); - } - else - { - elf_relocation_with_addend_t *r; - elf32_relocation_t *r32, *r32s; - - r32s = elf_get_section_contents (em, t->section_index, - sizeof (r32s[0]) + - has_addend * sizeof (r32s->addend[0])); - vec_resize (t->relocations, vec_len (r32s)); - - r32 = r32s; - vec_foreach (r, t->relocations) - { - r->address = elf_swap_u32 (em, r32->address); - r->symbol_and_type = elf_swap_u32 (em, r->symbol_and_type); - r->addend = has_addend ? elf_swap_u32 (em, r32->addend[0]) : 0; - r32 = elf_relocation_next (r32, s->header.type); - } - - vec_free (r32s); - } -} - -void -elf_parse_symbols (elf_main_t * em) -{ - elf_section_t *s; - - /* No need to parse symbols twice. */ - if (em->parsed_symbols) - return; - em->parsed_symbols = 1; - - vec_foreach (s, em->sections) - { - switch (s->header.type) - { - case ELF_SECTION_SYMBOL_TABLE: - case ELF_SECTION_DYNAMIC_SYMBOL_TABLE: - add_symbol_table (em, s); - break; - - case ELF_SECTION_RELOCATION_ADD: - case ELF_SECTION_RELOCATION: - add_relocation_table (em, s); - break; - - default: - break; - } - } -} - -void -elf_set_dynamic_entries (elf_main_t * em) -{ - uword i; - - /* Start address for sections may have changed. */ - { - elf64_dynamic_entry_t *e; - - vec_foreach (e, em->dynamic_entries) - { - switch (e->type) - { - case ELF_DYNAMIC_ENTRY_INIT_FUNCTION: - case ELF_DYNAMIC_ENTRY_FINI_FUNCTION: - case ELF_DYNAMIC_ENTRY_SYMBOL_HASH: - case ELF_DYNAMIC_ENTRY_GNU_HASH: - case ELF_DYNAMIC_ENTRY_STRING_TABLE: - case ELF_DYNAMIC_ENTRY_SYMBOL_TABLE: - case ELF_DYNAMIC_ENTRY_PLT_GOT: - case ELF_DYNAMIC_ENTRY_PLT_RELOCATION_ADDRESS: - case ELF_DYNAMIC_ENTRY_RELA_ADDRESS: - case ELF_DYNAMIC_ENTRY_VERSION_NEED: - case ELF_DYNAMIC_ENTRY_VERSYM: - { - elf_section_t *es = - elf_get_section_by_start_address_no_check (em, e->data); - /* If section is not found just leave e->data alone. */ - if (es) - e->data = es->header.exec_address; - break; - } - - default: - break; - } - } - } - - if (em->first_header.file_class == ELF_64BIT) - { - elf64_dynamic_entry_t *e, *es; - - es = em->dynamic_entries; - if (em->need_byte_swap) - { - es = vec_dup (es); - vec_foreach (e, es) - { - e->type = elf_swap_u64 (em, e->type); - e->data = elf_swap_u64 (em, e->data); - } - } - - elf_set_section_contents (em, em->dynamic_section_index, es, - vec_bytes (es)); - if (es != em->dynamic_entries) - vec_free (es); - } - else - { - elf32_dynamic_entry_t *es; - - vec_clone (es, em->dynamic_entries); - if (em->need_byte_swap) - { - for (i = 0; i < vec_len (es); i++) - { - es[i].type = elf_swap_u32 (em, em->dynamic_entries[i].type); - es[i].data = elf_swap_u32 (em, em->dynamic_entries[i].data); - } - } - - elf_set_section_contents (em, em->dynamic_section_index, es, - vec_bytes (es)); - vec_free (es); - } -} - -clib_error_t * -elf_parse (elf_main_t * em, void *data, uword data_bytes) -{ - elf_first_header_t *h = data; - elf64_file_header_t *fh = &em->file_header; - clib_error_t *error = 0; - - { - char *save = em->file_name; - memset (em, 0, sizeof (em[0])); - em->file_name = save; - } - - em->first_header = h[0]; - em->need_byte_swap = - CLIB_ARCH_IS_BIG_ENDIAN != (h->data_encoding == - ELF_TWOS_COMPLEMENT_BIG_ENDIAN); - elf_swap_first_header (em, &em->first_header); - - if (!(h->magic[0] == 0x7f - && h->magic[1] == 'E' && h->magic[2] == 'L' && h->magic[3] == 'F')) - return clib_error_return (0, "`%s': bad magic", em->file_name); - - if (h->file_class == ELF_64BIT) - { - elf64_file_header_t *h64 = (void *) (h + 1); -#define _(t,f) fh->f = elf_swap_##t (em, h64->f); - foreach_elf64_file_header -#undef _ - } - else - { - elf32_file_header_t *h32 = (void *) (h + 1); - -#define _(t,f) fh->f = elf_swap_##t (em, h32->f); - foreach_elf32_file_header -#undef _ - } - - elf_parse_segments (em, data); - elf_parse_sections (em, data); - - /* Figure which sections are contained in each segment. */ - { - elf_segment_t *g; - elf_section_t *s; - vec_foreach (g, em->segments) - { - u64 g_lo, g_hi; - u64 s_lo, s_hi; - - if (g->header.memory_size == 0) - continue; - - g_lo = g->header.virtual_address; - g_hi = g_lo + g->header.memory_size; - - vec_foreach (s, em->sections) - { - s_lo = s->header.exec_address; - s_hi = s_lo + s->header.file_size; - - if (s_lo >= g_lo && s_hi <= g_hi) - { - g->section_index_bitmap = - clib_bitmap_ori (g->section_index_bitmap, s->index); - s->segment_index_bitmap = - clib_bitmap_ori (s->segment_index_bitmap, g->index); - } - } - } - } - - return error; -} - -#ifdef CLIB_UNIX - -static void -add_dynamic_entries (elf_main_t * em, elf_section_t * s) -{ - uword i; - - /* Can't have more than one dynamic section. */ - ASSERT (em->dynamic_section_index == 0); - em->dynamic_section_index = s->index; - - if (em->first_header.file_class == ELF_64BIT) - { - elf64_dynamic_entry_t *e; - - e = elf_get_section_contents (em, s - em->sections, sizeof (e[0])); - if (em->need_byte_swap) - for (i = 0; i < vec_len (e); i++) - { - e[i].type = elf_swap_u64 (em, e[i].type); - e[i].data = elf_swap_u64 (em, e[i].data); - } - - em->dynamic_entries = e; - } - else - { - elf32_dynamic_entry_t *e; - - e = elf_get_section_contents (em, s - em->sections, sizeof (e[0])); - vec_clone (em->dynamic_entries, e); - if (em->need_byte_swap) - for (i = 0; i < vec_len (e); i++) - { - em->dynamic_entries[i].type = elf_swap_u32 (em, e[i].type); - em->dynamic_entries[i].data = elf_swap_u32 (em, e[i].data); - } - - vec_free (e); - } -} - -static void -byte_swap_verneed (elf_main_t * em, elf_dynamic_version_need_union_t * vus) -{ - uword *entries_swapped = 0; - uword i, j; - - for (i = 0; i < vec_len (vus); i++) - { - elf_dynamic_version_need_union_t *n = vec_elt_at_index (vus, i); - elf_dynamic_version_need_union_t *a; - - if (clib_bitmap_get (entries_swapped, i)) - continue; - - elf_swap_verneed (&n->need); - entries_swapped = clib_bitmap_set (entries_swapped, i, 1); - - if (n->need.first_aux_offset != 0) - { - ASSERT (n->need.first_aux_offset % sizeof (n[0]) == 0); - j = i + (n->need.first_aux_offset / sizeof (n[0])); - while (1) - { - a = vec_elt_at_index (vus, j); - if (!clib_bitmap_get (entries_swapped, j)) - { - entries_swapped = clib_bitmap_set (entries_swapped, j, 1); - elf_swap_verneed_aux (&a->aux); - } - if (a->aux.next_offset == 0) - break; - ASSERT (a->aux.next_offset % sizeof (a->aux) == 0); - j += (a->aux.next_offset / sizeof (a->aux)); - } - } - } - - clib_bitmap_free (entries_swapped); -} - -static void set_dynamic_verneed (elf_main_t * em) __attribute__ ((unused)); -static void -set_dynamic_verneed (elf_main_t * em) -{ - elf_dynamic_version_need_union_t *vus = em->verneed; - - if (em->need_byte_swap) - { - vus = vec_dup (vus); - byte_swap_verneed (em, vus); - } - - elf_set_section_contents (em, em->verneed_section_index, vus, - vec_bytes (vus)); - if (vus != em->verneed) - vec_free (vus); -} - -static void -set_symbol_table (elf_main_t * em, u32 table_index) __attribute__ ((unused)); -static void -set_symbol_table (elf_main_t * em, u32 table_index) -{ - elf_symbol_table_t *tab = vec_elt_at_index (em->symbol_tables, table_index); - - if (em->first_header.file_class == ELF_64BIT) - { - elf64_symbol_t *s, *syms; - - syms = vec_dup (tab->symbols); - vec_foreach (s, syms) - { -#define _(t,f) s->f = elf_swap_##t (em, s->f); - foreach_elf64_symbol_header; -#undef _ - } - - elf_set_section_contents (em, tab->section_index, - syms, vec_bytes (syms)); - } - else - { - elf32_symbol_t *syms; - uword i; - vec_clone (syms, tab->symbols); - for (i = 0; i < vec_len (tab->symbols); i++) - { -#define _(t,f) syms[i].f = elf_swap_##t (em, tab->symbols[i].f); - foreach_elf32_symbol_header; -#undef _ - } - - elf_set_section_contents (em, tab->section_index, - syms, vec_bytes (syms)); - } -} - -static char * -elf_find_interpreter (elf_main_t * em, void *data) -{ - elf_segment_t *g; - elf_section_t *s; - uword *p; - - vec_foreach (g, em->segments) - { - if (g->header.type == ELF_SEGMENT_INTERP) - break; - } - - if (g >= vec_end (em->segments)) - return 0; - - p = hash_get (em->section_by_start_address, g->header.virtual_address); - if (!p) - return 0; - - s = vec_elt_at_index (em->sections, p[0]); - return (char *) vec_dup (s->contents); -} - -static void * -elf_get_section_contents_with_starting_address (elf_main_t * em, - uword start_address, - uword elt_size, - u32 * section_index_result) -{ - elf_section_t *s; - clib_error_t *error; - - error = elf_get_section_by_start_address (em, start_address, &s); - if (error) - { - clib_error_report (error); - return 0; - } - - if (section_index_result) - *section_index_result = s->index; - - return elf_get_section_contents (em, s->index, elt_size); -} - -static void -elf_parse_dynamic (elf_main_t * em) -{ - elf_section_t *s; - elf64_dynamic_entry_t *e; - - vec_foreach (s, em->sections) - { - switch (s->header.type) - { - case ELF_SECTION_DYNAMIC: - add_dynamic_entries (em, s); - break; - - default: - break; - } - } - - em->dynamic_string_table_section_index = ~0; - em->dynamic_string_table = 0; - - vec_foreach (e, em->dynamic_entries) - { - switch (e->type) - { - case ELF_DYNAMIC_ENTRY_STRING_TABLE: - ASSERT (vec_len (em->dynamic_string_table) == 0); - em->dynamic_string_table - = - elf_get_section_contents_with_starting_address (em, e->data, - sizeof (u8), - &em-> - dynamic_string_table_section_index); - break; - - case ELF_DYNAMIC_ENTRY_SYMBOL_TABLE: - { - elf_section_t *s; - clib_error_t *error; - - error = elf_get_section_by_start_address (em, e->data, &s); - if (error) - { - clib_error_report (error); - return; - } - - em->dynamic_symbol_table_section_index = s - em->sections; - } - break; - - case ELF_DYNAMIC_ENTRY_VERSYM: - em->versym - = - elf_get_section_contents_with_starting_address (em, e->data, - sizeof (em->versym - [0]), - &em-> - versym_section_index); - if (em->need_byte_swap) - { - uword i; - for (i = 0; i < vec_len (em->versym); i++) - em->versym[i] = clib_byte_swap_u16 (em->versym[i]); - } - break; - - case ELF_DYNAMIC_ENTRY_VERSION_NEED: - em->verneed - = - elf_get_section_contents_with_starting_address (em, e->data, - sizeof (em->verneed - [0]), - &em-> - verneed_section_index); - if (em->need_byte_swap) - byte_swap_verneed (em, em->verneed); - break; - - default: - break; - } - } -} - -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> - -clib_error_t * -elf_read_file (elf_main_t * em, char *file_name) -{ - int fd; - struct stat fd_stat; - uword mmap_length = 0; - void *data = 0; - clib_error_t *error = 0; - - elf_main_init (em); - - fd = open (file_name, 0); - if (fd < 0) - { - error = clib_error_return_unix (0, "open `%s'", file_name); - goto done; - } - - if (fstat (fd, &fd_stat) < 0) - { - error = clib_error_return_unix (0, "fstat `%s'", file_name); - goto done; - } - mmap_length = fd_stat.st_size; - - data = mmap (0, mmap_length, PROT_READ, MAP_SHARED, fd, /* offset */ 0); - if (~pointer_to_uword (data) == 0) - { - error = clib_error_return_unix (0, "mmap `%s'", file_name); - goto done; - } - - em->file_name = file_name; - - error = elf_parse (em, data, mmap_length); - if (error) - goto done; - - elf_parse_symbols (em); - elf_parse_dynamic (em); - - em->interpreter = elf_find_interpreter (em, data); - - munmap (data, mmap_length); - close (fd); - - return /* no error */ 0; - -done: - elf_main_free (em); - if (fd >= 0) - close (fd); - if (data) - munmap (data, mmap_length); - return error; -} - -typedef struct -{ - u8 *new_table; - - u8 *old_table; - - uword *hash; -} string_table_builder_t; - -static u32 -string_table_add_name (string_table_builder_t * b, u8 * n) -{ - uword *p, i, j, l; - - p = hash_get_mem (b->hash, n); - if (p) - return p[0]; - - l = strlen ((char *) n); - i = vec_len (b->new_table); - vec_add (b->new_table, n, l + 1); - - for (j = 0; j <= l; j++) - { - if (j > 0) - { - p = hash_get_mem (b->hash, n + j); - - /* Sub-string already in table? */ - if (p) - continue; - } - - hash_set_mem (b->hash, n + j, i + j); - } - - return i; -} - -static u32 string_table_add_name_index (string_table_builder_t * b, u32 index) - __attribute__ ((unused)); -static u32 -string_table_add_name_index (string_table_builder_t * b, u32 index) -{ - u8 *n = b->old_table + index; - return string_table_add_name (b, n); -} - -static void string_table_init (string_table_builder_t * b, u8 * old_table) - __attribute__ ((unused)); -static void -string_table_init (string_table_builder_t * b, u8 * old_table) -{ - memset (b, 0, sizeof (b[0])); - b->old_table = old_table; - b->hash = hash_create_string (0, sizeof (uword)); -} - -static u8 *string_table_done (string_table_builder_t * b) - __attribute__ ((unused)); -static u8 * -string_table_done (string_table_builder_t * b) -{ - hash_free (b->hash); - return b->new_table; -} - -static void -layout_sections (elf_main_t * em) -{ - elf_section_t *s; - u32 n_sections_with_changed_exec_address = 0; - u32 *deferred_symbol_and_string_sections = 0; - u32 n_deleted_sections = 0; - /* note: rebuild is always zero. Intent lost in the sands of time */ -#if 0 - int rebuild = 0; - - /* Re-build section string table (sections may have been deleted). */ - if (rebuild) - { - u8 *st = 0; - - vec_foreach (s, em->sections) - { - u8 *name; - if (s->header.type == ~0) - continue; - name = elf_section_name (em, s); - s->header.name = vec_len (st); - vec_add (st, name, strlen ((char *) name) + 1); - } - - s = - vec_elt_at_index (em->sections, - em->file_header.section_header_string_table_index); - - vec_free (s->contents); - s->contents = st; - } - - /* Re-build dynamic string table. */ - if (rebuild && em->dynamic_string_table_section_index != ~0) - { - string_table_builder_t b; - - string_table_init (&b, em->dynamic_string_table); - - /* Add all dynamic symbols. */ - { - elf_symbol_table_t *symtab; - elf64_symbol_t *sym; - - symtab = - vec_elt_at_index (em->symbol_tables, - em->dynamic_symbol_table_index); - vec_foreach (sym, symtab->symbols) - { - u8 *name = elf_symbol_name (symtab, sym); - sym->name = string_table_add_name (&b, name); - } - - set_symbol_table (em, em->dynamic_symbol_table_index); - } - - /* Add all dynamic entries. */ - { - elf64_dynamic_entry_t *e; - - vec_foreach (e, em->dynamic_entries) - { - switch (e->type) - { - case ELF_DYNAMIC_ENTRY_NEEDED_LIBRARY: - case ELF_DYNAMIC_ENTRY_RPATH: - case ELF_DYNAMIC_ENTRY_RUN_PATH: - e->data = string_table_add_name_index (&b, e->data); - break; - } - } - } - - /* Add all version needs. */ - if (vec_len (em->verneed) > 0) - { - elf_dynamic_version_need_union_t *n, *a; - - n = em->verneed; - while (1) - { - n->need.file_name_offset = - string_table_add_name_index (&b, n->need.file_name_offset); - - if (n->need.first_aux_offset != 0) - { - a = n + n->need.first_aux_offset / sizeof (n[0]); - while (1) - { - a->aux.name = - string_table_add_name_index (&b, a->aux.name); - if (a->aux.next_offset == 0) - break; - a += a->aux.next_offset / sizeof (a[0]); - } - } - - if (n->need.next_offset == 0) - break; - - n += n->need.next_offset / sizeof (n[0]); - } - - set_dynamic_verneed (em); - } - - s = - vec_elt_at_index (em->sections, - em->dynamic_string_table_section_index); - - vec_free (s->contents); - s->contents = string_table_done (&b); - } -#endif /* dead code */ - - /* Figure file offsets and exec addresses for sections. */ - { - u64 exec_address = 0, file_offset = 0; - u64 file_size, align_size; - - vec_foreach (s, em->sections) - { - /* Ignore deleted and unused sections. */ - switch (s->header.type) - { - case ~0: - n_deleted_sections++; - case ELF_SECTION_UNUSED: - continue; - - case ELF_SECTION_STRING_TABLE: - case ELF_SECTION_SYMBOL_TABLE: - if (!(s->index == em->dynamic_string_table_section_index - || s->index == - em->file_header.section_header_string_table_index)) - { - vec_add1 (deferred_symbol_and_string_sections, s->index); - continue; - } - break; - - default: - break; - } - - exec_address = round_pow2_u64 (exec_address, s->header.align); - - /* Put sections we added at end of file. */ - if (s->header.file_offset == ~0) - s->header.file_offset = file_offset; - - /* Follow gaps in original file. */ - if (s->header.exec_address > exec_address) - { - exec_address = s->header.exec_address; - file_offset = s->header.file_offset; - } - - if (s->header.flags & ELF_SECTION_FLAG_ALLOC) - { - s->exec_address_change = exec_address - s->header.exec_address; - n_sections_with_changed_exec_address += s->exec_address_change != 0; - s->header.exec_address = exec_address; - } - - if (s->header.type == ELF_SECTION_NO_BITS) - file_size = s->header.file_size; - else - file_size = vec_len (s->contents); - - { - u64 align; - - if (s + 1 >= vec_end (em->sections)) - align = 16; - else if (s[1].header.type == ELF_SECTION_NO_BITS) - align = 8; - else - align = s[1].header.align; - - if (s->header.flags & ELF_SECTION_FLAG_ALLOC) - { - u64 v = round_pow2_u64 (exec_address + file_size, align); - align_size = v - exec_address; - } - else - { - u64 v = round_pow2_u64 (file_offset + file_size, align); - align_size = v - file_offset; - } - } - - s->header.file_offset = file_offset; - s->header.file_size = file_size; - s->align_size = align_size; - - if (s->header.type != ELF_SECTION_NO_BITS) - file_offset += align_size; - exec_address += align_size; - } - - /* Section headers go after last section but before symbol/string - tables. */ - { - elf64_file_header_t *fh = &em->file_header; - - fh->section_header_file_offset = file_offset; - fh->section_header_count = vec_len (em->sections) - n_deleted_sections; - file_offset += (u64) fh->section_header_count * fh->section_header_size; - } - - { - int i; - for (i = 0; i < vec_len (deferred_symbol_and_string_sections); i++) - { - s = - vec_elt_at_index (em->sections, - deferred_symbol_and_string_sections[i]); - - s->header.file_offset = file_offset; - s->header.file_size = vec_len (s->contents); - - align_size = round_pow2 (vec_len (s->contents), 16); - s->align_size = align_size; - file_offset += align_size; - } - vec_free (deferred_symbol_and_string_sections); - } - } - - /* Update dynamic entries now that sections have been assigned - possibly new addresses. */ -#if 0 - if (rebuild) - elf_set_dynamic_entries (em); -#endif - - /* Update segments for changed section addresses. */ - { - elf_segment_t *g; - uword si; - - vec_foreach (g, em->segments) - { - u64 s_lo, s_hi, f_lo = 0; - u32 n_sections = 0; - - if (g->header.memory_size == 0) - continue; - - s_lo = s_hi = 0; - /* *INDENT-OFF* */ - clib_bitmap_foreach (si, g->section_index_bitmap, ({ - u64 lo, hi; - - s = vec_elt_at_index (em->sections, si); - lo = s->header.exec_address; - hi = lo + s->align_size; - if (n_sections == 0) - { - s_lo = lo; - s_hi = hi; - f_lo = s->header.file_offset; - n_sections++; - } - else - { - if (lo < s_lo) - { - s_lo = lo; - f_lo = s->header.file_offset; - } - if (hi > s_hi) - s_hi = hi; - } - })); - /* *INDENT-ON* */ - - if (n_sections == 0) - continue; - - /* File offset zero includes ELF headers/segment headers. - Don't change that. */ - if (g->header.file_offset == 0 && g->header.type == ELF_SEGMENT_LOAD) - { - s_lo = g->header.virtual_address; - f_lo = g->header.file_offset; - } - - g->header.virtual_address = s_lo; - g->header.physical_address = s_lo; - g->header.file_offset = f_lo; - g->header.memory_size = s_hi - s_lo; - } - } -} - -clib_error_t * -elf_write_file (elf_main_t * em, char *file_name) -{ - int fd; - FILE *f; - clib_error_t *error = 0; - - fd = open (file_name, O_CREAT | O_RDWR | O_TRUNC, 0755); - if (fd < 0) - return clib_error_return_unix (0, "open `%s'", file_name); - - f = fdopen (fd, "w"); - - /* Section contents may have changed. So, we need to update - stuff to reflect this. */ - layout_sections (em); - - /* Write first header. */ - { - elf_first_header_t h = em->first_header; - - elf_swap_first_header (em, &h); - if (fwrite (&h, sizeof (h), 1, f) != 1) - { - error = clib_error_return_unix (0, "write first header"); - goto error; - } - } - - /* Write file header. */ - { - elf64_file_header_t h = em->file_header; - - /* Segment headers are after first header. */ - h.segment_header_file_offset = sizeof (elf_first_header_t); - if (em->first_header.file_class == ELF_64BIT) - h.segment_header_file_offset += sizeof (elf64_file_header_t); - else - h.segment_header_file_offset += sizeof (elf32_file_header_t); - - if (em->first_header.file_class == ELF_64BIT) - { -#define _(t,field) h.field = elf_swap_##t (em, h.field); - foreach_elf64_file_header; -#undef _ - - if (fwrite (&h, sizeof (h), 1, f) != 1) - { - error = clib_error_return_unix (0, "write file header"); - goto error; - } - } - else - { - elf32_file_header_t h32; - -#define _(t,field) h32.field = elf_swap_##t (em, h.field); - foreach_elf32_file_header; -#undef _ - - if (fwrite (&h32, sizeof (h32), 1, f) != 1) - { - error = clib_error_return_unix (0, "write file header"); - goto error; - } - } - } - - /* Write segment headers. */ - { - elf_segment_t *s; - - vec_foreach (s, em->segments) - { - elf64_segment_header_t h; - - if (s->header.type == ~0) - continue; - - h = s->header; - - if (em->first_header.file_class == ELF_64BIT) - { -#define _(t,field) h.field = elf_swap_##t (em, h.field); - foreach_elf64_segment_header; -#undef _ - - if (fwrite (&h, sizeof (h), 1, f) != 1) - { - error = - clib_error_return_unix (0, "write segment header %U", - format_elf_segment, em, s); - goto error; - } - } - else - { - elf32_segment_header_t h32; - -#define _(t,field) h32.field = elf_swap_##t (em, h.field); - foreach_elf32_segment_header; -#undef _ - - if (fwrite (&h32, sizeof (h32), 1, f) != 1) - { - error = - clib_error_return_unix (0, "write segment header %U", - format_elf_segment, em, s); - goto error; - } - } - } - } - - /* Write contents for all sections. */ - { - elf_section_t *s; - - vec_foreach (s, em->sections) - { - if (s->header.file_size == 0) - continue; - - if (fseek (f, s->header.file_offset, SEEK_SET) < 0) - { - fclose (f); - return clib_error_return_unix (0, "fseek 0x%Lx", - s->header.file_offset); - } - - if (s->header.type == ELF_SECTION_NO_BITS) - /* don't write for .bss sections */ ; - else if (fwrite (s->contents, vec_len (s->contents), 1, f) != 1) - { - error = - clib_error_return_unix (0, "write %s section contents", - elf_section_name (em, s)); - goto error; - } - } - - /* Finally write section headers. */ - if (fseek (f, em->file_header.section_header_file_offset, SEEK_SET) < 0) - { - fclose (f); - return clib_error_return_unix - (0, "fseek 0x%Lx", em->file_header.section_header_file_offset); - } - - vec_foreach (s, em->sections) - { - elf64_section_header_t h; - - if (s->header.type == ~0) - continue; - - h = s->header; - - if (em->first_header.file_class == ELF_64BIT) - { -#define _(t,field) h.field = elf_swap_##t (em, h.field); - foreach_elf64_section_header; -#undef _ - - if (fwrite (&h, sizeof (h), 1, f) != 1) - { - error = - clib_error_return_unix (0, "write %s section header", - elf_section_name (em, s)); - goto error; - } - } - else - { - elf32_section_header_t h32; - -#define _(t,field) h32.field = elf_swap_##t (em, h.field); - foreach_elf32_section_header; -#undef _ - - if (fwrite (&h32, sizeof (h32), 1, f) != 1) - { - error = - clib_error_return_unix (0, "write %s section header", - elf_section_name (em, s)); - goto error; - } - } - } - } - -error: - fclose (f); - return error; -} - -clib_error_t * -elf_delete_named_section (elf_main_t * em, char *section_name) -{ - elf_section_t *s; - clib_error_t *error; - - error = elf_get_section_by_name (em, section_name, &s); - if (error) - return error; - - s->header.type = ~0; - - return 0; -} - -void -elf_create_section_with_contents (elf_main_t * em, - char *section_name, - elf64_section_header_t * header, - void *contents, uword n_content_bytes) -{ - elf_section_t *s, *sts; - u8 *st, *c; - uword *p, is_new_section; - - /* See if section already exists with given name. - If so, just replace contents. */ - is_new_section = 0; - if ((p = hash_get_mem (em->section_by_name, section_name))) - { - s = vec_elt_at_index (em->sections, p[0]); - _vec_len (s->contents) = 0; - c = s->contents; - } - else - { - vec_add2 (em->sections, s, 1); - is_new_section = 1; - c = 0; - } - - sts = - vec_elt_at_index (em->sections, - em->file_header.section_header_string_table_index); - st = sts->contents; - - s->header = header[0]; - - s->header.file_offset = ~0; - s->header.file_size = n_content_bytes; - s->index = s - em->sections; - - /* Add name to string table. */ - s->header.name = vec_len (st); - vec_add (st, section_name, strlen (section_name)); - vec_add1 (st, 0); - sts->contents = st; - - vec_resize (c, n_content_bytes); - clib_memcpy (c, contents, n_content_bytes); - s->contents = c; - - em->file_header.section_header_count += is_new_section - && s->header.type != ~0; -} - -uword -elf_delete_segment_with_type (elf_main_t * em, - elf_segment_type_t segment_type) -{ - uword n_deleted = 0; - elf_segment_t *s; - - vec_foreach (s, em->segments) if (s->header.type == segment_type) - { - s->header.type = ~0; - n_deleted += 1; - } - - ASSERT (em->file_header.segment_header_count >= n_deleted); - em->file_header.segment_header_count -= n_deleted; - - return n_deleted; -} - -#endif /* CLIB_UNIX */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/elf.h b/vppinfra/vppinfra/elf.h deleted file mode 100644 index 008ea284b31..00000000000 --- a/vppinfra/vppinfra/elf.h +++ /dev/null @@ -1,1062 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_clib_elf_h -#define included_clib_elf_h - -#include <vppinfra/format.h> -#include <vppinfra/hash.h> -#include <vppinfra/vec.h> -#include <vppinfra/byte_order.h> - -#define foreach_elf_file_class \ - _ (CLASS_NONE) _ (32BIT) _ (64BIT) - -#define foreach_elf_data_encoding \ - _ (ENCODING_NONE) \ - _ (TWOS_COMPLEMENT_LITTLE_ENDIAN) \ - _ (TWOS_COMPLEMENT_BIG_ENDIAN) - -#define ELF_VERSION_NONE (0) -#define ELF_VERSION_CURRENT (1) - -#define foreach_elf_abi \ - _ (SYSV, 0) \ - _ (HPUX, 1) \ - _ (NETBSD, 2) \ - _ (LINUX, 3) \ - _ (SOLARIS, 6) \ - _ (AIX, 7) \ - _ (IRIX, 8) \ - _ (FREEBSD, 9) \ - _ (COMPAQ_TRU64, 10) \ - _ (MODESTO, 11) \ - _ (OPENBSD, 12) \ - _ (ARM, 97) \ - _ (STANDALONE, 255) - -/* Legal values for type (object file type). */ -#define foreach_elf_file_type \ - _ (NONE, 0) \ - _ (RELOC, 1) \ - _ (EXEC, 2) \ - _ (SHARED, 3) \ - _ (CORE, 4) \ - _ (OS_SPECIFIC_LO, 0xfe00) \ - _ (OS_SPECIFIC_HI, 0xfeff) \ - _ (ARCH_SPECIFIC_LO, 0xff00) \ - _ (ARCH_SPECIFIC_HI, 0xffff) - -/* Legal values for architecture. */ -#define foreach_elf_architecture \ - _ (NONE, 0) /* No machine */ \ - _ (M32, 1) /* AT&T WE 32100 */ \ - _ (SPARC, 2) /* SUN SPARC */ \ - _ (386, 3) /* Intel 80386 */ \ - _ (68K, 4) /* Motorola m68k family */ \ - _ (88K, 5) /* Motorola m88k family */ \ - _ (860, 7) /* Intel 80860 */ \ - _ (MIPS, 8) /* MIPS R3000 big-endian */ \ - _ (S370, 9) /* IBM System/370 */ \ - _ (MIPS_RS3_LE, 10) /* MIPS R3000 little-endian */ \ - _ (PARISC, 15) /* HPPA */ \ - _ (VPP500, 17) /* Fujitsu VPP500 */ \ - _ (SPARC32PLUS, 18) /* Sun's "v8plus" */ \ - _ (960, 19) /* Intel 80960 */ \ - _ (PPC, 20) /* PowerPC */ \ - _ (PPC64, 21) /* PowerPC 64-bit */ \ - _ (S390, 22) /* IBM S390 */ \ - _ (V800, 36) /* NEC V800 series */ \ - _ (FR20, 37) /* Fujitsu FR20 */ \ - _ (RH32, 38) /* TRW RH-32 */ \ - _ (RCE, 39) /* Motorola RCE */ \ - _ (ARM, 40) /* ARM */ \ - _ (FAKE_ALPHA, 41) /* Digital Alpha */ \ - _ (SH, 42) /* Hitachi SH */ \ - _ (SPARCV9, 43) /* SPARC v9 64-bit */ \ - _ (TRICORE, 44) /* Siemens Tricore */ \ - _ (ARC, 45) /* Argonaut RISC Core */ \ - _ (H8_300, 46) /* Hitachi H8/300 */ \ - _ (H8_300H, 47) /* Hitachi H8/300H */ \ - _ (H8S, 48) /* Hitachi H8S */ \ - _ (H8_500, 49) /* Hitachi H8/500 */ \ - _ (IA_64, 50) /* Intel Merced */ \ - _ (MIPS_X, 51) /* Stanford MIPS-X */ \ - _ (COLDFIRE, 52) /* Motorola Coldfire */ \ - _ (68HC12, 53) /* Motorola M68HC12 */ \ - _ (MMA, 54) /* Fujitsu MMA Multimedia Accel. */ \ - _ (PCP, 55) /* Siemens PCP */ \ - _ (NCPU, 56) /* Sony nCPU embeeded RISC */ \ - _ (NDR1, 57) /* Denso NDR1 microprocessor */ \ - _ (STARCORE, 58) /* Motorola Start*Core processor */ \ - _ (ME16, 59) /* Toyota ME16 processor */ \ - _ (ST100, 60) /* STMicroelectronic ST100 */ \ - _ (TINYJ, 61) /* Advanced Logic Corp. Tinyj */ \ - _ (X86_64, 62) /* AMD x86-64 architecture */ \ - _ (PDSP, 63) /* Sony DSP Processor */ \ - _ (FX66, 66) /* Siemens FX66 microcontroller */ \ - _ (ST9PLUS, 67) /* STMicroelectronics ST9+ 8/16 mc */ \ - _ (ST7, 68) /* STmicroelectronics ST7 8 bit mc */ \ - _ (68HC16, 69) /* Motorola MC68HC16 */ \ - _ (68HC11, 70) /* Motorola MC68HC11 */ \ - _ (68HC08, 71) /* Motorola MC68HC08 */ \ - _ (68HC05, 72) /* Motorola MC68HC05 */ \ - _ (SVX, 73) /* Silicon Graphics SVx */ \ - _ (ST19, 74) /* STMicroelectronics ST19 8 bit mc */ \ - _ (VAX, 75) /* Digital VAX */ \ - _ (CRIS, 76) /* Axis 32-bit embedded proc. */ \ - _ (JAVELIN, 77) /* Infineon 32-bit embedded proc. */ \ - _ (FIREPATH, 78) /* Element 14 64-bit DSP Processor */ \ - _ (ZSP, 79) /* LSI Logic 16-bit DSP Processor */ \ - _ (MMIX, 80) /* Knuth's 64-bit processor */ \ - _ (HUANY, 81) /* Harvard machine-independent */ \ - _ (PRISM, 82) /* SiTera Prism */ \ - _ (AVR, 83) /* Atmel AVR 8-bit microcontroller */ \ - _ (FR30, 84) /* Fujitsu FR30 */ \ - _ (D10V, 85) /* Mitsubishi D10V */ \ - _ (D30V, 86) /* Mitsubishi D30V */ \ - _ (V850, 87) /* NEC v850 */ \ - _ (M32R, 88) /* Mitsubishi M32R */ \ - _ (MN10300, 89) /* Matsushita MN10300 */ \ - _ (MN10200, 90) /* Matsushita MN10200 */ \ - _ (PJ, 91) /* picoJava */ \ - _ (OPENRISC, 92) /* OpenRISC 32-bit processor */ \ - _ (ARC_A5, 93) /* ARC Cores Tangent-A5 */ \ - _ (XTENSA, 94) /* Tensilica Xtensa Architecture */ \ - _ (ALPHA, 0x9026) - -#define _(f) ELF_##f, - -typedef enum -{ - foreach_elf_file_class ELF_N_FILE_CLASS, -} elf_file_class_t; - -typedef enum -{ - foreach_elf_data_encoding ELF_N_DATA_ENCODING, -} elf_data_encoding_t; - -#undef _ - -#define _(f,i) ELF_##f = i, - -typedef enum -{ - foreach_elf_abi -} elf_abi_t; - -typedef enum -{ - foreach_elf_file_type -} elf_file_type_t; - -#undef _ - -typedef enum -{ -#define _(f,i) ELF_ARCH_##f = i, - foreach_elf_architecture -#undef _ -} elf_architecture_t; - -typedef struct -{ - /* 0x7f ELF */ - u8 magic[4]; - - elf_file_class_t file_class:8; - elf_data_encoding_t data_encoding:8; - u8 file_version_ident; - elf_abi_t abi:8; - u8 abi_version; - - u8 pad[7]; - - elf_file_type_t file_type:16; - elf_architecture_t architecture:16; - - u32 file_version; -} elf_first_header_t; - -/* 32/64 bit file header following basic file header. */ -#define foreach_elf32_file_header \ - _ (u32, entry_point) \ - _ (u32, segment_header_file_offset) \ - _ (u32, section_header_file_offset) \ - _ (u32, flags) \ - _ (u16, n_bytes_this_header) \ - _ (u16, segment_header_size) \ - _ (u16, segment_header_count) \ - _ (u16, section_header_size) \ - _ (u16, section_header_count) \ - _ (u16, section_header_string_table_index) - -#define foreach_elf64_file_header \ - _ (u64, entry_point) \ - _ (u64, segment_header_file_offset) \ - _ (u64, section_header_file_offset) \ - _ (u32, flags) \ - _ (u16, n_bytes_this_header) \ - _ (u16, segment_header_size) \ - _ (u16, segment_header_count) \ - _ (u16, section_header_size) \ - _ (u16, section_header_count) \ - _ (u16, section_header_string_table_index) - -/* Section header. */ -#define foreach_elf32_section_header \ - _ (u32, name) \ - _ (u32, type) \ - _ (u32, flags) \ - _ (u32, exec_address) \ - _ (u32, file_offset) \ - _ (u32, file_size) \ - _ (u32, link) \ - _ (u32, additional_info) \ - _ (u32, align) \ - _ (u32, entry_size) - -#define foreach_elf64_section_header \ - _ (u32, name) \ - _ (u32, type) \ - _ (u64, flags) \ - _ (u64, exec_address) \ - _ (u64, file_offset) \ - _ (u64, file_size) \ - _ (u32, link) \ - _ (u32, additional_info) \ - _ (u64, align) \ - _ (u64, entry_size) - -/* Program segment header. */ -#define foreach_elf32_segment_header \ - _ (u32, type) \ - _ (u32, file_offset) \ - _ (u32, virtual_address) \ - _ (u32, physical_address) \ - _ (u32, file_size) \ - _ (u32, memory_size) \ - _ (u32, flags) \ - _ (u32, align) - -#define foreach_elf64_segment_header \ - _ (u32, type) \ - _ (u32, flags) \ - _ (u64, file_offset) \ - _ (u64, virtual_address) \ - _ (u64, physical_address) \ - _ (u64, file_size) \ - _ (u64, memory_size) \ - _ (u64, align) - -/* Symbol table. */ -#define foreach_elf32_symbol_header \ - _ (u32, name) \ - _ (u32, value) \ - _ (u32, size) \ - /* binding upper 4 bits; type lower 4 bits */ \ - _ (u8, binding_and_type) \ - _ (u8, visibility) \ - _ (u16, section_index) - -#define foreach_elf64_symbol_header \ - _ (u32, name) \ - _ (u8, binding_and_type) \ - _ (u8, visibility) \ - _ (u16, section_index) \ - _ (u64, value) \ - _ (u64, size) - -#define _(t,f) t f; - -typedef struct -{ -foreach_elf32_file_header} elf32_file_header_t; - -typedef struct -{ -foreach_elf64_file_header} elf64_file_header_t; - -typedef struct -{ -foreach_elf32_section_header} elf32_section_header_t; - -typedef struct -{ -foreach_elf64_section_header} elf64_section_header_t; - -typedef struct -{ -foreach_elf32_segment_header} elf32_segment_header_t; - -typedef struct -{ -foreach_elf64_segment_header} elf64_segment_header_t; - -typedef struct -{ -foreach_elf32_symbol_header} elf32_symbol_t; - -typedef struct -{ -foreach_elf64_symbol_header} elf64_symbol_t; -#undef _ - -/* Special section names. */ -#define foreach_elf_symbol_reserved_section_index \ - _ (ABSOLUTE, 0xfff1) /* Associated symbol is absolute */ \ - _ (COMMON, 0xfff2) /* Associated symbol is common */ \ - _ (XINDEX, 0xffff) /* Index is in extra table. */ - -#define ELF_SYMBOL_SECTION_RESERVED_LO 0xff00 -#define ELF_SYMBOL_SECTION_RESERVED_HI 0xffff -#define ELF_SYMBOL_SECTION_ARCH_SPECIFIC_LO 0xff00 -#define ELF_SYMBOL_SECTION_ARCH_SPECIFIC_HI 0xff1f -#define ELF_SYMBOL_SECTION_OS_SPECIFIC_LO 0xff20 -#define ELF_SYMBOL_SECTION_OS_SPECIFIC_HI 0xff3f - -/* Section types. */ -#define foreach_elf_section_type \ - _ (UNUSED, 0) \ - _ (PROGRAM_DATA, 1) \ - _ (SYMBOL_TABLE, 2) \ - _ (STRING_TABLE, 3) \ - _ (RELOCATION_ADD, 4) \ - _ (SYMBOL_TABLE_HASH, 5) \ - _ (DYNAMIC, 6) /* Dynamic linking information */ \ - _ (NOTE, 7) /* Notes */ \ - _ (NO_BITS, 8) /* Program space with no data (bss) */ \ - _ (RELOCATION, 9) /* Relocation entries, no addends */ \ - _ (DYNAMIC_SYMBOL_TABLE, 11) /* Dynamic linker symbol table */ \ - _ (INIT_ARRAY, 14) /* Array of constructors */ \ - _ (FINI_ARRAY, 15) /* Array of destructors */ \ - _ (PREINIT_ARRAY, 16) /* Array of pre-constructors */ \ - _ (GROUP, 17) /* Section group */ \ - _ (SYMTAB_SHNDX, 18) /* Extended section indices */ \ - _ (OS_SPECIFIC_LO, 0x60000000) /* Start OS-specific */ \ - _ (GNU_LIBLIST, 0x6ffffff7) /* Prelink library list */ \ - _ (CHECKSUM, 0x6ffffff8) /* Checksum for DSO content. */ \ - _ (SUNW_MOVE, 0x6ffffffa) \ - _ (SUNW_COMDAT, 0x6ffffffb) \ - _ (SUNW_SYMINFO, 0x6ffffffc) \ - _ (GNU_VERDEF, 0x6ffffffd) /* Version definition section. */ \ - _ (GNU_VERNEED, 0x6ffffffe) /* Version needs section. */ \ - _ (GNU_VERSYM, 0x6fffffff) /* Version symbol table. */ \ - _ (ARCH_SPECIFIC_LO, 0x70000000) /* Start of processor-specific */ \ - _ (ARCH_SPECIFIC_HI, 0x7fffffff) /* End of processor-specific */ \ - _ (APP_SPECIFIC_LO, 0x80000000) /* Start of application-specific */ \ - _ (APP_SPECIFIC_HI, 0x8fffffff) /* End of application-specific */ - -/* Section flags. */ -#define foreach_elf_section_flag \ - _ (WRITE, 0) \ - _ (ALLOC, 1) \ - _ (EXEC, 2) \ - _ (MERGE, 3) \ - _ (STRING_TABLE, 5) \ - _ (INFO_LINK, 6) \ - _ (PRESERVE_LINK_ORDER, 7) \ - _ (OS_NON_CONFORMING, 8) \ - _ (GROUP, 9) \ - _ (TLS, 10) \ - _ (OS_SPECIFIC_LO, 20) \ - _ (OS_SPECIFIC_HI, 27) \ - _ (ARCH_SPECIFIC_LO, 28) \ - _ (ARCH_SPECIFIC_HI, 31) - -typedef enum -{ -#define _(f,i) ELF_SECTION_##f = i, - foreach_elf_section_type -#undef _ - ELF_SECTION_OS_SPECIFIC_HI = 0x6fffffff, -} elf_section_type_t; - -typedef enum -{ -#define _(f,i) ELF_SECTION_FLAG_BIT_##f = i, - foreach_elf_section_flag -#undef _ -} elf_section_flag_bit_t; - -typedef enum -{ -#define _(f,i) ELF_SECTION_FLAG_##f = 1 << ELF_SECTION_FLAG_BIT_##f, - foreach_elf_section_flag -#undef _ -} elf_section_flag_t; - -/* Symbol bindings (upper 4 bits of binding_and_type). */ -#define foreach_elf_symbol_binding \ - _ (LOCAL, 0) /* Local symbol */ \ - _ (GLOBAL, 1) /* Global symbol */ \ - _ (WEAK, 2) /* Weak symbol */ \ - _ (OS_SPECIFIC_LO, 10) /* Start of OS-specific */ \ - _ (OS_SPECIFIC_HI, 12) /* End of OS-specific */ \ - _ (ARCH_SPECIFIC_LO, 13) /* Start of processor-specific */ \ - _ (ARCH_SPECIFIC_HI, 15) /* End of processor-specific */ - -/* Symbol types (lower 4 bits of binding_and_type). */ -#define foreach_elf_symbol_type \ - _ (NONE, 0) \ - _ (DATA, 1) /* Symbol is a data object */ \ - _ (CODE, 2) /* Symbol is a code object */ \ - _ (SECTION, 3) /* Symbol associated with a section */ \ - _ (FILE, 4) /* Symbol's name is file name */ \ - _ (COMMON, 5) /* Symbol is a common data object */ \ - _ (TLS, 6) /* Symbol is thread-local data */ \ - _ (OS_SPECIFIC_LO, 10) /* Start of OS-specific */ \ - _ (OS_SPECIFIC_HI, 12) /* End of OS-specific */ \ - _ (ARCH_SPECIFIC_LO, 13) /* Start of processor-specific */ \ - _ (ARCH_SPECIFIC_HI, 15) /* End of processor-specific */ - -/* Symbol visibility. */ -#define foreach_elf_symbol_visibility \ - _ (DEFAULT, 0) /* Default symbol visibility rules */ \ - _ (INTERNAL, 1) /* Processor specific hidden class */ \ - _ (HIDDEN, 2) /* Unavailable in other modules */ \ - _ (PROTECTED, 3) /* Not preemptible, not exported */ - -/* The syminfo section if available contains additional - information about every dynamic symbol. */ -typedef struct -{ - u16 bound_to; - u16 flags; -} elf_symbol_info_t; - -/* Possible values for bound_to. */ -#define foreach_elf_symbol_info_bound_to \ - _ (SELF, 0xffff) /* Symbol bound to self */ \ - _ (PARENT, 0xfffe) /* Symbol bound to parent */ \ - _ (RESERVED_LO, 0xff00) \ - _ (RESERVED_HI, 0xffff) - -/* Symbol info flags. */ -#define foreach_elf_symbol_info_flags \ - _ (DIRECT) /* Direct bound symbol */ \ - _ (PASS_THRU) /* Pass-thru symbol for translator */ \ - _ (COPY) /* Symbol is a copy-reloc */ \ - _ (LAZY_LOAD) /* Symbol bound to object to be lazy loaded */ - -/* Relocation table entry with/without addend. */ -typedef struct -{ - u32 address; - u32 symbol_and_type; /* high 24 symbol, low 8 type. */ - i32 addend[0]; -} elf32_relocation_t; - -typedef struct -{ - u64 address; - u64 symbol_and_type; /* high 32 symbol, low 32 type. */ - i64 addend[0]; -} elf64_relocation_t; - -typedef struct -{ - u64 address; - u64 symbol_and_type; - u64 addend; -} elf_relocation_with_addend_t; - -#define elf_relocation_next(r,type) \ - ((void *) ((r) + 1) \ - + ((type) == ELF_SECTION_RELOCATION_ADD ? sizeof ((r)->addend[0]) : 0)) - -/* Segment type. */ -#define foreach_elf_segment_type \ - _ (UNUSED, 0) \ - _ (LOAD, 1) /* Loadable program segment */ \ - _ (DYNAMIC, 2) /* Dynamic linking information */ \ - _ (INTERP, 3) /* Program interpreter */ \ - _ (NOTE, 4) /* Auxiliary information */ \ - _ (SEGMENT_TABLE, 6) /* Entry for header table itself */ \ - _ (TLS, 7) /* Thread-local storage segment */ \ - _ (OS_SPECIFIC_LO, 0x60000000) /* Start of OS-specific */ \ - _ (GNU_EH_FRAME, 0x6474e550) /* GCC .eh_frame_hdr segment */ \ - _ (GNU_STACK, 0x6474e551) /* Indicates stack executability */ \ - _ (GNU_RELRO, 0x6474e552) /* Read-only after relocation */ \ - _ (SUNW_BSS, 0x6ffffffa) /* Sun specific BSS */ \ - _ (SUNW_STACK, 0x6ffffffb) /* Sun specific stack */ \ - _ (OS_SPECIFIC_HI, 0x6fffffff) /* End of OS-specific */ \ - _ (ARCH_SPECIFIC_LO, 0x70000000) /* Start of processor-specific */ \ - _ (ARCH_SPECIFIC_HI, 0x7fffffff) /* End of processor-specific */ - -/* Segment flags. */ -#define foreach_elf_segment_flag \ - _ (EXEC, 0) \ - _ (WRITE, 1) \ - _ (READ, 2) \ - _ (OS_SPECIFIC_LO, 20) \ - _ (OS_SPECIFIC_HI, 27) \ - _ (ARCH_SPECIFIC_LO, 28) \ - _ (ARCH_SPECIFIC_HI, 31) - -typedef enum -{ -#define _(f,i) ELF_SEGMENT_##f = i, - foreach_elf_segment_type -#undef _ -} elf_segment_type_t; - -typedef enum -{ -#define _(f,i) ELF_SEGMENT_FLAG_BIT_##f = i, - foreach_elf_segment_flag -#undef _ -} elf_segment_flag_bit_t; - -typedef enum -{ -#define _(f,i) ELF_SEGMENT_FLAG_##f = 1 << ELF_SEGMENT_FLAG_BIT_##f, - foreach_elf_segment_flag -#undef _ -} elf_segment_flag_t; - -#define foreach_elf32_dynamic_entry_header \ - _ (u32, type) \ - _ (u32, data) - -#define foreach_elf64_dynamic_entry_header \ - _ (u64, type) \ - _ (u64, data) - -#define _(t,f) t f; - -typedef struct -{ -foreach_elf32_dynamic_entry_header} elf32_dynamic_entry_t; - -typedef struct -{ -foreach_elf64_dynamic_entry_header} elf64_dynamic_entry_t; - -#undef _ - -#define foreach_elf_dynamic_entry_type \ - _ (END, 0) /* Marks end of dynamic section */ \ - _ (NEEDED_LIBRARY, 1) /* Name of needed library */ \ - _ (PLT_RELOCATION_SIZE, 2) /* Size in bytes of PLT relocs */ \ - _ (PLT_GOT, 3) /* Processor defined value */ \ - _ (SYMBOL_HASH, 4) /* Address of symbol hash table */ \ - _ (STRING_TABLE, 5) /* Address of string table */ \ - _ (SYMBOL_TABLE, 6) /* Address of symbol table */ \ - _ (RELA_ADDRESS, 7) /* Address of Rela relocs */ \ - _ (RELA_SIZE, 8) /* Total size of Rela relocs */ \ - _ (RELA_ENTRY_SIZE, 9) /* Size of one Rela reloc */ \ - _ (STRING_TABLE_SIZE, 10) /* Size of string table */ \ - _ (SYMBOL_TABLE_ENTRY_SIZE, 11) /* Size of one symbol table entry */ \ - _ (INIT_FUNCTION, 12) /* Address of init function */ \ - _ (FINI_FUNCTION, 13) /* Address of termination function */ \ - _ (SONAME, 14) /* Name of shared object */ \ - _ (RPATH, 15) /* Library search path (deprecated) */ \ - _ (SYMBOLIC, 16) /* Start symbol search here */ \ - _ (REL, 17) /* Address of Rel relocs */ \ - _ (RELSZ, 18) /* Total size of Rel relocs */ \ - _ (RELENT, 19) /* Size of one Rel reloc */ \ - _ (PLT_RELOCATION_TYPE, 20) /* Type of reloc in PLT */ \ - _ (DEBUG, 21) /* For debugging; unspecified */ \ - _ (TEXTREL, 22) /* Reloc might modify .text */ \ - _ (PLT_RELOCATION_ADDRESS, 23) /* Address of PLT relocs */ \ - _ (BIND_NOW, 24) /* Process relocations of object */ \ - _ (INIT_ARRAY, 25) /* Array with addresses of init fct */ \ - _ (FINI_ARRAY, 26) /* Array with addresses of fini fct */ \ - _ (INIT_ARRAYSZ, 27) /* Size in bytes of DT_INIT_ARRAY */ \ - _ (FINI_ARRAYSZ, 28) /* Size in bytes of DT_FINI_ARRAY */ \ - _ (RUN_PATH, 29) /* Library search path */ \ - _ (FLAGS, 30) /* Flags for object being loaded */ \ - _ (ENCODING, 31) /* Start of encoded range */ \ - _ (PREINIT_ARRAY, 32) /* Array with addresses of fns */ \ - _ (PREINIT_ARRAY_SIZE, 33) /* Size of PREINIT_ARRAY in bytes. */ \ - _ (GNU_PRELINKED, 0x6ffffdf5) /* Prelinking timestamp */ \ - _ (GNU_CONFLICTSZ, 0x6ffffdf6) /* Size of conflict section */ \ - _ (GNU_LIBLISTSZ, 0x6ffffdf7) /* Size of library list */ \ - _ (CHECKSUM, 0x6ffffdf8) \ - _ (PLTPADSZ, 0x6ffffdf9) \ - _ (MOVEENT, 0x6ffffdfa) \ - _ (MOVESZ, 0x6ffffdfb) \ - _ (FEATURE_1, 0x6ffffdfc) /* Feature selection (DTF_*). */ \ - _ (POSFLAG_1, 0x6ffffdfd) /* Flags for following entries. */ \ - _ (SYMINSZ, 0x6ffffdfe) /* Size of syminfo table (in bytes) */ \ - _ (SYMINENT, 0x6ffffdff) /* Entry size of syminfo */ \ - _ (GNU_HASH, 0x6ffffef5) \ - _ (GNU_CONFLICT, 0x6ffffef8) /* Start of conflict section */ \ - _ (GNU_LIBLIST, 0x6ffffef9) /* Library list */ \ - _ (CONFIG, 0x6ffffefa) /* Configuration information. */ \ - _ (DEPAUDIT, 0x6ffffefb) /* Dependency auditing. */ \ - _ (AUDIT, 0x6ffffefc) /* Object auditing. */ \ - _ (PLTPAD, 0x6ffffefd) /* PLT padding. */ \ - _ (MOVETAB, 0x6ffffefe) /* Move table. */ \ - _ (SYMINFO, 0x6ffffeff) /* Syminfo table. */ \ - _ (VERSYM, 0x6ffffff0) \ - _ (RELACOUNT, 0x6ffffff9) \ - _ (RELCOUNT, 0x6ffffffa) \ - _ (FLAGS_1, 0x6ffffffb) /* State flags, see DF_1_* below. */ \ - _ (VERSION_DEF, 0x6ffffffc) /* Address of version definition table */ \ - _ (VERSION_DEF_COUNT, 0x6ffffffd) /* Number of version definitions */ \ - _ (VERSION_NEED, 0x6ffffffe) /* Address of table with needed versions */ \ - _ (VERSION_NEED_COUNT, 0x6fffffff) /* Number of needed versions */ \ - _ (AUXILIARY, 0x7ffffffd) /* Shared object to load before self */ \ - _ (FILTER, 0x7fffffff) /* Shared object to get values from */ - -typedef enum -{ -#define _(f,n) ELF_DYNAMIC_ENTRY_##f = (n), - foreach_elf_dynamic_entry_type -#undef _ -} elf_dynamic_entry_type_t; - -/* Values of `d_un.d_val' in the DT_FLAGS entry. */ -#define ELF_DYNAMIC_FLAGS_ORIGIN (1 << 0) /* Object may use DF_ORIGIN */ -#define ELF_DYNAMIC_FLAGS_SYMBOLIC (1 << 1) /* Symbol resolutions starts here */ -#define ELF_DYNAMIC_FLAGS_TEXT_RELOCATIONS (1 << 2) /* Object contains text relocations */ -#define ELF_DYNAMIC_FLAGS_BIND_NOW (1 << 3) /* No lazy binding for this object */ -#define ELF_DYNAMIC_FLAGS_STATIC_TLS (1 << 4) /* Module uses the static TLS model */ - -/* State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1 - entry in the dynamic section. */ -#define DF_1_NOW 0x00000001 /* Set RTLD_NOW for this object. */ -#define DF_1_GLOBAL 0x00000002 /* Set RTLD_GLOBAL for this object. */ -#define DF_1_GROUP 0x00000004 /* Set RTLD_GROUP for this object. */ -#define DF_1_NODELETE 0x00000008 /* Set RTLD_NODELETE for this object. */ -#define DF_1_LOADFLTR 0x00000010 /* Trigger filtee loading at runtime. */ -#define DF_1_INITFIRST 0x00000020 /* Set RTLD_INITFIRST for this object */ -#define DF_1_NOOPEN 0x00000040 /* Set RTLD_NOOPEN for this object. */ -#define DF_1_ORIGIN 0x00000080 /* $ORIGIN must be handled. */ -#define DF_1_DIRECT 0x00000100 /* Direct binding enabled. */ -#define DF_1_TRANS 0x00000200 -#define DF_1_INTERPOSE 0x00000400 /* Object is used to interpose. */ -#define DF_1_NODEFLIB 0x00000800 /* Ignore default lib search path. */ -#define DF_1_NODUMP 0x00001000 /* Object can't be dldump'ed. */ -#define DF_1_CONFALT 0x00002000 /* Configuration alternative created. */ -#define DF_1_ENDFILTEE 0x00004000 /* Filtee terminates filters search. */ -#define DF_1_DISPRELDNE 0x00008000 /* Disp reloc applied at build time. */ -#define DF_1_DISPRELPND 0x00010000 /* Disp reloc applied at run-time. */ - -/* Flags for the feature selection in DT_FEATURE_1. */ -#define DTF_1_PARINIT 0x00000001 -#define DTF_1_CONFEXP 0x00000002 - -/* Flags in the DT_POSFLAG_1 entry effecting only the next DT_* entry. */ -#define DF_P1_LAZYLOAD 0x00000001 /* Lazyload following object. */ -#define DF_P1_GROUPPERM 0x00000002 /* Symbols from next object are not - generally available. */ - -/* Version definition sections. */ -typedef struct -{ - u16 version; - u16 flags; - u16 index; - u16 aux_count; - u32 name_hash; - u32 aux_byte_offset; - u32 byte_offset_next_version_definition; -} elf_dynamic_version_definition_t; - -typedef struct -{ - u32 name; - u32 next_offset; /* byte offset of ver def aux next entry */ -} elf_dynamic_version_definition_aux_t; - -/* Version definition flags. */ -#define ELF_DYNAMIC_VERSION_FILE (1 << 0) /* Version definition of file itself */ -#define ELF_DYNAMIC_VERSION_WEAK (1 << 1) /* Weak version identifier */ - -/* Version symbol index. */ -#define ELF_DYNAMIC_VERSYM_LOCAL 0 /* Symbol is local. */ -#define ELF_DYNAMIC_VERSYM_GLOBAL 1 /* Symbol is global. */ -#define ELF_DYNAMIC_VERSYM_RESERVED_LO 0xff00 /* Beginning of reserved entries. */ -#define ELF_DYNAMIC_VERSYM_ELIMINATE 0xff01 /* Symbol is to be eliminated. */ - -/* Version dependency section. */ -#define foreach_elf_dynamic_version_need_field \ - _ (u16, version) \ - _ (u16, aux_count) \ - _ (u32, file_name_offset) \ - _ (u32, first_aux_offset) \ - _ (u32, next_offset) - -#define foreach_elf_dynamic_version_need_aux_field \ - _ (u32, hash) \ - _ (u16, flags) \ - _ (u16, versym_index) \ - _ (u32, name) \ - _ (u32, next_offset) - -typedef struct -{ -#define _(t,f) t f; - foreach_elf_dynamic_version_need_field -#undef _ -} elf_dynamic_version_need_t; - -typedef struct -{ -#define _(t,f) t f; - foreach_elf_dynamic_version_need_aux_field -#undef _ -} elf_dynamic_version_need_aux_t; - -typedef union -{ - elf_dynamic_version_need_t need; - elf_dynamic_version_need_aux_t aux; -} elf_dynamic_version_need_union_t; - -/* Note section contents. Each entry in the note section begins with - a header of a fixed form. */ - -typedef struct -{ - u32 name_size; - u32 descriptor_size; - u32 type; -} elf_note_t; - -/* Known names of notes. */ - -/* Solaris entries in the note section have this name. */ -#define ELF_NOTE_SOLARIS "SUNW Solaris" - -/* Note entries for GNU systems have this name. */ -#define ELF_NOTE_GNU "GNU" - - -/* Defined types of notes for Solaris. */ - -/* Value of descriptor (one word) is desired pagesize for the binary. */ -#define ELF_NOTE_PAGESIZE_HINT 1 - - -/* Defined note types for GNU systems. */ - -/* ABI information. The descriptor consists of words: - word 0: OS descriptor - word 1: major version of the ABI - word 2: minor version of the ABI - word 3: subminor version of the ABI -*/ -#ifndef ELF_NOTE_ABI -#define ELF_NOTE_ABI 1 -#endif - -/* Known OSes. These value can appear in word 0 of an ELF_NOTE_ABI - note section entry. */ -#define ELF_NOTE_OS_LINUX 0 -#define ELF_NOTE_OS_GNU 1 -#define ELF_NOTE_OS_SOLARIS2 2 -#define ELF_NOTE_OS_FREEBSD 3 - -/* AMD x86-64 relocations. */ -#define foreach_elf_x86_64_relocation_type \ - _ (NONE, 0) /* No reloc */ \ - _ (DIRECT_64, 1) /* Direct 64 bit */ \ - _ (PC_REL_I32, 2) /* PC relative 32 bit signed */ \ - _ (GOT_REL_32, 3) /* 32 bit GOT entry */ \ - _ (PLT_REL_32, 4) /* 32 bit PLT address */ \ - _ (COPY, 5) /* Copy symbol at runtime */ \ - _ (CREATE_GOT, 6) /* Create GOT entry */ \ - _ (CREATE_PLT, 7) /* Create PLT entry */ \ - _ (RELATIVE, 8) /* Adjust by program base */ \ - _ (PC_REL_I32_GOT, 9) /* 32 bit PC relative offset to GOT */ \ - _ (DIRECT_U32, 10) /* Direct 32 bit zero extended */ \ - _ (DIRECT_I32, 11) /* Direct 32 bit sign extended */ \ - _ (DIRECT_U16, 12) /* Direct 16 bit zero extended */ \ - _ (PC_REL_I16, 13) /* 16 bit sign extended pc relative */ \ - _ (DIRECT_I8, 14) /* Direct 8 bit sign extended */ \ - _ (PC_REL_I8, 15) /* 8 bit sign extended pc relative */ \ - _ (DTPMOD64, 16) /* ID of module containing symbol */ \ - _ (DTPOFF64, 17) /* Offset in module's TLS block */ \ - _ (TPOFF64, 18) /* Offset in initial TLS block */ \ - _ (TLSGD, 19) /* 32 bit signed PC relative offset to two GOT entries for GD symbol */ \ - _ (TLSLD, 20) /* 32 bit signed PC relative offset to two GOT entries for LD symbol */ \ - _ (DTPOFF32, 21) /* Offset in TLS block */ \ - _ (GOTTPOFF, 22) /* 32 bit signed PC relative offset to GOT entry for IE symbol */ \ - _ (TPOFF32, 23) /* Offset in initial TLS, block) */ - -typedef struct -{ - elf64_symbol_t *symbols; - - u32 section_index; - - u8 *string_table; - - uword *symbol_by_name; -} elf_symbol_table_t; - -always_inline void -elf_symbol_table_free (elf_symbol_table_t * s) -{ - vec_free (s->symbols); - hash_free (s->symbol_by_name); -} - -always_inline u8 * -elf_symbol_name (elf_symbol_table_t * t, elf64_symbol_t * sym) -{ - return vec_elt_at_index (t->string_table, sym->name); -} - -typedef struct -{ - elf_relocation_with_addend_t *relocations; - - u32 section_index; -} elf_relocation_table_t; - -always_inline void -elf_relocation_table_free (elf_relocation_table_t * r) -{ - vec_free (r->relocations); -} - -typedef struct -{ - elf64_section_header_t header; - - u32 index; - - /* Index of segments containing this section. */ - uword *segment_index_bitmap; - - /* Aligned size (included padding not included in - header.file_size). */ - u64 align_size; - - i64 exec_address_change; - - u8 *contents; -} elf_section_t; - -typedef struct -{ - elf64_segment_header_t header; - - /* Sections contained in this segment. */ - uword *section_index_bitmap; - - u32 index; - - u8 *contents; -} elf_segment_t; - -typedef struct -{ - u8 need_byte_swap; - - u8 parsed_symbols; - - char *file_name; - - elf_first_header_t first_header; - - elf64_file_header_t file_header; - - elf_segment_t *segments; - - elf_section_t *sections; - - uword *section_by_name; - uword *section_by_start_address; - - elf_symbol_table_t *symbol_tables; - elf_relocation_table_t *relocation_tables; - - char *interpreter; - - elf64_dynamic_entry_t *dynamic_entries; - u8 *dynamic_string_table; - u32 dynamic_string_table_section_index; - u32 dynamic_symbol_table_section_index; - u32 dynamic_symbol_table_index; - u32 dynamic_section_index; - u16 *versym; - u32 versym_section_index; - elf_dynamic_version_need_union_t *verneed; - u32 verneed_section_index; -} elf_main_t; - -always_inline void -elf_main_init (elf_main_t * em) -{ - memset (em, 0, sizeof (em[0])); -} - -always_inline void -elf_main_free (elf_main_t * em) -{ - uword i; - - for (i = 0; i < vec_len (em->segments); i++) - vec_free (em->segments[i].contents); - vec_free (em->segments); - - for (i = 0; i < vec_len (em->sections); i++) - vec_free (em->sections[i].contents); - vec_free (em->sections); - - hash_free (em->section_by_name); - for (i = 0; i < vec_len (em->symbol_tables); i++) - elf_symbol_table_free (em->symbol_tables + i); - for (i = 0; i < vec_len (em->relocation_tables); i++) - elf_relocation_table_free (em->relocation_tables + i); - - vec_free (em->dynamic_entries); - vec_free (em->interpreter); -} - -always_inline void -elf_get_segment_contents (elf_main_t * em, void *data, uword segment_index) -{ - elf_segment_t *g = vec_elt_at_index (em->segments, segment_index); - if (!g->contents) - vec_add (g->contents, data + g->header.file_offset, - g->header.memory_size); -} - -always_inline void * -elf_get_section_contents (elf_main_t * em, - uword section_index, uword elt_size) -{ - elf_section_t *s; - void *result; - - s = vec_elt_at_index (em->sections, section_index); - - result = 0; - if (vec_len (s->contents) > 0) - { - /* Make vector copy of contents with given element size. */ - result = _vec_resize (result, - vec_len (s->contents) / elt_size, - vec_len (s->contents), - /* header_bytes */ 0, - /* align */ 0); - clib_memcpy (result, s->contents, vec_len (s->contents)); - } - - return result; -} - -always_inline void -elf_set_section_contents (elf_main_t * em, - uword section_index, - void *new_contents, uword n_content_bytes) -{ - elf_section_t *s; - - s = vec_elt_at_index (em->sections, section_index); - vec_free (s->contents); - vec_add (s->contents, new_contents, n_content_bytes); -} - -always_inline u8 * -elf_section_name (elf_main_t * em, elf_section_t * s) -{ - elf_section_t *es = vec_elt_at_index (em->sections, - em-> - file_header.section_header_string_table_index); - return vec_elt_at_index (es->contents, s->header.name); -} - -always_inline u8 -elf_swap_u8 (elf_main_t * em, u8 x) -{ - return x; -} - -always_inline u16 -elf_swap_u16 (elf_main_t * em, u16 x) -{ - return em->need_byte_swap ? clib_byte_swap_u16 (x) : x; -} - -always_inline u32 -elf_swap_u32 (elf_main_t * em, u32 x) -{ - return em->need_byte_swap ? clib_byte_swap_u32 (x) : x; -} - -always_inline u64 -elf_swap_u64 (elf_main_t * em, u64 x) -{ - return em->need_byte_swap ? clib_byte_swap_u64 (x) : x; -} - -#define FORMAT_ELF_MAIN_SYMBOLS (1 << 0) -#define FORMAT_ELF_MAIN_RELOCATIONS (1 << 1) -#define FORMAT_ELF_MAIN_DYNAMIC (1 << 2) - -format_function_t format_elf_main; -format_function_t format_elf_symbol; - -clib_error_t *elf_read_file (elf_main_t * em, char *file_name); -clib_error_t *elf_write_file (elf_main_t * em, char *file_name); -clib_error_t *elf_delete_named_section (elf_main_t * em, char *section_name); -clib_error_t *elf_parse (elf_main_t * em, void *data, uword data_bytes); -void elf_parse_symbols (elf_main_t * em); - -clib_error_t *elf_get_section_by_name (elf_main_t * em, char *section_name, - elf_section_t ** result); -clib_error_t *elf_get_section_by_start_address (elf_main_t * em, - uword start_address, - elf_section_t ** result); - -void -elf_create_section_with_contents (elf_main_t * em, - char *section_name, - elf64_section_header_t * header, - void *contents, uword n_content_bytes); -uword elf_delete_segment_with_type (elf_main_t * em, - elf_segment_type_t segment_type); -void elf_set_dynamic_entries (elf_main_t * em); - -#endif /* included_clib_elf_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/elf_clib.c b/vppinfra/vppinfra/elf_clib.c deleted file mode 100644 index 7bb72ee3e3f..00000000000 --- a/vppinfra/vppinfra/elf_clib.c +++ /dev/null @@ -1,377 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include <vppinfra/elf_clib.h> - -#include <stdlib.h> -#include <fcntl.h> -#include <sys/stat.h> - -typedef struct -{ - char **path; -} path_search_t; - -always_inline void -path_search_free (path_search_t * p) -{ - uword i; - for (i = 0; i < vec_len (p->path); i++) - vec_free (p->path[i]); - vec_free (p->path); -} - -static char ** -split_string (char *string, u8 delimiter) -{ - char **result = 0; - char *p, *start, *s; - - p = string; - while (1) - { - start = p; - while (*p != 0 && *p != delimiter) - p++; - s = 0; - vec_add (s, start, p - start); - vec_add1 (s, 0); - vec_add1 (result, s); - if (*p == 0) - break; - p++; - } - - return result; -} - -static int -file_exists_and_is_executable (char *dir, char *file) -{ - char *path = (char *) format (0, "%s/%s%c", dir, file, 0); - struct stat s; - uword yes; - - yes = (stat (path, &s) >= 0 - && S_ISREG (s.st_mode) - && 0 != (s.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))); - - vec_free (path); - - return yes; -} - -static char * -path_search (char *file) -{ - path_search_t ps; - uword i; - char *result; - - /* Relative or absolute path. */ - if (file[0] == '.' || file[0] == '/') - return file; - - if (getenv ("PATH") == 0) - return file; - - ps.path = split_string (getenv ("PATH"), ':'); - - for (i = 0; i < vec_len (ps.path); i++) - if (file_exists_and_is_executable (ps.path[i], file)) - break; - - result = 0; - if (i < vec_len (ps.path)) - result = (char *) format (0, "%s/%s%c", ps.path[i], file); - - path_search_free (&ps); - - return result; -} - -static clib_error_t * -clib_elf_parse_file (clib_elf_main_t * cem, - char *file_name, void *link_address) -{ - elf_main_t *em; - elf_section_t *s; - int fd; - struct stat fd_stat; - uword mmap_length = 0; - void *data = 0; - clib_error_t *error = 0; - - vec_add2 (cem->elf_mains, em, 1); - - fd = open (file_name, 0); - if (fd < 0) - { - error = clib_error_return_unix (0, "open `%s'", file_name); - goto done; - } - - if (fstat (fd, &fd_stat) < 0) - { - error = clib_error_return_unix (0, "fstat `%s'", file_name); - goto done; - } - mmap_length = fd_stat.st_size; - - data = mmap (0, mmap_length, PROT_READ, MAP_SHARED, fd, /* offset */ 0); - if (~pointer_to_uword (data) == 0) - { - error = clib_error_return_unix (0, "mmap `%s'", file_name); - goto done; - } - - error = elf_parse (em, data, mmap_length); - if (error) - goto done; - - /* Look for CLIB special sections. */ - { - char *section_name_start = CLIB_ELF_SECTION_ADD_PREFIX (); - uword section_name_start_len = strlen (section_name_start); - - vec_foreach (s, em->sections) - { - u8 *name = elf_section_name (em, s); - uword *p; - clib_elf_section_t *vs; - clib_elf_section_bounds_t *b; - - /* Section name must begin with CLIB_ELF_SECTION key. */ - if (memcmp (name, section_name_start, section_name_start_len)) - continue; - - name += section_name_start_len; - p = hash_get_mem (cem->section_by_name, name); - if (p) - vs = vec_elt_at_index (cem->sections, p[0]); - else - { - name = format (0, "%s%c", name, 0); - if (!cem->section_by_name) - cem->section_by_name = hash_create_string (0, sizeof (uword)); - hash_set_mem (cem->section_by_name, name, vec_len (cem->sections)); - vec_add2 (cem->sections, vs, 1); - vs->name = name; - } - - vec_add2 (vs->bounds, b, 1); - b->lo = link_address + s->header.exec_address; - b->hi = b->lo + s->header.file_size; - } - } - - /* Parse symbols for this file. */ - { - elf_symbol_table_t *t; - elf64_symbol_t *s; - - elf_parse_symbols (em); - vec_foreach (t, em->symbol_tables) - { - vec_foreach (s, t->symbols) - { - s->value += pointer_to_uword (link_address); - } - } - } - - /* No need to keep section contents around. */ - { - elf_section_t *s; - vec_foreach (s, em->sections) - { - if (s->header.type != ELF_SECTION_STRING_TABLE) - vec_free (s->contents); - } - } - -done: - if (error) - elf_main_free (em); - if (fd >= 0) - close (fd); - if (data) - munmap (data, mmap_length); - return error; -} - -#define __USE_GNU -#include <link.h> - -static int -add_section (struct dl_phdr_info *info, size_t size, void *opaque) -{ - clib_elf_main_t *cem = opaque; - clib_error_t *error; - char *name = (char *) info->dlpi_name; - void *addr = (void *) info->dlpi_addr; - uword is_main; - - is_main = strlen (name) == 0; - if (is_main) - { - static int done; - - /* Only do main program once. */ - if (done++) - return 0; - - name = path_search (cem->exec_path); - if (!name) - { - clib_error ("failed to find %s on PATH", cem->exec_path); - return 0; - } - addr = 0; - } - - error = clib_elf_parse_file (cem, name, addr); - if (error) - clib_error_report (error); - - if (is_main && name != cem->exec_path) - vec_free (name); - - return 0; -} - -static clib_elf_main_t clib_elf_main; - -void -clib_elf_main_init (char *exec_path) -{ - clib_elf_main_t *cem = &clib_elf_main; - - cem->exec_path = exec_path; - - dl_iterate_phdr (add_section, cem); -} - -clib_elf_section_bounds_t * -clib_elf_get_section_bounds (char *name) -{ - clib_elf_main_t *em = &clib_elf_main; - uword *p = hash_get (em->section_by_name, name); - return p ? vec_elt_at_index (em->sections, p[0])->bounds : 0; -} - -static uword -symbol_by_address_or_name (char *by_name, - uword by_address, clib_elf_symbol_t * s) -{ - clib_elf_main_t *cem = &clib_elf_main; - elf_main_t *em; - - vec_foreach (em, cem->elf_mains) - { - elf_symbol_table_t *t; - s->elf_main_index = em - cem->elf_mains; - vec_foreach (t, em->symbol_tables) - { - s->symbol_table_index = t - em->symbol_tables; - if (by_name) - { - uword *p = hash_get (t->symbol_by_name, by_name); - if (p) - { - s->symbol = vec_elt (t->symbols, p[0]); - return 1; - } - } - else - { - elf64_symbol_t *x; - /* FIXME linear search. */ - vec_foreach (x, t->symbols) - { - if (by_address >= x->value && by_address < x->value + x->size) - { - s->symbol = x[0]; - return 1; - } - } - } - } - } - - return 0; -} - -uword -clib_elf_symbol_by_name (char *by_name, clib_elf_symbol_t * s) -{ - return symbol_by_address_or_name (by_name, /* by_address */ 0, s); -} - -uword -clib_elf_symbol_by_address (uword by_address, clib_elf_symbol_t * s) -{ - return symbol_by_address_or_name ( /* by_name */ 0, by_address, s); -} - -u8 * -format_clib_elf_symbol (u8 * s, va_list * args) -{ - clib_elf_main_t *cem = &clib_elf_main; - clib_elf_symbol_t *sym = va_arg (*args, clib_elf_symbol_t *); - elf_main_t *em; - elf_symbol_table_t *t; - - if (!sym) - /* Just print table headings. */ - return format (s, "%U", format_elf_symbol, 0, 0, 0); - - else - { - em = vec_elt_at_index (cem->elf_mains, sym->elf_main_index); - t = vec_elt_at_index (em->symbol_tables, sym->symbol_table_index); - return format (s, "%U", format_elf_symbol, em, t, &sym->symbol); - } -} - -u8 * -format_clib_elf_symbol_with_address (u8 * s, va_list * args) -{ - uword address = va_arg (*args, uword); - clib_elf_main_t *cem = &clib_elf_main; - clib_elf_symbol_t sym; - elf_main_t *em; - elf_symbol_table_t *t; - - if (clib_elf_symbol_by_address (address, &sym)) - { - em = vec_elt_at_index (cem->elf_mains, sym.elf_main_index); - t = vec_elt_at_index (em->symbol_tables, sym.symbol_table_index); - s = format (s, "%s + 0x%wx", - elf_symbol_name (t, &sym.symbol), - address - sym.symbol.value); - } - else - s = format (s, "0x%wx", address); - - return s; -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/elf_clib.h b/vppinfra/vppinfra/elf_clib.h deleted file mode 100644 index 25b928c22a5..00000000000 --- a/vppinfra/vppinfra/elf_clib.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2012 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_clib_elf_self_h -#define included_clib_elf_self_h - -#include <vppinfra/elf.h> -#include <vppinfra/hash.h> - -#define CLIB_ELF_SECTION_DATA_ALIGN 32 - -#define CLIB_ELF_SECTION_ADD_PREFIX(n) "clib_elf_section_" n - -/* Attribute used is so that static registrations work even if - variable is not referenced. */ -#define CLIB_ELF_SECTION(SECTION) \ - __attribute__ ((used, \ - aligned (CLIB_ELF_SECTION_DATA_ALIGN), \ - section (CLIB_ELF_SECTION_ADD_PREFIX (SECTION)))) - -/* Given pointer to previous data A get next pointer. EXTRA gives extra - space beyond A + 1 used in object. */ -#define clib_elf_section_data_next(a,extra) \ - uword_to_pointer (round_pow2 (pointer_to_uword (a + 1) + (extra), \ - CLIB_ELF_SECTION_DATA_ALIGN), \ - void *) - -typedef struct -{ - void *lo, *hi; -} clib_elf_section_bounds_t; - -typedef struct -{ - /* Vector of bounds for this section. Multiple shared objects may have instances - of the same sections. */ - clib_elf_section_bounds_t *bounds; - - /* Name of ELF section (e.g. .text). */ - u8 *name; -} clib_elf_section_t; - -typedef struct -{ - /* Vector of sections. */ - clib_elf_section_t *sections; - - /* Hash map of name to section index. */ - uword *section_by_name; - - /* Unix path that we were exec()ed with. */ - char *exec_path; - - elf_main_t *elf_mains; -} clib_elf_main_t; - -always_inline void -clib_elf_main_free (clib_elf_main_t * m) -{ - clib_elf_section_t *s; - vec_foreach (s, m->sections) - { - vec_free (s->bounds); - vec_free (s->name); - } - vec_free (m->sections); - hash_free (m->section_by_name); - - { - elf_main_t *em; - vec_foreach (em, m->elf_mains) - { - elf_main_free (em); - } - vec_free (m->elf_mains); - } -} - -/* Call with exec_path equal to argv[0] from C main. */ -void clib_elf_main_init (char *exec_path); - -clib_elf_section_bounds_t *clib_elf_get_section_bounds (char *name); - -typedef struct -{ - /* The symbol. */ - elf64_symbol_t symbol; - - /* elf_main_t where symbol came from. */ - u32 elf_main_index; - - /* Symbol table in elf_main_t where this symbol came from. */ - u32 symbol_table_index; -} clib_elf_symbol_t; - -/* Returns 1 if found; otherwise zero. */ -uword clib_elf_symbol_by_name (char *name, clib_elf_symbol_t * result); -uword clib_elf_symbol_by_address (uword address, clib_elf_symbol_t * result); - -format_function_t format_clib_elf_symbol, format_clib_elf_symbol_with_address; - -#endif /* included_clib_elf_self_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/elog.c b/vppinfra/vppinfra/elog.c deleted file mode 100644 index e9f06d0948c..00000000000 --- a/vppinfra/vppinfra/elog.c +++ /dev/null @@ -1,1061 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2005,2009 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include <vppinfra/elog.h> -#include <vppinfra/cache.h> -#include <vppinfra/error.h> -#include <vppinfra/format.h> -#include <vppinfra/hash.h> -#include <vppinfra/math.h> - -static inline void -elog_lock (elog_main_t * em) -{ - if (PREDICT_FALSE (em->lock != 0)) - while (__sync_lock_test_and_set (em->lock, 1)) - ; -} - -static inline void -elog_unlock (elog_main_t * em) -{ - if (PREDICT_FALSE (em->lock != 0)) - { - CLIB_MEMORY_BARRIER (); - *em->lock = 0; - } -} - -/* Non-inline version. */ -void * -elog_event_data (elog_main_t * em, - elog_event_type_t * type, elog_track_t * track, u64 cpu_time) -{ - return elog_event_data_inline (em, type, track, cpu_time); -} - -static void -new_event_type (elog_main_t * em, uword i) -{ - elog_event_type_t *t = vec_elt_at_index (em->event_types, i); - - if (!em->event_type_by_format) - em->event_type_by_format = - hash_create_vec ( /* size */ 0, sizeof (u8), sizeof (uword)); - - hash_set_mem (em->event_type_by_format, t->format, i); -} - -static uword -find_or_create_type (elog_main_t * em, elog_event_type_t * t) -{ - uword *p = hash_get_mem (em->event_type_by_format, t->format); - uword i; - - if (p) - i = p[0]; - else - { - i = vec_len (em->event_types); - vec_add1 (em->event_types, t[0]); - new_event_type (em, i); - } - - return i; -} - -/* External function to register types. */ -word -elog_event_type_register (elog_main_t * em, elog_event_type_t * t) -{ - elog_event_type_t *static_type = t; - word l; - - elog_lock (em); - - l = vec_len (em->event_types); - - t->type_index_plus_one = 1 + l; - - ASSERT (t->format); - - /* If format args are not specified try to be smart about providing defaults - so most of the time user does not have to specify them. */ - if (!t->format_args) - { - uword i, l; - char *this_arg; - - l = strlen (t->format); - for (i = 0; i < l; i++) - { - if (t->format[i] != '%') - continue; - if (i + 1 >= l) - continue; - if (t->format[i + 1] == '%') /* %% */ - continue; - - switch (t->format[i + 1]) - { - default: - case 'd': - case 'x': - case 'u': - this_arg = "i4"; /* size of u32 */ - break; - case 'f': - this_arg = "f8"; /* defaults to f64 */ - break; - case 's': - this_arg = "s0"; /* defaults to null terminated string. */ - break; - } - - t->format_args = - (char *) format ((u8 *) t->format_args, "%s", this_arg); - } - - /* Null terminate. */ - vec_add1 (t->format_args, 0); - } - - vec_add1 (em->event_types, t[0]); - - t = em->event_types + l; - - /* Make copies of strings for hashing etc. */ - if (t->function) - t->format = (char *) format (0, "%s %s%c", t->function, t->format, 0); - else - t->format = (char *) format (0, "%s%c", t->format, 0); - - t->format_args = (char *) format (0, "%s%c", t->format_args, 0); - - /* Construct string table. */ - { - uword i; - t->n_enum_strings = static_type->n_enum_strings; - for (i = 0; i < t->n_enum_strings; i++) - { - if (!static_type->enum_strings[i]) - static_type->enum_strings[i] = "MISSING"; - vec_add1 (t->enum_strings_vector, - (char *) format (0, "%s%c", static_type->enum_strings[i], - 0)); - } - } - - new_event_type (em, l); - elog_unlock (em); - - return l; -} - -word -elog_track_register (elog_main_t * em, elog_track_t * t) -{ - word l; - - elog_lock (em); - - l = vec_len (em->tracks); - - t->track_index_plus_one = 1 + l; - - ASSERT (t->name); - - vec_add1 (em->tracks, t[0]); - - t = em->tracks + l; - - t->name = (char *) format (0, "%s%c", t->name, 0); - - elog_unlock (em); - - return l; -} - -static uword -parse_2digit_decimal (char *p, uword * number) -{ - uword i = 0; - u8 digits[2]; - - digits[0] = digits[1] = 0; - while (p[i] >= '0' && p[i] <= '9') - { - if (i >= 2) - break; - digits[i] = p[i] - '0'; - i++; - } - - if (i >= 1 && i <= 2) - { - if (i == 1) - *number = digits[0]; - else - *number = 10 * digits[0] + digits[1]; - return i; - } - else - return 0; -} - -static u8 * -fixed_format (u8 * s, char *fmt, char *result, uword * result_len) -{ - char *f = fmt; - char *percent; - uword l = 0; - - while (1) - { - if (f[0] == 0) - break; - if (f[0] == '%' && f[1] != '%') - break; - f++; - } - if (f > fmt) - vec_add (s, fmt, f - fmt); - - if (f[0] != '%') - goto done; - - /* Skip percent. */ - percent = f++; - - /* Skip possible +-= justification. */ - f += f[0] == '+' || f[0] == '-' || f[0] == '='; - - /* Skip possible X.Y width. */ - while ((f[0] >= '0' && f[0] <= '9') || f[0] == '.') - f++; - - /* Skip wlL as in e.g. %Ld. */ - f += f[0] == 'w' || f[0] == 'l' || f[0] == 'L'; - - /* Finally skip format letter. */ - f += f[0] != 0; - - ASSERT (*result_len > f - percent); - l = clib_min (f - percent, *result_len - 1); - clib_memcpy (result, percent, l); - result[l] = 0; - -done: - *result_len = f - fmt; - return s; -} - -u8 * -format_elog_event (u8 * s, va_list * va) -{ - elog_main_t *em = va_arg (*va, elog_main_t *); - elog_event_t *e = va_arg (*va, elog_event_t *); - elog_event_type_t *t; - char *a, *f; - void *d = (u8 *) e->data; - char arg_format[64]; - - t = vec_elt_at_index (em->event_types, e->type); - - f = t->format; - a = t->format_args; - while (1) - { - uword n_bytes = 0, n_digits, f_bytes = 0; - - f_bytes = sizeof (arg_format); - s = fixed_format (s, f, arg_format, &f_bytes); - f += f_bytes; - - if (a == 0 || a[0] == 0) - { - /* Format must also be at end. */ - ASSERT (f[0] == 0); - break; - } - - /* Don't go past end of event data. */ - ASSERT (d < (void *) (e->data + sizeof (e->data))); - - n_digits = parse_2digit_decimal (a + 1, &n_bytes); - switch (a[0]) - { - case 'i': - case 't': - case 'T': - { - u32 i = 0; - u64 l = 0; - - if (n_bytes == 1) - i = ((u8 *) d)[0]; - else if (n_bytes == 2) - i = clib_mem_unaligned (d, u16); - else if (n_bytes == 4) - i = clib_mem_unaligned (d, u32); - else if (n_bytes == 8) - l = clib_mem_unaligned (d, u64); - else - ASSERT (0); - if (a[0] == 't') - { - char *e = - vec_elt (t->enum_strings_vector, n_bytes == 8 ? l : i); - s = format (s, arg_format, e); - } - else if (a[0] == 'T') - { - char *e = - vec_elt_at_index (em->string_table, n_bytes == 8 ? l : i); - s = format (s, arg_format, e); - } - else if (n_bytes == 8) - s = format (s, arg_format, l); - else - s = format (s, arg_format, i); - } - break; - - case 'f': - { - f64 x = 0; - if (n_bytes == 4) - x = clib_mem_unaligned (d, f32); - else if (n_bytes == 8) - x = clib_mem_unaligned (d, f64); - else - ASSERT (0); - s = format (s, arg_format, x); - } - break; - - case 's': - s = format (s, arg_format, d); - if (n_bytes == 0) - n_bytes = strlen (d) + 1; - break; - - default: - ASSERT (0); - break; - } - - ASSERT (n_digits > 0 && n_digits <= 2); - a += 1 + n_digits; - d += n_bytes; - } - - return s; -} - -u8 * -format_elog_track (u8 * s, va_list * va) -{ - elog_main_t *em = va_arg (*va, elog_main_t *); - elog_event_t *e = va_arg (*va, elog_event_t *); - elog_track_t *t = vec_elt_at_index (em->tracks, e->track); - return format (s, "%s", t->name); -} - -void -elog_time_now (elog_time_stamp_t * et) -{ - u64 cpu_time_now, os_time_now_nsec; - -#ifdef CLIB_UNIX - { -#include <sys/syscall.h> - struct timespec ts; - syscall (SYS_clock_gettime, CLOCK_REALTIME, &ts); - cpu_time_now = clib_cpu_time_now (); - os_time_now_nsec = 1e9 * ts.tv_sec + ts.tv_nsec; - } -#else - cpu_time_now = clib_cpu_time_now (); - os_time_now_nsec = 0; -#endif - - et->cpu = cpu_time_now; - et->os_nsec = os_time_now_nsec; -} - -always_inline i64 -elog_time_stamp_diff_os_nsec (elog_time_stamp_t * t1, elog_time_stamp_t * t2) -{ - return (i64) t1->os_nsec - (i64) t2->os_nsec; -} - -always_inline i64 -elog_time_stamp_diff_cpu (elog_time_stamp_t * t1, elog_time_stamp_t * t2) -{ - return (i64) t1->cpu - (i64) t2->cpu; -} - -always_inline f64 -elog_nsec_per_clock (elog_main_t * em) -{ - return ((f64) elog_time_stamp_diff_os_nsec (&em->serialize_time, - &em->init_time) - / (f64) elog_time_stamp_diff_cpu (&em->serialize_time, - &em->init_time)); -} - -void -elog_alloc (elog_main_t * em, u32 n_events) -{ - if (em->event_ring) - vec_free (em->event_ring); - - /* Ring size must be a power of 2. */ - em->event_ring_size = n_events = max_pow2 (n_events); - - /* Leave an empty ievent at end so we can always speculatively write - and event there (possibly a long form event). */ - vec_resize_aligned (em->event_ring, n_events, CLIB_CACHE_LINE_BYTES); -} - -void -elog_init (elog_main_t * em, u32 n_events) -{ - memset (em, 0, sizeof (em[0])); - - em->lock = 0; - - if (n_events > 0) - elog_alloc (em, n_events); - - clib_time_init (&em->cpu_timer); - - em->n_total_events_disable_limit = ~0; - - /* Make track 0. */ - em->default_track.name = "default"; - elog_track_register (em, &em->default_track); - - elog_time_now (&em->init_time); -} - -/* Returns number of events in ring and start index. */ -static uword -elog_event_range (elog_main_t * em, uword * lo) -{ - uword l = em->event_ring_size; - u64 i = em->n_total_events; - - /* Ring never wrapped? */ - if (i <= (u64) l) - { - if (lo) - *lo = 0; - return i; - } - else - { - if (lo) - *lo = i & (l - 1); - return l; - } -} - -elog_event_t * -elog_peek_events (elog_main_t * em) -{ - elog_event_t *e, *f, *es = 0; - uword i, j, n; - - n = elog_event_range (em, &j); - for (i = 0; i < n; i++) - { - vec_add2 (es, e, 1); - f = vec_elt_at_index (em->event_ring, j); - e[0] = f[0]; - - /* Convert absolute time from cycles to seconds from start. */ - e->time = - (e->time_cycles - - em->init_time.cpu) * em->cpu_timer.seconds_per_clock; - - j = (j + 1) & (em->event_ring_size - 1); - } - - return es; -} - -/* Add a formatted string to the string table. */ -u32 -elog_string (elog_main_t * em, char *fmt, ...) -{ - u32 offset; - va_list va; - - va_start (va, fmt); - offset = vec_len (em->string_table); - em->string_table = (char *) va_format ((u8 *) em->string_table, fmt, &va); - va_end (va); - - /* Null terminate string if it is not already. */ - if (vec_end (em->string_table)[-1] != 0) - vec_add1 (em->string_table, 0); - - return offset; -} - -elog_event_t * -elog_get_events (elog_main_t * em) -{ - if (!em->events) - em->events = elog_peek_events (em); - return em->events; -} - -static void -maybe_fix_string_table_offset (elog_event_t * e, - elog_event_type_t * t, u32 offset) -{ - void *d = (u8 *) e->data; - char *a; - - if (offset == 0) - return; - - a = t->format_args; - - while (1) - { - uword n_bytes = 0, n_digits; - - if (a[0] == 0) - break; - - /* Don't go past end of event data. */ - ASSERT (d < (void *) (e->data + sizeof (e->data))); - - n_digits = parse_2digit_decimal (a + 1, &n_bytes); - switch (a[0]) - { - case 'T': - ASSERT (n_bytes == 4); - clib_mem_unaligned (d, u32) += offset; - break; - - case 'i': - case 't': - case 'f': - case 's': - break; - - default: - ASSERT (0); - break; - } - - ASSERT (n_digits > 0 && n_digits <= 2); - a += 1 + n_digits; - d += n_bytes; - } -} - -static int -elog_cmp (void *a1, void *a2) -{ - elog_event_t *e1 = a1; - elog_event_t *e2 = a2; - - return e1->time - e2->time; -} - -void -elog_merge (elog_main_t * dst, u8 * dst_tag, elog_main_t * src, u8 * src_tag) -{ - elog_event_t *e; - uword l; - u32 string_table_offset_for_src_events; - u32 track_offset_for_src_tracks; - elog_track_t newt; - int i; - - memset (&newt, 0, sizeof (newt)); - - elog_get_events (src); - elog_get_events (dst); - - string_table_offset_for_src_events = vec_len (dst->string_table); - vec_append (dst->string_table, src->string_table); - - l = vec_len (dst->events); - vec_add (dst->events, src->events, vec_len (src->events)); - - /* Prepend the supplied tag (if any) to all dst track names */ - if (dst_tag) - { - for (i = 0; i < vec_len (dst->tracks); i++) - { - elog_track_t *t = vec_elt_at_index (dst->tracks, i); - char *new_name; - - new_name = (char *) format (0, "%s:%s%c", dst_tag, t->name, 0); - vec_free (t->name); - t->name = new_name; - } - } - - track_offset_for_src_tracks = vec_len (dst->tracks); - - /* Copy / tag source tracks */ - for (i = 0; i < vec_len (src->tracks); i++) - { - elog_track_t *t = vec_elt_at_index (src->tracks, i); - if (src_tag) - newt.name = (char *) format (0, "%s:%s%c", src_tag, t->name, 0); - else - newt.name = (char *) format (0, "%s%c", t->name, 0); - (void) elog_track_register (dst, &newt); - vec_free (newt.name); - } - - /* Across all (copied) src events... */ - for (e = dst->events + l; e < vec_end (dst->events); e++) - { - elog_event_type_t *t = vec_elt_at_index (src->event_types, e->type); - - /* Remap type from src -> dst. */ - e->type = find_or_create_type (dst, t); - - /* Remap string table offsets for 'T' format args */ - maybe_fix_string_table_offset (e, t, - string_table_offset_for_src_events); - - /* Remap track */ - e->track += track_offset_for_src_tracks; - } - - /* Adjust event times for relative starting times of event streams. */ - { - f64 dt_event, dt_os_nsec, dt_clock_nsec; - - /* Set clock parameters if dst was not generated by unserialize. */ - if (dst->serialize_time.cpu == 0) - { - dst->init_time = src->init_time; - dst->serialize_time = src->serialize_time; - dst->nsec_per_cpu_clock = src->nsec_per_cpu_clock; - } - - dt_os_nsec = - elog_time_stamp_diff_os_nsec (&src->init_time, &dst->init_time); - - dt_event = dt_os_nsec; - dt_clock_nsec = - (elog_time_stamp_diff_cpu (&src->init_time, &dst->init_time) * .5 * - (dst->nsec_per_cpu_clock + src->nsec_per_cpu_clock)); - - /* Heuristic to see if src/dst came from same time source. - If frequencies are "the same" and os clock and cpu clock agree - to within 100e-9 secs about time difference between src/dst - init_time, then we use cpu clock. Otherwise we use OS clock. */ - if (fabs (src->nsec_per_cpu_clock - dst->nsec_per_cpu_clock) < 1e-2 - && fabs (dt_os_nsec - dt_clock_nsec) < 100) - dt_event = dt_clock_nsec; - - /* Convert to seconds. */ - dt_event *= 1e-9; - - if (dt_event > 0) - { - /* Src started after dst. */ - for (e = dst->events + l; e < vec_end (dst->events); e++) - e->time += dt_event; - } - else - { - /* Dst started after src. */ - for (e = dst->events + 0; e < dst->events + l; e++) - e->time += dt_event; - } - } - - /* Sort events by increasing time. */ - vec_sort_with_function (dst->events, elog_cmp); - - /* Recreate the event ring or the results won't serialize */ - { - int i; - - ASSERT (dst->cpu_timer.seconds_per_clock); - - elog_alloc (dst, vec_len (dst->events)); - for (i = 0; i < vec_len (dst->events); i++) - { - elog_event_t *es, *ed; - - es = dst->events + i; - ed = dst->event_ring + i; - - ed[0] = es[0]; - - /* Invert elog_peek_events calculation */ - ed->time_cycles = - (es->time / dst->cpu_timer.seconds_per_clock) + dst->init_time.cpu; - } - dst->n_total_events = vec_len (dst->events); - } -} - -static void -serialize_elog_event (serialize_main_t * m, va_list * va) -{ - elog_main_t *em = va_arg (*va, elog_main_t *); - elog_event_t *e = va_arg (*va, elog_event_t *); - elog_event_type_t *t = vec_elt_at_index (em->event_types, e->type); - u8 *d = e->data; - u8 *p = (u8 *) t->format_args; - - serialize_integer (m, e->type, sizeof (e->type)); - serialize_integer (m, e->track, sizeof (e->track)); - serialize (m, serialize_f64, e->time); - - while (*p) - { - uword n_digits, n_bytes = 0; - - n_digits = parse_2digit_decimal ((char *) p + 1, &n_bytes); - - switch (p[0]) - { - case 'i': - case 't': - case 'T': - if (n_bytes == 1) - serialize_integer (m, d[0], sizeof (u8)); - else if (n_bytes == 2) - serialize_integer (m, clib_mem_unaligned (d, u16), sizeof (u16)); - else if (n_bytes == 4) - serialize_integer (m, clib_mem_unaligned (d, u32), sizeof (u32)); - else if (n_bytes == 8) - serialize (m, serialize_64, clib_mem_unaligned (d, u64)); - else - ASSERT (0); - break; - - case 's': - serialize_cstring (m, (char *) d); - if (n_bytes == 0) - n_bytes = strlen ((char *) d) + 1; - break; - - case 'f': - if (n_bytes == 4) - serialize (m, serialize_f32, clib_mem_unaligned (d, f32)); - else if (n_bytes == 8) - serialize (m, serialize_f64, clib_mem_unaligned (d, f64)); - else - ASSERT (0); - break; - - default: - ASSERT (0); - break; - } - - p += 1 + n_digits; - d += n_bytes; - } -} - -static void -unserialize_elog_event (serialize_main_t * m, va_list * va) -{ - elog_main_t *em = va_arg (*va, elog_main_t *); - elog_event_t *e = va_arg (*va, elog_event_t *); - elog_event_type_t *t; - u8 *p, *d; - - { - u16 tmp[2]; - - unserialize_integer (m, &tmp[0], sizeof (e->type)); - unserialize_integer (m, &tmp[1], sizeof (e->track)); - - e->type = tmp[0]; - e->track = tmp[1]; - - /* Make sure it fits. */ - ASSERT (e->type == tmp[0]); - ASSERT (e->track == tmp[1]); - } - - t = vec_elt_at_index (em->event_types, e->type); - - unserialize (m, unserialize_f64, &e->time); - - d = e->data; - p = (u8 *) t->format_args; - - while (p && *p) - { - uword n_digits, n_bytes = 0; - u32 tmp; - - n_digits = parse_2digit_decimal ((char *) p + 1, &n_bytes); - - switch (p[0]) - { - case 'i': - case 't': - case 'T': - if (n_bytes == 1) - { - unserialize_integer (m, &tmp, sizeof (u8)); - d[0] = tmp; - } - else if (n_bytes == 2) - { - unserialize_integer (m, &tmp, sizeof (u16)); - clib_mem_unaligned (d, u16) = tmp; - } - else if (n_bytes == 4) - { - unserialize_integer (m, &tmp, sizeof (u32)); - clib_mem_unaligned (d, u32) = tmp; - } - else if (n_bytes == 8) - { - u64 x; - unserialize (m, unserialize_64, &x); - clib_mem_unaligned (d, u64) = x; - } - else - ASSERT (0); - break; - - case 's': - { - char *t; - unserialize_cstring (m, &t); - if (n_bytes == 0) - n_bytes = strlen (t) + 1; - clib_memcpy (d, t, clib_min (n_bytes, vec_len (t))); - vec_free (t); - break; - } - - case 'f': - if (n_bytes == 4) - { - f32 x; - unserialize (m, unserialize_f32, &x); - clib_mem_unaligned (d, f32) = x; - } - else if (n_bytes == 8) - { - f64 x; - unserialize (m, unserialize_f64, &x); - clib_mem_unaligned (d, f64) = x; - } - else - ASSERT (0); - break; - - default: - ASSERT (0); - break; - } - - p += 1 + n_digits; - d += n_bytes; - } -} - -static void -serialize_elog_event_type (serialize_main_t * m, va_list * va) -{ - elog_event_type_t *t = va_arg (*va, elog_event_type_t *); - int n = va_arg (*va, int); - int i, j; - for (i = 0; i < n; i++) - { - serialize_cstring (m, t[i].format); - serialize_cstring (m, t[i].format_args); - serialize_integer (m, t[i].type_index_plus_one, - sizeof (t->type_index_plus_one)); - serialize_integer (m, t[i].n_enum_strings, - sizeof (t[i].n_enum_strings)); - for (j = 0; j < t[i].n_enum_strings; j++) - serialize_cstring (m, t[i].enum_strings_vector[j]); - } -} - -static void -unserialize_elog_event_type (serialize_main_t * m, va_list * va) -{ - elog_event_type_t *t = va_arg (*va, elog_event_type_t *); - int n = va_arg (*va, int); - int i, j; - for (i = 0; i < n; i++) - { - unserialize_cstring (m, &t[i].format); - unserialize_cstring (m, &t[i].format_args); - unserialize_integer (m, &t[i].type_index_plus_one, - sizeof (t->type_index_plus_one)); - unserialize_integer (m, &t[i].n_enum_strings, - sizeof (t[i].n_enum_strings)); - vec_resize (t[i].enum_strings_vector, t[i].n_enum_strings); - for (j = 0; j < t[i].n_enum_strings; j++) - unserialize_cstring (m, &t[i].enum_strings_vector[j]); - } -} - -static void -serialize_elog_track (serialize_main_t * m, va_list * va) -{ - elog_track_t *t = va_arg (*va, elog_track_t *); - int n = va_arg (*va, int); - int i; - for (i = 0; i < n; i++) - { - serialize_cstring (m, t[i].name); - } -} - -static void -unserialize_elog_track (serialize_main_t * m, va_list * va) -{ - elog_track_t *t = va_arg (*va, elog_track_t *); - int n = va_arg (*va, int); - int i; - for (i = 0; i < n; i++) - { - unserialize_cstring (m, &t[i].name); - } -} - -static void -serialize_elog_time_stamp (serialize_main_t * m, va_list * va) -{ - elog_time_stamp_t *st = va_arg (*va, elog_time_stamp_t *); - serialize (m, serialize_64, st->os_nsec); - serialize (m, serialize_64, st->cpu); -} - -static void -unserialize_elog_time_stamp (serialize_main_t * m, va_list * va) -{ - elog_time_stamp_t *st = va_arg (*va, elog_time_stamp_t *); - unserialize (m, unserialize_64, &st->os_nsec); - unserialize (m, unserialize_64, &st->cpu); -} - -static char *elog_serialize_magic = "elog v0"; - -void -serialize_elog_main (serialize_main_t * m, va_list * va) -{ - elog_main_t *em = va_arg (*va, elog_main_t *); - elog_event_t *e; - - serialize_magic (m, elog_serialize_magic, strlen (elog_serialize_magic)); - - serialize_integer (m, em->event_ring_size, sizeof (u32)); - - elog_time_now (&em->serialize_time); - serialize (m, serialize_elog_time_stamp, &em->serialize_time); - serialize (m, serialize_elog_time_stamp, &em->init_time); - - vec_serialize (m, em->event_types, serialize_elog_event_type); - vec_serialize (m, em->tracks, serialize_elog_track); - vec_serialize (m, em->string_table, serialize_vec_8); - - /* Free old events (cached) in case they have changed. */ - vec_free (em->events); - elog_get_events (em); - - serialize_integer (m, vec_len (em->events), sizeof (u32)); - - /* SMP logs can easily have local time paradoxes... */ - vec_sort_with_function (em->events, elog_cmp); - - vec_foreach (e, em->events) serialize (m, serialize_elog_event, em, e); -} - -void -unserialize_elog_main (serialize_main_t * m, va_list * va) -{ - elog_main_t *em = va_arg (*va, elog_main_t *); - uword i; - u32 rs; - - unserialize_check_magic (m, elog_serialize_magic, - strlen (elog_serialize_magic)); - - unserialize_integer (m, &rs, sizeof (u32)); - em->event_ring_size = rs; - elog_init (em, em->event_ring_size); - - unserialize (m, unserialize_elog_time_stamp, &em->serialize_time); - unserialize (m, unserialize_elog_time_stamp, &em->init_time); - em->nsec_per_cpu_clock = elog_nsec_per_clock (em); - - vec_unserialize (m, &em->event_types, unserialize_elog_event_type); - for (i = 0; i < vec_len (em->event_types); i++) - new_event_type (em, i); - - vec_unserialize (m, &em->tracks, unserialize_elog_track); - vec_unserialize (m, &em->string_table, unserialize_vec_8); - - { - u32 ne; - elog_event_t *e; - - unserialize_integer (m, &ne, sizeof (u32)); - vec_resize (em->events, ne); - vec_foreach (e, em->events) - unserialize (m, unserialize_elog_event, em, e); - } -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/elog.h b/vppinfra/vppinfra/elog.h deleted file mode 100644 index 9756fb83a8d..00000000000 --- a/vppinfra/vppinfra/elog.h +++ /dev/null @@ -1,460 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2005,2009 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -/* High speed event logging with much thanks to Dave Barach. */ - -#ifndef included_clib_elog_h -#define included_clib_elog_h - -#include <vppinfra/cache.h> -#include <vppinfra/error.h> /* for ASSERT */ -#include <vppinfra/serialize.h> -#include <vppinfra/time.h> /* for clib_cpu_time_now */ -#include <vppinfra/mhash.h> - -typedef struct -{ - union - { - /* Absolute time stamp in CPU clock cycles. */ - u64 time_cycles; - - /* Absolute time as floating point number in seconds. */ - f64 time; - }; - - /* Event type index. */ - u16 type; - - /* Track for this event. Tracks allow events to be sorted and - displayed by track. Think of 2 dimensional display with time and - track being the x and y axes. */ - u16 track; - - /* 20-bytes of data follows and pads to 32 bytes. */ - u8 data[20]; -} elog_event_t; - -typedef struct -{ - /* Type index plus one assigned to this type. - This is used to mark type as seen. */ - u32 type_index_plus_one; - - /* String table as a vector constructed when type is registered. */ - char **enum_strings_vector; - - /* Format string. (example: "my-event (%d,%d)"). */ - char *format; - - /* Specifies how arguments to format are parsed from event data. - String of characters '0' '1' or '2' '3' to specify log2 size of data - (e.g. for u8, u16, u32 or u64), - 's' means a null-terminated C string - 't' means argument is an index into enum string table for this type. - 'e' is a float, - 'f' is a double. */ - char *format_args; - - /* Function name generating event. */ - char *function; - - /* Number of elements in string enum table. */ - u32 n_enum_strings; - - /* String table for enum/number to string formatting. */ - char *enum_strings[]; -} elog_event_type_t; - -typedef struct -{ - /* Track name vector. */ - char *name; - - /* Set to one when track has been added to - main structure. */ - u32 track_index_plus_one; -} elog_track_t; - -typedef struct -{ - /* CPU cycle counter. */ - u64 cpu; - - /* OS timer in nano secs since epoch Jan 1 1970. */ - u64 os_nsec; -} elog_time_stamp_t; - -typedef struct -{ - /* Total number of events in buffer. */ - u32 n_total_events; - - /* When count reaches limit logging is disabled. This is - used for event triggers. */ - u32 n_total_events_disable_limit; - - /* Dummy event to use when logger is disabled. */ - elog_event_t dummy_event; - - /* Power of 2 number of elements in ring. */ - uword event_ring_size; - - /* Vector of events (circular buffer). Power of 2 size. - Used when events are being collected. */ - elog_event_t *event_ring; - - /* Vector of event types. */ - elog_event_type_t *event_types; - - /* Hash table mapping type format to type index. */ - uword *event_type_by_format; - - /* Events may refer to strings in string table. */ - char *string_table; - - /* Vector of tracks. */ - elog_track_t *tracks; - - /* Default track. */ - elog_track_t default_track; - - /* Place holder for CPU clock frequency. */ - clib_time_t cpu_timer; - - elog_time_stamp_t init_time, serialize_time; - - /* SMP lock, non-zero means locking required */ - uword *lock; - - /* Use serialize_time and init_time to give estimate for - cpu clock frequency. */ - f64 nsec_per_cpu_clock; - - /* Vector of events converted to generic form after collection. */ - elog_event_t *events; -} elog_main_t; - -always_inline uword -elog_n_events_in_buffer (elog_main_t * em) -{ - return clib_min (em->n_total_events, em->event_ring_size); -} - -always_inline uword -elog_buffer_capacity (elog_main_t * em) -{ - return em->event_ring_size; -} - -always_inline void -elog_reset_buffer (elog_main_t * em) -{ - em->n_total_events = 0; - em->n_total_events_disable_limit = ~0; -} - -always_inline void -elog_enable_disable (elog_main_t * em, int is_enabled) -{ - em->n_total_events = 0; - em->n_total_events_disable_limit = is_enabled ? ~0 : 0; -} - -/* Disable logging after specified number of ievents have been logged. - This is used as a "debug trigger" when a certain event has occurred. - Events will be logged both before and after the "event" but the - event will not be lost as long as N < RING_SIZE. */ -always_inline void -elog_disable_after_events (elog_main_t * em, uword n) -{ - em->n_total_events_disable_limit = em->n_total_events + n; -} - -/* Signal a trigger. We do this when we encounter an event that we want to save - context around (before and after). */ -always_inline void -elog_disable_trigger (elog_main_t * em) -{ - em->n_total_events_disable_limit = - em->n_total_events + vec_len (em->event_ring) / 2; -} - -/* External function to register types/tracks. */ -word elog_event_type_register (elog_main_t * em, elog_event_type_t * t); -word elog_track_register (elog_main_t * em, elog_track_t * t); - -always_inline uword -elog_is_enabled (elog_main_t * em) -{ - return em->n_total_events < em->n_total_events_disable_limit; -} - -/* Add an event to the log. Returns a pointer to the - data for caller to write into. */ -always_inline void * -elog_event_data_inline (elog_main_t * em, - elog_event_type_t * type, - elog_track_t * track, u64 cpu_time) -{ - elog_event_t *e; - uword ei; - word type_index, track_index; - - /* Return the user dummy memory to scribble data into. */ - if (PREDICT_FALSE (!elog_is_enabled (em))) - return em->dummy_event.data; - - type_index = (word) type->type_index_plus_one - 1; - track_index = (word) track->track_index_plus_one - 1; - if (PREDICT_FALSE ((type_index | track_index) < 0)) - { - if (type_index < 0) - type_index = elog_event_type_register (em, type); - if (track_index < 0) - track_index = elog_track_register (em, track); - } - - ASSERT (type_index < vec_len (em->event_types)); - ASSERT (track_index < vec_len (em->tracks)); - ASSERT (is_pow2 (vec_len (em->event_ring))); - - if (em->lock) - ei = clib_smp_atomic_add (&em->n_total_events, 1); - else - ei = em->n_total_events++; - - ei &= em->event_ring_size - 1; - e = vec_elt_at_index (em->event_ring, ei); - - e->time_cycles = cpu_time; - e->type = type_index; - e->track = track_index; - - /* Return user data for caller to fill in. */ - return e->data; -} - -/* External version of inline. */ -void *elog_event_data (elog_main_t * em, - elog_event_type_t * type, - elog_track_t * track, u64 cpu_time); - -/* Non-inline version. */ -always_inline void * -elog_event_data_not_inline (elog_main_t * em, - elog_event_type_t * type, - elog_track_t * track, u64 cpu_time) -{ - /* Return the user dummy memory to scribble data into. */ - if (PREDICT_FALSE (!elog_is_enabled (em))) - return em->dummy_event.data; - return elog_event_data (em, type, track, cpu_time); -} - -/* Most common forms: log a single 32 bit datum, w / w-out track */ -always_inline void -elog (elog_main_t * em, elog_event_type_t * type, u32 data) -{ - u32 *d = elog_event_data_not_inline (em, - type, - &em->default_track, - clib_cpu_time_now ()); - d[0] = data; -} - -/* Inline version of above. */ -always_inline void -elog_inline (elog_main_t * em, elog_event_type_t * type, u32 data) -{ - u32 *d = elog_event_data_inline (em, - type, - &em->default_track, - clib_cpu_time_now ()); - d[0] = data; -} - -always_inline void -elog_track (elog_main_t * em, elog_event_type_t * type, elog_track_t * track, - u32 data) -{ - u32 *d = elog_event_data_not_inline (em, - type, - track, - clib_cpu_time_now ()); - d[0] = data; -} - -always_inline void -elog_track_inline (elog_main_t * em, elog_event_type_t * type, - elog_track_t * track, u32 data) -{ - u32 *d = elog_event_data_inline (em, - type, - track, - clib_cpu_time_now ()); - d[0] = data; -} - -always_inline void * -elog_data (elog_main_t * em, elog_event_type_t * type, elog_track_t * track) -{ - return elog_event_data_not_inline (em, type, track, clib_cpu_time_now ()); -} - -always_inline void * -elog_data_inline (elog_main_t * em, elog_event_type_t * type, - elog_track_t * track) -{ - return elog_event_data_inline (em, type, track, clib_cpu_time_now ()); -} - -/* Macro shorthands for generating/declaring events. */ -#define __ELOG_TYPE_VAR(f) f -#define __ELOG_TRACK_VAR(f) f - -#define ELOG_TYPE_DECLARE(f) static elog_event_type_t __ELOG_TYPE_VAR(f) - -#define ELOG_TYPE_INIT_FORMAT_AND_FUNCTION(fmt,func) \ - { .format = fmt, .function = func, } - -#define ELOG_TYPE_INIT(fmt) \ - ELOG_TYPE_INIT_FORMAT_AND_FUNCTION(fmt,(char *) __FUNCTION__) - -#define ELOG_TYPE_DECLARE_HELPER(f,fmt,func) \ - static elog_event_type_t __ELOG_TYPE_VAR(f) = \ - ELOG_TYPE_INIT_FORMAT_AND_FUNCTION (fmt, func) - -#define ELOG_TYPE_DECLARE_FORMAT_AND_FUNCTION(f,fmt) \ - ELOG_TYPE_DECLARE_HELPER (f, fmt, (char *) __FUNCTION__) - -#define ELOG_TYPE_DECLARE_FORMAT(f,fmt) \ - ELOG_TYPE_DECLARE_HELPER (f, fmt, 0) - -/* Shorthands with and without __FUNCTION__. - D for decimal; X for hex. F for __FUNCTION__. */ -#define ELOG_TYPE(f,fmt) ELOG_TYPE_DECLARE_FORMAT_AND_FUNCTION(f,fmt) -#define ELOG_TYPE_D(f) ELOG_TYPE_DECLARE_FORMAT (f, #f " %d") -#define ELOG_TYPE_X(f) ELOG_TYPE_DECLARE_FORMAT (f, #f " 0x%x") -#define ELOG_TYPE_DF(f) ELOG_TYPE_DECLARE_FORMAT_AND_FUNCTION (f, #f " %d") -#define ELOG_TYPE_XF(f) ELOG_TYPE_DECLARE_FORMAT_AND_FUNCTION (f, #f " 0x%x") -#define ELOG_TYPE_FD(f) ELOG_TYPE_DECLARE_FORMAT_AND_FUNCTION (f, #f " %d") -#define ELOG_TYPE_FX(f) ELOG_TYPE_DECLARE_FORMAT_AND_FUNCTION (f, #f " 0x%x") - -#define ELOG_TRACK_DECLARE(f) static elog_track_t __ELOG_TRACK_VAR(f) -#define ELOG_TRACK(f) ELOG_TRACK_DECLARE(f) = { .name = #f, } - -/* Log 32 bits of data. */ -#define ELOG(em,f,data) elog ((em), &__ELOG_TYPE_VAR(f), data) -#define ELOG_INLINE(em,f,data) elog_inline ((em), &__ELOG_TYPE_VAR(f), data) - -/* Return data pointer to fill in. */ -#define ELOG_TRACK_DATA(em,f,track) \ - elog_data ((em), &__ELOG_TYPE_VAR(f), &__ELOG_TRACK_VAR(track)) -#define ELOG_TRACK_DATA_INLINE(em,f,track) \ - elog_data_inline ((em), &__ELOG_TYPE_VAR(f), &__ELOG_TRACK_VAR(track)) - -/* Shorthand with default track. */ -#define ELOG_DATA(em,f) elog_data ((em), &__ELOG_TYPE_VAR (f), &(em)->default_track) -#define ELOG_DATA_INLINE(em,f) elog_data_inline ((em), &__ELOG_TYPE_VAR (f), &(em)->default_track) - -u32 elog_string (elog_main_t * em, char *format, ...); -void elog_time_now (elog_time_stamp_t * et); - -/* Convert ievents to events and return them as a vector. - Sets em->events to resulting vector. */ -elog_event_t *elog_get_events (elog_main_t * em); - -/* Convert ievents to events and return them as a vector with no side effects. */ -elog_event_t *elog_peek_events (elog_main_t * em); - -/* Merge two logs, add supplied track tags. */ -void elog_merge (elog_main_t * dst, u8 * dst_tag, - elog_main_t * src, u8 * src_tag); - -/* 2 arguments elog_main_t and elog_event_t to format event or track name. */ -u8 *format_elog_event (u8 * s, va_list * va); -u8 *format_elog_track (u8 * s, va_list * va); - -void serialize_elog_main (serialize_main_t * m, va_list * va); -void unserialize_elog_main (serialize_main_t * m, va_list * va); - -void elog_init (elog_main_t * em, u32 n_events); -void elog_alloc (elog_main_t * em, u32 n_events); - -#ifdef CLIB_UNIX -always_inline clib_error_t * -elog_write_file (elog_main_t * em, char *unix_file) -{ - serialize_main_t m; - clib_error_t *error; - - error = serialize_open_unix_file (&m, unix_file); - if (error) - return error; - error = serialize (&m, serialize_elog_main, em); - if (!error) - serialize_close (&m); - return error; -} - -always_inline clib_error_t * -elog_read_file (elog_main_t * em, char *unix_file) -{ - serialize_main_t m; - clib_error_t *error; - - error = unserialize_open_unix_file (&m, unix_file); - if (error) - return error; - error = unserialize (&m, unserialize_elog_main, em); - if (!error) - unserialize_close (&m); - return error; -} - -#endif /* CLIB_UNIX */ - -#endif /* included_clib_elog_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/error.c b/vppinfra/vppinfra/error.c deleted file mode 100644 index 2722fb7be7e..00000000000 --- a/vppinfra/vppinfra/error.c +++ /dev/null @@ -1,292 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -/* Error reporting. */ -#include <stdarg.h> - -#include <vppinfra/clib.h> /* for HAVE_ERRNO */ - -#ifdef CLIB_LINUX_KERNEL -#include <linux/unistd.h> /* for write */ -#include <linux/kernel.h> /* for printk */ -#endif - -#ifdef CLIB_UNIX -#include <unistd.h> /* for write */ -#include <stdio.h> /* for printf */ -#define HAVE_ERRNO -#endif - -#ifdef CLIB_STANDALONE -#include <vppinfra/standalone_stdio.h> /* for printf */ -#endif - -#include <vppinfra/string.h> -#include <vppinfra/mem.h> -#include <vppinfra/vec.h> -#include <vppinfra/format.h> -#include <vppinfra/error.h> -#include <vppinfra/hash.h> -#include <vppinfra/os.h> /* for os_panic/os_exit/os_puts */ - -typedef struct -{ - clib_error_handler_func_t *func; - void *arg; -} clib_error_handler_t; - -static clib_error_handler_t *handlers = 0; - -void -clib_error_register_handler (clib_error_handler_func_t func, void *arg) -{ - clib_error_handler_t h = {.func = func,.arg = arg, }; - vec_add1 (handlers, h); -} - -static void -debugger (void) -{ - os_panic (); -} - -static void -error_exit (int code) -{ - os_exit (code); -} - -static u8 * -dispatch_message (u8 * msg) -{ - word i; - - if (!msg) - return msg; - - for (i = 0; i < vec_len (handlers); i++) - handlers[i].func (handlers[i].arg, msg, vec_len (msg)); - - /* If no message handler is specified provide a default one. */ - if (vec_len (handlers) == 0) - os_puts (msg, vec_len (msg), /* is_error */ 1); - - return msg; -} - -void -_clib_error (int how_to_die, - char *function_name, uword line_number, char *fmt, ...) -{ - u8 *msg = 0; - va_list va; - - if (function_name) - { - msg = format (msg, "%s:", function_name); - if (line_number > 0) - msg = format (msg, "%wd:", line_number); - msg = format (msg, " "); - } - - va_start (va, fmt); - msg = va_format (msg, fmt, &va); - va_end (va); - -#ifdef HAVE_ERRNO - if (how_to_die & CLIB_ERROR_ERRNO_VALID) - msg = format (msg, ": %s (errno %d)", strerror (errno), errno); -#endif - - if (vec_end (msg)[-1] != '\n') - vec_add1 (msg, '\n'); - - msg = dispatch_message (msg); - - vec_free (msg); - - if (how_to_die & CLIB_ERROR_ABORT) - debugger (); - if (how_to_die & CLIB_ERROR_FATAL) - error_exit (1); -} - -clib_error_t * -_clib_error_return (clib_error_t * errors, - any code, uword flags, char *where, char *fmt, ...) -{ - clib_error_t *e; - va_list va; - -#ifdef HAVE_ERRNO - /* Save errno since it may be re-set before we'll need it. */ - word errno_save = errno; -#endif - - va_start (va, fmt); - vec_add2 (errors, e, 1); - if (fmt) - e->what = va_format (0, fmt, &va); - -#ifdef HAVE_ERRNO - if (flags & CLIB_ERROR_ERRNO_VALID) - { - if (e->what) - e->what = format (e->what, ": "); - e->what = format (e->what, "%s", strerror (errno_save)); - } -#endif - - e->where = (u8 *) where; - e->code = code; - e->flags = flags; - va_end (va); - return errors; -} - -void * -clib_error_free_vector (clib_error_t * errors) -{ - clib_error_t *e; - vec_foreach (e, errors) vec_free (e->what); - vec_free (errors); - return 0; -} - -u8 * -format_clib_error (u8 * s, va_list * va) -{ - clib_error_t *errors = va_arg (*va, clib_error_t *); - clib_error_t *e; - - vec_foreach (e, errors) - { - if (!e->what) - continue; - - if (e->where) - { - u8 *where = 0; - - if (e > errors) - where = format (where, "from "); - where = format (where, "%s", e->where); - - s = format (s, "%v: ", where); - vec_free (where); - } - - s = format (s, "%v\n", e->what); - } - - return s; -} - -clib_error_t * -_clib_error_report (clib_error_t * errors) -{ - if (errors) - { - u8 *msg = format (0, "%U", format_clib_error, errors); - - msg = dispatch_message (msg); - vec_free (msg); - - if (errors->flags & CLIB_ERROR_ABORT) - debugger (); - if (errors->flags & CLIB_ERROR_FATAL) - error_exit (1); - - clib_error_free (errors); - } - return 0; -} - -#ifdef TEST - -static error_t * -foo1 (int x) -{ - return error_return (0, "x is odd %d", x); -} - -static error_t * -foo2 (int x) -{ - return error_return (0, "x is even %d", x); -} - -static error_t * -foo (int x) -{ - error_t *e; - if (x & 1) - e = foo1 (x); - else - e = foo2 (x); - if (e) - return error_return (e, 0); -} - -static void -error_handler (void *arg, char *msg, int msg_len) -{ - write (2, msg, msg_len); -} - -int -main (int argc, char *argv[]) -{ - error_t *e; - - register_error_handler (error_handler, 0); - - e = foo (getpid ()); - if (e) - error_report (e); - return 0; -} - -#endif - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/error.h b/vppinfra/vppinfra/error.h deleted file mode 100644 index 63d73af36c7..00000000000 --- a/vppinfra/vppinfra/error.h +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_error_h -#define included_error_h - -#include <vppinfra/clib.h> /* for CLIB_LINUX_KERNEL */ -#include <vppinfra/error_bootstrap.h> - -#ifdef CLIB_UNIX -#include <errno.h> -#endif - -#ifdef CLIB_LINUX_KERNEL -#include <linux/errno.h> -#endif - -#include <stdarg.h> -#include <vppinfra/vec.h> - -/* Callback functions for error reporting. */ -typedef void clib_error_handler_func_t (void *arg, u8 * msg, int msg_len); -void clib_error_register_handler (clib_error_handler_func_t func, void *arg); - -#define clib_warning(format,args...) \ - _clib_error (CLIB_ERROR_WARNING, clib_error_function, __LINE__, format, ## args) - -#define clib_error(format,args...) \ - _clib_error (CLIB_ERROR_FATAL, clib_error_function, __LINE__, format, ## args) - -#define clib_unix_error(format,args...) \ - _clib_error (CLIB_ERROR_FATAL | CLIB_ERROR_ERRNO_VALID, clib_error_function, __LINE__, format, ## args) - -#define clib_unix_warning(format,args...) \ - _clib_error (CLIB_ERROR_WARNING | CLIB_ERROR_ERRNO_VALID, clib_error_function, __LINE__, format, ## args) - -/* For programming errors and assert. */ -#define clib_panic(format,args...) \ - _clib_error (CLIB_ERROR_ABORT, (char *) clib_error_function, __LINE__, format, ## args) - -typedef struct -{ - /* Error message. */ - u8 *what; - - /* Where error occurred (e.g. __FUNCTION__ __LINE__) */ - const u8 *where; - - uword flags; - - /* Error code (e.g. errno for Unix errors). */ - any code; -} clib_error_t; - -#define clib_error_get_code(err) ((err) ? (err)->code : 0) -#define clib_error_set_code(err, c) \ -do { \ - if (err) \ - (err)->code = (c); \ -} while (0) - -extern void *clib_error_free_vector (clib_error_t * errors); - -#define clib_error_free(e) e = clib_error_free_vector(e) - -extern clib_error_t *_clib_error_return (clib_error_t * errors, - any code, - uword flags, - char *where, char *fmt, ...); - -#define clib_error_return_code(e,code,flags,args...) \ - _clib_error_return((e),(code),(flags),(char *)clib_error_function,args) - -#define clib_error_create(args...) \ - clib_error_return_code(0,0,0,args) - -#define clib_error_return(e,args...) \ - clib_error_return_code(e,0,0,args) - -#define clib_error_return_unix(e,args...) \ - clib_error_return_code(e,errno,CLIB_ERROR_ERRNO_VALID,args) - -#define clib_error_return_fatal(e,args...) \ - clib_error_return_code(e,0,CLIB_ERROR_FATAL,args) - -#define clib_error_return_unix_fatal(e,args...) \ - clib_error_return_code(e,errno,CLIB_ERROR_ERRNO_VALID|CLIB_ERROR_FATAL,args) - -extern clib_error_t *_clib_error_report (clib_error_t * errors); - -#define clib_error_report(e) do { (e) = _clib_error_report (e); } while (0) - -u8 *format_clib_error (u8 * s, va_list * va); - -always_inline word -unix_error_is_fatal (word error) -{ -#ifdef CLIB_UNIX - switch (error) - { - case EWOULDBLOCK: - case EINTR: - return 0; - } -#endif - return 1; -} - -#define IF_ERROR_IS_FATAL_RETURN_ELSE_FREE(e) \ -do { \ - if (e) \ - { \ - if (unix_error_is_fatal (clib_error_get_code (e))) \ - return (e); \ - else \ - clib_error_free (e); \ - } \ -} while (0) - -#define ERROR_RETURN_IF(x) \ -do { \ - clib_error_t * _error_return_if = (x); \ - if (_error_return_if) \ - return clib_error_return (_error_return_if, 0); \ -} while (0) - -#define ERROR_ASSERT(truth) \ -({ \ - clib_error_t * _error_assert = 0; \ - if (CLIB_DEBUG > 0 && ! (truth)) \ - { \ - _error_assert = clib_error_return_fatal \ - (0, "%s:%d (%s) assertion `%s' fails", \ - __FILE__, \ - (uword) __LINE__, \ - clib_error_function, \ - # truth); \ - } \ - _error_assert; \ -}) - -/* Assert to remain even if CLIB_DEBUG is set to 0. */ -#define CLIB_ERROR_ASSERT(truth) \ -({ \ - clib_error_t * _error_assert = 0; \ - if (! (truth)) \ - { \ - _error_assert = \ - clib_error_return_fatal \ - (0, "%s:%d (%s) assertion `%s' fails", \ - __FILE__, \ - (uword) __LINE__, \ - clib_error_function, \ - # truth); \ - } \ - _error_assert; \ -}) - -#endif /* included_error_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/error_bootstrap.h b/vppinfra/vppinfra/error_bootstrap.h deleted file mode 100644 index 3416c2f9033..00000000000 --- a/vppinfra/vppinfra/error_bootstrap.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_error_bootstrap_h -#define included_error_bootstrap_h - -/* Bootstrap include so that #include <vppinfra/mem.h> can include e.g. - <vppinfra/mheap.h> which depends on <vppinfra/vec.h>. */ - -#include <vppinfra/clib.h> /* for uword */ - -enum -{ - CLIB_ERROR_FATAL = 1 << 0, - CLIB_ERROR_ABORT = 1 << 1, - CLIB_ERROR_WARNING = 1 << 2, - CLIB_ERROR_ERRNO_VALID = 1 << 16, - CLIB_ERROR_NO_RATE_LIMIT = 1 << 17, -}; - -/* Current function name. Need (char *) cast to silence gcc4 pointer signedness warning. */ -#define clib_error_function ((char *) __FUNCTION__) - -#ifndef CLIB_ASSERT_ENABLE -#define CLIB_ASSERT_ENABLE (CLIB_DEBUG > 0) -#endif - -/* Low level error reporting function. - Code specifies whether to call exit, abort or nothing at - all (for non-fatal warnings). */ -extern void _clib_error (int code, - char *function_name, - uword line_number, char *format, ...); - -#define ASSERT(truth) \ -do { \ - if (CLIB_ASSERT_ENABLE && ! (truth)) \ - { \ - _clib_error (CLIB_ERROR_ABORT, 0, 0, \ - "%s:%d (%s) assertion `%s' fails", \ - __FILE__, \ - (uword) __LINE__, \ - clib_error_function, \ - # truth); \ - } \ -} while (0) - -#if defined(__clang__) -#define STATIC_ASSERT(truth,...) -#else -#define STATIC_ASSERT(truth,...) _Static_assert(truth, __VA_ARGS__) -#endif - -#define STATIC_ASSERT_SIZEOF(d, s) \ - STATIC_ASSERT (sizeof (d) == s, "Size of " #d " must be " # s " bytes") - -/* Assert without allocating memory. */ -#define ASSERT_AND_PANIC(truth) \ -do { \ - if (CLIB_ASSERT_ENABLE && ! (truth)) \ - os_panic (); \ -} while (0) - -#endif /* included_error_bootstrap_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/fheap.c b/vppinfra/vppinfra/fheap.c deleted file mode 100644 index 1369245615a..00000000000 --- a/vppinfra/vppinfra/fheap.c +++ /dev/null @@ -1,473 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include <vppinfra/fheap.h> - -/* Fibonacci heaps. */ -always_inline fheap_node_t * -fheap_get_node (fheap_t * f, u32 i) -{ - return i != ~0 ? vec_elt_at_index (f->nodes, i) : 0; -} - -always_inline fheap_node_t * -fheap_get_root (fheap_t * f) -{ - return fheap_get_node (f, f->min_root); -} - -static void -fheap_validate (fheap_t * f) -{ - fheap_node_t *n, *m; - uword ni, si; - - if (!CLIB_DEBUG || !f->enable_validate) - return; - - vec_foreach_index (ni, f->nodes) - { - n = vec_elt_at_index (f->nodes, ni); - - if (!n->is_valid) - continue; - - /* Min root must have minimal key. */ - m = vec_elt_at_index (f->nodes, f->min_root); - ASSERT (n->key >= m->key); - - /* Min root must have no parent. */ - if (ni == f->min_root) - ASSERT (n->parent == ~0); - - /* Check sibling linkages. */ - if (n->next_sibling == ~0) - ASSERT (n->prev_sibling == ~0); - else if (n->prev_sibling == ~0) - ASSERT (n->next_sibling == ~0); - else - { - fheap_node_t *prev, *next; - u32 si = n->next_sibling, si_start = si; - do - { - m = vec_elt_at_index (f->nodes, si); - prev = vec_elt_at_index (f->nodes, m->prev_sibling); - next = vec_elt_at_index (f->nodes, m->next_sibling); - ASSERT (prev->next_sibling == si); - ASSERT (next->prev_sibling == si); - si = m->next_sibling; - } - while (si != si_start); - } - - /* Loop through all siblings. */ - { - u32 n_siblings = 0; - - foreach_fheap_node_sibling (f, si, n->next_sibling, ( - { - m = - vec_elt_at_index - (f->nodes, si); - /* All siblings must have same parent. */ - ASSERT (m->parent - == - n-> - parent); - n_siblings += 1;} - )); - - /* Either parent is non-empty or there are siblings present. */ - if (n->parent == ~0 && ni != f->min_root) - ASSERT (n_siblings > 0); - } - - /* Loop through all children. */ - { - u32 found_first_child = n->first_child == ~0; - u32 n_children = 0; - - foreach_fheap_node_sibling (f, si, n->first_child, ( - { - m = - vec_elt_at_index - (f->nodes, si); - /* Children must have larger keys than their parent. */ - ASSERT (m->key >= - n->key); - if - (!found_first_child) - found_first_child = - si == - n->first_child; - n_children += 1;} - )); - - /* Check that first child is present on list. */ - ASSERT (found_first_child); - - /* Make sure rank is correct. */ - ASSERT (n->rank == n_children); - } - } - - /* Increment serial number for each successful validate. - Failure can be used as condition for gdb breakpoints. */ - f->validate_serial++; -} - -always_inline void -fheap_node_add_sibling (fheap_t * f, u32 ni, u32 ni_to_add) -{ - fheap_node_t *n = vec_elt_at_index (f->nodes, ni); - fheap_node_t *n_to_add = vec_elt_at_index (f->nodes, ni_to_add); - fheap_node_t *n_next = fheap_get_node (f, n->next_sibling); - fheap_node_t *parent; - - /* Empty list? */ - if (n->next_sibling == ~0) - { - ASSERT (n->prev_sibling == ~0); - n->next_sibling = n->prev_sibling = ni_to_add; - n_to_add->next_sibling = n_to_add->prev_sibling = ni; - } - else - { - /* Add node after existing node. */ - n_to_add->prev_sibling = ni; - n_to_add->next_sibling = n->next_sibling; - - n->next_sibling = ni_to_add; - n_next->prev_sibling = ni_to_add; - } - - n_to_add->parent = n->parent; - parent = fheap_get_node (f, n->parent); - if (parent) - parent->rank += 1; -} - -void -fheap_add (fheap_t * f, u32 ni, u32 key) -{ - fheap_node_t *r, *n; - u32 ri; - - n = vec_elt_at_index (f->nodes, ni); - - memset (n, 0, sizeof (n[0])); - n->parent = n->first_child = n->next_sibling = n->prev_sibling = ~0; - n->key = key; - - r = fheap_get_root (f); - ri = f->min_root; - if (!r) - { - /* No root? Add node as new root. */ - f->min_root = ni; - } - else - { - /* Add node as sibling of current root. */ - fheap_node_add_sibling (f, ri, ni); - - /* New node may become new root. */ - if (r->key > n->key) - f->min_root = ni; - } - - fheap_validate (f); -} - -always_inline u32 -fheap_node_remove_internal (fheap_t * f, u32 ni, u32 invalidate) -{ - fheap_node_t *n = vec_elt_at_index (f->nodes, ni); - u32 prev_ni = n->prev_sibling; - u32 next_ni = n->next_sibling; - u32 list_has_single_element = prev_ni == ni; - fheap_node_t *prev = fheap_get_node (f, prev_ni); - fheap_node_t *next = fheap_get_node (f, next_ni); - fheap_node_t *p = fheap_get_node (f, n->parent); - - if (p) - { - ASSERT (p->rank > 0); - p->rank -= 1; - p->first_child = list_has_single_element ? ~0 : next_ni; - } - - if (prev) - { - ASSERT (prev->next_sibling == ni); - prev->next_sibling = next_ni; - } - if (next) - { - ASSERT (next->prev_sibling == ni); - next->prev_sibling = prev_ni; - } - - n->prev_sibling = n->next_sibling = ni; - n->parent = ~0; - n->is_valid = invalidate == 0; - - return list_has_single_element ? ~0 : next_ni; -} - -always_inline u32 -fheap_node_remove (fheap_t * f, u32 ni) -{ - return fheap_node_remove_internal (f, ni, /* invalidate */ 0); -} - -always_inline u32 -fheap_node_remove_and_invalidate (fheap_t * f, u32 ni) -{ - return fheap_node_remove_internal (f, ni, /* invalidate */ 1); -} - -static void -fheap_link_root (fheap_t * f, u32 ni) -{ - fheap_node_t *n = vec_elt_at_index (f->nodes, ni); - fheap_node_t *r, *lo, *hi; - u32 ri, lo_i, hi_i, k; - - while (1) - { - k = n->rank; - vec_validate_init_empty (f->root_list_by_rank, k, ~0); - ri = f->root_list_by_rank[k]; - r = fheap_get_node (f, ri); - if (!r) - { - f->root_list_by_rank[k] = ni; - return; - } - - f->root_list_by_rank[k] = ~0; - - /* Sort n/r into lo/hi by their keys. */ - lo = r, lo_i = ri; - hi = n, hi_i = ni; - if (hi->key < lo->key) - { - u32 ti; - fheap_node_t *tn; - ti = lo_i, tn = lo; - lo = hi, lo_i = hi_i; - hi = tn, hi_i = ti; - } - - /* Remove larger key. */ - fheap_node_remove (f, hi_i); - - /* Add larger key as child of smaller one. */ - if (lo->first_child == ~0) - { - hi->parent = lo_i; - lo->first_child = hi_i; - lo->rank = 1; - } - else - fheap_node_add_sibling (f, lo->first_child, hi_i); - - /* Following Fredman & Trajan: "When making a root node X a child of another node in a linking step, - we unmark X". */ - hi->is_marked = 0; - - ni = lo_i; - n = lo; - } -} - -u32 -fheap_del_min (fheap_t * f, u32 * min_key) -{ - fheap_node_t *r = fheap_get_root (f); - u32 to_delete_min_ri = f->min_root; - u32 ri, ni; - - /* Empty heap? */ - if (!r) - return ~0; - - /* Root's children become siblings. Call this step a; see below. */ - if (r->first_child != ~0) - { - u32 ci, cni, rni; - fheap_node_t *c, *cn, *rn; - - /* Splice child & root circular lists together. */ - ci = r->first_child; - c = vec_elt_at_index (f->nodes, ci); - - cni = c->next_sibling; - rni = r->next_sibling; - cn = vec_elt_at_index (f->nodes, cni); - rn = vec_elt_at_index (f->nodes, rni); - - r->next_sibling = cni; - c->next_sibling = rni; - cn->prev_sibling = to_delete_min_ri; - rn->prev_sibling = ci; - } - - /* Remove min root. */ - ri = fheap_node_remove_and_invalidate (f, to_delete_min_ri); - - /* Find new min root from among siblings including the ones we've just added. */ - f->min_root = ~0; - if (ri != ~0) - { - u32 ri_last, ri_next, i, min_ds; - - r = fheap_get_node (f, ri); - ri_last = r->prev_sibling; - while (1) - { - /* Step a above can put children (with r->parent != ~0) on root list. */ - r->parent = ~0; - - ri_next = r->next_sibling; - fheap_link_root (f, ri); - if (ri == ri_last) - break; - ri = ri_next; - r = fheap_get_node (f, ri); - } - - min_ds = ~0; - vec_foreach_index (i, f->root_list_by_rank) - { - ni = f->root_list_by_rank[i]; - if (ni == ~0) - continue; - f->root_list_by_rank[i] = ~0; - r = fheap_get_node (f, ni); - if (r->key < min_ds) - { - f->min_root = ni; - min_ds = r->key; - ASSERT (r->parent == ~0); - } - } - } - - /* Return deleted min root. */ - r = vec_elt_at_index (f->nodes, to_delete_min_ri); - if (min_key) - *min_key = r->key; - - fheap_validate (f); - - return to_delete_min_ri; -} - -static void -fheap_mark_parent (fheap_t * f, u32 pi) -{ - fheap_node_t *p = vec_elt_at_index (f->nodes, pi); - - /* Parent is a root: do nothing. */ - if (p->parent == ~0) - return; - - /* If not marked, mark it. */ - if (!p->is_marked) - { - p->is_marked = 1; - return; - } - - /* Its a previously marked, non-root parent. - Cut edge to its parent and add to root list. */ - fheap_node_remove (f, pi); - fheap_node_add_sibling (f, f->min_root, pi); - - /* Unmark it since its now a root node. */ - p->is_marked = 0; - - /* "Cascading cuts": check parent. */ - if (p->parent != ~0) - fheap_mark_parent (f, p->parent); -} - -/* Set key to new smaller value. */ -void -fheap_decrease_key (fheap_t * f, u32 ni, u32 new_key) -{ - fheap_node_t *n = vec_elt_at_index (f->nodes, ni); - fheap_node_t *r = fheap_get_root (f); - - n->key = new_key; - - if (n->parent != ~0) - { - fheap_mark_parent (f, n->parent); - - /* Remove node and add to root list. */ - fheap_node_remove (f, ni); - fheap_node_add_sibling (f, f->min_root, ni); - } - - if (n->key < r->key) - f->min_root = ni; - - fheap_validate (f); -} - -void -fheap_del (fheap_t * f, u32 ni) -{ - fheap_node_t *n; - - n = vec_elt_at_index (f->nodes, ni); - - if (n->parent == ~0) - { - ASSERT (ni == f->min_root); - fheap_del_min (f, 0); - } - else - { - u32 ci; - - fheap_mark_parent (f, n->parent); - - /* Add children to root list. */ - foreach_fheap_node_sibling (f, ci, n->first_child, ( - { - fheap_node_remove - (f, ci); - fheap_node_add_sibling - (f, f->min_root, - ci);} - )); - - fheap_node_remove_and_invalidate (f, ni); - } - - fheap_validate (f); -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/fheap.h b/vppinfra/vppinfra/fheap.h deleted file mode 100644 index 6d4965f1bea..00000000000 --- a/vppinfra/vppinfra/fheap.h +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef included_clib_fheap_h -#define included_clib_fheap_h - -/* Fibonacci Heaps Fredman, M. L.; Tarjan (1987). - "Fibonacci heaps and their uses in improved network optimization algorithms" */ - -#include <vppinfra/vec.h> - -typedef struct -{ - /* Node index of parent. */ - u32 parent; - - /* Node index of first child. */ - u32 first_child; - - /* Next and previous nodes in doubly linked list of siblings. */ - u32 next_sibling, prev_sibling; - - /* Key (distance) for this node. Parent always has key - <= than keys of children. */ - u32 key; - - /* Number of children (as opposed to descendents). */ - u32 rank; - - u32 is_marked; - - /* Set to one when node is inserted; zero when deleted. */ - u32 is_valid; -} fheap_node_t; - -#define foreach_fheap_node_sibling(f,ni,first_ni,body) \ -do { \ - u32 __fheap_foreach_first_ni = (first_ni); \ - u32 __fheap_foreach_ni = __fheap_foreach_first_ni; \ - u32 __fheap_foreach_next_ni; \ - fheap_node_t * __fheap_foreach_n; \ - if (__fheap_foreach_ni != ~0) \ - while (1) \ - { \ - __fheap_foreach_n = fheap_get_node ((f), __fheap_foreach_ni); \ - __fheap_foreach_next_ni = __fheap_foreach_n -> next_sibling; \ - (ni) = __fheap_foreach_ni; \ - \ - body; \ - \ - /* End of circular list? */ \ - if (__fheap_foreach_next_ni == __fheap_foreach_first_ni) \ - break; \ - \ - __fheap_foreach_ni = __fheap_foreach_next_ni; \ - \ - } \ -} while (0) - -typedef struct -{ - u32 min_root; - - /* Vector of nodes. */ - fheap_node_t *nodes; - - u32 *root_list_by_rank; - - u32 enable_validate; - - u32 validate_serial; -} fheap_t; - -/* Initialize empty heap. */ -always_inline void -fheap_init (fheap_t * f, u32 n_nodes) -{ - fheap_node_t *save_nodes = f->nodes; - u32 *save_root_list = f->root_list_by_rank; - - memset (f, 0, sizeof (f[0])); - - f->nodes = save_nodes; - f->root_list_by_rank = save_root_list; - - vec_validate (f->nodes, n_nodes - 1); - vec_reset_length (f->root_list_by_rank); - - f->min_root = ~0; -} - -always_inline void -fheap_free (fheap_t * f) -{ - vec_free (f->nodes); - vec_free (f->root_list_by_rank); -} - -always_inline u32 -fheap_find_min (fheap_t * f) -{ - return f->min_root; -} - -always_inline u32 -fheap_is_empty (fheap_t * f) -{ - return f->min_root == ~0; -} - -/* Add/delete nodes. */ -void fheap_add (fheap_t * f, u32 ni, u32 key); -void fheap_del (fheap_t * f, u32 ni); - -/* Delete and return minimum. */ -u32 fheap_del_min (fheap_t * f, u32 * min_key); - -/* Change key value. */ -void fheap_decrease_key (fheap_t * f, u32 ni, u32 new_key); - -#endif /* included_clib_fheap_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/fifo.c b/vppinfra/vppinfra/fifo.c deleted file mode 100644 index 5b4c76d1084..00000000000 --- a/vppinfra/vppinfra/fifo.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include <vppinfra/cache.h> -#include <vppinfra/fifo.h> -#include <vppinfra/error.h> -#include <vppinfra/string.h> - -/* - General first in/first out queues. - FIFOs can have arbitrary size and type. - Let T be any type (i.e. char, int, struct foo, etc.). - - A null fifo is initialized: - - T * f = 0; - - For example, typedef struct { int a, b; } T; - - Elements can be added in 3 ways. - - #1 1 element is added: - T x; - x.a = 10; x.b = 20; - fifo_add1 (f, x); - - #2 n elements are added - T buf[10]; - initialize buf[0] .. buf[9]; - fifo_add (f, buf, 10); - - #3 1 element is added, pointer is returned - T * x; - fifo_add2 (f, x); - x->a = 10; - x->b = 20; - - Elements are removed 1 at a time: - T x; - fifo_sub1 (f, x); - - fifo_free (f) frees fifo. -*/ - -void * -_clib_fifo_resize (void *v_old, uword n_new_elts, uword elt_bytes) -{ - void *v_new, *end, *head; - uword n_old_elts, header_bytes; - uword n_copy_bytes, n_zero_bytes; - clib_fifo_header_t *f_new, *f_old; - - n_old_elts = clib_fifo_elts (v_old); - n_new_elts += n_old_elts; - if (n_new_elts < 32) - n_new_elts = 32; - else - n_new_elts = max_pow2 (n_new_elts); - - header_bytes = vec_header_bytes (sizeof (clib_fifo_header_t)); - - v_new = clib_mem_alloc_no_fail (n_new_elts * elt_bytes + header_bytes); - v_new += header_bytes; - - f_new = clib_fifo_header (v_new); - f_new->head_index = 0; - f_new->tail_index = n_old_elts; - _vec_len (v_new) = n_new_elts; - - /* Copy old -> new. */ - n_copy_bytes = n_old_elts * elt_bytes; - if (n_copy_bytes > 0) - { - f_old = clib_fifo_header (v_old); - end = v_old + _vec_len (v_old) * elt_bytes; - head = v_old + f_old->head_index * elt_bytes; - - if (head + n_copy_bytes >= end) - { - uword n = end - head; - clib_memcpy (v_new, head, n); - clib_memcpy (v_new + n, v_old, n_copy_bytes - n); - } - else - clib_memcpy (v_new, head, n_copy_bytes); - } - - /* Zero empty space. */ - n_zero_bytes = (n_new_elts - n_old_elts) * elt_bytes; - memset (v_new + n_copy_bytes, 0, n_zero_bytes); - - clib_fifo_free (v_old); - - return v_new; -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/fifo.h b/vppinfra/vppinfra/fifo.h deleted file mode 100644 index b0b35e25af7..00000000000 --- a/vppinfra/vppinfra/fifo.h +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2005 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_fifo_h -#define included_fifo_h - -#include <vppinfra/cache.h> -#include <vppinfra/error.h> /* for ASSERT */ -#include <vppinfra/vec.h> - -typedef struct -{ - /* First index of valid data in fifo. */ - u32 head_index; - - /* One beyond last index in fifo. */ - u32 tail_index; -} clib_fifo_header_t; - -always_inline clib_fifo_header_t * -clib_fifo_header (void *f) -{ - return vec_header (f, sizeof (clib_fifo_header_t)); -} - -/* Aliases. */ -#define clib_fifo_len(v) vec_len(v) -#define _clib_fifo_len(v) _vec_len(v) -#define clib_fifo_end(v) vec_end(v) - -always_inline uword -clib_fifo_elts (void *v) -{ - word l, r; - clib_fifo_header_t *f = clib_fifo_header (v); - - if (!v) - return 0; - - l = _clib_fifo_len (v); - r = (word) f->tail_index - (word) f->head_index; - r = r < 0 ? r + l : r; - ASSERT (r >= 0 && r <= l); - return r; -} - -always_inline uword -clib_fifo_free_elts (void *v) -{ - return clib_fifo_len (v) - clib_fifo_elts (v); -} - -always_inline void -clib_fifo_reset (void *v) -{ - clib_fifo_header_t *f = clib_fifo_header (v); - if (v) - { - f->head_index = f->tail_index = 0; - _vec_len (v) = 0; - } -} - -/* External resize function. */ -void *_clib_fifo_resize (void *v, uword n_elts, uword elt_bytes); - -#define clib_fifo_resize(f,n_elts) \ - f = _clib_fifo_resize ((f), (n_elts), sizeof ((f)[0])) - -always_inline void * -_clib_fifo_validate (void *v, uword n_elts, uword elt_bytes) -{ - if (clib_fifo_free_elts (v) < n_elts) - v = _clib_fifo_resize (v, n_elts, elt_bytes); - return v; -} - -#define clib_fifo_validate(f,n_elts) \ - f = _clib_fifo_validate ((f), (n_elts), sizeof (f[0])) - -/* Advance tail pointer by N_ELTS which can be either positive or negative. */ -always_inline void * -_clib_fifo_advance_tail (void *v, word n_elts, uword elt_bytes, - uword * tail_return) -{ - word i, l, n_free; - clib_fifo_header_t *f; - - n_free = clib_fifo_free_elts (v); - if (n_free < n_elts) - { - v = _clib_fifo_resize (v, n_elts, elt_bytes); - n_free = clib_fifo_free_elts (v); - } - - ASSERT (n_free >= n_elts); - n_free -= n_elts; - - f = clib_fifo_header (v); - l = _clib_fifo_len (v); - i = f->tail_index; - - if (n_free == 0) - { - /* Mark fifo full. */ - f->tail_index = f->head_index + l; - } - else - { - word n = f->tail_index + n_elts; - if (n >= l) - n -= l; - else if (n < 0) - n += l; - ASSERT (n >= 0 && n < l); - f->tail_index = n; - } - - ASSERT (clib_fifo_free_elts (v) == n_free); - - if (tail_return) - *tail_return = n_elts > 0 ? i : f->tail_index; - - return v; -} - -#define clib_fifo_advance_tail(f,n_elts) \ -({ \ - uword _i; \ - (f) = _clib_fifo_advance_tail ((f), (n_elts), sizeof ((f)[0]), &_i); \ - (f) + _i; \ -}) - -always_inline uword -clib_fifo_advance_head (void *v, uword n_elts) -{ - clib_fifo_header_t *f; - uword l, i, n; - - ASSERT (clib_fifo_elts (v) >= n_elts); - f = clib_fifo_header (v); - l = _clib_fifo_len (v); - - /* If fifo was full, restore tail pointer. */ - if (f->tail_index == f->head_index + l) - f->tail_index = f->head_index; - - n = i = f->head_index; - n += n_elts; - n = n >= l ? n - l : n; - ASSERT (n < l); - f->head_index = n; - - return i; -} - -/* Add given element to fifo. */ -#define clib_fifo_add1(f,e) \ -do { \ - uword _i; \ - (f) = _clib_fifo_advance_tail ((f), 1, sizeof ((f)[0]), &_i); \ - (f)[_i] = (e); \ -} while (0) - -/* Add element to fifo; return pointer to new element. */ -#define clib_fifo_add2(f,p) \ -do { \ - uword _i; \ - (f) = _clib_fifo_advance_tail ((f), 1, sizeof ((f)[0]), &_i); \ - (p) = (f) + _i; \ -} while (0) - -/* Add several elements to fifo. */ -#define clib_fifo_add(f,e,n) \ -do { \ - uword _i, _l; word _n0, _n1; \ - \ - _n0 = (n); \ - (f) = _clib_fifo_advance_tail ((f), _n0, sizeof ((f)[0]), &_i); \ - _l = clib_fifo_len (f); \ - _n1 = _i + _n0 - _l; \ - _n1 = _n1 < 0 ? 0 : _n1; \ - _n0 -= _n1; \ - clib_memcpy ((f) + _i, (e), _n0 * sizeof ((f)[0])); \ - if (_n1) \ - clib_memcpy ((f) + 0, (e) + _n0, _n1 * sizeof ((f)[0])); \ -} while (0) - -/* Subtract element from fifo. */ -#define clib_fifo_sub1(f,e) \ -do { \ - uword _i; \ - ASSERT (clib_fifo_elts (f) >= 1); \ - _i = clib_fifo_advance_head ((f), 1); \ - (e) = (f)[_i]; \ -} while (0) - -#define clib_fifo_sub2(f,p) \ -do { \ - uword _i; \ - ASSERT (clib_fifo_elts (f) >= 1); \ - _i = clib_fifo_advance_head ((f), 1); \ - (p) = (f) + _i; \ -} while (0) - -always_inline uword -clib_fifo_head_index (void *v) -{ - clib_fifo_header_t *f = clib_fifo_header (v); - return v ? f->head_index : 0; -} - -always_inline uword -clib_fifo_tail_index (void *v) -{ - clib_fifo_header_t *f = clib_fifo_header (v); - return v ? f->tail_index : 0; -} - -#define clib_fifo_head(v) ((v) + clib_fifo_head_index (v)) -#define clib_fifo_tail(v) ((v) + clib_fifo_tail_index (v)) - -#define clib_fifo_free(f) vec_free_h((f),sizeof(clib_fifo_header_t)) - -always_inline uword -clib_fifo_elt_index (void *v, uword i) -{ - clib_fifo_header_t *f = clib_fifo_header (v); - uword result = 0; - - ASSERT (i < clib_fifo_elts (v)); - - if (v) - { - result = f->head_index + i; - if (result >= _vec_len (v)) - result -= _vec_len (v); - } - - return result; -} - -#define clib_fifo_elt_at_index(v,i) ((v) + clib_fifo_elt_index (v, (i))) - -#define clib_fifo_foreach(v,f,body) \ -do { \ - uword _i, _l, _n; \ - \ - _i = clib_fifo_head_index (f); \ - _l = clib_fifo_len (f); \ - _n = clib_fifo_elts (f); \ - while (_n > 0) \ - { \ - (v) = (f) + _i; \ - do { body; } while (0); \ - _n--; \ - _i++; \ - _i = _i >= _l ? 0 : _i; \ - } \ -} while (0) - -#endif /* included_fifo_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/format.c b/vppinfra/vppinfra/format.c deleted file mode 100644 index 78e52e9a2ad..00000000000 --- a/vppinfra/vppinfra/format.c +++ /dev/null @@ -1,814 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/*------------------------------------------------------------------ - * format.c -- see notice below - * - * October 2003, Eliot Dresselhaus - * - * Modifications to this file Copyright (c) 2003 by cisco Systems, Inc. - * All rights reserved. - *------------------------------------------------------------------ - */ - -/* - Copyright (c) 2001, 2002, 2003, 2006 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include <stdarg.h> /* va_start, etc */ - -#ifdef CLIB_UNIX -#include <unistd.h> -#include <stdio.h> -#endif - -#ifdef CLIB_STANDALONE -#include <vppinfra/standalone_stdio.h> -#endif - -#include <vppinfra/mem.h> -#include <vppinfra/format.h> -#include <vppinfra/vec.h> -#include <vppinfra/error.h> -#include <vppinfra/string.h> -#include <vppinfra/os.h> /* os_puts */ - -typedef struct -{ - /* Output number in this base. */ - u8 base; - - /* Number of show of 64 bit number. */ - u8 n_bits; - - /* Signed or unsigned. */ - u8 is_signed; - - /* Output digits uppercase (not lowercase) %X versus %x. */ - u8 uppercase_digits; -} format_integer_options_t; - -static u8 *format_integer (u8 * s, u64 number, - format_integer_options_t * options); -static u8 *format_float (u8 * s, f64 x, uword n_digits_to_print, - uword output_style); - -typedef struct -{ - /* String justification: + => right, - => left, = => center. */ - uword justify; - - /* Width of string (before and after decimal point for numbers). - 0 => natural width. */ - uword width[2]; - - /* Long => 'l', long long 'L', int 0. */ - uword how_long; - - /* Pad character. Defaults to space. */ - uword pad_char; -} format_info_t; - -static u8 * -justify (u8 * s, format_info_t * fi, uword s_len_orig) -{ - uword i0, l0, l1; - - i0 = s_len_orig; - l0 = i0 + fi->width[0]; - l1 = vec_len (s); - - /* If width is zero user returned width. */ - if (l0 == i0) - l0 = l1; - - if (l1 > l0) - _vec_len (s) = l0; - else if (l0 > l1) - { - uword n = l0 - l1; - uword n_left = 0, n_right = 0; - - switch (fi->justify) - { - case '-': - n_right = n; - break; - - case '+': - n_left = n; - break; - - case '=': - n_right = n_left = n / 2; - if (n % 2) - n_left++; - break; - } - if (n_left > 0) - { - vec_insert (s, n_left, i0); - memset (s + i0, fi->pad_char, n_left); - l1 = vec_len (s); - } - if (n_right > 0) - { - vec_resize (s, n_right); - memset (s + l1, fi->pad_char, n_right); - } - } - return s; -} - -static u8 * -do_percent (u8 ** _s, u8 * fmt, va_list * va) -{ - u8 *s = *_s; - uword c; - - u8 *f = fmt; - - format_info_t fi = { - .justify = '+', - .width = {0}, - .pad_char = ' ', - .how_long = 0, - }; - - uword i; - - ASSERT (f[0] == '%'); - - switch (c = *++f) - { - case '%': - /* %% => % */ - vec_add1 (s, c); - f++; - goto done; - - case '-': - case '+': - case '=': - fi.justify = c; - c = *++f; - break; - } - - /* Parse width0 . width1. */ - { - uword is_first_digit = 1; - - fi.width[0] = fi.width[1] = 0; - for (i = 0; i < 2; i++) - { - if (c == '0' && i == 0 && is_first_digit) - fi.pad_char = '0'; - is_first_digit = 0; - if (c == '*') - { - fi.width[i] = va_arg (*va, int); - c = *++f; - } - else - { - while (c >= '0' && c <= '9') - { - fi.width[i] = 10 * fi.width[i] + (c - '0'); - c = *++f; - } - } - if (c != '.') - break; - c = *++f; - } - } - - /* Parse %l* and %L* */ - switch (c) - { - case 'w': - /* word format. */ - fi.how_long = 'w'; - c = *++f; - break; - - case 'L': - case 'l': - fi.how_long = c; - c = *++f; - if (c == 'l' && *f == 'l') - { - fi.how_long = 'L'; - c = *++f; - } - break; - } - - /* Finally we are ready for format letter. */ - if (c != 0) - { - uword s_initial_len = vec_len (s); - format_integer_options_t o = { - .is_signed = 0, - .base = 10, - .n_bits = BITS (uword), - .uppercase_digits = 0, - }; - - f++; - - switch (c) - { - default: - { - /* Try to give a helpful error message. */ - vec_free (s); - s = format (s, "**** CLIB unknown format `%%%c' ****", c); - goto done; - } - - case 'c': - vec_add1 (s, va_arg (*va, int)); - break; - - case 'p': - vec_add1 (s, '0'); - vec_add1 (s, 'x'); - - o.is_signed = 0; - o.n_bits = BITS (uword *); - o.base = 16; - o.uppercase_digits = 0; - - s = format_integer (s, pointer_to_uword (va_arg (*va, void *)), &o); - break; - - case 'x': - case 'X': - case 'u': - case 'd': - { - u64 number; - - o.base = 10; - if (c == 'x' || c == 'X') - o.base = 16; - o.is_signed = c == 'd'; - o.uppercase_digits = c == 'X'; - - switch (fi.how_long) - { - case 'L': - number = va_arg (*va, unsigned long long); - o.n_bits = BITS (unsigned long long); - break; - - case 'l': - number = va_arg (*va, long); - o.n_bits = BITS (long); - break; - - case 'w': - number = va_arg (*va, word); - o.n_bits = BITS (uword); - break; - - default: - number = va_arg (*va, int); - o.n_bits = BITS (int); - break; - } - - s = format_integer (s, number, &o); - } - break; - - case 's': - case 'S': - { - char *cstring = va_arg (*va, char *); - uword len; - - if (!cstring) - { - cstring = "(nil)"; - len = 5; - } - else if (fi.width[1] != 0) - len = clib_min (strlen (cstring), fi.width[1]); - else - len = strlen (cstring); - - /* %S => format string as C identifier (replace _ with space). */ - if (c == 'S') - { - for (i = 0; i < len; i++) - vec_add1 (s, cstring[i] == '_' ? ' ' : cstring[i]); - } - else - vec_add (s, cstring, len); - } - break; - - case 'v': - { - u8 *v = va_arg (*va, u8 *); - uword len; - - if (fi.width[1] != 0) - len = clib_min (vec_len (v), fi.width[1]); - else - len = vec_len (v); - - vec_add (s, v, len); - } - break; - - case 'f': - case 'g': - case 'e': - /* Floating point. */ - ASSERT (fi.how_long == 0 || fi.how_long == 'l'); - s = format_float (s, va_arg (*va, double), fi.width[1], c); - break; - - case 'U': - /* User defined function. */ - { - typedef u8 *(user_func_t) (u8 * s, va_list * args); - user_func_t *u = va_arg (*va, user_func_t *); - - s = (*u) (s, va); - } - break; - } - - s = justify (s, &fi, s_initial_len); - } - -done: - *_s = s; - return f; -} - -u8 * -va_format (u8 * s, const char *fmt, va_list * va) -{ - u8 *f = (u8 *) fmt, *g; - u8 c; - - g = f; - while (1) - { - c = *f; - - if (!c) - break; - - if (c == '%') - { - if (f > g) - vec_add (s, g, f - g); - f = g = do_percent (&s, f, va); - } - else - { - f++; - } - } - - if (f > g) - vec_add (s, g, f - g); - - return s; -} - -u8 * -format (u8 * s, const char *fmt, ...) -{ - va_list va; - va_start (va, fmt); - s = va_format (s, fmt, &va); - va_end (va); - return s; -} - -word -va_fformat (FILE * f, char *fmt, va_list * va) -{ - word ret; - u8 *s; - - s = va_format (0, fmt, va); - -#ifdef CLIB_UNIX - if (f) - { - ret = fwrite (s, vec_len (s), 1, f); - } - else -#endif /* CLIB_UNIX */ - { - ret = 0; - os_puts (s, vec_len (s), /* is_error */ 0); - } - - vec_free (s); - return ret; -} - -word -fformat (FILE * f, char *fmt, ...) -{ - va_list va; - word ret; - - va_start (va, fmt); - ret = va_fformat (f, fmt, &va); - va_end (va); - - return (ret); -} - -#ifdef CLIB_UNIX -word -fdformat (int fd, char *fmt, ...) -{ - word ret; - u8 *s; - va_list va; - - va_start (va, fmt); - s = va_format (0, fmt, &va); - va_end (va); - - ret = write (fd, s, vec_len (s)); - vec_free (s); - return ret; -} -#endif - -/* Format integral type. */ -static u8 * -format_integer (u8 * s, u64 number, format_integer_options_t * options) -{ - u64 q; - u32 r; - u8 digit_buffer[128]; - u8 *d = digit_buffer + sizeof (digit_buffer); - word c, base; - - if (options->is_signed && (i64) number < 0) - { - number = -number; - vec_add1 (s, '-'); - } - - if (options->n_bits < BITS (number)) - number &= ((u64) 1 << options->n_bits) - 1; - - base = options->base; - - while (1) - { - q = number / base; - r = number % base; - - if (r < 10 + 26 + 26) - { - if (r < 10) - c = '0' + r; - else if (r < 10 + 26) - c = 'a' + (r - 10); - else - c = 'A' + (r - 10 - 26); - - if (options->uppercase_digits - && base <= 10 + 26 && c >= 'a' && c <= 'z') - c += 'A' - 'a'; - - *--d = c; - } - else /* will never happen, warning be gone */ - { - *--d = '?'; - } - - if (q == 0) - break; - - number = q; - } - - vec_add (s, d, digit_buffer + sizeof (digit_buffer) - d); - return s; -} - -/* Floating point formatting. */ -/* Deconstruct IEEE 64 bit number into sign exponent and fraction. */ -#define f64_down(f,sign,expon,fraction) \ -do { \ - union { u64 u; f64 f; } _f64_down_tmp; \ - _f64_down_tmp.f = (f); \ - (sign) = (_f64_down_tmp.u >> 63); \ - (expon) = ((_f64_down_tmp.u >> 52) & 0x7ff) - 1023; \ - (fraction) = ((_f64_down_tmp.u << 12) >> 12) | ((u64) 1 << 52); \ -} while (0) - -/* Construct IEEE 64 bit number. */ -static f64 -f64_up (uword sign, word expon, u64 fraction) -{ - union - { - u64 u; - f64 f; - } tmp; - - tmp.u = (u64) ((sign) != 0) << 63; - - expon += 1023; - if (expon > 1023) - expon = 1023; - if (expon < 0) - expon = 0; - tmp.u |= (u64) expon << 52; - - tmp.u |= fraction & (((u64) 1 << 52) - 1); - - return tmp.f; -} - -/* Returns approximate precision of number given its exponent. */ -static f64 -f64_precision (int base2_expon) -{ - static int n_bits = 0; - - if (!n_bits) - { - /* Compute number of significant bits in floating point representation. */ - f64 one = 0; - f64 small = 1; - - while (one != 1) - { - small *= .5; - n_bits++; - one = 1 + small; - } - } - - return f64_up (0, base2_expon - n_bits, 0); -} - -/* Return x 10^n */ -static f64 -times_power_of_ten (f64 x, int n) -{ - if (n >= 0) - { - static f64 t[8] = { 1e+0, 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, }; - while (n >= 8) - { - x *= 1e+8; - n -= 8; - } - return x * t[n]; - } - else - { - static f64 t[8] = { 1e-0, 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7, }; - while (n <= -8) - { - x *= 1e-8; - n += 8; - } - return x * t[-n]; - } - -} - -/* Write x = y * 10^expon with 1 < y < 10. */ -static f64 -normalize (f64 x, word * expon_return, f64 * prec_return) -{ - word expon2, expon10; - CLIB_UNUSED (u64 fraction); - CLIB_UNUSED (word sign); - f64 prec; - - f64_down (x, sign, expon2, fraction); - - expon10 = - .5 + - expon2 * .301029995663981195213738894724493 /* Log (2) / Log (10) */ ; - - prec = f64_precision (expon2); - x = times_power_of_ten (x, -expon10); - prec = times_power_of_ten (prec, -expon10); - - while (x < 1) - { - x *= 10; - prec *= 10; - expon10--; - } - - while (x > 10) - { - x *= .1; - prec *= .1; - expon10++; - } - - if (x + prec >= 10) - { - x = 1; - expon10++; - } - - *expon_return = expon10; - *prec_return = prec; - - return x; -} - -static u8 * -add_some_zeros (u8 * s, uword n_zeros) -{ - while (n_zeros > 0) - { - vec_add1 (s, '0'); - n_zeros--; - } - return s; -} - -/* Format a floating point number with the given number of fractional - digits (e.g. 1.2345 with 2 fraction digits yields "1.23") and output style. */ -static u8 * -format_float (u8 * s, f64 x, uword n_fraction_digits, uword output_style) -{ - f64 prec; - word sign, expon, n_fraction_done, added_decimal_point; - /* Position of decimal point relative to where we are. */ - word decimal_point; - - /* Default number of digits to print when its not specified. */ - if (n_fraction_digits == ~0) - n_fraction_digits = 7; - n_fraction_done = 0; - decimal_point = 0; - added_decimal_point = 0; - sign = expon = 0; - - /* Special case: zero. */ - if (x == 0) - { - do_zero: - vec_add1 (s, '0'); - goto done; - } - - if (x < 0) - { - x = -x; - sign = 1; - } - - /* Check for infinity. */ - if (x == x / 2) - return format (s, "%cinfinity", sign ? '-' : '+'); - - x = normalize (x, &expon, &prec); - - /* Not enough digits to print anything: so just print 0 */ - if ((word) - expon > (word) n_fraction_digits - && (output_style == 'f' || (output_style == 'g'))) - goto do_zero; - - if (sign) - vec_add1 (s, '-'); - - if (output_style == 'f' - || (output_style == 'g' && expon > -10 && expon < 10)) - { - if (expon < 0) - { - /* Add decimal point and leading zeros. */ - vec_add1 (s, '.'); - n_fraction_done = clib_min (-(expon + 1), n_fraction_digits); - s = add_some_zeros (s, n_fraction_done); - decimal_point = -n_fraction_done; - added_decimal_point = 1; - } - else - decimal_point = expon + 1; - } - else - { - /* Exponential output style. */ - decimal_point = 1; - output_style = 'e'; - } - - while (1) - { - uword digit; - - /* Number is smaller than precision: call it zero. */ - if (x < prec) - break; - - digit = x; - x -= digit; - if (x + prec >= 1) - { - digit++; - x -= 1; - } - - /* Round last printed digit. */ - if (decimal_point <= 0 - && n_fraction_done + 1 == n_fraction_digits && digit < 9) - digit += x >= .5; - - vec_add1 (s, '0' + digit); - - /* Move rightwards towards/away from decimal point. */ - decimal_point--; - - n_fraction_done += decimal_point < 0; - if (decimal_point <= 0 && n_fraction_done >= n_fraction_digits) - break; - - if (decimal_point == 0 && x != 0) - { - vec_add1 (s, '.'); - added_decimal_point = 1; - } - - x *= 10; - prec *= 10; - } - -done: - if (decimal_point > 0) - { - s = add_some_zeros (s, decimal_point); - decimal_point = 0; - } - - if (n_fraction_done < n_fraction_digits) - { - if (!added_decimal_point) - vec_add1 (s, '.'); - s = add_some_zeros (s, n_fraction_digits - n_fraction_done); - } - - if (output_style == 'e') - s = format (s, "e%wd", expon); - - return s; -} - - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/format.h b/vppinfra/vppinfra/format.h deleted file mode 100644 index bc0d6d15fd5..00000000000 --- a/vppinfra/vppinfra/format.h +++ /dev/null @@ -1,331 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_format_h -#define included_format_h - -#include <stdarg.h> - -#include <vppinfra/clib.h> /* for CLIB_UNIX, etc. */ -#include <vppinfra/vec.h> -#include <vppinfra/error.h> /* for ASSERT */ -#include <vppinfra/string.h> - -typedef u8 *(format_function_t) (u8 * s, va_list * args); - -u8 *va_format (u8 * s, const char *format, va_list * args); -u8 *format (u8 * s, const char *format, ...); - -#ifdef CLIB_UNIX - -#include <stdio.h> - -#else /* ! CLIB_UNIX */ - -/* We're not Unix and have not stdio.h */ -#define FILE void -#define stdin ((FILE *) 0) -#define stdout ((FILE *) 1) -#define stderr ((FILE *) 2) - -#endif - -word va_fformat (FILE * f, char *fmt, va_list * va); -word fformat (FILE * f, char *fmt, ...); -word fdformat (int fd, char *fmt, ...); - -always_inline uword -format_get_indent (u8 * s) -{ - uword indent = 0; - u8 *nl; - - if (!s) - return indent; - - nl = vec_end (s) - 1; - while (nl >= s) - { - if (*nl-- == '\n') - break; - indent++; - } - return indent; -} - -#define _(f) u8 * f (u8 * s, va_list * va) - -/* Standard user-defined formats. */ -_(format_vec32); -_(format_vec_uword); -_(format_ascii_bytes); -_(format_hex_bytes); -_(format_white_space); -_(format_f64); -_(format_time_interval); - -#ifdef CLIB_UNIX -/* Unix specific formats. */ -_(format_address_family); -_(format_unix_arphrd); -_(format_unix_interface_flags); -_(format_network_address); -_(format_network_protocol); -_(format_network_port); -_(format_sockaddr); -_(format_ip4_tos_byte); -_(format_ip4_packet); -_(format_icmp4_type_and_code); -_(format_ethernet_packet); -_(format_hostname); -_(format_timeval); -_(format_time_float); -_(format_signal); -_(format_ucontext_pc); -#endif - -#undef _ - -/* Unformat. */ - -typedef struct _unformat_input_t -{ - /* Input buffer (vector). */ - u8 *buffer; - - /* Current index in input buffer. */ - uword index; - - /* Vector of buffer marks. Used to delineate pieces of the buffer - for error reporting and for parse recovery. */ - uword *buffer_marks; - - /* User's function to fill the buffer when its empty - (and argument). */ - uword (*fill_buffer) (struct _unformat_input_t * i); - - /* Return values for fill buffer function which indicate whether not - input has been exhausted. */ -#define UNFORMAT_END_OF_INPUT (~0) -#define UNFORMAT_MORE_INPUT 0 - - /* User controlled argument to fill buffer function. */ - void *fill_buffer_arg; -} unformat_input_t; - -always_inline void -unformat_init (unformat_input_t * i, - uword (*fill_buffer) (unformat_input_t *), - void *fill_buffer_arg) -{ - memset (i, 0, sizeof (i[0])); - i->fill_buffer = fill_buffer; - i->fill_buffer_arg = fill_buffer_arg; -} - -always_inline void -unformat_free (unformat_input_t * i) -{ - vec_free (i->buffer); - vec_free (i->buffer_marks); - memset (i, 0, sizeof (i[0])); -} - -always_inline uword -unformat_check_input (unformat_input_t * i) -{ - /* Low level fill input function. */ - extern uword _unformat_fill_input (unformat_input_t * i); - - if (i->index >= vec_len (i->buffer) && i->index != UNFORMAT_END_OF_INPUT) - _unformat_fill_input (i); - - return i->index; -} - -/* Return true if input is exhausted */ -always_inline uword -unformat_is_eof (unformat_input_t * input) -{ - return unformat_check_input (input) == UNFORMAT_END_OF_INPUT; -} - -/* Return next element in input vector, - possibly calling fill input to get more. */ -always_inline uword -unformat_get_input (unformat_input_t * input) -{ - uword i = unformat_check_input (input); - if (i < vec_len (input->buffer)) - { - input->index = i + 1; - i = input->buffer[i]; - } - return i; -} - -/* Back up input pointer by one. */ -always_inline void -unformat_put_input (unformat_input_t * input) -{ - input->index -= 1; -} - -/* Peek current input character without advancing. */ -always_inline uword -unformat_peek_input (unformat_input_t * input) -{ - uword c = unformat_get_input (input); - if (c != UNFORMAT_END_OF_INPUT) - unformat_put_input (input); - return c; -} - -/* Skip current input line. */ -always_inline void -unformat_skip_line (unformat_input_t * i) -{ - uword c; - - while ((c = unformat_get_input (i)) != UNFORMAT_END_OF_INPUT && c != '\n') - ; -} - -uword unformat_skip_white_space (unformat_input_t * input); - -/* Unformat function. */ -typedef uword (unformat_function_t) (unformat_input_t * input, - va_list * args); - -/* External functions. */ - -/* General unformatting function with programmable input stream. */ -uword unformat (unformat_input_t * i, char *fmt, ...); - -/* Call user defined parse function. - unformat_user (i, f, ...) is equivalent to unformat (i, "%U", f, ...) */ -uword unformat_user (unformat_input_t * input, unformat_function_t * func, - ...); - -/* Alternate version which allows for extensions. */ -uword va_unformat (unformat_input_t * i, char *fmt, va_list * args); - -/* Setup for unformat of Unix style command line. */ -void unformat_init_command_line (unformat_input_t * input, char *argv[]); - -/* Setup for unformat of given string. */ -void unformat_init_string (unformat_input_t * input, - char *string, int string_len); - -always_inline void -unformat_init_cstring (unformat_input_t * input, char *string) -{ - unformat_init_string (input, string, strlen (string)); -} - -/* Setup for unformat of given vector string; vector will be freed by unformat_string. */ -void unformat_init_vector (unformat_input_t * input, u8 * vector_string); - -/* Format function for unformat input usable when an unformat error - has occurred. */ -u8 *format_unformat_error (u8 * s, va_list * va); - -#define unformat_parse_error(input) \ - clib_error_return (0, "parse error `%U'", format_unformat_error, input) - -/* Print all input: not just error context. */ -u8 *format_unformat_input (u8 * s, va_list * va); - -/* Unformat (parse) function which reads a %s string and converts it - to and unformat_input_t. */ -unformat_function_t unformat_input; - -/* Parse a line ending with \n and return it. */ -unformat_function_t unformat_line; - -/* Parse a line ending with \n and return it as an unformat_input_t. */ -unformat_function_t unformat_line_input; - -/* Parse a token containing given set of characters. */ -unformat_function_t unformat_token; - -/* Parses a hexstring into a vector of bytes. */ -unformat_function_t unformat_hex_string; - -/* Returns non-zero match if input is exhausted. - Useful to ensure that the entire input matches with no trailing junk. */ -unformat_function_t unformat_eof; - -/* Parse memory size e.g. 100, 100k, 100m, 100g. */ -unformat_function_t unformat_memory_size; - -/* Unparse memory size e.g. 100, 100k, 100m, 100g. */ -u8 *format_memory_size (u8 * s, va_list * va); - -/* Format c identifier: e.g. a_name -> "a name". */ -u8 *format_c_identifier (u8 * s, va_list * va); - -/* Format hexdump with both hex and printable chars - compatible with text2pcap */ -u8 *format_hexdump (u8 * s, va_list * va); - -/* Unix specific formats. */ -#ifdef CLIB_UNIX -/* Setup input from Unix file. */ -void unformat_init_unix_file (unformat_input_t * input, int file_descriptor); - -/* Take input from Unix environment variable; returns - 1 if variable exists zero otherwise. */ -uword unformat_init_unix_env (unformat_input_t * input, char *var); -#endif /* CLIB_UNIX */ - -/* Test code. */ -int test_format_main (unformat_input_t * input); -int test_unformat_main (unformat_input_t * input); - -/* This is not the right place for this, but putting it in vec.h -created circular dependency problems. */ -int test_vec_main (unformat_input_t * input); - -#endif /* included_format_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/graph.c b/vppinfra/vppinfra/graph.c deleted file mode 100644 index 98a29046f17..00000000000 --- a/vppinfra/vppinfra/graph.c +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include <vppinfra/graph.h> - -/* Set link distance, creating link if not found. */ -u32 -graph_set_link (graph_t * g, u32 src, u32 dst, u32 distance) -{ - graph_node_t *src_node, *dst_node; - graph_link_t *l; - u32 old_distance; - - /* The following validate will not work if src or dst are on the - pool free list. */ - if (src < vec_len (g->nodes)) - ASSERT (!pool_is_free_index (g->nodes, src)); - if (dst < vec_len (g->nodes)) - ASSERT (!pool_is_free_index (g->nodes, dst)); - - /* Make new (empty) nodes to make src and dst valid. */ - pool_validate_index (g->nodes, clib_max (src, dst)); - - src_node = pool_elt_at_index (g->nodes, src); - dst_node = pool_elt_at_index (g->nodes, dst); - - l = graph_dir_get_link_to_node (&src_node->next, dst); - if (l) - { - old_distance = l->distance; - l->distance = distance; - - l = graph_dir_get_link_to_node (&dst_node->prev, src); - l->distance = distance; - } - else - { - uword li_next, li_prev; - - old_distance = ~0; - - li_next = graph_dir_add_link (&src_node->next, dst, distance); - li_prev = graph_dir_add_link (&dst_node->prev, src, distance); - - l = vec_elt_at_index (src_node->next.links, li_next); - l->link_to_self_index = li_prev; - - l = vec_elt_at_index (dst_node->prev.links, li_prev); - l->link_to_self_index = li_next; - } - - return old_distance; -} - -void -graph_del_link (graph_t * g, u32 src, u32 dst) -{ - graph_node_t *src_node, *dst_node; - - src_node = pool_elt_at_index (g->nodes, src); - dst_node = pool_elt_at_index (g->nodes, dst); - - graph_dir_del_link (&src_node->next, dst); - graph_dir_del_link (&dst_node->next, src); -} - -/* Delete source node and all links from other nodes from/to source. */ -uword -graph_del_node (graph_t * g, u32 src) -{ - graph_node_t *src_node, *n; - uword index; - graph_link_t *l; - - src_node = pool_elt_at_index (g->nodes, src); - - vec_foreach (l, src_node->next.links) - { - n = pool_elt_at_index (g->nodes, l->node_index); - graph_dir_del_link (&n->prev, src); - } - - vec_foreach (l, src_node->prev.links) - { - n = pool_elt_at_index (g->nodes, l->node_index); - graph_dir_del_link (&n->next, src); - } - - graph_dir_free (&src_node->next); - graph_dir_free (&src_node->prev); - - index = src_node - g->nodes; - pool_put (g->nodes, src_node); - memset (src_node, ~0, sizeof (src_node[0])); - - return index; -} - -uword -unformat_graph (unformat_input_t * input, va_list * args) -{ - graph_t *g = va_arg (*args, graph_t *); - typedef struct - { - u32 src, dst, distance; - } T; - T *links = 0, *l; - uword result; - - while (1) - { - vec_add2 (links, l, 1); - if (!unformat (input, "%d%d%d", &l->src, &l->dst, &l->distance)) - break; - } - _vec_len (links) -= 1; - result = vec_len (links) > 0; - vec_foreach (l, links) - { - graph_set_link (g, l->src, l->dst, l->distance); - graph_set_link (g, l->dst, l->src, l->distance); - } - - vec_free (links); - return result; -} - -u8 * -format_graph_node (u8 * s, va_list * args) -{ - graph_t *g = va_arg (*args, graph_t *); - u32 node_index = va_arg (*args, u32); - - if (g->format_node) - s = format (s, "%U", g->format_node, g, node_index); - else - s = format (s, "%d", node_index); - - return s; -} - -u8 * -format_graph (u8 * s, va_list * args) -{ - graph_t *g = va_arg (*args, graph_t *); - graph_node_t *n; - graph_link_t *l; - uword indent = format_get_indent (s); - - s = format (s, "graph %d nodes", pool_elts (g->nodes)); - /* *INDENT-OFF* */ - pool_foreach (n, g->nodes, ({ - s = format (s, "\n%U", format_white_space, indent + 2); - s = format (s, "%U -> ", format_graph_node, g, n - g->nodes); - vec_foreach (l, n->next.links) - s = format (s, "%U (%d), ", - format_graph_node, g, l->node_index, - l->distance); - })); - /* *INDENT-ON* */ - - return s; -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/graph.h b/vppinfra/vppinfra/graph.h deleted file mode 100644 index 1c26118f76c..00000000000 --- a/vppinfra/vppinfra/graph.h +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef included_clib_graph_h -#define included_clib_graph_h - -#include <vppinfra/format.h> -#include <vppinfra/hash.h> -#include <vppinfra/pool.h> - -/* Generic graphs. */ -typedef struct -{ - /* Next node along this link. */ - u32 node_index; - - /* Other direction link index to reach back to current node. */ - u32 link_to_self_index; - - /* Distance to next node. */ - u32 distance; -} graph_link_t; - -/* Direction on graph: either next or previous. */ -typedef struct -{ - /* Vector of links. */ - graph_link_t *links; - - /* Hash mapping node index to link which visits this node. */ - uword *link_index_by_node_index; -} graph_dir_t; - -always_inline void -graph_dir_free (graph_dir_t * d) -{ - vec_free (d->links); - hash_free (d->link_index_by_node_index); -} - -always_inline graph_link_t * -graph_dir_get_link_to_node (graph_dir_t * d, u32 node_index) -{ - uword *p = hash_get (d->link_index_by_node_index, node_index); - return p ? vec_elt_at_index (d->links, p[0]) : 0; -} - -always_inline uword -graph_dir_add_link (graph_dir_t * d, u32 node_index, u32 distance) -{ - graph_link_t *l; - ASSERT (!graph_dir_get_link_to_node (d, node_index)); - vec_add2 (d->links, l, 1); - l->node_index = node_index; - l->distance = distance; - hash_set (d->link_index_by_node_index, node_index, l - d->links); - return l - d->links; -} - -always_inline void -graph_dir_del_link (graph_dir_t * d, u32 node_index) -{ - graph_link_t *l = graph_dir_get_link_to_node (d, node_index); - uword li = l - d->links; - uword n_links = vec_len (d->links); - - ASSERT (l != 0); - hash_unset (d->link_index_by_node_index, node_index); - n_links -= 1; - if (li < n_links) - d->links[li] = d->links[n_links]; - _vec_len (d->links) = n_links; -} - -typedef struct -{ - /* Nodes we are connected to plus distances. */ - graph_dir_t next, prev; -} graph_node_t; - -typedef struct -{ - /* Pool of nodes. */ - graph_node_t *nodes; - - void *opaque; - - format_function_t *format_node; -} graph_t; - -/* Set link distance, creating link if not found. */ -u32 graph_set_link (graph_t * g, u32 src, u32 dst, u32 distance); - -always_inline void -graph_set_bidirectional_link (graph_t * g, u32 src, u32 dst, u32 distance) -{ - graph_set_link (g, src, dst, distance); - graph_set_link (g, dst, src, distance); -} - -void graph_del_link (graph_t * g, u32 src, u32 dst); -uword graph_del_node (graph_t * g, u32 src); - -unformat_function_t unformat_graph; -format_function_t format_graph; -format_function_t format_graph_node; - -#endif /* included_clib_graph_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/hash.c b/vppinfra/vppinfra/hash.c deleted file mode 100644 index 062ad8823e1..00000000000 --- a/vppinfra/vppinfra/hash.c +++ /dev/null @@ -1,1095 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001-2005 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include <vppinfra/hash.h> -#include <vppinfra/error.h> -#include <vppinfra/mem.h> -#include <vppinfra/byte_order.h> /* for clib_arch_is_big_endian */ - -always_inline void -zero_pair (hash_t * h, hash_pair_t * p) -{ - memset (p, 0, hash_pair_bytes (h)); -} - -always_inline void -init_pair (hash_t * h, hash_pair_t * p) -{ - memset (p->value, ~0, hash_value_bytes (h)); -} - -always_inline hash_pair_union_t * -get_pair (void *v, uword i) -{ - hash_t *h = hash_header (v); - hash_pair_t *p; - ASSERT (i < vec_len (v)); - p = v; - p += i << h->log2_pair_size; - return (hash_pair_union_t *) p; -} - -always_inline void -set_is_user (void *v, uword i, uword is_user) -{ - hash_t *h = hash_header (v); - uword i0 = i / BITS (h->is_user[0]); - uword i1 = (uword) 1 << (i % BITS (h->is_user[0])); - if (is_user) - h->is_user[i0] |= i1; - else - h->is_user[i0] &= ~i1; -} - -static u8 *hash_format_pair_default (u8 * s, va_list * args); - -#if uword_bits == 64 - -static inline u64 -zap64 (u64 x, word n) -{ -#define _(n) (((u64) 1 << (u64) (8*(n))) - (u64) 1) - static u64 masks_little_endian[] = { - 0, _(1), _(2), _(3), _(4), _(5), _(6), _(7), - }; - static u64 masks_big_endian[] = { - 0, ~_(7), ~_(6), ~_(5), ~_(4), ~_(3), ~_(2), ~_(1), - }; -#undef _ - if (clib_arch_is_big_endian) - return x & masks_big_endian[n]; - else - return x & masks_little_endian[n]; -} - -static inline u64 -hash_memory64 (void *p, word n_bytes, u64 state) -{ - u64 *q = p; - u64 a, b, c, n; - - a = b = 0x9e3779b97f4a7c13LL; - c = state; - n = n_bytes; - - while (n >= 3 * sizeof (u64)) - { - a += clib_mem_unaligned (q + 0, u64); - b += clib_mem_unaligned (q + 1, u64); - c += clib_mem_unaligned (q + 2, u64); - hash_mix64 (a, b, c); - n -= 3 * sizeof (u64); - q += 3; - } - - c += n_bytes; - switch (n / sizeof (u64)) - { - case 2: - a += clib_mem_unaligned (q + 0, u64); - b += clib_mem_unaligned (q + 1, u64); - if (n % sizeof (u64)) - c += zap64 (clib_mem_unaligned (q + 2, u64), n % sizeof (u64)) << 8; - break; - - case 1: - a += clib_mem_unaligned (q + 0, u64); - if (n % sizeof (u64)) - b += zap64 (clib_mem_unaligned (q + 1, u64), n % sizeof (u64)); - break; - - case 0: - if (n % sizeof (u64)) - a += zap64 (clib_mem_unaligned (q + 0, u64), n % sizeof (u64)); - break; - } - - hash_mix64 (a, b, c); - - return c; -} - -#else /* if uword_bits == 64 */ - -static inline u32 -zap32 (u32 x, word n) -{ -#define _(n) (((u32) 1 << (u32) (8*(n))) - (u32) 1) - static u32 masks_little_endian[] = { - 0, _(1), _(2), _(3), - }; - static u32 masks_big_endian[] = { - 0, ~_(3), ~_(2), ~_(1), - }; -#undef _ - if (clib_arch_is_big_endian) - return x & masks_big_endian[n]; - else - return x & masks_little_endian[n]; -} - -static inline u32 -hash_memory32 (void *p, word n_bytes, u32 state) -{ - u32 *q = p; - u32 a, b, c, n; - - a = b = 0x9e3779b9; - c = state; - n = n_bytes; - - while (n >= 3 * sizeof (u32)) - { - a += clib_mem_unaligned (q + 0, u32); - b += clib_mem_unaligned (q + 1, u32); - c += clib_mem_unaligned (q + 2, u32); - hash_mix32 (a, b, c); - n -= 3 * sizeof (u32); - q += 3; - } - - c += n_bytes; - switch (n / sizeof (u32)) - { - case 2: - a += clib_mem_unaligned (q + 0, u32); - b += clib_mem_unaligned (q + 1, u32); - if (n % sizeof (u32)) - c += zap32 (clib_mem_unaligned (q + 2, u32), n % sizeof (u32)) << 8; - break; - - case 1: - a += clib_mem_unaligned (q + 0, u32); - if (n % sizeof (u32)) - b += zap32 (clib_mem_unaligned (q + 1, u32), n % sizeof (u32)); - break; - - case 0: - if (n % sizeof (u32)) - a += zap32 (clib_mem_unaligned (q + 0, u32), n % sizeof (u32)); - break; - } - - hash_mix32 (a, b, c); - - return c; -} -#endif - -uword -hash_memory (void *p, word n_bytes, uword state) -{ - uword *q = p; - -#if uword_bits == 64 - return hash_memory64 (q, n_bytes, state); -#else - return hash_memory32 (q, n_bytes, state); -#endif -} - -#if uword_bits == 64 -always_inline uword -hash_uword (uword x) -{ - u64 a, b, c; - - a = b = 0x9e3779b97f4a7c13LL; - c = 0; - a += x; - hash_mix64 (a, b, c); - return c; -} -#else -always_inline uword -hash_uword (uword x) -{ - u32 a, b, c; - - a = b = 0x9e3779b9; - c = 0; - a += x; - hash_mix32 (a, b, c); - return c; -} -#endif - -/* Call sum function. Hash code will be sum function value - modulo the prime length of the hash table. */ -always_inline uword -key_sum (hash_t * h, uword key) -{ - uword sum; - switch (pointer_to_uword ((void *) h->key_sum)) - { - case KEY_FUNC_NONE: - sum = hash_uword (key); - break; - - case KEY_FUNC_POINTER_UWORD: - sum = hash_uword (*uword_to_pointer (key, uword *)); - break; - - case KEY_FUNC_POINTER_U32: - sum = hash_uword (*uword_to_pointer (key, u32 *)); - break; - - case KEY_FUNC_STRING: - sum = string_key_sum (h, key); - break; - - default: - sum = h->key_sum (h, key); - break; - } - - return sum; -} - -always_inline uword -key_equal1 (hash_t * h, uword key1, uword key2, uword e) -{ - switch (pointer_to_uword ((void *) h->key_equal)) - { - case KEY_FUNC_NONE: - break; - - case KEY_FUNC_POINTER_UWORD: - e = - *uword_to_pointer (key1, uword *) == *uword_to_pointer (key2, - uword *); - break; - - case KEY_FUNC_POINTER_U32: - e = *uword_to_pointer (key1, u32 *) == *uword_to_pointer (key2, u32 *); - break; - - case KEY_FUNC_STRING: - e = string_key_equal (h, key1, key2); - break; - - default: - e = h->key_equal (h, key1, key2); - break; - } - return e; -} - -/* Compares two keys: returns 1 if equal, 0 if not. */ -always_inline uword -key_equal (hash_t * h, uword key1, uword key2) -{ - uword e = key1 == key2; - if (CLIB_DEBUG > 0 && key1 == key2) - ASSERT (key_equal1 (h, key1, key2, e)); - if (!e) - e = key_equal1 (h, key1, key2, e); - return e; -} - -static hash_pair_union_t * -get_indirect (void *v, hash_pair_indirect_t * pi, uword key) -{ - hash_t *h = hash_header (v); - hash_pair_t *p0, *p1; - - p0 = p1 = pi->pairs; - if (h->log2_pair_size > 0) - p1 = hash_forward (h, p0, indirect_pair_get_len (pi)); - else - p1 += vec_len (p0); - - while (p0 < p1) - { - if (key_equal (h, p0->key, key)) - return (hash_pair_union_t *) p0; - p0 = hash_forward1 (h, p0); - } - - return (hash_pair_union_t *) 0; -} - -static hash_pair_union_t * -set_indirect_is_user (void *v, uword i, hash_pair_union_t * p, uword key) -{ - hash_t *h = hash_header (v); - hash_pair_t *q; - hash_pair_indirect_t *pi = &p->indirect; - uword log2_bytes = 0; - - if (h->log2_pair_size == 0) - q = vec_new (hash_pair_t, 2); - else - { - log2_bytes = 1 + hash_pair_log2_bytes (h); - q = clib_mem_alloc (1ULL << log2_bytes); - } - clib_memcpy (q, &p->direct, hash_pair_bytes (h)); - - pi->pairs = q; - if (h->log2_pair_size > 0) - indirect_pair_set (pi, log2_bytes, 2); - - set_is_user (v, i, 0); - - /* First element is used by existing pair, second will be used by caller. */ - q = hash_forward1 (h, q); - q->key = key; - init_pair (h, q); - return (hash_pair_union_t *) q; -} - -static hash_pair_union_t * -set_indirect (void *v, hash_pair_indirect_t * pi, uword key, - uword * found_key) -{ - hash_t *h = hash_header (v); - hash_pair_t *new_pair; - hash_pair_union_t *q; - - q = get_indirect (v, pi, key); - if (q) - { - *found_key = 1; - return q; - } - - if (h->log2_pair_size == 0) - vec_add2 (pi->pairs, new_pair, 1); - else - { - uword len, new_len, log2_bytes; - - len = indirect_pair_get_len (pi); - log2_bytes = indirect_pair_get_log2_bytes (pi); - - new_len = len + 1; - if (new_len * hash_pair_bytes (h) > (1ULL << log2_bytes)) - { - pi->pairs = clib_mem_realloc (pi->pairs, - 1ULL << (log2_bytes + 1), - 1ULL << log2_bytes); - log2_bytes++; - } - - indirect_pair_set (pi, log2_bytes, new_len); - new_pair = pi->pairs + (len << h->log2_pair_size); - } - new_pair->key = key; - init_pair (h, new_pair); - *found_key = 0; - return (hash_pair_union_t *) new_pair; -} - -static void -unset_indirect (void *v, uword i, hash_pair_t * q) -{ - hash_t *h = hash_header (v); - hash_pair_union_t *p = get_pair (v, i); - hash_pair_t *e; - hash_pair_indirect_t *pi = &p->indirect; - uword len, is_vec; - - is_vec = h->log2_pair_size == 0; - - ASSERT (!hash_is_user (v, i)); - len = is_vec ? vec_len (pi->pairs) : indirect_pair_get_len (pi); - e = hash_forward (h, pi->pairs, len - 1); - ASSERT (q >= pi->pairs && q <= e); - - /* We have two or fewer pairs and we are delete one pair. - Make indirect pointer direct and free indirect memory. */ - if (len <= 2) - { - hash_pair_t *r = pi->pairs; - - if (len == 2) - { - clib_memcpy (p, q == r ? hash_forward1 (h, r) : r, - hash_pair_bytes (h)); - set_is_user (v, i, 1); - } - else - zero_pair (h, &p->direct); - - if (is_vec) - vec_free (r); - else if (r) - clib_mem_free (r); - } - else - { - /* If deleting a pair we need to keep non-null pairs together. */ - if (q < e) - clib_memcpy (q, e, hash_pair_bytes (h)); - else - zero_pair (h, q); - if (is_vec) - _vec_len (pi->pairs) -= 1; - else - indirect_pair_set (pi, indirect_pair_get_log2_bytes (pi), len - 1); - } -} - -enum lookup_opcode -{ - GET = 1, - SET = 2, - UNSET = 3, -}; - -static hash_pair_t * -lookup (void *v, uword key, enum lookup_opcode op, - void *new_value, void *old_value) -{ - hash_t *h = hash_header (v); - hash_pair_union_t *p = 0; - uword found_key = 0; - uword i; - - if (!v) - return 0; - - i = key_sum (h, key) & (_vec_len (v) - 1); - p = get_pair (v, i); - - if (hash_is_user (v, i)) - { - found_key = key_equal (h, p->direct.key, key); - if (found_key) - { - if (op == UNSET) - { - set_is_user (v, i, 0); - if (old_value) - clib_memcpy (old_value, p->direct.value, - hash_value_bytes (h)); - zero_pair (h, &p->direct); - } - } - else - { - if (op == SET) - p = set_indirect_is_user (v, i, p, key); - else - p = 0; - } - } - else - { - hash_pair_indirect_t *pi = &p->indirect; - - if (op == SET) - { - if (!pi->pairs) - { - p->direct.key = key; - set_is_user (v, i, 1); - } - else - p = set_indirect (v, pi, key, &found_key); - } - else - { - p = get_indirect (v, pi, key); - found_key = p != 0; - if (found_key && op == UNSET) - { - if (old_value) - clib_memcpy (old_value, &p->direct.value, - hash_value_bytes (h)); - - unset_indirect (v, i, &p->direct); - - /* Nullify p (since it's just been deleted). - Otherwise we might be tempted to play with it. */ - p = 0; - } - } - } - - if (op == SET && p != 0) - { - /* Save away old value for caller. */ - if (old_value && found_key) - clib_memcpy (old_value, &p->direct.value, hash_value_bytes (h)); - clib_memcpy (&p->direct.value, new_value, hash_value_bytes (h)); - } - - if (op == SET) - h->elts += !found_key; - if (op == UNSET) - h->elts -= found_key; - - return &p->direct; -} - -/* Fetch value of key. */ -uword * -_hash_get (void *v, uword key) -{ - hash_t *h = hash_header (v); - hash_pair_t *p; - - /* Don't even search table if its empty. */ - if (!v || h->elts == 0) - return 0; - - p = lookup (v, key, GET, 0, 0); - if (!p) - return 0; - if (h->log2_pair_size == 0) - return &p->key; - else - return &p->value[0]; -} - -hash_pair_t * -_hash_get_pair (void *v, uword key) -{ - return lookup (v, key, GET, 0, 0); -} - -hash_pair_t * -hash_next (void *v, hash_next_t * hn) -{ - hash_t *h = hash_header (v); - hash_pair_t *p; - - while (1) - { - if (hn->i == 0 && hn->j == 0) - { - /* Save flags. */ - hn->f = h->flags; - - /* Prevent others from re-sizing hash table. */ - h->flags |= - (HASH_FLAG_NO_AUTO_GROW - | HASH_FLAG_NO_AUTO_SHRINK | HASH_FLAG_HASH_NEXT_IN_PROGRESS); - } - else if (hn->i >= hash_capacity (v)) - { - /* Restore flags. */ - h->flags = hn->f; - memset (hn, 0, sizeof (hn[0])); - return 0; - } - - p = hash_forward (h, v, hn->i); - if (hash_is_user (v, hn->i)) - { - hn->i++; - return p; - } - else - { - hash_pair_indirect_t *pi = (void *) p; - uword n; - - if (h->log2_pair_size > 0) - n = indirect_pair_get_len (pi); - else - n = vec_len (pi->pairs); - - if (hn->j >= n) - { - hn->i++; - hn->j = 0; - } - else - return hash_forward (h, pi->pairs, hn->j++); - } - } -} - -/* Remove key from table. */ -void * -_hash_unset (void *v, uword key, void *old_value) -{ - hash_t *h; - - if (!v) - return v; - - (void) lookup (v, key, UNSET, 0, old_value); - - h = hash_header (v); - if (!(h->flags & HASH_FLAG_NO_AUTO_SHRINK)) - { - /* Resize when 1/4 full. */ - if (h->elts > 32 && 4 * (h->elts + 1) < vec_len (v)) - v = hash_resize (v, vec_len (v) / 2); - } - - return v; -} - -void * -_hash_create (uword elts, hash_t * h_user) -{ - hash_t *h; - uword log2_pair_size; - void *v; - - /* Size of hash is power of 2 >= ELTS and larger than - number of bits in is_user bitmap elements. */ - elts = clib_max (elts, BITS (h->is_user[0])); - elts = 1ULL << max_log2 (elts); - - log2_pair_size = 1; - if (h_user) - log2_pair_size = h_user->log2_pair_size; - - v = _vec_resize (0, - /* vec len: */ elts, - /* data bytes: */ - (elts << log2_pair_size) * sizeof (hash_pair_t), - /* header bytes: */ - sizeof (h[0]) + - (elts / BITS (h->is_user[0])) * sizeof (h->is_user[0]), - /* alignment */ sizeof (hash_pair_t)); - h = hash_header (v); - - if (h_user) - h[0] = h_user[0]; - - h->log2_pair_size = log2_pair_size; - h->elts = 0; - - /* Default flags to never shrinking hash tables. - Shrinking tables can cause "jackpot" cases. */ - if (!h_user) - h->flags = HASH_FLAG_NO_AUTO_SHRINK; - - if (!h->format_pair) - { - h->format_pair = hash_format_pair_default; - h->format_pair_arg = 0; - } - - return v; -} - -void * -_hash_free (void *v) -{ - hash_t *h = hash_header (v); - hash_pair_union_t *p; - uword i; - - if (!v) - return v; - - /* We zero all freed memory in case user would be tempted to use it. */ - for (i = 0; i < hash_capacity (v); i++) - { - if (hash_is_user (v, i)) - continue; - p = get_pair (v, i); - if (h->log2_pair_size == 0) - vec_free (p->indirect.pairs); - else if (p->indirect.pairs) - clib_mem_free (p->indirect.pairs); - } - - vec_free_header (h); - - return 0; -} - -static void * -hash_resize_internal (void *old, uword new_size, uword free_old) -{ - void *new; - hash_pair_t *p; - - new = 0; - if (new_size > 0) - { - hash_t *h = old ? hash_header (old) : 0; - new = _hash_create (new_size, h); - /* *INDENT-OFF* */ - hash_foreach_pair (p, old, { - new = _hash_set3 (new, p->key, &p->value[0], 0); - }); - /* *INDENT-ON* */ - } - - if (free_old) - hash_free (old); - return new; -} - -void * -hash_resize (void *old, uword new_size) -{ - return hash_resize_internal (old, new_size, 1); -} - -void * -hash_dup (void *old) -{ - return hash_resize_internal (old, vec_len (old), 0); -} - -void * -_hash_set3 (void *v, uword key, void *value, void *old_value) -{ - hash_t *h; - - if (!v) - v = hash_create (0, sizeof (uword)); - - h = hash_header (v); - (void) lookup (v, key, SET, value, old_value); - - if (!(h->flags & HASH_FLAG_NO_AUTO_GROW)) - { - /* Resize when 3/4 full. */ - if (4 * (h->elts + 1) > 3 * vec_len (v)) - v = hash_resize (v, 2 * vec_len (v)); - } - - return v; -} - -uword -vec_key_sum (hash_t * h, uword key) -{ - void *v = uword_to_pointer (key, void *); - return hash_memory (v, vec_len (v) * h->user, 0); -} - -uword -vec_key_equal (hash_t * h, uword key1, uword key2) -{ - void *v1 = uword_to_pointer (key1, void *); - void *v2 = uword_to_pointer (key2, void *); - uword l1 = vec_len (v1); - uword l2 = vec_len (v2); - return l1 == l2 && 0 == memcmp (v1, v2, l1 * h->user); -} - -u8 * -vec_key_format_pair (u8 * s, va_list * args) -{ - void *CLIB_UNUSED (user_arg) = va_arg (*args, void *); - void *v = va_arg (*args, void *); - hash_pair_t *p = va_arg (*args, hash_pair_t *); - hash_t *h = hash_header (v); - void *u = uword_to_pointer (p->key, void *); - int i; - - switch (h->user) - { - case 1: - s = format (s, "%v", u); - break; - - case 2: - { - u16 *w = u; - for (i = 0; i < vec_len (w); i++) - s = format (s, "0x%x, ", w[i]); - break; - } - - case 4: - { - u32 *w = u; - for (i = 0; i < vec_len (w); i++) - s = format (s, "0x%x, ", w[i]); - break; - } - - case 8: - { - u64 *w = u; - for (i = 0; i < vec_len (w); i++) - s = format (s, "0x%Lx, ", w[i]); - break; - } - - default: - s = format (s, "0x%U", format_hex_bytes, u, vec_len (u) * h->user); - break; - } - - if (hash_value_bytes (h) > 0) - s = format (s, " -> 0x%wx", p->value[0]); - - return s; -} - -uword -mem_key_sum (hash_t * h, uword key) -{ - uword *v = uword_to_pointer (key, void *); - return hash_memory (v, h->user, 0); -} - -uword -mem_key_equal (hash_t * h, uword key1, uword key2) -{ - void *v1 = uword_to_pointer (key1, void *); - void *v2 = uword_to_pointer (key2, void *); - return v1 && v2 && 0 == memcmp (v1, v2, h->user); -} - -uword -string_key_sum (hash_t * h, uword key) -{ - char *v = uword_to_pointer (key, char *); - return hash_memory (v, strlen (v), 0); -} - -uword -string_key_equal (hash_t * h, uword key1, uword key2) -{ - void *v1 = uword_to_pointer (key1, void *); - void *v2 = uword_to_pointer (key2, void *); - return v1 && v2 && 0 == strcmp (v1, v2); -} - -u8 * -string_key_format_pair (u8 * s, va_list * args) -{ - void *CLIB_UNUSED (user_arg) = va_arg (*args, void *); - void *v = va_arg (*args, void *); - hash_pair_t *p = va_arg (*args, hash_pair_t *); - hash_t *h = hash_header (v); - void *u = uword_to_pointer (p->key, void *); - - s = format (s, "%s", u); - - if (hash_value_bytes (h) > 0) - s = - format (s, " -> 0x%8U", format_hex_bytes, &p->value[0], - hash_value_bytes (h)); - - return s; -} - -static u8 * -hash_format_pair_default (u8 * s, va_list * args) -{ - void *CLIB_UNUSED (user_arg) = va_arg (*args, void *); - void *v = va_arg (*args, void *); - hash_pair_t *p = va_arg (*args, hash_pair_t *); - hash_t *h = hash_header (v); - - s = format (s, "0x%08x", p->key); - if (hash_value_bytes (h) > 0) - s = - format (s, " -> 0x%8U", format_hex_bytes, &p->value[0], - hash_value_bytes (h)); - return s; -} - -uword -hash_bytes (void *v) -{ - uword i, bytes; - hash_t *h = hash_header (v); - - if (!v) - return 0; - - bytes = vec_capacity (v, hash_header_bytes (v)); - - for (i = 0; i < hash_capacity (v); i++) - { - if (!hash_is_user (v, i)) - { - hash_pair_union_t *p = get_pair (v, i); - if (h->log2_pair_size > 0) - bytes += 1 << indirect_pair_get_log2_bytes (&p->indirect); - else - bytes += vec_capacity (p->indirect.pairs, 0); - } - } - return bytes; -} - -u8 * -format_hash (u8 * s, va_list * va) -{ - void *v = va_arg (*va, void *); - int verbose = va_arg (*va, int); - hash_pair_t *p; - hash_t *h = hash_header (v); - uword i; - - s = format (s, "hash %p, %wd elts, capacity %wd, %wd bytes used,\n", - v, hash_elts (v), hash_capacity (v), hash_bytes (v)); - - { - uword *occupancy = 0; - - /* Count number of buckets with each occupancy. */ - for (i = 0; i < hash_capacity (v); i++) - { - uword j; - - if (hash_is_user (v, i)) - { - j = 1; - } - else - { - hash_pair_union_t *p = get_pair (v, i); - if (h->log2_pair_size > 0) - j = indirect_pair_get_len (&p->indirect); - else - j = vec_len (p->indirect.pairs); - } - - vec_validate (occupancy, j); - occupancy[j]++; - } - - s = format (s, " profile "); - for (i = 0; i < vec_len (occupancy); i++) - s = format (s, "%wd%c", occupancy[i], - i + 1 == vec_len (occupancy) ? '\n' : ' '); - - s = format (s, " lookup # of compares: "); - for (i = 1; i < vec_len (occupancy); i++) - s = format (s, "%wd: .%03d%c", i, - (1000 * i * occupancy[i]) / hash_elts (v), - i + 1 == vec_len (occupancy) ? '\n' : ' '); - - vec_free (occupancy); - } - - if (verbose) - { - /* *INDENT-OFF* */ - hash_foreach_pair (p, v, { - s = format (s, " %U\n", h->format_pair, h->format_pair_arg, v, p); - }); - /* *INDENT-ON* */ - } - - return s; -} - -static uword -unformat_hash_string_internal (unformat_input_t * input, - va_list * va, int is_vec) -{ - uword *hash = va_arg (*va, uword *); - int *result = va_arg (*va, int *); - u8 *string = 0; - uword *p; - - if (!unformat (input, is_vec ? "%v%_" : "%s%_", &string)) - return 0; - - p = hash_get_mem (hash, string); - if (p) - *result = *p; - - vec_free (string); - return p ? 1 : 0; -} - -uword -unformat_hash_vec_string (unformat_input_t * input, va_list * va) -{ - return unformat_hash_string_internal (input, va, /* is_vec */ 1); -} - -uword -unformat_hash_string (unformat_input_t * input, va_list * va) -{ - return unformat_hash_string_internal (input, va, /* is_vec */ 0); -} - -clib_error_t * -hash_validate (void *v) -{ - hash_t *h = hash_header (v); - uword i, j; - uword *keys = 0; - clib_error_t *error = 0; - -#define CHECK(x) if ((error = ERROR_ASSERT (x))) goto done; - - for (i = 0; i < hash_capacity (v); i++) - { - hash_pair_union_t *pu = get_pair (v, i); - - if (hash_is_user (v, i)) - { - CHECK (pu->direct.key != 0); - vec_add1 (keys, pu->direct.key); - } - else - { - hash_pair_t *p; - hash_pair_indirect_t *pi = &pu->indirect; - uword n; - - n = h->log2_pair_size > 0 - ? indirect_pair_get_len (pi) : vec_len (pi->pairs); - - for (p = pi->pairs; n-- > 0; p = hash_forward1 (h, p)) - { - /* Assert key uniqueness. */ - for (j = 0; j < vec_len (keys); j++) - CHECK (keys[j] != p->key); - vec_add1 (keys, p->key); - } - } - } - - CHECK (vec_len (keys) == h->elts); - - vec_free (keys); -done: - return error; -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/hash.h b/vppinfra/vppinfra/hash.h deleted file mode 100644 index 3f0efaa727c..00000000000 --- a/vppinfra/vppinfra/hash.h +++ /dev/null @@ -1,699 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001-2005 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_hash_h -#define included_hash_h - -#include <vppinfra/error.h> -#include <vppinfra/format.h> -#include <vppinfra/vec.h> -#include <vppinfra/vector.h> - -struct hash_header; - -typedef uword (hash_key_sum_function_t) (struct hash_header *, uword key); -typedef uword (hash_key_equal_function_t) - (struct hash_header *, uword key1, uword key2); - -/* Vector header for hash tables. */ -typedef struct hash_header -{ - /* Number of elements in hash table. */ - uword elts; - - /* Flags as follows. */ - u32 flags; - - /* Set if user does not want table to auto-resize when sufficiently full. */ -#define HASH_FLAG_NO_AUTO_GROW (1 << 0) - /* Set if user does not want table to auto-resize when sufficiently empty. */ -#define HASH_FLAG_NO_AUTO_SHRINK (1 << 1) - /* Set when hash_next is in the process of iterating through this hash table. */ -#define HASH_FLAG_HASH_NEXT_IN_PROGRESS (1 << 2) - - u32 log2_pair_size; - - /* Function to compute the "sum" of a hash key. - Hash function is this sum modulo the prime size of - the hash table (vec_len (v)). */ - hash_key_sum_function_t *key_sum; - - /* Special values for key_sum "function". */ -#define KEY_FUNC_NONE (0) /*< sum = key */ -#define KEY_FUNC_POINTER_UWORD (1) /*< sum = *(uword *) key */ -#define KEY_FUNC_POINTER_U32 (2) /*< sum = *(u32 *) key */ -#define KEY_FUNC_STRING (3) /*< sum = string_key_sum, etc. */ - - /* key comparison function */ - hash_key_equal_function_t *key_equal; - - /* Hook for user's data. Used to parameterize sum/equal functions. */ - any user; - - /* Format a (k,v) pair */ - format_function_t *format_pair; - - /* Format function arg */ - void *format_pair_arg; - - /* Bit i is set if pair i is a user object (as opposed to being - either zero or an indirect array of pairs). */ - uword is_user[0]; -} hash_t; - -/* Hash header size in bytes */ -always_inline uword -hash_header_bytes (void *v) -{ - hash_t *h; - uword is_user_bytes = - (sizeof (h->is_user[0]) * vec_len (v)) / BITS (h->is_user[0]); - return sizeof (h[0]) + is_user_bytes; -} - -/* Returns a pointer to the hash header given the vector pointer */ -always_inline hash_t * -hash_header (void *v) -{ - return vec_header (v, hash_header_bytes (v)); -} - -/* Number of elements in the hash table */ -always_inline uword -hash_elts (void *v) -{ - hash_t *h = hash_header (v); - return v ? h->elts : 0; -} - -/* Number of elements the hash table can hold */ -always_inline uword -hash_capacity (void *v) -{ - return vec_len (v); -} - -/* Returns 1 if the hash pair contains user data */ -always_inline uword -hash_is_user (void *v, uword i) -{ - hash_t *h = hash_header (v); - uword i0 = i / BITS (h->is_user[0]); - uword i1 = i % BITS (h->is_user[0]); - return (h->is_user[i0] & ((uword) 1 << i1)) != 0; -} - -/* Set the format function and format argument for a hash table */ -always_inline void -hash_set_pair_format (void *v, - format_function_t * format_pair, void *format_pair_arg) -{ - hash_t *h = hash_header (v); - h->format_pair = format_pair; - h->format_pair_arg = format_pair_arg; -} - -/* Set hash table flags */ -always_inline void -hash_set_flags (void *v, uword flags) -{ - hash_header (v)->flags |= flags; -} - -/* Key value pairs. */ -typedef struct -{ - /* The Key */ - uword key; - - /* The Value. Length is 2^log2_pair_size - 1. */ - uword value[0]; -} hash_pair_t; - -/* The indirect pair structure - - If log2_pair_size > 0 we overload hash pairs - with indirect pairs for buckets with more than one - pair. */ -typedef struct -{ - /* pair vector */ - hash_pair_t *pairs; - /* padding */ - u8 pad[sizeof (uword) - sizeof (hash_pair_t *)]; - /* allocated length */ - uword alloc_len; -} -hash_pair_indirect_t; - -/* Direct / Indirect pair union */ -typedef union -{ - hash_pair_t direct; - hash_pair_indirect_t indirect; -} hash_pair_union_t; - -#define LOG2_ALLOC_BITS (5) -#define PAIR_BITS (BITS (uword) - LOG2_ALLOC_BITS) - -/* Log2 number of bytes allocated in pairs array. */ -always_inline uword -indirect_pair_get_log2_bytes (hash_pair_indirect_t * p) -{ - return p->alloc_len >> PAIR_BITS; -} - -/* Get the length of an indirect pair */ -always_inline uword -indirect_pair_get_len (hash_pair_indirect_t * p) -{ - if (!p->pairs) - return 0; - else - return p->alloc_len & (((uword) 1 << PAIR_BITS) - 1); -} - -/* Set the length of an indirect pair */ -always_inline void -indirect_pair_set (hash_pair_indirect_t * p, uword log2_alloc, uword len) -{ - ASSERT (len < ((uword) 1 << PAIR_BITS)); - ASSERT (log2_alloc < ((uword) 1 << LOG2_ALLOC_BITS)); - p->alloc_len = (log2_alloc << PAIR_BITS) | len; -} - -/* internal routine to fetch value for given key */ -uword *_hash_get (void *v, uword key); - -/* internal routine to fetch value (key, value) pair for given key */ -hash_pair_t *_hash_get_pair (void *v, uword key); - -/* internal routine to unset a (key, value) pair */ -void *_hash_unset (void *v, uword key, void *old_value); - -/* internal routine to set a (key, value) pair, return the old value */ -void *_hash_set3 (void *v, uword key, void *value, void *old_value); - -/* Resize a hash table */ -void *hash_resize (void *old, uword new_size); - -/* duplicate a hash table */ -void *hash_dup (void *old); - -/* Returns the number of bytes used by a hash table */ -uword hash_bytes (void *v); - -/* Public macro to set a (key, value) pair, return the old value */ -#define hash_set3(h,key,value,old_value) \ -({ \ - uword _v = (uword) (value); \ - (h) = _hash_set3 ((h), (uword) (key), (void *) &_v, (old_value)); \ -}) - -/* Public macro to fetch value for given key */ -#define hash_get(h,key) _hash_get ((h), (uword) (key)) - -/* Public macro to fetch value (key, value) pair for given key */ -#define hash_get_pair(h,key) _hash_get_pair ((h), (uword) (key)) - -/* Public macro to set a (key, value) pair */ -#define hash_set(h,key,value) hash_set3(h,key,value,0) - -/* Public macro to set (key, 0) pair */ -#define hash_set1(h,key) (h) = _hash_set3(h,(uword) (key),0,0) - -/* Public macro to unset a (key, value) pair */ -#define hash_unset(h,key) ((h) = _hash_unset ((h), (uword) (key),0)) - -/* Public macro to unset a (key, value) pair, return the old value */ -#define hash_unset3(h,key,old_value) ((h) = _hash_unset ((h), (uword) (key), (void *) (old_value))) - -/* get/set/unset for pointer keys. */ - -/* Public macro to fetch value for given pointer key */ -#define hash_get_mem(h,key) _hash_get ((h), pointer_to_uword (key)) - -/* Public macro to fetch (key, value) for given pointer key */ -#define hash_get_pair_mem(h,key) _hash_get_pair ((h), pointer_to_uword (key)) - -/* Public macro to set (key, value) for pointer key */ -#define hash_set_mem(h,key,value) hash_set3 (h, pointer_to_uword (key), (value), 0) - -/* Public macro to set (key, 0) for pointer key */ -#define hash_set1_mem(h,key) hash_set3 ((h), pointer_to_uword (key), 0, 0) - -/* Public macro to unset (key, value) for pointer key */ -#define hash_unset_mem(h,key) ((h) = _hash_unset ((h), pointer_to_uword (key),0)) - -/* internal routine to free a hash table */ -extern void *_hash_free (void *v); - -/* Public macro to free a hash table */ -#define hash_free(h) (h) = _hash_free ((h)) - -clib_error_t *hash_validate (void *v); - -/* Public inline funcion to get the number of value bytes for a hash table */ -always_inline uword -hash_value_bytes (hash_t * h) -{ - hash_pair_t *p; - return (sizeof (p->value[0]) << h->log2_pair_size) - sizeof (p->key); -} - -/* Public inline funcion to get log2(size of a (key,value) pair) */ -always_inline uword -hash_pair_log2_bytes (hash_t * h) -{ - uword log2_bytes = h->log2_pair_size; - ASSERT (BITS (hash_pair_t) == 32 || BITS (hash_pair_t) == 64); - if (BITS (hash_pair_t) == 32) - log2_bytes += 2; - else if (BITS (hash_pair_t) == 64) - log2_bytes += 3; - return log2_bytes; -} - -/* Public inline funcion to get size of a (key,value) pair */ -always_inline uword -hash_pair_bytes (hash_t * h) -{ - return (uword) 1 << hash_pair_log2_bytes (h); -} - -/* Public inline funcion to advance a pointer past one (key,value) pair */ -always_inline void * -hash_forward1 (hash_t * h, void *v) -{ - return (u8 *) v + hash_pair_bytes (h); -} - -/* Public inline funcion to advance a pointer past N (key,value) pairs */ -always_inline void * -hash_forward (hash_t * h, void *v, uword n) -{ - return (u8 *) v + ((n * sizeof (hash_pair_t)) << h->log2_pair_size); -} - -/** Iterate over hash pairs. - - @param p The current (key,value) pair. This should be of type - <code>(hash_pair_t *)</code>. - @param v The hash table to iterate. - @param body The operation to perform on each (key,value) pair. - - Executes the expression or code block @c body with each active hash pair. -*/ -/* A previous version of this macro made use of the hash_pair_union_t - * structure; this version does not since that approach mightily upset - * the static analysis tool. In the rare chance someone is reading this - * code, pretend that _p below is of type hash_pair_union_t and that when - * used as an rvalue it's really using one of the union members as the - * rvalue. If you were confused before you might be marginally less - * confused after. - */ -#define hash_foreach_pair(p,v,body) \ -do { \ - __label__ _hash_foreach_done; \ - hash_t * _h = hash_header (v); \ - void * _p; \ - hash_pair_t * _q, * _q_end; \ - uword _i, _i1, _id, _pair_increment; \ - \ - _p = (v); \ - _i = 0; \ - _pair_increment = 1; \ - if ((v)) \ - _pair_increment = 1 << _h->log2_pair_size; \ - while (_i < hash_capacity (v)) \ - { \ - _id = _h->is_user[_i / BITS (_h->is_user[0])]; \ - _i1 = _i + BITS (_h->is_user[0]); \ - \ - do { \ - if (_id & 1) \ - { \ - _q = _p; \ - _q_end = _q + _pair_increment; \ - } \ - else \ - { \ - hash_pair_indirect_t * _pi = _p; \ - _q = _pi->pairs; \ - if (_h->log2_pair_size > 0) \ - _q_end = hash_forward (_h, _q, indirect_pair_get_len (_pi)); \ - else \ - _q_end = vec_end (_q); \ - } \ - \ - /* Loop through all elements in bucket. \ - Bucket may have 0 1 or more (indirect case) pairs. */ \ - while (_q < _q_end) \ - { \ - uword _break_in_body = 1; \ - (p) = _q; \ - do { \ - body; \ - _break_in_body = 0; \ - } while (0); \ - if (_break_in_body) \ - goto _hash_foreach_done; \ - _q += _pair_increment; \ - } \ - \ - _p = (hash_pair_t *)_p + _pair_increment; \ - _id = _id / 2; \ - _i++; \ - } while (_i < _i1); \ - } \ - _hash_foreach_done: \ - /* Be silent Mr. Compiler-Warning. */ \ - ; \ - } while (0) - -/* Iterate over key/value pairs - - @param key_var the current key - @param value_var the current value - @param h the hash table to iterate across - @param body the operation to perform on each (key_var,value_var) pair. - - calls body with each active hash pair -*/ -/* Iteratate over key/value pairs. */ -#define hash_foreach(key_var,value_var,h,body) \ -do { \ - hash_pair_t * _r; \ - hash_foreach_pair (_r, (h), { \ - (key_var) = (__typeof__ (key_var)) _r->key; \ - (value_var) = (__typeof__ (value_var)) _r->value[0]; \ - do { body; } while (0); \ - }); \ -} while (0) - -/* Iterate over key/value pairs for pointer key hash tables - - @param key_var the current key - @param value_var the current value - @param h the hash table to iterate across - @param body the operation to perform on each (key_var,value_var) pair. - - calls body with each active hash pair -*/ -#define hash_foreach_mem(key_var,value_var,h,body) \ -do { \ - hash_pair_t * _r; \ - hash_foreach_pair (_r, (h), { \ - (key_var) = (__typeof__ (key_var)) uword_to_pointer (_r->key, void *); \ - (value_var) = (__typeof__ (value_var)) _r->value[0]; \ - do { body; } while (0); \ - }); \ -} while (0) - -/* Support for iteration through hash table. */ - -/* This struct saves iteration state for hash_next. - None of these fields are meant to be visible to the user. - Hence, the cryptic short-hand names. */ -typedef struct -{ - uword i, j, f; -} hash_next_t; - -hash_pair_t *hash_next (void *v, hash_next_t * hn); - -void *_hash_create (uword elts, hash_t * h); - -always_inline void -hash_set_value_bytes (hash_t * h, uword value_bytes) -{ - hash_pair_t *p; - h->log2_pair_size = - max_log2 ((sizeof (p->key) + value_bytes + sizeof (p->key) - - 1) / sizeof (p->key)); -} - -#define hash_create2(_elts,_user,_value_bytes, \ - _key_sum,_key_equal, \ - _format_pair,_format_pair_arg) \ -({ \ - hash_t _h; \ - memset (&_h, 0, sizeof (_h)); \ - _h.user = (_user); \ - _h.key_sum = (hash_key_sum_function_t *) (_key_sum); \ - _h.key_equal = (_key_equal); \ - hash_set_value_bytes (&_h, (_value_bytes)); \ - _h.format_pair = (format_function_t *) (_format_pair); \ - _h.format_pair_arg = (_format_pair_arg); \ - _hash_create ((_elts), &_h); \ -}) - -/* Hash function based on that of Bob Jenkins (bob_jenkins@compuserve.com). - Public domain per: http://www.burtleburtle.net/bob/hash/doobs.html - Thanks, Bob. */ - -#define hash_mix_step(a,b,c,s0,s1,s2) \ -do { \ - (a) -= (b) + (c); (a) ^= (c) >> (s0); \ - (b) -= (c) + (a); (b) ^= (a) << (s1); \ - (c) -= (a) + (b); (c) ^= (b) >> (s2); \ -} while (0) - -#define hash_mix32_step_1(a,b,c) hash_mix_step(a,b,c,13,8,13) -#define hash_mix32_step_2(a,b,c) hash_mix_step(a,b,c,12,16,5) -#define hash_mix32_step_3(a,b,c) hash_mix_step(a,b,c,3,10,15) - -#define hash_mix64_step_1(a,b,c) hash_mix_step(a,b,c,43,9,8) -#define hash_mix64_step_2(a,b,c) hash_mix_step(a,b,c,38,23,5) -#define hash_mix64_step_3(a,b,c) hash_mix_step(a,b,c,35,49,11) -#define hash_mix64_step_4(a,b,c) hash_mix_step(a,b,c,12,18,22) - -/* Hash function based on that of Bob Jenkins (bob_jenkins@compuserve.com). - Thanks, Bob. */ -#define hash_mix64(a0,b0,c0) \ -do { \ - hash_mix64_step_1 (a0, b0, c0); \ - hash_mix64_step_2 (a0, b0, c0); \ - hash_mix64_step_3 (a0, b0, c0); \ - hash_mix64_step_4 (a0, b0, c0); \ -} while (0) \ - -#define hash_mix32(a0,b0,c0) \ -do { \ - hash_mix32_step_1 (a0, b0, c0); \ - hash_mix32_step_2 (a0, b0, c0); \ - hash_mix32_step_3 (a0, b0, c0); \ -} while (0) \ - -/* Finalize from Bob Jenkins lookup3.c */ - -always_inline uword -hash32_rotate_left (u32 x, u32 i) -{ - return (x << i) | (x >> (BITS (i) - i)); -} - -#define hash_v3_mix32(a,b,c) \ -do { \ - (a) -= (c); (a) ^= hash32_rotate_left ((c), 4); (c) += (b); \ - (b) -= (a); (b) ^= hash32_rotate_left ((a), 6); (a) += (c); \ - (c) -= (b); (c) ^= hash32_rotate_left ((b), 8); (b) += (a); \ - (a) -= (c); (a) ^= hash32_rotate_left ((c),16); (c) += (b); \ - (b) -= (a); (b) ^= hash32_rotate_left ((a),19); (a) += (c); \ - (c) -= (b); (c) ^= hash32_rotate_left ((b), 4); (b) += (a); \ -} while (0) - -#define hash_v3_finalize32(a,b,c) \ -do { \ - (c) ^= (b); (c) -= hash32_rotate_left ((b), 14); \ - (a) ^= (c); (a) -= hash32_rotate_left ((c), 11); \ - (b) ^= (a); (b) -= hash32_rotate_left ((a), 25); \ - (c) ^= (b); (c) -= hash32_rotate_left ((b), 16); \ - (a) ^= (c); (a) -= hash32_rotate_left ((c), 4); \ - (b) ^= (a); (b) -= hash32_rotate_left ((a), 14); \ - (c) ^= (b); (c) -= hash32_rotate_left ((b), 24); \ -} while (0) - -/* 32 bit mixing/finalize in steps. */ - -#define hash_v3_mix32_step1(a,b,c) \ -do { \ - (a) -= (c); (a) ^= hash32_rotate_left ((c), 4); (c) += (b); \ - (b) -= (a); (b) ^= hash32_rotate_left ((a), 6); (a) += (c); \ -} while (0) - -#define hash_v3_mix32_step2(a,b,c) \ -do { \ - (c) -= (b); (c) ^= hash32_rotate_left ((b), 8); (b) += (a); \ - (a) -= (c); (a) ^= hash32_rotate_left ((c),16); (c) += (b); \ -} while (0) - -#define hash_v3_mix32_step3(a,b,c) \ -do { \ - (b) -= (a); (b) ^= hash32_rotate_left ((a),19); (a) += (c); \ - (c) -= (b); (c) ^= hash32_rotate_left ((b), 4); (b) += (a); \ -} while (0) - -#define hash_v3_finalize32_step1(a,b,c) \ -do { \ - (c) ^= (b); (c) -= hash32_rotate_left ((b), 14); \ - (a) ^= (c); (a) -= hash32_rotate_left ((c), 11); \ -} while (0) - -#define hash_v3_finalize32_step2(a,b,c) \ -do { \ - (b) ^= (a); (b) -= hash32_rotate_left ((a), 25); \ - (c) ^= (b); (c) -= hash32_rotate_left ((b), 16); \ -} while (0) - -#define hash_v3_finalize32_step3(a,b,c) \ -do { \ - (a) ^= (c); (a) -= hash32_rotate_left ((c), 4); \ - (b) ^= (a); (b) -= hash32_rotate_left ((a), 14); \ - (c) ^= (b); (c) -= hash32_rotate_left ((b), 24); \ -} while (0) - -/* Vector v3 mixing/finalize. */ -#define hash_v3_mix_step_1_u32x(a,b,c) \ -do { \ - (a) -= (c); (a) ^= u32x_irotate_left ((c), 4); (c) += (b); \ - (b) -= (a); (b) ^= u32x_irotate_left ((a), 6); (a) += (c); \ - (c) -= (b); (c) ^= u32x_irotate_left ((b), 8); (b) += (a); \ -} while (0) - -#define hash_v3_mix_step_2_u32x(a,b,c) \ -do { \ - (a) -= (c); (a) ^= u32x_irotate_left ((c),16); (c) += (b); \ - (b) -= (a); (b) ^= u32x_irotate_left ((a),19); (a) += (c); \ - (c) -= (b); (c) ^= u32x_irotate_left ((b), 4); (b) += (a); \ -} while (0) - -#define hash_v3_finalize_step_1_u32x(a,b,c) \ -do { \ - (c) ^= (b); (c) -= u32x_irotate_left ((b), 14); \ - (a) ^= (c); (a) -= u32x_irotate_left ((c), 11); \ - (b) ^= (a); (b) -= u32x_irotate_left ((a), 25); \ -} while (0) - -#define hash_v3_finalize_step_2_u32x(a,b,c) \ -do { \ - (c) ^= (b); (c) -= u32x_irotate_left ((b), 16); \ - (a) ^= (c); (a) -= u32x_irotate_left ((c), 4); \ - (b) ^= (a); (b) -= u32x_irotate_left ((a), 14); \ - (c) ^= (b); (c) -= u32x_irotate_left ((b), 24); \ -} while (0) - -#define hash_v3_mix_u32x(a,b,c) \ -do { \ - hash_v3_mix_step_1_u32x(a,b,c); \ - hash_v3_mix_step_2_u32x(a,b,c); \ -} while (0) - -#define hash_v3_finalize_u32x(a,b,c) \ -do { \ - hash_v3_finalize_step_1_u32x(a,b,c); \ - hash_v3_finalize_step_2_u32x(a,b,c); \ -} while (0) - -extern uword hash_memory (void *p, word n_bytes, uword state); - -extern uword mem_key_sum (hash_t * h, uword key); -extern uword mem_key_equal (hash_t * h, uword key1, uword key2); - -#define hash_create_mem(elts,key_bytes,value_bytes) \ - hash_create2((elts),(key_bytes),(value_bytes),mem_key_sum,mem_key_equal,0,0) - -extern uword vec_key_sum (hash_t * h, uword key); -extern uword vec_key_equal (hash_t * h, uword key1, uword key2); -extern u8 *vec_key_format_pair (u8 * s, va_list * args); - -#define hash_create_vec(elts,key_bytes,value_bytes) \ - hash_create2((elts),(key_bytes),(value_bytes),\ - vec_key_sum,vec_key_equal,vec_key_format_pair,0) - -extern uword string_key_sum (hash_t * h, uword key); -extern uword string_key_equal (hash_t * h, uword key1, uword key2); -extern u8 *string_key_format_pair (u8 * s, va_list * args); - -#define hash_create_string(elts,value_bytes) \ - hash_create2((elts),0,(value_bytes), \ - (hash_key_sum_function_t *) KEY_FUNC_STRING, \ - (hash_key_equal_function_t *)KEY_FUNC_STRING, \ - 0, 0) - -#define hash_create(elts,value_bytes) \ - hash_create2((elts),0,(value_bytes), \ - (hash_key_sum_function_t *) KEY_FUNC_NONE, \ - (hash_key_equal_function_t *) KEY_FUNC_NONE, \ - 0,0) - -#define hash_create_uword(elts,value_bytes) \ - hash_create2((elts),0,(value_bytes), \ - (hash_key_sum_function_t *) KEY_FUNC_POINTER_UWORD, \ - (hash_key_equal_function_t *) KEY_FUNC_POINTER_UWORD, \ - 0,0) - -#define hash_create_u32(elts,value_bytes) \ - hash_create2((elts),0,(value_bytes), \ - (hash_key_sum_function_t *) KEY_FUNC_POINTER_U32, \ - (hash_key_equal_function_t *) KEY_FUNC_POINTER_U32, \ - 0,0) - -u8 *format_hash (u8 * s, va_list * va); - -/* Looks up input in hash table indexed by either vec string or - c string (null terminated). */ -unformat_function_t unformat_hash_vec_string; -unformat_function_t unformat_hash_string; - -/* Main test routine. */ -int test_hash_main (unformat_input_t * input); - -static inline void -hash_delete (void *bob) -{ -} - -#endif /* included_hash_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/heap.c b/vppinfra/vppinfra/heap.c deleted file mode 100644 index 2a5fb5c8d8e..00000000000 --- a/vppinfra/vppinfra/heap.c +++ /dev/null @@ -1,828 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include <vppinfra/cache.h> /* for CLIB_CACHE_LINE_BYTES */ -#include <vppinfra/mem.h> -#include <vppinfra/hash.h> -#include <vppinfra/vec.h> -#include <vppinfra/heap.h> -#include <vppinfra/error.h> - -always_inline heap_elt_t * -elt_at (heap_header_t * h, uword i) -{ - ASSERT (i < vec_len (h->elts)); - return h->elts + i; -} - -always_inline heap_elt_t * -last (heap_header_t * h) -{ - return elt_at (h, h->tail); -} - -always_inline heap_elt_t * -first (heap_header_t * h) -{ - return elt_at (h, h->head); -} - -/* Objects sizes are binned into N_BINS bins. - Objects with size <= SMALL_BINS have their own bins. - Larger objects are grouped together in power or 2 sized - bins. - - Sizes are in units of elt_bytes bytes. */ - -/* Convert size to bin. */ -always_inline uword -size_to_bin (uword size) -{ - uword bin; - - ASSERT (size > 0); - - if (size <= HEAP_SMALL_BINS) - { - bin = size - 1; - if (size == 0) - bin = 0; - } - else - { - bin = HEAP_SMALL_BINS + max_log2 (size) - (HEAP_LOG2_SMALL_BINS + 1); - if (bin >= HEAP_N_BINS) - bin = HEAP_N_BINS - 1; - } - - return bin; -} - -/* Convert bin to size. */ -always_inline __attribute__ ((unused)) - uword bin_to_size (uword bin) -{ - uword size; - - if (bin <= HEAP_SMALL_BINS - 1) - size = bin + 1; - else - size = (uword) 1 << ((bin - HEAP_SMALL_BINS) + HEAP_LOG2_SMALL_BINS + 1); - - return size; -} - -static void -elt_delete (heap_header_t * h, heap_elt_t * e) -{ - heap_elt_t *l = vec_end (h->elts) - 1; - - ASSERT (e >= h->elts && e <= l); - - /* Update doubly linked pointers. */ - { - heap_elt_t *p = heap_prev (e); - heap_elt_t *n = heap_next (e); - - if (p == e) - { - n->prev = 0; - h->head = n - h->elts; - } - else if (n == e) - { - p->next = 0; - h->tail = p - h->elts; - } - else - { - p->next = n - p; - n->prev = p - n; - } - } - - /* Add to index free list or delete from end. */ - if (e < l) - vec_add1 (h->free_elts, e - h->elts); - else - _vec_len (h->elts)--; -} - -/* - Before: P ... E - After : P ... NEW ... E -*/ -always_inline void -elt_insert_before (heap_header_t * h, heap_elt_t * e, heap_elt_t * new) -{ - heap_elt_t *p = heap_prev (e); - - if (p == e) - { - new->prev = 0; - new->next = e - new; - p->prev = new - p; - h->head = new - h->elts; - } - else - { - new->prev = p - new; - new->next = e - new; - e->prev = new - e; - p->next = new - p; - } -} - -/* - Before: E ... N - After : E ... NEW ... N -*/ -always_inline void -elt_insert_after (heap_header_t * h, heap_elt_t * e, heap_elt_t * new) -{ - heap_elt_t *n = heap_next (e); - - if (n == e) - { - new->next = 0; - new->prev = e - new; - e->next = new - e; - h->tail = new - h->elts; - } - else - { - new->prev = e - new; - new->next = n - new; - e->next = new - e; - n->prev = new - n; - } -} - -always_inline heap_elt_t * -elt_new (heap_header_t * h) -{ - heap_elt_t *e; - uword l; - if ((l = vec_len (h->free_elts)) > 0) - { - e = elt_at (h, h->free_elts[l - 1]); - _vec_len (h->free_elts) -= 1; - } - else - vec_add2 (h->elts, e, 1); - return e; -} - -/* Return pointer to object at given offset. - Used to write free list index of free objects. */ -always_inline u32 * -elt_data (void *v, heap_elt_t * e) -{ - heap_header_t *h = heap_header (v); - return v + heap_offset (e) * h->elt_bytes; -} - -always_inline void -set_free_elt (void *v, heap_elt_t * e, uword fi) -{ - heap_header_t *h = heap_header (v); - - e->offset |= HEAP_ELT_FREE_BIT; - if (h->elt_bytes >= sizeof (u32)) - { - *elt_data (v, e) = fi; - } - else - { - /* For elt_bytes < 4 we must store free index in separate - vector. */ - uword elt_index = e - h->elts; - vec_validate (h->small_free_elt_free_index, elt_index); - h->small_free_elt_free_index[elt_index] = fi; - } -} - -always_inline uword -get_free_elt (void *v, heap_elt_t * e, uword * bin_result) -{ - heap_header_t *h = heap_header (v); - uword fb, fi; - - ASSERT (heap_is_free (e)); - fb = size_to_bin (heap_elt_size (v, e)); - - if (h->elt_bytes >= sizeof (u32)) - { - fi = *elt_data (v, e); - } - else - { - uword elt_index = e - h->elts; - fi = vec_elt (h->small_free_elt_free_index, elt_index); - } - - *bin_result = fb; - return fi; -} - -always_inline void -remove_free_block (void *v, uword b, uword i) -{ - heap_header_t *h = heap_header (v); - uword l; - - ASSERT (b < vec_len (h->free_lists)); - ASSERT (i < vec_len (h->free_lists[b])); - - l = vec_len (h->free_lists[b]); - - if (i < l - 1) - { - uword t = h->free_lists[b][l - 1]; - h->free_lists[b][i] = t; - set_free_elt (v, elt_at (h, t), i); - } - _vec_len (h->free_lists[b]) = l - 1; -} - -static heap_elt_t * -search_free_list (void *v, uword size) -{ - heap_header_t *h = heap_header (v); - heap_elt_t *f, *u; - uword b, fb, f_size, f_index; - word s, l; - - if (!v) - return 0; - - /* Search free lists for bins >= given size. */ - for (b = size_to_bin (size); b < vec_len (h->free_lists); b++) - if ((l = vec_len (h->free_lists[b])) > 0) - { - /* Find an object that is large enough. - Search list in reverse so that more recently freed objects will be - allocated again sooner. */ - do - { - l--; - f_index = h->free_lists[b][l]; - f = elt_at (h, f_index); - f_size = heap_elt_size (v, f); - if ((s = f_size - size) >= 0) - break; - } - while (l >= 0); - - /* If we fail to find a large enough object, try the next larger size. */ - if (l < 0) - continue; - - ASSERT (heap_is_free (f)); - - /* Link in used object (u) after free object (f). */ - if (s == 0) - { - u = f; - fb = HEAP_N_BINS; - } - else - { - u = elt_new (h); - f = elt_at (h, f_index); - elt_insert_after (h, f, u); - fb = size_to_bin (s); - } - - u->offset = heap_offset (f) + s; - - if (fb != b) - { - if (fb < HEAP_N_BINS) - { - uword i; - vec_validate (h->free_lists, fb); - i = vec_len (h->free_lists[fb]); - vec_add1 (h->free_lists[fb], f - h->elts); - set_free_elt (v, f, i); - } - - remove_free_block (v, b, l); - } - - return u; - } - - return 0; -} - -static void combine_free_blocks (void *v, heap_elt_t * e0, heap_elt_t * e1); - -static inline void -dealloc_elt (void *v, heap_elt_t * e) -{ - heap_header_t *h = heap_header (v); - uword b, l; - heap_elt_t *n, *p; - - b = size_to_bin (heap_elt_size (v, e)); - vec_validate (h->free_lists, b); - l = vec_len (h->free_lists[b]); - vec_add1 (h->free_lists[b], e - h->elts); - set_free_elt (v, e, l); - - /* See if we can combine the block we just freed with neighboring free blocks. */ - p = heap_prev (e); - if (!heap_is_free (p)) - p = e; - - n = heap_next (e); - if (!heap_is_free (n)) - n = e; - - if (p != n) - combine_free_blocks (v, p, n); -} - -void * -_heap_alloc (void *v, - uword size, - uword align, - uword elt_bytes, uword * offset_return, uword * handle_return) -{ - uword offset = 0, align_size; - heap_header_t *h; - heap_elt_t *e; - - if (size == 0) - goto error; - - /* Round up alignment to power of 2. */ - if (align <= 1) - { - align = 0; - align_size = size; - } - else - { - align = max_pow2 (align); - align_size = size + align - 1; - } - - e = search_free_list (v, align_size); - - /* If nothing found on free list, allocate object from end of vector. */ - if (!e) - { - uword max_len; - - offset = vec_len (v); - max_len = heap_get_max_len (v); - - if (max_len && offset + align_size > max_len) - goto error; - - h = heap_header (v); - if (!v || !(h->flags & HEAP_IS_STATIC)) - v = _vec_resize (v, - align_size, - (offset + align_size) * elt_bytes, - sizeof (h[0]), HEAP_DATA_ALIGN); - else - _vec_len (v) += align_size; - - if (offset == 0) - { - h = heap_header (v); - h->elt_bytes = elt_bytes; - } - } - - h = heap_header (v); - - /* Add new element to doubly linked chain of elements. */ - if (!e) - { - e = elt_new (h); - e->offset = offset; - elt_insert_after (h, last (h), e); - } - - if (align > 0) - { - uword e_index; - uword new_offset, old_offset; - - old_offset = e->offset; - new_offset = (old_offset + align - 1) & ~(align - 1); - e->offset = new_offset; - e_index = e - h->elts; - - /* Free fragments before and after aligned object. */ - if (new_offset > old_offset) - { - heap_elt_t *before_e = elt_new (h); - before_e->offset = old_offset; - elt_insert_before (h, h->elts + e_index, before_e); - dealloc_elt (v, before_e); - } - - if (new_offset + size < old_offset + align_size) - { - heap_elt_t *after_e = elt_new (h); - after_e->offset = new_offset + size; - elt_insert_after (h, h->elts + e_index, after_e); - dealloc_elt (v, after_e); - } - - e = h->elts + e_index; - } - - h->used_count++; - - /* Keep track of used elements when debugging. - This allows deallocation to check that passed objects are valid. */ - if (CLIB_DEBUG > 0) - { - uword handle = e - h->elts; - ASSERT (!clib_bitmap_get (h->used_elt_bitmap, handle)); - h->used_elt_bitmap = clib_bitmap_ori (h->used_elt_bitmap, handle); - } - - *offset_return = e->offset; - *handle_return = e - h->elts; - return v; - -error: - *offset_return = *handle_return = ~0; - return v; -} - -void -heap_dealloc (void *v, uword handle) -{ - heap_header_t *h = heap_header (v); - heap_elt_t *e; - - ASSERT (handle < vec_len (h->elts)); - - /* For debugging we keep track of indices for valid objects. - We make sure user is not trying to free object with an invalid index. */ - if (CLIB_DEBUG > 0) - { - ASSERT (clib_bitmap_get (h->used_elt_bitmap, handle)); - h->used_elt_bitmap = clib_bitmap_andnoti (h->used_elt_bitmap, handle); - } - - h->used_count--; - - e = h->elts + handle; - ASSERT (!heap_is_free (e)); - - dealloc_elt (v, e); -} - -/* While freeing objects at INDEX we noticed free blocks i0 <= index and - i1 >= index. We combine these two or three blocks into one big free block. */ -static void -combine_free_blocks (void *v, heap_elt_t * e0, heap_elt_t * e1) -{ - heap_header_t *h = heap_header (v); - uword total_size, i, b, tb, ti, i_last, g_offset; - heap_elt_t *e; - - struct - { - u32 index; - u32 bin; - u32 bin_index; - } f[3], g; - - /* Compute total size of free objects i0 through i1. */ - total_size = 0; - for (i = 0, e = e0; 1; e = heap_next (e), i++) - { - ASSERT (i < ARRAY_LEN (f)); - - ti = get_free_elt (v, e, &tb); - - ASSERT (tb < vec_len (h->free_lists)); - ASSERT (ti < vec_len (h->free_lists[tb])); - - f[i].index = h->free_lists[tb][ti]; - f[i].bin = tb; - f[i].bin_index = ti; - - total_size += heap_elt_size (v, elt_at (h, f[i].index)); - - if (e == e1) - { - i_last = i; - break; - } - } - - /* Compute combined bin. See if all objects can be - combined into existing bin. */ - b = size_to_bin (total_size); - g.index = g.bin_index = 0; - for (i = 0; i <= i_last; i++) - if (b == f[i].bin) - { - g = f[i]; - break; - } - - /* Make sure we found a bin. */ - if (i > i_last) - { - g.index = elt_new (h) - h->elts; - vec_validate (h->free_lists, b); - g.bin_index = vec_len (h->free_lists[b]); - vec_add1 (h->free_lists[b], g.index); - elt_insert_before (h, elt_at (h, f[0].index), elt_at (h, g.index)); - } - - g_offset = elt_at (h, f[0].index)->offset; - - /* Delete unused bins. */ - for (i = 0; i <= i_last; i++) - if (g.index != f[i].index) - { - ti = get_free_elt (v, elt_at (h, f[i].index), &tb); - remove_free_block (v, tb, ti); - elt_delete (h, elt_at (h, f[i].index)); - } - - /* Initialize new element. */ - elt_at (h, g.index)->offset = g_offset; - set_free_elt (v, elt_at (h, g.index), g.bin_index); -} - -uword -heap_len (void *v, word handle) -{ - heap_header_t *h = heap_header (v); - - if (CLIB_DEBUG > 0) - ASSERT (clib_bitmap_get (h->used_elt_bitmap, handle)); - return heap_elt_size (v, elt_at (h, handle)); -} - -void * -_heap_free (void *v) -{ - heap_header_t *h = heap_header (v); - uword b; - - if (!v) - return v; - - clib_bitmap_free (h->used_elt_bitmap); - for (b = 0; b < vec_len (h->free_lists); b++) - vec_free (h->free_lists[b]); - vec_free (h->free_lists); - vec_free (h->elts); - vec_free (h->free_elts); - vec_free (h->small_free_elt_free_index); - if (!(h->flags & HEAP_IS_STATIC)) - vec_free_h (v, sizeof (h[0])); - return v; -} - -uword -heap_bytes (void *v) -{ - heap_header_t *h = heap_header (v); - uword bytes, b; - - if (!v) - return 0; - - bytes = sizeof (h[0]); - bytes += vec_len (v) * sizeof (h->elt_bytes); - for (b = 0; b < vec_len (h->free_lists); b++) - bytes += vec_capacity (h->free_lists[b], 0); - bytes += vec_bytes (h->free_lists); - bytes += vec_capacity (h->elts, 0); - bytes += vec_capacity (h->free_elts, 0); - bytes += vec_bytes (h->used_elt_bitmap); - - return bytes; -} - -static u8 * -debug_elt (u8 * s, void *v, word i, word n) -{ - heap_elt_t *e, *e0, *e1; - heap_header_t *h = heap_header (v); - word j; - - if (vec_len (h->elts) == 0) - return s; - - if (i < 0) - e0 = first (h); - else - { - e0 = h->elts + i; - for (j = 0; j < n / 2; j++) - e0 = heap_prev (e0); - } - - if (n < 0) - e1 = h->elts + h->tail; - else - { - e1 = h->elts + i; - for (j = 0; j < n / 2; j++) - e1 = heap_next (e1); - } - - i = -n / 2; - for (e = e0; 1; e = heap_next (e)) - { - if (heap_is_free (e)) - s = format (s, "index %4d, free\n", e - h->elts); - else if (h->format_elt) - s = format (s, "%U", h->format_elt, v, elt_data (v, e)); - else - s = format (s, "index %4d, used\n", e - h->elts); - i++; - if (e == e1) - break; - } - - return s; -} - -u8 * -format_heap (u8 * s, va_list * va) -{ - void *v = va_arg (*va, void *); - uword verbose = va_arg (*va, uword); - heap_header_t *h = heap_header (v); - heap_header_t zero; - - memset (&zero, 0, sizeof (zero)); - - if (!v) - h = &zero; - - { - f64 elt_bytes = vec_len (v) * h->elt_bytes; - f64 overhead_bytes = heap_bytes (v); - - s = format (s, "heap %p, %6d objects, size %.1fk + overhead %.1fk\n", - v, h->used_count, elt_bytes / 1024, - (overhead_bytes - elt_bytes) / 1024); - } - - if (v && verbose) - s = debug_elt (s, v, -1, -1); - - return s; -} - -void -heap_validate (void *v) -{ - heap_header_t *h = heap_header (v); - uword i, o, s; - u8 *free_map; - heap_elt_t *e, *n; - - uword used_count, total_size; - uword free_count, free_size; - - ASSERT (h->used_count == clib_bitmap_count_set_bits (h->used_elt_bitmap)); - - ASSERT (first (h)->prev == 0); - ASSERT (last (h)->next == 0); - - /* Validate number of elements and size. */ - free_size = free_count = 0; - for (i = 0; i < vec_len (h->free_lists); i++) - { - free_count += vec_len (h->free_lists[i]); - for (o = 0; o < vec_len (h->free_lists[i]); o++) - { - e = h->elts + h->free_lists[i][o]; - s = heap_elt_size (v, e); - ASSERT (size_to_bin (s) == i); - ASSERT (heap_is_free (e)); - free_size += s; - } - } - - { - uword elt_free_size, elt_free_count; - - used_count = total_size = elt_free_size = elt_free_count = 0; - for (e = first (h); 1; e = n) - { - int is_free = heap_is_free (e); - used_count++; - s = heap_elt_size (v, e); - total_size += s; - ASSERT (is_free == - !clib_bitmap_get (h->used_elt_bitmap, e - h->elts)); - if (is_free) - { - elt_free_count++; - elt_free_size += s; - } - n = heap_next (e); - if (e == n) - { - ASSERT (last (h) == n); - break; - } - - /* We should never have two free adjacent elements. */ - ASSERT (!(heap_is_free (e) && heap_is_free (n))); - } - - ASSERT (free_count == elt_free_count); - ASSERT (free_size == elt_free_size); - ASSERT (used_count == h->used_count + free_count); - ASSERT (total_size == vec_len (v)); - } - - free_map = vec_new (u8, used_count); - - e = first (h); - for (i = o = 0; 1; i++) - { - ASSERT (heap_offset (e) == o); - s = heap_elt_size (v, e); - - if (heap_is_free (e)) - { - uword fb, fi; - - fi = get_free_elt (v, e, &fb); - - ASSERT (fb < vec_len (h->free_lists)); - ASSERT (fi < vec_len (h->free_lists[fb])); - ASSERT (h->free_lists[fb][fi] == e - h->elts); - - ASSERT (!free_map[i]); - free_map[i] = 1; - } - - n = heap_next (e); - - if (e == n) - break; - - ASSERT (heap_prev (n) == e); - - o += s; - e = n; - } - - vec_free (free_map); -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/heap.h b/vppinfra/vppinfra/heap.h deleted file mode 100644 index 8c1aae46ebf..00000000000 --- a/vppinfra/vppinfra/heap.h +++ /dev/null @@ -1,357 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -/* Heaps of objects of type T (e.g. int, struct foo, ...). - - Usage. To declare a null heap: - - T * heap = 0; - - To allocate: - - offset = heap_alloc (heap, size, handle); - - New object is heap[offset] ... heap[offset + size] - Handle is used to free/query object. - - To free object: - - heap_dealloc (heap, handle); - - To query the size of an object: - - heap_size (heap, handle) - -*/ - -#ifndef included_heap_h -#define included_heap_h - -#include <vppinfra/clib.h> -#include <vppinfra/cache.h> -#include <vppinfra/hash.h> -#include <vppinfra/format.h> -#include <vppinfra/bitmap.h> - -/* Doubly linked list of elements. */ -typedef struct -{ - /* Offset of this element (plus free bit). - If element is free, data at offset contains pointer to free list. */ - u32 offset; - - /* Index of next and previous elements relative to current element. */ - i32 next, prev; -} heap_elt_t; - -/* Use high bit of offset as free bit. */ -#define HEAP_ELT_FREE_BIT (1 << 31) - -always_inline uword -heap_is_free (heap_elt_t * e) -{ - return (e->offset & HEAP_ELT_FREE_BIT) != 0; -} - -always_inline uword -heap_offset (heap_elt_t * e) -{ - return e->offset & ~HEAP_ELT_FREE_BIT; -} - -always_inline heap_elt_t * -heap_next (heap_elt_t * e) -{ - return e + e->next; -} - -always_inline heap_elt_t * -heap_prev (heap_elt_t * e) -{ - return e + e->prev; -} - -always_inline uword -heap_elt_size (void *v, heap_elt_t * e) -{ - heap_elt_t *n = heap_next (e); - uword next_offset = n != e ? heap_offset (n) : vec_len (v); - return next_offset - heap_offset (e); -} - -/* Sizes are binned. Sizes 1 to 2^log2_small_bins have their - own free lists. Larger sizes are grouped in powers of two. */ -#define HEAP_LOG2_SMALL_BINS (5) -#define HEAP_SMALL_BINS (1 << HEAP_LOG2_SMALL_BINS) -#define HEAP_N_BINS (2 * HEAP_SMALL_BINS) - -/* Header for heaps. */ -typedef struct -{ - /* Vector of used and free elements. */ - heap_elt_t *elts; - - /* For elt_bytes < sizeof (u32) we need some extra space - per elt to store free list index. */ - u32 *small_free_elt_free_index; - - /* Vector of free indices of elts array. */ - u32 *free_elts; - - /* Indices of free elts indexed by size bin. */ - u32 **free_lists; - - format_function_t *format_elt; - - /* Used for validattion/debugging. */ - uword *used_elt_bitmap; - - /* First and last element of doubly linked chain of elements. */ - u32 head, tail; - - u32 used_count, max_len; - - /* Number of bytes in a help element. */ - u32 elt_bytes; - - u32 flags; - /* Static heaps are made from external memory given to - us by user and are not re-sizeable vectors. */ -#define HEAP_IS_STATIC (1) -} heap_header_t; - -/* Start of heap elements is always cache aligned. */ -#define HEAP_DATA_ALIGN (CLIB_CACHE_LINE_BYTES) - -always_inline heap_header_t * -heap_header (void *v) -{ - return vec_header (v, sizeof (heap_header_t)); -} - -always_inline uword -heap_header_bytes () -{ - return vec_header_bytes (sizeof (heap_header_t)); -} - -always_inline void -heap_dup_header (heap_header_t * old, heap_header_t * new) -{ - uword i; - - new[0] = old[0]; - new->elts = vec_dup (new->elts); - new->free_elts = vec_dup (new->free_elts); - new->free_lists = vec_dup (new->free_lists); - for (i = 0; i < vec_len (new->free_lists); i++) - new->free_lists[i] = vec_dup (new->free_lists[i]); - new->used_elt_bitmap = clib_bitmap_dup (new->used_elt_bitmap); - new->small_free_elt_free_index = vec_dup (new->small_free_elt_free_index); -} - -/* Make a duplicate copy of a heap. */ -#define heap_dup(v) _heap_dup(v, vec_len (v) * sizeof (v[0])) - -always_inline void * -_heap_dup (void *v_old, uword v_bytes) -{ - heap_header_t *h_old, *h_new; - void *v_new; - - h_old = heap_header (v_old); - - if (!v_old) - return v_old; - - v_new = 0; - v_new = - _vec_resize (v_new, _vec_len (v_old), v_bytes, sizeof (heap_header_t), - HEAP_DATA_ALIGN); - h_new = heap_header (v_new); - heap_dup_header (h_old, h_new); - clib_memcpy (v_new, v_old, v_bytes); - return v_new; -} - -always_inline uword -heap_elts (void *v) -{ - heap_header_t *h = heap_header (v); - return h->used_count; -} - -uword heap_bytes (void *v); - -always_inline void * -_heap_new (u32 len, u32 n_elt_bytes) -{ - void *v = _vec_resize (0, len, (uword) len * n_elt_bytes, - sizeof (heap_header_t), - HEAP_DATA_ALIGN); - heap_header (v)->elt_bytes = n_elt_bytes; - return v; -} - -#define heap_new(v) (v) = _heap_new (0, sizeof ((v)[0])) - -always_inline void -heap_set_format (void *v, format_function_t * format_elt) -{ - ASSERT (v); - heap_header (v)->format_elt = format_elt; -} - -always_inline void -heap_set_max_len (void *v, uword max_len) -{ - ASSERT (v); - heap_header (v)->max_len = max_len; -} - -always_inline uword -heap_get_max_len (void *v) -{ - return v ? heap_header (v)->max_len : 0; -} - -/* Create fixed size heap with given block of memory. */ -always_inline void * -heap_create_from_memory (void *memory, uword max_len, uword elt_bytes) -{ - heap_header_t *h; - void *v; - - if (max_len * elt_bytes < sizeof (h[0])) - return 0; - - h = memory; - memset (h, 0, sizeof (h[0])); - h->max_len = max_len; - h->elt_bytes = elt_bytes; - h->flags = HEAP_IS_STATIC; - - v = (void *) (memory + heap_header_bytes ()); - _vec_len (v) = 0; - return v; -} - -/* Execute BODY for each allocated heap element. */ -#define heap_foreach(var,len,heap,body) \ -do { \ - if (vec_len (heap) > 0) \ - { \ - heap_header_t * _h = heap_header (heap); \ - heap_elt_t * _e = _h->elts + _h->head; \ - heap_elt_t * _end = _h->elts + _h->tail; \ - while (1) \ - { \ - if (! heap_is_free (_e)) \ - { \ - (var) = (heap) + heap_offset (_e); \ - (len) = heap_elt_size ((heap), _e); \ - do { body; } while (0); \ - } \ - if (_e == _end) \ - break; \ - _e = heap_next (_e); \ - } \ - } \ -} while (0) - -#define heap_elt_at_index(v,index) vec_elt_at_index(v,index) - -always_inline heap_elt_t * -heap_get_elt (void *v, uword handle) -{ - heap_header_t *h = heap_header (v); - heap_elt_t *e = vec_elt_at_index (h->elts, handle); - ASSERT (!heap_is_free (e)); - return e; -} - -#define heap_elt_with_handle(v,handle) \ -({ \ - heap_elt_t * _e = heap_get_elt ((v), (handle)); \ - (v) + heap_offset (_e); \ -}) - -always_inline uword -heap_is_free_handle (void *v, uword heap_handle) -{ - heap_header_t *h = heap_header (v); - heap_elt_t *e = vec_elt_at_index (h->elts, heap_handle); - return heap_is_free (e); -} - -extern uword heap_len (void *v, word handle); - -/* Low level allocation call. */ -extern void *_heap_alloc (void *v, uword size, uword alignment, - uword elt_bytes, uword * offset, uword * handle); - -#define heap_alloc_aligned(v,size,align,handle) \ -({ \ - uword _o, _h; \ - uword _a = (align); \ - uword _s = (size); \ - (v) = _heap_alloc ((v), _s, _a, sizeof ((v)[0]), &_o, &_h); \ - (handle) = _h; \ - _o; \ -}) - -#define heap_alloc(v,size,handle) heap_alloc_aligned((v),(size),0,(handle)) - -extern void heap_dealloc (void *v, uword handle); -extern void heap_validate (void *v); - -/* Format heap internal data structures as string. */ -extern u8 *format_heap (u8 * s, va_list * va); - -void *_heap_free (void *v); - -#define heap_free(v) (v)=_heap_free(v) - -#endif /* included_heap_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/longjmp.S b/vppinfra/vppinfra/longjmp.S deleted file mode 100644 index d4dd4c7d916..00000000000 --- a/vppinfra/vppinfra/longjmp.S +++ /dev/null @@ -1,690 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2005 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#if defined(__x86_64__) - .global clib_setjmp - .align 4 - .type clib_setjmp, @function -clib_setjmp: - movq %rbx, 8*0(%rdi) - movq %rbp, 8*1(%rdi) - movq %r12, 8*2(%rdi) - movq %r13, 8*3(%rdi) - movq %r14, 8*4(%rdi) - movq %r15, 8*5(%rdi) - - /* Save SP after return. */ - leaq 8(%rsp), %rdx - movq %rdx, 8*6(%rdi) - - /* Save PC we are returning to from stack frame. */ - movq 0(%rsp), %rax - movq %rax, 8*7(%rdi) - - /* Give back user's return value. */ - movq %rsi, %rax - ret - - .global clib_longjmp - .align 4 - .type clib_longjmp, @function -clib_longjmp: - /* Restore regs. */ - movq 8*0(%rdi), %rbx - movq 8*1(%rdi), %rbp - movq 8*2(%rdi), %r12 - movq 8*3(%rdi), %r13 - movq 8*4(%rdi), %r14 - movq 8*5(%rdi), %r15 - movq 8*6(%rdi), %rsp - movq 8*7(%rdi), %rdx - - /* Give back user's return value. */ - movq %rsi, %rax - - /* Away we go. */ - jmpq *%rdx - - .global clib_calljmp - .align 4 - .type clib_calljmp, @function -clib_calljmp: - /* Make sure stack is 16-byte aligned. */ - movq %rdx, %rax - andq $0xf, %rax - subq %rax, %rdx - - /* Get return address. */ - pop %rax - - /* Switch to new stack. */ - xchgq %rsp, %rdx - - /* Save return address on new stack. */ - push %rax - - /* Save old stack pointer on new stack. */ - push %rdx - - /* Get function. */ - movq %rdi, %rdx - - /* Move argument into place. */ - movq %rsi, %rdi - - /* Away we go. */ - callq *%rdx - - /* Switch back to old stack. */ - movq 8(%rsp), %rdx - movq 0(%rsp), %rcx - xchgq %rcx, %rsp - - /* Return to caller. */ - jmpq *%rdx - -#elif defined(i386) - .global clib_setjmp - .align 4 - .type clib_setjmp, @function -clib_setjmp: - movl 4(%esp), %ecx - - movl %ebp, 4*0(%ecx) - movl %ebx, 4*1(%ecx) - movl %edi, 4*2(%ecx) - movl %esi, 4*3(%ecx) - - /* Save SP after return. */ - leal 4(%esp), %edx - movl %edx, 4*4(%ecx) - - /* Save PC we are returning to from stack frame. */ - movl 0(%esp), %eax - movl %eax, 4*5(%ecx) - - /* Give back user's return value. */ - movl 8(%esp), %eax - ret - - .global clib_longjmp - .align 4 - .type clib_longjmp, @function -clib_longjmp: - movl 4(%esp), %ecx - - /* Give back user's return value. */ - movl 8(%esp), %eax - - /* Restore regs. */ - movl 4*0(%ecx), %ebp - movl 4*1(%ecx), %ebx - movl 4*2(%ecx), %edi - movl 4*3(%ecx), %esi - movl 4*4(%ecx), %esp - movl 4*5(%ecx), %edx - - /* Away we go. */ - jmp *%edx - - .global clib_calljmp - .align 4 - .type clib_calljmp, @function -clib_calljmp: - /* Get new stack pointer. */ - movl 12(%esp), %edx - - /* Switch stacks. */ - xchgl %esp, %edx - - /* Save old stack pointer on new stack. */ - sub $8, %esp - movl %edx, 4(%esp) - - /* Put function argument in stack frame. */ - movl 8(%edx), %eax - movl %eax, 0(%esp) - - /* Get function. */ - movl 4(%edx), %eax - - /* Away we go. */ - call *%eax - - /* Switch back to old stack. */ - movl 4(%esp), %edx - xchgl %edx, %esp - - /* Return to caller. */ - ret - -#elif defined(__SPU__) - -#elif defined(__powerpc64__) - - .text - -#define _prologue(n) \ - .align 2 ; \ - .globl n, .##n ; \ - .section ".opd", "aw" ; \ - .align 3 ; \ -n: .quad .##n, .TOC.@tocbase, 0 ; \ - .previous ; \ - .size n, 24 ; \ - .type .##n, @function ; \ -.##n: - -#define _foreach_14_31 \ -_ (14, 0) _ (15, 1) _ (16, 2) _ (17, 3) _ (18, 4) _ (19, 5) \ -_ (20, 6) _ (21, 7) _ (22, 8) _ (23, 9) _ (24, 10) _ (25, 11) \ -_ (26, 12) _ (27, 13) _ (28, 14) _ (29, 15) _ (30, 16) _ (31, 17) - -#define _foreach_20_31 \ -_ (20, 0) _ (21, 1) _ (22, 2) _ (23, 3) _ (24, 4) _ (25, 5) \ -_ (26, 6) _ (27, 7) _ (28, 8) _ (29, 9) _ (30, 10) _ (31, 11) - -#ifdef __ALTIVEC__ -#define CLIB_POWERPC_ALTIVEC_N_REGS 12 -#else -#define CLIB_POWERPC_ALTIVEC_N_REGS 0 -#endif - -_prologue (clib_setjmp) - mflr 0 - std 0, 8*0(3) - std 1, 8*1(3) - std 2, 8*2(3) - mfcr 0 - std 0, 8*3(3) - mfspr 0, 256 - stw 0, 8*4(3) - - /* gprs 14 - 31 */ -#define _(a,b) std a, 8*((b) + 4 + 18*0)(3) ; - _foreach_14_31 -#undef _ - - /* fprs 14 - 31 */ -#define _(a,b) stfd a, 8*((b) + 4 + 18*1)(3) ; - _foreach_14_31 -#undef _ - -#if CLIB_POWERPC_ALTIVEC_N_REGS > 0 - /* vrs 20 - 31 */ - li 5, 8*(4 + 18*2) -#define _(a,b) stvx a, 5, 3 ; addi 5, 5, 16 ; - _foreach_20_31 -#undef _ -#endif /* CLIB_POWERPC_ALTIVEC_N_REGS > 0 */ - - /* Return value. */ - mr 3, 4 - - blr - -_prologue (clib_longjmp) - ld 0, 8*0(3) - mtlr 0 - ld 1, 8*1(3) - ld 2, 8*2(3) - ld 0, 8*3(3) - mtcrf 0xff, 0 - lwz 0, 8*3(3) - mtspr 256, 0 - - /* gprs 14 - 31 */ -#define _(a,b) ld a, 8*((b) + 4 + 18*0)(3) ; - _foreach_14_31 -#undef _ - - /* fprs 14 - 31 */ -#define _(a,b) lfd a, 8*((b) + 4 + 18*1)(3) ; - _foreach_14_31 -#undef _ - -#if CLIB_POWERPC_ALTIVEC_N_REGS > 0 - /* vrs 20 - 31 */ - li 5, 8*(4 + 18*2) -#define _(a,b) lvx a, 5, 3 ; addi 5, 5, 16 ; - _foreach_20_31 -#undef _ -#endif /* CLIB_POWERPC_ALTIVEC_N_REGS > 0 */ - - /* Return value. */ - mr 3, 4 - - blr - - .globl clib_calljmp - .section ".opd","aw" - .align 3 -clib_calljmp: - .quad .L.clib_calljmp,.TOC.@tocbase,0 - .previous - .type clib_calljmp, @function -.L.clib_calljmp: - mflr 0 - mr 9,3 - std 0,16(1) - stdu 1,-112(1) -#APP - std 1,-8(5) - addi 5,5,-256 - mr 1,5 -#NO_APP - ld 10,0(9) - std 2,40(1) - mr 3,4 - mtctr 10 - ld 11,16(9) - ld 2,8(9) - bctrl - ld 2,40(1) -#APP - addi 1,1,256 - ld 1,-8(1) -#NO_APP - addi 1,1,112 - ld 0,16(1) - mtlr 0 - blr - .long 0 - .byte 0,0,0,1,128,0,0,0 - .size clib_calljmp,.-.L.clib_calljmp - -#elif defined(__powerpc__) - -#define _foreach_14_31 \ -_ (14, 0) _ (15, 1) _ (16, 2) _ (17, 3) _ (18, 4) _ (19, 5) \ -_ (20, 6) _ (21, 7) _ (22, 8) _ (23, 9) _ (24, 10) _ (25, 11) \ -_ (26, 12) _ (27, 13) _ (28, 14) _ (29, 15) _ (30, 16) _ (31, 17) - -#define _foreach_20_31 \ -_ (20, 0) _ (21, 1) _ (22, 2) _ (23, 3) _ (24, 4) _ (25, 5) \ -_ (26, 6) _ (27, 7) _ (28, 8) _ (29, 9) _ (30, 10) _ (31, 11) - -#ifdef __ALTIVEC__ -#define CLIB_POWERPC_ALTIVEC_N_REGS 12 -#else -#define CLIB_POWERPC_ALTIVEC_N_REGS 0 -#endif - - .global clib_setjmp - .align 4 - .type clib_setjmp, @function -clib_setjmp: - mflr 0 - stw 0, 4*0(3) - stw 1, 4*1(3) - mfcr 0 - stw 0, 4*2(3) -#if CLIB_POWERPC_ALTIVEC_N_REGS > 0 - mfspr 0, 256 -#endif - stw 0, 4*3(3) - -#if CLIB_POWERPC_ALTIVEC_N_REGS > 0 - li 5, 4*4 -#define _(a,b) stvx a, 3, 5 ; addi 5, 5, 16 ; - _foreach_20_31 -#undef _ -#endif /* CLIB_POWERPC_ALTIVEC_N_REGS > 0 */ - - /* gp 14 - 31 */ -#define _(a,b) stw a, 4*(1*(b) + 4 + 4*CLIB_POWERPC_ALTIVEC_N_REGS + 0*18)(3) ; - _foreach_14_31 -#undef _ - - /* fp 14 - 31 */ -#define _(a,b) stfd a, 4*(2*(b) + 4 + 4*CLIB_POWERPC_ALTIVEC_N_REGS + 1*18)(3) ; - _foreach_14_31 -#undef _ - - /* Return value. */ - mr 3, 4 - - blr - - .global clib_longjmp - .align 4 - .type clib_longjmp, @function -clib_longjmp: - - lwz 0, 4*0(3) - mtlr 0 - lwz 1, 4*1(3) - lwz 0, 4*2(3) - mtcr 0 - lwz 0, 4*3(3) -#if CLIB_POWERPC_ALTIVEC_N_REGS > 0 - mtspr 256, 0 -#endif - -#if CLIB_POWERPC_ALTIVEC_N_REGS > 0 - li 5, 4*4 -#define _(a,b) lvx a, 3, 5 ; addi 5, 5, 16 ; - _foreach_20_31 -#undef _ -#endif /* CLIB_POWERPC_ALTIVEC_N_REGS > 0 */ - - /* gp 14 - 31 */ -#define _(a,b) lwz a, 4*(1*(b) + 4 + 4*CLIB_POWERPC_ALTIVEC_N_REGS + 0*18)(3) ; - _foreach_14_31 -#undef _ - - /* fp 14 - 31 */ -#define _(a,b) lfd a, 4*(2*(b) + 4 + 4*CLIB_POWERPC_ALTIVEC_N_REGS + 1*18)(3) ; - _foreach_14_31 -#undef _ - - /* Return value. */ - mr 3, 4 - - blr - - .global clib_calljmp - .align 4 - .type clib_calljmp, @function -clib_calljmp: - /* Make sure stack is 16 byte aligned. */ - andi. 0, 5, 0xf - sub 5, 5, 0 - addi 5, 5, -16 - - /* Save old stack/link pointer on new stack. */ - stw 1, 0(5) - mflr 0 - stw 0, 4(5) - - /* account for (sp, lr) tuple, and keep aligned */ - addi 5, 5, -16 - - /* Switch stacks. */ - mr 1, 5 - - /* Move argument into place. */ - mtctr 3 - mr 3, 4 - - /* Away we go. */ - bctrl - - /* back to our synthetic frame */ - addi 1,1,16 - - /* Switch back to old stack. */ - lwz 0, 4(1) - mtlr 0 - lwz 0, 0(1) - mr 1, 0 - - /* Return to caller. */ - blr - -#elif defined(__arm__) - - .global clib_setjmp - .align 4 - .type clib_setjmp, %function -clib_setjmp: - mov ip, r0 /* jmp buffer */ - - /* Save integer registers */ - stmia ip!, {v1-v6, sl, fp, sp, lr} - -#ifdef __IWMMXT__ - /* Save the call-preserved iWMMXt registers. */ - wstrd wr10, [ip], #8 - wstrd wr11, [ip], #8 - wstrd wr12, [ip], #8 - wstrd wr13, [ip], #8 - wstrd wr14, [ip], #8 - wstrd wr15, [ip], #8 -#endif - - /* Give back user's return value. */ - mov r0, r1 - bx lr - - .global clib_longjmp - .align 4 - .type clib_longjmp, %function -clib_longjmp: - mov ip, r0 /* jmp buffer */ - - /* Restore integer registers. */ - ldmia ip!, {v1-v6, sl, fp, sp, lr} - -#ifdef __IWMMXT__ - /* Save the call-preserved iWMMXt registers. */ - wldrd wr10, [ip], #8 - wldrd wr11, [ip], #8 - wldrd wr12, [ip], #8 - wldrd wr13, [ip], #8 - wldrd wr14, [ip], #8 - wldrd wr15, [ip], #8 -#endif - - /* Give back user's return value. */ - mov r0, r1 - bx lr - - .global clib_calljmp - .align 4 - .type clib_calljmp, %function -clib_calljmp: - /* Make sure stack is 8 byte aligned. */ - bic r2, r2, #7 - - /* Allocate space for stack/link pointer on new stack. */ - sub r2, r2, #8 - - /* Save old stack/link pointer on new stack. */ - str sp, [r2, #0] - str lr, [r2, #4] - - /* Switch stacks. */ - mov sp, r2 - - /* Save function to call. */ - mov ip, r0 - - /* Move argument into place. */ - mov r0, r1 - - /* Away we go. */ - bx ip - - /* Switch back to old stack. */ - ldr lr, [sp, #4] - ldr ip, [sp, #0] - mov sp, ip - - /* Return to caller. */ - bx lr - -#elif defined(__xtensa__) - - /* FIXME implement if needed. */ - .global clib_setjmp - .align 4 - .type clib_setjmp, %function -clib_setjmp: -1: j 1b - - .global clib_longjmp - .align 4 - .type clib_longjmp, @function -clib_longjmp: -1: j 1b - - .global clib_calljmp - .align 4 - .type clib_calljmp, %function -clib_calljmp: -1: j 1b - -#elif defined(__TMS320C6X__) - - /* FIXME implement if needed. */ - .global clib_setjmp - .align 4 - .type clib_setjmp, %function -clib_setjmp: -1: B .S1 1b - - .global clib_longjmp - .align 4 - .type clib_longjmp, @function -clib_longjmp: -1: B .S1 1b - - .global clib_calljmp - .align 4 - .type clib_calljmp, %function -clib_calljmp: -1: B .S1 1b - -#elif defined (__aarch64__) -/* - Copyright (c) 2011, 2012 ARM Ltd - All rights reserved. - 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 company may not be used to endorse or promote - products derived from this software without specific prior written - permission. - THIS SOFTWARE IS PROVIDED BY ARM LTD ``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 ARM LTD 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. - */ -#define GPR_LAYOUT \ - REG_PAIR (x19, x20, 0); \ - REG_PAIR (x21, x22, 16); \ - REG_PAIR (x23, x24, 32); \ - REG_PAIR (x25, x26, 48); \ - REG_PAIR (x27, x28, 64); \ - REG_PAIR (x29, x30, 80); \ - REG_ONE (x16, 96) -#define FPR_LAYOUT \ - REG_PAIR ( d8, d9, 112); \ - REG_PAIR (d10, d11, 128); \ - REG_PAIR (d12, d13, 144); \ - REG_PAIR (d14, d15, 160); -// int clib_setjmp (jmp_buf) - .global clib_setjmp - .type clib_setjmp, %function -clib_setjmp: - mov x16, sp -#define REG_PAIR(REG1, REG2, OFFS) stp REG1, REG2, [x0, OFFS] -#define REG_ONE(REG1, OFFS) str REG1, [x0, OFFS] - GPR_LAYOUT - FPR_LAYOUT -#undef REG_PAIR -#undef REG_ONE - mov x0, x1 - ret - .size clib_setjmp, .-clib_setjmp -// void clib_longjmp (jmp_buf, int) __attribute__ ((noreturn)) - .global clib_longjmp - .type clib_longjmp, %function -clib_longjmp: -#define REG_PAIR(REG1, REG2, OFFS) ldp REG1, REG2, [x0, OFFS] -#define REG_ONE(REG1, OFFS) ldr REG1, [x0, OFFS] - GPR_LAYOUT - FPR_LAYOUT -#undef REG_PAIR -#undef REG_ONE - mov sp, x16 - mov x0, x1 - // cmp w1, #0 - // cinc w0, w1, eq - // use br not ret, as ret is guaranteed to mispredict - br x30 - .size clib_longjmp, .-clib_longjmp - - -// void clib_calljmp (x0=function, x1=arg, x2=new_stack) - .global clib_calljmp - .type clib_calljmp, %function -clib_calljmp: - // save fn ptr - mov x3, x0 - // set up fn arg - mov x0, x1 - // switch stacks - mov x4, sp - - // space for saved sp, lr on new stack - sub x2, x2, #16 - mov sp, x2 - - // save old sp and link register on new stack - str x4, [sp] - str x30,[sp,#8] - mov x4, sp - - // go there - blr x3 - - // restore old sp and link register - mov x4, sp - - ldr x3, [x4] - ldr x30,[x4, #8] - mov sp, x3 - ret - .size clib_calljmp, .-clib_calljmp -#else -#error "unknown machine" -#endif - -.section .note.GNU-stack,"",%progbits diff --git a/vppinfra/vppinfra/longjmp.h b/vppinfra/vppinfra/longjmp.h deleted file mode 100644 index 8d83203e41d..00000000000 --- a/vppinfra/vppinfra/longjmp.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2005 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_clib_longjmp_h -#define included_clib_longjmp_h - -#include <vppinfra/types.h> - -#if defined(__x86_64__) -/* rbx, rbp, r12, r13, r14, r15, eip, rsp */ -#define CLIB_ARCH_LONGJMP_REGS 8 - -#elif defined(i386) -/* ebx, ebp, esi, edi, eip, rsp */ -#define CLIB_ARCH_LONGJMP_REGS 6 - -#elif (defined(__powerpc64__) || defined(__powerpc__)) - -#ifdef __ALTIVEC__ -#define CLIB_POWERPC_ALTIVEC_N_REGS 12 -#else -#define CLIB_POWERPC_ALTIVEC_N_REGS 0 -#endif - -/* r1 r2 link condition+vsave regs 14-31 fp regs 14-31 vector regs 20-31 */ -#define CLIB_ARCH_LONGJMP_REGS \ - (/* r1 lr cr vrsave */ \ - 4 \ - /* gp */ \ - + (31 - 14 + 1) \ - /* fp */ \ - + (sizeof (f64) / sizeof (uword)) * (31 - 14 + 1) \ - /* vector regs */ \ - + (16 / sizeof (uword)) * CLIB_POWERPC_ALTIVEC_N_REGS) - -#elif defined(__SPU__) -/* FIXME */ -#define CLIB_ARCH_LONGJMP_REGS (10) - -#elif defined(__arm__) - -#ifndef __IWMMXT__ -/* v1-v6 sl fp sp lr */ -#define CLIB_ARCH_LONGJMP_REGS (10) -#else -/* For iwmmxt we save 6 extra 8 byte registers. */ -#define CLIB_ARCH_LONGJMP_REGS (10 + (6*2)) -#endif - -#elif defined(__xtensa__) - -/* setjmp/longjmp not supported for the moment. */ -#define CLIB_ARCH_LONGJMP_REGS 0 - -#elif defined(__TMS320C6X__) - -/* setjmp/longjmp not supported for the moment. */ -#define CLIB_ARCH_LONGJMP_REGS 0 - -#elif defined(__aarch64__) -#define CLIB_ARCH_LONGJMP_REGS (22) -#else -#error "unknown machine" -#endif - -typedef struct -{ - uword regs[CLIB_ARCH_LONGJMP_REGS]; -} clib_longjmp_t __attribute__ ((aligned (16))); - -/* Return given value to saved context. */ -void clib_longjmp (clib_longjmp_t * save, uword return_value); - -/* Save context. Returns given value if jump is not taken; - otherwise returns value from clib_longjmp if long jump is taken. */ -uword clib_setjmp (clib_longjmp_t * save, uword return_value_not_taken); - -/* Call function on given stack. */ -uword clib_calljmp (uword (*func) (uword func_arg), - uword func_arg, void *stack); - -#endif /* included_clib_longjmp_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/macros.c b/vppinfra/vppinfra/macros.c deleted file mode 100644 index ce4cc9bc81b..00000000000 --- a/vppinfra/vppinfra/macros.c +++ /dev/null @@ -1,266 +0,0 @@ -/* - macros.c - a simple macro expander - - Copyright (c) 2010, 2014 Cisco and/or its affiliates. - - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. -*/ - -#include <vppinfra/macros.h> - -static inline int -macro_isalnum (i8 c) -{ - if ((c >= 'A' && c <= 'Z') - || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || (c == '_')) - return 1; - return 0; -} - -static i8 * -builtin_eval (macro_main_t * mm, i8 * varname, i32 complain) -{ - uword *p; - i8 *(*fp) (macro_main_t *, i32); - - p = hash_get_mem (mm->the_builtin_eval_hash, varname); - if (p == 0) - return 0; - fp = (void *) (p[0]); - return (*fp) (mm, complain); -} - -int -clib_macro_unset (macro_main_t * mm, char *name) -{ - hash_pair_t *p; - u8 *key, *value; - - p = hash_get_pair (mm->the_value_table_hash, name); - - if (p == 0) - return 1; - - key = (u8 *) (p->key); - value = (u8 *) (p->value[0]); - hash_unset_mem (mm->the_value_table_hash, name); - - vec_free (value); - vec_free (key); - return 0; -} - -int -clib_macro_set_value (macro_main_t * mm, char *name, char *value) -{ - u8 *key_copy, *value_copy; - int rv; - - rv = clib_macro_unset (mm, name); - - key_copy = format (0, "%s%c", name, 0); - value_copy = format (0, "%s%c", value, 0); - - hash_set_mem (mm->the_value_table_hash, key_copy, value_copy); - return rv; -} - -i8 * -clib_macro_get_value (macro_main_t * mm, char *name) -{ - uword *p; - - p = hash_get_mem (mm->the_value_table_hash, name); - if (p) - return (i8 *) (p[0]); - else - return 0; -} - -/* - * eval: takes a string, returns a vector. - * looks up $foobar in the variable table. - */ -i8 * -clib_macro_eval (macro_main_t * mm, i8 * s, i32 complain) -{ - i8 *rv = 0; - i8 *varname, *varvalue; - i8 *ts; - - while (*s) - { - switch (*s) - { - case '\\': - s++; - /* fallthrough */ - - default: - vec_add1 (rv, *s); - s++; - break; - - case '$': - s++; - varname = 0; - /* - * Make vector with variable name in it. - */ - while (*s && (macro_isalnum (*s) || (*s == '_') || (*s == '('))) - { - - /* handle $(foo) */ - if (*s == '(') - { - s++; /* skip '(' */ - while (*s && *s != ')') - { - vec_add1 (varname, *s); - s++; - } - if (*s) - s++; /* skip ')' */ - break; - } - vec_add1 (varname, *s); - s++; - } - /* null terminate */ - vec_add1 (varname, 0); - /* Look for a builtin, e.g. $my_hostname */ - if (!(varvalue = builtin_eval (mm, varname, complain))) - { - /* Look in value table */ - if (!varvalue) - { - char *tmp = clib_macro_get_value (mm, varname); - if (tmp) - varvalue = (i8 *) format (0, "%s%c", tmp, 0); - } -#ifdef CLIB_UNIX - /* Look in environment. */ - if (!varvalue) - { - char *tmp = getenv (varname); - if (tmp) - varvalue = (i8 *) format (0, "%s%c", tmp, 0); - } -#endif /* CLIB_UNIX */ - } - if (varvalue) - { - /* recursively evaluate */ - ts = clib_macro_eval (mm, varvalue, complain); - vec_free (varvalue); - /* add results to answer */ - vec_append (rv, ts); - /* Remove NULL termination or the results are sad */ - _vec_len (rv) = vec_len (rv) - 1; - vec_free (ts); - } - else - { - if (complain) - clib_warning ("Undefined Variable Reference: %s\n", varname); - vec_append (rv, format (0, "UNSET ")); - _vec_len (rv) = vec_len (rv) - 1; - - } - vec_free (varname); - } - } - vec_add1 (rv, 0); - return (rv); -} - -/* - * eval: takes a string, returns a vector. - * looks up $foobar in the variable table. - */ -i8 * -clib_macro_eval_dollar (macro_main_t * mm, i8 * s, i32 complain) -{ - i8 *s2; - i8 *rv; - - s2 = (i8 *) format (0, "$(%s)%c", s, 0); - rv = clib_macro_eval (mm, s2, complain); - vec_free (s2); - return (rv); -} - -void -clib_macro_add_builtin (macro_main_t * mm, char *name, void *eval_fn) -{ - hash_set_mem (mm->the_builtin_eval_hash, name, (uword) eval_fn); -} - -#ifdef CLIB_UNIX -static i8 * -eval_hostname (macro_main_t * mm, i32 complain) -{ - char tmp[128]; - if (gethostname (tmp, sizeof (tmp))) - return ((i8 *) format (0, "gethostname-error%c", 0)); - return ((i8 *) format (0, "%s%c", tmp, 0)); -} -#endif - -void -clib_macro_init (macro_main_t * mm) -{ - if (mm->the_builtin_eval_hash != 0) - { - clib_warning ("mm %p already initialized", mm); - return; - } - - mm->the_builtin_eval_hash = hash_create_string (0, sizeof (uword)); - mm->the_value_table_hash = hash_create_string (0, sizeof (uword)); - -#ifdef CLIB_UNIX - hash_set_mem (mm->the_builtin_eval_hash, "hostname", (uword) eval_hostname); -#endif -} - -void -clib_macro_free (macro_main_t * mm) -{ - hash_pair_t *p; - u8 **strings_to_free = 0; - int i; - - hash_free (mm->the_builtin_eval_hash); - - /* *INDENT-OFF* */ - hash_foreach_pair (p, mm->the_value_table_hash, - ({ - vec_add1 (strings_to_free, (u8 *) (p->key)); - vec_add1 (strings_to_free, (u8 *) (p->value[0])); - })); - /* *INDENT-ON* */ - - for (i = 0; i < vec_len (strings_to_free); i++) - vec_free (strings_to_free[i]); - vec_free (strings_to_free); - hash_free (mm->the_value_table_hash); -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/macros.h b/vppinfra/vppinfra/macros.h deleted file mode 100644 index 5c2e7033f8d..00000000000 --- a/vppinfra/vppinfra/macros.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - macros.h - definitions for a simple macro expander - - Copyright (c) 2010, 2014 Cisco and/or its affiliates. - - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. -*/ - -#ifndef included_macros_h -#define included_macros_h - -#include <vppinfra/vec.h> -#include <vppinfra/hash.h> -#include <vppinfra/format.h> - -#ifdef CLIB_UNIX -#include <stdlib.h> -#include <unistd.h> -#endif - -typedef struct -{ - uword *the_builtin_eval_hash; - uword *the_value_table_hash; -} macro_main_t; - -int clib_macro_unset (macro_main_t * mm, char *name); -int clib_macro_set_value (macro_main_t * mm, char *name, char *value); -void clib_macro_add_builtin (macro_main_t * mm, char *name, void *eval_fn); -i8 *clib_macro_get_value (macro_main_t * mm, char *name); -i8 *clib_macro_eval (macro_main_t * mm, i8 * s, i32 complain); -i8 *clib_macro_eval_dollar (macro_main_t * mm, i8 * s, i32 complain); -void clib_macro_init (macro_main_t * mm); -void clib_macro_free (macro_main_t * mm); - -#endif /* included_macros_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/math.h b/vppinfra/vppinfra/math.h deleted file mode 100644 index 48f8c0f4b83..00000000000 --- a/vppinfra/vppinfra/math.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_math_h -#define included_math_h - -#include <vppinfra/clib.h> - -always_inline f64 -sqrt (f64 x) -{ - return __builtin_sqrt (x); -} - -always_inline f64 -fabs (f64 x) -{ - return __builtin_fabs (x); -} - -#endif /* included_math_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/md5.c b/vppinfra/vppinfra/md5.c deleted file mode 100644 index 9ac1efc708d..00000000000 --- a/vppinfra/vppinfra/md5.c +++ /dev/null @@ -1,317 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm */ - -/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All -rights reserved. - -License to copy and use this software is granted provided that it -is identified as the "RSA Data Security, Inc. MD5 Message-Digest -Algorithm" in all material mentioning or referencing this software -or this function. - -License is also granted to make and use derivative works provided -that such works are identified as "derived from the RSA Data -Security, Inc. MD5 Message-Digest Algorithm" in all material -mentioning or referencing the derived work. - -RSA Data Security, Inc. makes no representations concerning either -the merchantability of this software or the suitability of this -software for any particular purpose. It is provided "as is" -without express or implied warranty of any kind. - -These notices must be retained in any copies of any part of this -documentation and/or software. - */ - -#include <vppinfra/string.h> /* for memset */ -#include <vppinfra/byte_order.h> -#include <vppinfra/md5.h> - -/* F, G, H and I are basic MD5 functions. */ -#define F(b, c, d) (d ^ (b & (c ^ d))) -#define G(b, c, d) F (d, b, c) -#define H(b, c, d) (b ^ c ^ d) -#define I(b, c, d) (c ^ (b | ~d)) - -/* ROTATE_LEFT rotates x left n bits. */ -#define ROTATE_LEFT(x,n) \ - (((x) << (n)) | ((x) >> (32 - (n)))) - -/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. - Rotation is separate from addition to prevent recomputation. */ -#define FF(a,b,c,d,x,s,ac) \ -do { \ - a += F (b, c, d) + x + ac; \ - a = ROTATE_LEFT (a, s); \ - a += b; \ -} while (0) - -#define GG(a,b,c,d,x,s,ac) \ -do { \ - a += G (b, c, d) + x + ac; \ - a = ROTATE_LEFT (a, s); \ - a += b; \ -} while (0) - -#define HH(a,b,c,d,x,s,ac) \ -do { \ - a += H (b, c, d) + x + ac; \ - a = ROTATE_LEFT (a, s); \ - a += b; \ -} while (0) - -#define II(a,b,c,d,x,s,ac) \ -do { \ - a += I (b, c, d) + x + ac; \ - a = ROTATE_LEFT (a, s); \ - a += b; \ -} while (0) - -#undef _ - -/* MD5 basic transformation. Transforms state based on block. */ -static void -md5_transform (md5_context_t * m, u32 * data, u32 * result, int zero_buffer) -{ - u32 a = m->state[0], b = m->state[1], c = m->state[2], d = m->state[3]; - u32 *x = data; - -/* Constants for MD5Transform routine. */ -#define S11 7 -#define S12 12 -#define S13 17 -#define S14 22 -#define S21 5 -#define S22 9 -#define S23 14 -#define S24 20 -#define S31 4 -#define S32 11 -#define S33 16 -#define S34 23 -#define S41 6 -#define S42 10 -#define S43 15 -#define S44 21 - - /* Round 1 */ - FF (a, b, c, d, clib_host_to_little_u32 (x[0]), S11, 0xd76aa478); /* 1 */ - FF (d, a, b, c, clib_host_to_little_u32 (x[1]), S12, 0xe8c7b756); /* 2 */ - FF (c, d, a, b, clib_host_to_little_u32 (x[2]), S13, 0x242070db); /* 3 */ - FF (b, c, d, a, clib_host_to_little_u32 (x[3]), S14, 0xc1bdceee); /* 4 */ - FF (a, b, c, d, clib_host_to_little_u32 (x[4]), S11, 0xf57c0faf); /* 5 */ - FF (d, a, b, c, clib_host_to_little_u32 (x[5]), S12, 0x4787c62a); /* 6 */ - FF (c, d, a, b, clib_host_to_little_u32 (x[6]), S13, 0xa8304613); /* 7 */ - FF (b, c, d, a, clib_host_to_little_u32 (x[7]), S14, 0xfd469501); /* 8 */ - FF (a, b, c, d, clib_host_to_little_u32 (x[8]), S11, 0x698098d8); /* 9 */ - FF (d, a, b, c, clib_host_to_little_u32 (x[9]), S12, 0x8b44f7af); /* 10 */ - FF (c, d, a, b, clib_host_to_little_u32 (x[10]), S13, 0xffff5bb1); /* 11 */ - FF (b, c, d, a, clib_host_to_little_u32 (x[11]), S14, 0x895cd7be); /* 12 */ - FF (a, b, c, d, clib_host_to_little_u32 (x[12]), S11, 0x6b901122); /* 13 */ - FF (d, a, b, c, clib_host_to_little_u32 (x[13]), S12, 0xfd987193); /* 14 */ - FF (c, d, a, b, clib_host_to_little_u32 (x[14]), S13, 0xa679438e); /* 15 */ - FF (b, c, d, a, clib_host_to_little_u32 (x[15]), S14, 0x49b40821); /* 16 */ - - /* Round 2 */ - GG (a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */ - GG (d, a, b, c, x[6], S22, 0xc040b340); /* 18 */ - GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ - GG (b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */ - GG (a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */ - GG (d, a, b, c, x[10], S22, 0x02441453); /* 22 */ - GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ - GG (b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */ - GG (a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */ - GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ - GG (c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */ - GG (b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */ - GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ - GG (d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */ - GG (c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */ - GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ - - /* Round 3 */ - HH (a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */ - HH (d, a, b, c, x[8], S32, 0x8771f681); /* 34 */ - HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ - HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ - HH (a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */ - HH (d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */ - HH (c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */ - HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ - HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ - HH (d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */ - HH (c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */ - HH (b, c, d, a, x[6], S34, 0x04881d05); /* 44 */ - HH (a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */ - HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ - HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ - HH (b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */ - - /* Round 4 */ - II (a, b, c, d, x[0], S41, 0xf4292244); /* 49 */ - II (d, a, b, c, x[7], S42, 0x432aff97); /* 50 */ - II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ - II (b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */ - II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ - II (d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */ - II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ - II (b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */ - II (a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */ - II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ - II (c, d, a, b, x[6], S43, 0xa3014314); /* 59 */ - II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ - II (a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */ - II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ - II (c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */ - II (b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */ - - a += m->state[0]; - b += m->state[1]; - c += m->state[2]; - d += m->state[3]; - - if (result) - { - result[0] = clib_host_to_little_u32 (a); - result[1] = clib_host_to_little_u32 (b); - result[2] = clib_host_to_little_u32 (c); - result[3] = clib_host_to_little_u32 (d); - } - else - { - m->state[0] = a; - m->state[1] = b; - m->state[2] = c; - m->state[3] = d; - } - - /* Zero sensitive information. */ - if (result) - memset (m, ~0, sizeof (m[0])); - else if (zero_buffer) - memset (m->input_buffer.b8, 0, sizeof (m->input_buffer)); -} - -/* MD5 initialization. Begins an MD5 operation, writing a new context. */ -void -md5_init (md5_context_t * c) -{ - memset (c, 0, sizeof (c[0])); - - /* Load magic initialization constants. */ - c->state[0] = 0x67452301; - c->state[1] = 0xefcdab89; - c->state[2] = 0x98badcfe; - c->state[3] = 0x10325476; -} - -always_inline void __attribute__ ((unused)) -md5_fill_buffer_aligned (md5_context_t * c, u32 * d32) -{ - int i; - for (i = 0; i < ARRAY_LEN (c->input_buffer.b32); i++) - c->input_buffer.b32[i] = d32[i]; -} - -/* MD5 block update operation. Continues an MD5 message-digest - operation, processing another message block, and updating the - context. - */ -void -md5_add (md5_context_t * c, void *data, int data_bytes) -{ - u32 data_bytes_left; - void *d; - - if (data_bytes == 0) - return; - - d = data; - data_bytes_left = data_bytes; - - if ((pointer_to_uword (d) % sizeof (u32)) == 0 - && (c->n_bits % BITS (c->input_buffer)) == 0 - && data_bytes >= sizeof (c->input_buffer)) - { - int is_last_iteration; - /* Fast aligned version. */ - do - { - data_bytes_left -= sizeof (c->input_buffer); - is_last_iteration = data_bytes_left < sizeof (c->input_buffer); - md5_transform (c, d, /* result */ 0, /* zero_buffer */ - is_last_iteration); - d += sizeof (c->input_buffer); - } - while (!is_last_iteration); - } - - /* Slow unaligned version. */ - { - int bi; - u8 *d8 = d; - - bi = (c->n_bits / BITS (u8)) % ARRAY_LEN (c->input_buffer.b8); - - while (data_bytes_left > 0) - { - c->input_buffer.b8[bi] = d8[0]; - data_bytes_left -= 1; - d8++; - bi++; - if (bi == ARRAY_LEN (c->input_buffer.b8)) - { - bi = 0; - md5_transform (c, c->input_buffer.b32, - /* result */ 0, - /* zero_buffer */ 1); - } - } - } - - c->n_bits += data_bytes * BITS (u8); -} - -void -md5_finish (md5_context_t * c, u8 * digest) -{ - u64 n_bits_save; - int bi, n_pad; - static u8 padding[sizeof (c->input_buffer)] = { 0x80, 0, }; - - n_bits_save = c->n_bits; - bi = (n_bits_save / BITS (u8)) % ARRAY_LEN (c->input_buffer.b8); - - n_pad = sizeof (c->input_buffer) - (bi + sizeof (u64)); - if (n_pad <= 0) - n_pad += sizeof (c->input_buffer); - md5_add (c, padding, n_pad); - - c->input_buffer.b64[ARRAY_LEN (c->input_buffer.b64) - 1] - = clib_host_to_little_u64 (n_bits_save); - - md5_transform (c, c->input_buffer.b32, (u32 *) digest, - /* zero_buffer */ 1); -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/md5.h b/vppinfra/vppinfra/md5.h deleted file mode 100644 index 52123886f7e..00000000000 --- a/vppinfra/vppinfra/md5.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - Copyright (c) 2004 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_md5_h -#define included_md5_h - -#include <vppinfra/clib.h> - -typedef struct -{ - u64 n_bits; - - u32 state[4]; - - union - { - u64 b64[8]; - u32 b32[16]; - u8 b8[16 * 4]; - } input_buffer; - - /* Resulting message digest filled in by md5_finish. */ -} md5_context_t; - -void md5_init (md5_context_t * c); -void md5_add (md5_context_t * c, void *data, int data_bytes); -void md5_finish (md5_context_t * c, u8 digest[16]); - -#endif /* included_md5_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/mem.h b/vppinfra/vppinfra/mem.h deleted file mode 100644 index 1260eab28c0..00000000000 --- a/vppinfra/vppinfra/mem.h +++ /dev/null @@ -1,291 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef _included_clib_mem_h -#define _included_clib_mem_h - -#include <stdarg.h> - -#include <vppinfra/clib.h> /* uword, etc */ -#include <vppinfra/mheap_bootstrap.h> -#include <vppinfra/os.h> -#include <vppinfra/string.h> /* memcpy, memset */ -#include <vppinfra/valgrind.h> - -#define CLIB_MAX_MHEAPS 256 - -/* Per CPU heaps. */ -extern void *clib_per_cpu_mheaps[CLIB_MAX_MHEAPS]; - -always_inline void * -clib_mem_get_per_cpu_heap (void) -{ - int cpu = os_get_cpu_number (); - return clib_per_cpu_mheaps[cpu]; -} - -always_inline void * -clib_mem_set_per_cpu_heap (u8 * new_heap) -{ - int cpu = os_get_cpu_number (); - void *old = clib_per_cpu_mheaps[cpu]; - clib_per_cpu_mheaps[cpu] = new_heap; - return old; -} - -/* Memory allocator which may call os_out_of_memory() if it fails */ -always_inline void * -clib_mem_alloc_aligned_at_offset (uword size, uword align, uword align_offset, - int os_out_of_memory_on_failure) -{ - void *heap, *p; - uword offset, cpu; - - if (align_offset > align) - { - if (align > 0) - align_offset %= align; - else - align_offset = align; - } - - cpu = os_get_cpu_number (); - heap = clib_per_cpu_mheaps[cpu]; - heap = mheap_get_aligned (heap, size, align, align_offset, &offset); - clib_per_cpu_mheaps[cpu] = heap; - - if (offset != ~0) - { - p = heap + offset; -#if CLIB_DEBUG > 0 - VALGRIND_MALLOCLIKE_BLOCK (p, mheap_data_bytes (heap, offset), 0, 0); -#endif - return p; - } - else - { - if (os_out_of_memory_on_failure) - os_out_of_memory (); - return 0; - } -} - -/* Memory allocator which calls os_out_of_memory() when it fails */ -always_inline void * -clib_mem_alloc (uword size) -{ - return clib_mem_alloc_aligned_at_offset (size, /* align */ 1, - /* align_offset */ 0, - /* os_out_of_memory */ 1); -} - -always_inline void * -clib_mem_alloc_aligned (uword size, uword align) -{ - return clib_mem_alloc_aligned_at_offset (size, align, /* align_offset */ 0, - /* os_out_of_memory */ 1); -} - -/* Memory allocator which calls os_out_of_memory() when it fails */ -always_inline void * -clib_mem_alloc_or_null (uword size) -{ - return clib_mem_alloc_aligned_at_offset (size, /* align */ 1, - /* align_offset */ 0, - /* os_out_of_memory */ 0); -} - -always_inline void * -clib_mem_alloc_aligned_or_null (uword size, uword align) -{ - return clib_mem_alloc_aligned_at_offset (size, align, /* align_offset */ 0, - /* os_out_of_memory */ 0); -} - - - -/* Memory allocator which panics when it fails. - Use macro so that clib_panic macro can expand __FUNCTION__ and __LINE__. */ -#define clib_mem_alloc_aligned_no_fail(size,align) \ -({ \ - uword _clib_mem_alloc_size = (size); \ - void * _clib_mem_alloc_p; \ - _clib_mem_alloc_p = clib_mem_alloc_aligned (_clib_mem_alloc_size, (align)); \ - if (! _clib_mem_alloc_p) \ - clib_panic ("failed to allocate %d bytes", _clib_mem_alloc_size); \ - _clib_mem_alloc_p; \ -}) - -#define clib_mem_alloc_no_fail(size) clib_mem_alloc_aligned_no_fail(size,1) - -/* Alias to stack allocator for naming consistency. */ -#define clib_mem_alloc_stack(bytes) __builtin_alloca(bytes) - -always_inline uword -clib_mem_is_heap_object (void *p) -{ - void *heap = clib_mem_get_per_cpu_heap (); - uword offset = (uword) p - (uword) heap; - mheap_elt_t *e, *n; - - if (offset >= vec_len (heap)) - return 0; - - e = mheap_elt_at_uoffset (heap, offset); - n = mheap_next_elt (e); - - /* Check that heap forward and reverse pointers agree. */ - return e->n_user_data == n->prev_n_user_data; -} - -always_inline void -clib_mem_free (void *p) -{ - u8 *heap = clib_mem_get_per_cpu_heap (); - - /* Make sure object is in the correct heap. */ - ASSERT (clib_mem_is_heap_object (p)); - - mheap_put (heap, (u8 *) p - heap); - -#if CLIB_DEBUG > 0 - VALGRIND_FREELIKE_BLOCK (p, 0); -#endif -} - -always_inline void * -clib_mem_realloc (void *p, uword new_size, uword old_size) -{ - /* By default use alloc, copy and free to emulate realloc. */ - void *q = clib_mem_alloc (new_size); - if (q) - { - uword copy_size; - if (old_size < new_size) - copy_size = old_size; - else - copy_size = new_size; - clib_memcpy (q, p, copy_size); - clib_mem_free (p); - } - return q; -} - -always_inline uword -clib_mem_size (void *p) -{ - ASSERT (clib_mem_is_heap_object (p)); - mheap_elt_t *e = mheap_user_pointer_to_elt (p); - return mheap_elt_data_bytes (e); -} - -always_inline void * -clib_mem_get_heap (void) -{ - return clib_mem_get_per_cpu_heap (); -} - -always_inline void * -clib_mem_set_heap (void *heap) -{ - return clib_mem_set_per_cpu_heap (heap); -} - -void *clib_mem_init (void *heap, uword size); - -void clib_mem_exit (void); - -uword clib_mem_get_page_size (void); - -void clib_mem_validate (void); - -void clib_mem_trace (int enable); - -typedef struct -{ - /* Total number of objects allocated. */ - uword object_count; - - /* Total allocated bytes. Bytes used and free. - used + free = total */ - uword bytes_total, bytes_used, bytes_free; - - /* Number of bytes used by mheap data structure overhead - (e.g. free lists, mheap header). */ - uword bytes_overhead; - - /* Amount of free space returned to operating system. */ - uword bytes_free_reclaimed; - - /* For malloc which puts small objects in sbrk region and - large objects in mmap'ed regions. */ - uword bytes_used_sbrk; - uword bytes_used_mmap; - - /* Max. number of bytes in this heap. */ - uword bytes_max; -} clib_mem_usage_t; - -void clib_mem_usage (clib_mem_usage_t * usage); - -u8 *format_clib_mem_usage (u8 * s, va_list * args); - -/* Include appropriate VM functions depending on whether - we are compiling for linux kernel, for Unix or standalone. */ -#ifdef CLIB_LINUX_KERNEL -#include <vppinfra/vm_linux_kernel.h> -#endif - -#ifdef CLIB_UNIX -#include <vppinfra/vm_unix.h> -#endif - -#ifdef CLIB_STANDALONE -#include <vppinfra/vm_standalone.h> -#endif - -#include <vppinfra/error.h> /* clib_panic */ - -#endif /* _included_clib_mem_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/mem_mheap.c b/vppinfra/vppinfra/mem_mheap.c deleted file mode 100644 index 9b2af520ca6..00000000000 --- a/vppinfra/vppinfra/mem_mheap.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include <vppinfra/format.h> -#include <vppinfra/mheap.h> -#include <vppinfra/os.h> - -/* Valgrind stuff. */ -#include <vppinfra/memcheck.h> -#include <vppinfra/valgrind.h> - -void *clib_per_cpu_mheaps[CLIB_MAX_MHEAPS]; - -void -clib_mem_exit (void) -{ - u8 *heap = clib_mem_get_per_cpu_heap (); - if (heap) - mheap_free (heap); - clib_mem_set_per_cpu_heap (0); -} - -/* Initialize CLIB heap based on memory/size given by user. - Set memory to 0 and CLIB will try to allocate its own heap. */ -void * -clib_mem_init (void *memory, uword memory_size) -{ - u8 *heap; - - if (memory || memory_size) - heap = mheap_alloc (memory, memory_size); - else - { - /* Allocate lots of address space since this will limit - the amount of memory the program can allocate. - In the kernel we're more conservative since some architectures - (e.g. mips) have pretty small kernel virtual address spaces. */ -#ifdef __KERNEL__ -#define MAX_VM_MEG 64 -#else -#define MAX_VM_MEG 1024 -#endif - - uword alloc_size = MAX_VM_MEG << 20; - uword tries = 16; - - while (1) - { - heap = mheap_alloc (0, alloc_size); - if (heap) - break; - alloc_size = (alloc_size * 3) / 4; - tries--; - if (tries == 0) - break; - } - } - - clib_mem_set_heap (heap); - - return heap; -} - -#ifdef CLIB_LINUX_KERNEL -#include <asm/page.h> - -uword -clib_mem_get_page_size (void) -{ - return PAGE_SIZE; -} -#endif - -#ifdef CLIB_UNIX -uword -clib_mem_get_page_size (void) -{ - return getpagesize (); -} -#endif - -/* Make a guess for standalone. */ -#ifdef CLIB_STANDALONE -uword -clib_mem_get_page_size (void) -{ - return 4096; -} -#endif - -u8 * -format_clib_mem_usage (u8 * s, va_list * va) -{ - int verbose = va_arg (*va, int); - return format (s, "%U", format_mheap, clib_mem_get_heap (), verbose); -} - -void -clib_mem_usage (clib_mem_usage_t * u) -{ - mheap_usage (clib_mem_get_heap (), u); -} - -/* Call serial number for debugger breakpoints. */ -uword clib_mem_validate_serial = 0; - -void -clib_mem_validate (void) -{ - if (MHEAP_HAVE_SMALL_OBJECT_CACHE) - clib_warning ("clib_mem_validate disabled (small object cache is ON)"); - else - { - mheap_validate (clib_mem_get_heap ()); - clib_mem_validate_serial++; - } -} - -void -clib_mem_trace (int enable) -{ - mheap_trace (clib_mem_get_heap (), enable); -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/memcheck.h b/vppinfra/vppinfra/memcheck.h deleted file mode 100644 index 44db3a8a6cb..00000000000 --- a/vppinfra/vppinfra/memcheck.h +++ /dev/null @@ -1,317 +0,0 @@ - -/* - ---------------------------------------------------------------- - - Notice that the following BSD-style license applies to this one - file (memcheck.h) only. The rest of Valgrind is licensed under the - terms of the GNU General Public License, version 2, unless - otherwise indicated. See the COPYING file in the source - distribution for details. - - ---------------------------------------------------------------- - - This file is part of MemCheck, a heavyweight Valgrind tool for - detecting memory errors. - - Copyright (C) 2000-2009 Julian Seward. All rights reserved. - - 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. The origin of this software must not be misrepresented; you must - not claim that you wrote the original software. If you use this - software in a product, an acknowledgment in the product - documentation would be appreciated but is not required. - - 3. Altered source versions must be plainly marked as such, and must - not be misrepresented as being the original software. - - 4. The name of the author may not 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. - - ---------------------------------------------------------------- - - Notice that the above BSD-style license applies to this one file - (memcheck.h) only. The entire rest of Valgrind is licensed under - the terms of the GNU General Public License, version 2. See the - COPYING file in the source distribution for details. - - ---------------------------------------------------------------- -*/ - - -#ifndef __MEMCHECK_H -#define __MEMCHECK_H - - -/* This file is for inclusion into client (your!) code. - - You can use these macros to manipulate and query memory permissions - inside your own programs. - - See comment near the top of valgrind.h on how to use them. -*/ - -#include "valgrind.h" - -/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !! - This enum comprises an ABI exported by Valgrind to programs - which use client requests. DO NOT CHANGE THE ORDER OF THESE - ENTRIES, NOR DELETE ANY -- add new ones at the end. */ -typedef enum -{ - VG_USERREQ__MAKE_MEM_NOACCESS = VG_USERREQ_TOOL_BASE ('M', 'C'), - VG_USERREQ__MAKE_MEM_UNDEFINED, - VG_USERREQ__MAKE_MEM_DEFINED, - VG_USERREQ__DISCARD, - VG_USERREQ__CHECK_MEM_IS_ADDRESSABLE, - VG_USERREQ__CHECK_MEM_IS_DEFINED, - VG_USERREQ__DO_LEAK_CHECK, - VG_USERREQ__COUNT_LEAKS, - - VG_USERREQ__GET_VBITS, - VG_USERREQ__SET_VBITS, - - VG_USERREQ__CREATE_BLOCK, - - VG_USERREQ__MAKE_MEM_DEFINED_IF_ADDRESSABLE, - - /* Not next to VG_USERREQ__COUNT_LEAKS because it was added later. */ - VG_USERREQ__COUNT_LEAK_BLOCKS, - - /* This is just for memcheck's internal use - don't use it */ - _VG_USERREQ__MEMCHECK_RECORD_OVERLAP_ERROR - = VG_USERREQ_TOOL_BASE ('M', 'C') + 256 -} Vg_MemCheckClientRequest; - - - -/* Client-code macros to manipulate the state of memory. */ - -/* Mark memory at _qzz_addr as unaddressable for _qzz_len bytes. */ -#define VALGRIND_MAKE_MEM_NOACCESS(_qzz_addr,_qzz_len) \ - (__extension__({unsigned long _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* default return */, \ - VG_USERREQ__MAKE_MEM_NOACCESS, \ - _qzz_addr, _qzz_len, 0, 0, 0); \ - _qzz_res; \ - })) - -/* Similarly, mark memory at _qzz_addr as addressable but undefined - for _qzz_len bytes. */ -#define VALGRIND_MAKE_MEM_UNDEFINED(_qzz_addr,_qzz_len) \ - (__extension__({unsigned long _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* default return */, \ - VG_USERREQ__MAKE_MEM_UNDEFINED, \ - _qzz_addr, _qzz_len, 0, 0, 0); \ - _qzz_res; \ - })) - -/* Similarly, mark memory at _qzz_addr as addressable and defined - for _qzz_len bytes. */ -#define VALGRIND_MAKE_MEM_DEFINED(_qzz_addr,_qzz_len) \ - (__extension__({unsigned long _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* default return */, \ - VG_USERREQ__MAKE_MEM_DEFINED, \ - _qzz_addr, _qzz_len, 0, 0, 0); \ - _qzz_res; \ - })) - -/* Similar to VALGRIND_MAKE_MEM_DEFINED except that addressability is - not altered: bytes which are addressable are marked as defined, - but those which are not addressable are left unchanged. */ -#define VALGRIND_MAKE_MEM_DEFINED_IF_ADDRESSABLE(_qzz_addr,_qzz_len) \ - (__extension__({unsigned long _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* default return */, \ - VG_USERREQ__MAKE_MEM_DEFINED_IF_ADDRESSABLE, \ - _qzz_addr, _qzz_len, 0, 0, 0); \ - _qzz_res; \ - })) - -/* Create a block-description handle. The description is an ascii - string which is included in any messages pertaining to addresses - within the specified memory range. Has no other effect on the - properties of the memory range. */ -#define VALGRIND_CREATE_BLOCK(_qzz_addr,_qzz_len, _qzz_desc) \ - (__extension__({unsigned long _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* default return */, \ - VG_USERREQ__CREATE_BLOCK, \ - _qzz_addr, _qzz_len, _qzz_desc, \ - 0, 0); \ - _qzz_res; \ - })) - -/* Discard a block-description-handle. Returns 1 for an - invalid handle, 0 for a valid handle. */ -#define VALGRIND_DISCARD(_qzz_blkindex) \ - (__extension__ ({unsigned long _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* default return */, \ - VG_USERREQ__DISCARD, \ - 0, _qzz_blkindex, 0, 0, 0); \ - _qzz_res; \ - })) - - -/* Client-code macros to check the state of memory. */ - -/* Check that memory at _qzz_addr is addressable for _qzz_len bytes. - If suitable addressibility is not established, Valgrind prints an - error message and returns the address of the first offending byte. - Otherwise it returns zero. */ -#define VALGRIND_CHECK_MEM_IS_ADDRESSABLE(_qzz_addr,_qzz_len) \ - (__extension__({unsigned long _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__CHECK_MEM_IS_ADDRESSABLE,\ - _qzz_addr, _qzz_len, 0, 0, 0); \ - _qzz_res; \ - })) - -/* Check that memory at _qzz_addr is addressable and defined for - _qzz_len bytes. If suitable addressibility and definedness are not - established, Valgrind prints an error message and returns the - address of the first offending byte. Otherwise it returns zero. */ -#define VALGRIND_CHECK_MEM_IS_DEFINED(_qzz_addr,_qzz_len) \ - (__extension__({unsigned long _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__CHECK_MEM_IS_DEFINED, \ - _qzz_addr, _qzz_len, 0, 0, 0); \ - _qzz_res; \ - })) - -/* Use this macro to force the definedness and addressibility of an - lvalue to be checked. If suitable addressibility and definedness - are not established, Valgrind prints an error message and returns - the address of the first offending byte. Otherwise it returns - zero. */ -#define VALGRIND_CHECK_VALUE_IS_DEFINED(__lvalue) \ - VALGRIND_CHECK_MEM_IS_DEFINED( \ - (volatile unsigned char *)&(__lvalue), \ - (unsigned long)(sizeof (__lvalue))) - - -/* Do a full memory leak check (like --leak-check=full) mid-execution. */ -#define VALGRIND_DO_LEAK_CHECK \ - {unsigned long _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__DO_LEAK_CHECK, \ - 0, 0, 0, 0, 0); \ - } - -/* Do a summary memory leak check (like --leak-check=summary) mid-execution. */ -#define VALGRIND_DO_QUICK_LEAK_CHECK \ - {unsigned long _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__DO_LEAK_CHECK, \ - 1, 0, 0, 0, 0); \ - } - -/* Return number of leaked, dubious, reachable and suppressed bytes found by - all previous leak checks. They must be lvalues. */ -#define VALGRIND_COUNT_LEAKS(leaked, dubious, reachable, suppressed) \ - /* For safety on 64-bit platforms we assign the results to private - unsigned long variables, then assign these to the lvalues the user - specified, which works no matter what type 'leaked', 'dubious', etc - are. We also initialise '_qzz_leaked', etc because - VG_USERREQ__COUNT_LEAKS doesn't mark the values returned as - defined. */ \ - {unsigned long _qzz_res; \ - unsigned long _qzz_leaked = 0, _qzz_dubious = 0; \ - unsigned long _qzz_reachable = 0, _qzz_suppressed = 0; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__COUNT_LEAKS, \ - &_qzz_leaked, &_qzz_dubious, \ - &_qzz_reachable, &_qzz_suppressed, 0); \ - leaked = _qzz_leaked; \ - dubious = _qzz_dubious; \ - reachable = _qzz_reachable; \ - suppressed = _qzz_suppressed; \ - } - -/* Return number of leaked, dubious, reachable and suppressed bytes found by - all previous leak checks. They must be lvalues. */ -#define VALGRIND_COUNT_LEAK_BLOCKS(leaked, dubious, reachable, suppressed) \ - /* For safety on 64-bit platforms we assign the results to private - unsigned long variables, then assign these to the lvalues the user - specified, which works no matter what type 'leaked', 'dubious', etc - are. We also initialise '_qzz_leaked', etc because - VG_USERREQ__COUNT_LEAKS doesn't mark the values returned as - defined. */ \ - {unsigned long _qzz_res; \ - unsigned long _qzz_leaked = 0, _qzz_dubious = 0; \ - unsigned long _qzz_reachable = 0, _qzz_suppressed = 0; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__COUNT_LEAK_BLOCKS, \ - &_qzz_leaked, &_qzz_dubious, \ - &_qzz_reachable, &_qzz_suppressed, 0); \ - leaked = _qzz_leaked; \ - dubious = _qzz_dubious; \ - reachable = _qzz_reachable; \ - suppressed = _qzz_suppressed; \ - } - - -/* Get the validity data for addresses [zza..zza+zznbytes-1] and copy it - into the provided zzvbits array. Return values: - 0 if not running on valgrind - 1 success - 2 [previously indicated unaligned arrays; these are now allowed] - 3 if any parts of zzsrc/zzvbits are not addressable. - The metadata is not copied in cases 0, 2 or 3 so it should be - impossible to segfault your system by using this call. -*/ -#define VALGRIND_GET_VBITS(zza,zzvbits,zznbytes) \ - (__extension__({unsigned long _qzz_res; \ - char* czza = (char*)zza; \ - char* czzvbits = (char*)zzvbits; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__GET_VBITS, \ - czza, czzvbits, zznbytes, 0, 0 ); \ - _qzz_res; \ - })) - -/* Set the validity data for addresses [zza..zza+zznbytes-1], copying it - from the provided zzvbits array. Return values: - 0 if not running on valgrind - 1 success - 2 [previously indicated unaligned arrays; these are now allowed] - 3 if any parts of zza/zzvbits are not addressable. - The metadata is not copied in cases 0, 2 or 3 so it should be - impossible to segfault your system by using this call. -*/ -#define VALGRIND_SET_VBITS(zza,zzvbits,zznbytes) \ - (__extension__({unsigned int _qzz_res; \ - char* czza = (char*)zza; \ - char* czzvbits = (char*)zzvbits; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__SET_VBITS, \ - czza, czzvbits, zznbytes, 0, 0 ); \ - _qzz_res; \ - })) - -#endif - - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/memcpy_avx.h b/vppinfra/vppinfra/memcpy_avx.h deleted file mode 100644 index e3feb76b6b7..00000000000 --- a/vppinfra/vppinfra/memcpy_avx.h +++ /dev/null @@ -1,293 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/*- - * BSD LICENSE - * - * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. - * All rights reserved. - * - * 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. - */ - -#ifndef included_clib_memcpy_avx_h -#define included_clib_memcpy_avx_h - -#include <stdint.h> -#include <x86intrin.h> - -typedef u8 u8x16u __attribute__ ((vector_size (16), aligned (1))); -typedef u8 u8x32u __attribute__ ((vector_size (32), aligned (1))); - -static inline void -clib_mov16 (u8 * dst, const u8 * src) -{ - *(u8x16u *) dst = *(u8x16u *) src; -} - -static inline void -clib_mov32 (u8 * dst, const u8 * src) -{ - *(u8x32u *) dst = *(u8x32u *) src; -} - -static inline void -clib_mov64 (u8 * dst, const u8 * src) -{ - clib_mov32 ((u8 *) dst + 0 * 32, (const u8 *) src + 0 * 32); - clib_mov32 ((u8 *) dst + 1 * 32, (const u8 *) src + 1 * 32); -} - -static inline void -clib_mov128 (u8 * dst, const u8 * src) -{ - clib_mov64 ((u8 *) dst + 0 * 64, (const u8 *) src + 0 * 64); - clib_mov64 ((u8 *) dst + 1 * 64, (const u8 *) src + 1 * 64); -} - -static inline void -clib_mov256 (u8 * dst, const u8 * src) -{ - clib_mov128 ((u8 *) dst + 0 * 128, (const u8 *) src + 0 * 128); - clib_mov128 ((u8 *) dst + 1 * 128, (const u8 *) src + 1 * 128); -} - -static inline void -clib_mov64blocks (u8 * dst, const u8 * src, size_t n) -{ - __m256i ymm0, ymm1; - - while (n >= 64) - { - ymm0 = - _mm256_loadu_si256 ((const __m256i *) ((const u8 *) src + 0 * 32)); - n -= 64; - ymm1 = - _mm256_loadu_si256 ((const __m256i *) ((const u8 *) src + 1 * 32)); - src = (const u8 *) src + 64; - _mm256_storeu_si256 ((__m256i *) ((u8 *) dst + 0 * 32), ymm0); - _mm256_storeu_si256 ((__m256i *) ((u8 *) dst + 1 * 32), ymm1); - dst = (u8 *) dst + 64; - } -} - -static inline void -clib_mov256blocks (u8 * dst, const u8 * src, size_t n) -{ - __m256i ymm0, ymm1, ymm2, ymm3, ymm4, ymm5, ymm6, ymm7; - - while (n >= 256) - { - ymm0 = - _mm256_loadu_si256 ((const __m256i *) ((const u8 *) src + 0 * 32)); - n -= 256; - ymm1 = - _mm256_loadu_si256 ((const __m256i *) ((const u8 *) src + 1 * 32)); - ymm2 = - _mm256_loadu_si256 ((const __m256i *) ((const u8 *) src + 2 * 32)); - ymm3 = - _mm256_loadu_si256 ((const __m256i *) ((const u8 *) src + 3 * 32)); - ymm4 = - _mm256_loadu_si256 ((const __m256i *) ((const u8 *) src + 4 * 32)); - ymm5 = - _mm256_loadu_si256 ((const __m256i *) ((const u8 *) src + 5 * 32)); - ymm6 = - _mm256_loadu_si256 ((const __m256i *) ((const u8 *) src + 6 * 32)); - ymm7 = - _mm256_loadu_si256 ((const __m256i *) ((const u8 *) src + 7 * 32)); - src = (const u8 *) src + 256; - _mm256_storeu_si256 ((__m256i *) ((u8 *) dst + 0 * 32), ymm0); - _mm256_storeu_si256 ((__m256i *) ((u8 *) dst + 1 * 32), ymm1); - _mm256_storeu_si256 ((__m256i *) ((u8 *) dst + 2 * 32), ymm2); - _mm256_storeu_si256 ((__m256i *) ((u8 *) dst + 3 * 32), ymm3); - _mm256_storeu_si256 ((__m256i *) ((u8 *) dst + 4 * 32), ymm4); - _mm256_storeu_si256 ((__m256i *) ((u8 *) dst + 5 * 32), ymm5); - _mm256_storeu_si256 ((__m256i *) ((u8 *) dst + 6 * 32), ymm6); - _mm256_storeu_si256 ((__m256i *) ((u8 *) dst + 7 * 32), ymm7); - dst = (u8 *) dst + 256; - } -} - -static inline void * -clib_memcpy (void *dst, const void *src, size_t n) -{ - uword dstu = (uword) dst; - uword srcu = (uword) src; - void *ret = dst; - size_t dstofss; - size_t bits; - - /** - * Copy less than 16 bytes - */ - if (n < 16) - { - if (n & 0x01) - { - *(u8 *) dstu = *(const u8 *) srcu; - srcu = (uword) ((const u8 *) srcu + 1); - dstu = (uword) ((u8 *) dstu + 1); - } - if (n & 0x02) - { - *(uint16_t *) dstu = *(const uint16_t *) srcu; - srcu = (uword) ((const uint16_t *) srcu + 1); - dstu = (uword) ((uint16_t *) dstu + 1); - } - if (n & 0x04) - { - *(uint32_t *) dstu = *(const uint32_t *) srcu; - srcu = (uword) ((const uint32_t *) srcu + 1); - dstu = (uword) ((uint32_t *) dstu + 1); - } - if (n & 0x08) - { - *(uint64_t *) dstu = *(const uint64_t *) srcu; - } - return ret; - } - - /** - * Fast way when copy size doesn't exceed 512 bytes - */ - if (n <= 32) - { - clib_mov16 ((u8 *) dst, (const u8 *) src); - clib_mov16 ((u8 *) dst - 16 + n, (const u8 *) src - 16 + n); - return ret; - } - if (n <= 64) - { - clib_mov32 ((u8 *) dst, (const u8 *) src); - clib_mov32 ((u8 *) dst - 32 + n, (const u8 *) src - 32 + n); - return ret; - } - if (n <= 512) - { - if (n >= 256) - { - n -= 256; - clib_mov256 ((u8 *) dst, (const u8 *) src); - src = (const u8 *) src + 256; - dst = (u8 *) dst + 256; - } - if (n >= 128) - { - n -= 128; - clib_mov128 ((u8 *) dst, (const u8 *) src); - src = (const u8 *) src + 128; - dst = (u8 *) dst + 128; - } - if (n >= 64) - { - n -= 64; - clib_mov64 ((u8 *) dst, (const u8 *) src); - src = (const u8 *) src + 64; - dst = (u8 *) dst + 64; - } - COPY_BLOCK_64_BACK31: - if (n > 32) - { - clib_mov32 ((u8 *) dst, (const u8 *) src); - clib_mov32 ((u8 *) dst - 32 + n, (const u8 *) src - 32 + n); - return ret; - } - if (n > 0) - { - clib_mov32 ((u8 *) dst - 32 + n, (const u8 *) src - 32 + n); - } - return ret; - } - - /** - * Make store aligned when copy size exceeds 512 bytes - */ - dstofss = (uword) dst & 0x1F; - if (dstofss > 0) - { - dstofss = 32 - dstofss; - n -= dstofss; - clib_mov32 ((u8 *) dst, (const u8 *) src); - src = (const u8 *) src + dstofss; - dst = (u8 *) dst + dstofss; - } - - /** - * Copy 256-byte blocks. - * Use copy block function for better instruction order control, - * which is important when load is unaligned. - */ - clib_mov256blocks ((u8 *) dst, (const u8 *) src, n); - bits = n; - n = n & 255; - bits -= n; - src = (const u8 *) src + bits; - dst = (u8 *) dst + bits; - - /** - * Copy 64-byte blocks. - * Use copy block function for better instruction order control, - * which is important when load is unaligned. - */ - if (n >= 64) - { - clib_mov64blocks ((u8 *) dst, (const u8 *) src, n); - bits = n; - n = n & 63; - bits -= n; - src = (const u8 *) src + bits; - dst = (u8 *) dst + bits; - } - - /** - * Copy whatever left - */ - goto COPY_BLOCK_64_BACK31; -} - - -#endif /* included_clib_mamcpy_avx_h */ - - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/memcpy_sse3.h b/vppinfra/vppinfra/memcpy_sse3.h deleted file mode 100644 index 4fc48c86c8b..00000000000 --- a/vppinfra/vppinfra/memcpy_sse3.h +++ /dev/null @@ -1,355 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/*- - * BSD LICENSE - * - * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. - * All rights reserved. - * - * 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. - */ - -#ifndef included_clib_memcpy_sse3_h -#define included_clib_memcpy_sse3_h - -#include <stdint.h> -#include <x86intrin.h> - -typedef u8 u8x16u __attribute__ ((vector_size (16), aligned (1))); -typedef u8 u8x32u __attribute__ ((vector_size (32), aligned (1))); - -static inline void -clib_mov16 (u8 * dst, const u8 * src) -{ - *(u8x16u *) dst = *(u8x16u *) src; -} - -static inline void -clib_mov32 (u8 * dst, const u8 * src) -{ - *(u8x32u *) dst = *(u8x32u *) src; -} - -static inline void -clib_mov64 (u8 * dst, const u8 * src) -{ - clib_mov32 ((u8 *) dst + 0 * 32, (const u8 *) src + 0 * 32); - clib_mov32 ((u8 *) dst + 1 * 32, (const u8 *) src + 1 * 32); -} - -static inline void -clib_mov128 (u8 * dst, const u8 * src) -{ - clib_mov64 ((u8 *) dst + 0 * 64, (const u8 *) src + 0 * 64); - clib_mov64 ((u8 *) dst + 1 * 64, (const u8 *) src + 1 * 64); -} - -static inline void -clib_mov256 (u8 * dst, const u8 * src) -{ - clib_mov128 ((u8 *) dst + 0 * 128, (const u8 *) src + 0 * 128); - clib_mov128 ((u8 *) dst + 1 * 128, (const u8 *) src + 1 * 128); -} - -/** - * Macro for copying unaligned block from one location to another with constant load offset, - * 47 bytes leftover maximum, - * locations should not overlap. - * Requirements: - * - Store is aligned - * - Load offset is <offset>, which must be immediate value within [1, 15] - * - For <src>, make sure <offset> bit backwards & <16 - offset> bit forwards are available for loading - * - <dst>, <src>, <len> must be variables - * - __m128i <xmm0> ~ <xmm8> must be pre-defined - */ -#define CLIB_MVUNALIGN_LEFT47_IMM(dst, src, len, offset) \ -({ \ - int tmp; \ - while (len >= 128 + 16 - offset) { \ - xmm0 = _mm_loadu_si128((const __m128i *)((const u8 *)src - offset + 0 * 16)); \ - len -= 128; \ - xmm1 = _mm_loadu_si128((const __m128i *)((const u8 *)src - offset + 1 * 16)); \ - xmm2 = _mm_loadu_si128((const __m128i *)((const u8 *)src - offset + 2 * 16)); \ - xmm3 = _mm_loadu_si128((const __m128i *)((const u8 *)src - offset + 3 * 16)); \ - xmm4 = _mm_loadu_si128((const __m128i *)((const u8 *)src - offset + 4 * 16)); \ - xmm5 = _mm_loadu_si128((const __m128i *)((const u8 *)src - offset + 5 * 16)); \ - xmm6 = _mm_loadu_si128((const __m128i *)((const u8 *)src - offset + 6 * 16)); \ - xmm7 = _mm_loadu_si128((const __m128i *)((const u8 *)src - offset + 7 * 16)); \ - xmm8 = _mm_loadu_si128((const __m128i *)((const u8 *)src - offset + 8 * 16)); \ - src = (const u8 *)src + 128; \ - _mm_storeu_si128((__m128i *)((u8 *)dst + 0 * 16), _mm_alignr_epi8(xmm1, xmm0, offset)); \ - _mm_storeu_si128((__m128i *)((u8 *)dst + 1 * 16), _mm_alignr_epi8(xmm2, xmm1, offset)); \ - _mm_storeu_si128((__m128i *)((u8 *)dst + 2 * 16), _mm_alignr_epi8(xmm3, xmm2, offset)); \ - _mm_storeu_si128((__m128i *)((u8 *)dst + 3 * 16), _mm_alignr_epi8(xmm4, xmm3, offset)); \ - _mm_storeu_si128((__m128i *)((u8 *)dst + 4 * 16), _mm_alignr_epi8(xmm5, xmm4, offset)); \ - _mm_storeu_si128((__m128i *)((u8 *)dst + 5 * 16), _mm_alignr_epi8(xmm6, xmm5, offset)); \ - _mm_storeu_si128((__m128i *)((u8 *)dst + 6 * 16), _mm_alignr_epi8(xmm7, xmm6, offset)); \ - _mm_storeu_si128((__m128i *)((u8 *)dst + 7 * 16), _mm_alignr_epi8(xmm8, xmm7, offset)); \ - dst = (u8 *)dst + 128; \ - } \ - tmp = len; \ - len = ((len - 16 + offset) & 127) + 16 - offset; \ - tmp -= len; \ - src = (const u8 *)src + tmp; \ - dst = (u8 *)dst + tmp; \ - if (len >= 32 + 16 - offset) { \ - while (len >= 32 + 16 - offset) { \ - xmm0 = _mm_loadu_si128((const __m128i *)((const u8 *)src - offset + 0 * 16)); \ - len -= 32; \ - xmm1 = _mm_loadu_si128((const __m128i *)((const u8 *)src - offset + 1 * 16)); \ - xmm2 = _mm_loadu_si128((const __m128i *)((const u8 *)src - offset + 2 * 16)); \ - src = (const u8 *)src + 32; \ - _mm_storeu_si128((__m128i *)((u8 *)dst + 0 * 16), _mm_alignr_epi8(xmm1, xmm0, offset)); \ - _mm_storeu_si128((__m128i *)((u8 *)dst + 1 * 16), _mm_alignr_epi8(xmm2, xmm1, offset)); \ - dst = (u8 *)dst + 32; \ - } \ - tmp = len; \ - len = ((len - 16 + offset) & 31) + 16 - offset; \ - tmp -= len; \ - src = (const u8 *)src + tmp; \ - dst = (u8 *)dst + tmp; \ - } \ -}) - -/** - * Macro for copying unaligned block from one location to another, - * 47 bytes leftover maximum, - * locations should not overlap. - * Use switch here because the aligning instruction requires immediate value for shift count. - * Requirements: - * - Store is aligned - * - Load offset is <offset>, which must be within [1, 15] - * - For <src>, make sure <offset> bit backwards & <16 - offset> bit forwards are available for loading - * - <dst>, <src>, <len> must be variables - * - __m128i <xmm0> ~ <xmm8> used in CLIB_MVUNALIGN_LEFT47_IMM must be pre-defined - */ -#define CLIB_MVUNALIGN_LEFT47(dst, src, len, offset) \ -({ \ - switch (offset) { \ - case 0x01: CLIB_MVUNALIGN_LEFT47_IMM(dst, src, n, 0x01); break; \ - case 0x02: CLIB_MVUNALIGN_LEFT47_IMM(dst, src, n, 0x02); break; \ - case 0x03: CLIB_MVUNALIGN_LEFT47_IMM(dst, src, n, 0x03); break; \ - case 0x04: CLIB_MVUNALIGN_LEFT47_IMM(dst, src, n, 0x04); break; \ - case 0x05: CLIB_MVUNALIGN_LEFT47_IMM(dst, src, n, 0x05); break; \ - case 0x06: CLIB_MVUNALIGN_LEFT47_IMM(dst, src, n, 0x06); break; \ - case 0x07: CLIB_MVUNALIGN_LEFT47_IMM(dst, src, n, 0x07); break; \ - case 0x08: CLIB_MVUNALIGN_LEFT47_IMM(dst, src, n, 0x08); break; \ - case 0x09: CLIB_MVUNALIGN_LEFT47_IMM(dst, src, n, 0x09); break; \ - case 0x0A: CLIB_MVUNALIGN_LEFT47_IMM(dst, src, n, 0x0A); break; \ - case 0x0B: CLIB_MVUNALIGN_LEFT47_IMM(dst, src, n, 0x0B); break; \ - case 0x0C: CLIB_MVUNALIGN_LEFT47_IMM(dst, src, n, 0x0C); break; \ - case 0x0D: CLIB_MVUNALIGN_LEFT47_IMM(dst, src, n, 0x0D); break; \ - case 0x0E: CLIB_MVUNALIGN_LEFT47_IMM(dst, src, n, 0x0E); break; \ - case 0x0F: CLIB_MVUNALIGN_LEFT47_IMM(dst, src, n, 0x0F); break; \ - default:; \ - } \ -}) - -static inline void * -clib_memcpy (void *dst, const void *src, size_t n) -{ - __m128i xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; - uword dstu = (uword) dst; - uword srcu = (uword) src; - void *ret = dst; - size_t dstofss; - size_t srcofs; - - /** - * Copy less than 16 bytes - */ - if (n < 16) - { - if (n & 0x01) - { - *(u8 *) dstu = *(const u8 *) srcu; - srcu = (uword) ((const u8 *) srcu + 1); - dstu = (uword) ((u8 *) dstu + 1); - } - if (n & 0x02) - { - *(u16 *) dstu = *(const u16 *) srcu; - srcu = (uword) ((const u16 *) srcu + 1); - dstu = (uword) ((u16 *) dstu + 1); - } - if (n & 0x04) - { - *(u32 *) dstu = *(const u32 *) srcu; - srcu = (uword) ((const u32 *) srcu + 1); - dstu = (uword) ((u32 *) dstu + 1); - } - if (n & 0x08) - { - *(u64 *) dstu = *(const u64 *) srcu; - } - return ret; - } - - /** - * Fast way when copy size doesn't exceed 512 bytes - */ - if (n <= 32) - { - clib_mov16 ((u8 *) dst, (const u8 *) src); - clib_mov16 ((u8 *) dst - 16 + n, (const u8 *) src - 16 + n); - return ret; - } - if (n <= 48) - { - clib_mov32 ((u8 *) dst, (const u8 *) src); - clib_mov16 ((u8 *) dst - 16 + n, (const u8 *) src - 16 + n); - return ret; - } - if (n <= 64) - { - clib_mov32 ((u8 *) dst, (const u8 *) src); - clib_mov16 ((u8 *) dst + 32, (const u8 *) src + 32); - clib_mov16 ((u8 *) dst - 16 + n, (const u8 *) src - 16 + n); - return ret; - } - if (n <= 128) - { - goto COPY_BLOCK_128_BACK15; - } - if (n <= 512) - { - if (n >= 256) - { - n -= 256; - clib_mov128 ((u8 *) dst, (const u8 *) src); - clib_mov128 ((u8 *) dst + 128, (const u8 *) src + 128); - src = (const u8 *) src + 256; - dst = (u8 *) dst + 256; - } - COPY_BLOCK_255_BACK15: - if (n >= 128) - { - n -= 128; - clib_mov128 ((u8 *) dst, (const u8 *) src); - src = (const u8 *) src + 128; - dst = (u8 *) dst + 128; - } - COPY_BLOCK_128_BACK15: - if (n >= 64) - { - n -= 64; - clib_mov64 ((u8 *) dst, (const u8 *) src); - src = (const u8 *) src + 64; - dst = (u8 *) dst + 64; - } - COPY_BLOCK_64_BACK15: - if (n >= 32) - { - n -= 32; - clib_mov32 ((u8 *) dst, (const u8 *) src); - src = (const u8 *) src + 32; - dst = (u8 *) dst + 32; - } - if (n > 16) - { - clib_mov16 ((u8 *) dst, (const u8 *) src); - clib_mov16 ((u8 *) dst - 16 + n, (const u8 *) src - 16 + n); - return ret; - } - if (n > 0) - { - clib_mov16 ((u8 *) dst - 16 + n, (const u8 *) src - 16 + n); - } - return ret; - } - - /** - * Make store aligned when copy size exceeds 512 bytes, - * and make sure the first 15 bytes are copied, because - * unaligned copy functions require up to 15 bytes - * backwards access. - */ - dstofss = 16 - ((uword) dst & 0x0F) + 16; - n -= dstofss; - clib_mov32 ((u8 *) dst, (const u8 *) src); - src = (const u8 *) src + dstofss; - dst = (u8 *) dst + dstofss; - srcofs = ((uword) src & 0x0F); - - /** - * For aligned copy - */ - if (srcofs == 0) - { - /** - * Copy 256-byte blocks - */ - for (; n >= 256; n -= 256) - { - clib_mov256 ((u8 *) dst, (const u8 *) src); - dst = (u8 *) dst + 256; - src = (const u8 *) src + 256; - } - - /** - * Copy whatever left - */ - goto COPY_BLOCK_255_BACK15; - } - - /** - * For copy with unaligned load - */ - CLIB_MVUNALIGN_LEFT47 (dst, src, n, srcofs); - - /** - * Copy whatever left - */ - goto COPY_BLOCK_64_BACK15; -} - - -#undef CLIB_MVUNALIGN_LEFT47_IMM -#undef CLIB_MVUNALIGN_LEFT47 - -#endif /* included_clib_memcpy_sse3_h */ - - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/mhash.c b/vppinfra/vppinfra/mhash.c deleted file mode 100644 index c917e164cd9..00000000000 --- a/vppinfra/vppinfra/mhash.c +++ /dev/null @@ -1,408 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2010 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include <vppinfra/mhash.h> - -always_inline u32 -load_partial_u32 (void *d, uword n) -{ - if (n == 4) - return ((u32 *) d)[0]; - if (n == 3) - return ((u16 *) d)[0] | (((u8 *) d)[2] << 16); - if (n == 2) - return ((u16 *) d)[0]; - if (n == 1) - return ((u8 *) d)[0]; - ASSERT (0); - return 0; -} - -always_inline u32 -mhash_key_sum_inline (void *data, uword n_data_bytes, u32 seed) -{ - u32 *d32 = data; - u32 a, b, c, n_left; - - a = b = c = seed; - n_left = n_data_bytes; - a ^= n_data_bytes; - - while (n_left > 12) - { - a += d32[0]; - b += d32[1]; - c += d32[2]; - hash_v3_mix32 (a, b, c); - n_left -= 12; - d32 += 3; - } - - if (n_left > 8) - { - c += load_partial_u32 (d32 + 2, n_left - 8); - n_left = 8; - } - if (n_left > 4) - { - b += load_partial_u32 (d32 + 1, n_left - 4); - n_left = 4; - } - if (n_left > 0) - a += load_partial_u32 (d32 + 0, n_left - 0); - - hash_v3_finalize32 (a, b, c); - - return c; -} - -#define foreach_mhash_key_size \ - _ (2) _ (3) _ (4) _ (5) _ (6) _ (7) \ - _ (8) _ (12) _ (16) _ (20) \ - _ (24) _ (28) _ (32) _ (36) \ - _ (40) _ (44) _ (48) _ (52) \ - _ (56) _ (60) _ (64) - -#define _(N_KEY_BYTES) \ - static uword \ - mhash_key_sum_##N_KEY_BYTES (hash_t * h, uword key) \ - { \ - mhash_t * hv = uword_to_pointer (h->user, mhash_t *); \ - return mhash_key_sum_inline (mhash_key_to_mem (hv, key), \ - (N_KEY_BYTES), \ - hv->hash_seed); \ - } \ - \ - static uword \ - mhash_key_equal_##N_KEY_BYTES (hash_t * h, uword key1, uword key2) \ - { \ - mhash_t * hv = uword_to_pointer (h->user, mhash_t *); \ - void * k1 = mhash_key_to_mem (hv, key1); \ - void * k2 = mhash_key_to_mem (hv, key2); \ - return ! memcmp (k1, k2, (N_KEY_BYTES)); \ - } - -foreach_mhash_key_size -#undef _ -static uword -mhash_key_sum_c_string (hash_t * h, uword key) -{ - mhash_t *hv = uword_to_pointer (h->user, mhash_t *); - void *k = mhash_key_to_mem (hv, key); - return mhash_key_sum_inline (k, strlen (k), hv->hash_seed); -} - -static uword -mhash_key_equal_c_string (hash_t * h, uword key1, uword key2) -{ - mhash_t *hv = uword_to_pointer (h->user, mhash_t *); - void *k1 = mhash_key_to_mem (hv, key1); - void *k2 = mhash_key_to_mem (hv, key2); - return strcmp (k1, k2) == 0; -} - -static uword -mhash_key_sum_vec_string (hash_t * h, uword key) -{ - mhash_t *hv = uword_to_pointer (h->user, mhash_t *); - void *k = mhash_key_to_mem (hv, key); - return mhash_key_sum_inline (k, vec_len (k), hv->hash_seed); -} - -static uword -mhash_key_equal_vec_string (hash_t * h, uword key1, uword key2) -{ - mhash_t *hv = uword_to_pointer (h->user, mhash_t *); - void *k1 = mhash_key_to_mem (hv, key1); - void *k2 = mhash_key_to_mem (hv, key2); - return vec_len (k1) == vec_len (k2) && memcmp (k1, k2, vec_len (k1)) == 0; -} - -/* The CLIB hash user pointer must always point to a valid mhash_t. - Now, the address of mhash_t can change (think vec_resize). - So we must always be careful that it points to the correct - address. */ -always_inline void -mhash_sanitize_hash_user (mhash_t * mh) -{ - uword *hash = mh->hash; - hash_t *h = hash_header (hash); - h->user = pointer_to_uword (mh); -} - -void -mhash_init (mhash_t * h, uword n_value_bytes, uword n_key_bytes) -{ - static struct - { - hash_key_sum_function_t *key_sum; - hash_key_equal_function_t *key_equal; - } t[] = - { -#define _(N_KEY_BYTES) \ - [N_KEY_BYTES] = { \ - .key_sum = mhash_key_sum_##N_KEY_BYTES, \ - .key_equal = mhash_key_equal_##N_KEY_BYTES, \ - }, - - foreach_mhash_key_size -#undef _ - [MHASH_C_STRING_KEY] = - { - .key_sum = mhash_key_sum_c_string,.key_equal = mhash_key_equal_c_string,}, - [MHASH_VEC_STRING_KEY] = - { - .key_sum = mhash_key_sum_vec_string,.key_equal = - mhash_key_equal_vec_string,},}; - - if (mhash_key_vector_is_heap (h)) - heap_free (h->key_vector_or_heap); - else - vec_free (h->key_vector_or_heap); - vec_free (h->key_vector_free_indices); - { - int i; - for (i = 0; i < vec_len (h->key_tmps); i++) - vec_free (h->key_tmps[i]); - } - vec_free (h->key_tmps); - hash_free (h->hash); - - memset (h, 0, sizeof (h[0])); - h->n_key_bytes = n_key_bytes; - -#if 0 - if (h->n_key_bytes > 0) - { - vec_validate (h->key_tmp, h->n_key_bytes - 1); - _vec_len (h->key_tmp) = 0; - } -#endif - - ASSERT (n_key_bytes < ARRAY_LEN (t)); - h->hash = hash_create2 ( /* elts */ 0, - /* user */ pointer_to_uword (h), - /* value_bytes */ n_value_bytes, - t[n_key_bytes].key_sum, t[n_key_bytes].key_equal, - /* format pair/arg */ - 0, 0); -} - -static uword -mhash_set_tmp_key (mhash_t * h, const void *key) -{ - u8 *key_tmp; - int my_cpu = os_get_cpu_number (); - - vec_validate (h->key_tmps, my_cpu); - key_tmp = h->key_tmps[my_cpu]; - - vec_reset_length (key_tmp); - - if (mhash_key_vector_is_heap (h)) - { - uword is_c_string = h->n_key_bytes == MHASH_C_STRING_KEY; - - if (is_c_string) - vec_add (key_tmp, key, strlen (key) + 1); - else - vec_add (key_tmp, key, vec_len (key)); - } - else - vec_add (key_tmp, key, h->n_key_bytes); - - h->key_tmps[my_cpu] = key_tmp; - - return ~0; -} - -hash_pair_t * -mhash_get_pair (mhash_t * h, const void *key) -{ - uword ikey; - mhash_sanitize_hash_user (h); - ikey = mhash_set_tmp_key (h, key); - return hash_get_pair (h->hash, ikey); -} - -typedef struct -{ - u32 heap_handle; - - /* Must conincide with vec_header. */ - vec_header_t vec; -} mhash_string_key_t; - -uword -mhash_set_mem (mhash_t * h, void *key, uword * new_value, uword * old_value) -{ - u8 *k; - uword ikey, i, l = 0, n_key_bytes, old_n_elts, key_alloc_from_free_list = 0; - - mhash_sanitize_hash_user (h); - - if (mhash_key_vector_is_heap (h)) - { - mhash_string_key_t *sk; - uword is_c_string = h->n_key_bytes == MHASH_C_STRING_KEY; - uword handle; - - n_key_bytes = is_c_string ? (strlen (key) + 1) : vec_len (key); - i = - heap_alloc (h->key_vector_or_heap, n_key_bytes + sizeof (sk[0]), - handle); - - sk = (void *) (h->key_vector_or_heap + i); - sk->heap_handle = handle; - sk->vec.len = n_key_bytes; - clib_memcpy (sk->vec.vector_data, key, n_key_bytes); - - /* Advance key past vector header. */ - i += sizeof (sk[0]); - } - else - { - key_alloc_from_free_list = (l = - vec_len (h->key_vector_free_indices)) > 0; - if (key_alloc_from_free_list) - { - i = h->key_vector_free_indices[l - 1]; - k = vec_elt_at_index (h->key_vector_or_heap, i); - _vec_len (h->key_vector_free_indices) = l - 1; - } - else - { - vec_add2 (h->key_vector_or_heap, k, h->n_key_bytes); - i = k - h->key_vector_or_heap; - } - - n_key_bytes = h->n_key_bytes; - clib_memcpy (k, key, n_key_bytes); - } - ikey = i; - - old_n_elts = hash_elts (h->hash); - h->hash = _hash_set3 (h->hash, ikey, new_value, old_value); - - /* If element already existed remove duplicate key. */ - if (hash_elts (h->hash) == old_n_elts) - { - hash_pair_t *p; - - /* Fetch old key for return value. */ - p = hash_get_pair (h->hash, ikey); - ikey = p->key; - - /* Remove duplicate key. */ - if (mhash_key_vector_is_heap (h)) - { - mhash_string_key_t *sk; - sk = (void *) (h->key_vector_or_heap + i - sizeof (sk[0])); - heap_dealloc (h->key_vector_or_heap, sk->heap_handle); - } - else - { - if (key_alloc_from_free_list) - { - h->key_vector_free_indices[l] = i; - _vec_len (h->key_vector_free_indices) = l + 1; - } - else - _vec_len (h->key_vector_or_heap) -= h->n_key_bytes; - } - } - - return ikey; -} - -uword -mhash_unset (mhash_t * h, void *key, uword * old_value) -{ - hash_pair_t *p; - uword i; - - mhash_sanitize_hash_user (h); - i = mhash_set_tmp_key (h, key); - - p = hash_get_pair (h->hash, i); - if (!p) - return 0; - - ASSERT (p->key != ~0); - i = p->key; - - if (mhash_key_vector_is_heap (h)) - { - mhash_string_key_t *sk; - sk = (void *) (h->key_vector_or_heap + i) - sizeof (sk[0]); - heap_dealloc (h->key_vector_or_heap, sk->heap_handle); - } - else - vec_add1 (h->key_vector_free_indices, i); - - hash_unset3 (h->hash, i, old_value); - return 1; -} - -u8 * -format_mhash_key (u8 * s, va_list * va) -{ - mhash_t *h = va_arg (*va, mhash_t *); - u32 ki = va_arg (*va, u32); - void *k = mhash_key_to_mem (h, ki); - - if (mhash_key_vector_is_heap (h)) - { - uword is_c_string = h->n_key_bytes == MHASH_C_STRING_KEY; - u32 l = is_c_string ? strlen (k) : vec_len (k); - vec_add (s, k, l); - } - else if (h->format_key) - s = format (s, "%U", h->format_key, k); - else - s = format (s, "%U", format_hex_bytes, k, h->n_key_bytes); - - return s; -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/mhash.h b/vppinfra/vppinfra/mhash.h deleted file mode 100644 index 102adf4eb83..00000000000 --- a/vppinfra/vppinfra/mhash.h +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef included_clib_mhash_h -#define included_clib_mhash_h - -/* - Copyright (c) 2010 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include <vppinfra/format.h> -#include <vppinfra/hash.h> -#include <vppinfra/heap.h> - -/* Hash table plus vector of keys. */ -typedef struct -{ - /* Vector or heap used to store keys. Hash table stores keys as byte - offsets into this vector. */ - u8 *key_vector_or_heap; - - /* Byte offsets of free keys in vector (used to store free keys when - n_key_bytes > 1). */ - u32 *key_vector_free_indices; - - u8 **key_tmps; - - /* Possibly fixed size of key. - 0 means keys are vectors of u8's. - 1 means keys are null terminated c strings. */ -#define MHASH_VEC_STRING_KEY 0 -#define MHASH_C_STRING_KEY 1 - u32 n_key_bytes; - - /* Seed value for Jenkins hash. */ - u32 hash_seed; - - /* Hash table mapping key -> value. */ - uword *hash; - - /* Format function for keys. */ - format_function_t *format_key; -} mhash_t; - -void mhash_init (mhash_t * h, uword n_value_bytes, uword n_key_bytes); - -always_inline void -mhash_init_c_string (mhash_t * h, uword n_value_bytes) -{ - mhash_init (h, n_value_bytes, MHASH_C_STRING_KEY); -} - -always_inline void -mhash_init_vec_string (mhash_t * h, uword n_value_bytes) -{ - mhash_init (h, n_value_bytes, MHASH_VEC_STRING_KEY); -} - -always_inline void * -mhash_key_to_mem (mhash_t * h, uword key) -{ - if (key == ~0) - { - u8 *key_tmp; - - int my_cpu = os_get_cpu_number (); - vec_validate (h->key_tmps, my_cpu); - key_tmp = h->key_tmps[my_cpu]; - return key_tmp; - } - return vec_elt_at_index (h->key_vector_or_heap, key); -} - -hash_pair_t *mhash_get_pair (mhash_t * h, const void *key); -uword mhash_set_mem (mhash_t * h, void *key, uword * new_value, - uword * old_value); -uword mhash_unset (mhash_t * h, void *key, uword * old_value); - -always_inline uword * -mhash_get (mhash_t * h, const void *key) -{ - hash_pair_t *p = mhash_get_pair (h, key); - return p ? &p->value[0] : 0; -} - -always_inline uword -mhash_set (mhash_t * h, void *key, uword new_value, uword * old_value) -{ - return mhash_set_mem (h, key, &new_value, old_value); -} - -always_inline uword -mhash_unset_key (mhash_t * h, uword key, uword * old_value) -{ - void *k = mhash_key_to_mem (h, key); - return mhash_unset (h, k, old_value); -} - -always_inline uword -mhash_value_bytes (mhash_t * m) -{ - hash_t *h = hash_header (m->hash); - return hash_value_bytes (h); -} - -always_inline uword -mhash_elts (mhash_t * m) -{ - return hash_elts (m->hash); -} - -always_inline uword -mhash_key_vector_is_heap (mhash_t * h) -{ - return h->n_key_bytes <= 1; -} - -always_inline void -mhash_free (mhash_t * h) -{ - if (mhash_key_vector_is_heap (h)) - heap_free (h->key_vector_or_heap); - else - vec_free (h->key_vector_or_heap); - vec_free (h->key_vector_free_indices); - hash_free (h->hash); -} - -#define mhash_foreach(k,v,mh,body) \ -do { \ - hash_pair_t * _mhash_foreach_p; \ - hash_foreach_pair (_mhash_foreach_p, (mh)->hash, ({ \ - (k) = mhash_key_to_mem ((mh), _mhash_foreach_p->key); \ - (v) = &_mhash_foreach_p->value[0]; \ - body; \ - })); \ -} while (0) - -format_function_t format_mhash_key; - -#endif /* included_clib_mhash_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/mheap.c b/vppinfra/vppinfra/mheap.c deleted file mode 100644 index b8828f9e3e7..00000000000 --- a/vppinfra/vppinfra/mheap.c +++ /dev/null @@ -1,1649 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include <vppinfra/bitops.h> -#include <vppinfra/hash.h> -#include <vppinfra/format.h> -#include <vppinfra/mheap.h> -#include <vppinfra/os.h> -#include <vppinfra/time.h> - -#ifdef CLIB_UNIX -#include <vppinfra/elf_clib.h> -#endif - -static void mheap_get_trace (void *v, uword offset, uword size); -static void mheap_put_trace (void *v, uword offset, uword size); -static int mheap_trace_sort (const void *t1, const void *t2); - -always_inline void -mheap_maybe_lock (void *v) -{ - mheap_t *h = mheap_header (v); - if (v && (h->flags & MHEAP_FLAG_THREAD_SAFE)) - { - u32 my_cpu = os_get_cpu_number (); - if (h->owner_cpu == my_cpu) - { - h->recursion_count++; - return; - } - - while (__sync_lock_test_and_set (&h->lock, 1)) - ; - - h->owner_cpu = my_cpu; - h->recursion_count = 1; - } -} - -always_inline void -mheap_maybe_unlock (void *v) -{ - mheap_t *h = mheap_header (v); - if (v && h->flags & MHEAP_FLAG_THREAD_SAFE) - { - ASSERT (os_get_cpu_number () == h->owner_cpu); - if (--h->recursion_count == 0) - { - h->owner_cpu = ~0; - CLIB_MEMORY_BARRIER (); - h->lock = 0; - } - } -} - -/* Find bin for objects with size at least n_user_data_bytes. */ -always_inline uword -user_data_size_to_bin_index (uword n_user_data_bytes) -{ - uword n_user_data_words; - word small_bin, large_bin; - - /* User size must be at least big enough to hold free elt. */ - n_user_data_bytes = clib_max (n_user_data_bytes, MHEAP_MIN_USER_DATA_BYTES); - - /* Round to words. */ - n_user_data_words = - (round_pow2 (n_user_data_bytes, MHEAP_USER_DATA_WORD_BYTES) / - MHEAP_USER_DATA_WORD_BYTES); - - ASSERT (n_user_data_words > 0); - small_bin = - n_user_data_words - - (MHEAP_MIN_USER_DATA_BYTES / MHEAP_USER_DATA_WORD_BYTES); - ASSERT (small_bin >= 0); - - large_bin = - MHEAP_N_SMALL_OBJECT_BINS + max_log2 (n_user_data_bytes) - - MHEAP_LOG2_N_SMALL_OBJECT_BINS; - - return small_bin < MHEAP_N_SMALL_OBJECT_BINS ? small_bin : large_bin; -} - -always_inline uword -mheap_elt_size_to_user_n_bytes (uword n_bytes) -{ - ASSERT (n_bytes >= sizeof (mheap_elt_t)); - return (n_bytes - STRUCT_OFFSET_OF (mheap_elt_t, user_data)); -} - -always_inline uword __attribute__ ((unused)) -mheap_elt_size_to_user_n_words (uword n_bytes) -{ - ASSERT (n_bytes % MHEAP_USER_DATA_WORD_BYTES == 0); - return mheap_elt_size_to_user_n_bytes (n_bytes) / - MHEAP_USER_DATA_WORD_BYTES; -} - -always_inline void -mheap_elt_set_size (void *v, - uword uoffset, uword n_user_data_bytes, uword is_free) -{ - mheap_elt_t *e, *n; - - e = mheap_elt_at_uoffset (v, uoffset); - - ASSERT (n_user_data_bytes % MHEAP_USER_DATA_WORD_BYTES == 0); - - e->n_user_data = n_user_data_bytes / MHEAP_USER_DATA_WORD_BYTES; - e->is_free = is_free; - ASSERT (e->prev_n_user_data * sizeof (e->user_data[0]) >= - MHEAP_MIN_USER_DATA_BYTES); - - n = mheap_next_elt (e); - n->prev_n_user_data = e->n_user_data; - n->prev_is_free = is_free; -} - -always_inline void -set_first_free_elt_offset (mheap_t * h, uword bin, uword uoffset) -{ - uword i0, i1; - - h->first_free_elt_uoffset_by_bin[bin] = uoffset; - - i0 = bin / BITS (h->non_empty_free_elt_heads[0]); - i1 = (uword) 1 << (uword) (bin % BITS (h->non_empty_free_elt_heads[0])); - - ASSERT (i0 < ARRAY_LEN (h->non_empty_free_elt_heads)); - if (h->first_free_elt_uoffset_by_bin[bin] == MHEAP_GROUNDED) - h->non_empty_free_elt_heads[i0] &= ~i1; - else - h->non_empty_free_elt_heads[i0] |= i1; -} - -always_inline void -set_free_elt (void *v, uword uoffset, uword n_user_data_bytes) -{ - mheap_t *h = mheap_header (v); - mheap_elt_t *e = mheap_elt_at_uoffset (v, uoffset); - mheap_elt_t *n = mheap_next_elt (e); - uword bin = user_data_size_to_bin_index (n_user_data_bytes); - - ASSERT (n->prev_is_free); - ASSERT (e->is_free); - - e->free_elt.prev_uoffset = MHEAP_GROUNDED; - e->free_elt.next_uoffset = h->first_free_elt_uoffset_by_bin[bin]; - - /* Fill in next free elt's previous pointer. */ - if (e->free_elt.next_uoffset != MHEAP_GROUNDED) - { - mheap_elt_t *nf = mheap_elt_at_uoffset (v, e->free_elt.next_uoffset); - ASSERT (nf->is_free); - nf->free_elt.prev_uoffset = uoffset; - } - - set_first_free_elt_offset (h, bin, uoffset); -} - -always_inline void -new_free_elt (void *v, uword uoffset, uword n_user_data_bytes) -{ - mheap_elt_set_size (v, uoffset, n_user_data_bytes, /* is_free */ 1); - set_free_elt (v, uoffset, n_user_data_bytes); -} - -always_inline void -remove_free_elt (void *v, mheap_elt_t * e, uword bin) -{ - mheap_t *h = mheap_header (v); - mheap_elt_t *p, *n; -#if CLIB_VEC64 > 0 - u64 no, po; -#else - u32 no, po; -#endif - - no = e->free_elt.next_uoffset; - - n = no != MHEAP_GROUNDED ? mheap_elt_at_uoffset (v, no) : 0; - po = e->free_elt.prev_uoffset; - p = po != MHEAP_GROUNDED ? mheap_elt_at_uoffset (v, po) : 0; - - if (!p) - set_first_free_elt_offset (h, bin, no); - else - p->free_elt.next_uoffset = no; - - if (n) - n->free_elt.prev_uoffset = po; -} - -always_inline void -remove_free_elt2 (void *v, mheap_elt_t * e) -{ - uword bin; - bin = user_data_size_to_bin_index (mheap_elt_data_bytes (e)); - remove_free_elt (v, e, bin); -} - -#define MHEAP_VM_MAP (1 << 0) -#define MHEAP_VM_UNMAP (1 << 1) -#define MHEAP_VM_NOMAP (0 << 1) -#define MHEAP_VM_ROUND (1 << 2) -#define MHEAP_VM_ROUND_UP MHEAP_VM_ROUND -#define MHEAP_VM_ROUND_DOWN (0 << 2) - -static uword mheap_page_size; - -static_always_inline uword -mheap_page_round (uword addr) -{ - return (addr + mheap_page_size - 1) & ~(mheap_page_size - 1); -} - -static_always_inline uword -mheap_page_truncate (uword addr) -{ - return addr & ~(mheap_page_size - 1); -} - -static_always_inline uword -mheap_vm (void *v, uword flags, clib_address_t start_addr, uword size) -{ - mheap_t *h = mheap_header (v); - clib_address_t start_page, end_page, end_addr; - uword mapped_bytes; - - ASSERT (!(h->flags & MHEAP_FLAG_DISABLE_VM)); - - end_addr = start_addr + size; - - /* Round start/end address up to page boundary. */ - start_page = mheap_page_round (start_addr); - - if ((flags & MHEAP_VM_ROUND) == MHEAP_VM_ROUND_UP) - end_page = mheap_page_round (end_addr); - else - end_page = mheap_page_truncate (end_addr); - - mapped_bytes = 0; - if (end_page > start_page) - { - mapped_bytes = end_page - start_page; - if (flags & MHEAP_VM_MAP) - clib_mem_vm_map ((void *) start_page, end_page - start_page); - else if (flags & MHEAP_VM_UNMAP) - clib_mem_vm_unmap ((void *) start_page, end_page - start_page); - } - - return mapped_bytes; -} - -static_always_inline uword -mheap_vm_elt (void *v, uword flags, uword offset) -{ - mheap_elt_t *e; - clib_address_t start_addr, end_addr; - - e = mheap_elt_at_uoffset (v, offset); - start_addr = (clib_address_t) ((void *) e->user_data); - end_addr = (clib_address_t) mheap_next_elt (e); - return mheap_vm (v, flags, start_addr, end_addr - start_addr); -} - -always_inline uword -mheap_small_object_cache_mask (mheap_small_object_cache_t * c, uword bin) -{ - uword mask; - -/* $$$$ ELIOT FIXME: add Altivec version of this routine */ -#if !defined (CLIB_HAVE_VEC128) || defined (__ALTIVEC__) - mask = 0; -#else - u8x16 b = u8x16_splat (bin); - - ASSERT (bin < 256); - -#define _(i) ((uword) u8x16_compare_byte_mask (u8x16_is_equal (b, c->bins.as_u8x16[i])) << (uword) ((i)*16)) - mask = _(0) | _(1); - if (BITS (uword) > 32) - mask |= _(2) | _(3); -#undef _ - -#endif - return mask; -} - -always_inline uword -mheap_get_small_object (mheap_t * h, uword bin) -{ - mheap_small_object_cache_t *c = &h->small_object_cache; - uword mask = mheap_small_object_cache_mask (c, bin + 1); - uword offset = MHEAP_GROUNDED; - - if (mask) - { - uword i = min_log2 (mask); - uword o = c->offsets[i]; - ASSERT (o != MHEAP_GROUNDED); - c->bins.as_u8[i] = 0; - offset = o; - } - - return offset; -} - -always_inline uword -mheap_put_small_object (mheap_t * h, uword bin, uword offset) -{ - mheap_small_object_cache_t *c = &h->small_object_cache; - uword free_mask = mheap_small_object_cache_mask (c, 0); - uword b = bin + 1; - uword i; - - if (free_mask != 0) - { - i = min_log2 (free_mask); - c->bins.as_u8[i] = b; - c->offsets[i] = offset; - return 0; - } - else - /* Nothing free with right size: cyclic replacement. */ - { - uword old_offset; - - i = c->replacement_index++; - i %= BITS (uword); - c->bins.as_u8[i] = b; - old_offset = c->offsets[i]; - c->offsets[i] = offset; - - /* Return old offset so it can be freed. */ - return old_offset; - } -} - -static uword -mheap_get_search_free_bin (void *v, - uword bin, - uword * n_user_data_bytes_arg, - uword align, uword align_offset) -{ - mheap_t *h = mheap_header (v); - mheap_elt_t *e; - - /* Free object is at offset f0 ... f1; - Allocatted object is at offset o0 ... o1. */ - word o0, o1, f0, f1, search_n_user_data_bytes; - word lo_free_usize, hi_free_usize; - - ASSERT (h->first_free_elt_uoffset_by_bin[bin] != MHEAP_GROUNDED); - e = mheap_elt_at_uoffset (v, h->first_free_elt_uoffset_by_bin[bin]); - - search_n_user_data_bytes = *n_user_data_bytes_arg; - - /* Silence compiler warning. */ - o0 = o1 = f0 = f1 = 0; - - h->stats.free_list.n_search_attempts += 1; - - /* Find an object that is large enough with correct alignment at given alignment offset. */ - while (1) - { - uword this_object_n_user_data_bytes = mheap_elt_data_bytes (e); - - ASSERT (e->is_free); - if (bin < MHEAP_N_SMALL_OBJECT_BINS) - ASSERT (this_object_n_user_data_bytes >= search_n_user_data_bytes); - - h->stats.free_list.n_objects_searched += 1; - - if (this_object_n_user_data_bytes < search_n_user_data_bytes) - goto next; - - /* Bounds of free object: from f0 to f1. */ - f0 = ((void *) e->user_data - v); - f1 = f0 + this_object_n_user_data_bytes; - - /* Place candidate object at end of free block and align as requested. */ - o0 = ((f1 - search_n_user_data_bytes) & ~(align - 1)) - align_offset; - while (o0 < f0) - o0 += align; - - /* Make sure that first free fragment is either empty or - large enough to be valid. */ - while (1) - { - lo_free_usize = o0 != f0 ? o0 - f0 - MHEAP_ELT_OVERHEAD_BYTES : 0; - if (o0 <= f0 || lo_free_usize >= (word) MHEAP_MIN_USER_DATA_BYTES) - break; - o0 -= align; - } - - o1 = o0 + search_n_user_data_bytes; - - /* Does it fit? */ - if (o0 >= f0 && o1 <= f1) - goto found; - - next: - /* Reached end of free list without finding large enough object. */ - if (e->free_elt.next_uoffset == MHEAP_GROUNDED) - return MHEAP_GROUNDED; - - /* Otherwise keep searching for large enough object. */ - e = mheap_elt_at_uoffset (v, e->free_elt.next_uoffset); - } - -found: - /* Free fragment at end. */ - hi_free_usize = f1 != o1 ? f1 - o1 - MHEAP_ELT_OVERHEAD_BYTES : 0; - - /* If fragment at end is too small to be a new object, - give user's object a bit more space than requested. */ - if (hi_free_usize < (word) MHEAP_MIN_USER_DATA_BYTES) - { - search_n_user_data_bytes += f1 - o1; - o1 = f1; - hi_free_usize = 0; - } - - /* Need to make sure that relevant memory areas are mapped. */ - if (!(h->flags & MHEAP_FLAG_DISABLE_VM)) - { - mheap_elt_t *f0_elt = mheap_elt_at_uoffset (v, f0); - mheap_elt_t *f1_elt = mheap_elt_at_uoffset (v, f1); - mheap_elt_t *o0_elt = mheap_elt_at_uoffset (v, o0); - mheap_elt_t *o1_elt = mheap_elt_at_uoffset (v, o1); - - uword f0_page_start, f0_page_end; - uword o0_page_start, o0_page_end; - - /* Free elt is mapped. Addresses after that may not be mapped. */ - f0_page_start = mheap_page_round (pointer_to_uword (f0_elt->user_data)); - f0_page_end = mheap_page_truncate (pointer_to_uword (f1_elt)); - - o0_page_start = mheap_page_truncate (pointer_to_uword (o0_elt)); - o0_page_end = mheap_page_round (pointer_to_uword (o1_elt->user_data)); - - if (o0_page_start < f0_page_start) - o0_page_start = f0_page_start; - if (o0_page_end > f0_page_end) - o0_page_end = f0_page_end; - - if (o0_page_end > o0_page_start) - clib_mem_vm_map (uword_to_pointer (o0_page_start, void *), - o0_page_end - o0_page_start); - } - - /* Remove free object from free list. */ - remove_free_elt (v, e, bin); - - /* Free fragment at begining. */ - if (lo_free_usize > 0) - { - ASSERT (lo_free_usize >= (word) MHEAP_MIN_USER_DATA_BYTES); - mheap_elt_set_size (v, f0, lo_free_usize, /* is_free */ 1); - new_free_elt (v, f0, lo_free_usize); - } - - mheap_elt_set_size (v, o0, search_n_user_data_bytes, /* is_free */ 0); - - if (hi_free_usize > 0) - { - uword uo = o1 + MHEAP_ELT_OVERHEAD_BYTES; - mheap_elt_set_size (v, uo, hi_free_usize, /* is_free */ 1); - new_free_elt (v, uo, hi_free_usize); - } - - /* Return actual size of block. */ - *n_user_data_bytes_arg = search_n_user_data_bytes; - - h->stats.free_list.n_objects_found += 1; - - return o0; -} - -/* Search free lists for object with given size and alignment. */ -static uword -mheap_get_search_free_list (void *v, - uword * n_user_bytes_arg, - uword align, uword align_offset) -{ - mheap_t *h = mheap_header (v); - uword bin, n_user_bytes, i, bi; - - n_user_bytes = *n_user_bytes_arg; - bin = user_data_size_to_bin_index (n_user_bytes); - - if (MHEAP_HAVE_SMALL_OBJECT_CACHE - && (h->flags & MHEAP_FLAG_SMALL_OBJECT_CACHE) - && bin < 255 - && align == STRUCT_SIZE_OF (mheap_elt_t, user_data[0]) - && align_offset == 0) - { - uword r = mheap_get_small_object (h, bin); - h->stats.n_small_object_cache_attempts += 1; - if (r != MHEAP_GROUNDED) - { - h->stats.n_small_object_cache_hits += 1; - return r; - } - } - - for (i = bin / BITS (uword); i < ARRAY_LEN (h->non_empty_free_elt_heads); - i++) - { - uword non_empty_bin_mask = h->non_empty_free_elt_heads[i]; - - /* No need to search smaller bins. */ - if (i == bin / BITS (uword)) - non_empty_bin_mask &= ~pow2_mask (bin % BITS (uword)); - - /* Search each occupied free bin which is large enough. */ - foreach_set_bit (bi, non_empty_bin_mask, ( - { - uword r = - mheap_get_search_free_bin (v, - bi - + - i - * - BITS - (uword), - n_user_bytes_arg, - align, - align_offset); - if (r != - MHEAP_GROUNDED) return - r;} - )); - } - - return MHEAP_GROUNDED; -} - -static never_inline void * -mheap_get_extend_vector (void *v, - uword n_user_data_bytes, - uword align, - uword align_offset, uword * offset_return) -{ - /* Bounds of free and allocated objects (as above). */ - uword f0, f1, o0, o1; - word free_size; - mheap_t *h = mheap_header (v); - mheap_elt_t *e; - - if (_vec_len (v) == 0) - { - _vec_len (v) = MHEAP_ELT_OVERHEAD_BYTES; - - /* Create first element of heap. */ - e = mheap_elt_at_uoffset (v, _vec_len (v)); - e->prev_n_user_data = MHEAP_N_USER_DATA_INVALID; - } - - f0 = _vec_len (v); - - o0 = round_pow2 (f0, align) - align_offset; - while (1) - { - free_size = o0 - f0 - MHEAP_ELT_OVERHEAD_BYTES; - if (o0 == f0 || free_size >= (word) sizeof (mheap_elt_t)) - break; - - o0 += align; - } - - o1 = o0 + n_user_data_bytes; - f1 = o1 + MHEAP_ELT_OVERHEAD_BYTES; - - ASSERT (v != 0); - h = mheap_header (v); - - /* Make sure we have space for object plus overhead. */ - if (f1 > h->max_size) - { - *offset_return = MHEAP_GROUNDED; - return v; - } - - _vec_len (v) = f1; - - if (!(h->flags & MHEAP_FLAG_DISABLE_VM)) - { - mheap_elt_t *f0_elt = mheap_elt_at_uoffset (v, f0); - mheap_elt_t *f1_elt = mheap_elt_at_uoffset (v, f1); - - uword f0_page = mheap_page_round (pointer_to_uword (f0_elt->user_data)); - uword f1_page = mheap_page_round (pointer_to_uword (f1_elt->user_data)); - - if (f1_page > f0_page) - mheap_vm (v, MHEAP_VM_MAP, f0_page, f1_page - f0_page); - } - - if (free_size > 0) - new_free_elt (v, f0, free_size); - - mheap_elt_set_size (v, o0, n_user_data_bytes, /* is_free */ 0); - - /* Mark last element. */ - e = mheap_elt_at_uoffset (v, f1); - e->n_user_data = MHEAP_N_USER_DATA_INVALID; - - *offset_return = o0; - - return v; -} - -void * -mheap_get_aligned (void *v, - uword n_user_data_bytes, - uword align, uword align_offset, uword * offset_return) -{ - mheap_t *h; - uword offset; - u64 cpu_times[2]; - - cpu_times[0] = clib_cpu_time_now (); - - align = clib_max (align, STRUCT_SIZE_OF (mheap_elt_t, user_data[0])); - align = max_pow2 (align); - - /* Correct align offset to be smaller than alignment. */ - align_offset &= (align - 1); - - /* Align offset must be multiple of minimum object size. */ - if (align_offset % STRUCT_SIZE_OF (mheap_elt_t, user_data[0]) != 0) - { - *offset_return = MHEAP_GROUNDED; - return v; - } - - /* Round requested size. */ - n_user_data_bytes = clib_max (n_user_data_bytes, MHEAP_MIN_USER_DATA_BYTES); - n_user_data_bytes = - round_pow2 (n_user_data_bytes, - STRUCT_SIZE_OF (mheap_elt_t, user_data[0])); - - if (!v) - v = mheap_alloc (0, 64 << 20); - - mheap_maybe_lock (v); - - h = mheap_header (v); - - if (h->flags & MHEAP_FLAG_VALIDATE) - mheap_validate (v); - - /* First search free lists for object. */ - offset = - mheap_get_search_free_list (v, &n_user_data_bytes, align, align_offset); - - h = mheap_header (v); - - /* If that fails allocate object at end of heap by extending vector. */ - if (offset == MHEAP_GROUNDED && _vec_len (v) < h->max_size) - { - v = - mheap_get_extend_vector (v, n_user_data_bytes, align, align_offset, - &offset); - h = mheap_header (v); - h->stats.n_vector_expands += offset != MHEAP_GROUNDED; - } - - *offset_return = offset; - if (offset != MHEAP_GROUNDED) - { - h->n_elts += 1; - - if (h->flags & MHEAP_FLAG_TRACE) - { - /* Recursion block for case when we are traceing main clib heap. */ - h->flags &= ~MHEAP_FLAG_TRACE; - - mheap_get_trace (v, offset, n_user_data_bytes); - - h->flags |= MHEAP_FLAG_TRACE; - } - } - - if (h->flags & MHEAP_FLAG_VALIDATE) - mheap_validate (v); - - mheap_maybe_unlock (v); - - cpu_times[1] = clib_cpu_time_now (); - h->stats.n_clocks_get += cpu_times[1] - cpu_times[0]; - h->stats.n_gets += 1; - - return v; -} - -static void -free_last_elt (void *v, mheap_elt_t * e) -{ - mheap_t *h = mheap_header (v); - - /* Possibly delete preceeding free element also. */ - if (e->prev_is_free) - { - e = mheap_prev_elt (e); - remove_free_elt2 (v, e); - } - - if (e->prev_n_user_data == MHEAP_N_USER_DATA_INVALID) - { - if (!(h->flags & MHEAP_FLAG_DISABLE_VM)) - mheap_vm_elt (v, MHEAP_VM_UNMAP, mheap_elt_uoffset (v, e)); - _vec_len (v) = 0; - } - else - { - uword uo = mheap_elt_uoffset (v, e); - if (!(h->flags & MHEAP_FLAG_DISABLE_VM)) - mheap_vm_elt (v, MHEAP_VM_UNMAP, uo); - e->n_user_data = MHEAP_N_USER_DATA_INVALID; - _vec_len (v) = uo; - } -} - -void -mheap_put (void *v, uword uoffset) -{ - mheap_t *h; - uword n_user_data_bytes, bin; - mheap_elt_t *e, *n; - uword trace_uoffset, trace_n_user_data_bytes; - u64 cpu_times[2]; - - cpu_times[0] = clib_cpu_time_now (); - - h = mheap_header (v); - - mheap_maybe_lock (v); - - if (h->flags & MHEAP_FLAG_VALIDATE) - mheap_validate (v); - - ASSERT (h->n_elts > 0); - h->n_elts--; - h->stats.n_puts += 1; - - e = mheap_elt_at_uoffset (v, uoffset); - n = mheap_next_elt (e); - n_user_data_bytes = mheap_elt_data_bytes (e); - - trace_uoffset = uoffset; - trace_n_user_data_bytes = n_user_data_bytes; - - bin = user_data_size_to_bin_index (n_user_data_bytes); - if (MHEAP_HAVE_SMALL_OBJECT_CACHE - && bin < 255 && (h->flags & MHEAP_FLAG_SMALL_OBJECT_CACHE)) - { - uoffset = mheap_put_small_object (h, bin, uoffset); - if (uoffset == 0) - goto done; - - e = mheap_elt_at_uoffset (v, uoffset); - n = mheap_next_elt (e); - n_user_data_bytes = mheap_elt_data_bytes (e); - } - - /* Assert that forward and back pointers are equal. */ - if (e->n_user_data != n->prev_n_user_data) - os_panic (); - - /* Forward and backwards is_free must agree. */ - if (e->is_free != n->prev_is_free) - os_panic (); - - /* Object was already freed. */ - if (e->is_free) - os_panic (); - - /* Special case: delete last element in heap. */ - if (n->n_user_data == MHEAP_N_USER_DATA_INVALID) - free_last_elt (v, e); - - else - { - uword f0, f1, n_combine; - - f0 = uoffset; - f1 = f0 + n_user_data_bytes; - n_combine = 0; - - if (e->prev_is_free) - { - mheap_elt_t *p = mheap_prev_elt (e); - f0 = mheap_elt_uoffset (v, p); - remove_free_elt2 (v, p); - n_combine++; - } - - if (n->is_free) - { - mheap_elt_t *m = mheap_next_elt (n); - f1 = (void *) m - v; - remove_free_elt2 (v, n); - n_combine++; - } - - if (n_combine) - mheap_elt_set_size (v, f0, f1 - f0, /* is_free */ 1); - else - e->is_free = n->prev_is_free = 1; - set_free_elt (v, f0, f1 - f0); - - if (!(h->flags & MHEAP_FLAG_DISABLE_VM)) - mheap_vm_elt (v, MHEAP_VM_UNMAP, f0); - } - -done: - h = mheap_header (v); - - if (h->flags & MHEAP_FLAG_TRACE) - { - /* Recursion block for case when we are traceing main clib heap. */ - h->flags &= ~MHEAP_FLAG_TRACE; - - mheap_put_trace (v, trace_uoffset, trace_n_user_data_bytes); - - h->flags |= MHEAP_FLAG_TRACE; - } - - if (h->flags & MHEAP_FLAG_VALIDATE) - mheap_validate (v); - - mheap_maybe_unlock (v); - - cpu_times[1] = clib_cpu_time_now (); - h->stats.n_clocks_put += cpu_times[1] - cpu_times[0]; -} - -void * -mheap_alloc_with_flags (void *memory, uword memory_size, uword flags) -{ - mheap_t *h; - void *v; - uword size; - - if (!mheap_page_size) - mheap_page_size = clib_mem_get_page_size (); - - if (!memory) - { - /* No memory given, try to VM allocate some. */ - memory = clib_mem_vm_alloc (memory_size); - if (!memory) - return 0; - - /* No memory region implies we have virtual memory. */ - flags &= ~MHEAP_FLAG_DISABLE_VM; - } - - /* Make sure that given memory is page aligned. */ - { - uword am, av, ah; - - am = pointer_to_uword (memory); - av = mheap_page_round (am); - v = uword_to_pointer (av, void *); - h = mheap_header (v); - ah = pointer_to_uword (h); - while (ah < am) - ah += mheap_page_size; - - h = uword_to_pointer (ah, void *); - v = mheap_vector (h); - - if (PREDICT_FALSE (memory + memory_size < v)) - { - /* - * This will happen when the requested memory_size is too - * small to cope with the heap header and/or memory alignment. - */ - clib_mem_vm_free (memory, memory_size); - return 0; - } - - size = memory + memory_size - v; - } - - /* VM map header so we can use memory. */ - if (!(flags & MHEAP_FLAG_DISABLE_VM)) - clib_mem_vm_map (h, sizeof (h[0])); - - /* Zero vector header: both heap header and vector length. */ - memset (h, 0, sizeof (h[0])); - _vec_len (v) = 0; - - h->vm_alloc_offset_from_header = (void *) h - memory; - h->vm_alloc_size = memory_size; - - h->max_size = size; - h->owner_cpu = ~0; - - /* Set flags based on those given less builtin-flags. */ - h->flags |= (flags & ~MHEAP_FLAG_TRACE); - - /* Unmap remainder of heap until we will be ready to use it. */ - if (!(h->flags & MHEAP_FLAG_DISABLE_VM)) - mheap_vm (v, MHEAP_VM_UNMAP | MHEAP_VM_ROUND_UP, - (clib_address_t) v, h->max_size); - - /* Initialize free list heads to empty. */ - memset (h->first_free_elt_uoffset_by_bin, 0xFF, - sizeof (h->first_free_elt_uoffset_by_bin)); - - return v; -} - -void * -mheap_alloc (void *memory, uword size) -{ - uword flags = 0; - - if (memory != 0) - flags |= MHEAP_FLAG_DISABLE_VM; - -#ifdef CLIB_HAVE_VEC128 - flags |= MHEAP_FLAG_SMALL_OBJECT_CACHE; -#endif - - return mheap_alloc_with_flags (memory, size, flags); -} - -void * -_mheap_free (void *v) -{ - mheap_t *h = mheap_header (v); - - if (v) - clib_mem_vm_free ((void *) h - h->vm_alloc_offset_from_header, - h->vm_alloc_size); - - return 0; -} - -/* Call user's function with each object in heap. */ -void -mheap_foreach (void *v, - uword (*func) (void *arg, void *v, void *elt_data, - uword elt_size), void *arg) -{ - mheap_elt_t *e; - u8 *stack_heap, *clib_mem_mheap_save; - u8 tmp_heap_memory[16 * 1024]; - - mheap_maybe_lock (v); - - if (vec_len (v) == 0) - goto done; - - clib_mem_mheap_save = 0; - stack_heap = 0; - - /* Allocate a new temporary heap on the stack. - This is so that our hash table & user's callback function can - themselves allocate memory somewhere without getting in the way - of the heap we are looking at. */ - if (v == clib_mem_get_heap ()) - { - stack_heap = mheap_alloc (tmp_heap_memory, sizeof (tmp_heap_memory)); - clib_mem_mheap_save = v; - clib_mem_set_heap (stack_heap); - } - - for (e = v; - e->n_user_data != MHEAP_N_USER_DATA_INVALID; e = mheap_next_elt (e)) - { - void *p = mheap_elt_data (v, e); - if (e->is_free) - continue; - if ((*func) (arg, v, p, mheap_elt_data_bytes (e))) - break; - } - - /* Restore main CLIB heap. */ - if (clib_mem_mheap_save) - clib_mem_set_heap (clib_mem_mheap_save); - -done: - mheap_maybe_unlock (v); -} - -/* Bytes in mheap header overhead not including data bytes. */ -always_inline uword -mheap_bytes_overhead (void *v) -{ - mheap_t *h = mheap_header (v); - return v ? sizeof (h[0]) + h->n_elts * sizeof (mheap_elt_t) : 0; -} - -/* Total number of bytes including both data and overhead. */ -uword -mheap_bytes (void *v) -{ - return mheap_bytes_overhead (v) + vec_bytes (v); -} - -static void -mheap_usage_no_lock (void *v, clib_mem_usage_t * usage) -{ - mheap_t *h = mheap_header (v); - uword used = 0, free = 0, free_vm_unmapped = 0; - - if (vec_len (v) > 0) - { - mheap_elt_t *e; - - for (e = v; - e->n_user_data != MHEAP_N_USER_DATA_INVALID; - e = mheap_next_elt (e)) - { - uword size = mheap_elt_data_bytes (e); - if (e->is_free) - { - free += size; - if (!(h->flags & MHEAP_FLAG_DISABLE_VM)) - free_vm_unmapped += - mheap_vm_elt (v, MHEAP_VM_NOMAP, mheap_elt_uoffset (v, e)); - } - else - used += size; - } - } - - usage->object_count = mheap_elts (v); - usage->bytes_total = mheap_bytes (v); - usage->bytes_overhead = mheap_bytes_overhead (v); - usage->bytes_max = mheap_max_size (v); - usage->bytes_used = used; - usage->bytes_free = free; - usage->bytes_free_reclaimed = free_vm_unmapped; -} - -void -mheap_usage (void *v, clib_mem_usage_t * usage) -{ - mheap_maybe_lock (v); - mheap_usage_no_lock (v, usage); - mheap_maybe_unlock (v); -} - -static u8 * -format_mheap_byte_count (u8 * s, va_list * va) -{ - uword n_bytes = va_arg (*va, uword); - if (n_bytes < 1024) - return format (s, "%wd", n_bytes); - else - return format (s, "%wdk", n_bytes / 1024); -} - -/* Returns first corrupt heap element. */ -static mheap_elt_t * -mheap_first_corrupt (void *v) -{ - mheap_elt_t *e, *n; - - if (vec_len (v) == 0) - return 0; - - e = v; - while (1) - { - if (e->n_user_data == MHEAP_N_USER_DATA_INVALID) - break; - - n = mheap_next_elt (e); - - if (e->n_user_data != n->prev_n_user_data) - return e; - - if (e->is_free != n->prev_is_free) - return e; - - e = n; - } - - return 0; -} - -static u8 * -format_mheap_stats (u8 * s, va_list * va) -{ - mheap_t *h = va_arg (*va, mheap_t *); - mheap_stats_t *st = &h->stats; - uword indent = format_get_indent (s); - - s = - format (s, - "alloc. from small object cache: %Ld hits %Ld attempts (%.2f%%) replacements %d", - st->n_small_object_cache_hits, st->n_small_object_cache_attempts, - (st->n_small_object_cache_attempts != - 0 ? 100. * (f64) st->n_small_object_cache_hits / - (f64) st->n_small_object_cache_attempts : 0.), - h->small_object_cache.replacement_index); - - s = - format (s, - "\n%Ualloc. from free-list: %Ld attempts, %Ld hits (%.2f%%), %Ld considered (per-attempt %.2f)", - format_white_space, indent, st->free_list.n_search_attempts, - st->free_list.n_objects_found, - (st->free_list.n_search_attempts != - 0 ? 100. * (f64) st->free_list.n_objects_found / - (f64) st->free_list.n_search_attempts : 0.), - st->free_list.n_objects_searched, - (st->free_list.n_search_attempts != - 0 ? (f64) st->free_list.n_objects_searched / - (f64) st->free_list.n_search_attempts : 0.)); - - s = format (s, "\n%Ualloc. from vector-expand: %Ld", - format_white_space, indent, st->n_vector_expands); - - s = format (s, "\n%Uallocs: %Ld %.2f clocks/call", - format_white_space, indent, - st->n_gets, (f64) st->n_clocks_get / (f64) st->n_gets); - - s = format (s, "\n%Ufrees: %Ld %.2f clocks/call", - format_white_space, indent, - st->n_puts, (f64) st->n_clocks_put / (f64) st->n_puts); - - return s; -} - -u8 * -format_mheap (u8 * s, va_list * va) -{ - void *v = va_arg (*va, u8 *); - int verbose = va_arg (*va, int); - - mheap_t *h; - uword i, size, indent; - clib_mem_usage_t usage; - mheap_elt_t *first_corrupt; - - mheap_maybe_lock (v); - - h = mheap_header (v); - - mheap_usage_no_lock (v, &usage); - - indent = format_get_indent (s); - - s = - format (s, - "%d objects, %U of %U used, %U free, %U reclaimed, %U overhead", - usage.object_count, format_mheap_byte_count, usage.bytes_used, - format_mheap_byte_count, usage.bytes_total, - format_mheap_byte_count, usage.bytes_free, - format_mheap_byte_count, usage.bytes_free_reclaimed, - format_mheap_byte_count, usage.bytes_overhead); - - if (usage.bytes_max != ~0) - s = format (s, ", %U capacity", format_mheap_byte_count, usage.bytes_max); - - /* Show histogram of sizes. */ - if (verbose > 1) - { - uword hist[MHEAP_N_BINS]; - mheap_elt_t *e; - uword i, n_hist; - - memset (hist, 0, sizeof (hist)); - - n_hist = 0; - for (e = v; - e->n_user_data != MHEAP_N_USER_DATA_INVALID; - e = mheap_next_elt (e)) - { - uword n_user_data_bytes = mheap_elt_data_bytes (e); - uword bin = user_data_size_to_bin_index (n_user_data_bytes); - if (!e->is_free) - { - hist[bin] += 1; - n_hist += 1; - } - } - - s = format (s, "\n%U%=12s%=12s%=16s", - format_white_space, indent + 2, - "Size", "Count", "Fraction"); - - for (i = 0; i < ARRAY_LEN (hist); i++) - { - if (hist[i] == 0) - continue; - s = format (s, "\n%U%12d%12wd%16.4f", - format_white_space, indent + 2, - MHEAP_MIN_USER_DATA_BYTES + - i * MHEAP_USER_DATA_WORD_BYTES, hist[i], - (f64) hist[i] / (f64) n_hist); - } - } - - if (verbose) - s = format (s, "\n%U%U", - format_white_space, indent + 2, format_mheap_stats, h); - - if ((h->flags & MHEAP_FLAG_TRACE) && vec_len (h->trace_main.traces) > 0) - { - /* Make a copy of traces since we'll be sorting them. */ - mheap_trace_t *t, *traces_copy; - uword indent, total_objects_traced; - - traces_copy = vec_dup (h->trace_main.traces); - qsort (traces_copy, vec_len (traces_copy), sizeof (traces_copy[0]), - mheap_trace_sort); - - total_objects_traced = 0; - s = format (s, "\n"); - vec_foreach (t, traces_copy) - { - /* Skip over free elements. */ - if (t->n_allocations == 0) - continue; - - total_objects_traced += t->n_allocations; - - /* When not verbose only report allocations of more than 1k. */ - if (!verbose && t->n_bytes < 1024) - continue; - - if (t == traces_copy) - s = format (s, "%=9s%=9s %=10s Traceback\n", "Bytes", "Count", - "Sample"); - s = format (s, "%9d%9d %p", t->n_bytes, t->n_allocations, - t->offset + v); - indent = format_get_indent (s); - for (i = 0; i < ARRAY_LEN (t->callers) && t->callers[i]; i++) - { - if (i > 0) - s = format (s, "%U", format_white_space, indent); -#ifdef CLIB_UNIX - s = - format (s, " %U\n", format_clib_elf_symbol_with_address, - t->callers[i]); -#else - s = format (s, " %p\n", t->callers[i]); -#endif - } - } - - s = format (s, "%d total traced objects\n", total_objects_traced); - - vec_free (traces_copy); - } - - first_corrupt = mheap_first_corrupt (v); - if (first_corrupt) - { - size = mheap_elt_data_bytes (first_corrupt); - s = format (s, "\n first corrupt object: %p, size %wd\n %U", - first_corrupt, size, format_hex_bytes, first_corrupt, size); - } - - /* FIXME. This output could be wrong in the unlikely case that format - uses the same mheap as we are currently inspecting. */ - if (verbose > 1) - { - mheap_elt_t *e; - uword i, o; - - s = format (s, "\n"); - - e = mheap_elt_at_uoffset (v, 0); - i = 0; - while (1) - { - if ((i % 8) == 0) - s = format (s, "%8d: ", i); - - o = mheap_elt_uoffset (v, e); - - if (e->is_free) - s = format (s, "(%8d) ", o); - else - s = format (s, " %8d ", o); - - if ((i % 8) == 7 || (i + 1) >= h->n_elts) - s = format (s, "\n"); - } - } - - mheap_maybe_unlock (v); - - return s; -} - -void -dmh (void *v) -{ - fformat (stderr, "%U", format_mheap, v, 1); -} - -static void -mheap_validate_breakpoint () -{ - os_panic (); -} - -void -mheap_validate (void *v) -{ - mheap_t *h = mheap_header (v); - uword i, s; - - uword elt_count, elt_size; - uword free_count_from_free_lists, free_size_from_free_lists; - uword small_elt_free_count, small_elt_free_size; - -#define CHECK(x) if (! (x)) { mheap_validate_breakpoint (); os_panic (); } - - if (vec_len (v) == 0) - return; - - mheap_maybe_lock (v); - - /* Validate number of elements and size. */ - free_size_from_free_lists = free_count_from_free_lists = 0; - for (i = 0; i < ARRAY_LEN (h->first_free_elt_uoffset_by_bin); i++) - { - mheap_elt_t *e, *n; - uword is_first; - - CHECK ((h->first_free_elt_uoffset_by_bin[i] != MHEAP_GROUNDED) - == - ((h->non_empty_free_elt_heads[i / - BITS (uword)] & ((uword) 1 << - (uword) (i % - BITS - (uword)))) - != 0)); - - if (h->first_free_elt_uoffset_by_bin[i] == MHEAP_GROUNDED) - continue; - - e = mheap_elt_at_uoffset (v, h->first_free_elt_uoffset_by_bin[i]); - is_first = 1; - while (1) - { - uword s; - - n = mheap_next_elt (e); - - /* Object must be marked free. */ - CHECK (e->is_free); - - /* Next object's previous free bit must also be set. */ - CHECK (n->prev_is_free); - - if (is_first) - CHECK (e->free_elt.prev_uoffset == MHEAP_GROUNDED); - is_first = 0; - - s = mheap_elt_data_bytes (e); - CHECK (user_data_size_to_bin_index (s) == i); - - free_count_from_free_lists += 1; - free_size_from_free_lists += s; - - if (e->free_elt.next_uoffset == MHEAP_GROUNDED) - break; - - n = mheap_elt_at_uoffset (v, e->free_elt.next_uoffset); - - /* Check free element linkages. */ - CHECK (n->free_elt.prev_uoffset == mheap_elt_uoffset (v, e)); - - e = n; - } - } - - /* Go through small object cache. */ - small_elt_free_count = small_elt_free_size = 0; - for (i = 0; i < ARRAY_LEN (h->small_object_cache.bins.as_u8); i++) - { - if (h->small_object_cache.bins.as_u8[i] != 0) - { - mheap_elt_t *e; - uword b = h->small_object_cache.bins.as_u8[i] - 1; - uword o = h->small_object_cache.offsets[i]; - uword s; - - e = mheap_elt_at_uoffset (v, o); - - /* Object must be allocated. */ - CHECK (!e->is_free); - - s = mheap_elt_data_bytes (e); - CHECK (user_data_size_to_bin_index (s) == b); - - small_elt_free_count += 1; - small_elt_free_size += s; - } - } - - { - mheap_elt_t *e, *n; - uword elt_free_size, elt_free_count; - - elt_count = elt_size = elt_free_size = elt_free_count = 0; - for (e = v; e->n_user_data != MHEAP_N_USER_DATA_INVALID; e = n) - { - if (e->prev_n_user_data != MHEAP_N_USER_DATA_INVALID) - CHECK (e->prev_n_user_data * sizeof (e->user_data[0]) >= - MHEAP_MIN_USER_DATA_BYTES); - - CHECK (e->n_user_data * sizeof (e->user_data[0]) >= - MHEAP_MIN_USER_DATA_BYTES); - - n = mheap_next_elt (e); - - CHECK (e->is_free == n->prev_is_free); - - elt_count++; - s = mheap_elt_data_bytes (e); - elt_size += s; - - if (e->is_free) - { - elt_free_count++; - elt_free_size += s; - } - - /* Consecutive free objects should have been combined. */ - CHECK (!(e->prev_is_free && n->prev_is_free)); - } - - CHECK (free_count_from_free_lists == elt_free_count); - CHECK (free_size_from_free_lists == elt_free_size); - CHECK (elt_count == h->n_elts + elt_free_count + small_elt_free_count); - CHECK (elt_size + (elt_count + 1) * MHEAP_ELT_OVERHEAD_BYTES == - vec_len (v)); - } - - { - mheap_elt_t *e, *n; - - for (e = v; e->n_user_data == MHEAP_N_USER_DATA_INVALID; e = n) - { - n = mheap_next_elt (e); - CHECK (e->n_user_data == n->prev_n_user_data); - } - } - -#undef CHECK - - mheap_maybe_unlock (v); - - h->validate_serial += 1; -} - -static void -mheap_get_trace (void *v, uword offset, uword size) -{ - mheap_t *h; - mheap_trace_main_t *tm; - mheap_trace_t *t; - uword i, n_callers, trace_index, *p; - mheap_trace_t trace; - - /* Spurious Coverity warnings be gone. */ - memset (&trace, 0, sizeof (trace)); - - n_callers = clib_backtrace (trace.callers, ARRAY_LEN (trace.callers), - /* Skip mheap_get_aligned's frame */ 1); - if (n_callers == 0) - return; - - for (i = n_callers; i < ARRAY_LEN (trace.callers); i++) - trace.callers[i] = 0; - - h = mheap_header (v); - tm = &h->trace_main; - - if (!tm->trace_by_callers) - tm->trace_by_callers = - hash_create_mem (0, sizeof (trace.callers), sizeof (uword)); - - p = hash_get_mem (tm->trace_by_callers, &trace.callers); - if (p) - { - trace_index = p[0]; - t = tm->traces + trace_index; - } - else - { - i = vec_len (tm->trace_free_list); - if (i > 0) - { - trace_index = tm->trace_free_list[i - 1]; - _vec_len (tm->trace_free_list) = i - 1; - } - else - { - mheap_trace_t *old_start = tm->traces; - mheap_trace_t *old_end = vec_end (tm->traces); - - vec_add2 (tm->traces, t, 1); - - if (tm->traces != old_start) - { - hash_pair_t *p; - mheap_trace_t *q; - /* *INDENT-OFF* */ - hash_foreach_pair (p, tm->trace_by_callers, - ({ - q = uword_to_pointer (p->key, mheap_trace_t *); - ASSERT (q >= old_start && q < old_end); - p->key = pointer_to_uword (tm->traces + (q - old_start)); - })); - /* *INDENT-ON* */ - } - trace_index = t - tm->traces; - } - - t = tm->traces + trace_index; - t[0] = trace; - t->n_allocations = 0; - t->n_bytes = 0; - hash_set_mem (tm->trace_by_callers, t->callers, trace_index); - } - - t->n_allocations += 1; - t->n_bytes += size; - t->offset = offset; /* keep a sample to autopsy */ - hash_set (tm->trace_index_by_offset, offset, t - tm->traces); -} - -static void -mheap_put_trace (void *v, uword offset, uword size) -{ - mheap_t *h; - mheap_trace_main_t *tm; - mheap_trace_t *t; - uword trace_index, *p; - - h = mheap_header (v); - tm = &h->trace_main; - p = hash_get (tm->trace_index_by_offset, offset); - if (!p) - return; - - trace_index = p[0]; - hash_unset (tm->trace_index_by_offset, offset); - ASSERT (trace_index < vec_len (tm->traces)); - - t = tm->traces + trace_index; - ASSERT (t->n_allocations > 0); - ASSERT (t->n_bytes >= size); - t->n_allocations -= 1; - t->n_bytes -= size; - if (t->n_allocations == 0) - { - hash_unset_mem (tm->trace_by_callers, t->callers); - vec_add1 (tm->trace_free_list, trace_index); - memset (t, 0, sizeof (t[0])); - } -} - -static int -mheap_trace_sort (const void *_t1, const void *_t2) -{ - const mheap_trace_t *t1 = _t1; - const mheap_trace_t *t2 = _t2; - word cmp; - - cmp = (word) t2->n_bytes - (word) t1->n_bytes; - if (!cmp) - cmp = (word) t2->n_allocations - (word) t1->n_allocations; - return cmp; -} - -always_inline void -mheap_trace_main_free (mheap_trace_main_t * tm) -{ - vec_free (tm->traces); - vec_free (tm->trace_free_list); - hash_free (tm->trace_by_callers); - hash_free (tm->trace_index_by_offset); -} - -void -mheap_trace (void *v, int enable) -{ - mheap_t *h; - - h = mheap_header (v); - - if (enable) - { - h->flags |= MHEAP_FLAG_TRACE; - } - else - { - mheap_trace_main_free (&h->trace_main); - h->flags &= ~MHEAP_FLAG_TRACE; - } -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/mheap.h b/vppinfra/vppinfra/mheap.h deleted file mode 100644 index 5b7cdfbaf8d..00000000000 --- a/vppinfra/vppinfra/mheap.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_mheap_h -#define included_mheap_h - -#include <vppinfra/vec.h> -#include <vppinfra/error.h> /* clib_error_t */ -#include <vppinfra/mem.h> /* clib_mem_usage_t */ -#include <vppinfra/format.h> /* for unformat_input_t */ - -/* Allocate size bytes. New heap and offset are returned. - offset == ~0 means allocation failed. */ -always_inline void * -mheap_get (void *v, uword size, uword * offset_return) -{ - return mheap_get_aligned (v, size, 0, 0, offset_return); -} - -/* Create allocation heap of given size. - * The actual usable size is smaller than the requested size. - * memory_bytes must be greater than mheap_page_size + sizeof (mheap_t) + 16. - * Otherwise, allocation may fail and return 0. - */ -void *mheap_alloc (void *memory, uword memory_bytes); -void *mheap_alloc_with_flags (void *memory, uword memory_bytes, uword flags); - -#define mheap_free(v) (v) = _mheap_free(v) -void *_mheap_free (void *v); - -void mheap_foreach (void *v, - uword (*func) (void *arg, void *v, void *elt_data, - uword elt_size), void *arg); - -/* Format mheap data structures as string. */ -u8 *format_mheap (u8 * s, va_list * va); - -/* Validate internal consistency. */ -void mheap_validate (void *h); - -/* Query bytes used. */ -uword mheap_bytes (void *v); - -void mheap_usage (void *v, clib_mem_usage_t * usage); - -/* Enable disable traceing. */ -void mheap_trace (void *v, int enable); - -/* Test routine. */ -int test_mheap_main (unformat_input_t * input); - -#endif /* included_mheap_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/mheap_bootstrap.h b/vppinfra/vppinfra/mheap_bootstrap.h deleted file mode 100644 index 4b21051bfcc..00000000000 --- a/vppinfra/vppinfra/mheap_bootstrap.h +++ /dev/null @@ -1,374 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_mem_mheap_h -#define included_mem_mheap_h - -/* Bootstrap include so that #include <vppinfra/mem.h> can include e.g. - <vppinfra/mheap.h> which depends on <vppinfra/vec.h>. */ - -#include <vppinfra/vec_bootstrap.h> -#include <vppinfra/error_bootstrap.h> -#include <vppinfra/os.h> -#include <vppinfra/vector.h> - -/* Each element in heap is immediately followed by this struct. */ -typedef struct -{ - /* Number of mheap_size_t words of user data in previous object. - Used to find mheap_elt_t for previous object. */ -#if CLIB_VEC64 > 0 - u64 prev_n_user_data:63; - - /* Used to mark end/start of of doubly-linked list of mheap_elt_t's. */ -#define MHEAP_N_USER_DATA_INVALID (0x7fffffffffffffffULL) -#define MHEAP_GROUNDED (~0ULL) - - /* Set if previous object is free. */ - u64 prev_is_free:1; - - /* Number of mheap_size_t words of user data that follow this object. */ - u64 n_user_data:63; - - /* Set if this object is on free list (and therefore following free_elt - is valid). */ - u64 is_free:1; - -#else - u32 prev_n_user_data:31; - - /* Used to mark end/start of of doubly-linked list of mheap_elt_t's. */ -#define MHEAP_N_USER_DATA_INVALID (0x7fffffff) -#define MHEAP_GROUNDED (~0) - - /* Set if previous object is free. */ - u32 prev_is_free:1; - - /* Number of mheap_size_t words of user data that follow this object. */ - u32 n_user_data:31; - - /* Set if this object is on free list (and therefore following free_elt - is valid). */ - u32 is_free:1; -#endif - - union - { -#if CLIB_VEC64 > 0 - /* For allocated objects: user data follows. - User data is allocated in units of typeof (user_data[0]). */ - u64 user_data[0]; - - /* For free objects, offsets of next and previous free objects of this size; - ~0 means end of doubly-linked list. - This is stored in user data (guaranteed to be at least 8 bytes) - but only for *free* objects. */ - struct - { - u64 next_uoffset, prev_uoffset; - } free_elt; -#else - /* For allocated objects: user data follows. - User data is allocated in units of typeof (user_data[0]). */ - u32 user_data[0]; - - /* For free objects, offsets of next and previous free objects of this size; - ~0 means end of doubly-linked list. - This is stored in user data (guaranteed to be at least 8 bytes) - but only for *free* objects. */ - struct - { - u32 next_uoffset, prev_uoffset; - } free_elt; -#endif - }; -} mheap_elt_t; - -/* Number of bytes of "overhead": e.g. not user data. */ -#define MHEAP_ELT_OVERHEAD_BYTES (sizeof (mheap_elt_t) - STRUCT_OFFSET_OF (mheap_elt_t, user_data)) - -/* User objects must be large enough to hold 2 x u32 free offsets in free elt. */ -#define MHEAP_MIN_USER_DATA_BYTES MHEAP_ELT_OVERHEAD_BYTES - -/* Number of byte in user data "words". */ -#define MHEAP_USER_DATA_WORD_BYTES STRUCT_SIZE_OF (mheap_elt_t, user_data[0]) - -typedef struct -{ - /* Address of callers: outer first, inner last. */ - uword callers[12]; - - /* Count of allocations with this traceback. */ -#if CLIB_VEC64 > 0 - u64 n_allocations; -#else - u32 n_allocations; -#endif - - /* Count of bytes allocated with this traceback. */ - u32 n_bytes; - - /* Offset of this item */ - uword offset; -} mheap_trace_t; - -typedef struct -{ - mheap_trace_t *traces; - - /* Indices of free traces. */ - u32 *trace_free_list; - - /* Hash table mapping callers to trace index. */ - uword *trace_by_callers; - - /* Hash table mapping mheap offset to trace index. */ - uword *trace_index_by_offset; -} mheap_trace_main_t; - - /* Small object bin i is for objects with - user_size > sizeof (mheap_elt_t) + sizeof (mheap_elt_t) * (i - 1) - user_size <= sizeof (mheap_elt_t) + sizeof (mheap_size_t) * i. */ -#define MHEAP_LOG2_N_SMALL_OBJECT_BINS 8 -#define MHEAP_N_SMALL_OBJECT_BINS (1 << MHEAP_LOG2_N_SMALL_OBJECT_BINS) - -#define MHEAP_N_BINS \ - (MHEAP_N_SMALL_OBJECT_BINS \ - + (STRUCT_BITS_OF (mheap_elt_t, user_data[0]) - MHEAP_LOG2_N_SMALL_OBJECT_BINS)) - -typedef struct -{ - struct - { - u64 n_search_attempts; - u64 n_objects_searched; - u64 n_objects_found; - } free_list; - - u64 n_vector_expands; - - u64 n_small_object_cache_hits; - u64 n_small_object_cache_attempts; - - u64 n_gets, n_puts; - u64 n_clocks_get, n_clocks_put; -} mheap_stats_t; - -/* Without vector instructions don't bother with small object cache. */ -#ifdef CLIB_HAVE_VEC128 -#define MHEAP_HAVE_SMALL_OBJECT_CACHE 1 -#else -#define MHEAP_HAVE_SMALL_OBJECT_CACHE 0 -#endif - -#if CLIB_VEC64 > 0 -#undef MHEAP_HAVE_SMALL_OBJECT_CACHE -#define MHEAP_HAVE_SMALL_OBJECT_CACHE 0 -#endif - -/* For objects with align == 4 and align_offset == 0 (e.g. vector strings). */ -typedef struct -{ - union - { -#ifdef CLIB_HAVE_VEC128 - u8x16 as_u8x16[BITS (uword) / 16]; -#endif - - /* Store bin + 1; zero means unused. */ - u8 as_u8[BITS (uword)]; - } bins; - - uword offsets[BITS (uword)]; - - u32 replacement_index; -} mheap_small_object_cache_t; - -/* Vec header for heaps. */ -typedef struct -{ - /* User offsets for head of doubly-linked list of free objects of this size. */ -#if CLIB_VEC64 > 0 - u64 first_free_elt_uoffset_by_bin[MHEAP_N_BINS]; -#else - u32 first_free_elt_uoffset_by_bin[MHEAP_N_BINS]; -#endif - - /* Bitmap of non-empty free list bins. */ - uword non_empty_free_elt_heads[(MHEAP_N_BINS + BITS (uword) - 1) / - BITS (uword)]; - - mheap_small_object_cache_t small_object_cache; - - u32 flags; -#define MHEAP_FLAG_TRACE (1 << 0) -#define MHEAP_FLAG_DISABLE_VM (1 << 1) -#define MHEAP_FLAG_THREAD_SAFE (1 << 2) -#define MHEAP_FLAG_SMALL_OBJECT_CACHE (1 << 3) -#define MHEAP_FLAG_VALIDATE (1 << 4) - - /* Lock use when MHEAP_FLAG_THREAD_SAFE is set. */ - volatile u32 lock; - volatile u32 owner_cpu; - int recursion_count; - - /* Number of allocated objects. */ - u64 n_elts; - - /* Maximum size (in bytes) this heap is allowed to grow to. - Set to ~0 to grow heap (via vec_resize) arbitrarily. */ - u64 max_size; - - uword vm_alloc_offset_from_header; - uword vm_alloc_size; - - /* Each successful mheap_validate call increments this serial number. - Used to debug heap corruption problems. GDB breakpoints can be - made conditional on validate_serial. */ - u64 validate_serial; - - mheap_trace_main_t trace_main; - - mheap_stats_t stats; -} mheap_t; - -always_inline mheap_t * -mheap_header (u8 * v) -{ - return vec_aligned_header (v, sizeof (mheap_t), 16); -} - -always_inline u8 * -mheap_vector (mheap_t * h) -{ - return vec_aligned_header_end (h, sizeof (mheap_t), 16); -} - -always_inline uword -mheap_elt_uoffset (void *v, mheap_elt_t * e) -{ - return (uword) e->user_data - (uword) v; -} - -always_inline mheap_elt_t * -mheap_user_pointer_to_elt (void *v) -{ - return v - STRUCT_OFFSET_OF (mheap_elt_t, user_data); -} - -/* For debugging we keep track of offsets for valid objects. - We make sure user is not trying to free object with invalid offset. */ -always_inline uword -mheap_offset_is_valid (void *v, uword uo) -{ - return uo >= MHEAP_ELT_OVERHEAD_BYTES && uo <= vec_len (v); -} - -always_inline mheap_elt_t * -mheap_elt_at_uoffset (void *v, uword uo) -{ - ASSERT (mheap_offset_is_valid (v, uo)); - return (mheap_elt_t *) (v + uo - STRUCT_OFFSET_OF (mheap_elt_t, user_data)); -} - -always_inline void * -mheap_elt_data (void *v, mheap_elt_t * e) -{ - return v + mheap_elt_uoffset (v, e); -} - -always_inline uword -mheap_elt_data_bytes (mheap_elt_t * e) -{ - return e->n_user_data * sizeof (e->user_data[0]); -} - -always_inline uword -mheap_data_bytes (void *v, uword uo) -{ - mheap_elt_t *e = mheap_elt_at_uoffset (v, uo); - return mheap_elt_data_bytes (e); -} - -#define mheap_len(v,d) (mheap_data_bytes((v),(void *) (d) - (void *) (v)) / sizeof ((d)[0])) - -always_inline mheap_elt_t * -mheap_next_elt (mheap_elt_t * e) -{ - ASSERT (e->n_user_data < MHEAP_N_USER_DATA_INVALID); - return (mheap_elt_t *) (e->user_data + e->n_user_data); -} - -always_inline mheap_elt_t * -mheap_prev_elt (mheap_elt_t * e) -{ - ASSERT (e->prev_n_user_data < MHEAP_N_USER_DATA_INVALID); - return ((void *) e - - e->prev_n_user_data * sizeof (e->user_data[0]) - - MHEAP_ELT_OVERHEAD_BYTES); -} - -/* Exported operations. */ - -always_inline uword -mheap_elts (void *v) -{ - return v ? mheap_header (v)->n_elts : 0; -} - -always_inline uword -mheap_max_size (void *v) -{ - return v ? mheap_header (v)->max_size : ~0; -} - -/* Free previously allocated offset. */ -void mheap_put (void *v, uword offset); - -/* Allocate object from mheap. */ -void *mheap_get_aligned (void *v, uword size, uword align, uword align_offset, - uword * offset_return); - -#endif /* included_mem_mheap_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/mod_test_hash.c b/vppinfra/vppinfra/mod_test_hash.c deleted file mode 100644 index b3fa676d2e2..00000000000 --- a/vppinfra/vppinfra/mod_test_hash.c +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include <vppinfra/linux_kernel_init.h> -#include <vppinfra/hash.h> - -CLIB_LINUX_KERNEL_MODULE ("test_hash", test_hash_main, - /* kernel-thread flags */ 0 & CLONE_KERNEL); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/os.h b/vppinfra/vppinfra/os.h deleted file mode 100644 index a5c74f8ce72..00000000000 --- a/vppinfra/vppinfra/os.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001-2005 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_os_h -#define included_os_h - -#include <vppinfra/clib.h> -#include <vppinfra/types.h> - -/* External panic function. */ -void os_panic (void); - -/* External exit function analagous to unix exit. */ -void os_exit (int code); - -/* External function to print a line. */ -void os_puts (u8 * string, uword length, uword is_error); - -/* External function to handle out of memory. */ -void os_out_of_memory (void); - -/* Estimate, measure or divine CPU timestamp clock frequency. */ -f64 os_cpu_clock_frequency (void); - -uword os_get_cpu_number (void); -uword os_get_ncpus (void); - -#include <vppinfra/smp.h> - -#endif /* included_os_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/pfhash.c b/vppinfra/vppinfra/pfhash.c deleted file mode 100644 index 3b9fa8f34aa..00000000000 --- a/vppinfra/vppinfra/pfhash.c +++ /dev/null @@ -1,689 +0,0 @@ -/* - Copyright (c) 2013 Cisco and/or its affiliates. - - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. -*/ - -#include <vppinfra/pfhash.h> -#include <vppinfra/format.h> - -/* This is incredibly handy when debugging */ -u32 vl (void *v) __attribute__ ((weak)); -u32 -vl (void *v) -{ - return vec_len (v); -} - -#if defined(CLIB_HAVE_VEC128) && ! defined (__ALTIVEC__) - -typedef struct -{ - u8 *key[16]; - u64 value; -} pfhash_show_t; - -static int -sh_compare (pfhash_show_t * sh0, pfhash_show_t * sh1) -{ - return ((i32) (sh0->value) - ((i32) sh1->value)); -} - -u8 * -format_pfhash (u8 * s, va_list * args) -{ - pfhash_t *p = va_arg (*args, pfhash_t *); - int verbose = va_arg (*args, int); - - if (p == 0 || p->overflow_hash == 0 || p->buckets == 0) - { - s = format (s, "*** uninitialized ***"); - return s; - } - - s = format (s, "Prefetch hash '%s'\n", p->name); - s = - format (s, " %d buckets, %u bucket overflows, %.1f%% bucket overflow \n", - vec_len (p->buckets), p->overflow_count, - 100.0 * ((f64) p->overflow_count) / ((f64) vec_len (p->buckets))); - if (p->nitems) - s = - format (s, - " %u items, %u items in overflow, %.1f%% items in overflow\n", - p->nitems, p->nitems_in_overflow, - 100.0 * ((f64) p->nitems_in_overflow) / ((f64) p->nitems)); - - if (verbose) - { - pfhash_show_t *shs = 0, *sh; - hash_pair_t *hp; - int i, j; - - for (i = 0; i < vec_len (p->buckets); i++) - { - pfhash_kv_t *kv; - pfhash_kv_16_t *kv16; - pfhash_kv_8_t *kv8; - pfhash_kv_8v8_t *kv8v8; - pfhash_kv_4_t *kv4; - - if (p->buckets[i] == 0 || p->buckets[i] == PFHASH_BUCKET_OVERFLOW) - continue; - - kv = pool_elt_at_index (p->kvp, p->buckets[i]); - - switch (p->key_size) - { - case 16: - kv16 = &kv->kv16; - for (j = 0; j < 3; j++) - { - if (kv16->values[j] != (u32) ~ 0) - { - vec_add2 (shs, sh, 1); - clib_memcpy (sh->key, &kv16->kb.k_u32x4[j], - p->key_size); - sh->value = kv16->values[j]; - } - } - break; - case 8: - if (p->value_size == 4) - { - kv8 = &kv->kv8; - for (j = 0; j < 5; j++) - { - if (kv8->values[j] != (u32) ~ 0) - { - vec_add2 (shs, sh, 1); - clib_memcpy (sh->key, &kv8->kb.k_u64[j], - p->key_size); - sh->value = kv8->values[j]; - } - } - } - else - { - kv8v8 = &kv->kv8v8; - for (j = 0; j < 4; j++) - { - if (kv8v8->values[j] != (u64) ~ 0) - { - vec_add2 (shs, sh, 1); - clib_memcpy (sh->key, &kv8v8->kb.k_u64[j], - p->key_size); - sh->value = kv8v8->values[j]; - } - } - - } - break; - case 4: - kv4 = &kv->kv4; - for (j = 0; j < 8; j++) - { - if (kv4->values[j] != (u32) ~ 0) - { - vec_add2 (shs, sh, 1); - clib_memcpy (sh->key, &kv4->kb.kb[j], p->key_size); - sh->value = kv4->values[j]; - } - } - break; - } - } - - /* *INDENT-OFF* */ - hash_foreach_pair (hp, p->overflow_hash, - ({ - vec_add2 (shs, sh, 1); - clib_memcpy (sh->key, (u8 *)hp->key, p->key_size); - sh->value = hp->value[0]; - })); - /* *INDENT-ON* */ - - vec_sort_with_function (shs, sh_compare); - - for (i = 0; i < vec_len (shs); i++) - { - sh = vec_elt_at_index (shs, i); - s = format (s, " %U value %u\n", format_hex_bytes, sh->key, - p->key_size, sh->value); - } - vec_free (shs); - } - return s; -} - - -void abort (void); - -void -pfhash_init (pfhash_t * p, char *name, u32 key_size, u32 value_size, - u32 nbuckets) -{ - pfhash_kv_t *kv; - memset (p, 0, sizeof (*p)); - u32 key_bytes; - - switch (key_size) - { - case 4: - key_bytes = 4; - break; - case 8: - key_bytes = 8; - break; - case 16: - key_bytes = 16; - break; - default: - ASSERT (0); - abort (); - } - - switch (value_size) - { - case 4: - case 8: - break; - default: - ASSERT (0); - abort (); - } - - - p->name = format (0, "%s", name); - vec_add1 (p->name, 0); - p->overflow_hash = hash_create_mem (0, key_bytes, sizeof (uword)); - - nbuckets = 1 << (max_log2 (nbuckets)); - - /* This sets the entire bucket array to zero */ - vec_validate (p->buckets, nbuckets - 1); - p->key_size = key_size; - p->value_size = value_size; - - /* - * Unset buckets implicitly point at the 0th pool elt. - * All search routines will return ~0 if they go there. - */ - pool_get_aligned (p->kvp, kv, 16); - memset (kv, 0xff, sizeof (*kv)); -} - -static pfhash_kv_16_t * -pfhash_get_kv_16 (pfhash_t * p, u32 bucket_contents, - u32x4 * key, u32 * match_index) -{ - u32x4 diff[3]; - u32 is_equal[3]; - pfhash_kv_16_t *kv = 0; - - *match_index = (u32) ~ 0; - - kv = &p->kvp[bucket_contents].kv16; - - diff[0] = u32x4_sub (kv->kb.k_u32x4[0], key[0]); - diff[1] = u32x4_sub (kv->kb.k_u32x4[1], key[0]); - diff[2] = u32x4_sub (kv->kb.k_u32x4[2], key[0]); - - is_equal[0] = u32x4_zero_byte_mask (diff[0]) == 0xffff; - is_equal[1] = u32x4_zero_byte_mask (diff[1]) == 0xffff; - is_equal[2] = u32x4_zero_byte_mask (diff[2]) == 0xffff; - - if (is_equal[0]) - *match_index = 0; - if (is_equal[1]) - *match_index = 1; - if (is_equal[2]) - *match_index = 2; - - return kv; -} - -static pfhash_kv_8_t * -pfhash_get_kv_8 (pfhash_t * p, u32 bucket_contents, - u64 * key, u32 * match_index) -{ - pfhash_kv_8_t *kv; - - *match_index = (u32) ~ 0; - - kv = &p->kvp[bucket_contents].kv8; - - if (kv->kb.k_u64[0] == key[0]) - *match_index = 0; - if (kv->kb.k_u64[1] == key[0]) - *match_index = 1; - if (kv->kb.k_u64[2] == key[0]) - *match_index = 2; - if (kv->kb.k_u64[3] == key[0]) - *match_index = 3; - if (kv->kb.k_u64[4] == key[0]) - *match_index = 4; - - return kv; -} - -static pfhash_kv_8v8_t * -pfhash_get_kv_8v8 (pfhash_t * p, - u32 bucket_contents, u64 * key, u32 * match_index) -{ - pfhash_kv_8v8_t *kv; - - *match_index = (u32) ~ 0; - - kv = &p->kvp[bucket_contents].kv8v8; - - if (kv->kb.k_u64[0] == key[0]) - *match_index = 0; - if (kv->kb.k_u64[1] == key[0]) - *match_index = 1; - if (kv->kb.k_u64[2] == key[0]) - *match_index = 2; - if (kv->kb.k_u64[3] == key[0]) - *match_index = 3; - - return kv; -} - -static pfhash_kv_4_t * -pfhash_get_kv_4 (pfhash_t * p, u32 bucket_contents, - u32 * key, u32 * match_index) -{ - u32x4 vector_key; - u32x4 is_equal[2]; - u32 zbm[2], winner_index; - pfhash_kv_4_t *kv; - - *match_index = (u32) ~ 0; - - kv = &p->kvp[bucket_contents].kv4; - - vector_key = u32x4_splat (key[0]); - - is_equal[0] = u32x4_is_equal (kv->kb.k_u32x4[0], vector_key); - is_equal[1] = u32x4_is_equal (kv->kb.k_u32x4[1], vector_key); - zbm[0] = ~u32x4_zero_byte_mask (is_equal[0]) & 0xFFFF; - zbm[1] = ~u32x4_zero_byte_mask (is_equal[1]) & 0xFFFF; - - if (PREDICT_FALSE ((zbm[0] == 0) && (zbm[1] == 0))) - return kv; - - winner_index = min_log2 (zbm[0]) >> 2; - winner_index = zbm[1] ? (4 + (min_log2 (zbm[1]) >> 2)) : winner_index; - - *match_index = winner_index; - return kv; -} - -static pfhash_kv_t * -pfhash_get_internal (pfhash_t * p, u32 bucket_contents, - void *key, u32 * match_index) -{ - pfhash_kv_t *kv = 0; - - switch (p->key_size) - { - case 16: - kv = - (pfhash_kv_t *) pfhash_get_kv_16 (p, bucket_contents, key, - match_index); - break; - case 8: - if (p->value_size == 4) - kv = (pfhash_kv_t *) pfhash_get_kv_8 (p, bucket_contents, - key, match_index); - else - kv = (pfhash_kv_t *) pfhash_get_kv_8v8 (p, bucket_contents, - key, match_index); - break; - case 4: - kv = - (pfhash_kv_t *) pfhash_get_kv_4 (p, bucket_contents, key, - match_index); - break; - default: - ASSERT (0); - } - return kv; -} - -u64 -pfhash_get (pfhash_t * p, u32 bucket, void *key) -{ - pfhash_kv_t *kv; - u32 match_index = ~0; - pfhash_kv_16_t *kv16; - pfhash_kv_8_t *kv8; - pfhash_kv_8v8_t *kv8v8; - pfhash_kv_4_t *kv4; - - u32 bucket_contents = pfhash_read_bucket_prefetch_kv (p, bucket); - - if (bucket_contents == PFHASH_BUCKET_OVERFLOW) - { - uword *hp; - - hp = hash_get_mem (p->overflow_hash, key); - if (hp) - return hp[0]; - return (u64) ~ 0; - } - - kv = pfhash_get_internal (p, bucket_contents, key, &match_index); - if (match_index == (u32) ~ 0) - return (u64) ~ 0; - - kv16 = (void *) kv; - kv8 = (void *) kv; - kv4 = (void *) kv; - kv8v8 = (void *) kv; - - switch (p->key_size) - { - case 16: - return (kv16->values[match_index] == (u32) ~ 0) - ? (u64) ~ 0 : (u64) kv16->values[match_index]; - case 8: - if (p->value_size == 4) - return (kv8->values[match_index] == (u32) ~ 0) - ? (u64) ~ 0 : (u64) kv8->values[match_index]; - else - return kv8v8->values[match_index]; - case 4: - return (kv4->values[match_index] == (u32) ~ 0) - ? (u64) ~ 0 : (u64) kv4->values[match_index]; - default: - ASSERT (0); - } - return (u64) ~ 0; -} - -void -pfhash_set (pfhash_t * p, u32 bucket, void *key, void *value) -{ - u32 bucket_contents = pfhash_read_bucket_prefetch_kv (p, bucket); - u32 match_index = (u32) ~ 0; - pfhash_kv_t *kv; - pfhash_kv_16_t *kv16; - pfhash_kv_8_t *kv8; - pfhash_kv_8v8_t *kv8v8; - pfhash_kv_4_t *kv4; - int i; - u8 *kcopy; - - if (bucket_contents == PFHASH_BUCKET_OVERFLOW) - { - hash_pair_t *hp; - hp = hash_get_pair_mem (p->overflow_hash, key); - if (hp) - { - clib_warning ("replace value 0x%08x with value 0x%08x", - hp->value[0], (u64) value); - hp->value[0] = (u64) value; - return; - } - kcopy = clib_mem_alloc (p->key_size); - clib_memcpy (kcopy, key, p->key_size); - hash_set_mem (p->overflow_hash, kcopy, value); - p->nitems++; - p->nitems_in_overflow++; - return; - } - - if (bucket_contents == 0) - { - pool_get_aligned (p->kvp, kv, 16); - memset (kv, 0xff, sizeof (*kv)); - p->buckets[bucket] = kv - p->kvp; - } - else - kv = pfhash_get_internal (p, bucket_contents, key, &match_index); - - kv16 = (void *) kv; - kv8 = (void *) kv; - kv8v8 = (void *) kv; - kv4 = (void *) kv; - - p->nitems++; - - if (match_index != (u32) ~ 0) - { - switch (p->key_size) - { - case 16: - kv16->values[match_index] = (u32) (u64) value; - return; - - case 8: - if (p->value_size == 4) - kv8->values[match_index] = (u32) (u64) value; - else - kv8v8->values[match_index] = (u64) value; - return; - - case 4: - kv4->values[match_index] = (u64) value; - return; - - default: - ASSERT (0); - } - } - - switch (p->key_size) - { - case 16: - for (i = 0; i < 3; i++) - { - if (kv16->values[i] == (u32) ~ 0) - { - clib_memcpy (&kv16->kb.k_u32x4[i], key, p->key_size); - kv16->values[i] = (u32) (u64) value; - return; - } - } - /* copy bucket contents to overflow hash tbl */ - for (i = 0; i < 3; i++) - { - kcopy = clib_mem_alloc (p->key_size); - clib_memcpy (kcopy, &kv16->kb.k_u32x4[i], p->key_size); - hash_set_mem (p->overflow_hash, kcopy, kv16->values[i]); - p->nitems_in_overflow++; - } - /* Add new key to overflow */ - kcopy = clib_mem_alloc (p->key_size); - clib_memcpy (kcopy, key, p->key_size); - hash_set_mem (p->overflow_hash, kcopy, value); - p->buckets[bucket] = PFHASH_BUCKET_OVERFLOW; - p->overflow_count++; - p->nitems_in_overflow++; - return; - - case 8: - if (p->value_size == 4) - { - for (i = 0; i < 5; i++) - { - if (kv8->values[i] == (u32) ~ 0) - { - clib_memcpy (&kv8->kb.k_u64[i], key, 8); - kv8->values[i] = (u32) (u64) value; - return; - } - } - /* copy bucket contents to overflow hash tbl */ - for (i = 0; i < 5; i++) - { - kcopy = clib_mem_alloc (p->key_size); - clib_memcpy (kcopy, &kv8->kb.k_u64[i], 8); - hash_set_mem (p->overflow_hash, kcopy, kv8->values[i]); - p->nitems_in_overflow++; - } - } - else - { - for (i = 0; i < 4; i++) - { - if (kv8v8->values[i] == (u64) ~ 0) - { - clib_memcpy (&kv8v8->kb.k_u64[i], key, 8); - kv8v8->values[i] = (u64) value; - return; - } - } - /* copy bucket contents to overflow hash tbl */ - for (i = 0; i < 4; i++) - { - kcopy = clib_mem_alloc (p->key_size); - clib_memcpy (kcopy, &kv8v8->kb.k_u64[i], 8); - hash_set_mem (p->overflow_hash, kcopy, kv8v8->values[i]); - p->nitems_in_overflow++; - } - - } - /* Add new key to overflow */ - kcopy = clib_mem_alloc (p->key_size); - clib_memcpy (kcopy, key, p->key_size); - hash_set_mem (p->overflow_hash, kcopy, value); - p->buckets[bucket] = PFHASH_BUCKET_OVERFLOW; - p->overflow_count++; - p->nitems_in_overflow++; - return; - - case 4: - for (i = 0; i < 8; i++) - { - if (kv4->values[i] == (u32) ~ 0) - { - clib_memcpy (&kv4->kb.kb[i], key, 4); - kv4->values[i] = (u32) (u64) value; - return; - } - } - /* copy bucket contents to overflow hash tbl */ - for (i = 0; i < 8; i++) - { - kcopy = clib_mem_alloc (p->key_size); - clib_memcpy (kcopy, &kv4->kb.kb[i], 4); - hash_set_mem (p->overflow_hash, kcopy, kv4->values[i]); - p->nitems_in_overflow++; - } - /* Add new key to overflow */ - kcopy = clib_mem_alloc (p->key_size); - clib_memcpy (kcopy, key, p->key_size); - hash_set_mem (p->overflow_hash, kcopy, value); - p->buckets[bucket] = PFHASH_BUCKET_OVERFLOW; - p->overflow_count++; - p->nitems_in_overflow++; - return; - - default: - ASSERT (0); - } -} - -void -pfhash_unset (pfhash_t * p, u32 bucket, void *key) -{ - u32 bucket_contents = pfhash_read_bucket_prefetch_kv (p, bucket); - u32 match_index = (u32) ~ 0; - pfhash_kv_t *kv; - pfhash_kv_16_t *kv16; - pfhash_kv_8_t *kv8; - pfhash_kv_8v8_t *kv8v8; - pfhash_kv_4_t *kv4; - void *oldkey; - - if (bucket_contents == PFHASH_BUCKET_OVERFLOW) - { - hash_pair_t *hp; - hp = hash_get_pair_mem (p->overflow_hash, key); - if (hp) - { - oldkey = (void *) hp->key; - hash_unset_mem (p->overflow_hash, key); - clib_mem_free (oldkey); - p->nitems--; - p->nitems_in_overflow--; - } - return; - } - - kv = pfhash_get_internal (p, bucket_contents, key, &match_index); - if (match_index == (u32) ~ 0) - return; - - p->nitems--; - - kv16 = (void *) kv; - kv8 = (void *) kv; - kv8v8 = (void *) kv; - kv4 = (void *) kv; - - switch (p->key_size) - { - case 16: - kv16->values[match_index] = (u32) ~ 0; - return; - - case 8: - if (p->value_size == 4) - kv8->values[match_index] = (u32) ~ 0; - else - kv8v8->values[match_index] = (u64) ~ 0; - return; - - case 4: - kv4->values[match_index] = (u32) ~ 0; - return; - - default: - ASSERT (0); - } -} - -void -pfhash_free (pfhash_t * p) -{ - hash_pair_t *hp; - int i; - u8 **keys = 0; - - vec_free (p->name); - - pool_free (p->kvp); - - /* *INDENT-OFF* */ - hash_foreach_pair (hp, p->overflow_hash, - ({ - vec_add1 (keys, (u8 *)hp->key); - })); - /* *INDENT-ON* */ - hash_free (p->overflow_hash); - for (i = 0; i < vec_len (keys); i++) - vec_free (keys[i]); - vec_free (keys); -} - -#endif - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/pfhash.h b/vppinfra/vppinfra/pfhash.h deleted file mode 100644 index e054c668f3b..00000000000 --- a/vppinfra/vppinfra/pfhash.h +++ /dev/null @@ -1,276 +0,0 @@ -/* - Copyright (c) 2013 Cisco and/or its affiliates. - - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. -*/ - -#ifndef included_clib_pfhash_h -#define included_clib_pfhash_h - - -#include <vppinfra/clib.h> -#include <vppinfra/hash.h> -#include <vppinfra/pool.h> - -#if defined(CLIB_HAVE_VEC128) && ! defined (__ALTIVEC__) - -typedef struct -{ - /* 3 x 16 = 48 key bytes */ - union - { - u32x4 k_u32x4[3]; - u64 k_u64[6]; - } kb; - /* 3 x 4 = 12 value bytes */ - u32 values[3]; - u32 pad; -} pfhash_kv_16_t; - -typedef struct -{ - /* 5 x 8 = 40 key bytes */ - union - { - u64 k_u64[5]; - } kb; - - /* 5 x 4 = 20 value bytes */ - u32 values[5]; - u32 pad; -} pfhash_kv_8_t; - -typedef struct -{ - /* 4 x 8 = 32 key bytes */ - union - { - u64 k_u64[4]; - } kb; - - /* 4 x 8 = 32 value bytes */ - u64 values[4]; -} pfhash_kv_8v8_t; - -typedef struct -{ - /* 8 x 4 = 32 key bytes */ - union - { - u32x4 k_u32x4[2]; - u32 kb[8]; - } kb; - - /* 8 x 4 = 32 value bytes */ - u32 values[8]; -} pfhash_kv_4_t; - -typedef union -{ - pfhash_kv_16_t kv16; - pfhash_kv_8_t kv8; - pfhash_kv_8v8_t kv8v8; - pfhash_kv_4_t kv4; -} pfhash_kv_t; - -typedef struct -{ - /* Bucket vector */ - u32 *buckets; -#define PFHASH_BUCKET_OVERFLOW (u32)~0 - - /* Pool of key/value pairs */ - pfhash_kv_t *kvp; - - /* overflow plain-o-hash */ - uword *overflow_hash; - - /* Pretty-print name */ - u8 *name; - - u32 key_size; - u32 value_size; - - u32 overflow_count; - u32 nitems; - u32 nitems_in_overflow; -} pfhash_t; - -void pfhash_init (pfhash_t * p, char *name, u32 key_size, u32 value_size, - u32 nbuckets); -void pfhash_free (pfhash_t * p); -u64 pfhash_get (pfhash_t * p, u32 bucket, void *key); -void pfhash_set (pfhash_t * p, u32 bucket, void *key, void *value); -void pfhash_unset (pfhash_t * p, u32 bucket, void *key); - -format_function_t format_pfhash; - -static inline void -pfhash_prefetch_bucket (pfhash_t * p, u32 bucket) -{ - CLIB_PREFETCH (&p->buckets[bucket], CLIB_CACHE_LINE_BYTES, LOAD); -} - -static inline u32 -pfhash_read_bucket_prefetch_kv (pfhash_t * p, u32 bucket) -{ - u32 bucket_contents = p->buckets[bucket]; - if (PREDICT_TRUE ((bucket_contents & PFHASH_BUCKET_OVERFLOW) == 0)) - CLIB_PREFETCH (&p->kvp[bucket_contents], CLIB_CACHE_LINE_BYTES, LOAD); - return bucket_contents; -} - -/* - * pfhash_search_kv_16 - * See if the supplied 16-byte key matches one of three 16-byte (key,value) pairs. - * Return the indicated value, or ~0 if no match - * - * Note: including the overflow test, the fast path is 35 instrs - * on x86_64. Elves will steal your keyboard in the middle of the night if - * you "improve" it without checking the generated code! - */ -static inline u32 -pfhash_search_kv_16 (pfhash_t * p, u32 bucket_contents, u32x4 * key) -{ - u32x4 diff0, diff1, diff2; - u32 is_equal0, is_equal1, is_equal2; - u32 no_match; - pfhash_kv_16_t *kv; - u32 rv; - - if (PREDICT_FALSE (bucket_contents == PFHASH_BUCKET_OVERFLOW)) - { - uword *hp; - hp = hash_get_mem (p->overflow_hash, key); - if (hp) - return hp[0]; - return (u32) ~ 0; - } - - kv = &p->kvp[bucket_contents].kv16; - - diff0 = u32x4_sub (kv->kb.k_u32x4[0], key[0]); - diff1 = u32x4_sub (kv->kb.k_u32x4[1], key[0]); - diff2 = u32x4_sub (kv->kb.k_u32x4[2], key[0]); - - no_match = is_equal0 = (i16) u32x4_zero_byte_mask (diff0); - is_equal1 = (i16) u32x4_zero_byte_mask (diff1); - no_match |= is_equal1; - is_equal2 = (i16) u32x4_zero_byte_mask (diff2); - no_match |= is_equal2; - /* If any of the three items matched, no_match will be zero after this line */ - no_match = ~no_match; - - rv = (is_equal0 & kv->values[0]) - | (is_equal1 & kv->values[1]) | (is_equal2 & kv->values[2]) | no_match; - - return rv; -} - -static inline u32 -pfhash_search_kv_8 (pfhash_t * p, u32 bucket_contents, u64 * key) -{ - pfhash_kv_8_t *kv; - u32 rv = (u32) ~ 0; - - if (PREDICT_FALSE (bucket_contents == PFHASH_BUCKET_OVERFLOW)) - { - uword *hp; - hp = hash_get_mem (p->overflow_hash, key); - if (hp) - return hp[0]; - return (u32) ~ 0; - } - - kv = &p->kvp[bucket_contents].kv8; - - rv = (kv->kb.k_u64[0] == key[0]) ? kv->values[0] : rv; - rv = (kv->kb.k_u64[1] == key[0]) ? kv->values[1] : rv; - rv = (kv->kb.k_u64[2] == key[0]) ? kv->values[2] : rv; - rv = (kv->kb.k_u64[3] == key[0]) ? kv->values[3] : rv; - rv = (kv->kb.k_u64[4] == key[0]) ? kv->values[4] : rv; - - return rv; -} - -static inline u64 -pfhash_search_kv_8v8 (pfhash_t * p, u32 bucket_contents, u64 * key) -{ - pfhash_kv_8v8_t *kv; - u64 rv = (u64) ~ 0; - - if (PREDICT_FALSE (bucket_contents == PFHASH_BUCKET_OVERFLOW)) - { - uword *hp; - hp = hash_get_mem (p->overflow_hash, key); - if (hp) - return hp[0]; - return (u64) ~ 0; - } - - kv = &p->kvp[bucket_contents].kv8v8; - - rv = (kv->kb.k_u64[0] == key[0]) ? kv->values[0] : rv; - rv = (kv->kb.k_u64[1] == key[0]) ? kv->values[1] : rv; - rv = (kv->kb.k_u64[2] == key[0]) ? kv->values[2] : rv; - rv = (kv->kb.k_u64[3] == key[0]) ? kv->values[3] : rv; - - return rv; -} - -static inline u32 -pfhash_search_kv_4 (pfhash_t * p, u32 bucket_contents, u32 * key) -{ - u32x4 vector_key; - u32x4 is_equal[2]; - u32 zbm[2], winner_index; - pfhash_kv_4_t *kv; - - if (PREDICT_FALSE (bucket_contents == PFHASH_BUCKET_OVERFLOW)) - { - uword *hp; - hp = hash_get_mem (p->overflow_hash, key); - if (hp) - return hp[0]; - return (u32) ~ 0; - } - - kv = &p->kvp[bucket_contents].kv4; - - vector_key = u32x4_splat (key[0]); - - is_equal[0] = u32x4_is_equal (kv->kb.k_u32x4[0], vector_key); - is_equal[1] = u32x4_is_equal (kv->kb.k_u32x4[1], vector_key); - zbm[0] = ~u32x4_zero_byte_mask (is_equal[0]) & 0xFFFF; - zbm[1] = ~u32x4_zero_byte_mask (is_equal[1]) & 0xFFFF; - - if (PREDICT_FALSE ((zbm[0] == 0) && (zbm[1] == 0))) - return (u32) ~ 0; - - winner_index = min_log2 (zbm[0]) >> 2; - winner_index = zbm[1] ? (4 + (min_log2 (zbm[1]) >> 2)) : winner_index; - - return kv->values[winner_index]; -} - -#endif /* CLIB_HAVE_VEC128 */ - -#endif /* included_clib_pfhash_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/phash.c b/vppinfra/vppinfra/phash.c deleted file mode 100644 index 14da522594a..00000000000 --- a/vppinfra/vppinfra/phash.c +++ /dev/null @@ -1,1017 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2005 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -/* This is all stolen from Bob Jenkins and reworked for clib. Thanks - once again Bob for the great work. */ - -/* ------------------------------------------------------------------------------- -perfect.c: code to generate code for a hash for perfect hashing. -(c) Bob Jenkins, September 1996, December 1999 -You may use this code in any way you wish, and it is free. No warranty. -I hereby place this in the public domain. -Source is http://burtleburtle.net/bob/c/perfect.c - -This generates a minimal perfect hash function. That means, given a -set of n keys, this determines a hash function that maps each of -those keys into a value in 0..n-1 with no collisions. - -The perfect hash function first uses a normal hash function on the key -to determine (a,b) such that the pair (a,b) is distinct for all -keys, then it computes a^scramble[tab[b]] to get the final perfect hash. -tab[] is an array of 1-byte values and scramble[] is a 256-term array of -2-byte or 4-byte values. If there are n keys, the length of tab[] is a -power of two between n/3 and n. - -I found the idea of computing distinct (a,b) values in "Practical minimal -perfect hash functions for large databases", Fox, Heath, Chen, and Daoud, -Communications of the ACM, January 1992. They found the idea in Chichelli -(CACM Jan 1980). Beyond that, our methods differ. - -The key is hashed to a pair (a,b) where a in 0..*alen*-1 and b in -0..*blen*-1. A fast hash function determines both a and b -simultaneously. Any decent hash function is likely to produce -hashes so that (a,b) is distinct for all pairs. I try the hash -using different values of *salt* until all pairs are distinct. - -The final hash is (a XOR scramble[tab[b]]). *scramble* is a -predetermined mapping of 0..255 into 0..smax-1. *tab* is an -array that we fill in in such a way as to make the hash perfect. - -First we fill in all values of *tab* that are used by more than one -key. We try all possible values for each position until one works. - -This leaves m unmapped keys and m values that something could hash to. -If you treat unmapped keys as lefthand nodes and unused hash values -as righthand nodes, and draw a line connecting each key to each hash -value it could map to, you get a bipartite graph. We attempt to -find a perfect matching in this graph. If we succeed, we have -determined a perfect hash for the whole set of keys. - -*scramble* is used because (a^tab[i]) clusters keys around *a*. ------------------------------------------------------------------------------- -*/ - -#include <vppinfra/bitmap.h> -#include <vppinfra/format.h> -#include <vppinfra/phash.h> -#include <vppinfra/random.h> - -static void -init_keys_direct_u32 (phash_main_t * pm) -{ - int n_keys_left, b_mask, a_shift; - u32 seed; - phash_key_t *k; - - seed = pm->hash_seed; - b_mask = (1 << pm->b_bits) - 1; - a_shift = BITS (seed) - pm->a_bits; - - k = pm->keys; - n_keys_left = vec_len (pm->keys); - - while (n_keys_left >= 2) - { - u32 x0, y0, z0; - u32 x1, y1, z1; - - x0 = y0 = z0 = seed; - x1 = y1 = z1 = seed; - x0 += (u32) k[0].key; - x1 += (u32) k[1].key; - - hash_mix32 (x0, y0, z0); - hash_mix32 (x1, y1, z1); - - k[0].b = z0 & b_mask; - k[1].b = z1 & b_mask; - k[0].a = z0 >> a_shift; - k[1].a = z1 >> a_shift; - if (PREDICT_FALSE (a_shift >= BITS (z0))) - k[0].a = k[1].a = 0; - - k += 2; - n_keys_left -= 2; - } - - if (n_keys_left >= 1) - { - u32 x0, y0, z0; - - x0 = y0 = z0 = seed; - x0 += k[0].key; - - hash_mix32 (x0, y0, z0); - - k[0].b = z0 & b_mask; - k[0].a = z0 >> a_shift; - if (PREDICT_FALSE (a_shift >= BITS (z0))) - k[0].a = 0; - - k += 1; - n_keys_left -= 1; - } -} - -static void -init_keys_direct_u64 (phash_main_t * pm) -{ - int n_keys_left, b_mask, a_shift; - u64 seed; - phash_key_t *k; - - seed = pm->hash_seed; - b_mask = (1 << pm->b_bits) - 1; - a_shift = BITS (seed) - pm->a_bits; - - k = pm->keys; - n_keys_left = vec_len (pm->keys); - - while (n_keys_left >= 2) - { - u64 x0, y0, z0; - u64 x1, y1, z1; - - x0 = y0 = z0 = seed; - x1 = y1 = z1 = seed; - x0 += (u64) k[0].key; - x1 += (u64) k[1].key; - - hash_mix64 (x0, y0, z0); - hash_mix64 (x1, y1, z1); - - k[0].b = z0 & b_mask; - k[1].b = z1 & b_mask; - k[0].a = z0 >> a_shift; - k[1].a = z1 >> a_shift; - if (PREDICT_FALSE (a_shift >= BITS (z0))) - k[0].a = k[1].a = 0; - - k += 2; - n_keys_left -= 2; - } - - if (n_keys_left >= 1) - { - u64 x0, y0, z0; - - x0 = y0 = z0 = seed; - x0 += k[0].key; - - hash_mix64 (x0, y0, z0); - - k[0].b = z0 & b_mask; - k[0].a = z0 >> a_shift; - if (PREDICT_FALSE (a_shift >= BITS (z0))) - k[0].a = 0; - - k += 1; - n_keys_left -= 1; - } -} - -static void -init_keys_indirect_u32 (phash_main_t * pm) -{ - int n_keys_left, b_mask, a_shift; - u32 seed; - phash_key_t *k; - - seed = pm->hash_seed; - b_mask = (1 << pm->b_bits) - 1; - a_shift = BITS (seed) - pm->a_bits; - - k = pm->keys; - n_keys_left = vec_len (pm->keys); - - while (n_keys_left >= 2) - { - u32 xyz[6]; - u32 x0, y0, z0; - u32 x1, y1, z1; - - pm->key_seed2 (pm->private, k[0].key, k[1].key, &xyz); - - x0 = y0 = z0 = seed; - x1 = y1 = z1 = seed; - x0 += xyz[0]; - y0 += xyz[1]; - z0 += xyz[2]; - x1 += xyz[3]; - y1 += xyz[4]; - z1 += xyz[5]; - - hash_mix32 (x0, y0, z0); - hash_mix32 (x1, y1, z1); - - k[0].b = z0 & b_mask; - k[1].b = z1 & b_mask; - k[0].a = z0 >> a_shift; - k[1].a = z1 >> a_shift; - if (PREDICT_FALSE (a_shift >= BITS (z0))) - k[0].a = k[1].a = 0; - - k += 2; - n_keys_left -= 2; - } - - if (n_keys_left >= 1) - { - u32 xyz[3]; - u32 x0, y0, z0; - - pm->key_seed1 (pm->private, k[0].key, &xyz); - - x0 = y0 = z0 = seed; - x0 += xyz[0]; - y0 += xyz[1]; - z0 += xyz[2]; - - hash_mix32 (x0, y0, z0); - - k[0].b = z0 & b_mask; - k[0].a = z0 >> a_shift; - if (PREDICT_FALSE (a_shift >= BITS (z0))) - k[0].a = 0; - - k += 1; - n_keys_left -= 1; - } -} - -static void -init_keys_indirect_u64 (phash_main_t * pm) -{ - int n_keys_left, b_mask, a_shift; - u64 seed; - phash_key_t *k; - - seed = pm->hash_seed; - b_mask = (1 << pm->b_bits) - 1; - a_shift = BITS (seed) - pm->a_bits; - - k = pm->keys; - n_keys_left = vec_len (pm->keys); - - while (n_keys_left >= 2) - { - u64 xyz[6]; - u64 x0, y0, z0; - u64 x1, y1, z1; - - pm->key_seed2 (pm->private, k[0].key, k[1].key, &xyz); - - x0 = y0 = z0 = seed; - x1 = y1 = z1 = seed; - x0 += xyz[0]; - y0 += xyz[1]; - z0 += xyz[2]; - x1 += xyz[3]; - y1 += xyz[4]; - z1 += xyz[5]; - - hash_mix64 (x0, y0, z0); - hash_mix64 (x1, y1, z1); - - k[0].b = z0 & b_mask; - k[1].b = z1 & b_mask; - k[0].a = z0 >> a_shift; - k[1].a = z1 >> a_shift; - if (PREDICT_FALSE (a_shift >= BITS (z0))) - k[0].a = k[1].a = 0; - - k += 2; - n_keys_left -= 2; - } - - if (n_keys_left >= 1) - { - u64 xyz[3]; - u64 x0, y0, z0; - - pm->key_seed1 (pm->private, k[0].key, &xyz); - - x0 = y0 = z0 = seed; - x0 += xyz[0]; - y0 += xyz[1]; - z0 += xyz[2]; - - hash_mix64 (x0, y0, z0); - - k[0].b = z0 & b_mask; - k[0].a = z0 >> a_shift; - if (PREDICT_FALSE (a_shift >= BITS (z0))) - k[0].a = 0; - - k += 1; - n_keys_left -= 1; - } -} - -/* - * insert keys into table according to key->b - * check if the initial hash might work - */ -static int -init_tabb (phash_main_t * pm) -{ - int no_collisions; - phash_tabb_t *tb; - phash_key_t *k, *l; - - if (pm->key_seed1) - { - if (pm->flags & PHASH_FLAG_MIX64) - init_keys_indirect_u64 (pm); - else - init_keys_indirect_u32 (pm); - } - else - { - if (pm->flags & PHASH_FLAG_MIX64) - init_keys_direct_u64 (pm); - else - init_keys_direct_u32 (pm); - } - - if (!pm->tabb) - vec_resize (pm->tabb, 1 << pm->b_bits); - else - vec_foreach (tb, pm->tabb) phash_tabb_free (tb); - - /* Two keys with the same (a,b) guarantees a collision */ - no_collisions = 1; - vec_foreach (k, pm->keys) - { - u32 i, *ki; - - tb = pm->tabb + k->b; - ki = tb->keys; - for (i = 0; i < vec_len (ki); i++) - { - l = pm->keys + ki[i]; - if (k->a == l->a) - { - /* Given keys are supposed to be unique. */ - if (pm->key_is_equal - && pm->key_is_equal (pm->private, l->key, k->key)) - clib_error ("duplicate keys"); - no_collisions = 0; - goto done; - } - } - - vec_add1 (tb->keys, k - pm->keys); - } - -done: - return no_collisions; -} - -/* Try to apply an augmenting list */ -static int -apply (phash_main_t * pm, u32 tail, u32 rollback) -{ - phash_key_t *k; - phash_tabb_t *pb; - phash_tabq_t *q_child, *q_parent; - u32 ki, i, hash, child, parent; - u32 stabb; /* scramble[tab[b]] */ - int no_collision; - - no_collision = 1; - - /* Walk from child to parent until root is reached. */ - for (child = tail - 1; child; child = parent) - { - q_child = &pm->tabq[child]; - parent = q_child->parent_q; - q_parent = &pm->tabq[parent]; - - /* find parent's list of siblings */ - ASSERT (q_parent->b_q < vec_len (pm->tabb)); - pb = pm->tabb + q_parent->b_q; - - /* erase old hash values */ - stabb = pm->scramble[pb->val_b]; - for (i = 0; i < vec_len (pb->keys); i++) - { - ki = pb->keys[i]; - k = pm->keys + ki; - hash = k->a ^ stabb; - - /* Erase hash for all of child's siblings. */ - if (ki == pm->tabh[hash]) - pm->tabh[hash] = ~0; - } - - /* change pb->val_b, which will change the hashes of all parent siblings */ - pb->val_b = rollback ? q_child->oldval_q : q_child->newval_q; - - /* set new hash values */ - stabb = pm->scramble[pb->val_b]; - for (i = 0; i < vec_len (pb->keys); i++) - { - ki = pb->keys[i]; - k = pm->keys + ki; - - hash = k->a ^ stabb; - if (rollback) - { - if (parent == 0) - continue; /* root never had a hash */ - } - else if (pm->tabh[hash] != ~0) - { - /* Very rare case: roll back any changes. */ - apply (pm, tail, /* rollback changes */ 1); - no_collision = 0; - goto done; - } - pm->tabh[hash] = ki; - } - } - -done: - return no_collision; -} - - -/* -------------------------------------------------------------------------------- -augment(): Add item to the mapping. - -Construct a spanning tree of *b*s with *item* as root, where each -parent can have all its hashes changed (by some new val_b) with -at most one collision, and each child is the b of that collision. - -I got this from Tarjan's "Data Structures and Network Algorithms". The -path from *item* to a *b* that can be remapped with no collision is -an "augmenting path". Change values of tab[b] along the path so that -the unmapped key gets mapped and the unused hash value gets used. - -Assuming 1 key per b, if m out of n hash values are still unused, -you should expect the transitive closure to cover n/m nodes before -an unused node is found. Sum(i=1..n)(n/i) is about nlogn, so expect -this approach to take about nlogn time to map all single-key b's. -------------------------------------------------------------------------------- - -high_water: a value higher than any now in tabb[].water_b. -*/ -static int -augment (phash_main_t * pm, u32 b_root, u32 high_water) -{ - u32 q; /* current position walking through the queue */ - u32 tail; /* tail of the queue. 0 is the head of the queue. */ - phash_tabb_t *tb_parent, *tb_child, *tb_hit; - phash_key_t *k_parent, *k_child; - u32 v, v_limit; /* possible value for myb->val_b */ - u32 i, ki, hash; - - v_limit = - 1 << ((pm->flags & PHASH_FLAG_USE_SCRAMBLE) ? pm->s_bits : BITS (u8)); - - /* Initialize the root of the spanning tree. */ - pm->tabq[0].b_q = b_root; - tail = 1; - - /* construct the spanning tree by walking the queue, add children to tail */ - for (q = 0; q < tail; q++) - { - if ((pm->flags & PHASH_FLAG_FAST_MODE) - && !(pm->flags & PHASH_FLAG_MINIMAL) && q == 1) - break; /* don't do transitive closure */ - - tb_parent = pm->tabb + pm->tabq[q].b_q; /* the b for this node */ - - for (v = 0; v < v_limit; v++) - { - tb_child = 0; - - for (i = 0; i < vec_len (tb_parent->keys); i++) - { - ki = tb_parent->keys[i]; - k_parent = pm->keys + ki; - - hash = k_parent->a ^ pm->scramble[v]; - if (hash >= pm->hash_max) - goto try_next_v; /* hash code out of bounds => we can't use this v */ - - ki = pm->tabh[hash]; - if (ki == ~0) - continue; - - k_child = pm->keys + ki; - tb_hit = pm->tabb + k_child->b; - - if (tb_child) - { - /* Hit at most one child b. */ - if (tb_child == tb_hit) - goto try_next_v; - } - else - { - /* Remember this as child b. */ - tb_child = tb_hit; - if (tb_hit->water_b == high_water) - goto try_next_v; /* already explored */ - } - } - - /* tb_parent with v has either one or zero collisions. */ - - /* add childb to the queue of reachable things */ - if (tb_child) - tb_child->water_b = high_water; - pm->tabq[tail].b_q = tb_child ? tb_child - pm->tabb : ~0; - pm->tabq[tail].newval_q = v; /* how to make parent (myb) use this hash */ - pm->tabq[tail].oldval_q = tb_parent->val_b; /* need this for rollback */ - pm->tabq[tail].parent_q = q; - ++tail; - - /* Found a v with no collisions? */ - if (!tb_child) - { - /* Try to apply the augmenting path. */ - if (apply (pm, tail, /* rollback */ 0)) - return 1; /* success, item was added to the perfect hash */ - --tail; /* don't know how to handle such a child! */ - } - - try_next_v: - ; - } - } - return 0; -} - - -static phash_tabb_t *sort_tabb; - -static int -phash_tabb_compare (void *a1, void *a2) -{ - u32 *b1 = a1; - u32 *b2 = a2; - phash_tabb_t *tb1, *tb2; - - tb1 = sort_tabb + b1[0]; - tb2 = sort_tabb + b2[0]; - - return ((int) vec_len (tb2->keys) - (int) vec_len (tb1->keys)); -} - -/* find a mapping that makes this a perfect hash */ -static int -perfect (phash_main_t * pm) -{ - u32 i; - - /* clear any state from previous attempts */ - if (vec_bytes (pm->tabh)) - memset (pm->tabh, ~0, vec_bytes (pm->tabh)); - - vec_validate (pm->tabb_sort, vec_len (pm->tabb) - 1); - for (i = 0; i < vec_len (pm->tabb_sort); i++) - pm->tabb_sort[i] = i; - - sort_tabb = pm->tabb; - - vec_sort_with_function (pm->tabb_sort, phash_tabb_compare); - - /* In descending order by number of keys, map all *b*s */ - for (i = 0; i < vec_len (pm->tabb_sort); i++) - { - if (!augment (pm, pm->tabb_sort[i], i + 1)) - return 0; - } - - /* Success! We found a perfect hash of all keys into 0..nkeys-1. */ - return 1; -} - - -/* - * Find initial a_bits = log2 (a_max), b_bits = log2 (b_max). - * Initial a_max and b_max values were found empirically. Some factors: - * - * If s_max<256 there is no scramble, so tab[b] needs to cover 0..s_max-1. - * - * a_max and b_max must be powers of 2 because the values in 0..a_max-1 and - * 0..b_max-1 are produced by applying a bitmask to the initial hash function. - * - * a_max must be less than s_max, in fact less than n_keys, because otherwise - * there would often be no i such that a^scramble[i] is in 0..n_keys-1 for - * all the *a*s associated with a given *b*, so there would be no legal - * value to assign to tab[b]. This only matters when we're doing a minimal - * perfect hash. - * - * It takes around 800 trials to find distinct (a,b) with nkey=s_max*(5/8) - * and a_max*b_max = s_max*s_max/32. - * - * Values of b_max less than s_max/4 never work, and s_max/2 always works. - * - * We want b_max as small as possible because it is the number of bytes in - * the huge array we must create for the perfect hash. - * - * When nkey <= s_max*(5/8), b_max=s_max/4 works much more often with - * a_max=s_max/8 than with a_max=s_max/4. Above s_max*(5/8), b_max=s_max/4 - * doesn't seem to care whether a_max=s_max/8 or a_max=s_max/4. I think it - * has something to do with 5/8 = 1/8 * 5. For example examine 80000, - * 85000, and 90000 keys with different values of a_max. This only matters - * if we're doing a minimal perfect hash. - * - * When a_max*b_max <= 1<<U32BITS, the initial hash must produce one integer. - * Bigger than that it must produce two integers, which increases the - * cost of the hash per character hashed. - */ -static void -guess_initial_parameters (phash_main_t * pm) -{ - u32 s_bits, s_max, a_max, b_max, n_keys; - int is_minimal, is_fast_mode; - const u32 b_max_use_scramble_threshold = 4096; - - is_minimal = (pm->flags & PHASH_FLAG_MINIMAL) != 0; - is_fast_mode = (pm->flags & PHASH_FLAG_FAST_MODE) != 0; - - n_keys = vec_len (pm->keys); - s_bits = max_log2 (n_keys); - s_max = 1 << s_bits; - a_max = 0; - - if (is_minimal) - { - switch (s_bits) - { - case 0: - a_max = 1; - b_max = 1; - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - /* - * Was: a_max = is_minimal ? s_max / 2 : s_max; - * However, we know that is_minimal must be true, so the - * if-arm of the ternary expression is always executed. - */ - a_max = s_max / 2; - b_max = s_max / 2; - break; - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - case 15: - case 16: - case 17: - if (is_fast_mode) - { - a_max = s_max / 2; - b_max = s_max / 4; - } - else if (s_max / 4 < b_max_use_scramble_threshold) - { - if (n_keys <= s_max * 0.52) - a_max = b_max = s_max / 8; - else - a_max = b_max = s_max / 4; - } - else - { - a_max = ((n_keys <= s_max * (5.0 / 8.0)) ? s_max / 8 : - (n_keys <= - s_max * (3.0 / 4.0)) ? s_max / 4 : s_max / 2); - b_max = s_max / 4; /* always give the small size a shot */ - } - break; - case 18: - if (is_fast_mode) - a_max = b_max = s_max / 2; - else - { - a_max = s_max / 8; /* never require the multiword hash */ - b_max = (n_keys <= s_max * (5.0 / 8.0)) ? s_max / 4 : s_max / 2; - } - break; - case 19: - case 20: - a_max = (n_keys <= s_max * (5.0 / 8.0)) ? s_max / 8 : s_max / 2; - b_max = (n_keys <= s_max * (5.0 / 8.0)) ? s_max / 4 : s_max / 2; - break; - default: - /* Just find a hash as quick as possible. - We'll be thrashing virtual memory at this size. */ - a_max = b_max = s_max / 2; - break; - } - } - else - { - /* Non-minimal perfect hash. */ - if (is_fast_mode && n_keys > s_max * 0.8) - { - s_max *= 2; - s_bits += 1; - } - - if (s_max / 4 <= (1 << 14)) - b_max = ((n_keys <= s_max * 0.56) ? s_max / 32 : - (n_keys <= s_max * 0.74) ? s_max / 16 : s_max / 8); - else - b_max = ((n_keys <= s_max * 0.6) ? s_max / 16 : - (n_keys <= s_max * 0.8) ? s_max / 8 : s_max / 4); - - if (is_fast_mode && b_max < s_max / 8) - b_max = s_max / 8; - - if (a_max < 1) - a_max = 1; - if (b_max < 1) - b_max = 1; - } - - ASSERT (s_max == (1 << s_bits)); - ASSERT (is_pow2 (a_max)); - ASSERT (is_pow2 (b_max)); - pm->s_bits = s_bits; - pm->a_bits = min_log2 (a_max); - pm->b_bits = min_log2 (b_max); - if (b_max >= b_max_use_scramble_threshold) - pm->flags |= PHASH_FLAG_USE_SCRAMBLE; -} - -/* compute p(x), where p is a permutation of 0..(1<<nbits)-1 */ -/* permute(0)=0. This is intended and useful. */ -always_inline u32 -scramble_permute (u32 x, u32 nbits) -{ - int i; - int mask = (1 << nbits) - 1; - int const2 = 1 + nbits / 2; - int const3 = 1 + nbits / 3; - int const4 = 1 + nbits / 4; - int const5 = 1 + nbits / 5; - for (i = 0; i < 20; i++) - { - x = (x + (x << const2)) & mask; - x = (x ^ (x >> const3)); - x = (x + (x << const4)) & mask; - x = (x ^ (x >> const5)); - } - return x; -} - -/* initialize scramble[] with distinct random values in 0..smax-1 */ -static void -scramble_init (phash_main_t * pm) -{ - u32 i; - - /* fill scramble[] with distinct random integers in 0..smax-1 */ - vec_validate (pm->scramble, (1 << (pm->s_bits < 8 ? 8 : pm->s_bits)) - 1); - for (i = 0; i < vec_len (pm->scramble); i++) - pm->scramble[i] = scramble_permute (i, pm->s_bits); -} - -/* Try to find a perfect hash function. */ -clib_error_t * -phash_find_perfect_hash (phash_main_t * pm) -{ - clib_error_t *error = 0; - u32 max_a_bits, n_tries_this_a_b, want_minimal; - - /* guess initial values for s_max, a_max and b_max */ - guess_initial_parameters (pm); - - want_minimal = pm->flags & PHASH_FLAG_MINIMAL; - -new_s: - if (pm->b_bits == 0) - pm->a_bits = pm->s_bits; - - max_a_bits = pm->s_bits - want_minimal; - if (max_a_bits < 1) - max_a_bits = 1; - - pm->hash_max = want_minimal ? vec_len (pm->keys) : (1 << pm->s_bits); - - scramble_init (pm); - - /* Allocate working memory. */ - vec_free (pm->tabh); - vec_validate_init_empty (pm->tabh, pm->hash_max - 1, ~0); - vec_free (pm->tabq); - vec_validate (pm->tabq, 1 << pm->b_bits); - - /* Actually find the perfect hash */ - n_tries_this_a_b = 0; - while (1) - { - /* Choose random hash seeds until keys become unique. */ - pm->hash_seed = random_u64 (&pm->random_seed); - pm->n_seed_trials++; - if (init_tabb (pm)) - { - /* Found unique (A, B). */ - - /* Hash may already be perfect. */ - if (pm->b_bits == 0) - goto done; - - pm->n_perfect_calls++; - if (perfect (pm)) - goto done; - - goto increase_b; - } - - /* Keep trying with different seed value. */ - n_tries_this_a_b++; - if (n_tries_this_a_b < 2048) - continue; - - /* Try to put more bits in (A,B) to make distinct (A,B) more likely */ - if (pm->a_bits < max_a_bits) - pm->a_bits++; - else if (pm->b_bits < pm->s_bits) - { - increase_b: - vec_resize (pm->tabb, vec_len (pm->tabb)); - vec_resize (pm->tabq, vec_len (pm->tabq)); - pm->b_bits++; - } - else - { - /* Can't increase (A, B) any more, so try increasing S. */ - goto new_s; - } - } - -done: - /* Construct mapping table for hash lookups. */ - if (!error) - { - u32 b, v; - - pm->a_shift = ((pm->flags & PHASH_FLAG_MIX64) ? 64 : 32) - pm->a_bits; - pm->b_mask = (1 << pm->b_bits) - 1; - - vec_resize (pm->tab, vec_len (pm->tabb)); - for (b = 0; b < vec_len (pm->tabb); b++) - { - v = pm->tabb[b].val_b; - - /* Apply scramble now for small enough value of b_bits. */ - if (!(pm->flags & PHASH_FLAG_USE_SCRAMBLE)) - v = pm->scramble[v]; - - pm->tab[b] = v; - } - } - - /* Free working memory. */ - phash_main_free_working_memory (pm); - - return error; -} - -/* Slow hash computation for general keys. */ -uword -phash_hash_slow (phash_main_t * pm, uword key) -{ - u32 a, b, v; - - if (pm->flags & PHASH_FLAG_MIX64) - { - u64 x0, y0, z0; - - x0 = y0 = z0 = pm->hash_seed; - - if (pm->key_seed1) - { - u64 xyz[3]; - pm->key_seed1 (pm->private, key, &xyz); - x0 += xyz[0]; - y0 += xyz[1]; - z0 += xyz[2]; - } - else - x0 += key; - - hash_mix64 (x0, y0, z0); - - a = z0 >> pm->a_shift; - b = z0 & pm->b_mask; - } - else - { - u32 x0, y0, z0; - - x0 = y0 = z0 = pm->hash_seed; - - if (pm->key_seed1) - { - u32 xyz[3]; - pm->key_seed1 (pm->private, key, &xyz); - x0 += xyz[0]; - y0 += xyz[1]; - z0 += xyz[2]; - } - else - x0 += key; - - hash_mix32 (x0, y0, z0); - - a = z0 >> pm->a_shift; - b = z0 & pm->b_mask; - } - - v = pm->tab[b]; - if (pm->flags & PHASH_FLAG_USE_SCRAMBLE) - v = pm->scramble[v]; - return a ^ v; -} - -/* Verify that perfect hash is perfect. */ -clib_error_t * -phash_validate (phash_main_t * pm) -{ - phash_key_t *k; - uword *unique_bitmap = 0; - clib_error_t *error = 0; - - vec_foreach (k, pm->keys) - { - uword h = phash_hash_slow (pm, k->key); - - if (h >= pm->hash_max) - { - error = clib_error_return (0, "hash out of range %wd", h); - goto done; - } - - if (clib_bitmap_get (unique_bitmap, h)) - { - error = clib_error_return (0, "hash non-unique"); - goto done; - } - - unique_bitmap = clib_bitmap_ori (unique_bitmap, h); - } - -done: - clib_bitmap_free (unique_bitmap); - return error; -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/phash.h b/vppinfra/vppinfra/phash.h deleted file mode 100644 index 746a0fddfab..00000000000 --- a/vppinfra/vppinfra/phash.h +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2005 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_phash_h -#define included_phash_h - -#include <vppinfra/hash.h> /* for Bob's mixing functions */ - -typedef struct -{ - /* Maybe either pointer to vector or inline word. */ - uword key; - - /* Hash code (A, B). */ - u32 a, b; -} phash_key_t; - -/* Table indexed by B. */ -typedef struct -{ - /* Vector of key indices with this same value of B. */ - u32 *keys; - - /* hash=a^tabb[b].val_b */ - u32 val_b; - - /* High watermark of who has visited this map node. */ - u32 water_b; -} phash_tabb_t; - -always_inline void -phash_tabb_free (phash_tabb_t * b) -{ - vec_free (b->keys); - b->val_b = b->water_b = 0; -} - -typedef struct -{ - /* b that currently occupies this hash */ - u32 b_q; - - /* Queue position of parent that could use this hash. */ - u32 parent_q; - - /* What to change parent tab[b] to use this hash. */ - u32 newval_q; - - /* Original value of tab[b]. */ - u32 oldval_q; -} phash_tabq_t; - -typedef struct -{ - u8 a_bits, b_bits, s_bits, a_shift; - u32 b_mask; - u32 *tab; - u32 *scramble; - - /* Seed value for hash mixer. */ - u64 hash_seed; - - u32 flags; - - /* Key functions want 64 bit keys. - Use hash_mix64 rather than hash_mix32. */ -#define PHASH_FLAG_MIX64 (1 << 0) -#define PHASH_FLAG_MIX32 (0 << 0) - - /* When b_bits is large enough (>= 12) we scramble. */ -#define PHASH_FLAG_USE_SCRAMBLE (1 << 1) - - /* Slow mode gives smaller tables but at the expense of more run time. */ -#define PHASH_FLAG_SLOW_MODE (0 << 2) -#define PHASH_FLAG_FAST_MODE (1 << 2) - - /* Generate minimal perfect hash instead of perfect hash. */ -#define PHASH_FLAG_NON_MINIMAL (0 << 3) -#define PHASH_FLAG_MINIMAL (1 << 3) - - /* vec_len (keys) for minimal hash; - 1 << s_bits for non-minimal hash. */ - u32 hash_max; - - /* Vector of keys. */ - phash_key_t *keys; - - /* Used by callbacks to identify keys. */ - void *private; - - /* Key comparison callback. */ - int (*key_is_equal) (void *private, uword key1, uword key2); - - /* Callback to reduce single key -> hash seeds. */ - void (*key_seed1) (void *private, uword key, void *seed); - - /* Callback to reduce two key2 -> hash seeds. */ - void (*key_seed2) (void *private, uword key1, uword key2, void *seed); - - /* Stuff used to compute perfect hash. */ - u32 random_seed; - - /* Stuff indexed by B. */ - phash_tabb_t *tabb; - - /* Table of B ordered by number of keys in tabb[b]. */ - u32 *tabb_sort; - - /* Unique key (or ~0 if none) for a given hash - H = A ^ scramble[tab[B].val_b]. */ - u32 *tabh; - - /* Stuff indexed by q. */ - phash_tabq_t *tabq; - - /* Stats. */ - u32 n_seed_trials, n_perfect_calls; -} phash_main_t; - -always_inline void -phash_main_free_working_memory (phash_main_t * pm) -{ - vec_free (pm->tabb); - vec_free (pm->tabq); - vec_free (pm->tabh); - vec_free (pm->tabb_sort); - if (!(pm->flags & PHASH_FLAG_USE_SCRAMBLE)) - vec_free (pm->scramble); -} - -always_inline void -phash_main_free (phash_main_t * pm) -{ - phash_main_free_working_memory (pm); - vec_free (pm->tab); - vec_free (pm->keys); - memset (pm, 0, sizeof (pm[0])); -} - -/* Slow hash computation for general keys. */ -uword phash_hash_slow (phash_main_t * pm, uword key); - -/* Main routine to compute perfect hash. */ -clib_error_t *phash_find_perfect_hash (phash_main_t * pm); - -/* Validates that hash is indeed perfect. */ -clib_error_t *phash_validate (phash_main_t * pm); - -/* Unit test. */ -int phash_test_main (unformat_input_t * input); - -#endif /* included_phash_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/pipeline.h b/vppinfra/vppinfra/pipeline.h deleted file mode 100644 index 5a9799b455e..00000000000 --- a/vppinfra/vppinfra/pipeline.h +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - * pipeline.h: software pipeline infrastructure - * - * Copyright (c) 2010 Eliot Dresselhaus - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef included_clib_pipeline_h -#define included_clib_pipeline_h - -#define clib_pipeline_stage(F,TYPE,ARG,I,BODY) \ - always_inline void F##_inline (void * _, u32 I) \ - { TYPE ARG = _; { BODY; } } \ - never_inline void F##_no_inline (TYPE ARG, u32 I) \ - { F##_inline (ARG, I); } - -#define clib_pipeline_stage_static(F,TYPE,ARG,I,BODY) \ - static_always_inline void F##_inline (void * _, u32 I) \ - { TYPE ARG = _; { BODY; } } \ - never_inline void F##_no_inline (TYPE ARG, u32 I) \ - { F##_inline (ARG, I); } - -#define clib_pipeline_stage_no_inline(F,TYPE,ARG,I,BODY) \ - never_inline void F##_no_inline (void * _, u32 I) \ - { TYPE ARG = _; { BODY; } } \ - never_inline void F##_inline (TYPE ARG, u32 I) \ - { F##_no_inline (ARG, I); } - -#define _clib_pipeline_var(v) _clib_pipeline_##v - -#define clib_pipeline_stage_execute(F,A,I,S) \ - F##_##S (A, _clib_pipeline_var(i) - (I)) - -#define clib_pipeline_main_stage(F,A,I) \ - clib_pipeline_stage_execute (F, A, I, inline) -#define clib_pipeline_init_stage(F,A,I) \ - if (_clib_pipeline_var(i) >= (I)) clib_pipeline_stage_execute (F, A, I, no_inline) -#define clib_pipeline_exit_stage(F,A,I) \ - if (_clib_pipeline_var(i) >= (I) && _clib_pipeline_var(i) - (I) < _clib_pipeline_var(n_vectors)) \ - clib_pipeline_stage_execute (F, A, I, no_inline) - -#define clib_pipeline_init_loop \ - for (_clib_pipeline_var(i) = 0; \ - _clib_pipeline_var(i) < \ - clib_min (_clib_pipeline_var(n_stages) - 1, \ - _clib_pipeline_var(n_vectors)); \ - _clib_pipeline_var(i)++) - -#define clib_pipeline_main_loop \ - for (; _clib_pipeline_var(i) < _clib_pipeline_var(n_vectors); \ - _clib_pipeline_var(i)++) - -#define clib_pipeline_exit_loop \ - for (; _clib_pipeline_var(i) < (_clib_pipeline_var(n_vectors) \ - + _clib_pipeline_var(n_stages) - 1); \ - _clib_pipeline_var(i)++) - -#define clib_pipeline_run_2_stage(N,ARG,STAGE0,STAGE1) \ -do { \ - uword _clib_pipeline_var(n_vectors) = (N); \ - uword _clib_pipeline_var(n_stages) = 2; \ - uword _clib_pipeline_var(i); \ - \ - clib_pipeline_init_loop \ - { \ - clib_pipeline_init_stage (STAGE0, ARG, 0); \ - } \ - \ - clib_pipeline_main_loop \ - { \ - clib_pipeline_main_stage (STAGE0, ARG, 0); \ - clib_pipeline_main_stage (STAGE1, ARG, 1); \ - } \ - \ - clib_pipeline_exit_loop \ - { \ - clib_pipeline_exit_stage (STAGE1, ARG, 1); \ - } \ -} while (0) - -#define clib_pipeline_run_3_stage(N,ARG,STAGE0,STAGE1,STAGE2) \ -do { \ - uword _clib_pipeline_var(n_vectors) = (N); \ - uword _clib_pipeline_var(n_stages) = 3; \ - uword _clib_pipeline_var(i); \ - \ - clib_pipeline_init_loop \ - { \ - clib_pipeline_init_stage (STAGE0, ARG, 0); \ - clib_pipeline_init_stage (STAGE1, ARG, 1); \ - } \ - \ - clib_pipeline_main_loop \ - { \ - clib_pipeline_main_stage (STAGE0, ARG, 0); \ - clib_pipeline_main_stage (STAGE1, ARG, 1); \ - clib_pipeline_main_stage (STAGE2, ARG, 2); \ - } \ - \ - clib_pipeline_exit_loop \ - { \ - clib_pipeline_exit_stage (STAGE1, ARG, 1); \ - clib_pipeline_exit_stage (STAGE2, ARG, 2); \ - } \ -} while (0) - -#define clib_pipeline_run_4_stage(N,ARG,STAGE0,STAGE1,STAGE2,STAGE3) \ -do { \ - uword _clib_pipeline_var(n_vectors) = (N); \ - uword _clib_pipeline_var(n_stages) = 4; \ - uword _clib_pipeline_var(i); \ - \ - clib_pipeline_init_loop \ - { \ - clib_pipeline_init_stage (STAGE0, ARG, 0); \ - clib_pipeline_init_stage (STAGE1, ARG, 1); \ - clib_pipeline_init_stage (STAGE2, ARG, 2); \ - } \ - \ - clib_pipeline_main_loop \ - { \ - clib_pipeline_main_stage (STAGE0, ARG, 0); \ - clib_pipeline_main_stage (STAGE1, ARG, 1); \ - clib_pipeline_main_stage (STAGE2, ARG, 2); \ - clib_pipeline_main_stage (STAGE3, ARG, 3); \ - } \ - \ - clib_pipeline_exit_loop \ - { \ - clib_pipeline_exit_stage (STAGE1, ARG, 1); \ - clib_pipeline_exit_stage (STAGE2, ARG, 2); \ - clib_pipeline_exit_stage (STAGE3, ARG, 3); \ - } \ -} while (0) - -#endif /* included_clib_pipeline_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/pool.h b/vppinfra/vppinfra/pool.h deleted file mode 100644 index e1c89e0a5fa..00000000000 --- a/vppinfra/vppinfra/pool.h +++ /dev/null @@ -1,405 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001, 2002, 2003, 2004 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ -/** @file - * @brief Fixed length block allocator. - Pools are built from clib vectors and bitmaps. Use pools when - repeatedly allocating and freeing fixed-size data. Pools are - fast, and avoid memory fragmentation. - */ - -#ifndef included_pool_h -#define included_pool_h - -#include <vppinfra/bitmap.h> -#include <vppinfra/error.h> -#include <vppinfra/mheap.h> - - -typedef struct -{ - /** Bitmap of indices of free objects. */ - uword *free_bitmap; - - /** Vector of free indices. One element for each set bit in bitmap. */ - u32 *free_indices; -} pool_header_t; - -/** Align pool header so that pointers are naturally aligned. */ -#define pool_aligned_header_bytes \ - vec_aligned_header_bytes (sizeof (pool_header_t), sizeof (void *)) - -/** Get pool header from user pool pointer */ -always_inline pool_header_t * -pool_header (void *v) -{ - return vec_aligned_header (v, sizeof (pool_header_t), sizeof (void *)); -} - -/** Validate a pool */ -always_inline void -pool_validate (void *v) -{ - pool_header_t *p = pool_header (v); - uword i, n_free_bitmap; - - if (!v) - return; - - n_free_bitmap = clib_bitmap_count_set_bits (p->free_bitmap); - ASSERT (n_free_bitmap == vec_len (p->free_indices)); - for (i = 0; i < vec_len (p->free_indices); i++) - ASSERT (clib_bitmap_get (p->free_bitmap, p->free_indices[i]) == 1); -} - -always_inline void -pool_header_validate_index (void *v, uword index) -{ - pool_header_t *p = pool_header (v); - - if (v) - vec_validate (p->free_bitmap, index / BITS (uword)); -} - -#define pool_validate_index(v,i) \ -do { \ - uword __pool_validate_index = (i); \ - vec_validate_ha ((v), __pool_validate_index, \ - pool_aligned_header_bytes, /* align */ 0); \ - pool_header_validate_index ((v), __pool_validate_index); \ -} while (0) - -/** Number of active elements in a pool. - * @return Number of active elements in a pool - */ -always_inline uword -pool_elts (void *v) -{ - uword ret = vec_len (v); - if (v) - ret -= vec_len (pool_header (v)->free_indices); - return ret; -} - -/** Number of elements in pool vector. - - @note You probably want to call pool_elts() instead. -*/ -#define pool_len(p) vec_len(p) - -/** Number of elements in pool vector (usable as an lvalue) - - @note You probably don't want to use this macro. -*/ -#define _pool_len(p) _vec_len(p) - -/** Memory usage of pool header. */ -always_inline uword -pool_header_bytes (void *v) -{ - pool_header_t *p = pool_header (v); - - if (!v) - return 0; - - return vec_bytes (p->free_bitmap) + vec_bytes (p->free_indices); -} - -/** Memory usage of pool. */ -#define pool_bytes(P) (vec_bytes (P) + pool_header_bytes (P)) - -/** Local variable naming macro. */ -#define _pool_var(v) _pool_##v - -/** Queries whether pool has at least N_FREE free elements. */ -always_inline uword -pool_free_elts (void *v) -{ - pool_header_t *p = pool_header (v); - uword n_free = 0; - - if (v) - { - n_free += vec_len (p->free_indices); - - /* Space left at end of vector? */ - n_free += vec_capacity (v, sizeof (p[0])) - vec_len (v); - } - - return n_free; -} - -/** Allocate an object E from a pool P (general version). - - First search free list. If nothing is free extend vector of objects. -*/ -#define pool_get_aligned(P,E,A) \ -do { \ - pool_header_t * _pool_var (p) = pool_header (P); \ - uword _pool_var (l); \ - \ - _pool_var (l) = 0; \ - if (P) \ - _pool_var (l) = vec_len (_pool_var (p)->free_indices); \ - \ - if (_pool_var (l) > 0) \ - { \ - /* Return free element from free list. */ \ - uword _pool_var (i) = _pool_var (p)->free_indices[_pool_var (l) - 1]; \ - (E) = (P) + _pool_var (i); \ - _pool_var (p)->free_bitmap = \ - clib_bitmap_andnoti (_pool_var (p)->free_bitmap, _pool_var (i)); \ - _vec_len (_pool_var (p)->free_indices) = _pool_var (l) - 1; \ - } \ - else \ - { \ - /* Nothing on free list, make a new element and return it. */ \ - P = _vec_resize (P, \ - /* length_increment */ 1, \ - /* new size */ (vec_len (P) + 1) * sizeof (P[0]), \ - pool_aligned_header_bytes, \ - /* align */ (A)); \ - E = vec_end (P) - 1; \ - } \ -} while (0) - -/** Allocate an object E from a pool P (unspecified alignment). */ -#define pool_get(P,E) pool_get_aligned(P,E,0) - -/** Use free bitmap to query whether given element is free. */ -#define pool_is_free(P,E) \ -({ \ - pool_header_t * _pool_var (p) = pool_header (P); \ - uword _pool_var (i) = (E) - (P); \ - (_pool_var (i) < vec_len (P)) ? clib_bitmap_get (_pool_var (p)->free_bitmap, _pool_i) : 1; \ -}) - -/** Use free bitmap to query whether given index is free */ -#define pool_is_free_index(P,I) pool_is_free((P),(P)+(I)) - -/** Free an object E in pool P. */ -#define pool_put(P,E) \ -do { \ - pool_header_t * _pool_var (p) = pool_header (P); \ - uword _pool_var (l) = (E) - (P); \ - ASSERT (vec_is_member (P, E)); \ - ASSERT (! pool_is_free (P, E)); \ - \ - /* Add element to free bitmap and to free list. */ \ - _pool_var (p)->free_bitmap = \ - clib_bitmap_ori (_pool_var (p)->free_bitmap, _pool_var (l)); \ - vec_add1 (_pool_var (p)->free_indices, _pool_var (l)); \ -} while (0) - -/** Free pool element with given index. */ -#define pool_put_index(p,i) \ -do { \ - typeof (p) _e = (p) + (i); \ - pool_put (p, _e); \ -} while (0) - -/** Allocate N more free elements to pool (general version). */ -#define pool_alloc_aligned(P,N,A) \ -do { \ - pool_header_t * _p; \ - (P) = _vec_resize ((P), 0, (vec_len (P) + (N)) * sizeof (P[0]), \ - pool_aligned_header_bytes, \ - (A)); \ - _p = pool_header (P); \ - vec_resize (_p->free_indices, (N)); \ - _vec_len (_p->free_indices) -= (N); \ -} while (0) - -/** Allocate N more free elements to pool (unspecified alignment). */ -#define pool_alloc(P,N) pool_alloc_aligned(P,N,0) - -/** Low-level free pool operator (do not call directly). */ -always_inline void * -_pool_free (void *v) -{ - pool_header_t *p = pool_header (v); - if (!v) - return v; - clib_bitmap_free (p->free_bitmap); - vec_free (p->free_indices); - vec_free_h (v, pool_aligned_header_bytes); - return 0; -} - -/** Free a pool. */ -#define pool_free(p) (p) = _pool_free(p) - -/** Optimized iteration through pool. - - @param LO pointer to first element in chunk - @param HI pointer to last element in chunk - @param POOL pool to iterate across - @param BODY operation to perform - - Optimized version which assumes that BODY is smart enough to - process multiple (LOW,HI) chunks. See also pool_foreach(). - */ -#define pool_foreach_region(LO,HI,POOL,BODY) \ -do { \ - uword _pool_var (i), _pool_var (lo), _pool_var (hi), _pool_var (len); \ - uword _pool_var (bl), * _pool_var (b); \ - pool_header_t * _pool_var (p); \ - \ - _pool_var (p) = pool_header (POOL); \ - _pool_var (b) = (POOL) ? _pool_var (p)->free_bitmap : 0; \ - _pool_var (bl) = vec_len (_pool_var (b)); \ - _pool_var (len) = vec_len (POOL); \ - _pool_var (lo) = 0; \ - \ - for (_pool_var (i) = 0; \ - _pool_var (i) <= _pool_var (bl); \ - _pool_var (i)++) \ - { \ - uword _pool_var (m), _pool_var (f); \ - _pool_var (m) = (_pool_var (i) < _pool_var (bl) \ - ? _pool_var (b) [_pool_var (i)] \ - : 1); \ - while (_pool_var (m) != 0) \ - { \ - _pool_var (f) = first_set (_pool_var (m)); \ - _pool_var (hi) = (_pool_var (i) * BITS (_pool_var (b)[0]) \ - + min_log2 (_pool_var (f))); \ - _pool_var (hi) = (_pool_var (i) < _pool_var (bl) \ - ? _pool_var (hi) : _pool_var (len)); \ - _pool_var (m) ^= _pool_var (f); \ - if (_pool_var (hi) > _pool_var (lo)) \ - { \ - (LO) = _pool_var (lo); \ - (HI) = _pool_var (hi); \ - do { BODY; } while (0); \ - } \ - _pool_var (lo) = _pool_var (hi) + 1; \ - } \ - } \ -} while (0) - -/** Iterate through pool. - - @param VAR A variable of same type as pool vector to be used as an - iterator. - @param POOL The pool to iterate across. - @param BODY The operation to perform, typically a code block. See - the example below. - - This macro will call @c BODY with each active pool element. - - It is a bad idea to allocate or free pool element from within - @c pool_foreach. Build a vector of indices and dispose of them later. - - - @par Example - @code{.c} - proc_t *procs; // a pool of processes. - proc_t *proc; // pointer to one process; used as the iterator. - - pool_foreach (proc, procs, ({ - if (proc->state != PROC_STATE_RUNNING) - continue; - - // check a running proc in some way - ... - })); - @endcode - - @warning Because @c pool_foreach is a macro, syntax errors can be - difficult to find inside @c BODY, let alone actual code bugs. One - can temporarily split a complex @c pool_foreach into a trivial - @c pool_foreach which builds a vector of active indices, and a - vec_foreach() (or plain for-loop) to walk the active index vector. - */ -#define pool_foreach(VAR,POOL,BODY) \ -do { \ - uword _pool_foreach_lo, _pool_foreach_hi; \ - pool_foreach_region (_pool_foreach_lo, _pool_foreach_hi, (POOL), \ - ({ \ - for ((VAR) = (POOL) + _pool_foreach_lo; \ - (VAR) < (POOL) + _pool_foreach_hi; \ - (VAR)++) \ - do { BODY; } while (0); \ - })); \ -} while (0) - -/** Returns pointer to element at given index. - - ASSERTs that the supplied index is valid. - Even though one can write correct code of the form - @code - p = pool_base + index; - @endcode - use of @c pool_elt_at_index is strongly suggested. - */ -#define pool_elt_at_index(p,i) \ -({ \ - typeof (p) _e = (p) + (i); \ - ASSERT (! pool_is_free (p, _e)); \ - _e; \ -}) - -/** Return next occupied pool index after @c i, useful for safe iteration. */ -#define pool_next_index(P,I) \ -({ \ - pool_header_t * _pool_var (p) = pool_header (P); \ - uword _pool_var (rv) = (I) + 1; \ - \ - _pool_var(rv) = \ - (_pool_var (rv) < vec_len (P) ? \ - clib_bitmap_next_clear (_pool_var (p)->free_bitmap, _pool_var(rv)) \ - : ~0); \ - _pool_var(rv); \ -}) - -/** Iterate pool by index. */ -#define pool_foreach_index(i,v,body) \ - for ((i) = 0; (i) < vec_len (v); (i)++) \ - { \ - if (! pool_is_free_index ((v), (i))) \ - do { body; } while (0); \ - } - -#endif /* included_pool_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/ptclosure.c b/vppinfra/vppinfra/ptclosure.c deleted file mode 100644 index cda873ef442..00000000000 --- a/vppinfra/vppinfra/ptclosure.c +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <vppinfra/ptclosure.h> - -u8 ** -clib_ptclosure_alloc (int n) -{ - u8 **rv = 0; - u8 *row; - int i; - - ASSERT (n > 0); - - vec_validate (rv, n - 1); - for (i = 0; i < n; i++) - { - row = 0; - vec_validate (row, n - 1); - - rv[i] = row; - } - return rv; -} - -void -clib_ptclosure_free (u8 ** ptc) -{ - u8 *row; - int n = vec_len (ptc); - int i; - - ASSERT (n > 0); - - for (i = 0; i < n; i++) - { - row = ptc[i]; - vec_free (row); - } - vec_free (ptc); -} - -void -clib_ptclosure_copy (u8 ** dst, u8 ** src) -{ - int i, n; - u8 *src_row, *dst_row; - - n = vec_len (dst); - - for (i = 0; i < vec_len (dst); i++) - { - src_row = src[i]; - dst_row = dst[i]; - clib_memcpy (dst_row, src_row, n); - } -} - -/* - * compute the positive transitive closure - * of a relation via Warshall's algorithm. - * - * Ref: - * Warshall, Stephen (January 1962). "A theorem on Boolean matrices". - * Journal of the ACM 9 (1): 11–12. - * - * foo[i][j] = 1 means that item i - * "bears the relation" to item j. - * - * For example: "item i must be before item j" - * - * You could use a bitmap, but since the algorithm is - * O(n**3) in the first place, large N is inadvisable... - * - */ - -u8 ** -clib_ptclosure (u8 ** orig) -{ - int i, j, k; - int n; - u8 **prev, **cur; - - n = vec_len (orig); - prev = clib_ptclosure_alloc (n); - cur = clib_ptclosure_alloc (n); - - clib_ptclosure_copy (prev, orig); - - for (k = 0; k < n; k++) - { - for (i = 0; i < n; i++) - { - for (j = 0; j < n; j++) - { - cur[i][j] = prev[i][j] || (prev[i][k] && prev[k][j]); - } - } - clib_ptclosure_copy (prev, cur); - } - clib_ptclosure_free (prev); - return cur; -} - - - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/ptclosure.h b/vppinfra/vppinfra/ptclosure.h deleted file mode 100644 index ee1609a1250..00000000000 --- a/vppinfra/vppinfra/ptclosure.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef included_clib_ptclosure_h -#define included_clib_ptclosure_h - -#include <vppinfra/vec.h> -#include <vppinfra/format.h> -#include <vppinfra/error.h> - -/* - * set r[i][j] if item i "bears the relation to" item j - * - */ - -u8 **clib_ptclosure_alloc (int n); -void clib_ptclosure_free (u8 ** ptc); -void clib_ptclosure_copy (u8 ** dst, u8 ** src); -u8 **clib_ptclosure (u8 ** orig); - -#endif /* included_clib_ptclosure_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/qhash.c b/vppinfra/vppinfra/qhash.c deleted file mode 100644 index f4e38c4a1d7..00000000000 --- a/vppinfra/vppinfra/qhash.c +++ /dev/null @@ -1,858 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2006 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include <vppinfra/qhash.h> - -#define QHASH_ALL_VALID ((1 << QHASH_KEYS_PER_BUCKET) - 1) - -void * -_qhash_resize (void *v, uword length, uword elt_bytes) -{ - qhash_t *h; - uword l; - - l = clib_max (max_log2 (length), 2 + QHASH_LOG2_KEYS_PER_BUCKET); - - /* Round up if less than 1/2 full. */ - l += ((f64) length / (f64) (1 << l)) < .5; - - v = _vec_resize (0, 1 << l, elt_bytes << l, sizeof (h[0]), - /* align */ sizeof (uword)); - - h = qhash_header (v); - h->n_elts = 0; - h->log2_hash_size = l; - h->hash_keys = - clib_mem_alloc_aligned_no_fail (sizeof (h->hash_keys[0]) << l, - CLIB_CACHE_LINE_BYTES); - vec_resize (h->hash_key_valid_bitmap, - 1 << (l - QHASH_LOG2_KEYS_PER_BUCKET)); - memset (v, ~0, elt_bytes << l); - - return v; -} - -static u8 min_log2_table[256]; - -static inline uword -qhash_min_log2 (uword x) -{ - ASSERT (is_pow2 (x)); - ASSERT (x < 256); - return min_log2_table[x]; -} - -static void -qhash_min_log2_init () -{ - int i; - for (i = 0; i < 256; i++) - min_log2_table[i] = min_log2 (i); -} - -always_inline uword -qhash_get_valid_elt_mask (qhash_t * h, uword i) -{ - return h->hash_key_valid_bitmap[i / QHASH_KEYS_PER_BUCKET]; -} - -always_inline void -qhash_set_valid_elt_mask (qhash_t * h, uword i, uword mask) -{ - h->hash_key_valid_bitmap[i / QHASH_KEYS_PER_BUCKET] = mask; -} - -always_inline uword -qhash_search_bucket (uword * hash_keys, uword search_key, uword m) -{ - uword t; -#define _(i) ((hash_keys[i] == search_key) << i) - t = (_(0) | _(1) | _(2) | _(3)); - if (QHASH_KEYS_PER_BUCKET > 4) - t |= (_(4) | _(5) | _(6) | _(7)); - if (QHASH_KEYS_PER_BUCKET > 8) - t |= (_(8) | _(9) | _(10) | _(11) | _(12) | _(13) | _(14) | _(15)); -#undef _ - return m & t; -} - -/* Lookup multiple keys in the same hash table. */ -void -qhash_get_multiple (void *v, - uword * search_keys, - uword n_search_keys, u32 * result_indices) -{ - qhash_t *h = qhash_header (v); - uword *k, *hash_keys; - uword n_left, bucket_mask; - u32 *r; - - if (!v) - { - memset (result_indices, ~0, sizeof (result_indices[0]) * n_search_keys); - return; - } - - bucket_mask = pow2_mask (h->log2_hash_size) & ~(QHASH_KEYS_PER_BUCKET - 1); - - k = search_keys; - n_left = n_search_keys; - hash_keys = h->hash_keys; - r = result_indices; - - while (n_left >= 2) - { - u32 a0, b0, c0, bi0, valid0, match0; - u32 a1, b1, c1, bi1, valid1, match1; - uword k0, k1, *h0, *h1; - - k0 = k[0]; - k1 = k[1]; - n_left -= 2; - k += 2; - - a0 = a1 = h->hash_seeds[0]; - b0 = b1 = h->hash_seeds[1]; - c0 = c1 = h->hash_seeds[2]; - a0 ^= k0; - a1 ^= k1; -#if uword_bits == 64 - b0 ^= k0 >> 32; - b1 ^= k1 >> 32; -#endif - - hash_mix32_step_1 (a0, b0, c0); - hash_mix32_step_1 (a1, b1, c1); - hash_mix32_step_2 (a0, b0, c0); - hash_mix32_step_2 (a1, b1, c1); - hash_mix32_step_3 (a0, b0, c0); - hash_mix32_step_3 (a1, b1, c1); - - bi0 = c0 & bucket_mask; - bi1 = c1 & bucket_mask; - - h0 = hash_keys + bi0; - h1 = hash_keys + bi1; - - /* Search two buckets. */ - valid0 = qhash_get_valid_elt_mask (h, bi0); - valid1 = qhash_get_valid_elt_mask (h, bi1); - - match0 = qhash_search_bucket (h0, k0, valid0); - match1 = qhash_search_bucket (h1, k1, valid1); - - bi0 += qhash_min_log2 (match0); - bi1 += qhash_min_log2 (match1); - - r[0] = match0 ? bi0 : ~0; - r[1] = match1 ? bi1 : ~0; - r += 2; - - /* Full buckets trigger search of overflow hash. */ - if (PREDICT_FALSE (!match0 && valid0 == QHASH_ALL_VALID)) - { - uword *p = hash_get (h->overflow_hash, k0); - r[-2] = p ? p[0] : ~0; - } - - /* Full buckets trigger search of overflow hash. */ - if (PREDICT_FALSE (!match1 && valid1 == QHASH_ALL_VALID)) - { - uword *p = hash_get (h->overflow_hash, k1); - r[-1] = p ? p[0] : ~0; - } - } - - while (n_left >= 1) - { - u32 a0, b0, c0, bi0, valid0, match0; - uword k0, *h0; - - k0 = k[0]; - n_left -= 1; - k += 1; - - a0 = h->hash_seeds[0]; - b0 = h->hash_seeds[1]; - c0 = h->hash_seeds[2]; - a0 ^= k0; -#if uword_bits == 64 - b0 ^= k0 >> 32; -#endif - - hash_mix32 (a0, b0, c0); - - bi0 = c0 & bucket_mask; - - h0 = hash_keys + bi0; - - /* Search one bucket. */ - valid0 = qhash_get_valid_elt_mask (h, bi0); - match0 = qhash_search_bucket (h0, k0, valid0); - - bi0 += qhash_min_log2 (match0); - - r[0] = match0 ? bi0 : ~0; - r += 1; - - /* Full buckets trigger search of overflow hash. */ - if (PREDICT_FALSE (!match0 && valid0 == QHASH_ALL_VALID)) - { - uword *p = hash_get (h->overflow_hash, k0); - r[-1] = p ? p[0] : ~0; - } - } -} - -/* Lookup multiple keys in the same hash table. - Returns index of first matching key. */ -u32 -qhash_get_first_match (void *v, - uword * search_keys, - uword n_search_keys, uword * matching_key) -{ - qhash_t *h = qhash_header (v); - uword *k, *hash_keys; - uword n_left, match_mask, bucket_mask; - - if (!v) - return ~0; - - match_mask = 0; - bucket_mask = pow2_mask (h->log2_hash_size) & ~(QHASH_KEYS_PER_BUCKET - 1); - - k = search_keys; - n_left = n_search_keys; - hash_keys = h->hash_keys; - while (n_left >= 2) - { - u32 a0, b0, c0, bi0, valid0; - u32 a1, b1, c1, bi1, valid1; - uword k0, k1, *h0, *h1; - - k0 = k[0]; - k1 = k[1]; - n_left -= 2; - k += 2; - - a0 = a1 = h->hash_seeds[0]; - b0 = b1 = h->hash_seeds[1]; - c0 = c1 = h->hash_seeds[2]; - a0 ^= k0; - a1 ^= k1; -#if uword_bits == 64 - b0 ^= k0 >> 32; - b1 ^= k1 >> 32; -#endif - - hash_mix32_step_1 (a0, b0, c0); - hash_mix32_step_1 (a1, b1, c1); - hash_mix32_step_2 (a0, b0, c0); - hash_mix32_step_2 (a1, b1, c1); - hash_mix32_step_3 (a0, b0, c0); - hash_mix32_step_3 (a1, b1, c1); - - bi0 = c0 & bucket_mask; - bi1 = c1 & bucket_mask; - - h0 = hash_keys + bi0; - h1 = hash_keys + bi1; - - /* Search two buckets. */ - valid0 = qhash_get_valid_elt_mask (h, bi0); - valid1 = qhash_get_valid_elt_mask (h, bi1); - match_mask = qhash_search_bucket (h0, k0, valid0); - match_mask |= (qhash_search_bucket (h1, k1, valid1) - << QHASH_KEYS_PER_BUCKET); - if (match_mask) - { - uword bi, is_match1; - - bi = qhash_min_log2 (match_mask); - is_match1 = bi >= QHASH_KEYS_PER_BUCKET; - - bi += ((is_match1 ? bi1 : bi0) - - (is_match1 << QHASH_LOG2_KEYS_PER_BUCKET)); - *matching_key = (k - 2 - search_keys) + is_match1; - return bi; - } - - /* Full buckets trigger search of overflow hash. */ - if (PREDICT_FALSE (valid0 == QHASH_ALL_VALID - || valid1 == QHASH_ALL_VALID)) - { - uword *p = 0; - uword ki = k - 2 - search_keys; - - if (valid0 == QHASH_ALL_VALID) - p = hash_get (h->overflow_hash, k0); - - if (!p && valid1 == QHASH_ALL_VALID) - { - p = hash_get (h->overflow_hash, k1); - ki++; - } - - if (p) - { - *matching_key = ki; - return p[0]; - } - } - } - - while (n_left >= 1) - { - u32 a0, b0, c0, bi0, valid0; - uword k0, *h0; - - k0 = k[0]; - n_left -= 1; - k += 1; - - a0 = h->hash_seeds[0]; - b0 = h->hash_seeds[1]; - c0 = h->hash_seeds[2]; - a0 ^= k0; -#if uword_bits == 64 - b0 ^= k0 >> 32; -#endif - - hash_mix32 (a0, b0, c0); - - bi0 = c0 & bucket_mask; - - h0 = hash_keys + bi0; - - /* Search one bucket. */ - valid0 = qhash_get_valid_elt_mask (h, bi0); - match_mask = qhash_search_bucket (h0, k0, valid0); - if (match_mask) - { - uword bi; - bi = bi0 + qhash_min_log2 (match_mask); - *matching_key = (k - 1 - search_keys); - return bi; - } - - /* Full buckets trigger search of overflow hash. */ - if (PREDICT_FALSE (valid0 == QHASH_ALL_VALID)) - { - uword *p = hash_get (h->overflow_hash, k0); - if (p) - { - *matching_key = (k - 1 - search_keys); - return p[0]; - } - } - } - - return ~0; -} - -static void * -qhash_set_overflow (void *v, uword elt_bytes, - uword key, uword bi, uword * n_elts, u32 * result) -{ - qhash_t *h = qhash_header (v); - uword *p = hash_get (h->overflow_hash, key); - uword i; - - bi /= QHASH_KEYS_PER_BUCKET; - - if (p) - i = p[0]; - else - { - uword l = vec_len (h->overflow_free_indices); - if (l > 0) - { - i = h->overflow_free_indices[l - 1]; - _vec_len (h->overflow_free_indices) = l - 1; - } - else - i = (1 << h->log2_hash_size) + hash_elts (h->overflow_hash); - hash_set (h->overflow_hash, key, i); - vec_validate (h->overflow_counts, bi); - h->overflow_counts[bi] += 1; - *n_elts += 1; - - l = vec_len (v); - if (i >= l) - { - uword dl = round_pow2 (1 + i - l, 8); - v = _vec_resize (v, dl, (l + dl) * elt_bytes, sizeof (h[0]), - /* align */ sizeof (uword)); - memset (v + l * elt_bytes, ~0, dl * elt_bytes); - } - } - - *result = i; - - return v; -} - -static uword -qhash_unset_overflow (void *v, uword key, uword bi, uword * n_elts) -{ - qhash_t *h = qhash_header (v); - uword *p = hash_get (h->overflow_hash, key); - uword result; - - bi /= QHASH_KEYS_PER_BUCKET; - - if (p) - { - result = p[0]; - hash_unset (h->overflow_hash, key); - ASSERT (bi < vec_len (h->overflow_counts)); - ASSERT (h->overflow_counts[bi] > 0); - ASSERT (*n_elts > 0); - vec_add1 (h->overflow_free_indices, result); - h->overflow_counts[bi] -= 1; - *n_elts -= 1; - } - else - result = ~0; - - return result; -} - -always_inline uword -qhash_find_free (uword i, uword valid_mask) -{ - return first_set (~valid_mask & pow2_mask (QHASH_KEYS_PER_BUCKET)); -} - -void * -_qhash_set_multiple (void *v, - uword elt_bytes, - uword * search_keys, - uword n_search_keys, u32 * result_indices) -{ - qhash_t *h = qhash_header (v); - uword *k, *hash_keys; - uword n_left, n_elts, bucket_mask; - u32 *r; - - if (vec_len (v) < n_search_keys) - v = _qhash_resize (v, n_search_keys, elt_bytes); - - if (qhash_min_log2 (2) != 1) - { - qhash_min_log2_init (); - ASSERT (qhash_min_log2 (2) == 1); - } - - ASSERT (v != 0); - - bucket_mask = pow2_mask (h->log2_hash_size) & ~(QHASH_KEYS_PER_BUCKET - 1); - - hash_keys = h->hash_keys; - k = search_keys; - r = result_indices; - n_left = n_search_keys; - n_elts = h->n_elts; - - while (n_left >= 2) - { - u32 a0, b0, c0, bi0, match0, valid0, free0; - u32 a1, b1, c1, bi1, match1, valid1, free1; - uword k0, *h0; - uword k1, *h1; - - k0 = k[0]; - k1 = k[1]; - - /* Keys must be unique. */ - ASSERT (k0 != k1); - - n_left -= 2; - k += 2; - - a0 = a1 = h->hash_seeds[0]; - b0 = b1 = h->hash_seeds[1]; - c0 = c1 = h->hash_seeds[2]; - a0 ^= k0; - a1 ^= k1; -#if uword_bits == 64 - b0 ^= k0 >> 32; - b1 ^= k1 >> 32; -#endif - - hash_mix32_step_1 (a0, b0, c0); - hash_mix32_step_1 (a1, b1, c1); - hash_mix32_step_2 (a0, b0, c0); - hash_mix32_step_2 (a1, b1, c1); - hash_mix32_step_3 (a0, b0, c0); - hash_mix32_step_3 (a1, b1, c1); - - bi0 = c0 & bucket_mask; - bi1 = c1 & bucket_mask; - - h0 = hash_keys + bi0; - h1 = hash_keys + bi1; - - /* Search two buckets. */ - valid0 = qhash_get_valid_elt_mask (h, bi0); - valid1 = qhash_get_valid_elt_mask (h, bi1); - - match0 = qhash_search_bucket (h0, k0, valid0); - match1 = qhash_search_bucket (h1, k1, valid1); - - /* Find first free element starting at hash offset into bucket. */ - free0 = qhash_find_free (c0 & (QHASH_KEYS_PER_BUCKET - 1), valid0); - - valid1 = valid1 | (bi0 == bi1 ? free0 : 0); - free1 = qhash_find_free (c1 & (QHASH_KEYS_PER_BUCKET - 1), valid1); - - n_elts += (match0 == 0) + (match1 == 0); - - match0 = match0 ? match0 : free0; - match1 = match1 ? match1 : free1; - - valid0 |= match0; - valid1 |= match1; - - h0 += qhash_min_log2 (match0); - h1 += qhash_min_log2 (match1); - - if (PREDICT_FALSE (!match0 || !match1)) - goto slow_path2; - - h0[0] = k0; - h1[0] = k1; - r[0] = h0 - hash_keys; - r[1] = h1 - hash_keys; - r += 2; - qhash_set_valid_elt_mask (h, bi0, valid0); - qhash_set_valid_elt_mask (h, bi1, valid1); - continue; - - slow_path2: - if (!match0) - { - n_elts -= 1; - v = qhash_set_overflow (v, elt_bytes, k0, bi0, &n_elts, &r[0]); - } - else - { - h0[0] = k0; - r[0] = h0 - hash_keys; - qhash_set_valid_elt_mask (h, bi0, valid0); - } - if (!match1) - { - n_elts -= 1; - v = qhash_set_overflow (v, elt_bytes, k1, bi1, &n_elts, &r[1]); - } - else - { - h1[0] = k1; - r[1] = h1 - hash_keys; - qhash_set_valid_elt_mask (h, bi1, valid1); - } - r += 2; - } - - while (n_left >= 1) - { - u32 a0, b0, c0, bi0, match0, valid0, free0; - uword k0, *h0; - - k0 = k[0]; - n_left -= 1; - k += 1; - - a0 = h->hash_seeds[0]; - b0 = h->hash_seeds[1]; - c0 = h->hash_seeds[2]; - a0 ^= k0; -#if uword_bits == 64 - b0 ^= k0 >> 32; -#endif - - hash_mix32 (a0, b0, c0); - - bi0 = c0 & bucket_mask; - - h0 = hash_keys + bi0; - - valid0 = qhash_get_valid_elt_mask (h, bi0); - - /* Find first free element starting at hash offset into bucket. */ - free0 = qhash_find_free (c0 & (QHASH_KEYS_PER_BUCKET - 1), valid0); - - match0 = qhash_search_bucket (h0, k0, valid0); - - n_elts += (match0 == 0); - - match0 = match0 ? match0 : free0; - - valid0 |= match0; - - h0 += qhash_min_log2 (match0); - - if (PREDICT_FALSE (!match0)) - goto slow_path1; - - h0[0] = k0; - r[0] = h0 - hash_keys; - r += 1; - qhash_set_valid_elt_mask (h, bi0, valid0); - continue; - - slow_path1: - n_elts -= 1; - v = qhash_set_overflow (v, elt_bytes, k0, bi0, &n_elts, &r[0]); - r += 1; - } - - h = qhash_header (v); - h->n_elts = n_elts; - - return v; -} - -static uword -unset_slow_path (void *v, uword elt_bytes, - uword k0, uword bi0, uword valid0, uword match0, - uword * n_elts) -{ - qhash_t *h = qhash_header (v); - uword i, j = 0, k, l, t = ~0; - hash_pair_t *p, *found; - - if (!match0) - { - if (valid0 == QHASH_ALL_VALID) - t = qhash_unset_overflow (v, k0, bi0, n_elts); - return t; - } - - i = bi0 / QHASH_KEYS_PER_BUCKET; - t = bi0 + qhash_min_log2 (match0); - - if (valid0 == QHASH_ALL_VALID - && i < vec_len (h->overflow_counts) && h->overflow_counts[i] > 0) - { - found = 0; - /* *INDENT-OFF* */ - hash_foreach_pair (p, h->overflow_hash, ({ - j = qhash_hash_mix (h, p->key) / QHASH_KEYS_PER_BUCKET; - if (j == i) - { - found = p; - break; - } - })); - /* *INDENT-ON* */ - ASSERT (found != 0); - ASSERT (j == i); - - l = found->value[0]; - k = found->key; - hash_unset3 (h->overflow_hash, k, &j); - vec_add1 (h->overflow_free_indices, j); - h->overflow_counts[i] -= 1; - - qhash_set_valid_elt_mask (h, bi0, valid0); - - h->hash_keys[t] = k; - clib_memswap (v + t * elt_bytes, v + l * elt_bytes, elt_bytes); - t = l; - } - else - qhash_set_valid_elt_mask (h, bi0, valid0 ^ match0); - - return t; -} - -void -_qhash_unset_multiple (void *v, - uword elt_bytes, - uword * search_keys, - uword n_search_keys, u32 * result_indices) -{ - qhash_t *h = qhash_header (v); - uword *k, *hash_keys; - uword n_left, n_elts, bucket_mask; - u32 *r; - - if (!v) - { - uword i; - for (i = 0; i < n_search_keys; i++) - result_indices[i] = ~0; - } - - bucket_mask = pow2_mask (h->log2_hash_size) & ~(QHASH_KEYS_PER_BUCKET - 1); - - hash_keys = h->hash_keys; - k = search_keys; - r = result_indices; - n_left = n_search_keys; - n_elts = h->n_elts; - - while (n_left >= 2) - { - u32 a0, b0, c0, bi0, match0, valid0; - u32 a1, b1, c1, bi1, match1, valid1; - uword k0, *h0; - uword k1, *h1; - - k0 = k[0]; - k1 = k[1]; - - /* Keys must be unique. */ - ASSERT (k0 != k1); - - n_left -= 2; - k += 2; - - a0 = a1 = h->hash_seeds[0]; - b0 = b1 = h->hash_seeds[1]; - c0 = c1 = h->hash_seeds[2]; - a0 ^= k0; - a1 ^= k1; -#if uword_bits == 64 - b0 ^= k0 >> 32; - b1 ^= k1 >> 32; -#endif - - hash_mix32_step_1 (a0, b0, c0); - hash_mix32_step_1 (a1, b1, c1); - hash_mix32_step_2 (a0, b0, c0); - hash_mix32_step_2 (a1, b1, c1); - hash_mix32_step_3 (a0, b0, c0); - hash_mix32_step_3 (a1, b1, c1); - - bi0 = c0 & bucket_mask; - bi1 = c1 & bucket_mask; - - h0 = hash_keys + bi0; - h1 = hash_keys + bi1; - - /* Search two buckets. */ - valid0 = qhash_get_valid_elt_mask (h, bi0); - valid1 = qhash_get_valid_elt_mask (h, bi1); - - match0 = qhash_search_bucket (h0, k0, valid0); - match1 = qhash_search_bucket (h1, k1, valid1); - - n_elts -= (match0 != 0) + (match1 != 0); - - if (PREDICT_FALSE (valid0 == QHASH_ALL_VALID - || valid1 == QHASH_ALL_VALID)) - goto slow_path2; - - valid0 ^= match0; - qhash_set_valid_elt_mask (h, bi0, valid0); - - valid1 = bi0 == bi1 ? valid0 : valid1; - valid1 ^= match1; - - qhash_set_valid_elt_mask (h, bi1, valid1); - - r[0] = match0 ? bi0 + qhash_min_log2 (match0) : ~0; - r[1] = match1 ? bi1 + qhash_min_log2 (match1) : ~0; - r += 2; - continue; - - slow_path2: - r[0] = unset_slow_path (v, elt_bytes, k0, bi0, valid0, match0, &n_elts); - if (bi0 == bi1) - { - /* Search again in same bucket to test new overflow element. */ - valid1 = qhash_get_valid_elt_mask (h, bi0); - if (!match1) - { - match1 = qhash_search_bucket (h1, k1, valid1); - n_elts -= (match1 != 0); - } - } - r[1] = unset_slow_path (v, elt_bytes, k1, bi1, valid1, match1, &n_elts); - r += 2; - } - - while (n_left >= 1) - { - u32 a0, b0, c0, bi0, match0, valid0; - uword k0, *h0; - - k0 = k[0]; - n_left -= 1; - k += 1; - - a0 = h->hash_seeds[0]; - b0 = h->hash_seeds[1]; - c0 = h->hash_seeds[2]; - a0 ^= k0; -#if uword_bits == 64 - b0 ^= k0 >> 32; -#endif - - hash_mix32 (a0, b0, c0); - - bi0 = c0 & bucket_mask; - - h0 = hash_keys + bi0; - - valid0 = qhash_get_valid_elt_mask (h, bi0); - - match0 = qhash_search_bucket (h0, k0, valid0); - n_elts -= (match0 != 0); - qhash_set_valid_elt_mask (h, bi0, valid0 ^ match0); - - r[0] = match0 ? bi0 + qhash_min_log2 (match0) : ~0; - r += 1; - - if (PREDICT_FALSE (valid0 == QHASH_ALL_VALID)) - r[-1] = unset_slow_path (v, elt_bytes, k0, bi0, valid0, match0, - &n_elts); - } - - h->n_elts = n_elts; -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/qhash.h b/vppinfra/vppinfra/qhash.h deleted file mode 100644 index 9dbbd971ade..00000000000 --- a/vppinfra/vppinfra/qhash.h +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2006 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_qhash_h -#define included_qhash_h - -#include <vppinfra/cache.h> -#include <vppinfra/hash.h> - -/* Word hash tables. */ -typedef struct -{ - /* Number of elements in hash. */ - u32 n_elts; - - u32 log2_hash_size; - - /* Jenkins hash seeds. */ - u32 hash_seeds[3]; - - /* Fall back CLIB hash for overflow in fixed sized buckets. */ - uword *overflow_hash; - - u32 *overflow_counts, *overflow_free_indices; - - u8 *hash_key_valid_bitmap; - - uword *hash_keys; -} qhash_t; - -always_inline qhash_t * -qhash_header (void *v) -{ - return vec_header (v, sizeof (qhash_t)); -} - -always_inline uword -qhash_elts (void *v) -{ - return v ? qhash_header (v)->n_elts : 0; -} - -always_inline uword -qhash_n_overflow (void *v) -{ - return v ? hash_elts (qhash_header (v)->overflow_hash) : 0; -} - -#define QHASH_LOG2_KEYS_PER_BUCKET 2 -#define QHASH_KEYS_PER_BUCKET (1 << QHASH_LOG2_KEYS_PER_BUCKET) - -always_inline uword -qhash_hash_mix (qhash_t * h, uword key) -{ - u32 a, b, c; - - a = h->hash_seeds[0]; - b = h->hash_seeds[1]; - c = h->hash_seeds[2]; - - a ^= key; -#if uword_bits == 64 - b ^= key >> 32; -#endif - - hash_mix32 (a, b, c); - - return c & pow2_mask (h->log2_hash_size); -} - -#define qhash_resize(v,n) (v) = _qhash_resize ((v), (n), sizeof ((v)[0])) - -#define qhash_foreach(var,v,body) - -#define qhash_set_multiple(v,keys,n,results) \ - (v) = _qhash_set_multiple ((v), sizeof ((v)[0]), (keys), (n), (results)) - -#define qhash_unset_multiple(v,keys,n,results) \ - _qhash_unset_multiple ((v), sizeof ((v)[0]), (keys), (n), (results)) - -#define qhash_get(v,key) \ -({ \ - uword _qhash_get_k = (key); \ - qhash_get_first_match ((v), &_qhash_get_k, 1, &_qhash_get_k); \ -}) - -#define qhash_set(v,k) \ -({ \ - uword _qhash_set_k = (k); \ - qhash_set_multiple ((v), &_qhash_set_k, 1, &_qhash_set_k); \ - _qhash_set_k; \ -}) - -#define qhash_unset(v,k) \ -({ \ - uword _qhash_unset_k = (k); \ - qhash_unset_multiple ((v), &_qhash_unset_k, 1, &_qhash_unset_k); \ - _qhash_unset_k; \ -}) - -void *_qhash_resize (void *v, uword length, uword elt_bytes); - -/* Lookup multiple keys in the same hash table. */ -void -qhash_get_multiple (void *v, - uword * search_keys, - uword n_search_keys, u32 * result_indices); - -/* Lookup multiple keys in the same hash table. - Returns index of first matching key. */ -u32 -qhash_get_first_match (void *v, - uword * search_keys, - uword n_search_keys, uword * matching_key); - -/* Set/unset helper functions. */ -void *_qhash_set_multiple (void *v, - uword elt_bytes, - uword * search_keys, - uword n_search_keys, u32 * result_indices); -void -_qhash_unset_multiple (void *v, - uword elt_bytes, - uword * search_keys, - uword n_search_keys, u32 * result_indices); - -#endif /* included_qhash_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/qsort.c b/vppinfra/vppinfra/qsort.c deleted file mode 100644 index 2faa5897eb2..00000000000 --- a/vppinfra/vppinfra/qsort.c +++ /dev/null @@ -1,269 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - * Imported into CLIB by Eliot Dresselhaus from: - * - * This file is part of - * MakeIndex - A formatter and format independent index processor - * - * This file is public domain software donated by - * Nelson Beebe (beebe@science.utah.edu). - * - * modifications copyright (c) 2003 Cisco Systems, Inc. - */ - -#include <vppinfra/clib.h> - -/* - * qsort.c: Our own version of the system qsort routine which is faster by an - * average of 25%, with lows and highs of 10% and 50%. The THRESHold below is - * the insertion sort threshold, and has been adjusted for records of size 48 - * bytes. The MTHREShold is where we stop finding a better median. - */ - -#define THRESH 4 /* threshold for insertion */ -#define MTHRESH 6 /* threshold for median */ - -typedef struct -{ - word qsz; /* size of each record */ - word thresh; /* THRESHold in chars */ - word mthresh; /* MTHRESHold in chars */ - int (*qcmp) (const void *, const void *); /* the comparison routine */ -} qst_t; - -static void qst (qst_t * q, char *base, char *max); - -/* - * qqsort: First, set up some global parameters for qst to share. - * Then, quicksort with qst(), and then a cleanup insertion sort ourselves. - * Sound simple? It's not... - */ - -void -qsort (void *base, uword n, uword size, - int (*compar) (const void *, const void *)) -{ - char *i; - char *j; - char *lo; - char *hi; - char *min; - char c; - char *max; - qst_t _q, *q = &_q; - - if (n <= 1) - return; - - q->qsz = size; - q->qcmp = compar; - q->thresh = q->qsz * THRESH; - q->mthresh = q->qsz * MTHRESH; - max = base + n * q->qsz; - if (n >= THRESH) - { - qst (q, base, max); - hi = base + q->thresh; - } - else - { - hi = max; - } - /* - * First put smallest element, which must be in the first THRESH, in the - * first position as a sentinel. This is done just by searching the - * first THRESH elements (or the first n if n < THRESH), finding the min, - * and swapping it into the first position. - */ - for (j = lo = base; (lo += q->qsz) < hi;) - { - if ((*compar) (j, lo) > 0) - j = lo; - } - if (j != base) - { /* swap j into place */ - for (i = base, hi = base + q->qsz; i < hi;) - { - c = *j; - *j++ = *i; - *i++ = c; - } - } - /* - * With our sentinel in place, we now run the following hyper-fast - * insertion sort. For each remaining element, min, from [1] to [n-1], - * set hi to the index of the element AFTER which this one goes. Then, do - * the standard insertion sort shift on a character at a time basis for - * each element in the frob. - */ - for (min = base; (hi = min += q->qsz) < max;) - { - while ((*q->qcmp) (hi -= q->qsz, min) > 0); - if ((hi += q->qsz) != min) - { - for (lo = min + q->qsz; --lo >= min;) - { - c = *lo; - for (i = j = lo; (j -= q->qsz) >= hi; i = j) - *i = *j; - *i = c; - } - } - } -} - - - -/* - * qst: Do a quicksort. First, find the median element, and put that one in - * the first place as the discriminator. (This "median" is just the median - * of the first, last and middle elements). (Using this median instead of - * the first element is a big win). Then, the usual partitioning/swapping, - * followed by moving the discriminator into the right place. Then, figure - * out the sizes of the two partions, do the smaller one recursively and the - * larger one via a repeat of this code. Stopping when there are less than - * THRESH elements in a partition and cleaning up with an insertion sort (in - * our caller) is a huge win. All data swaps are done in-line, which is - * space-losing but time-saving. (And there are only three places where this - * is done). - */ - -static void -qst (qst_t * q, char *base, char *max) -{ - char *i; - char *j; - char *jj; - char *mid; - int ii; - char c; - char *tmp; - int lo; - int hi; - int qsz = q->qsz; - - lo = (int) (max - base); /* number of elements as chars */ - do - { - /* - * At the top here, lo is the number of characters of elements in the - * current partition. (Which should be max - base). Find the median - * of the first, last, and middle element and make that the middle - * element. Set j to largest of first and middle. If max is larger - * than that guy, then it's that guy, else compare max with loser of - * first and take larger. Things are set up to prefer the middle, - * then the first in case of ties. - */ - mid = i = base + qsz * ((unsigned) (lo / qsz) >> 1); - if (lo >= q->mthresh) - { - j = ((*q->qcmp) ((jj = base), i) > 0 ? jj : i); - if ((*q->qcmp) (j, (tmp = max - qsz)) > 0) - { - /* switch to first loser */ - j = (j == jj ? i : jj); - if ((*q->qcmp) (j, tmp) < 0) - j = tmp; - } - if (j != i) - { - ii = qsz; - do - { - c = *i; - *i++ = *j; - *j++ = c; - } - while (--ii); - } - } - /* Semi-standard quicksort partitioning/swapping */ - for (i = base, j = max - qsz;;) - { - while (i < mid && (*q->qcmp) (i, mid) <= 0) - i += qsz; - while (j > mid) - { - if ((*q->qcmp) (mid, j) <= 0) - { - j -= qsz; - continue; - } - tmp = i + qsz; /* value of i after swap */ - if (i == mid) - { /* j <-> mid, new mid is j */ - mid = jj = j; - } - else - { /* i <-> j */ - jj = j; - j -= qsz; - } - goto swap; - } - if (i == mid) - { - break; - } - else - { /* i <-> mid, new mid is i */ - jj = mid; - tmp = mid = i; /* value of i after swap */ - j -= qsz; - } - swap: - ii = qsz; - do - { - c = *i; - *i++ = *jj; - *jj++ = c; - } - while (--ii); - i = tmp; - } - /* - * Look at sizes of the two partitions, do the smaller one first by - * recursion, then do the larger one by making sure lo is its size, - * base and max are update correctly, and branching back. But only - * repeat (recursively or by branching) if the partition is of at - * least size THRESH. - */ - i = (j = mid) + qsz; - if ((lo = (int) (j - base)) <= (hi = (int) (max - i))) - { - if (lo >= q->thresh) - qst (q, base, j); - base = i; - lo = hi; - } - else - { - if (hi >= q->thresh) - qst (q, i, max); - max = j; - } - } - while (lo >= q->thresh); -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/random.c b/vppinfra/vppinfra/random.c deleted file mode 100644 index fa5bcc8c78a..00000000000 --- a/vppinfra/vppinfra/random.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include <vppinfra/random.h> - -/* Default random seed for standalone version of library. - Value can be overridden by platform code from e.g. - machine's clock count register. */ -u32 standalone_random_default_seed = 1; - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/random.h b/vppinfra/vppinfra/random.h deleted file mode 100644 index 5c139d05490..00000000000 --- a/vppinfra/vppinfra/random.h +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_random_h -#define included_random_h - -#include <vppinfra/clib.h> -#include <vppinfra/vec.h> /* for vec_resize */ -#include <vppinfra/format.h> /* for unformat_input_t */ - -/** \file - Linear Congruential Random Number Generator - - This specific random number generator is described in - "Numerical Recipes in C", 2nd edition, page 284. If you need - random numbers with really excellent statistics, take a look - at Chapter 7... - - By definition, a linear congruential random number generator - is of the form: rand[i+1] = a*rand[i] + c (mod m) for specific - values of (a,c,m). - - In this case, choose m = 2**32 and use the low-order 32-bits of - the 64-bit product a*N[i]. Knuth suggests the use of a=1664525, - H.W. Lewis has tested C=1013904223 extensively. This routine is - reputedly as good as any 32-bit LCRN, and costs only a single - multiply-add. - - Several variants: 32/64-bit, machine word width, - f64 on the closed interval [0,1]. -*/ - -/** \brief 32-bit random number generator */ -always_inline u32 -random_u32 (u32 * seed) -{ - *seed = (1664525 * *seed) + 1013904223; - return *seed; -} - -/* External test routine. */ -int test_random_main (unformat_input_t * input); - -/** \brief Maximum value returned by random_u32() */ -always_inline u32 -random_u32_max (void) -{ - return 0xffffffff; -} - -#ifdef CLIB_UNIX - -#include <unistd.h> /* for getpid */ - -/** \brief Default random seed (unix/linux user-mode) */ -always_inline uword -random_default_seed (void) -{ - return getpid (); -} - -#endif - -#ifdef CLIB_LINUX_KERNEL - -#include <linux/sched.h> /* for jiffies */ - -/** \brief Default random seed (Linux kernel) */ -always_inline uword -random_default_seed (void) -{ - return jiffies; -} - -#endif - -#ifdef CLIB_STANDALONE -extern u32 standalone_random_default_seed; - -always_inline u32 -random_default_seed (void) -{ - return standalone_random_default_seed; -} -#endif - -/** \brief 64-bit random number generator - * Again, constants courtesy of Donald Knuth. - * - */ -always_inline u64 -random_u64 (u64 * seed) -{ - *seed = 6364136223846793005ULL * *seed + 1442695040888963407ULL; - return *seed; -} - -/** \brief machine word size random number generator */ - -always_inline uword -random_uword (u32 * seed) -{ - if (sizeof (uword) == sizeof (u64)) - return random_u64 ((u64 *) seed); - else - return random_u32 (seed); -} - -/** \brief Generate f64 random number in the interval [0,1] */ -always_inline f64 -random_f64 (u32 * seed) -{ - return (f64) random_u32 (seed) / (f64) random_u32_max (); -} - -/** \brief Generate random character vector - - From the alphabet a-z, lower case. - Returns a vector of the supplied length which is NOT guaranteed to be - NULL-terminated. FIXME? -*/ -always_inline u8 * -random_string (u32 * seed, uword len) -{ - u8 *alphabet = (u8 *) "abcdefghijklmnopqrstuvwxyz"; - u8 *s = 0; - word i; - - vec_resize (s, len); - for (i = 0; i < len; i++) - s[i] = alphabet[random_u32 (seed) % 26]; - - return s; -} - -#endif /* included_random_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/random_buffer.c b/vppinfra/vppinfra/random_buffer.c deleted file mode 100644 index df03698066c..00000000000 --- a/vppinfra/vppinfra/random_buffer.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2005 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include <vppinfra/random_buffer.h> - -/* Fill random buffer. */ -void -clib_random_buffer_fill (clib_random_buffer_t * b, uword n_words) -{ - uword *w, n = n_words; - - if (n < 256) - n = 256; - - n = round_pow2 (n, 2 << ISAAC_LOG2_SIZE); - - vec_add2 (b->buffer, w, n); - do - { - isaac2 (b->ctx, w); - w += 2 * ISAAC_SIZE; - n -= 2 * ISAAC_SIZE; - } - while (n > 0); -} - -void -clib_random_buffer_init (clib_random_buffer_t * b, uword seed) -{ - uword i, j; - - memset (b, 0, sizeof (b[0])); - - /* Seed ISAAC. */ - for (i = 0; i < ARRAY_LEN (b->ctx); i++) - { - uword s[ISAAC_SIZE]; - - for (j = 0; j < ARRAY_LEN (s); j++) - s[j] = ARRAY_LEN (b->ctx) * (seed + j) + i; - - isaac_init (&b->ctx[i], s); - } -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/random_buffer.h b/vppinfra/vppinfra/random_buffer.h deleted file mode 100644 index eb318548b0a..00000000000 --- a/vppinfra/vppinfra/random_buffer.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2005 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_clib_random_buffer_h -#define included_clib_random_buffer_h - -#include <vppinfra/clib.h> -#include <vppinfra/random_isaac.h> - -typedef struct -{ - /* Two parallel ISAAC contexts for speed. */ - isaac_t ctx[2]; - - /* Random buffer. */ - uword *buffer; - - /* Cache up to 1 word worth of bytes for random data - less than one word at a time. */ - uword n_cached_bytes; - - union - { - u8 cached_bytes[sizeof (uword)]; - uword cached_word; - }; -} -clib_random_buffer_t; - -always_inline void -clib_random_buffer_free (clib_random_buffer_t * b) -{ - vec_free (b->buffer); -} - -/* Fill random buffer. */ -void clib_random_buffer_fill (clib_random_buffer_t * b, uword n_words); - -/* Initialize random buffer. */ -void clib_random_buffer_init (clib_random_buffer_t * b, uword seed); - -/* Returns word aligned random data, possibly filling buffer. */ -always_inline void * -clib_random_buffer_get_data (clib_random_buffer_t * b, uword n_bytes) -{ - uword n_words, i, l; - - l = b->n_cached_bytes; - if (n_bytes <= l) - { - b->n_cached_bytes = l - n_bytes; - return &b->cached_bytes[l]; - } - - n_words = n_bytes / sizeof (uword); - if (n_bytes % sizeof (uword)) - n_words++; - - /* Enough random words left? */ - if (PREDICT_FALSE (n_words > vec_len (b->buffer))) - clib_random_buffer_fill (b, n_words); - - i = vec_len (b->buffer) - n_words; - _vec_len (b->buffer) = i; - - if (n_bytes < sizeof (uword)) - { - b->cached_word = b->buffer[i]; - b->n_cached_bytes = sizeof (uword) - n_bytes; - return b->cached_bytes; - } - else - return b->buffer + i; -} - -#endif /* included_clib_random_buffer_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/random_isaac.c b/vppinfra/vppinfra/random_isaac.c deleted file mode 100644 index 6f00fc32424..00000000000 --- a/vppinfra/vppinfra/random_isaac.c +++ /dev/null @@ -1,434 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - ------------------------------------------------------------------------------ - By Bob Jenkins, 1996, Public Domain - MODIFIED: - 960327: Creation (addition of randinit, really) - 970719: use context, not global variables, for internal state - 980324: renamed seed to flag - 980605: recommend ISAAC_LOG2_SIZE=4 for noncryptography. - 010626: note this is public domain - ------------------------------------------------------------------------------ - - Modified for CLIB by Eliot Dresselhaus. - Dear Bob, Thanks for all the great work. - Eliot - - modifications copyright (c) 2003 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -/* ISAAC is Bob Jenkins' random number generator. - http://burtleburtle.net/bob/rand/isaacafa.html */ - -#include <vppinfra/random_isaac.h> - -#if uword_bits != 32 && uword_bits != 64 -#error "isaac only works for 32 or 64 bit words" -#endif - -#if uword_bits == 32 - -#define ind32(mm,x) (*(u32 *)((u8 *)(mm) + ((x) & ((ISAAC_SIZE-1)<<2)))) -#define rngstep32(mix,a,b,mm,m,m2,r,x,y) \ -{ \ - x = *m; \ - a = (a^(mix)) + *(m2++); \ - *(m++) = y = ind32(mm,x) + a + b; \ - *(r++) = b = ind32(mm,y>>ISAAC_LOG2_SIZE) + x; \ -} - -void -isaac (isaac_t * ctx, uword * results) -{ - u32 a, b, c, x, y, *m, *mm, *m2, *r, *mend; - - mm = ctx->memory; - r = results; - a = ctx->a; - b = ctx->b; - c = ctx->c; - - b += ++c; - mend = m2 = mm + ARRAY_LEN (ctx->memory) / 2; - m = mm; - while (m < mend) - { - rngstep32 (a << 13, a, b, mm, m, m2, r, x, y); - rngstep32 (a >> 6, a, b, mm, m, m2, r, x, y); - rngstep32 (a << 2, a, b, mm, m, m2, r, x, y); - rngstep32 (a >> 16, a, b, mm, m, m2, r, x, y); - } - - m2 = mm; - while (m2 < mend) - { - rngstep32 (a << 13, a, b, mm, m, m2, r, x, y); - rngstep32 (a >> 6, a, b, mm, m, m2, r, x, y); - rngstep32 (a << 2, a, b, mm, m, m2, r, x, y); - rngstep32 (a >> 16, a, b, mm, m, m2, r, x, y); - } - - ctx->a = a; - ctx->b = b; - ctx->c = c; -} - -/* Perform 2 isaac runs with different contexts simultaneously. */ -void -isaac2 (isaac_t * ctx, uword * results) -{ -#define _(n) \ - u32 a##n, b##n, c##n, x##n, y##n, * m##n, * mm##n, * m2##n, * r##n, * mend##n - - _(0); - _(1); - (void) mend1; /* "set but unused variable" error on mend1 with gcc 4.9 */ -#undef _ - -#define _(n) \ -do { \ - mm##n = ctx[(n)].memory; \ - r##n = results + (n) * ISAAC_SIZE; \ - a##n = ctx[(n)].a; \ - b##n = ctx[(n)].b; \ - c##n = ctx[(n)].c; \ - b##n += ++c##n; \ - mend##n = m2##n = mm##n + ARRAY_LEN (ctx[(n)].memory) / 2; \ - m##n = mm##n; \ -} while (0) - - _(0); - _(1); - -#undef _ - - while (m0 < mend0) - { - rngstep32 (a0 << 13, a0, b0, mm0, m0, m20, r0, x0, y0); - rngstep32 (a1 << 13, a1, b1, mm1, m1, m21, r1, x1, y1); - rngstep32 (a0 >> 6, a0, b0, mm0, m0, m20, r0, x0, y0); - rngstep32 (a1 >> 6, a1, b1, mm1, m1, m21, r1, x1, y1); - rngstep32 (a0 << 2, a0, b0, mm0, m0, m20, r0, x0, y0); - rngstep32 (a1 << 2, a1, b1, mm1, m1, m21, r1, x1, y1); - rngstep32 (a0 >> 16, a0, b0, mm0, m0, m20, r0, x0, y0); - rngstep32 (a1 >> 16, a1, b1, mm1, m1, m21, r1, x1, y1); - } - - m20 = mm0; - m21 = mm1; - while (m20 < mend0) - { - rngstep32 (a0 << 13, a0, b0, mm0, m0, m20, r0, x0, y0); - rngstep32 (a1 << 13, a1, b1, mm1, m1, m21, r1, x1, y1); - rngstep32 (a0 >> 6, a0, b0, mm0, m0, m20, r0, x0, y0); - rngstep32 (a1 >> 6, a1, b1, mm1, m1, m21, r1, x1, y1); - rngstep32 (a0 << 2, a0, b0, mm0, m0, m20, r0, x0, y0); - rngstep32 (a1 << 2, a1, b1, mm1, m1, m21, r1, x1, y1); - rngstep32 (a0 >> 16, a0, b0, mm0, m0, m20, r0, x0, y0); - rngstep32 (a1 >> 16, a1, b1, mm1, m1, m21, r1, x1, y1); - } - - ctx[0].a = a0; - ctx[0].b = b0; - ctx[0].c = c0; - ctx[1].a = a1; - ctx[1].b = b1; - ctx[1].c = c1; -} - -#define mix32(a,b,c,d,e,f,g,h) \ -{ \ - a^=b<<11; d+=a; b+=c; \ - b^=c>>2; e+=b; c+=d; \ - c^=d<<8; f+=c; d+=e; \ - d^=e>>16; g+=d; e+=f; \ - e^=f<<10; h+=e; f+=g; \ - f^=g>>4; a+=f; g+=h; \ - g^=h<<8; b+=g; h+=a; \ - h^=a>>9; c+=h; a+=b; \ -} - -void -isaac_init (isaac_t * ctx, uword * seeds) -{ - word i; - u32 a, b, c, d, e, f, g, h, *m, *r; - - ctx->a = ctx->b = ctx->c = 0; - m = ctx->memory; - r = seeds; - - a = b = c = d = e = f = g = h = 0x9e3779b9; /* the golden ratio */ - - for (i = 0; i < 4; ++i) /* scramble it */ - mix32 (a, b, c, d, e, f, g, h); - - /* initialize using the contents of r[] as the seed */ - for (i = 0; i < ISAAC_SIZE; i += 8) - { - a += r[i]; - b += r[i + 1]; - c += r[i + 2]; - d += r[i + 3]; - e += r[i + 4]; - f += r[i + 5]; - g += r[i + 6]; - h += r[i + 7]; - mix32 (a, b, c, d, e, f, g, h); - m[i] = a; - m[i + 1] = b; - m[i + 2] = c; - m[i + 3] = d; - m[i + 4] = e; - m[i + 5] = f; - m[i + 6] = g; - m[i + 7] = h; - } - - /* do a second pass to make all of the seed affect all of m */ - for (i = 0; i < ISAAC_SIZE; i += 8) - { - a += m[i]; - b += m[i + 1]; - c += m[i + 2]; - d += m[i + 3]; - e += m[i + 4]; - f += m[i + 5]; - g += m[i + 6]; - h += m[i + 7]; - mix32 (a, b, c, d, e, f, g, h); - m[i] = a; - m[i + 1] = b; - m[i + 2] = c; - m[i + 3] = d; - m[i + 4] = e; - m[i + 5] = f; - m[i + 6] = g; - m[i + 7] = h; - } -} -#endif /* uword_bits == 32 */ - -#if uword_bits == 64 - -#define ind64(mm,x) (*(u64 *)((u8 *)(mm) + ((x) & ((ISAAC_SIZE-1)<<3)))) -#define rngstep64(mix,a,b,mm,m,m2,r,x,y) \ -{ \ - x = *m; \ - a = (mix) + *(m2++); \ - *(m++) = y = ind64(mm,x) + a + b; \ - *(r++) = b = ind64(mm,y>>ISAAC_LOG2_SIZE) + x; \ -} - -void -isaac (isaac_t * ctx, uword * results) -{ - u64 a, b, c, x, y, *m, *mm, *m2, *r, *mend; - - mm = ctx->memory; - r = results; - a = ctx->a; - b = ctx->b; - c = ctx->c; - - b += ++c; - mend = m2 = mm + ARRAY_LEN (ctx->memory) / 2; - m = mm; - while (m < mend) - { - rngstep64 (~(a ^ (a << 21)), a, b, mm, m, m2, r, x, y); - rngstep64 (a ^ (a >> 5), a, b, mm, m, m2, r, x, y); - rngstep64 (a ^ (a << 12), a, b, mm, m, m2, r, x, y); - rngstep64 (a ^ (a >> 33), a, b, mm, m, m2, r, x, y); - } - - m2 = mm; - while (m2 < mend) - { - rngstep64 (~(a ^ (a << 21)), a, b, mm, m, m2, r, x, y); - rngstep64 (a ^ (a >> 5), a, b, mm, m, m2, r, x, y); - rngstep64 (a ^ (a << 12), a, b, mm, m, m2, r, x, y); - rngstep64 (a ^ (a >> 33), a, b, mm, m, m2, r, x, y); - } - - ctx->a = a; - ctx->b = b; - ctx->c = c; -} - -/* Perform 2 isaac runs with different contexts simultaneously. */ -void -isaac2 (isaac_t * ctx, uword * results) -{ -#define _(n) \ - u64 a##n, b##n, c##n, x##n, y##n, * m##n, * mm##n, * m2##n, * r##n, * mend##n - - _(0); - _(1); - -#undef _ - -#define _(n) \ -do { \ - mm##n = ctx[(n)].memory; \ - r##n = results + (n) * ISAAC_SIZE; \ - a##n = ctx[(n)].a; \ - b##n = ctx[(n)].b; \ - c##n = ctx[(n)].c; \ - b##n += ++c##n; \ - mend##n = m2##n = mm##n + ARRAY_LEN (ctx[(n)].memory) / 2; \ - m##n = mm##n; \ -} while (0) - - _(0); - _(1); - -#undef _ - - (void) mend1; /* compiler warning */ - - while (m0 < mend0) - { - rngstep64 (~(a0 ^ (a0 << 21)), a0, b0, mm0, m0, m20, r0, x0, y0); - rngstep64 (~(a1 ^ (a1 << 21)), a1, b1, mm1, m1, m21, r1, x1, y1); - rngstep64 (a0 ^ (a0 >> 5), a0, b0, mm0, m0, m20, r0, x0, y0); - rngstep64 (a1 ^ (a1 >> 5), a1, b1, mm1, m1, m21, r1, x1, y1); - rngstep64 (a0 ^ (a0 << 12), a0, b0, mm0, m0, m20, r0, x0, y0); - rngstep64 (a1 ^ (a1 << 12), a1, b1, mm1, m1, m21, r1, x1, y1); - rngstep64 (a0 ^ (a0 >> 33), a0, b0, mm0, m0, m20, r0, x0, y0); - rngstep64 (a1 ^ (a1 >> 33), a1, b1, mm1, m1, m21, r1, x1, y1); - } - - m20 = mm0; - m21 = mm1; - while (m20 < mend0) - { - rngstep64 (~(a0 ^ (a0 << 21)), a0, b0, mm0, m0, m20, r0, x0, y0); - rngstep64 (~(a1 ^ (a1 << 21)), a1, b1, mm1, m1, m21, r1, x1, y1); - rngstep64 (a0 ^ (a0 >> 5), a0, b0, mm0, m0, m20, r0, x0, y0); - rngstep64 (a1 ^ (a1 >> 5), a1, b1, mm1, m1, m21, r1, x1, y1); - rngstep64 (a0 ^ (a0 << 12), a0, b0, mm0, m0, m20, r0, x0, y0); - rngstep64 (a1 ^ (a1 << 12), a1, b1, mm1, m1, m21, r1, x1, y1); - rngstep64 (a0 ^ (a0 >> 33), a0, b0, mm0, m0, m20, r0, x0, y0); - rngstep64 (a1 ^ (a1 >> 33), a1, b1, mm1, m1, m21, r1, x1, y1); - } - - ctx[0].a = a0; - ctx[0].b = b0; - ctx[0].c = c0; - ctx[1].a = a1; - ctx[1].b = b1; - ctx[1].c = c1; -} - -#define mix64(a,b,c,d,e,f,g,h) \ -{ \ - a-=e; f^=h>>9; h+=a; \ - b-=f; g^=a<<9; a+=b; \ - c-=g; h^=b>>23; b+=c; \ - d-=h; a^=c<<15; c+=d; \ - e-=a; b^=d>>14; d+=e; \ - f-=b; c^=e<<20; e+=f; \ - g-=c; d^=f>>17; f+=g; \ - h-=d; e^=g<<14; g+=h; \ -} - -void -isaac_init (isaac_t * ctx, uword * seeds) -{ - word i; - u64 a, b, c, d, e, f, g, h, *m, *r; - - ctx->a = ctx->b = ctx->c = 0; - m = ctx->memory; - r = seeds; - - a = b = c = d = e = f = g = h = 0x9e3779b97f4a7c13LL; /* the golden ratio */ - - for (i = 0; i < 4; ++i) /* scramble it */ - mix64 (a, b, c, d, e, f, g, h); - - for (i = 0; i < ISAAC_SIZE; i += 8) /* fill in mm[] with messy stuff */ - { - a += r[i]; - b += r[i + 1]; - c += r[i + 2]; - d += r[i + 3]; - e += r[i + 4]; - f += r[i + 5]; - g += r[i + 6]; - h += r[i + 7]; - mix64 (a, b, c, d, e, f, g, h); - m[i] = a; - m[i + 1] = b; - m[i + 2] = c; - m[i + 3] = d; - m[i + 4] = e; - m[i + 5] = f; - m[i + 6] = g; - m[i + 7] = h; - } - - /* do a second pass to make all of the seed affect all of mm */ - for (i = 0; i < ISAAC_SIZE; i += 8) - { - a += m[i]; - b += m[i + 1]; - c += m[i + 2]; - d += m[i + 3]; - e += m[i + 4]; - f += m[i + 5]; - g += m[i + 6]; - h += m[i + 7]; - mix64 (a, b, c, d, e, f, g, h); - m[i] = a; - m[i + 1] = b; - m[i + 2] = c; - m[i + 3] = d; - m[i + 4] = e; - m[i + 5] = f; - m[i + 6] = g; - m[i + 7] = h; - } -} -#endif /* uword_bits == 64 */ - - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/random_isaac.h b/vppinfra/vppinfra/random_isaac.h deleted file mode 100644 index 803fbd621e2..00000000000 --- a/vppinfra/vppinfra/random_isaac.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - ------------------------------------------------------------------------------ - By Bob Jenkins, 1996, Public Domain - MODIFIED: - 960327: Creation (addition of randinit, really) - 970719: use context, not global variables, for internal state - 980324: renamed seed to flag - 980605: recommend ISAAC_LOG2_SIZE=4 for noncryptography. - 010626: note this is public domain - ------------------------------------------------------------------------------ - - Modified for CLIB by Eliot Dresselhaus. - Dear Bob, Thanks for all the great work. - Eliot - - modifications copyright (c) 2003 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_random_isaac_h -#define included_random_isaac_h - -#include <vppinfra/clib.h> /* for u32/u64 */ -#include <vppinfra/format.h> /* for unformat_input_t */ - -/* Bob recommends 8 for crypto, 4 for simulations */ -#define ISAAC_LOG2_SIZE (4) -#define ISAAC_SIZE (1 << ISAAC_LOG2_SIZE) - -typedef struct -{ - uword memory[ISAAC_SIZE]; - uword a, b, c; -} isaac_t; - -void isaac (isaac_t * ctx, uword * results); -void isaac2 (isaac_t * ctx, uword * results); -void isaac_init (isaac_t * ctx, uword * results); - -int test_isaac_main (unformat_input_t * input); - -#endif /* included_random_isaac_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/serialize.c b/vppinfra/vppinfra/serialize.c deleted file mode 100644 index 5d401a080c1..00000000000 --- a/vppinfra/vppinfra/serialize.c +++ /dev/null @@ -1,1254 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2005 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -/* Turn data structures into byte streams for saving or transport. */ - -#include <vppinfra/heap.h> -#include <vppinfra/pool.h> -#include <vppinfra/serialize.h> - -void -serialize_64 (serialize_main_t * m, va_list * va) -{ - u64 x = va_arg (*va, u64); - u32 lo, hi; - lo = x; - hi = x >> 32; - serialize_integer (m, lo, sizeof (lo)); - serialize_integer (m, hi, sizeof (hi)); -} - -void -serialize_32 (serialize_main_t * m, va_list * va) -{ - u32 x = va_arg (*va, u32); - serialize_integer (m, x, sizeof (x)); -} - -void -serialize_16 (serialize_main_t * m, va_list * va) -{ - u32 x = va_arg (*va, u32); - serialize_integer (m, x, sizeof (u16)); -} - -void -serialize_8 (serialize_main_t * m, va_list * va) -{ - u32 x = va_arg (*va, u32); - serialize_integer (m, x, sizeof (u8)); -} - -void -unserialize_64 (serialize_main_t * m, va_list * va) -{ - u64 *x = va_arg (*va, u64 *); - u32 lo, hi; - unserialize_integer (m, &lo, sizeof (lo)); - unserialize_integer (m, &hi, sizeof (hi)); - *x = ((u64) hi << 32) | (u64) lo; -} - -void -unserialize_32 (serialize_main_t * m, va_list * va) -{ - u32 *x = va_arg (*va, u32 *); - unserialize_integer (m, x, sizeof (x[0])); -} - -void -unserialize_16 (serialize_main_t * m, va_list * va) -{ - u16 *x = va_arg (*va, u16 *); - u32 t; - unserialize_integer (m, &t, sizeof (x[0])); - x[0] = t; -} - -void -unserialize_8 (serialize_main_t * m, va_list * va) -{ - u8 *x = va_arg (*va, u8 *); - u32 t; - unserialize_integer (m, &t, sizeof (x[0])); - x[0] = t; -} - -void -serialize_f64 (serialize_main_t * m, va_list * va) -{ - f64 x = va_arg (*va, f64); - union - { - f64 f; - u64 i; - } y; - y.f = x; - serialize (m, serialize_64, y.i); -} - -void -serialize_f32 (serialize_main_t * m, va_list * va) -{ - f32 x = va_arg (*va, f64); - union - { - f32 f; - u32 i; - } y; - y.f = x; - serialize_integer (m, y.i, sizeof (y.i)); -} - -void -unserialize_f64 (serialize_main_t * m, va_list * va) -{ - f64 *x = va_arg (*va, f64 *); - union - { - f64 f; - u64 i; - } y; - unserialize (m, unserialize_64, &y.i); - *x = y.f; -} - -void -unserialize_f32 (serialize_main_t * m, va_list * va) -{ - f32 *x = va_arg (*va, f32 *); - union - { - f32 f; - u32 i; - } y; - unserialize_integer (m, &y.i, sizeof (y.i)); - *x = y.f; -} - -void -serialize_cstring (serialize_main_t * m, char *s) -{ - u32 len = s ? strlen (s) : 0; - void *p; - - serialize_likely_small_unsigned_integer (m, len); - if (len > 0) - { - p = serialize_get (m, len); - clib_memcpy (p, s, len); - } -} - -void -unserialize_cstring (serialize_main_t * m, char **s) -{ - char *p, *r = 0; - u32 len; - - len = unserialize_likely_small_unsigned_integer (m); - - /* - * Given broken enough data, we could get len = 0xFFFFFFFF. - * Add one, it overflows, we call vec_new (char, 0), then - * memcpy until we bus error. - */ - if (len > 0 && len != 0xFFFFFFFF) - { - r = vec_new (char, len + 1); - p = unserialize_get (m, len); - clib_memcpy (r, p, len); - - /* Null terminate. */ - r[len] = 0; - } - *s = r; -} - -/* vec_serialize/vec_unserialize helper functions for basic vector types. */ -void -serialize_vec_8 (serialize_main_t * m, va_list * va) -{ - u8 *s = va_arg (*va, u8 *); - u32 n = va_arg (*va, u32); - u8 *p = serialize_get (m, n * sizeof (u8)); - clib_memcpy (p, s, n * sizeof (u8)); -} - -void -unserialize_vec_8 (serialize_main_t * m, va_list * va) -{ - u8 *s = va_arg (*va, u8 *); - u32 n = va_arg (*va, u32); - u8 *p = unserialize_get (m, n); - clib_memcpy (s, p, n); -} - -#define _(n_bits) \ - void serialize_vec_##n_bits (serialize_main_t * m, va_list * va) \ - { \ - u##n_bits * s = va_arg (*va, u##n_bits *); \ - u32 n = va_arg (*va, u32); \ - u##n_bits * p = serialize_get (m, n * sizeof (s[0])); \ - \ - while (n >= 4) \ - { \ - p[0] = clib_host_to_net_u##n_bits (s[0]); \ - p[1] = clib_host_to_net_u##n_bits (s[1]); \ - p[2] = clib_host_to_net_u##n_bits (s[2]); \ - p[3] = clib_host_to_net_u##n_bits (s[3]); \ - s += 4; \ - p += 4; \ - n -= 4; \ - } \ - \ - while (n >= 1) \ - { \ - p[0] = clib_host_to_net_u##n_bits (s[0]); \ - s += 1; \ - p += 1; \ - n -= 1; \ - } \ - } \ - \ - void unserialize_vec_##n_bits (serialize_main_t * m, va_list * va) \ - { \ - u##n_bits * s = va_arg (*va, u##n_bits *); \ - u32 n = va_arg (*va, u32); \ - u##n_bits * p = unserialize_get (m, n * sizeof (s[0])); \ - \ - while (n >= 4) \ - { \ - s[0] = clib_net_to_host_mem_u##n_bits (&p[0]); \ - s[1] = clib_net_to_host_mem_u##n_bits (&p[1]); \ - s[2] = clib_net_to_host_mem_u##n_bits (&p[2]); \ - s[3] = clib_net_to_host_mem_u##n_bits (&p[3]); \ - s += 4; \ - p += 4; \ - n -= 4; \ - } \ - \ - while (n >= 1) \ - { \ - s[0] = clib_net_to_host_mem_u##n_bits (&p[0]); \ - s += 1; \ - p += 1; \ - n -= 1; \ - } \ - } - -_(16); -_(32); -_(64); - -#undef _ - -#define SERIALIZE_VECTOR_CHUNK_SIZE 64 - -void -serialize_vector (serialize_main_t * m, va_list * va) -{ - void *vec = va_arg (*va, void *); - u32 elt_bytes = va_arg (*va, u32); - serialize_function_t *f = va_arg (*va, serialize_function_t *); - u32 l = vec_len (vec); - void *p = vec; - - serialize_integer (m, l, sizeof (l)); - - /* Serialize vector in chunks for cache locality. */ - while (l != 0) - { - u32 n = clib_min (SERIALIZE_VECTOR_CHUNK_SIZE, l); - serialize (m, f, p, n); - l -= n; - p += SERIALIZE_VECTOR_CHUNK_SIZE * elt_bytes; - } -} - -void * -unserialize_vector_ha (serialize_main_t * m, - u32 elt_bytes, - u32 header_bytes, - u32 align, u32 max_length, serialize_function_t * f) -{ - void *v, *p; - u32 l; - - unserialize_integer (m, &l, sizeof (l)); - if (l > max_length) - serialize_error (&m->header, - clib_error_create ("bad vector length %d", l)); - p = v = _vec_resize (0, l, (uword) l * elt_bytes, header_bytes, - /* align */ align); - - while (l != 0) - { - u32 n = clib_min (SERIALIZE_VECTOR_CHUNK_SIZE, l); - unserialize (m, f, p, n); - l -= n; - p += SERIALIZE_VECTOR_CHUNK_SIZE * elt_bytes; - } - return v; -} - -void -unserialize_aligned_vector (serialize_main_t * m, va_list * va) -{ - void **vec = va_arg (*va, void **); - u32 elt_bytes = va_arg (*va, u32); - serialize_function_t *f = va_arg (*va, serialize_function_t *); - u32 align = va_arg (*va, u32); - - *vec = unserialize_vector_ha (m, elt_bytes, - /* header_bytes */ 0, - /* align */ align, - /* max_length */ ~0, - f); -} - -void -unserialize_vector (serialize_main_t * m, va_list * va) -{ - void **vec = va_arg (*va, void **); - u32 elt_bytes = va_arg (*va, u32); - serialize_function_t *f = va_arg (*va, serialize_function_t *); - - *vec = unserialize_vector_ha (m, elt_bytes, - /* header_bytes */ 0, - /* align */ 0, - /* max_length */ ~0, - f); -} - -void -serialize_bitmap (serialize_main_t * m, uword * b) -{ - u32 l, i, n_u32s; - - l = vec_len (b); - n_u32s = l * sizeof (b[0]) / sizeof (u32); - serialize_integer (m, n_u32s, sizeof (n_u32s)); - - /* Send 32 bit words, low-order word first on 64 bit. */ - for (i = 0; i < l; i++) - { - serialize_integer (m, b[i], sizeof (u32)); - if (BITS (uword) == 64) - serialize_integer (m, (u64) b[i] >> (u64) 32, sizeof (u32)); - } -} - -uword * -unserialize_bitmap (serialize_main_t * m) -{ - uword *b = 0; - u32 i, n_u32s; - - unserialize_integer (m, &n_u32s, sizeof (n_u32s)); - if (n_u32s == 0) - return b; - - i = (n_u32s * sizeof (u32) + sizeof (b[0]) - 1) / sizeof (b[0]); - vec_resize (b, i); - for (i = 0; i < n_u32s; i++) - { - u32 data; - unserialize_integer (m, &data, sizeof (u32)); - - /* Low-word is first on 64 bit. */ - if (BITS (uword) == 64) - { - if ((i % 2) == 0) - b[i / 2] |= (u64) data << (u64) 0; - else - b[i / 2] |= (u64) data << (u64) 32; - } - else - { - b[i] = data; - } - } - - return b; -} - -void -serialize_pool (serialize_main_t * m, va_list * va) -{ - void *pool = va_arg (*va, void *); - u32 elt_bytes = va_arg (*va, u32); - serialize_function_t *f = va_arg (*va, serialize_function_t *); - u32 l, lo, hi; - pool_header_t *p; - - l = vec_len (pool); - serialize_integer (m, l, sizeof (u32)); - if (l == 0) - return; - p = pool_header (pool); - - /* No need to send free bitmap. Need to send index vector - to guarantee that unserialized pool will be identical. */ - vec_serialize (m, p->free_indices, serialize_vec_32); - - pool_foreach_region (lo, hi, pool, - serialize (m, f, pool + lo * elt_bytes, hi - lo)); -} - -static void * -unserialize_pool_helper (serialize_main_t * m, - u32 elt_bytes, u32 align, serialize_function_t * f) -{ - void *v; - u32 i, l, lo, hi; - pool_header_t *p; - - unserialize_integer (m, &l, sizeof (l)); - if (l == 0) - { - return 0; - } - - v = _vec_resize (0, l, (uword) l * elt_bytes, sizeof (p[0]), align); - p = pool_header (v); - - vec_unserialize (m, &p->free_indices, unserialize_vec_32); - - /* Construct free bitmap. */ - p->free_bitmap = 0; - for (i = 0; i < vec_len (p->free_indices); i++) - p->free_bitmap = clib_bitmap_ori (p->free_bitmap, p->free_indices[i]); - - pool_foreach_region (lo, hi, v, - unserialize (m, f, v + lo * elt_bytes, hi - lo)); - - return v; -} - -void -unserialize_pool (serialize_main_t * m, va_list * va) -{ - void **result = va_arg (*va, void **); - u32 elt_bytes = va_arg (*va, u32); - serialize_function_t *f = va_arg (*va, serialize_function_t *); - *result = unserialize_pool_helper (m, elt_bytes, /* align */ 0, f); -} - -void -unserialize_aligned_pool (serialize_main_t * m, va_list * va) -{ - void **result = va_arg (*va, void **); - u32 elt_bytes = va_arg (*va, u32); - u32 align = va_arg (*va, u32); - serialize_function_t *f = va_arg (*va, serialize_function_t *); - *result = unserialize_pool_helper (m, elt_bytes, align, f); -} - -static void -serialize_vec_heap_elt (serialize_main_t * m, va_list * va) -{ - heap_elt_t *e = va_arg (*va, heap_elt_t *); - u32 i, n = va_arg (*va, u32); - for (i = 0; i < n; i++) - { - serialize_integer (m, e[i].offset, sizeof (e[i].offset)); - serialize_integer (m, e[i].next, sizeof (e[i].next)); - serialize_integer (m, e[i].prev, sizeof (e[i].prev)); - } -} - -static void -unserialize_vec_heap_elt (serialize_main_t * m, va_list * va) -{ - heap_elt_t *e = va_arg (*va, heap_elt_t *); - u32 i, n = va_arg (*va, u32); - for (i = 0; i < n; i++) - { - unserialize_integer (m, &e[i].offset, sizeof (e[i].offset)); - unserialize_integer (m, &e[i].next, sizeof (e[i].next)); - unserialize_integer (m, &e[i].prev, sizeof (e[i].prev)); - } -} - -void -serialize_heap (serialize_main_t * m, va_list * va) -{ - void *heap = va_arg (*va, void *); - serialize_function_t *f = va_arg (*va, serialize_function_t *); - u32 i, l; - heap_header_t *h; - - l = vec_len (heap); - serialize_integer (m, l, sizeof (u32)); - if (l == 0) - return; - - h = heap_header (heap); - -#define foreach_serialize_heap_header_integer \ - _ (head) _ (tail) _ (used_count) _ (max_len) _ (flags) _ (elt_bytes) - -#define _(f) serialize_integer (m, h->f, sizeof (h->f)); - foreach_serialize_heap_header_integer; -#undef _ - - serialize_integer (m, vec_len (h->free_lists), sizeof (u32)); - for (i = 0; i < vec_len (h->free_lists); i++) - vec_serialize (m, h->free_lists[i], serialize_vec_32); - - vec_serialize (m, h->elts, serialize_vec_heap_elt); - vec_serialize (m, h->small_free_elt_free_index, serialize_vec_32); - vec_serialize (m, h->free_elts, serialize_vec_32); - - /* Serialize data in heap. */ - { - heap_elt_t *e, *end; - e = h->elts + h->head; - end = h->elts + h->tail; - while (1) - { - if (!heap_is_free (e)) - { - void *v = heap + heap_offset (e) * h->elt_bytes; - u32 n = heap_elt_size (heap, e); - serialize (m, f, v, n); - } - if (e == end) - break; - e = heap_next (e); - } - } -} - -void -unserialize_heap (serialize_main_t * m, va_list * va) -{ - void **result = va_arg (*va, void **); - serialize_function_t *f = va_arg (*va, serialize_function_t *); - u32 i, vl, fl; - heap_header_t h; - void *heap; - - unserialize_integer (m, &vl, sizeof (u32)); - if (vl == 0) - { - *result = 0; - return; - } - - memset (&h, 0, sizeof (h)); -#define _(f) unserialize_integer (m, &h.f, sizeof (h.f)); - foreach_serialize_heap_header_integer; -#undef _ - - unserialize_integer (m, &fl, sizeof (u32)); - vec_resize (h.free_lists, fl); - - for (i = 0; i < vec_len (h.free_lists); i++) - vec_unserialize (m, &h.free_lists[i], unserialize_vec_32); - - vec_unserialize (m, &h.elts, unserialize_vec_heap_elt); - vec_unserialize (m, &h.small_free_elt_free_index, unserialize_vec_32); - vec_unserialize (m, &h.free_elts, unserialize_vec_32); - - /* Re-construct used elt bitmap. */ - if (CLIB_DEBUG > 0) - { - heap_elt_t *e; - vec_foreach (e, h.elts) - { - if (!heap_is_free (e)) - h.used_elt_bitmap = clib_bitmap_ori (h.used_elt_bitmap, e - h.elts); - } - } - - heap = *result = _heap_new (vl, h.elt_bytes); - heap_header (heap)[0] = h; - - /* Unserialize data in heap. */ - { - heap_elt_t *e, *end; - e = h.elts + h.head; - end = h.elts + h.tail; - while (1) - { - if (!heap_is_free (e)) - { - void *v = heap + heap_offset (e) * h.elt_bytes; - u32 n = heap_elt_size (heap, e); - unserialize (m, f, v, n); - } - if (e == end) - break; - e = heap_next (e); - } - } -} - -void -serialize_magic (serialize_main_t * m, void *magic, u32 magic_bytes) -{ - void *p; - serialize_integer (m, magic_bytes, sizeof (magic_bytes)); - p = serialize_get (m, magic_bytes); - clib_memcpy (p, magic, magic_bytes); -} - -void -unserialize_check_magic (serialize_main_t * m, void *magic, u32 magic_bytes) -{ - u32 l; - void *d; - - unserialize_integer (m, &l, sizeof (l)); - if (l != magic_bytes) - { - bad: - serialize_error_return (m, "bad magic number"); - } - d = serialize_get (m, magic_bytes); - if (memcmp (magic, d, magic_bytes)) - goto bad; -} - -clib_error_t * -va_serialize (serialize_main_t * sm, va_list * va) -{ - serialize_main_header_t *m = &sm->header; - serialize_function_t *f = va_arg (*va, serialize_function_t *); - clib_error_t *error = 0; - - m->recursion_level += 1; - if (m->recursion_level == 1) - { - uword r = clib_setjmp (&m->error_longjmp, 0); - error = uword_to_pointer (r, clib_error_t *); - } - - if (!error) - f (sm, va); - - m->recursion_level -= 1; - return error; -} - -clib_error_t * -serialize (serialize_main_t * m, ...) -{ - clib_error_t *error; - va_list va; - - va_start (va, m); - error = va_serialize (m, &va); - va_end (va); - return error; -} - -clib_error_t * -unserialize (serialize_main_t * m, ...) -{ - clib_error_t *error; - va_list va; - - va_start (va, m); - error = va_serialize (m, &va); - va_end (va); - return error; -} - -static void * -serialize_write_not_inline (serialize_main_header_t * m, - serialize_stream_t * s, - uword n_bytes_to_write, uword flags) -{ - uword cur_bi, n_left_b, n_left_o; - - ASSERT (s->current_buffer_index <= s->n_buffer_bytes); - cur_bi = s->current_buffer_index; - n_left_b = s->n_buffer_bytes - cur_bi; - n_left_o = vec_len (s->overflow_buffer); - - /* Prepend overflow buffer if present. */ - do - { - if (n_left_o > 0 && n_left_b > 0) - { - uword n = clib_min (n_left_b, n_left_o); - clib_memcpy (s->buffer + cur_bi, s->overflow_buffer, n); - cur_bi += n; - n_left_b -= n; - n_left_o -= n; - if (n_left_o == 0) - _vec_len (s->overflow_buffer) = 0; - else - vec_delete (s->overflow_buffer, n, 0); - } - - /* Call data function when buffer is complete. Data function should - dispatch with current buffer and give us a new one to write more - data into. */ - if (n_left_b == 0) - { - s->current_buffer_index = cur_bi; - m->data_function (m, s); - cur_bi = s->current_buffer_index; - n_left_b = s->n_buffer_bytes - cur_bi; - } - } - while (n_left_o > 0); - - if (n_left_o > 0 || n_left_b < n_bytes_to_write) - { - u8 *r; - vec_add2 (s->overflow_buffer, r, n_bytes_to_write); - return r; - } - else - { - s->current_buffer_index = cur_bi + n_bytes_to_write; - return s->buffer + cur_bi; - } -} - -static void * -serialize_read_not_inline (serialize_main_header_t * m, - serialize_stream_t * s, - uword n_bytes_to_read, uword flags) -{ - uword cur_bi, cur_oi, n_left_b, n_left_o, n_left_to_read; - - ASSERT (s->current_buffer_index <= s->n_buffer_bytes); - - cur_bi = s->current_buffer_index; - cur_oi = s->current_overflow_index; - - n_left_b = s->n_buffer_bytes - cur_bi; - n_left_o = vec_len (s->overflow_buffer) - cur_oi; - - /* Read from overflow? */ - if (n_left_o >= n_bytes_to_read) - { - s->current_overflow_index = cur_oi + n_bytes_to_read; - return vec_elt_at_index (s->overflow_buffer, cur_oi); - } - - /* Reset overflow buffer. */ - if (n_left_o == 0 && s->overflow_buffer) - { - s->current_overflow_index = 0; - _vec_len (s->overflow_buffer) = 0; - } - - n_left_to_read = n_bytes_to_read; - while (n_left_to_read > 0) - { - uword n; - - /* If we don't have enough data between overflow and normal buffer - call read function. */ - if (n_left_o + n_left_b < n_bytes_to_read) - { - /* Save any left over buffer in overflow vector. */ - if (n_left_b > 0) - { - vec_add (s->overflow_buffer, s->buffer + cur_bi, n_left_b); - n_left_o += n_left_b; - n_left_to_read -= n_left_b; - /* Advance buffer to end --- even if - SERIALIZE_FLAG_NO_ADVANCE_CURRENT_BUFFER_INDEX is set. */ - cur_bi = s->n_buffer_bytes; - n_left_b = 0; - } - - if (m->data_function) - { - m->data_function (m, s); - cur_bi = s->current_buffer_index; - n_left_b = s->n_buffer_bytes - cur_bi; - } - } - - /* For first time through loop return if we have enough data - in normal buffer and overflow vector is empty. */ - if (n_left_o == 0 - && n_left_to_read == n_bytes_to_read && n_left_b >= n_left_to_read) - { - s->current_buffer_index = cur_bi + n_bytes_to_read; - return s->buffer + cur_bi; - } - - if (!m->data_function || serialize_stream_is_end_of_stream (s)) - { - /* This can happen for a peek at end of file. - Pad overflow buffer with 0s. */ - vec_resize (s->overflow_buffer, n_left_to_read); - n_left_o += n_left_to_read; - n_left_to_read = 0; - } - else - { - /* Copy from buffer to overflow vector. */ - n = clib_min (n_left_to_read, n_left_b); - vec_add (s->overflow_buffer, s->buffer + cur_bi, n); - cur_bi += n; - n_left_b -= n; - n_left_o += n; - n_left_to_read -= n; - } - } - - s->current_buffer_index = cur_bi; - s->current_overflow_index = cur_oi + n_bytes_to_read; - return vec_elt_at_index (s->overflow_buffer, cur_oi); -} - -void * -serialize_read_write_not_inline (serialize_main_header_t * m, - serialize_stream_t * s, - uword n_bytes, uword flags) -{ - return (((flags & SERIALIZE_FLAG_IS_READ) ? serialize_read_not_inline : - serialize_write_not_inline) (m, s, n_bytes, flags)); -} - -static void -serialize_read_write_close (serialize_main_header_t * m, - serialize_stream_t * s, uword flags) -{ - if (serialize_stream_is_end_of_stream (s)) - return; - - if (flags & SERIALIZE_FLAG_IS_WRITE) - /* "Write" 0 bytes to flush overflow vector. */ - serialize_write_not_inline (m, s, /* n bytes */ 0, flags); - - serialize_stream_set_end_of_stream (s); - - /* Call it one last time to flush buffer and close. */ - m->data_function (m, s); - - vec_free (s->overflow_buffer); -} - -void -serialize_close (serialize_main_t * m) -{ - serialize_read_write_close (&m->header, &m->stream, - SERIALIZE_FLAG_IS_WRITE); -} - -void -unserialize_close (serialize_main_t * m) -{ - serialize_read_write_close (&m->header, &m->stream, SERIALIZE_FLAG_IS_READ); -} - -void -serialize_open_data (serialize_main_t * m, u8 * data, uword n_data_bytes) -{ - memset (m, 0, sizeof (m[0])); - m->stream.buffer = data; - m->stream.n_buffer_bytes = n_data_bytes; -} - -void -unserialize_open_data (serialize_main_t * m, u8 * data, uword n_data_bytes) -{ - serialize_open_data (m, data, n_data_bytes); -} - -static void -serialize_vector_write (serialize_main_header_t * m, serialize_stream_t * s) -{ - if (!serialize_stream_is_end_of_stream (s)) - { - /* Double buffer size. */ - uword l = vec_len (s->buffer); - vec_resize (s->buffer, l > 0 ? l : 64); - s->n_buffer_bytes = vec_len (s->buffer); - } -} - -void -serialize_open_vector (serialize_main_t * m, u8 * vector) -{ - memset (m, 0, sizeof (m[0])); - m->header.data_function = serialize_vector_write; - m->stream.buffer = vector; - m->stream.current_buffer_index = 0; - m->stream.n_buffer_bytes = vec_len (vector); -} - -void * -serialize_close_vector (serialize_main_t * m) -{ - serialize_stream_t *s = &m->stream; - void *result; - - serialize_close (m); /* frees overflow buffer */ - - if (s->buffer) - _vec_len (s->buffer) = s->current_buffer_index; - result = s->buffer; - memset (m, 0, sizeof (m[0])); - return result; -} - -void -serialize_multiple_1 (serialize_main_t * m, - void *data, uword data_stride, uword n_data) -{ - u8 *d = data; - u8 *p; - uword n_left = n_data; - - while (n_left >= 4) - { - p = serialize_get (m, 4 * sizeof (d[0])); - p[0] = d[0 * data_stride]; - p[1] = d[1 * data_stride]; - p[2] = d[2 * data_stride]; - p[3] = d[3 * data_stride]; - n_left -= 4; - d += 4 * data_stride; - } - - if (n_left > 0) - { - p = serialize_get (m, n_left * sizeof (p[0])); - while (n_left > 0) - { - p[0] = d[0]; - p += 1; - d += 1 * data_stride; - n_left -= 1; - } - } -} - -void -serialize_multiple_2 (serialize_main_t * m, - void *data, uword data_stride, uword n_data) -{ - void *d = data; - u16 *p; - uword n_left = n_data; - - while (n_left >= 4) - { - p = serialize_get (m, 4 * sizeof (p[0])); - clib_mem_unaligned (p + 0, u16) = - clib_host_to_net_mem_u16 (d + 0 * data_stride); - clib_mem_unaligned (p + 1, u16) = - clib_host_to_net_mem_u16 (d + 1 * data_stride); - clib_mem_unaligned (p + 2, u16) = - clib_host_to_net_mem_u16 (d + 2 * data_stride); - clib_mem_unaligned (p + 3, u16) = - clib_host_to_net_mem_u16 (d + 3 * data_stride); - n_left -= 4; - d += 4 * data_stride; - } - - if (n_left > 0) - { - p = serialize_get (m, n_left * sizeof (p[0])); - while (n_left > 0) - { - clib_mem_unaligned (p + 0, u16) = - clib_host_to_net_mem_u16 (d + 0 * data_stride); - p += 1; - d += 1 * data_stride; - n_left -= 1; - } - } -} - -void -serialize_multiple_4 (serialize_main_t * m, - void *data, uword data_stride, uword n_data) -{ - void *d = data; - u32 *p; - uword n_left = n_data; - - while (n_left >= 4) - { - p = serialize_get (m, 4 * sizeof (p[0])); - clib_mem_unaligned (p + 0, u32) = - clib_host_to_net_mem_u32 (d + 0 * data_stride); - clib_mem_unaligned (p + 1, u32) = - clib_host_to_net_mem_u32 (d + 1 * data_stride); - clib_mem_unaligned (p + 2, u32) = - clib_host_to_net_mem_u32 (d + 2 * data_stride); - clib_mem_unaligned (p + 3, u32) = - clib_host_to_net_mem_u32 (d + 3 * data_stride); - n_left -= 4; - d += 4 * data_stride; - } - - if (n_left > 0) - { - p = serialize_get (m, n_left * sizeof (p[0])); - while (n_left > 0) - { - clib_mem_unaligned (p + 0, u32) = - clib_host_to_net_mem_u32 (d + 0 * data_stride); - p += 1; - d += 1 * data_stride; - n_left -= 1; - } - } -} - -void -unserialize_multiple_1 (serialize_main_t * m, - void *data, uword data_stride, uword n_data) -{ - u8 *d = data; - u8 *p; - uword n_left = n_data; - - while (n_left >= 4) - { - p = unserialize_get (m, 4 * sizeof (d[0])); - d[0 * data_stride] = p[0]; - d[1 * data_stride] = p[1]; - d[2 * data_stride] = p[2]; - d[3 * data_stride] = p[3]; - n_left -= 4; - d += 4 * data_stride; - } - - if (n_left > 0) - { - p = unserialize_get (m, n_left * sizeof (p[0])); - while (n_left > 0) - { - d[0] = p[0]; - p += 1; - d += 1 * data_stride; - n_left -= 1; - } - } -} - -void -unserialize_multiple_2 (serialize_main_t * m, - void *data, uword data_stride, uword n_data) -{ - void *d = data; - u16 *p; - uword n_left = n_data; - - while (n_left >= 4) - { - p = unserialize_get (m, 4 * sizeof (p[0])); - clib_mem_unaligned (d + 0 * data_stride, u16) = - clib_net_to_host_mem_u16 (p + 0); - clib_mem_unaligned (d + 1 * data_stride, u16) = - clib_net_to_host_mem_u16 (p + 1); - clib_mem_unaligned (d + 2 * data_stride, u16) = - clib_net_to_host_mem_u16 (p + 2); - clib_mem_unaligned (d + 3 * data_stride, u16) = - clib_net_to_host_mem_u16 (p + 3); - n_left -= 4; - d += 4 * data_stride; - } - - if (n_left > 0) - { - p = unserialize_get (m, n_left * sizeof (p[0])); - while (n_left > 0) - { - clib_mem_unaligned (d + 0 * data_stride, u16) = - clib_net_to_host_mem_u16 (p + 0); - p += 1; - d += 1 * data_stride; - n_left -= 1; - } - } -} - -void -unserialize_multiple_4 (serialize_main_t * m, - void *data, uword data_stride, uword n_data) -{ - void *d = data; - u32 *p; - uword n_left = n_data; - - while (n_left >= 4) - { - p = unserialize_get (m, 4 * sizeof (p[0])); - clib_mem_unaligned (d + 0 * data_stride, u32) = - clib_net_to_host_mem_u32 (p + 0); - clib_mem_unaligned (d + 1 * data_stride, u32) = - clib_net_to_host_mem_u32 (p + 1); - clib_mem_unaligned (d + 2 * data_stride, u32) = - clib_net_to_host_mem_u32 (p + 2); - clib_mem_unaligned (d + 3 * data_stride, u32) = - clib_net_to_host_mem_u32 (p + 3); - n_left -= 4; - d += 4 * data_stride; - } - - if (n_left > 0) - { - p = unserialize_get (m, n_left * sizeof (p[0])); - while (n_left > 0) - { - clib_mem_unaligned (d + 0 * data_stride, u32) = - clib_net_to_host_mem_u32 (p + 0); - p += 1; - d += 1 * data_stride; - n_left -= 1; - } - } -} - -#ifdef CLIB_UNIX - -#include <unistd.h> -#include <fcntl.h> - -static void -unix_file_write (serialize_main_header_t * m, serialize_stream_t * s) -{ - int fd, n; - - fd = s->data_function_opaque; - n = write (fd, s->buffer, s->current_buffer_index); - if (n < 0) - { - if (!unix_error_is_fatal (errno)) - n = 0; - else - serialize_error (m, clib_error_return_unix (0, "write")); - } - if (n == s->current_buffer_index) - _vec_len (s->buffer) = 0; - else - vec_delete (s->buffer, n, 0); - s->current_buffer_index = vec_len (s->buffer); -} - -static void -unix_file_read (serialize_main_header_t * m, serialize_stream_t * s) -{ - int fd, n; - - fd = s->data_function_opaque; - n = read (fd, s->buffer, vec_len (s->buffer)); - if (n < 0) - { - if (!unix_error_is_fatal (errno)) - n = 0; - else - serialize_error (m, clib_error_return_unix (0, "read")); - } - else if (n == 0) - serialize_stream_set_end_of_stream (s); - s->current_buffer_index = 0; - s->n_buffer_bytes = n; -} - -static void -serialize_open_unix_file_descriptor_helper (serialize_main_t * m, int fd, - uword is_read) -{ - memset (m, 0, sizeof (m[0])); - vec_resize (m->stream.buffer, 4096); - - if (!is_read) - { - m->stream.n_buffer_bytes = vec_len (m->stream.buffer); - _vec_len (m->stream.buffer) = 0; - } - - m->header.data_function = is_read ? unix_file_read : unix_file_write; - m->stream.data_function_opaque = fd; -} - -void -serialize_open_unix_file_descriptor (serialize_main_t * m, int fd) -{ - serialize_open_unix_file_descriptor_helper (m, fd, /* is_read */ 0); -} - -void -unserialize_open_unix_file_descriptor (serialize_main_t * m, int fd) -{ - serialize_open_unix_file_descriptor_helper (m, fd, /* is_read */ 1); -} - -static clib_error_t * -serialize_open_unix_file_helper (serialize_main_t * m, char *file, - uword is_read) -{ - int fd, mode; - - mode = is_read ? O_RDONLY : O_RDWR | O_CREAT | O_TRUNC; - fd = open (file, mode, 0666); - if (fd < 0) - return clib_error_return_unix (0, "open `%s'", file); - - serialize_open_unix_file_descriptor_helper (m, fd, is_read); - return 0; -} - -clib_error_t * -serialize_open_unix_file (serialize_main_t * m, char *file) -{ - return serialize_open_unix_file_helper (m, file, /* is_read */ 0); -} - -clib_error_t * -unserialize_open_unix_file (serialize_main_t * m, char *file) -{ - return serialize_open_unix_file_helper (m, file, /* is_read */ 1); -} - -#endif /* CLIB_UNIX */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/serialize.h b/vppinfra/vppinfra/serialize.h deleted file mode 100644 index 6cc2372e6ab..00000000000 --- a/vppinfra/vppinfra/serialize.h +++ /dev/null @@ -1,443 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2005 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_clib_serialize_h -#define included_clib_serialize_h - -#include <stdarg.h> -#include <vppinfra/byte_order.h> -#include <vppinfra/types.h> -#include <vppinfra/vec.h> -#include <vppinfra/longjmp.h> - -struct serialize_main_header_t; -struct serialize_stream_t; - -typedef void (serialize_data_function_t) (struct serialize_main_header_t * h, - struct serialize_stream_t * s); - -typedef struct serialize_stream_t -{ - /* Current data buffer being serialized/unserialized. */ - u8 *buffer; - - /* Size of buffer in bytes. */ - u32 n_buffer_bytes; - - /* Current index into buffer. */ - u32 current_buffer_index; - - /* Overflow buffer for when there is not enough room at the end of - buffer to hold serialized/unserialized data. */ - u8 *overflow_buffer; - - /* Current index in overflow buffer for reads. */ - u32 current_overflow_index; - - u32 flags; -#define SERIALIZE_END_OF_STREAM (1 << 0) - - uword data_function_opaque; - - u32 opaque[64 - 4 * sizeof (u32) - 1 * sizeof (uword) - - 2 * sizeof (void *)]; -} serialize_stream_t; - -always_inline void -serialize_stream_set_end_of_stream (serialize_stream_t * s) -{ - s->flags |= SERIALIZE_END_OF_STREAM; -} - -always_inline uword -serialize_stream_is_end_of_stream (serialize_stream_t * s) -{ - return (s->flags & SERIALIZE_END_OF_STREAM) != 0; -} - -typedef struct serialize_main_header_t -{ - u32 recursion_level; - - /* Data callback function and opaque data. */ - serialize_data_function_t *data_function; - - /* Error if signaled by data function. */ - clib_error_t *error; - - /* Exit unwind point if error occurs. */ - clib_longjmp_t error_longjmp; -} serialize_main_header_t; - -always_inline void -serialize_error (serialize_main_header_t * m, clib_error_t * error) -{ - clib_longjmp (&m->error_longjmp, pointer_to_uword (error)); -} - -#define serialize_error_return(m,args...) \ - serialize_error (&(m)->header, clib_error_return (0, args)) - -void *serialize_read_write_not_inline (serialize_main_header_t * m, - serialize_stream_t * s, - uword n_bytes, uword flags); - -#define SERIALIZE_FLAG_IS_READ (1 << 0) -#define SERIALIZE_FLAG_IS_WRITE (1 << 1) - -always_inline void * -serialize_stream_read_write (serialize_main_header_t * header, - serialize_stream_t * s, - uword n_bytes, uword flags) -{ - uword i, j, l; - - l = vec_len (s->overflow_buffer); - i = s->current_buffer_index; - j = i + n_bytes; - s->current_buffer_index = j; - if (l == 0 && j <= s->n_buffer_bytes) - { - return s->buffer + i; - } - else - { - s->current_buffer_index = i; - return serialize_read_write_not_inline (header, s, n_bytes, flags); - } -} - -typedef struct -{ - serialize_main_header_t header; - serialize_stream_t stream; -} serialize_main_t; - -always_inline void -serialize_set_end_of_stream (serialize_main_t * m) -{ - serialize_stream_set_end_of_stream (&m->stream); -} - -always_inline uword -serialize_is_end_of_stream (serialize_main_t * m) -{ - return serialize_stream_is_end_of_stream (&m->stream); -} - -typedef struct -{ - serialize_main_header_t header; - serialize_stream_t *streams; -} serialize_multiple_main_t; - -typedef void (serialize_function_t) (serialize_main_t * m, va_list * va); - -always_inline void * -unserialize_get (serialize_main_t * m, uword n_bytes) -{ - return serialize_stream_read_write (&m->header, &m->stream, n_bytes, - SERIALIZE_FLAG_IS_READ); -} - -always_inline void * -serialize_get (serialize_main_t * m, uword n_bytes) -{ - return serialize_stream_read_write (&m->header, &m->stream, n_bytes, - SERIALIZE_FLAG_IS_WRITE); -} - -always_inline void -serialize_integer (serialize_main_t * m, u64 x, u32 n_bytes) -{ - u8 *p = serialize_get (m, n_bytes); - if (n_bytes == 1) - p[0] = x; - else if (n_bytes == 2) - clib_mem_unaligned (p, u16) = clib_host_to_net_u16 (x); - else if (n_bytes == 4) - clib_mem_unaligned (p, u32) = clib_host_to_net_u32 (x); - else if (n_bytes == 8) - clib_mem_unaligned (p, u64) = clib_host_to_net_u64 (x); - else - ASSERT (0); -} - -always_inline void -unserialize_integer (serialize_main_t * m, void *x, u32 n_bytes) -{ - u8 *p = unserialize_get (m, n_bytes); - if (n_bytes == 1) - *(u8 *) x = p[0]; - else if (n_bytes == 2) - *(u16 *) x = clib_net_to_host_unaligned_mem_u16 ((u16 *) p); - else if (n_bytes == 4) - *(u32 *) x = clib_net_to_host_unaligned_mem_u32 ((u32 *) p); - else if (n_bytes == 8) - *(u64 *) x = clib_net_to_host_unaligned_mem_u64 ((u64 *) p); - else - ASSERT (0); -} - -/* As above but tries to be more compact. */ -always_inline void -serialize_likely_small_unsigned_integer (serialize_main_t * m, u64 x) -{ - u64 r = x; - u8 *p; - - /* Low bit set means it fits into 1 byte. */ - if (r < (1 << 7)) - { - p = serialize_get (m, 1); - p[0] = 1 + 2 * r; - return; - } - - /* Low 2 bits 1 0 means it fits into 2 bytes. */ - r -= (1 << 7); - if (r < (1 << 14)) - { - p = serialize_get (m, 2); - clib_mem_unaligned (p, u16) = clib_host_to_little_u16 (4 * r + 2); - return; - } - - r -= (1 << 14); - if (r < (1 << 29)) - { - p = serialize_get (m, 4); - clib_mem_unaligned (p, u32) = clib_host_to_little_u32 (8 * r + 4); - return; - } - - p = serialize_get (m, 9); - p[0] = 0; /* Only low 3 bits are used. */ - clib_mem_unaligned (p + 1, u64) = clib_host_to_little_u64 (x); -} - -always_inline u64 -unserialize_likely_small_unsigned_integer (serialize_main_t * m) -{ - u8 *p = unserialize_get (m, 1); - u64 r; - u32 y = p[0]; - - if (y & 1) - return y / 2; - - r = 1 << 7; - if (y & 2) - { - p = unserialize_get (m, 1); - r += (y / 4) + (p[0] << 6); - return r; - } - - r += 1 << 14; - if (y & 4) - { - p = unserialize_get (m, 3); - r += ((y / 8) - + (p[0] << (5 + 8 * 0)) - + (p[1] << (5 + 8 * 1)) + (p[2] << (5 + 8 * 2))); - return r; - } - - p = unserialize_get (m, 8); - r = clib_mem_unaligned (p, u64); - r = clib_little_to_host_u64 (r); - - return r; -} - -always_inline void -serialize_likely_small_signed_integer (serialize_main_t * m, i64 s) -{ - u64 u = s < 0 ? -(2 * s + 1) : 2 * s; - serialize_likely_small_unsigned_integer (m, u); -} - -always_inline i64 -unserialize_likely_small_signed_integer (serialize_main_t * m) -{ - u64 u = unserialize_likely_small_unsigned_integer (m); - i64 s = u / 2; - return (u & 1) ? -s : s; -} - -void -serialize_multiple_1 (serialize_main_t * m, - void *data, uword data_stride, uword n_data); -void -serialize_multiple_2 (serialize_main_t * m, - void *data, uword data_stride, uword n_data); -void -serialize_multiple_4 (serialize_main_t * m, - void *data, uword data_stride, uword n_data); - -void -unserialize_multiple_1 (serialize_main_t * m, - void *data, uword data_stride, uword n_data); -void -unserialize_multiple_2 (serialize_main_t * m, - void *data, uword data_stride, uword n_data); -void -unserialize_multiple_4 (serialize_main_t * m, - void *data, uword data_stride, uword n_data); - -always_inline void -serialize_multiple (serialize_main_t * m, - void *data, - uword n_data_bytes, uword data_stride, uword n_data) -{ - if (n_data_bytes == 1) - serialize_multiple_1 (m, data, data_stride, n_data); - else if (n_data_bytes == 2) - serialize_multiple_2 (m, data, data_stride, n_data); - else if (n_data_bytes == 4) - serialize_multiple_4 (m, data, data_stride, n_data); - else - ASSERT (0); -} - -always_inline void -unserialize_multiple (serialize_main_t * m, - void *data, - uword n_data_bytes, uword data_stride, uword n_data) -{ - if (n_data_bytes == 1) - unserialize_multiple_1 (m, data, data_stride, n_data); - else if (n_data_bytes == 2) - unserialize_multiple_2 (m, data, data_stride, n_data); - else if (n_data_bytes == 4) - unserialize_multiple_4 (m, data, data_stride, n_data); - else - ASSERT (0); -} - -/* Basic types. */ -serialize_function_t serialize_64, unserialize_64; -serialize_function_t serialize_32, unserialize_32; -serialize_function_t serialize_16, unserialize_16; -serialize_function_t serialize_8, unserialize_8; -serialize_function_t serialize_f64, unserialize_f64; -serialize_function_t serialize_f32, unserialize_f32; - -/* Basic vector types. */ -serialize_function_t serialize_vec_8, unserialize_vec_8; -serialize_function_t serialize_vec_16, unserialize_vec_16; -serialize_function_t serialize_vec_32, unserialize_vec_32; -serialize_function_t serialize_vec_64, unserialize_vec_64; - -/* Serialize generic vectors. */ -serialize_function_t serialize_vector, unserialize_vector, - unserialize_aligned_vector; - -#define vec_serialize(m,v,f) \ - serialize ((m), serialize_vector, (v), sizeof ((v)[0]), (f)) - -#define vec_unserialize(m,v,f) \ - unserialize ((m), unserialize_vector, (v), sizeof ((*(v))[0]), (f)) - -#define vec_unserialize_aligned(m,v,f) \ - unserialize ((m), unserialize_aligned_vector, (v), sizeof ((*(v))[0]), (f)) - -/* Serialize pools. */ -serialize_function_t serialize_pool, unserialize_pool, - unserialize_aligned_pool; - -#define pool_serialize(m,v,f) \ - serialize ((m), serialize_pool, (v), sizeof ((v)[0]), (f)) - -#define pool_unserialize(m,v,f) \ - unserialize ((m), unserialize_pool, (v), sizeof ((*(v))[0]), (f)) - -#define pool_unserialize_aligned(m,v,a,f) \ - unserialize ((m), unserialize_aligned_pool, (v), sizeof ((*(v))[0]), (a), (f)) - -/* Serialize heaps. */ -serialize_function_t serialize_heap, unserialize_heap; - -void serialize_bitmap (serialize_main_t * m, uword * b); -uword *unserialize_bitmap (serialize_main_t * m); - -void serialize_cstring (serialize_main_t * m, char *string); -void unserialize_cstring (serialize_main_t * m, char **string); - -void serialize_close (serialize_main_t * m); -void unserialize_close (serialize_main_t * m); - -void serialize_open_data (serialize_main_t * m, u8 * data, - uword n_data_bytes); -void unserialize_open_data (serialize_main_t * m, u8 * data, - uword n_data_bytes); - -/* Starts serialization with expanding vector as buffer. */ -void serialize_open_vector (serialize_main_t * m, u8 * vector); - -/* Serialization is done: returns vector buffer to caller. */ -void *serialize_close_vector (serialize_main_t * m); - -void unserialize_open_vector (serialize_main_t * m, u8 * vector); - -#ifdef CLIB_UNIX -clib_error_t *serialize_open_unix_file (serialize_main_t * m, char *file); -clib_error_t *unserialize_open_unix_file (serialize_main_t * m, char *file); - -void serialize_open_unix_file_descriptor (serialize_main_t * m, int fd); -void unserialize_open_unix_file_descriptor (serialize_main_t * m, int fd); -#endif /* CLIB_UNIX */ - -/* Main routines. */ -clib_error_t *serialize (serialize_main_t * m, ...); -clib_error_t *unserialize (serialize_main_t * m, ...); -clib_error_t *va_serialize (serialize_main_t * m, va_list * va); - -void serialize_magic (serialize_main_t * m, void *magic, u32 magic_bytes); -void unserialize_check_magic (serialize_main_t * m, void *magic, - u32 magic_bytes); - -#endif /* included_clib_serialize_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/slist.c b/vppinfra/vppinfra/slist.c deleted file mode 100644 index 892517bbb79..00000000000 --- a/vppinfra/vppinfra/slist.c +++ /dev/null @@ -1,336 +0,0 @@ -/* - Copyright (c) 2012 Cisco and/or its affiliates. - - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. -*/ - -#include <vppinfra/slist.h> - -/* - * skip-list implementation - * - * Good news / bad news. As balanced binary tree schemes go, - * this one seems pretty fast and is reasonably simple. There's a very - * limited amount that can be done to mitigate sdram read latency. - * - * Each active clib_slist_elt_t is on from 1 to N lists. Each active element - * is always on the "level-0" list. Since most elements are *only* on - * level 0, we keep the level 0 (and level 1) in the element. For those - * elements on more than two lists, we switch to a vector. Hence, the - * "n" union in slib_slist_elt_t. - * - * The low-order bit of elt->n.next0[0] is 1 for inlined next indices, - * 0 for vector indices (since the allocator always aligns to at least - * a 4-byte boundary). We can only represent 2e9 items, but since the - * practical performance limit is O(1e7), it doesn't matter. - * - * We create a "head" element which (by construction) is always - * lexically lighter than any other element. This makes a large number - * of irritating special cases go away. - * - * User code is in charge of comparing a supplied key with - * the key component of a user pool element. The user tells this code - * to add or delete (opaque key, 32-bit integer) pairs to the skip-list. - * - * The algorithm adds new elements to one or more lists. - * For levels greater than zero, the probability of a new element landing on - * a list is branching_factor**N. Branching_factor = 0.2 seems to work - * OK, yielding about 50 compares per search at O(1e7) items. - */ - -clib_error_t * -clib_slist_init (clib_slist_t * sp, f64 branching_factor, - clib_slist_key_compare_function_t compare, - format_function_t format_user_element) -{ - clib_slist_elt_t *head; - memset (sp, 0, sizeof (sp[0])); - sp->branching_factor = branching_factor; - sp->format_user_element = format_user_element; - sp->compare = compare; - sp->seed = 0xdeaddabe; - pool_get (sp->elts, head); - vec_add1 (head->n.nexts, (u32) ~ 0); - head->user_pool_index = (u32) ~ 0; - vec_validate (sp->path, 1); - vec_validate (sp->occupancy, 0); - - return 0; -} - -/* - * slist_search_internal - */ -static inline clib_slist_search_result_t -slist_search_internal (clib_slist_t * sp, void *key, int need_full_path) -{ - int level, comp_result; - clib_slist_elt_t *search_elt, *head_elt; - - sp->ncompares = 0; - /* - * index 0 is the magic listhead element which is - * lexically lighter than / to the left of every element - */ - search_elt = head_elt = pool_elt_at_index (sp->elts, 0); - - /* - * Initial negotiating position, only the head_elt is - * lighter than the supplied key - */ - memset (sp->path, 0, vec_len (head_elt->n.nexts) * sizeof (u32)); - - /* Walk the fastest lane first */ - level = vec_len (head_elt->n.nexts) - 1; - _vec_len (sp->path) = level + 1; - - while (1) - { - u32 next_index_this_level; - clib_slist_elt_t *prefetch_elt; - - /* - * Prefetching the next element at this level makes a measurable - * difference, but doesn't fix the dependent read stall problem - */ - prefetch_elt = sp->elts + - clib_slist_get_next_at_level (search_elt, level); - - CLIB_PREFETCH (prefetch_elt, CLIB_CACHE_LINE_BYTES, READ); - - /* Compare the key with the current element */ - comp_result = (search_elt == head_elt) ? 1 : - sp->compare (key, search_elt->user_pool_index); - - sp->ncompares++; - /* key "lighter" than this element */ - if (comp_result < 0) - { - /* - * Back up to previous item on this list - * and search the next finer-grained list - * starting there. - */ - search_elt = pool_elt_at_index (sp->elts, sp->path[level]); - next_list: - if (level > 0) - { - level--; - continue; - } - else - { - return CLIB_SLIST_NO_MATCH; - } - } - /* Match */ - if (comp_result == 0) - { - /* - * If we're trying to delete an element, we need to - * track down all of the elements which point at it. - * Otherwise, don't bother with it - */ - if (need_full_path && level > 0) - { - search_elt = pool_elt_at_index (sp->elts, sp->path[level]); - level--; - continue; - } - level = vec_len (head_elt->n.nexts); - sp->path[level] = search_elt - sp->elts; - _vec_len (sp->path) = level + 1; - return CLIB_SLIST_MATCH; - } - /* - * comp_result positive, key is to the right of - * this element - */ - sp->path[level] = search_elt - sp->elts; - - /* Out of list at this level? */ - next_index_this_level = - clib_slist_get_next_at_level (search_elt, level); - if (next_index_this_level == (u32) ~ 0) - goto next_list; - - /* No, try the next element */ - search_elt = pool_elt_at_index (sp->elts, next_index_this_level); - } - return 0; /* notreached */ -} - -u32 -clib_slist_search (clib_slist_t * sp, void *key, u32 * ncompares) -{ - clib_slist_search_result_t rv; - - rv = slist_search_internal (sp, key, 0 /* dont need full path */ ); - if (rv == CLIB_SLIST_MATCH) - { - clib_slist_elt_t *elt; - elt = pool_elt_at_index (sp->elts, sp->path[vec_len (sp->path) - 1]); - if (ncompares) - *ncompares = sp->ncompares; - return elt->user_pool_index; - } - return (u32) ~ 0; -} - -void -clib_slist_add (clib_slist_t * sp, void *key, u32 user_pool_index) -{ - clib_slist_elt_t *new_elt; - clib_slist_search_result_t search_result; - int level; - - search_result = slist_search_internal (sp, key, - 0 /* don't need full path */ ); - - /* Special case: key exists, just replace user_pool_index */ - if (PREDICT_FALSE (search_result == CLIB_SLIST_MATCH)) - { - clib_slist_elt_t *elt; - elt = pool_elt_at_index (sp->elts, sp->path[0]); - elt->user_pool_index = user_pool_index; - return; - } - - pool_get (sp->elts, new_elt); - new_elt->n.nexts = 0; - new_elt->user_pool_index = user_pool_index; - - /* sp->path lists elements to the left of key, by level */ - for (level = 0; level < vec_len (sp->path); level++) - { - clib_slist_elt_t *prev_elt_this_level; - u32 prev_elt_next_index_this_level; - - /* Add to list at the current level */ - prev_elt_this_level = pool_elt_at_index (sp->elts, sp->path[level]); - prev_elt_next_index_this_level = clib_slist_get_next_at_level - (prev_elt_this_level, level); - - clib_slist_set_next_at_level (new_elt, prev_elt_next_index_this_level, - level); - - clib_slist_set_next_at_level (prev_elt_this_level, new_elt - sp->elts, - level); - sp->occupancy[level]++; - - /* Randomly add to the next-higher level */ - if (random_f64 (&sp->seed) > sp->branching_factor) - break; - } - { - /* Time to add a new ply? */ - clib_slist_elt_t *head_elt = pool_elt_at_index (sp->elts, 0); - int top_level = vec_len (head_elt->n.nexts) - 1; - if (((f64) sp->occupancy[top_level]) * sp->branching_factor > 1.0) - { - vec_add1 (sp->occupancy, 0); - vec_add1 (head_elt->n.nexts, (u32) ~ 0); - /* full match case returns n+1 items */ - vec_validate (sp->path, vec_len (head_elt->n.nexts)); - } - } -} - -clib_slist_search_result_t -clib_slist_del (clib_slist_t * sp, void *key) -{ - clib_slist_search_result_t search_result; - clib_slist_elt_t *del_elt; - int level; - - search_result = slist_search_internal (sp, key, 1 /* need full path */ ); - - if (PREDICT_FALSE (search_result == CLIB_SLIST_NO_MATCH)) - return search_result; - - del_elt = pool_elt_at_index (sp->elts, sp->path[vec_len (sp->path) - 1]); - ASSERT (vec_len (sp->path) > 1); - - for (level = 0; level < vec_len (sp->path) - 1; level++) - { - clib_slist_elt_t *path_elt; - u32 path_elt_next_index; - - path_elt = pool_elt_at_index (sp->elts, sp->path[level]); - path_elt_next_index = clib_slist_get_next_at_level (path_elt, level); - - /* Splice the item out of the list if it's adjacent to the victim */ - if (path_elt_next_index == del_elt - sp->elts) - { - sp->occupancy[level]--; - path_elt_next_index = clib_slist_get_next_at_level (del_elt, level); - clib_slist_set_next_at_level (path_elt, path_elt_next_index, level); - } - } - - /* If this element is on more than two lists it has a vector of nexts */ - if (!(del_elt->n.next0[0] & 1)) - vec_free (del_elt->n.nexts); - pool_put (sp->elts, del_elt); - return CLIB_SLIST_MATCH; -} - -u8 * -format_slist (u8 * s, va_list * args) -{ - clib_slist_t *sl = va_arg (*args, clib_slist_t *); - int verbose = va_arg (*args, int); - int i; - clib_slist_elt_t *head_elt, *elt; - - s = format (s, "slist 0x%x, %u items, branching_factor %.2f\n", sl, - sl->occupancy ? sl->occupancy[0] : 0, sl->branching_factor); - - if (pool_elts (sl->elts) == 0) - return s; - - head_elt = pool_elt_at_index (sl->elts, 0); - - for (i = 0; i < vec_len (head_elt->n.nexts); i++) - { - s = format (s, "level %d: %d elts\n", i, - sl->occupancy ? sl->occupancy[i] : 0); - - if (verbose && head_elt->n.nexts[i] != (u32) ~ 0) - { - elt = pool_elt_at_index (sl->elts, head_elt->n.nexts[i]); - while (elt) - { - u32 next_index; - s = format (s, "%U(%d) ", sl->format_user_element, - elt->user_pool_index, elt - sl->elts); - next_index = clib_slist_get_next_at_level (elt, i); - ASSERT (next_index != 0x7fffffff); - if (next_index == (u32) ~ 0) - break; - else - elt = pool_elt_at_index (sl->elts, next_index); - } - } - s = format (s, "\n"); - } - return s; -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/slist.h b/vppinfra/vppinfra/slist.h deleted file mode 100644 index a7c77e27c96..00000000000 --- a/vppinfra/vppinfra/slist.h +++ /dev/null @@ -1,145 +0,0 @@ -/* - Copyright (c) 2012 Cisco and/or its affiliates. - - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. -*/ - -#ifndef included_slist_h -#define included_slist_h - -#include <stdarg.h> -#include <vppinfra/clib.h> -#include <vppinfra/vec.h> -#include <vppinfra/pool.h> -#include <vppinfra/error.h> -#include <vppinfra/format.h> -#include <vppinfra/cache.h> - -typedef word (clib_slist_key_compare_function_t) - (void *key, u32 elt_pool_index); - -typedef enum -{ - CLIB_SLIST_MATCH = 0, - CLIB_SLIST_NO_MATCH -} clib_slist_search_result_t; - -typedef struct -{ - /* Vector of next elements. Every valid instance has at least one */ - union - { - u32 next0[2]; - u32 *nexts; - } n; - - /* Index of item in user's pool */ - u32 user_pool_index; - /* $$$ pad to even divisor of cache line */ -} clib_slist_elt_t; - -static inline u32 -clib_slist_get_next_at_level (clib_slist_elt_t * elt, int level) -{ - if (elt->n.next0[0] & 1) - { - ASSERT (level < 2); - if (level == 1) - return elt->n.next0[1]; - /* preserve ~0 (end of list) */ - return (elt->n.next0[0] == (u32) ~ 0) ? elt->n.next0[0] : - (elt->n.next0[0] >> 1); - } - else - { - ASSERT (level < vec_len (elt->n.nexts)); - return elt->n.nexts[level]; - } -} - -static inline void -clib_slist_set_next_at_level (clib_slist_elt_t * elt, u32 index, int level) -{ - u32 old_level0_value[2]; - /* level0 and not a vector */ - if (level < 2 && (elt->n.next0[0] == 0 || elt->n.next0[0] & 1)) - { - if (level == 0) - { - elt->n.next0[0] = (index << 1) | 1; - return; - } - elt->n.next0[1] = index; - return; - } - /* have to save old level0 values? */ - if (elt->n.next0[0] & 1) - { - old_level0_value[0] = (elt->n.next0[0] == (u32) ~ 0) ? - elt->n.next0[0] : elt->n.next0[0] >> 1; - old_level0_value[1] = elt->n.next0[1]; - elt->n.nexts = 0; - vec_add1 (elt->n.nexts, old_level0_value[0]); - vec_add1 (elt->n.nexts, old_level0_value[1]); - } - vec_validate (elt->n.nexts, level); - elt->n.nexts[level] = index; -} - - -typedef struct -{ - /* pool of skip-list elements */ - clib_slist_elt_t *elts; - - /* last search path */ - u32 *path; - - /* last search number of compares */ - u32 ncompares; - - /* occupancy stats */ - u32 *occupancy; - - /* Comparison function */ - clib_slist_key_compare_function_t *compare; - - /* Format function */ - format_function_t *format_user_element; - - /* items appear in successive plies with Pr (1 / branching_factor) */ - f64 branching_factor; - - /* random seed */ - u32 seed; -} clib_slist_t; - -clib_error_t *clib_slist_init (clib_slist_t * sp, f64 branching_factor, - clib_slist_key_compare_function_t compare, - format_function_t format_user_element); - -format_function_t format_slist; - -void clib_slist_add (clib_slist_t * sp, void *key, u32 user_pool_index); -clib_slist_search_result_t clib_slist_del (clib_slist_t * sp, void *key); -u32 clib_slist_search (clib_slist_t * sp, void *key, u32 * ncompares); - -#endif /* included_slist_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/smp.c b/vppinfra/vppinfra/smp.c deleted file mode 100644 index 8ac19960982..00000000000 --- a/vppinfra/vppinfra/smp.c +++ /dev/null @@ -1,325 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include <vppinfra/longjmp.h> -#include <vppinfra/mheap.h> -#include <vppinfra/os.h> - -void -clib_smp_free (clib_smp_main_t * m) -{ - clib_mem_vm_free (m->vm_base, - (uword) ((1 + m->n_cpus) << m->log2_n_per_cpu_vm_bytes)); -} - -static uword -allocate_per_cpu_mheap (uword cpu) -{ - clib_smp_main_t *m = &clib_smp_main; - void *heap; - uword vm_size, stack_size, mheap_flags; - - ASSERT (os_get_cpu_number () == cpu); - - vm_size = (uword) 1 << m->log2_n_per_cpu_vm_bytes; - stack_size = (uword) 1 << m->log2_n_per_cpu_stack_bytes; - - mheap_flags = MHEAP_FLAG_SMALL_OBJECT_CACHE; - - /* Heap extends up to start of stack. */ - heap = mheap_alloc_with_flags (clib_smp_vm_base_for_cpu (m, cpu), - vm_size - stack_size, mheap_flags); - clib_mem_set_heap (heap); - - if (cpu == 0) - { - /* Now that we have a heap, allocate main structure on cpu 0. */ - vec_resize (m->per_cpu_mains, m->n_cpus); - - /* Allocate shared global heap (thread safe). */ - m->global_heap = - mheap_alloc_with_flags (clib_smp_vm_base_for_cpu (m, cpu + m->n_cpus), - vm_size, - mheap_flags | MHEAP_FLAG_THREAD_SAFE); - } - - m->per_cpu_mains[cpu].heap = heap; - return 0; -} - -void -clib_smp_init (void) -{ - clib_smp_main_t *m = &clib_smp_main; - uword cpu; - - m->vm_base = - clib_mem_vm_alloc ((uword) (m->n_cpus + 1) << m->log2_n_per_cpu_vm_bytes); - if (!m->vm_base) - clib_error ("error allocating virtual memory"); - - for (cpu = 0; cpu < m->n_cpus; cpu++) - clib_calljmp (allocate_per_cpu_mheap, cpu, - clib_smp_stack_top_for_cpu (m, cpu)); -} - -void -clib_smp_lock_init (clib_smp_lock_t ** pl) -{ - clib_smp_lock_t *l; - uword i, n_bytes, n_fifo_elts; - - /* No locking necessary if n_cpus <= 1. - Null means no locking is necessary. */ - if (clib_smp_main.n_cpus < 2) - { - *pl = 0; - return; - } - - /* Need n_cpus - 1 elts in waiting fifo. One CPU holds lock - and others could potentially be waiting. */ - n_fifo_elts = clib_smp_main.n_cpus - 1; - - n_bytes = sizeof (l[0]) + n_fifo_elts * sizeof (l->waiting_fifo[0]); - ASSERT_AND_PANIC (n_bytes % CLIB_CACHE_LINE_BYTES == 0); - - l = clib_mem_alloc_aligned (n_bytes, CLIB_CACHE_LINE_BYTES); - - memset (l, 0, n_bytes); - l->n_waiting_fifo_elts = n_fifo_elts; - - for (i = 0; i < l->n_waiting_fifo_elts; i++) - l->waiting_fifo[i].wait_type = CLIB_SMP_LOCK_WAIT_EMPTY; - - *pl = l; -} - -void -clib_smp_lock_free (clib_smp_lock_t ** pl) -{ - if (*pl) - clib_mem_free (*pl); - *pl = 0; -} - -void -clib_smp_lock_slow_path (clib_smp_lock_t * l, - uword my_cpu, - clib_smp_lock_header_t h0, clib_smp_lock_type_t type) -{ - clib_smp_lock_header_t h1, h2, h3; - uword is_reader = type == CLIB_SMP_LOCK_TYPE_READER; - uword n_fifo_elts = l->n_waiting_fifo_elts; - uword my_tail; - - /* Atomically advance waiting FIFO tail pointer; my_tail will point - to entry where we can insert ourselves to wait for lock to be granted. */ - while (1) - { - h1 = h0; - my_tail = h1.waiting_fifo.head_index + h1.waiting_fifo.n_elts; - my_tail = my_tail >= n_fifo_elts ? my_tail - n_fifo_elts : my_tail; - h1.waiting_fifo.n_elts += 1; - h1.request_cpu = my_cpu; - - ASSERT_AND_PANIC (h1.waiting_fifo.n_elts <= n_fifo_elts); - ASSERT_AND_PANIC (my_tail >= 0 && my_tail < n_fifo_elts); - - h2 = clib_smp_lock_set_header (l, h1, h0); - - /* Tail successfully advanced? */ - if (clib_smp_lock_header_is_equal (h0, h2)) - break; - - /* It is possible that if head and tail are both zero, CPU with lock would have unlocked lock. */ - else if (type == CLIB_SMP_LOCK_TYPE_SPIN) - { - while (!h2.writer_has_lock) - { - ASSERT_AND_PANIC (h2.waiting_fifo.n_elts == 0); - h1 = h2; - h1.request_cpu = my_cpu; - h1.writer_has_lock = 1; - - h3 = clib_smp_lock_set_header (l, h1, h2); - - /* Got it? */ - if (clib_smp_lock_header_is_equal (h2, h3)) - return; - - h2 = h3; - } - } - - /* Try to advance tail again. */ - h0 = h2; - } - - { - clib_smp_lock_waiting_fifo_elt_t *w; - - w = l->waiting_fifo + my_tail; - - while (w->wait_type != CLIB_SMP_LOCK_WAIT_EMPTY) - clib_smp_pause (); - - w->wait_type = (is_reader - ? CLIB_SMP_LOCK_WAIT_READER : CLIB_SMP_LOCK_WAIT_WRITER); - - /* Wait until CPU holding the lock grants us the lock. */ - while (w->wait_type != CLIB_SMP_LOCK_WAIT_DONE) - clib_smp_pause (); - - w->wait_type = CLIB_SMP_LOCK_WAIT_EMPTY; - } -} - -void -clib_smp_unlock_slow_path (clib_smp_lock_t * l, - uword my_cpu, - clib_smp_lock_header_t h0, - clib_smp_lock_type_t type) -{ - clib_smp_lock_header_t h1, h2; - clib_smp_lock_waiting_fifo_elt_t *head; - clib_smp_lock_wait_type_t head_wait_type; - uword is_reader = type == CLIB_SMP_LOCK_TYPE_READER; - uword n_fifo_elts = l->n_waiting_fifo_elts; - uword head_index, must_wait_for_readers; - - while (1) - { - /* Advance waiting fifo giving lock to first waiter. */ - while (1) - { - ASSERT_AND_PANIC (h0.waiting_fifo.n_elts != 0); - - h1 = h0; - - head_index = h1.waiting_fifo.head_index; - head = l->waiting_fifo + head_index; - if (is_reader) - { - ASSERT_AND_PANIC (h1.n_readers_with_lock > 0); - h1.n_readers_with_lock -= 1; - } - else - { - /* Writer will already have lock. */ - ASSERT_AND_PANIC (h1.writer_has_lock); - } - - while ((head_wait_type = - head->wait_type) == CLIB_SMP_LOCK_WAIT_EMPTY) - clib_smp_pause (); - - /* Don't advance FIFO to writer unless all readers have unlocked. */ - must_wait_for_readers = - (type != CLIB_SMP_LOCK_TYPE_SPIN - && head_wait_type == CLIB_SMP_LOCK_WAIT_WRITER - && h1.n_readers_with_lock != 0); - - if (!must_wait_for_readers) - { - head_index += 1; - h1.waiting_fifo.n_elts -= 1; - if (type != CLIB_SMP_LOCK_TYPE_SPIN) - { - if (head_wait_type == CLIB_SMP_LOCK_WAIT_WRITER) - h1.writer_has_lock = h1.n_readers_with_lock == 0; - else - { - h1.writer_has_lock = 0; - h1.n_readers_with_lock += 1; - } - } - } - - h1.waiting_fifo.head_index = - head_index == n_fifo_elts ? 0 : head_index; - h1.request_cpu = my_cpu; - - ASSERT_AND_PANIC (h1.waiting_fifo.head_index >= 0 - && h1.waiting_fifo.head_index < n_fifo_elts); - ASSERT_AND_PANIC (h1.waiting_fifo.n_elts >= 0 - && h1.waiting_fifo.n_elts <= n_fifo_elts); - - h2 = clib_smp_lock_set_header (l, h1, h0); - - if (clib_smp_lock_header_is_equal (h2, h0)) - break; - - h0 = h2; - - if (h0.waiting_fifo.n_elts == 0) - return clib_smp_unlock_inline (l, type); - } - - if (must_wait_for_readers) - return; - - /* Wake up head of waiting fifo. */ - { - uword done_waking; - - /* Shift lock to first thread waiting in fifo. */ - head->wait_type = CLIB_SMP_LOCK_WAIT_DONE; - - /* For read locks we may be able to wake multiple readers. */ - done_waking = 1; - if (head_wait_type == CLIB_SMP_LOCK_WAIT_READER) - { - uword hi = h0.waiting_fifo.head_index; - if (h0.waiting_fifo.n_elts != 0 - && l->waiting_fifo[hi].wait_type == CLIB_SMP_LOCK_WAIT_READER) - done_waking = 0; - } - - if (done_waking) - break; - } - } -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/smp.h b/vppinfra/vppinfra/smp.h deleted file mode 100644 index 7e703b3d6aa..00000000000 --- a/vppinfra/vppinfra/smp.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001-2005 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_clib_smp_h -#define included_clib_smp_h - -#include <vppinfra/cache.h> -#include <vppinfra/os.h> /* for os_panic */ - -#define clib_smp_compare_and_swap(addr,new,old) __sync_val_compare_and_swap(addr,old,new) -#define clib_smp_swap(addr,new) __sync_lock_test_and_set(addr,new) -#define clib_smp_atomic_add(addr,increment) __sync_fetch_and_add(addr,increment) - -#if defined (i386) || defined (__x86_64__) -#define clib_smp_pause() do { asm volatile ("pause"); } while (0) -#endif - -#ifndef clib_smp_pause -#define clib_smp_pause() do { } while (0) -#endif - -#ifdef CLIB_UNIX -#include <sched.h> - -always_inline void -os_sched_yield (void) -{ - sched_yield (); -} -#else -always_inline void -os_sched_yield (void) -{ - clib_smp_pause (); -} -#endif - - -#endif /* included_clib_smp_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/smp_fifo.c b/vppinfra/vppinfra/smp_fifo.c deleted file mode 100644 index bb74064d8f3..00000000000 --- a/vppinfra/vppinfra/smp_fifo.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2012 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include <vppinfra/smp_fifo.h> -#include <vppinfra/mem.h> - -clib_smp_fifo_t * -clib_smp_fifo_init (uword max_n_elts, uword n_bytes_per_elt) -{ - clib_smp_fifo_t *f; - uword n_bytes_per_elt_cache_aligned; - - f = clib_mem_alloc_aligned (sizeof (f[0]), CLIB_CACHE_LINE_BYTES); - - memset (f, 0, sizeof (f[0])); - - max_n_elts = max_n_elts ? max_n_elts : 32; - f->log2_max_n_elts = max_log2 (max_n_elts); - f->max_n_elts_less_one = (1 << f->log2_max_n_elts) - 1; - - n_bytes_per_elt_cache_aligned = - clib_smp_fifo_round_elt_bytes (n_bytes_per_elt); - clib_exec_on_global_heap ( - { - f->data = - clib_mem_alloc_aligned - (n_bytes_per_elt_cache_aligned << - f->log2_max_n_elts, CLIB_CACHE_LINE_BYTES);} - ); - - /* Zero all data and mark all elements free. */ - { - uword i; - for (i = 0; i <= f->max_n_elts_less_one; i++) - { - void *d = clib_smp_fifo_elt_at_index (f, n_bytes_per_elt, i); - clib_smp_fifo_data_footer_t *t; - - memset (d, 0, n_bytes_per_elt_cache_aligned); - - t = clib_smp_fifo_get_data_footer (d, n_bytes_per_elt); - clib_smp_fifo_data_footer_set_state (t, - CLIB_SMP_FIFO_DATA_STATE_free); - } - } - - return f; -} - - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/smp_fifo.h b/vppinfra/vppinfra/smp_fifo.h deleted file mode 100644 index c74a77c8e9b..00000000000 --- a/vppinfra/vppinfra/smp_fifo.h +++ /dev/null @@ -1,313 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2012 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_clib_smp_vec_h -#define included_clib_smp_vec_h - -#include <vppinfra/smp.h> - -#define foreach_clib_smp_fifo_data_state \ - _ (free) \ - _ (write_alloc) \ - _ (write_done) \ - _ (read_fetch) - -typedef enum -{ -#define _(f) CLIB_SMP_FIFO_DATA_STATE_##f, - foreach_clib_smp_fifo_data_state -#undef _ - CLIB_SMP_FIFO_N_DATA_STATE, -} clib_smp_fifo_data_state_t; - -/* Footer at end of each data element. */ -typedef struct -{ - /* Magic number marking valid footer plus state encoded in low bits. */ - u32 magic_state; -} clib_smp_fifo_data_footer_t; - -#define CLIB_SMP_DATA_FOOTER_MAGIC 0xfafbfcf0 - -always_inline clib_smp_fifo_data_state_t -clib_smp_fifo_data_footer_get_state (clib_smp_fifo_data_footer_t * f) -{ - u32 s = f->magic_state - CLIB_SMP_DATA_FOOTER_MAGIC; - - /* Check that magic number plus state is still valid. */ - if (s >= CLIB_SMP_FIFO_N_DATA_STATE) - os_panic (); - - return s; -} - -always_inline void -clib_smp_fifo_data_footer_set_state (clib_smp_fifo_data_footer_t * f, - clib_smp_fifo_data_state_t s) -{ - f->magic_state = CLIB_SMP_DATA_FOOTER_MAGIC + s; -} - -typedef struct -{ - /* Read/write indices each on their own cache line. - Atomic incremented for each read/write. */ - u32 read_index, write_index; - - /* Power of 2 number of elements in fifo less one. */ - u32 max_n_elts_less_one; - - /* Log2 of above. */ - u32 log2_max_n_elts; - - /* Cache aligned data. */ - void *data; -} clib_smp_fifo_t; - -/* External functions. */ -clib_smp_fifo_t *clib_smp_fifo_init (uword max_n_elts, uword n_bytes_per_elt); - -/* Elements are always cache-line sized; this is to avoid smp cache thrashing. */ -always_inline uword -clib_smp_fifo_round_elt_bytes (uword n_bytes_per_elt) -{ - return round_pow2 (n_bytes_per_elt, CLIB_CACHE_LINE_BYTES); -} - -always_inline uword -clib_smp_fifo_n_elts (clib_smp_fifo_t * f) -{ - uword n = f->write_index - f->read_index; - ASSERT (n <= f->max_n_elts_less_one + 1); - return n; -} - -always_inline clib_smp_fifo_data_footer_t * -clib_smp_fifo_get_data_footer (void *d, uword n_bytes_per_elt) -{ - clib_smp_fifo_data_footer_t *f; - f = d + clib_smp_fifo_round_elt_bytes (n_bytes_per_elt) - sizeof (f[0]); - return f; -} - -always_inline void * -clib_smp_fifo_elt_at_index (clib_smp_fifo_t * f, uword n_bytes_per_elt, - uword i) -{ - uword n_bytes_per_elt_cache_aligned; - - ASSERT (i <= f->max_n_elts_less_one); - - n_bytes_per_elt_cache_aligned = - clib_smp_fifo_round_elt_bytes (n_bytes_per_elt); - - return f->data + i * n_bytes_per_elt_cache_aligned; -} - -always_inline void * -clib_smp_fifo_write_alloc (clib_smp_fifo_t * f, uword n_bytes_per_elt) -{ - void *d; - clib_smp_fifo_data_footer_t *t; - clib_smp_fifo_data_state_t s; - u32 wi0, wi1; - - wi0 = f->write_index; - - /* Fifo full? */ - if (wi0 - f->read_index > f->max_n_elts_less_one) - return 0; - - while (1) - { - wi1 = wi0 + 1; - - d = - clib_smp_fifo_elt_at_index (f, n_bytes_per_elt, - wi0 & f->max_n_elts_less_one); - t = clib_smp_fifo_get_data_footer (d, n_bytes_per_elt); - - s = clib_smp_fifo_data_footer_get_state (t); - if (s != CLIB_SMP_FIFO_DATA_STATE_free) - { - d = 0; - break; - } - - wi1 = clib_smp_compare_and_swap (&f->write_index, wi1, wi0); - - if (wi1 == wi0) - { - clib_smp_fifo_data_footer_set_state (t, - CLIB_SMP_FIFO_DATA_STATE_write_alloc); - break; - } - - /* Other cpu wrote write index first: try again. */ - wi0 = wi1; - } - - return d; -} - -always_inline void -clib_smp_fifo_write_done (clib_smp_fifo_t * f, void *d, uword n_bytes_per_elt) -{ - clib_smp_fifo_data_footer_t *t; - - /* Flush out pending writes before we change state to write_done. - This will hold off readers until data is flushed. */ - CLIB_MEMORY_BARRIER (); - - t = clib_smp_fifo_get_data_footer (d, n_bytes_per_elt); - - ASSERT (clib_smp_fifo_data_footer_get_state (t) == - CLIB_SMP_FIFO_DATA_STATE_write_alloc); - clib_smp_fifo_data_footer_set_state (t, - CLIB_SMP_FIFO_DATA_STATE_write_done); -} - -always_inline void * -clib_smp_fifo_read_fetch (clib_smp_fifo_t * f, uword n_bytes_per_elt) -{ - void *d; - clib_smp_fifo_data_footer_t *t; - clib_smp_fifo_data_state_t s; - u32 ri0, ri1; - - ri0 = f->read_index; - - /* Fifo empty? */ - if (f->write_index - ri0 == 0) - return 0; - - while (1) - { - ri1 = ri0 + 1; - - d = - clib_smp_fifo_elt_at_index (f, n_bytes_per_elt, - ri0 & f->max_n_elts_less_one); - t = clib_smp_fifo_get_data_footer (d, n_bytes_per_elt); - - s = clib_smp_fifo_data_footer_get_state (t); - if (s != CLIB_SMP_FIFO_DATA_STATE_write_done) - { - d = 0; - break; - } - - ri1 = clib_smp_compare_and_swap (&f->read_index, ri1, ri0); - if (ri1 == ri0) - { - clib_smp_fifo_data_footer_set_state (t, - CLIB_SMP_FIFO_DATA_STATE_read_fetch); - break; - } - - ri0 = ri1; - } - - return d; -} - -always_inline void -clib_smp_fifo_read_done (clib_smp_fifo_t * f, void *d, uword n_bytes_per_elt) -{ - clib_smp_fifo_data_footer_t *t; - - t = clib_smp_fifo_get_data_footer (d, n_bytes_per_elt); - - ASSERT (clib_smp_fifo_data_footer_get_state (t) == - CLIB_SMP_FIFO_DATA_STATE_read_fetch); - clib_smp_fifo_data_footer_set_state (t, CLIB_SMP_FIFO_DATA_STATE_free); -} - -always_inline void -clib_smp_fifo_memcpy (uword * dst, uword * src, uword n_bytes) -{ - word n_bytes_left = n_bytes; - - while (n_bytes_left >= 4 * sizeof (uword)) - { - dst[0] = src[0]; - dst[1] = src[1]; - dst[2] = src[2]; - dst[3] = src[3]; - dst += 4; - src += 4; - n_bytes_left -= 4 * sizeof (dst[0]); - } - - while (n_bytes_left > 0) - { - dst[0] = src[0]; - dst += 1; - src += 1; - n_bytes_left -= 1 * sizeof (dst[0]); - } -} - -always_inline void -clib_smp_fifo_write_inline (clib_smp_fifo_t * f, void *elt_to_write, - uword n_bytes_per_elt) -{ - uword *dst; - dst = clib_smp_fifo_write_alloc (f, n_bytes_per_elt); - clib_smp_fifo_memcpy (dst, elt_to_write, n_bytes_per_elt); - clib_smp_fifo_write_done (f, dst, n_bytes_per_elt); -} - -always_inline void -clib_smp_fifo_read_inline (clib_smp_fifo_t * f, void *elt_to_read, - uword n_bytes_per_elt) -{ - uword *src; - src = clib_smp_fifo_read_fetch (f, n_bytes_per_elt); - clib_smp_fifo_memcpy (elt_to_read, src, n_bytes_per_elt); - clib_smp_fifo_read_done (f, src, n_bytes_per_elt); -} - -#endif /* included_clib_smp_vec_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/socket.c b/vppinfra/vppinfra/socket.c deleted file mode 100644 index 99b353fcd52..00000000000 --- a/vppinfra/vppinfra/socket.c +++ /dev/null @@ -1,422 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001, 2002, 2003, 2005 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include <sys/un.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <netdb.h> -#include <unistd.h> -#include <stdio.h> -#include <fcntl.h> -#include <string.h> /* strchr */ - -#include <vppinfra/mem.h> -#include <vppinfra/vec.h> -#include <vppinfra/socket.h> -#include <vppinfra/format.h> -#include <vppinfra/error.h> - -void -clib_socket_tx_add_formatted (clib_socket_t * s, char *fmt, ...) -{ - va_list va; - va_start (va, fmt); - clib_socket_tx_add_va_formatted (s, fmt, &va); - va_end (va); -} - -/* Return and bind to an unused port. */ -static word -find_free_port (word sock) -{ - word port; - - for (port = IPPORT_USERRESERVED; port < 1 << 16; port++) - { - struct sockaddr_in a; - - memset (&a, 0, sizeof (a)); /* Warnings be gone */ - - a.sin_family = PF_INET; - a.sin_addr.s_addr = INADDR_ANY; - a.sin_port = htons (port); - - if (bind (sock, (struct sockaddr *) &a, sizeof (a)) >= 0) - break; - } - - return port < 1 << 16 ? port : -1; -} - -/* Convert a config string to a struct sockaddr and length for use - with bind or connect. */ -static clib_error_t * -socket_config (char *config, - void *addr, socklen_t * addr_len, u32 ip4_default_address) -{ - clib_error_t *error = 0; - - if (!config) - config = ""; - - /* Anything that begins with a / is a local PF_LOCAL socket. */ - if (config[0] == '/') - { - struct sockaddr_un *su = addr; - su->sun_family = PF_LOCAL; - clib_memcpy (&su->sun_path, config, - clib_min (sizeof (su->sun_path), 1 + strlen (config))); - *addr_len = sizeof (su[0]); - } - - /* Hostname or hostname:port or port. */ - else - { - char *host_name; - int port = -1; - struct sockaddr_in *sa = addr; - - host_name = 0; - port = -1; - if (config[0] != 0) - { - unformat_input_t i; - - unformat_init_string (&i, config, strlen (config)); - if (unformat (&i, "%s:%d", &host_name, &port) - || unformat (&i, "%s:0x%x", &host_name, &port)) - ; - else if (unformat (&i, "%s", &host_name)) - ; - else - error = clib_error_return (0, "unknown input `%U'", - format_unformat_error, &i); - unformat_free (&i); - - if (error) - goto done; - } - - sa->sin_family = PF_INET; - *addr_len = sizeof (sa[0]); - if (port != -1) - sa->sin_port = htons (port); - else - sa->sin_port = 0; - - if (host_name) - { - struct in_addr host_addr; - - /* Recognize localhost to avoid host lookup in most common cast. */ - if (!strcmp (host_name, "localhost")) - sa->sin_addr.s_addr = htonl (INADDR_LOOPBACK); - - else if (inet_aton (host_name, &host_addr)) - sa->sin_addr = host_addr; - - else if (host_name && strlen (host_name) > 0) - { - struct hostent *host = gethostbyname (host_name); - if (!host) - error = clib_error_return (0, "unknown host `%s'", config); - else - clib_memcpy (&sa->sin_addr.s_addr, host->h_addr_list[0], - host->h_length); - } - - else - sa->sin_addr.s_addr = htonl (ip4_default_address); - - vec_free (host_name); - if (error) - goto done; - } - } - -done: - return error; -} - -static clib_error_t * -default_socket_write (clib_socket_t * s) -{ - clib_error_t *err = 0; - word written = 0; - word fd = 0; - word tx_len; - - fd = s->fd; - - /* Map standard input to standard output. - Typically, fd is a socket for which read/write both work. */ - if (fd == 0) - fd = 1; - - tx_len = vec_len (s->tx_buffer); - written = write (fd, s->tx_buffer, tx_len); - - /* Ignore certain errors. */ - if (written < 0 && !unix_error_is_fatal (errno)) - written = 0; - - /* A "real" error occurred. */ - if (written < 0) - { - err = clib_error_return_unix (0, "write %wd bytes", tx_len); - vec_free (s->tx_buffer); - goto done; - } - - /* Reclaim the transmitted part of the tx buffer on successful writes. */ - else if (written > 0) - { - if (written == tx_len) - _vec_len (s->tx_buffer) = 0; - else - vec_delete (s->tx_buffer, written, 0); - } - - /* If a non-fatal error occurred AND - the buffer is full, then we must free it. */ - else if (written == 0 && tx_len > 64 * 1024) - { - vec_free (s->tx_buffer); - } - -done: - return err; -} - -static clib_error_t * -default_socket_read (clib_socket_t * sock, int n_bytes) -{ - word fd, n_read; - u8 *buf; - - /* RX side of socket is down once end of file is reached. */ - if (sock->flags & SOCKET_RX_END_OF_FILE) - return 0; - - fd = sock->fd; - - n_bytes = clib_max (n_bytes, 4096); - vec_add2 (sock->rx_buffer, buf, n_bytes); - - if ((n_read = read (fd, buf, n_bytes)) < 0) - { - n_read = 0; - - /* Ignore certain errors. */ - if (!unix_error_is_fatal (errno)) - goto non_fatal; - - return clib_error_return_unix (0, "read %d bytes", n_bytes); - } - - /* Other side closed the socket. */ - if (n_read == 0) - sock->flags |= SOCKET_RX_END_OF_FILE; - -non_fatal: - _vec_len (sock->rx_buffer) += n_read - n_bytes; - - return 0; -} - -static clib_error_t * -default_socket_close (clib_socket_t * s) -{ - if (close (s->fd) < 0) - return clib_error_return_unix (0, "close"); - return 0; -} - -static void -socket_init_funcs (clib_socket_t * s) -{ - if (!s->write_func) - s->write_func = default_socket_write; - if (!s->read_func) - s->read_func = default_socket_read; - if (!s->close_func) - s->close_func = default_socket_close; -} - -clib_error_t * -clib_socket_init (clib_socket_t * s) -{ - union - { - struct sockaddr sa; - struct sockaddr_un su; - } addr; - socklen_t addr_len = 0; - clib_error_t *error = 0; - word port; - - error = socket_config (s->config, &addr.sa, &addr_len, - (s->flags & SOCKET_IS_SERVER - ? INADDR_LOOPBACK : INADDR_ANY)); - if (error) - goto done; - - socket_init_funcs (s); - - s->fd = socket (addr.sa.sa_family, SOCK_STREAM, 0); - if (s->fd < 0) - { - error = clib_error_return_unix (0, "socket"); - goto done; - } - - port = 0; - if (addr.sa.sa_family == PF_INET) - port = ((struct sockaddr_in *) &addr)->sin_port; - - if (s->flags & SOCKET_IS_SERVER) - { - uword need_bind = 1; - - if (addr.sa.sa_family == PF_INET) - { - if (port == 0) - { - port = find_free_port (s->fd); - if (port < 0) - { - error = clib_error_return (0, "no free port"); - goto done; - } - need_bind = 0; - } - } - if (addr.sa.sa_family == PF_LOCAL) - unlink (((struct sockaddr_un *) &addr)->sun_path); - - /* Make address available for multiple users. */ - { - int v = 1; - if (setsockopt (s->fd, SOL_SOCKET, SO_REUSEADDR, &v, sizeof (v)) < 0) - clib_unix_warning ("setsockopt SO_REUSEADDR fails"); - } - - if (need_bind && bind (s->fd, &addr.sa, addr_len) < 0) - { - error = clib_error_return_unix (0, "bind"); - goto done; - } - - if (listen (s->fd, 5) < 0) - { - error = clib_error_return_unix (0, "listen"); - goto done; - } - } - else - { - if ((s->flags & SOCKET_NON_BLOCKING_CONNECT) - && fcntl (s->fd, F_SETFL, O_NONBLOCK) < 0) - { - error = clib_error_return_unix (0, "fcntl NONBLOCK"); - goto done; - } - - if (connect (s->fd, &addr.sa, addr_len) < 0 - && !((s->flags & SOCKET_NON_BLOCKING_CONNECT) && - errno == EINPROGRESS)) - { - error = clib_error_return_unix (0, "connect"); - goto done; - } - } - - return error; - -done: - if (s->fd > 0) - close (s->fd); - return error; -} - -clib_error_t * -clib_socket_accept (clib_socket_t * server, clib_socket_t * client) -{ - clib_error_t *err = 0; - socklen_t len = 0; - - memset (client, 0, sizeof (client[0])); - - /* Accept the new socket connection. */ - client->fd = accept (server->fd, 0, 0); - if (client->fd < 0) - return clib_error_return_unix (0, "accept"); - - /* Set the new socket to be non-blocking. */ - if (fcntl (client->fd, F_SETFL, O_NONBLOCK) < 0) - { - err = clib_error_return_unix (0, "fcntl O_NONBLOCK"); - goto close_client; - } - - /* Get peer info. */ - len = sizeof (client->peer); - if (getpeername (client->fd, (struct sockaddr *) &client->peer, &len) < 0) - { - err = clib_error_return_unix (0, "getpeername"); - goto close_client; - } - - client->flags = SOCKET_IS_CLIENT; - - socket_init_funcs (client); - return 0; - -close_client: - close (client->fd); - return err; -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/socket.h b/vppinfra/vppinfra/socket.h deleted file mode 100644 index 08e22e7eb61..00000000000 --- a/vppinfra/vppinfra/socket.h +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef _clib_included_socket_h -#define _clib_included_socket_h - -#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> - -#include <vppinfra/clib.h> -#include <vppinfra/error.h> -#include <vppinfra/format.h> - -typedef struct _socket_t -{ - /* File descriptor. */ - i32 fd; - - /* Config string for socket HOST:PORT or just HOST. */ - char *config; - - u32 flags; -#define SOCKET_IS_SERVER (1 << 0) -#define SOCKET_IS_CLIENT (0 << 0) -#define SOCKET_NON_BLOCKING_CONNECT (1 << 1) - - /* Read returned end-of-file. */ -#define SOCKET_RX_END_OF_FILE (1 << 2) - - /* Transmit buffer. Holds data waiting to be written. */ - u8 *tx_buffer; - - /* Receive buffer. Holds data read from socket. */ - u8 *rx_buffer; - - /* Peer socket we are connected to. */ - struct sockaddr_in peer; - - clib_error_t *(*write_func) (struct _socket_t * sock); - clib_error_t *(*read_func) (struct _socket_t * sock, int min_bytes); - clib_error_t *(*close_func) (struct _socket_t * sock); - void *private_data; -} clib_socket_t; - -/* socket config format is host:port. - Unspecified port causes a free one to be chosen starting - from IPPORT_USERRESERVED (5000). */ -clib_error_t *clib_socket_init (clib_socket_t * socket); - -clib_error_t *clib_socket_accept (clib_socket_t * server, - clib_socket_t * client); - -always_inline uword -clib_socket_is_server (clib_socket_t * sock) -{ - return (sock->flags & SOCKET_IS_SERVER) != 0; -} - -always_inline uword -clib_socket_is_client (clib_socket_t * s) -{ - return !clib_socket_is_server (s); -} - -always_inline int -clib_socket_rx_end_of_file (clib_socket_t * s) -{ - return s->flags & SOCKET_RX_END_OF_FILE; -} - -always_inline void * -clib_socket_tx_add (clib_socket_t * s, int n_bytes) -{ - u8 *result; - vec_add2 (s->tx_buffer, result, n_bytes); - return result; -} - -always_inline void -clib_socket_tx_add_va_formatted (clib_socket_t * s, char *fmt, va_list * va) -{ - s->tx_buffer = va_format (s->tx_buffer, fmt, va); -} - -always_inline clib_error_t * -clib_socket_tx (clib_socket_t * s) -{ - return s->write_func (s); -} - -always_inline clib_error_t * -clib_socket_rx (clib_socket_t * s, int n_bytes) -{ - return s->read_func (s, n_bytes); -} - -always_inline void -clib_socket_free (clib_socket_t * s) -{ - vec_free (s->tx_buffer); - vec_free (s->rx_buffer); - if (clib_mem_is_heap_object (s->config)) - vec_free (s->config); - memset (s, 0, sizeof (s[0])); -} - -always_inline clib_error_t * -clib_socket_close (clib_socket_t * sock) -{ - clib_error_t *err; - err = (*sock->close_func) (sock); - return err; -} - -void clib_socket_tx_add_formatted (clib_socket_t * s, char *fmt, ...); - -#endif /* _clib_included_socket_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/sparse_vec.h b/vppinfra/vppinfra/sparse_vec.h deleted file mode 100644 index ec8f0a1c4bf..00000000000 --- a/vppinfra/vppinfra/sparse_vec.h +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2005 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_sparse_vec_h -#define included_sparse_vec_h - -#include <vppinfra/vec.h> -#include <vppinfra/bitops.h> - -/* Sparsely indexed vectors. Basic idea taken from Hacker's delight. - Eliot added ranges. */ -typedef struct -{ - /* Bitmap one for each sparse index. */ - uword *is_member_bitmap; - - /* member_counts[i] = total number of members with j < i. */ - u16 *member_counts; - -#define SPARSE_VEC_IS_RANGE (1 << 0) -#define SPARSE_VEC_IS_VALID_RANGE (1 << 1) - u8 *range_flags; -} sparse_vec_header_t; - -always_inline sparse_vec_header_t * -sparse_vec_header (void *v) -{ - return vec_header (v, sizeof (sparse_vec_header_t)); -} - -/* Index 0 is always used to mark indices that are not valid in - sparse vector. For example, you look up V[0x1234] and 0x1234 is not - known you'll get 0 back as an index. */ -#define SPARSE_VEC_INVALID_INDEX (0) - -always_inline void * -sparse_vec_new (uword elt_bytes, uword sparse_index_bits) -{ - void *v; - sparse_vec_header_t *h; - word n; - - ASSERT (sparse_index_bits <= 16); - - v = _vec_resize (0, - /* length increment */ 8, - /* data bytes */ 8 * elt_bytes, - /* header bytes */ sizeof (h[0]), - /* data align */ 0); - - /* Make space for invalid entry (entry 0). */ - _vec_len (v) = 1; - - h = sparse_vec_header (v); - - n = sparse_index_bits - min_log2 (BITS (uword)); - if (n < 0) - n = 0; - n = 1ULL << n; - vec_resize (h->is_member_bitmap, n); - vec_resize (h->member_counts, n); - - return v; -} - -always_inline uword -sparse_vec_index_internal (void *v, - uword sparse_index, - uword maybe_range, u32 * insert) -{ - sparse_vec_header_t *h; - uword i, b, d, w; - u8 is_member; - - h = sparse_vec_header (v); - i = sparse_index / BITS (h->is_member_bitmap[0]); - b = (uword) 1 << (uword) (sparse_index % BITS (h->is_member_bitmap[0])); - - ASSERT (i < vec_len (h->is_member_bitmap)); - ASSERT (i < vec_len (h->member_counts)); - - w = h->is_member_bitmap[i]; - d = h->member_counts[i] + count_set_bits (w & (b - 1)); - - is_member = (w & b) != 0; - if (maybe_range) - { - u8 r = h->range_flags[d]; - u8 is_range, is_valid_range; - - is_range = maybe_range & (r & SPARSE_VEC_IS_RANGE); - is_valid_range = (r & SPARSE_VEC_IS_VALID_RANGE) != 0; - - is_member = is_range ? is_valid_range : is_member; - } - - if (insert) - { - *insert = !is_member; - if (!is_member) - { - uword j; - w |= b; - h->is_member_bitmap[i] = w; - for (j = i + 1; j < vec_len (h->member_counts); j++) - h->member_counts[j] += 1; - } - - return 1 + d; - } - - d = is_member ? d : 0; - - return is_member + d; -} - -always_inline uword -sparse_vec_index (void *v, uword sparse_index) -{ - return sparse_vec_index_internal (v, sparse_index, - /* maybe range */ 0, - /* insert? */ 0); -} - -always_inline void -sparse_vec_index2 (void *v, - u32 si0, u32 si1, u32 * i0_return, u32 * i1_return) -{ - sparse_vec_header_t *h; - uword b0, b1, w0, w1, v0, v1; - u32 i0, i1, d0, d1; - u8 is_member0, is_member1; - - h = sparse_vec_header (v); - - i0 = si0 / BITS (h->is_member_bitmap[0]); - i1 = si1 / BITS (h->is_member_bitmap[0]); - - b0 = (uword) 1 << (uword) (si0 % BITS (h->is_member_bitmap[0])); - b1 = (uword) 1 << (uword) (si1 % BITS (h->is_member_bitmap[0])); - - ASSERT (i0 < vec_len (h->is_member_bitmap)); - ASSERT (i1 < vec_len (h->is_member_bitmap)); - - ASSERT (i0 < vec_len (h->member_counts)); - ASSERT (i1 < vec_len (h->member_counts)); - - w0 = h->is_member_bitmap[i0]; - w1 = h->is_member_bitmap[i1]; - - v0 = w0 & (b0 - 1); - v1 = w1 & (b1 - 1); - - /* Speculate that masks will have zero or one bits set. */ - d0 = h->member_counts[i0] + (v0 != 0); - d1 = h->member_counts[i1] + (v1 != 0); - - /* Validate speculation. */ - if (PREDICT_FALSE (!is_pow2 (v0) || !is_pow2 (v1))) - { - d0 += count_set_bits (v0) - (v0 != 0); - d1 += count_set_bits (v1) - (v1 != 0); - } - - is_member0 = (w0 & b0) != 0; - is_member1 = (w1 & b1) != 0; - - d0 = is_member0 ? d0 : 0; - d1 = is_member1 ? d1 : 0; - - *i0_return = is_member0 + d0; - *i1_return = is_member1 + d1; -} - -#define sparse_vec_free(v) vec_free(v) - -#define sparse_vec_elt_at_index(v,i) \ - vec_elt_at_index ((v), sparse_vec_index ((v), (i))) - -#define sparse_vec_validate(v,i) \ -({ \ - uword _i; \ - u32 _insert; \ - \ - if (! (v)) \ - (v) = sparse_vec_new (sizeof ((v)[0]), BITS (u16)); \ - \ - _i = sparse_vec_index_internal ((v), (i), \ - /* maybe range */ 0, \ - /* insert? */ &_insert); \ - if (_insert) \ - vec_insert_ha ((v), 1, _i, \ - /* header size */ sizeof (sparse_vec_header_t), \ - /* align */ 0); \ - \ - /* Invalid index is 0. */ \ - ASSERT (_i > 0); \ - \ - (v) + _i; \ -}) - -#endif /* included_sparse_vec_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/std-formats.c b/vppinfra/vppinfra/std-formats.c deleted file mode 100644 index ac98f999f21..00000000000 --- a/vppinfra/vppinfra/std-formats.c +++ /dev/null @@ -1,330 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include <vppinfra/format.h> -#include <ctype.h> - -/* Format vectors. */ -u8 * -format_vec32 (u8 * s, va_list * va) -{ - u32 *v = va_arg (*va, u32 *); - char *fmt = va_arg (*va, char *); - uword i; - for (i = 0; i < vec_len (v); i++) - { - if (i > 0) - s = format (s, ", "); - s = format (s, fmt, v[i]); - } - return s; -} - -u8 * -format_vec_uword (u8 * s, va_list * va) -{ - uword *v = va_arg (*va, uword *); - char *fmt = va_arg (*va, char *); - uword i; - for (i = 0; i < vec_len (v); i++) - { - if (i > 0) - s = format (s, ", "); - s = format (s, fmt, v[i]); - } - return s; -} - -/* Ascii buffer and length. */ -u8 * -format_ascii_bytes (u8 * s, va_list * va) -{ - u8 *v = va_arg (*va, u8 *); - uword n_bytes = va_arg (*va, uword); - vec_add (s, v, n_bytes); - return s; -} - -/* Format hex dump. */ -u8 * -format_hex_bytes (u8 * s, va_list * va) -{ - u8 *bytes = va_arg (*va, u8 *); - int n_bytes = va_arg (*va, int); - uword i; - - /* Print short or long form depending on byte count. */ - uword short_form = n_bytes <= 32; - uword indent = format_get_indent (s); - - if (n_bytes == 0) - return s; - - for (i = 0; i < n_bytes; i++) - { - if (!short_form && (i % 32) == 0) - s = format (s, "%08x: ", i); - - s = format (s, "%02x", bytes[i]); - - if (!short_form && ((i + 1) % 32) == 0 && (i + 1) < n_bytes) - s = format (s, "\n%U", format_white_space, indent); - } - - return s; -} - -/* Add variable number of spaces. */ -u8 * -format_white_space (u8 * s, va_list * va) -{ - uword n = va_arg (*va, uword); - while (n-- > 0) - vec_add1 (s, ' '); - return s; -} - -u8 * -format_time_interval (u8 * s, va_list * args) -{ - u8 *fmt = va_arg (*args, u8 *); - f64 t = va_arg (*args, f64); - u8 *f; - - const f64 seconds_per_minute = 60; - const f64 seconds_per_hour = 60 * seconds_per_minute; - const f64 seconds_per_day = 24 * seconds_per_hour; - uword days, hours, minutes, secs, msecs, usecs; - - days = t / seconds_per_day; - t -= days * seconds_per_day; - - hours = t / seconds_per_hour; - t -= hours * seconds_per_hour; - - minutes = t / seconds_per_minute; - t -= minutes * seconds_per_minute; - - secs = t; - t -= secs; - - msecs = 1e3 * t; - usecs = 1e6 * t; - - for (f = fmt; *f; f++) - { - uword what, c; - char *what_fmt = "%d"; - - switch (c = *f) - { - default: - vec_add1 (s, c); - continue; - - case 'd': - what = days; - what_fmt = "%d"; - break; - case 'h': - what = hours; - what_fmt = "%02d"; - break; - case 'm': - what = minutes; - what_fmt = "%02d"; - break; - case 's': - what = secs; - what_fmt = "%02d"; - break; - case 'f': - what = msecs; - what_fmt = "%03d"; - break; - case 'u': - what = usecs; - what_fmt = "%06d"; - break; - } - - s = format (s, what_fmt, what); - } - - return s; -} - -/* Unparse memory size e.g. 100, 100k, 100m, 100g. */ -u8 * -format_memory_size (u8 * s, va_list * va) -{ - uword size = va_arg (*va, uword); - uword l, u, log_u; - - l = size > 0 ? min_log2 (size) : 0; - if (l < 10) - log_u = 0; - else if (l < 20) - log_u = 10; - else if (l < 30) - log_u = 20; - else - log_u = 30; - - u = (uword) 1 << log_u; - if (size & (u - 1)) - s = format (s, "%.2f", (f64) size / (f64) u); - else - s = format (s, "%d", size >> log_u); - - if (log_u != 0) - s = format (s, "%c", " kmg"[log_u / 10]); - - return s; -} - -/* Parse memory size e.g. 100, 100k, 100m, 100g. */ -uword -unformat_memory_size (unformat_input_t * input, va_list * va) -{ - uword amount, shift, c; - uword *result = va_arg (*va, uword *); - - if (!unformat (input, "%wd%_", &amount)) - return 0; - - c = unformat_get_input (input); - switch (c) - { - case 'k': - case 'K': - shift = 10; - break; - case 'm': - case 'M': - shift = 20; - break; - case 'g': - case 'G': - shift = 30; - break; - default: - shift = 0; - unformat_put_input (input); - break; - } - - *result = amount << shift; - return 1; -} - -/* Format c identifier: e.g. a_name -> "a name". - Words for both vector names and null terminated c strings. */ -u8 * -format_c_identifier (u8 * s, va_list * va) -{ - u8 *id = va_arg (*va, u8 *); - uword i, l; - - l = ~0; - if (clib_mem_is_vec (id)) - l = vec_len (id); - - if (id) - for (i = 0; id[i] != 0 && i < l; i++) - { - u8 c = id[i]; - - if (c == '_') - c = ' '; - vec_add1 (s, c); - } - - return s; -} - -u8 * -format_hexdump (u8 * s, va_list * args) -{ - u8 *data = va_arg (*args, u8 *); - uword len = va_arg (*args, uword); - int i, index = 0; - const int line_len = 16; - u8 *line_hex = 0; - u8 *line_str = 0; - uword indent = format_get_indent (s); - - if (!len) - return s; - - for (i = 0; i < len; i++) - { - line_hex = format (line_hex, "%02x ", data[i]); - line_str = format (line_str, "%c", isprint (data[i]) ? data[i] : '.'); - if (!((i + 1) % line_len)) - { - s = format (s, "%U%05x: %v[%v]", - format_white_space, index ? indent : 0, - index, line_hex, line_str); - if (i < len - 1) - s = format (s, "\n"); - index = i + 1; - vec_reset_length (line_hex); - vec_reset_length (line_str); - } - } - - while (i++ % line_len) - line_hex = format (line_hex, " "); - - if (vec_len (line_hex)) - s = format (s, "%U%05x: %v[%v]", - format_white_space, indent, index, line_hex, line_str); - - vec_free (line_hex); - vec_free (line_str); - - return s; -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/string.c b/vppinfra/vppinfra/string.c deleted file mode 100644 index ba21e7b3490..00000000000 --- a/vppinfra/vppinfra/string.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2006 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include <vppinfra/string.h> -#include <vppinfra/error.h> - -/* Exchanges source and destination. */ -void -clib_memswap (void *_a, void *_b, uword bytes) -{ - uword pa = pointer_to_uword (_a); - uword pb = pointer_to_uword (_b); - -#define _(TYPE) \ - if (0 == ((pa | pb) & (sizeof (TYPE) - 1))) \ - { \ - TYPE * a = uword_to_pointer (pa, TYPE *); \ - TYPE * b = uword_to_pointer (pb, TYPE *); \ - \ - while (bytes >= 2*sizeof (TYPE)) \ - { \ - TYPE a0, a1, b0, b1; \ - bytes -= 2*sizeof (TYPE); \ - a += 2; \ - b += 2; \ - a0 = a[-2]; a1 = a[-1]; \ - b0 = b[-2]; b1 = b[-1]; \ - a[-2] = b0; a[-1] = b1; \ - b[-2] = a0; b[-1] = a1; \ - } \ - pa = pointer_to_uword (a); \ - pb = pointer_to_uword (b); \ - } - - if (BITS (uword) == BITS (u64)) - _(u64); - _(u32); - _(u16); - _(u8); - -#undef _ - - ASSERT (bytes < 2); - if (bytes) - { - u8 *a = uword_to_pointer (pa, u8 *); - u8 *b = uword_to_pointer (pb, u8 *); - u8 a0 = a[0], b0 = b[0]; - a[0] = b0; - b[0] = a0; - } -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/string.h b/vppinfra/vppinfra/string.h deleted file mode 100644 index 69a99a3f0ce..00000000000 --- a/vppinfra/vppinfra/string.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_clib_string_h -#define included_clib_string_h - -#include <vppinfra/clib.h> /* for CLIB_LINUX_KERNEL */ -#include <vppinfra/vector.h> - -#ifdef CLIB_LINUX_KERNEL -#include <linux/string.h> -#endif - -#ifdef CLIB_UNIX -#include <string.h> -#endif - -#ifdef CLIB_STANDALONE -#include <vppinfra/standalone_string.h> -#endif - -/* Exchanges source and destination. */ -void clib_memswap (void *_a, void *_b, uword bytes); - -/* - * the vector unit memcpy variants confuse coverity - * so don't let it anywhere near them. - */ -#ifndef __COVERITY__ -#if __AVX__ -#include <vppinfra/memcpy_avx.h> -#elif __SSSE3__ -#include <vppinfra/memcpy_sse3.h> -#else -#define clib_memcpy(a,b,c) memcpy(a,b,c) -#endif -#else /* __COVERITY__ */ -#define clib_memcpy(a,b,c) memcpy(a,b,c) -#endif - -#endif /* included_clib_string_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/test_bihash_template.c b/vppinfra/vppinfra/test_bihash_template.c deleted file mode 100644 index c505bd83d9a..00000000000 --- a/vppinfra/vppinfra/test_bihash_template.c +++ /dev/null @@ -1,297 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include <vppinfra/time.h> -#include <vppinfra/cache.h> -#include <vppinfra/error.h> - -#include <vppinfra/bihash_8_8.h> -#include <vppinfra/bihash_template.h> - -#include <vppinfra/bihash_template.c> - -typedef struct -{ - u64 seed; - u32 nbuckets; - u32 nitems; - u32 search_iter; - int careful_delete_tests; - int verbose; - int non_random_keys; - uword *key_hash; - u64 *keys; - BVT (clib_bihash) hash; - clib_time_t clib_time; - - unformat_input_t *input; - -} test_main_t; - -test_main_t test_main; - -uword -vl (void *v) -{ - return vec_len (v); -} - -static clib_error_t * -test_bihash (test_main_t * tm) -{ - int i, j; - uword *p; - uword total_searches; - f64 before, delta; - BVT (clib_bihash) * h; - BVT (clib_bihash_kv) kv; - - h = &tm->hash; - - BV (clib_bihash_init) (h, "test", tm->nbuckets, 3ULL << 30); - - fformat (stdout, "Pick %lld unique %s keys...\n", - tm->nitems, tm->non_random_keys ? "non-random" : "random"); - - for (i = 0; i < tm->nitems; i++) - { - u64 rndkey; - - if (tm->non_random_keys == 0) - { - - again: - rndkey = random_u64 (&tm->seed); - - p = hash_get (tm->key_hash, rndkey); - if (p) - goto again; - } - else - rndkey = (u64) (i + 1) << 16; - - hash_set (tm->key_hash, rndkey, i + 1); - vec_add1 (tm->keys, rndkey); - } - - fformat (stdout, "Add items...\n"); - for (i = 0; i < tm->nitems; i++) - { - kv.key = tm->keys[i]; - kv.value = i + 1; - - BV (clib_bihash_add_del) (h, &kv, 1 /* is_add */ ); - - if (tm->verbose > 1) - { - fformat (stdout, "--------------------\n"); - fformat (stdout, "After adding key %llu value %lld...\n", - tm->keys[i], (u64) (i + 1)); - fformat (stdout, "%U", BV (format_bihash), h, - 2 /* very verbose */ ); - } - } - - fformat (stdout, "%U", BV (format_bihash), h, 0 /* very verbose */ ); - - fformat (stdout, "Search for items %d times...\n", tm->search_iter); - - before = clib_time_now (&tm->clib_time); - - for (j = 0; j < tm->search_iter; j++) - { - u64 hash1 = clib_xxhash (tm->keys[0]); - - for (i = 0; i < tm->nitems; i++) - { - if (i < (tm->nitems - 3)) - { - clib_bihash_bucket_t *b; - BVT (clib_bihash_value) * v; - u64 hash2 = clib_xxhash (tm->keys[i + 3]); - u32 bucket_index = hash2 & (h->nbuckets - 1); - b = &h->buckets[bucket_index]; - CLIB_PREFETCH (b, CLIB_CACHE_LINE_BYTES, LOAD); - - bucket_index = hash1 & (h->nbuckets - 1); - b = &h->buckets[bucket_index]; - v = BV (clib_bihash_get_value) (h, b->offset); - hash1 >>= h->log2_nbuckets; - hash1 = hash1 & ((1 << b->log2_pages) - 1); - v += hash1; - CLIB_PREFETCH (v, CLIB_CACHE_LINE_BYTES, LOAD); - - hash1 = hash2; - } - - kv.key = tm->keys[i]; - if (BV (clib_bihash_search) (h, &kv, &kv) < 0) - clib_warning ("search for key %lld failed unexpectedly\n", - tm->keys[i]); - if (kv.value != (u64) (i + 1)) - clib_warning ("search for key %lld returned %lld, not %lld\n", - tm->keys, kv.value, (u64) (i + 1)); - } - } - - delta = clib_time_now (&tm->clib_time) - before; - total_searches = (uword) tm->search_iter * (uword) tm->nitems; - - if (delta > 0) - fformat (stdout, "%.f searches per second\n", - ((f64) total_searches) / delta); - - fformat (stdout, "%lld searches in %.6f seconds\n", total_searches, delta); - - fformat (stdout, "Standard E-hash search for items %d times...\n", - tm->search_iter); - - before = clib_time_now (&tm->clib_time); - - for (j = 0; j < tm->search_iter; j++) - { - for (i = 0; i < tm->nitems; i++) - { - p = hash_get (tm->key_hash, tm->keys[i]); - if (p == 0 || p[0] != (uword) (i + 1)) - clib_warning ("ugh, couldn't find %lld\n", tm->keys[i]); - } - } - - delta = clib_time_now (&tm->clib_time) - before; - total_searches = (uword) tm->search_iter * (uword) tm->nitems; - - fformat (stdout, "%lld searches in %.6f seconds\n", total_searches, delta); - - if (delta > 0) - fformat (stdout, "%.f searches per second\n", - ((f64) total_searches) / delta); - - fformat (stdout, "Delete items...\n"); - - for (i = 0; i < tm->nitems; i++) - { - int j; - int rv; - - kv.key = tm->keys[i]; - kv.value = (u64) (i + 1); - rv = BV (clib_bihash_add_del) (h, &kv, 0 /* is_add */ ); - - if (rv < 0) - clib_warning ("delete key %lld not ok but should be", tm->keys[i]); - - if (tm->careful_delete_tests) - { - for (j = 0; j < tm->nitems; j++) - { - kv.key = tm->keys[j]; - rv = BV (clib_bihash_search) (h, &kv, &kv); - if (j <= i && rv >= 0) - { - clib_warning - ("i %d j %d search ok but should not be, value %lld", - i, j, kv.value); - } - if (j > i && rv < 0) - { - clib_warning ("i %d j %d search not ok but should be", - i, j); - } - } - } - } - - fformat (stdout, "After deletions, should be empty...\n"); - - fformat (stdout, "%U", BV (format_bihash), h, 0 /* very verbose */ ); - return 0; -} - -clib_error_t * -test_bihash_main (test_main_t * tm) -{ - unformat_input_t *i = tm->input; - clib_error_t *error; - - while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) - { - if (unformat (i, "seed %u", &tm->seed)) - ; - - else if (unformat (i, "nbuckets %d", &tm->nbuckets)) - ; - else if (unformat (i, "non-random-keys")) - tm->non_random_keys = 1; - else if (unformat (i, "nitems %d", &tm->nitems)) - ; - else if (unformat (i, "careful %d", &tm->careful_delete_tests)) - ; - else if (unformat (i, "verbose %d", &tm->verbose)) - ; - else if (unformat (i, "search %d", &tm->search_iter)) - ; - else if (unformat (i, "verbose")) - tm->verbose = 1; - else - return clib_error_return (0, "unknown input '%U'", - format_unformat_error, i); - } - - error = test_bihash (tm); - - return error; -} - -#ifdef CLIB_UNIX -int -main (int argc, char *argv[]) -{ - unformat_input_t i; - clib_error_t *error; - test_main_t *tm = &test_main; - - clib_mem_init (0, 3ULL << 30); - - tm->input = &i; - tm->seed = 0xdeaddabe; - - tm->nbuckets = 2; - tm->nitems = 5; - tm->verbose = 1; - tm->search_iter = 1; - tm->careful_delete_tests = 0; - tm->key_hash = hash_create (0, sizeof (uword)); - clib_time_init (&tm->clib_time); - - unformat_init_command_line (&i, argv); - error = test_bihash_main (tm); - unformat_free (&i); - - if (error) - { - clib_error_report (error); - return 1; - } - return 0; -} -#endif /* CLIB_UNIX */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/test_dlist.c b/vppinfra/vppinfra/test_dlist.c deleted file mode 100644 index c5535c854a6..00000000000 --- a/vppinfra/vppinfra/test_dlist.c +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <vppinfra/dlist.h> - -typedef struct -{ - dlist_elt_t *test_pool; - u32 head_index; -} test_main_t; - -test_main_t test_main; - -int -test_dlist_main (unformat_input_t * input) -{ - test_main_t *tm = &test_main; - dlist_elt_t *head, *elt; - u32 elt_index, head_index; - u32 value; - int i; - - pool_get (tm->test_pool, head); - head_index = head - tm->test_pool; - clib_dlist_init (tm->test_pool, head - tm->test_pool); - - for (i = 1; i <= 3; i++) - { - pool_get (tm->test_pool, elt); - elt_index = elt - tm->test_pool; - - clib_dlist_init (tm->test_pool, elt_index); - elt->value = i; - clib_dlist_addtail (tm->test_pool, head_index, elt_index); - } - - head = pool_elt_at_index (tm->test_pool, head_index); - - fformat (stdout, "Dump forward links\n"); - elt_index = head->next; - i = 1; - value = 0; - while (value != ~0) - { - elt = pool_elt_at_index (tm->test_pool, elt_index); - fformat (stdout, "elt %d value %d\n", i++, elt->value); - elt_index = elt->next; - value = elt->value; - } - - fformat (stdout, "Dump reverse links\n"); - elt_index = head->prev; - i = 1; - value = 0; - while (value != ~0) - { - elt = pool_elt_at_index (tm->test_pool, elt_index); - fformat (stdout, "elt %d value %d\n", i++, elt->value); - elt_index = elt->prev; - value = elt->value; - } - - fformat (stdout, "remove first element\n"); - - elt_index = clib_dlist_remove_head (tm->test_pool, head_index); - elt = pool_elt_at_index (tm->test_pool, elt_index); - - fformat (stdout, "removed index %d value %d\n", elt_index, elt->value); - - head = pool_elt_at_index (tm->test_pool, head_index); - - fformat (stdout, "Dump forward links\n"); - elt_index = head->next; - i = 1; - value = 0; - while (value != ~0) - { - elt = pool_elt_at_index (tm->test_pool, elt_index); - fformat (stdout, "elt %d value %d\n", i++, elt->value); - elt_index = elt->next; - value = elt->value; - } - - fformat (stdout, "Dump reverse links\n"); - elt_index = head->prev; - i = 1; - value = 0; - while (value != ~0) - { - elt = pool_elt_at_index (tm->test_pool, elt_index); - fformat (stdout, "elt %d value %d\n", i++, elt->value); - elt_index = elt->prev; - value = elt->value; - } - - fformat (stdout, "re-insert index %d value %d at head\n", 1, 1); - - clib_dlist_addhead (tm->test_pool, head_index, 1); - - fformat (stdout, "Dump forward links\n"); - elt_index = head->next; - i = 1; - value = 0; - while (value != ~0) - { - elt = pool_elt_at_index (tm->test_pool, elt_index); - fformat (stdout, "elt %d value %d\n", i++, elt->value); - elt_index = elt->next; - value = elt->value; - } - - fformat (stdout, "Dump reverse links\n"); - elt_index = head->prev; - i = 1; - value = 0; - while (value != ~0) - { - elt = pool_elt_at_index (tm->test_pool, elt_index); - fformat (stdout, "elt %d value %d\n", i++, elt->value); - elt_index = elt->prev; - value = elt->value; - } - - fformat (stdout, "Remove middle element\n"); - - clib_dlist_remove (tm->test_pool, 2); - elt = pool_elt_at_index (tm->test_pool, 2); - - fformat (stdout, "removed index %d value %d\n", elt_index, elt->value); - - fformat (stdout, "Dump forward links\n"); - elt_index = head->next; - i = 1; - value = 0; - while (value != ~0) - { - elt = pool_elt_at_index (tm->test_pool, elt_index); - fformat (stdout, "elt %d value %d\n", i++, elt->value); - elt_index = elt->next; - value = elt->value; - } - - fformat (stdout, "Dump reverse links\n"); - elt_index = head->prev; - i = 1; - value = 0; - while (value != ~0) - { - elt = pool_elt_at_index (tm->test_pool, elt_index); - fformat (stdout, "elt %d value %d\n", i++, elt->value); - elt_index = elt->prev; - value = elt->value; - } - - return 0; -} - -#ifdef CLIB_UNIX -int -main (int argc, char *argv[]) -{ - unformat_input_t i; - int ret; - - clib_mem_init (0, 3ULL << 30); - - unformat_init_command_line (&i, argv); - ret = test_dlist_main (&i); - unformat_free (&i); - - return ret; -} -#endif /* CLIB_UNIX */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/test_elf.c b/vppinfra/vppinfra/test_elf.c deleted file mode 100644 index 84fe0776c33..00000000000 --- a/vppinfra/vppinfra/test_elf.c +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2008 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include <vppinfra/elf.h> - -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> - -#ifndef CLIB_UNIX -#error "unix only" -#endif - -static clib_error_t * -elf_set_interpreter (elf_main_t * em, char *interp) -{ - elf_segment_t *g; - elf_section_t *s; - clib_error_t *error; - - vec_foreach (g, em->segments) - { - if (g->header.type == ELF_SEGMENT_INTERP) - break; - } - - if (g >= vec_end (em->segments)) - return clib_error_return (0, "interpreter not found"); - - if (g->header.memory_size < 1 + strlen (interp)) - return clib_error_return (0, - "given interpreter does not fit; must be less than %d bytes (`%s' given)", - g->header.memory_size, interp); - - error = - elf_get_section_by_start_address (em, g->header.virtual_address, &s); - if (error) - return error; - - /* Put in new null terminated string. */ - memset (s->contents, 0, vec_len (s->contents)); - clib_memcpy (s->contents, interp, strlen (interp)); - - return 0; -} - -static void -delete_dynamic_rpath_entries_from_section (elf_main_t * em, elf_section_t * s) -{ - elf64_dynamic_entry_t *e; - elf64_dynamic_entry_t *new_es = 0; - - vec_foreach (e, em->dynamic_entries) - { - switch (e->type) - { - case ELF_DYNAMIC_ENTRY_RPATH: - case ELF_DYNAMIC_ENTRY_RUN_PATH: - break; - - default: - vec_add1 (new_es, e[0]); - break; - } - } - - /* Pad so as to keep section size constant. */ - { - elf64_dynamic_entry_t e_end; - e_end.type = ELF_DYNAMIC_ENTRY_END; - e_end.data = 0; - while (vec_len (new_es) < vec_len (em->dynamic_entries)) - vec_add1 (new_es, e_end); - } - - elf_set_dynamic_entries (em); -} - -static void -elf_delete_dynamic_rpath_entries (elf_main_t * em) -{ - elf_section_t *s; - - vec_foreach (s, em->sections) - { - switch (s->header.type) - { - case ELF_SECTION_DYNAMIC: - delete_dynamic_rpath_entries_from_section (em, s); - break; - - default: - break; - } - } -} - -typedef struct -{ - elf_main_t elf_main; - char *input_file; - char *output_file; - char *set_interpreter; - int verbose; -} elf_test_main_t; - -int -main (int argc, char *argv[]) -{ - elf_test_main_t _tm, *tm = &_tm; - elf_main_t *em = &tm->elf_main; - unformat_input_t i; - clib_error_t *error = 0; - - memset (tm, 0, sizeof (tm[0])); - - unformat_init_command_line (&i, argv); - while (unformat_check_input (&i) != UNFORMAT_END_OF_INPUT) - { - if (unformat (&i, "in %s", &tm->input_file)) - ; - else if (unformat (&i, "out %s", &tm->output_file)) - ; - else if (unformat (&i, "set-interpreter %s", &tm->set_interpreter)) - ; - else if (unformat (&i, "verbose")) - tm->verbose = ~0; - else if (unformat (&i, "verbose-symbols")) - tm->verbose |= FORMAT_ELF_MAIN_SYMBOLS; - else if (unformat (&i, "verbose-relocations")) - tm->verbose |= FORMAT_ELF_MAIN_RELOCATIONS; - else if (unformat (&i, "verbose-dynamic")) - tm->verbose |= FORMAT_ELF_MAIN_DYNAMIC; - else - { - error = unformat_parse_error (&i); - goto done; - } - } - - if (!tm->input_file) - { - clib_warning ("No input file! Using test_bihash_template"); - tm->input_file = "test_bihash_template"; - } - - error = elf_read_file (em, tm->input_file); - if (error) - goto done; - - if (tm->set_interpreter) - { - clib_error_t *error = elf_set_interpreter (em, tm->set_interpreter); - if (error) - goto done; - elf_delete_dynamic_rpath_entries (em); - } - - if (tm->verbose) - fformat (stdout, "%U", format_elf_main, em, tm->verbose); - - if (tm->output_file) - error = elf_write_file (em, tm->output_file); - - elf_main_free (em); - -done: - if (error) - { - clib_error_report (error); - return 1; - } - else - return 0; -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/test_elog.c b/vppinfra/vppinfra/test_elog.c deleted file mode 100644 index 89905adb4be..00000000000 --- a/vppinfra/vppinfra/test_elog.c +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2005 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include <vppinfra/elog.h> -#include <vppinfra/error.h> -#include <vppinfra/format.h> -#include <vppinfra/random.h> -#include <vppinfra/serialize.h> -#include <vppinfra/unix.h> - -int -test_elog_main (unformat_input_t * input) -{ - clib_error_t *error = 0; - u32 i, n_iter, seed, max_events; - elog_main_t _em, *em = &_em; - u32 verbose; - f64 min_sample_time; - char *dump_file, *load_file, *merge_file, **merge_files; - u8 *tag, **tags; - - n_iter = 100; - max_events = 100000; - seed = 1; - verbose = 0; - dump_file = 0; - load_file = 0; - merge_files = 0; - tags = 0; - min_sample_time = 2; - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "iter %d", &n_iter)) - ; - else if (unformat (input, "seed %d", &seed)) - ; - else if (unformat (input, "dump %s", &dump_file)) - ; - else if (unformat (input, "load %s", &load_file)) - ; - else if (unformat (input, "tag %s", &tag)) - vec_add1 (tags, tag); - else if (unformat (input, "merge %s", &merge_file)) - vec_add1 (merge_files, merge_file); - - else if (unformat (input, "verbose %=", &verbose, 1)) - ; - else if (unformat (input, "max-events %d", &max_events)) - ; - else if (unformat (input, "sample-time %f", &min_sample_time)) - ; - else - { - error = clib_error_create ("unknown input `%U'\n", - format_unformat_error, input); - goto done; - } - } - -#ifdef CLIB_UNIX - if (load_file) - { - if ((error = elog_read_file (em, load_file))) - goto done; - } - - else if (merge_files) - { - uword i; - elog_main_t *ems; - - vec_clone (ems, merge_files); - - elog_init (em, max_events); - for (i = 0; i < vec_len (ems); i++) - { - if ((error = - elog_read_file (i == 0 ? em : &ems[i], merge_files[i]))) - goto done; - if (i > 0) - { - elog_merge (em, tags[0], &ems[i], tags[i]); - tags[0] = 0; - } - } - } - - else -#endif /* CLIB_UNIX */ - { - f64 t[2]; - - elog_init (em, max_events); - elog_enable_disable (em, 1); - t[0] = unix_time_now (); - - for (i = 0; i < n_iter; i++) - { - u32 j, n, sum; - - n = 1 + (random_u32 (&seed) % 128); - sum = 0; - for (j = 0; j < n; j++) - sum += random_u32 (&seed); - - { - ELOG_TYPE_XF (e); - ELOG (em, e, sum); - } - - { - ELOG_TYPE_XF (e); - ELOG (em, e, sum + 1); - } - - { - struct - { - u32 string_index; - f32 f; - } *d; - ELOG_TYPE_DECLARE (e) = - { - .format = "fumble %s %.9f",.format_args = - "t4f4",.n_enum_strings = 4,.enum_strings = - { - "string0", "string1", "string2", "string3",},}; - - d = ELOG_DATA (em, e); - - d->string_index = sum & 3; - d->f = (sum & 0xff) / 128.; - } - - { - ELOG_TYPE_DECLARE (e) = - { - .format = "bar %d.%d.%d.%d",.format_args = "i1i1i1i1",}; - ELOG_TRACK (my_track); - u8 *d = ELOG_TRACK_DATA (em, e, my_track); - d[0] = i + 0; - d[1] = i + 1; - d[2] = i + 2; - d[3] = i + 3; - } - - { - ELOG_TYPE_DECLARE (e) = - { - .format = "bar `%s'",.format_args = "s20",}; - struct - { - char s[20]; - } *d; - u8 *v; - - d = ELOG_DATA (em, e); - v = format (0, "foo %d%c", i, 0); - clib_memcpy (d->s, v, clib_min (vec_len (v), sizeof (d->s))); - } - - { - ELOG_TYPE_DECLARE (e) = - { - .format = "bar `%s'",.format_args = "T4",}; - struct - { - u32 offset; - } *d; - - d = ELOG_DATA (em, e); - d->offset = elog_string (em, "string table %d", i); - } - } - - do - { - t[1] = unix_time_now (); - } - while (t[1] - t[0] < min_sample_time); - } - -#ifdef CLIB_UNIX - if (dump_file) - { - if ((error = elog_write_file (em, dump_file))) - goto done; - } -#endif - - if (verbose) - { - elog_event_t *e, *es; - es = elog_get_events (em); - vec_foreach (e, es) - { - clib_warning ("%18.9f: %12U %U\n", e->time, - format_elog_track, em, e, format_elog_event, em, e); - } - } - -done: - if (error) - clib_error_report (error); - return 0; -} - -#ifdef CLIB_UNIX -int -main (int argc, char *argv[]) -{ - unformat_input_t i; - int r; - - unformat_init_command_line (&i, argv); - r = test_elog_main (&i); - unformat_free (&i); - return r; -} -#endif - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/test_fifo.c b/vppinfra/vppinfra/test_fifo.c deleted file mode 100644 index 45392bc35eb..00000000000 --- a/vppinfra/vppinfra/test_fifo.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2005 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include <vppinfra/fifo.h> -#include <vppinfra/random.h> - -typedef struct -{ - int a, b, c; -} A; - -always_inline void -A_set (A * a, int k) -{ - a->a = 1 * k; - a->b = 2 * k; - a->c = 3 * k; -} - -always_inline int -A_is_valid (A * a, int k) -{ - return a->a == 1 * k && a->b == 2 * k && a->c == 3 * k; -} - -int -test_fifo_main (unformat_input_t * input) -{ - u32 n_added, n_removed, i, j, n_iter, seed, verbose; - A *as = 0, *a; - - n_iter = 1000; - seed = random_default_seed (); - verbose = 0; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "iter %d", &n_iter)) - ; - else if (unformat (input, "seed %d", &seed)) - ; - else if (unformat (input, "verbose %=", &verbose, 1)) - ; - else - { - clib_warning ("unknown input `%U'\n", format_unformat_error, input); - return 1; - } - } - - if (verbose) - clib_warning ("iter %d seed %d\n", n_iter, seed); - - n_added = n_removed = 0; - for (i = 0; i < n_iter; i++) - { - if (clib_fifo_elts (as) > 0 && (random_u32 (&seed) & 1)) - { - A tmp; - clib_fifo_sub1 (as, tmp); - ASSERT (A_is_valid (&tmp, n_removed)); - n_removed++; - } - else - { - clib_fifo_add2 (as, a); - A_set (a, n_added); - n_added++; - } - - ASSERT (clib_fifo_elts (as) == n_added - n_removed); - - j = 0; - /* *INDENT-OFF* */ - clib_fifo_foreach (a, as, { - ASSERT (A_is_valid (a, n_removed + j)); - j++; - }); - /* *INDENT-ON* */ - - ASSERT (j == clib_fifo_elts (as)); - } - - clib_fifo_free (as); - - return 0; -} - -#ifdef CLIB_UNIX -int -main (int argc, char *argv[]) -{ - unformat_input_t i; - int r; - - unformat_init_command_line (&i, argv); - r = test_fifo_main (&i); - unformat_free (&i); - - return r; -} -#endif - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/test_format.c b/vppinfra/vppinfra/test_format.c deleted file mode 100644 index cc95a00ef48..00000000000 --- a/vppinfra/vppinfra/test_format.c +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include <vppinfra/format.h> - -static int verbose; -static u8 *test_vec; - -static u8 * -format_test1 (u8 * s, va_list * va) -{ - uword x = va_arg (*va, uword); - f64 y = va_arg (*va, f64); - return format (s, "%12d %12f%12.4e", x, y, y); -} - -static int -expectation (const char *exp, char *fmt, ...) -{ - int ret = 0; - - va_list va; - va_start (va, fmt); - test_vec = va_format (test_vec, fmt, &va); - va_end (va); - - vec_add1 (test_vec, 0); - if (strcmp (exp, (char *) test_vec)) - { - fformat (stdout, "FAIL: %s (expected vs. result)\n\"%s\"\n\"%v\"\n", - fmt, exp, test_vec); - ret = 1; - } - else if (verbose) - fformat (stdout, "PASS: %s\n", fmt); - vec_delete (test_vec, vec_len (test_vec), 0); - return ret; -} - -int -test_format_main (unformat_input_t * input) -{ - int ret = 0; - u8 *food = format (0, "food"); - - ret |= expectation ("foo", "foo"); - ret |= expectation ("foo", "%s", "foo"); - ret |= expectation ("9876", "%d", 9876); - ret |= expectation ("-9876", "%wd", (word) - 9876); - ret |= expectation ("98765432", "%u", 98765432); - ret |= expectation ("1200ffee", "%x", 0x1200ffee); - ret |= expectation ("BABEBABE", "%X", 0xbabebabe); - ret |= expectation ("10%a", "%d%%%c", 10, 'a'); - ret |= expectation ("123456789abcdef0", "%016Lx", 0x123456789abcdef0LL); - ret |= expectation ("00000123", "%08x", 0x123); - ret |= expectation (" 23 23 2.3037e1", - "%40U", format_test1, 23, 23.0367); - ret |= expectation ("left ", "%-10s", "left"); - ret |= expectation (" center ", "%=10s", "center"); - ret |= expectation (" right", "%+10s", "right"); - ret |= expectation ("123456", "%.0f", 123456.); - ret |= expectation ("1234567.0", "%.1f", 1234567.); - ret |= expectation ("foo", "%.*s", 3, "food"); - ret |= expectation ("food ", "%.*s", 10, "food "); - ret |= expectation ("(nil)", "%.*s", 3, (void *) 0); - ret |= expectation ("foo", "%.*v", 3, food); - ret |= expectation ("foobar", "%.*v%s", 3, food, "bar"); - ret |= expectation ("foo bar", "%S", "foo_bar"); - vec_free (food); - vec_free (test_vec); - return ret; -} - -typedef struct -{ - int a, b; -} foo_t; - -static u8 * -format_foo (u8 * s, va_list * va) -{ - foo_t *foo = va_arg (*va, foo_t *); - return format (s, "{a %d, b %d}", foo->a, foo->b); -} - -static uword -unformat_foo (unformat_input_t * i, va_list * va) -{ - foo_t *foo = va_arg (*va, foo_t *); - return unformat (i, "{%D,%D}", - sizeof (foo->a), &foo->a, sizeof (foo->b), &foo->b); -} - -int -test_unformat_main (unformat_input_t * input) -{ - u32 v[8]; - long l; - long long ll; - f64 f; - u8 *s; - foo_t foo = {.a = ~0,.b = ~0 }; - - v[0] = v[1] = 0; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "01 %d %d", &v[0], &v[1])) - fformat (stdout, "got 01 %d %d\n", v[0], v[1]); - else if (unformat (input, "d %d", &v[0])) - fformat (stdout, "got it d %d\n", v[0]); - else if (unformat (input, "ld %ld", &l)) - fformat (stdout, "got it ld %ld\n", l); - else if (unformat (input, "lld %lld", &ll)) - fformat (stdout, "got it lld %lld\n", ll); - else if (unformat (input, "string %s", &s)) - fformat (stdout, "got string `%s'\n", s); - else if (unformat (input, "float %f", &f)) - fformat (stdout, "got float `%.4f'\n", f); - else if (unformat (input, "foo %U", unformat_foo, &foo)) - fformat (stdout, "got a foo `%U'\n", format_foo, &foo); - else if (unformat (input, "ignore-me1")) - fformat (stdout, "got an `ignore-me1'\n"); - else if (unformat (input, "ignore-me2")) - fformat (stdout, "got an `ignore-me2'\n"); - else if (unformat (input, "gi%d_%d@-", &v[0], &v[1])) - fformat (stdout, "got `gi%d_%d@-'\n", v[0], v[1]); - else if (unformat (input, "%_%d.%d.%d.%d%_->%_%d.%d.%d.%d%_", - &v[0], &v[1], &v[2], &v[3], - &v[4], &v[5], &v[6], &v[7])) - fformat (stdout, "got %d.%d.%d.%d -> %d.%d.%d.%d", - v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]); - else - { - clib_warning ("unknown input `%U'\n", format_unformat_error, input); - return 1; - } - } - - return 0; -} - -#ifdef CLIB_UNIX -int -main (int argc, char *argv[]) -{ - unformat_input_t i; - - verbose = (argc > 1); - unformat_init_command_line (&i, argv); - - if (unformat (&i, "unformat")) - return test_unformat_main (&i); - else - return test_format_main (&i); -} -#endif - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/test_hash.c b/vppinfra/vppinfra/test_hash.c deleted file mode 100644 index 94110ab68ad..00000000000 --- a/vppinfra/vppinfra/test_hash.c +++ /dev/null @@ -1,458 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifdef CLIB_LINUX_KERNEL -#include <linux/unistd.h> -#endif - -#ifdef CLIB_UNIX -#include <unistd.h> -#include <stdlib.h> -#include <stdio.h> -#include <vppinfra/time.h> -#endif - -#include <vppinfra/random.h> -#include <vppinfra/mem.h> -#include <vppinfra/hash.h> -#include <vppinfra/error.h> -#include <vppinfra/format.h> -#include <vppinfra/bitmap.h> - -static int verbose; -#define if_verbose(format,args...) \ - if (verbose) { clib_warning(format, ## args); } - -typedef struct -{ - int n_iterations; - - int n_iterations_per_print; - - /* Number of pairs to insert into hash. */ - int n_pairs; - - /* True to validate correctness of hash functions. */ - int n_iterations_per_validate; - - /* Non-zero if hash table size is to be fixed. */ - int fixed_hash_size; - - /* Verbosity level for hash formats. */ - int verbose; - - /* Random number seed. */ - u32 seed; -} hash_test_t; - -static clib_error_t * -hash_next_test (word * h) -{ - hash_next_t hn = { 0 }; - hash_pair_t *p0, *p1; - clib_error_t *error = 0; - - /* *INDENT-OFF* */ - hash_foreach_pair (p0, h, { - p1 = hash_next (h, &hn); - error = CLIB_ERROR_ASSERT (p0 == p1); - if (error) - break; - }); - /* *INDENT-ON* */ - - if (!error) - error = CLIB_ERROR_ASSERT (!hash_next (h, &hn)); - - return error; -} - -static u8 * -test1_format (u8 * s, va_list * args) -{ - void *CLIB_UNUSED (user_arg) = va_arg (*args, void *); - void *v = va_arg (*args, void *); - hash_pair_t *p = va_arg (*args, hash_pair_t *); - hash_t *h = hash_header (v); - - return format (s, "0x%8U -> 0x%8U", - format_hex_bytes, &p->key, sizeof (p->key), - format_hex_bytes, &p->value[0], hash_value_bytes (h)); -} - -static clib_error_t * -test_word_key (hash_test_t * ht) -{ - word *h = 0; - word i, j; - - word *keys = 0, *vals = 0; - uword *is_inserted = 0; - - clib_error_t *error = 0; - - vec_resize (keys, ht->n_pairs); - vec_resize (vals, vec_len (keys)); - - h = hash_create (ht->fixed_hash_size, sizeof (vals[0])); - - hash_set_pair_format (h, test1_format, 0); - if (ht->fixed_hash_size) - hash_set_flags (h, HASH_FLAG_NO_AUTO_GROW | HASH_FLAG_NO_AUTO_SHRINK); - - { - uword *unique = 0; - u32 k; - - for (i = 0; i < vec_len (keys); i++) - { - do - { - k = random_u32 (&ht->seed) & 0xfffff; - } - while (clib_bitmap_get (unique, k)); - unique = clib_bitmap_ori (unique, k); - keys[i] = k; - vals[i] = i; - } - - clib_bitmap_free (unique); - } - - for (i = 0; i < ht->n_iterations; i++) - { - u32 vi = random_u32 (&ht->seed) % vec_len (keys); - - if (clib_bitmap_get (is_inserted, vi)) - hash_unset (h, keys[vi]); - else - hash_set (h, keys[vi], vals[vi]); - - is_inserted = clib_bitmap_xori (is_inserted, vi); - - if (ht->n_iterations_per_print > 0 - && ((i + 1) % ht->n_iterations_per_print) == 0) - if_verbose ("iteration %d\n %U", i + 1, format_hash, h, ht->verbose); - - if (ht->n_iterations_per_validate == 0 - || (i + 1) % ht->n_iterations_per_validate) - continue; - - { - hash_pair_t *p; - uword ki; - - /* *INDENT-OFF* */ - hash_foreach_pair (p, h, { - ki = p->value[0]; - ASSERT (keys[ki] == p->key); - }); - /* *INDENT-ON* */ - } - - clib_mem_validate (); - - if ((error = hash_validate (h))) - goto done; - - for (j = 0; j < vec_len (keys); j++) - { - uword *v; - v = hash_get (h, keys[j]); - if ((error = - CLIB_ERROR_ASSERT (clib_bitmap_get (is_inserted, j) == - (v != 0)))) - goto done; - if (v) - { - if ((error = CLIB_ERROR_ASSERT (v[0] == vals[j]))) - goto done; - } - } - } - - if ((error = hash_next_test (h))) - goto done; - - if_verbose ("%U", format_hash, h, ht->verbose); - - for (i = 0; i < vec_len (keys); i++) - { - if (!clib_bitmap_get (is_inserted, i)) - continue; - - hash_unset (h, keys[i]); - is_inserted = clib_bitmap_xori (is_inserted, i); - - if (ht->n_iterations_per_validate == 0 - || (i + 1) % ht->n_iterations_per_validate) - continue; - - clib_mem_validate (); - - if ((error = hash_validate (h))) - goto done; - - for (j = 0; j < vec_len (keys); j++) - { - uword *v; - v = hash_get (h, keys[j]); - if ((error = - CLIB_ERROR_ASSERT (clib_bitmap_get (is_inserted, j) == - (v != 0)))) - goto done; - if (v) - { - if ((error = CLIB_ERROR_ASSERT (v[0] == vals[j]))) - goto done; - } - } - } - -done: - hash_free (h); - vec_free (keys); - vec_free (vals); - clib_bitmap_free (is_inserted); - - if (verbose) - fformat (stderr, "%U\n", format_clib_mem_usage, /* verbose */ 0); - - return error; -} - -static u8 * -test2_format (u8 * s, va_list * args) -{ - void *CLIB_UNUSED (user_arg) = va_arg (*args, void *); - void *v = va_arg (*args, void *); - hash_pair_t *p = va_arg (*args, hash_pair_t *); - hash_t *h = hash_header (v); - - return format (s, "0x%8U <- %v", - format_hex_bytes, &p->value[0], hash_value_bytes (h), - p->key); -} - -static clib_error_t * -test_string_key (hash_test_t * ht) -{ - word i, j; - - u8 **keys = 0; - word *vals = 0; - uword *is_inserted = 0; - - word *h = 0; - - clib_error_t *error = 0; - - vec_resize (keys, ht->n_pairs); - vec_resize (vals, vec_len (keys)); - - h = - hash_create_vec (ht->fixed_hash_size, sizeof (keys[0][0]), - sizeof (uword)); - hash_set_pair_format (h, test2_format, 0); - if (ht->fixed_hash_size) - hash_set_flags (h, HASH_FLAG_NO_AUTO_SHRINK | HASH_FLAG_NO_AUTO_GROW); - - for (i = 0; i < vec_len (keys); i++) - { - keys[i] = random_string (&ht->seed, 5 + (random_u32 (&ht->seed) & 0xf)); - keys[i] = format (keys[i], "%x", i); - vals[i] = random_u32 (&ht->seed); - } - - for (i = 0; i < ht->n_iterations; i++) - { - u32 vi = random_u32 (&ht->seed) % vec_len (keys); - - if (clib_bitmap_get (is_inserted, vi)) - hash_unset_mem (h, keys[vi]); - else - hash_set_mem (h, keys[vi], vals[vi]); - - is_inserted = clib_bitmap_xori (is_inserted, vi); - - if (ht->n_iterations_per_print > 0 - && ((i + 1) % ht->n_iterations_per_print) == 0) - if_verbose ("iteration %d\n %U", i + 1, format_hash, h, ht->verbose); - - if (ht->n_iterations_per_validate == 0 - || (i + 1) % ht->n_iterations_per_validate) - continue; - - clib_mem_validate (); - - if ((error = hash_validate (h))) - goto done; - - for (j = 0; j < vec_len (keys); j++) - { - uword *v; - v = hash_get_mem (h, keys[j]); - if ((error = - CLIB_ERROR_ASSERT (clib_bitmap_get (is_inserted, j) == - (v != 0)))) - goto done; - if (v) - { - if ((error = CLIB_ERROR_ASSERT (v[0] == vals[j]))) - goto done; - } - } - } - - if ((error = hash_next_test (h))) - goto done; - - if_verbose ("%U", format_hash, h, ht->verbose); - - for (i = 0; i < vec_len (keys); i++) - { - if (!clib_bitmap_get (is_inserted, i)) - continue; - - hash_unset_mem (h, keys[i]); - is_inserted = clib_bitmap_xori (is_inserted, i); - - if (ht->n_iterations_per_validate == 0 - || (i + 1) % ht->n_iterations_per_validate) - continue; - - clib_mem_validate (); - - if ((error = hash_validate (h))) - goto done; - - for (j = 0; j < vec_len (keys); j++) - { - uword *v; - v = hash_get_mem (h, keys[j]); - if ((error = - CLIB_ERROR_ASSERT (clib_bitmap_get (is_inserted, j) == - (v != 0)))) - goto done; - if (v) - { - if ((error = CLIB_ERROR_ASSERT (v[0] == vals[j]))) - goto done; - } - } - } - -done: - hash_free (h); - vec_free (vals); - clib_bitmap_free (is_inserted); - - for (i = 0; i < vec_len (keys); i++) - vec_free (keys[i]); - vec_free (keys); - - if (verbose) - fformat (stderr, "%U\n", format_clib_mem_usage, /* verbose */ 0); - - return error; -} - -int -test_hash_main (unformat_input_t * input) -{ - hash_test_t _ht = { 0 }, *ht = &_ht; - clib_error_t *error; - - ht->n_iterations = 100; - ht->n_pairs = 10; - ht->fixed_hash_size = 0; /* zero means non-fixed size */ - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (0 == unformat (input, "iter %d", &ht->n_iterations) - && 0 == unformat (input, "print %d", &ht->n_iterations_per_print) - && 0 == unformat (input, "elts %d", &ht->n_pairs) - && 0 == unformat (input, "size %d", &ht->fixed_hash_size) - && 0 == unformat (input, "seed %d", &ht->seed) - && 0 == unformat (input, "verbose %=", &ht->verbose, 1) - && 0 == unformat (input, "valid %d", - &ht->n_iterations_per_validate)) - { - clib_warning ("unknown input `%U'", format_unformat_error, input); - return 1; - } - } - - if (!ht->seed) - ht->seed = random_default_seed (); - - if_verbose ("testing %d iterations, seed %d", ht->n_iterations, ht->seed); - - error = test_word_key (ht); - if (error) - clib_error_report (error); - - error = test_string_key (ht); - if (error) - clib_error_report (error); - - return 0; -} - -#ifdef CLIB_UNIX -int -main (int argc, char *argv[]) -{ - unformat_input_t i; - int ret; - - verbose = (argc > 1); - unformat_init_command_line (&i, argv); - ret = test_hash_main (&i); - unformat_free (&i); - - return ret; -} -#endif /* CLIB_UNIX */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/test_heap.c b/vppinfra/vppinfra/test_heap.c deleted file mode 100644 index 3d5171bf053..00000000000 --- a/vppinfra/vppinfra/test_heap.c +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include <unistd.h> -#include <stdlib.h> - -#include <vppinfra/mem.h> -#include <vppinfra/heap.h> -#include <vppinfra/format.h> - -static int verbose; -#define if_verbose(format,args...) \ - if (verbose) { clib_warning(format, ## args); } - -int -main (int argc, char *argv[]) -{ - word i, j, k, n, check_mask; - u32 seed; - u32 *h = 0; - uword *objects = 0; - uword *handles = 0; - uword objects_used; - uword align, fixed_size; - - n = 10; - seed = (u32) getpid (); - check_mask = 0; - fixed_size = 0; - - if (argc > 1) - { - n = atoi (argv[1]); - verbose = 1; - } - if (argc > 2) - { - word i = atoi (argv[2]); - if (i) - seed = i; - } - if (argc > 3) - check_mask = atoi (argv[3]); - - align = 0; - if (argc > 4) - align = 1 << atoi (argv[4]); - - if_verbose ("testing %wd iterations seed %wd\n", n, seed); - - if (verbose) - fformat (stderr, "%U\n", format_clib_mem_usage, /* verbose */ 0); - - vec_resize (objects, 1000); - if (vec_bytes (objects)) /* stupid warning be gone */ - memset (objects, ~0, vec_bytes (objects)); - vec_resize (handles, vec_len (objects)); - - objects_used = 0; - - if (fixed_size) - { - uword max_len = 1024 * 1024; - void *memory = clib_mem_alloc (max_len * sizeof (h[0])); - h = heap_create_from_memory (memory, max_len, sizeof (h[0])); - } - - for (i = 0; i < n; i++) - { - while (1) - { - j = random_u32 (&seed) % vec_len (objects); - if (objects[j] != ~0 || i + objects_used < n) - break; - } - - if (objects[j] != ~0) - { - heap_dealloc (h, handles[j]); - objects_used--; - objects[j] = ~0; - } - else - { - u32 *data; - uword size; - - size = 1 + (random_u32 (&seed) % 100); - objects[j] = heap_alloc_aligned (h, size, align, handles[j]); - objects_used++; - - if (align) - ASSERT (0 == (objects[j] & (align - 1))); - ASSERT (objects[j] < vec_len (h)); - ASSERT (size <= heap_len (h, handles[j])); - - /* Set newly allocated object with test data. */ - if (check_mask & 2) - { - data = h + objects[j]; - - for (k = 0; k < size; k++) - data[k] = objects[j] + k; - } - } - - if (check_mask & 1) - heap_validate (h); - - if (check_mask & 4) - { - /* Duplicate heap at each iteration. */ - u32 *h1 = heap_dup (h); - heap_free (h); - h = h1; - } - - /* Verify that all used objects have correct test data. */ - if (check_mask & 2) - { - for (j = 0; j < vec_len (objects); j++) - if (objects[j] != ~0) - { - u32 *data = h + objects[j]; - for (k = 0; k < heap_len (h, handles[j]); k++) - ASSERT (data[k] == objects[j] + k); - } - } - } - - if (verbose) - fformat (stderr, "%U\n", format_heap, h, 1); - - { - u32 *h1 = heap_dup (h); - if (verbose) - fformat (stderr, "%U\n", format_heap, h1, 1); - heap_free (h1); - } - - heap_free (h); - if (verbose) - fformat (stderr, "%U\n", format_heap, h, 1); - ASSERT (objects_used == 0); - - vec_free (objects); - vec_free (handles); - - if (fixed_size) - vec_free_h (h, sizeof (heap_header_t)); - - if (verbose) - fformat (stderr, "%U\n", format_clib_mem_usage, /* verbose */ 0); - - return 0; -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/test_longjmp.c b/vppinfra/vppinfra/test_longjmp.c deleted file mode 100644 index 2415c4f061c..00000000000 --- a/vppinfra/vppinfra/test_longjmp.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2005 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include <vppinfra/clib.h> -#include <vppinfra/longjmp.h> -#include <vppinfra/format.h> - -static void test_calljmp (unformat_input_t * input); - -static int i; - -static int verbose; -#define if_verbose(format,args...) \ - if (verbose) { clib_warning(format, ## args); } - -static never_inline void -f2 (clib_longjmp_t * env) -{ - i++; - clib_longjmp (env, 1); -} - -static never_inline void -f1 (clib_longjmp_t * env) -{ - i++; - f2 (env); -} - -int -test_longjmp_main (unformat_input_t * input) -{ - clib_longjmp_t env; - - i = 0; - if (clib_setjmp (&env, 0) == 0) - { - if_verbose ("calling long jumper %d", i); - f1 (&env); - } - if_verbose ("back from long jump %d", i); - - test_calljmp (input); - - return 0; -} - -static uword -f3 (uword arg) -{ - uword i, j, array[10]; - - for (i = 0; i < ARRAY_LEN (array); i++) - array[i] = arg + i; - - j = 0; - for (i = 0; i < ARRAY_LEN (array); i++) - j ^= array[i]; - - return j; -} - -static void -test_calljmp (unformat_input_t * input) -{ - static u8 stack[32 * 1024] __attribute__ ((aligned (16))); - uword v; - - v = clib_calljmp (f3, 0, stack + sizeof (stack)); - ASSERT (v == f3 (0)); - if_verbose ("calljump ok"); -} - -#ifdef CLIB_UNIX -int -main (int argc, char *argv[]) -{ - unformat_input_t i; - int res; - - verbose = (argc > 1); - unformat_init_command_line (&i, argv); - res = test_longjmp_main (&i); - unformat_free (&i); - return res; -} -#endif - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/test_macros.c b/vppinfra/vppinfra/test_macros.c deleted file mode 100644 index de8f2c49fc1..00000000000 --- a/vppinfra/vppinfra/test_macros.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - Copyright (c) 2014 Cisco and/or its affiliates. - - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. -*/ - -#include <vppinfra/macros.h> - -macro_main_t macro_main; - -int -test_macros_main (unformat_input_t * input) -{ - macro_main_t *mm = ¯o_main; - - clib_macro_init (mm); - - fformat (stdout, "hostname: %s\n", - clib_macro_eval_dollar (mm, "hostname", 1 /* complain */ )); - - clib_macro_set_value (mm, "foo", "this is foo which contains $(bar)"); - clib_macro_set_value (mm, "bar", "bar"); - - fformat (stdout, "evaluate: %s\n", - clib_macro_eval (mm, "returns '$(foo)'", 1 /* complain */ )); - - clib_macro_free (mm); - - return 0; -} - -#ifdef CLIB_UNIX -int -main (int argc, char *argv[]) -{ - unformat_input_t i; - int ret; - - unformat_init_command_line (&i, argv); - ret = test_macros_main (&i); - unformat_free (&i); - - return ret; -} -#endif /* CLIB_UNIX */ - - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/test_md5.c b/vppinfra/vppinfra/test_md5.c deleted file mode 100644 index 4be6f964963..00000000000 --- a/vppinfra/vppinfra/test_md5.c +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2004 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include <vppinfra/vec.h> -#include <vppinfra/format.h> -#include <vppinfra/error.h> -#include <vppinfra/md5.h> - -#include <fcntl.h> -#include <unistd.h> - -static clib_error_t *md5_test_suite (void); - -int -main (int argc, char *argv[]) -{ - int i; - - if (argc == 1) - { - clib_error_t *e; - e = md5_test_suite (); - if (e) - { - clib_error_report (e); - exit (1); - } - } - - for (i = 1; i < argc; i++) - { - md5_context_t m; - u8 digest[16]; - u8 buffer[64 * 1024]; - int fd, n; - - fd = open (argv[i], 0); - if (fd < 0) - clib_unix_error ("can't open %s", argv[i]); - - md5_init (&m); - while ((n = read (fd, buffer, sizeof (buffer))) > 0) - md5_add (&m, buffer, n); - close (fd); - md5_finish (&m, digest); - fformat (stdout, "%U %s\n", - format_hex_bytes, digest, sizeof (digest), argv[i]); - } - - return 0; -} - -static clib_error_t * -md5_test_suite (void) -{ - typedef struct - { - char *input; - char *output; - } md5_test_t; - - static md5_test_t tests[] = { - {.input = "", - .output = "d41d8cd98f00b204e9800998ecf8427e",}, - {.input = "a", - .output = "0cc175b9c0f1b6a831c399e269772661",}, - {.input = "abc", - .output = "900150983cd24fb0d6963f7d28e17f72",}, - {.input = "message digest", - .output = "f96b697d7cb7938d525a2f31aaf161d0",}, - {.input = "abcdefghijklmnopqrstuvwxyz", - .output = "c3fcd3d76192e4007dfb496cca67e13b",}, - {.input = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", - .output = "d174ab98d277d9f5a5611c2c9f419d9f",}, - {.input = - "12345678901234567890123456789012345678901234567890123456789012345678901234567890", - .output = "57edf4a22be3c955ac49da2e2107b67a",}, - }; - - int i; - u8 *s; - md5_context_t m; - u8 digest[16]; - - for (i = 0; i < ARRAY_LEN (tests); i++) - { - md5_init (&m); - md5_add (&m, tests[i].input, strlen (tests[i].input)); - md5_finish (&m, digest); - s = format (0, "%U", format_hex_bytes, digest, sizeof (digest)); - if (memcmp (s, tests[i].output, 2 * sizeof (digest))) - return clib_error_return - (0, "%s -> %v expected %s", tests[i].input, s, tests[i].output); - vec_free (s); - } - - return 0; -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/test_mheap.c b/vppinfra/vppinfra/test_mheap.c deleted file mode 100644 index 6bc36b89ac3..00000000000 --- a/vppinfra/vppinfra/test_mheap.c +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifdef CLIB_LINUX_KERNEL -#include <linux/unistd.h> -#endif - -#ifdef CLIB_UNIX -#include <unistd.h> -#include <stdlib.h> -#include <stdio.h> /* scanf */ -#endif - -#include <vppinfra/mheap.h> -#include <vppinfra/format.h> -#include <vppinfra/random.h> - -static int verbose = 0; -#define if_verbose(format,args...) \ - if (verbose) { clib_warning(format, ## args); } - -int -test_mheap_main (unformat_input_t * input) -{ - int i, j, k, n_iterations; - void *h, *h_mem; - uword *objects = 0; - u32 objects_used, really_verbose, n_objects, max_object_size; - u32 check_mask, seed, trace, use_vm; - u32 print_every = 0; - u32 *data; - mheap_t *mh; - - /* Validation flags. */ - check_mask = 0; -#define CHECK_VALIDITY 1 -#define CHECK_DATA 2 -#define CHECK_ALIGN 4 - - n_iterations = 10; - seed = 0; - max_object_size = 100; - n_objects = 1000; - trace = 0; - really_verbose = 0; - use_vm = 0; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (0 == unformat (input, "iter %d", &n_iterations) - && 0 == unformat (input, "count %d", &n_objects) - && 0 == unformat (input, "size %d", &max_object_size) - && 0 == unformat (input, "seed %d", &seed) - && 0 == unformat (input, "print %d", &print_every) - && 0 == unformat (input, "validdata %|", - &check_mask, CHECK_DATA | CHECK_VALIDITY) - && 0 == unformat (input, "valid %|", - &check_mask, CHECK_VALIDITY) - && 0 == unformat (input, "verbose %=", &really_verbose, 1) - && 0 == unformat (input, "trace %=", &trace, 1) - && 0 == unformat (input, "vm %=", &use_vm, 1) - && 0 == unformat (input, "align %|", &check_mask, CHECK_ALIGN)) - { - clib_warning ("unknown input `%U'", format_unformat_error, input); - return 1; - } - } - - /* Zero seed means use default. */ - if (!seed) - seed = random_default_seed (); - - if_verbose - ("testing %d iterations, %d %saligned objects, max. size %d, seed %d", - n_iterations, n_objects, (check_mask & CHECK_ALIGN) ? "randomly " : "un", - max_object_size, seed); - - vec_resize (objects, n_objects); - if (vec_bytes (objects)) /* stupid warning be gone */ - memset (objects, ~0, vec_bytes (objects)); - objects_used = 0; - - /* Allocate initial heap. */ - { - uword size = - max_pow2 (2 * n_objects * max_object_size * sizeof (data[0])); - - h_mem = clib_mem_alloc (size); - if (!h_mem) - return 0; - - h = mheap_alloc (h_mem, size); - } - - if (trace) - mheap_trace (h, trace); - - mh = mheap_header (h); - - if (use_vm) - mh->flags &= ~MHEAP_FLAG_DISABLE_VM; - else - mh->flags |= MHEAP_FLAG_DISABLE_VM; - - if (check_mask & CHECK_VALIDITY) - mh->flags |= MHEAP_FLAG_VALIDATE; - - for (i = 0; i < n_iterations; i++) - { - while (1) - { - j = random_u32 (&seed) % vec_len (objects); - if (objects[j] != ~0 || i + objects_used < n_iterations) - break; - } - - if (objects[j] != ~0) - { - mheap_put (h, objects[j]); - objects_used--; - objects[j] = ~0; - } - else - { - uword size, align, align_offset; - - size = (random_u32 (&seed) % max_object_size) * sizeof (data[0]); - align = align_offset = 0; - if (check_mask & CHECK_ALIGN) - { - align = 1 << (random_u32 (&seed) % 10); - align_offset = round_pow2 (random_u32 (&seed) & (align - 1), - sizeof (u32)); - } - - h = mheap_get_aligned (h, size, align, align_offset, &objects[j]); - - if (align > 0) - ASSERT (0 == ((objects[j] + align_offset) & (align - 1))); - - ASSERT (objects[j] != ~0); - objects_used++; - - /* Set newly allocated object with test data. */ - if (check_mask & CHECK_DATA) - { - uword len; - - data = (void *) h + objects[j]; - len = mheap_len (h, data); - - ASSERT (size <= mheap_data_bytes (h, objects[j])); - - data[0] = len; - for (k = 1; k < len; k++) - data[k] = objects[j] + k; - } - } - - /* Verify that all used objects have correct test data. */ - if (check_mask & 2) - { - for (j = 0; j < vec_len (objects); j++) - if (objects[j] != ~0) - { - u32 *data = h + objects[j]; - uword len = data[0]; - for (k = 1; k < len; k++) - ASSERT (data[k] == objects[j] + k); - } - } - if (print_every != 0 && i > 0 && (i % print_every) == 0) - fformat (stderr, "iteration %d: %U\n", i, format_mheap, h, - really_verbose); - } - - if (verbose) - fformat (stderr, "%U\n", format_mheap, h, really_verbose); - mheap_free (h); - clib_mem_free (h_mem); - vec_free (objects); - - return 0; -} - -#ifdef CLIB_UNIX -int -main (int argc, char *argv[]) -{ - unformat_input_t i; - int ret; - - verbose = (argc > 1); - unformat_init_command_line (&i, argv); - ret = test_mheap_main (&i); - unformat_free (&i); - - return ret; -} -#endif /* CLIB_UNIX */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/test_pfhash.c b/vppinfra/vppinfra/test_pfhash.c deleted file mode 100644 index ddbdbb34be5..00000000000 --- a/vppinfra/vppinfra/test_pfhash.c +++ /dev/null @@ -1,322 +0,0 @@ -/* - Copyright (c) 2013 Cisco and/or its affiliates. - - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. -*/ - -#include <vppinfra/pfhash.h> -#include <vppinfra/format.h> -#include <vppinfra/random.h> - -#if defined(CLIB_HAVE_VEC128) && ! defined (__ALTIVEC__) - -int verbose = 0; - -always_inline u8 * -random_aligned_string (u32 * seed, uword len) -{ - u8 *alphabet = (u8 *) "abcdefghijklmnopqrstuvwxyz"; - u8 *s = 0; - word i; - - vec_resize_aligned (s, len, 16); - for (i = 0; i < len; i++) - s[i] = alphabet[random_u32 (seed) % 26]; - - return s; -} - -void exit (int); - -int -test_pfhash_main (unformat_input_t * input) -{ - u32 seed = 0xdeaddabe; - int i, iter; - u32 nkeys = 4; - u32 niter = 1; - u32 nbuckets = 1; - u32 bucket; - u32 sizes[3] = { 16, 8, 4 }, this_size, size; - u8 **keys = 0; - pfhash_t _rec, *p = &_rec; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "seed %d", &seed)) - ; - else if (unformat (input, "niter %d", &niter)) - ; - else if (unformat (input, "nkeys %d", &nkeys)) - ; - else if (unformat (input, "nbuckets %d", &nbuckets)) - ; - else if (unformat (input, "verbose %d", &verbose)) - ; - else if (unformat (input, "verbose")) - verbose = 1; - else - clib_error ("unknown input `%U'", format_unformat_error, input); - } - - vec_validate (keys, nkeys - 1); - - for (i = 0; i < nkeys; i++) - { - int j, k; - - again: - keys[i] = random_aligned_string (&seed, 16); - for (j = 0; j < (i - 1); j++) - { - /* Make sure we don't have a dup key in the min key size */ - for (k = 0; k < 4; k++) - { - if (keys[i][k] != keys[j][k]) - goto check_next_key; - } - vec_free (keys[i]); - goto again; - check_next_key: - ; - } - } - - /* test 8 byte key, 8 byte value case separately */ - - for (size = 8; size < 9; size++) - { - this_size = 8; - - fformat (stdout, "%d-byte key 8 byte value test\n", this_size); - - pfhash_init (p, "test", 8 /* key size */ , 8 /* value size */ , - nbuckets + 1); - - for (iter = 0; iter < niter; iter++) - { - bucket = 0; - for (i = 0; i < nkeys; i++) - { - bucket = (i % nbuckets) + 1; - pfhash_set (p, bucket, keys[i], - (void *) (u64) 0x100000000ULL + i + 1); - } - - for (i = 0; i < nkeys; i++) - { - bucket = (i % nbuckets) + 1; - if (pfhash_get (p, bucket, keys[i]) - != (u64) 0x100000000ULL + i + 1) - { - clib_warning ("key %d bucket %d lookup FAIL\n", i, bucket); - (void) pfhash_get (p, bucket, keys[i]); - } - } - - /* test inline functions */ - for (i = 0; i < nkeys; i++) - { - u32 bucket_contents; - u64 value = 0xdeadbeef; - bucket = (i % nbuckets) + 1; - - pfhash_prefetch_bucket (p, bucket); - bucket_contents = pfhash_read_bucket_prefetch_kv (p, bucket); - - value = pfhash_search_kv_8v8 (p, bucket_contents, - (u64 *) keys[i]); - if (value != (u64) 0x100000000ULL + i + 1) - clib_warning ("key %d bucket %d lookup FAIL\n", i, bucket); - } - - if (verbose) - fformat (stdout, "%U\n", format_pfhash, p, verbose > 1); - - for (i = 0; i < nkeys; i++) - { - bucket = (i % nbuckets) + 1; - pfhash_unset (p, bucket, keys[i]); - } - - for (i = 0; i < nkeys; i++) - { - bucket = (i % nbuckets) + 1; - if (pfhash_get (p, bucket, keys[i]) != (u64) ~ 0) - { - clib_warning ("key %d bucket %d lookup FAIL\n", i, bucket); - (void) pfhash_get (p, bucket, keys[i]); - } - } - /* test inline functions */ - for (i = 0; i < nkeys; i++) - { - u32 bucket_contents; - u64 value = 0xdeadbeef; - bucket = (i % nbuckets) + 1; - - pfhash_prefetch_bucket (p, bucket); - bucket_contents = pfhash_read_bucket_prefetch_kv (p, bucket); - - value = pfhash_search_kv_8v8 (p, bucket_contents, - (u64 *) keys[i]); - - if (value != (u64) ~ 0) - clib_warning ("key %d bucket %d lookup FAIL\n", i, bucket); - } - } - pfhash_free (p); - } - - /* test other cases */ - - for (size = 0; size < ARRAY_LEN (sizes); size++) - { - this_size = sizes[size]; - - fformat (stdout, "%d-byte key test\n", this_size); - - pfhash_init (p, "test", this_size, 4 /* value size */ , nbuckets + 1); - - for (iter = 0; iter < niter; iter++) - { - bucket = 0; - for (i = 0; i < nkeys; i++) - { - bucket = (i % nbuckets) + 1; - pfhash_set (p, bucket, keys[i], (void *) (u64) i + 1); - } - - for (i = 0; i < nkeys; i++) - { - bucket = (i % nbuckets) + 1; - if (pfhash_get (p, bucket, keys[i]) != i + 1) - { - clib_warning ("key %d bucket %d lookup FAIL\n", i, bucket); - (void) pfhash_get (p, bucket, keys[i]); - } - } - - /* test inline functions */ - for (i = 0; i < nkeys; i++) - { - u32 bucket_contents; - u32 value = 0xdeadbeef; - bucket = (i % nbuckets) + 1; - - pfhash_prefetch_bucket (p, bucket); - bucket_contents = pfhash_read_bucket_prefetch_kv (p, bucket); - switch (p->key_size) - { - case 16: - value = - pfhash_search_kv_16 (p, bucket_contents, - (u32x4 *) keys[i]); - break; - case 8: - value = - pfhash_search_kv_8 (p, bucket_contents, (u64 *) keys[i]); - break; - case 4: - value = - pfhash_search_kv_4 (p, bucket_contents, (u32 *) keys[i]); - break; - } - - if (value != (i + 1)) - clib_warning ("key %d bucket %d lookup FAIL\n", i, bucket); - } - - if (verbose) - fformat (stdout, "%U\n", format_pfhash, p, verbose > 1); - - for (i = 0; i < nkeys; i++) - { - bucket = (i % nbuckets) + 1; - pfhash_unset (p, bucket, keys[i]); - } - - for (i = 0; i < nkeys; i++) - { - bucket = (i % nbuckets) + 1; - if (pfhash_get (p, bucket, keys[i]) != (u64) ~ 0) - { - clib_warning ("key %d bucket %d lookup FAIL\n", i, bucket); - (void) pfhash_get (p, bucket, keys[i]); - } - } - /* test inline functions */ - for (i = 0; i < nkeys; i++) - { - u32 bucket_contents; - u32 value = 0xdeadbeef; - bucket = (i % nbuckets) + 1; - - pfhash_prefetch_bucket (p, bucket); - bucket_contents = pfhash_read_bucket_prefetch_kv (p, bucket); - switch (p->key_size) - { - case 16: - value = - pfhash_search_kv_16 (p, bucket_contents, - (u32x4 *) keys[i]); - break; - case 8: - value = - pfhash_search_kv_8 (p, bucket_contents, (u64 *) keys[i]); - break; - case 4: - value = - pfhash_search_kv_4 (p, bucket_contents, (u32 *) keys[i]); - break; - } - if (value != (u32) ~ 0) - clib_warning ("key %d bucket %d lookup FAIL\n", i, bucket); - } - } - pfhash_free (p); - } - - exit (0); -} -#else -int -test_pfhash_main (unformat_input_t * input) -{ - clib_warning ("MMX unit not available"); - return 0; -} -#endif - -#ifdef CLIB_UNIX -int -main (int argc, char *argv[]) -{ - unformat_input_t i; - int ret; - - unformat_init_command_line (&i, argv); - ret = test_pfhash_main (&i); - unformat_free (&i); - - return ret; -} -#endif /* CLIB_UNIX */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/test_phash.c b/vppinfra/vppinfra/test_phash.c deleted file mode 100644 index 9ed2ac7b950..00000000000 --- a/vppinfra/vppinfra/test_phash.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2005 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include <vppinfra/phash.h> -#include <vppinfra/format.h> -#include <vppinfra/random.h> - -static int verbose; -#define if_verbose(format,args...) \ - if (verbose) { clib_warning(format, ## args); } - -int -test_phash_main (unformat_input_t * input) -{ - phash_main_t _pm = { 0 }, *pm = &_pm; - int n_keys, random_keys; - u32 seed; - clib_error_t *error; - - random_keys = 1; - n_keys = 1000; - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (0 == unformat (input, "keys %d", &n_keys) - && 0 == unformat (input, "verbose %=", &verbose, 1) - && 0 == unformat (input, "random-keys %=", &random_keys, 1) - && 0 == unformat (input, "sequential-keys %=", &random_keys, 0) - && 0 == unformat (input, "seed %d", &pm->random_seed) - && 0 == unformat (input, "64-bit %|", &pm->flags, PHASH_FLAG_MIX64) - && 0 == unformat (input, "32-bit %|", &pm->flags, PHASH_FLAG_MIX32) - && 0 == unformat (input, "fast %|", &pm->flags, - PHASH_FLAG_FAST_MODE) - && 0 == unformat (input, "slow %|", &pm->flags, - PHASH_FLAG_SLOW_MODE) - && 0 == unformat (input, "minimal %|", &pm->flags, - PHASH_FLAG_MINIMAL) - && 0 == unformat (input, "non-minimal %|", &pm->flags, - PHASH_FLAG_NON_MINIMAL)) - clib_error ("unknown input `%U'", format_unformat_error, input); - } - - if (!pm->random_seed) - pm->random_seed = random_default_seed (); - - if_verbose - ("%d %d-bit keys, random seed %d, %s mode, looking for %sminimal hash", - n_keys, (pm->flags & PHASH_FLAG_MIX64) ? 64 : 32, pm->random_seed, - (pm->flags & PHASH_FLAG_FAST_MODE) ? "fast" : "slow", - (pm->flags & PHASH_FLAG_MINIMAL) ? "" : "non-"); - - seed = pm->random_seed; - - /* Initialize random keys. */ - { - phash_key_t *k; - - vec_resize (pm->keys, n_keys); - vec_foreach (k, pm->keys) - { - k->key = k - pm->keys; - if (random_keys) - { - if (pm->flags & PHASH_FLAG_MIX64) - k->key = random_u64 (&seed); - else - k->key = random_u32 (&seed); - } - } - } - - error = phash_find_perfect_hash (pm); - if (error) - { - clib_error_report (error); - return 1; - } - else - { - if_verbose ("(%d,%d) (a,b) bits, %d seeds tried, %d tree walks", - pm->a_bits, pm->b_bits, - pm->n_seed_trials, pm->n_perfect_calls); - - error = phash_validate (pm); - if (error) - { - clib_error_report (error); - return 1; - } - } - - return 0; -} - -#ifdef CLIB_UNIX -int -main (int argc, char *argv[]) -{ - unformat_input_t i; - int res; - - verbose = (argc > 1); - unformat_init_command_line (&i, argv); - res = test_phash_main (&i); - unformat_free (&i); - return res; -} -#endif - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/test_pool.c b/vppinfra/vppinfra/test_pool.c deleted file mode 100644 index 67a5e50a38a..00000000000 --- a/vppinfra/vppinfra/test_pool.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include <vppinfra/mem.h> -#include <vppinfra/pool.h> - -#ifdef __KERNEL__ -#include <linux/unistd.h> -#else -#include <unistd.h> -#endif - -int -main (int argc, char *argv[]) -{ - int i, n, seed; - - int *p = 0, *e, j, *o = 0; - - n = atoi (argv[1]); - seed = getpid (); - srandom (1); - - for (i = 0; i < n; i++) - { - if (vec_len (o) < 10 || (random () & 1)) - { - pool_get (p, e); - j = e - p; - *e = j; - vec_add1 (o, j); - } - else - { - j = random () % vec_len (o); - e = p + j; - pool_put (p, e); - vec_delete (o, 1, j); - } - } - p = pool_free (p); - vec_free (o); - return 0; -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/test_pool_iterate.c b/vppinfra/vppinfra/test_pool_iterate.c deleted file mode 100644 index 27ce4bb37b7..00000000000 --- a/vppinfra/vppinfra/test_pool_iterate.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - Copyright (c) 2011 Cisco and/or its affiliates. - - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. -*/ - -#include <vppinfra/mem.h> -#include <vppinfra/pool.h> - -#ifdef __KERNEL__ -#include <linux/unistd.h> -#else -#include <unistd.h> -#endif - -int -main (int argc, char *argv[]) -{ - int i; - uword next; - u32 *tp = 0; - u32 *junk; - - for (i = 0; i < 70; i++) - pool_get (tp, junk); - - (void) junk; /* compiler warning */ - - pool_put_index (tp, 1); - pool_put_index (tp, 65); - - next = ~0; - do - { - next = pool_next_index (tp, next); - fformat (stdout, "next index %d\n", next); - } - while (next != ~0); - - return 0; -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/test_ptclosure.c b/vppinfra/vppinfra/test_ptclosure.c deleted file mode 100644 index be7d51dfa7d..00000000000 --- a/vppinfra/vppinfra/test_ptclosure.c +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <vppinfra/ptclosure.h> -#include <vppinfra/hash.h> - -typedef struct -{ - uword *index_by_name; - u8 *items; -} test_main_t; - -test_main_t test_main; - -static char *items[] = { - "d", - "a", - "b", - "c", -}; - -char *constraints[] = { - "a,b", - "b,c", - "d,b", - // "c,a", /* no partial order possible */ -}; - -u32 -vl (void *p) -{ - return vec_len (p); -} - -static void -dump_closure (test_main_t * tm, char *s, u8 ** orig) -{ - int i, j; - - fformat (stdout, "--------- %s --------------\n", s); - for (i = 0; i < vec_len (orig); i++) - { - for (j = 0; j < vec_len (orig); j++) - if (orig[i][j]) - { - fformat (stdout, "%s <before> %s\n", items[i], items[j]); - } - } -} - -int -comma_split (u8 * s, u8 ** a, u8 ** b) -{ - *a = s; - - while (*s && *s != ',') - s++; - - if (*s == ',') - *s = 0; - else - return 1; - - *b = (u8 *) (s + 1); - return 0; -} - -int -test_ptclosure_main (unformat_input_t * input) -{ - test_main_t *tm = &test_main; - u8 *item_name; - int i, j; - u8 **orig; - u8 **closure; - u8 *a_name, *b_name; - int a_index, b_index; - uword *p; - u8 *this_constraint; - int n; - u32 *result = 0; - - tm->index_by_name = hash_create_string (0, sizeof (uword)); - - n = ARRAY_LEN (items); - - for (i = 0; i < n; i++) - { - item_name = (u8 *) items[i]; - hash_set_mem (tm->index_by_name, item_name, i); - } - - orig = clib_ptclosure_alloc (n); - - for (i = 0; i < ARRAY_LEN (constraints); i++) - { - this_constraint = format (0, "%s%c", constraints[i], 0); - - if (comma_split (this_constraint, &a_name, &b_name)) - { - clib_warning ("couldn't split '%s'", constraints[i]); - return 1; - } - - p = hash_get_mem (tm->index_by_name, a_name); - if (p == 0) - { - clib_warning ("couldn't find '%s'", a_name); - return 1; - } - a_index = p[0]; - - p = hash_get_mem (tm->index_by_name, b_name); - if (p == 0) - { - clib_warning ("couldn't find '%s'", b_name); - return 1; - } - b_index = p[0]; - - orig[a_index][b_index] = 1; - vec_free (this_constraint); - } - - dump_closure (tm, "original relation", orig); - - closure = clib_ptclosure (orig); - - dump_closure (tm, "closure", closure); - - /* - * Output partial order - */ - -again: - for (i = 0; i < n; i++) - { - for (j = 0; j < n; j++) - { - if (closure[i][j]) - goto item_constrained; - } - /* Item i can be output */ - vec_add1 (result, i); - { - int k; - for (k = 0; k < n; k++) - closure[k][i] = 0; - /* "Magic" a before a, to keep from ever outputting it again */ - closure[i][i] = 1; - goto again; - } - item_constrained: - ; - } - - if (vec_len (result) != n) - { - clib_warning ("no partial order exists"); - exit (1); - } - - fformat (stdout, "Partial order:\n"); - - for (i = vec_len (result) - 1; i >= 0; i--) - { - fformat (stdout, "%s\n", items[result[i]]); - } - - vec_free (result); - clib_ptclosure_free (orig); - clib_ptclosure_free (closure); - - return 0; -} - -#ifdef CLIB_UNIX -int -main (int argc, char *argv[]) -{ - unformat_input_t i; - int ret; - - clib_mem_init (0, 3ULL << 30); - - unformat_init_command_line (&i, argv); - ret = test_ptclosure_main (&i); - unformat_free (&i); - - return ret; -} -#endif /* CLIB_UNIX */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/test_qhash.c b/vppinfra/vppinfra/test_qhash.c deleted file mode 100644 index fdbf0bbebb0..00000000000 --- a/vppinfra/vppinfra/test_qhash.c +++ /dev/null @@ -1,333 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include <vppinfra/bitmap.h> -#include <vppinfra/os.h> -#include <vppinfra/qhash.h> -#include <vppinfra/random.h> -#include <vppinfra/time.h> - -typedef struct -{ - u32 n_iter, seed, n_keys, n_hash_keys, verbose; - - u32 max_vector; - - uword *hash; - - uword *keys_in_hash_bitmap; - - u32 *qhash; - - uword *keys; - - uword *lookup_keys; - uword *lookup_key_indices; - u32 *lookup_results; - - u32 *get_multiple_results; - - clib_time_t time; - - f64 overflow_fraction, ave_elts; - f64 get_time, hash_get_time; - f64 set_time, set_count; - f64 unset_time, unset_count; - f64 hash_set_time, hash_unset_time; -} test_qhash_main_t; - -clib_error_t * -test_qhash_main (unformat_input_t * input) -{ - clib_error_t *error = 0; - test_qhash_main_t _tm, *tm = &_tm; - uword i, iter; - - memset (tm, 0, sizeof (tm[0])); - tm->n_iter = 10; - tm->seed = 1; - tm->n_keys = 10; - tm->max_vector = 1; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "iter %d", &tm->n_iter)) - ; - else if (unformat (input, "seed %d", &tm->seed)) - ; - else if (unformat (input, "keys %d", &tm->n_keys)) - ; - else if (unformat (input, "size %d", &tm->n_hash_keys)) - ; - else if (unformat (input, "vector %d", &tm->max_vector)) - ; - else if (unformat (input, "verbose")) - tm->verbose = 1; - else - { - error = clib_error_create ("unknown input `%U'\n", - format_unformat_error, input); - goto done; - } - } - - if (!tm->seed) - tm->seed = random_default_seed (); - - clib_time_init (&tm->time); - - clib_warning ("iter %d, seed %u, keys %d, max vector %d, ", - tm->n_iter, tm->seed, tm->n_keys, tm->max_vector); - - vec_resize (tm->keys, tm->n_keys); - vec_resize (tm->get_multiple_results, tm->n_keys); - for (i = 0; i < vec_len (tm->keys); i++) - tm->keys[i] = random_uword (&tm->seed); - - if (!tm->n_hash_keys) - tm->n_hash_keys = 2 * max_pow2 (tm->n_keys); - tm->n_hash_keys = clib_max (tm->n_keys, tm->n_hash_keys); - qhash_resize (tm->qhash, tm->n_hash_keys); - - { - qhash_t *h = qhash_header (tm->qhash); - int i; - for (i = 0; i < ARRAY_LEN (h->hash_seeds); i++) - h->hash_seeds[i] = random_uword (&tm->seed); - } - - vec_resize (tm->lookup_keys, tm->max_vector); - vec_resize (tm->lookup_key_indices, tm->max_vector); - vec_resize (tm->lookup_results, tm->max_vector); - - for (iter = 0; iter < tm->n_iter; iter++) - { - uword *p, j, n, is_set; - - n = tm->max_vector; - - is_set = random_u32 (&tm->seed) & 1; - is_set |= hash_elts (tm->hash) < (tm->n_keys / 4); - if (hash_elts (tm->hash) > (3 * tm->n_keys) / 4) - is_set = 0; - - _vec_len (tm->lookup_keys) = n; - _vec_len (tm->lookup_key_indices) = n; - j = 0; - while (j < n) - { - i = random_u32 (&tm->seed) % vec_len (tm->keys); - if (clib_bitmap_get (tm->keys_in_hash_bitmap, i) != is_set) - { - f64 t[2]; - tm->lookup_key_indices[j] = i; - tm->lookup_keys[j] = tm->keys[i]; - t[0] = clib_time_now (&tm->time); - if (is_set) - hash_set (tm->hash, tm->keys[i], i); - else - hash_unset (tm->hash, tm->keys[i]); - t[1] = clib_time_now (&tm->time); - if (is_set) - tm->hash_set_time += t[1] - t[0]; - else - tm->hash_unset_time += t[1] - t[0]; - tm->keys_in_hash_bitmap - = clib_bitmap_set (tm->keys_in_hash_bitmap, i, is_set); - j++; - } - } - - { - f64 t[2]; - - if (is_set) - { - t[0] = clib_time_now (&tm->time); - qhash_set_multiple (tm->qhash, - tm->lookup_keys, - vec_len (tm->lookup_keys), - tm->lookup_results); - t[1] = clib_time_now (&tm->time); - tm->set_time += t[1] - t[0]; - tm->set_count += vec_len (tm->lookup_keys); - for (i = 0; i < vec_len (tm->lookup_keys); i++) - { - uword r = tm->lookup_results[i]; - *vec_elt_at_index (tm->qhash, r) = tm->lookup_key_indices[i]; - } - } - else - { - t[0] = clib_time_now (&tm->time); - qhash_unset_multiple (tm->qhash, - tm->lookup_keys, - vec_len (tm->lookup_keys), - tm->lookup_results); - t[1] = clib_time_now (&tm->time); - tm->unset_time += t[1] - t[0]; - tm->unset_count += vec_len (tm->lookup_keys); - - for (i = 0; i < vec_len (tm->lookup_keys); i++) - { - uword r = tm->lookup_results[i]; - *vec_elt_at_index (tm->qhash, r) = ~0; - } - } - } - - if (qhash_elts (tm->qhash) != hash_elts (tm->hash)) - os_panic (); - - { - qhash_t *h; - uword i, k, l, count; - - h = qhash_header (tm->qhash); - - for (i = k = 0; k < vec_len (h->hash_key_valid_bitmap); k++) - i += count_set_bits (h->hash_key_valid_bitmap[k]); - k = hash_elts (h->overflow_hash); - l = qhash_elts (tm->qhash); - if (i + k != l) - os_panic (); - - count = hash_elts (h->overflow_hash); - for (i = 0; i < (1 << h->log2_hash_size); i++) - count += tm->qhash[i] != ~0; - if (count != qhash_elts (tm->qhash)) - os_panic (); - - { - u32 *tmp = 0; - - /* *INDENT-OFF* */ - hash_foreach (k, l, h->overflow_hash, ({ - j = qhash_hash_mix (h, k) / QHASH_KEYS_PER_BUCKET; - vec_validate (tmp, j); - tmp[j] += 1; - })); - /* *INDENT-ON* */ - - for (k = 0; k < vec_len (tmp); k++) - { - if (k >= vec_len (h->overflow_counts)) - os_panic (); - if (h->overflow_counts[k] != tmp[k]) - os_panic (); - } - for (; k < vec_len (h->overflow_counts); k++) - if (h->overflow_counts[k] != 0) - os_panic (); - - vec_free (tmp); - } - } - - { - f64 t[2]; - - t[0] = clib_time_now (&tm->time); - qhash_get_multiple (tm->qhash, tm->keys, vec_len (tm->keys), - tm->get_multiple_results); - t[1] = clib_time_now (&tm->time); - tm->get_time += t[1] - t[0]; - - for (i = 0; i < vec_len (tm->keys); i++) - { - u32 r; - - t[0] = clib_time_now (&tm->time); - p = hash_get (tm->hash, tm->keys[i]); - t[1] = clib_time_now (&tm->time); - tm->hash_get_time += t[1] - t[0]; - - r = qhash_get (tm->qhash, tm->keys[i]); - if (p) - { - if (p[0] != i) - os_panic (); - if (*vec_elt_at_index (tm->qhash, r) != i) - os_panic (); - } - else - { - if (r != ~0) - os_panic (); - } - if (r != tm->get_multiple_results[i]) - os_panic (); - } - } - - tm->overflow_fraction += - ((f64) qhash_n_overflow (tm->qhash) / qhash_elts (tm->qhash)); - tm->ave_elts += qhash_elts (tm->qhash); - } - - fformat (stderr, "%d iter %.6e overflow, %.4f ave. elts\n", - tm->n_iter, - tm->overflow_fraction / tm->n_iter, tm->ave_elts / tm->n_iter); - - tm->get_time /= tm->n_iter * vec_len (tm->keys); - tm->hash_get_time /= tm->n_iter * vec_len (tm->keys); - - tm->set_time /= tm->set_count; - tm->unset_time /= tm->unset_count; - tm->hash_set_time /= tm->set_count; - tm->hash_unset_time /= tm->unset_count; - - fformat (stderr, - "get/set/unset clocks %.2e %.2e %.2e clib %.2e %.2e %.2e ratio %.2f %.2f %.2f\n", - tm->get_time * tm->time.clocks_per_second, - tm->set_time * tm->time.clocks_per_second, - tm->unset_time * tm->time.clocks_per_second, - tm->hash_get_time * tm->time.clocks_per_second, - tm->hash_set_time * tm->time.clocks_per_second, - tm->hash_unset_time * tm->time.clocks_per_second, - tm->hash_get_time / tm->get_time, tm->hash_set_time / tm->set_time, - tm->hash_unset_time / tm->unset_time); - - -done: - return error; -} - -#ifdef CLIB_UNIX -int -main (int argc, char *argv[]) -{ - unformat_input_t i; - clib_error_t *error; - - unformat_init_command_line (&i, argv); - error = test_qhash_main (&i); - unformat_free (&i); - if (error) - { - clib_error_report (error); - return 1; - } - else - return 0; -} -#endif /* CLIB_UNIX */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/test_random.c b/vppinfra/vppinfra/test_random.c deleted file mode 100644 index 49759eacb97..00000000000 --- a/vppinfra/vppinfra/test_random.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include <vppinfra/format.h> -#include <vppinfra/bitmap.h> - -static u32 known_random_sequence[] = { - 0x00000000, 0x3c6ef35f, 0x47502932, 0xd1ccf6e9, - 0xaaf95334, 0x6252e503, 0x9f2ec686, 0x57fe6c2d, - 0xa3d95fa8, 0x81fdbee7, 0x94f0af1a, 0xcbf633b1, -}; - - -int -test_random_main (unformat_input_t * input) -{ - uword n_iterations; - uword i, repeat_count; - uword *bitmap = 0; - uword print; - u32 seed; - u32 *seedp = &seed; - - /* first, check known sequence from Numerical Recipes in C, 2nd ed. - page 284 */ - seed = known_random_sequence[0]; - for (i = 0; i < ARRAY_LEN (known_random_sequence) - 1; i++) - { - u32 rv; - rv = random_u32 (seedp); - if (rv != known_random_sequence[i + 1]) - { - fformat (stderr, "known sequence check FAILS at index %d", i + 1); - break; - } - } - - clib_warning ("known sequence check passes"); - - n_iterations = 1000; - seed = 0; - print = 1 << 24; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (0 == unformat (input, "iter %d", &n_iterations) - && 0 == unformat (input, "print %d", &print) - && 0 == unformat (input, "seed %d", &seed)) - clib_error ("unknown input `%U'", format_unformat_error, input); - } - - if (!seed) - seed = random_default_seed (); - - if (n_iterations == 0) - n_iterations = random_u32_max (); - - clib_warning ("%d iterations, seed %d\n", n_iterations, seed); - - repeat_count = 0; - for (i = 0; i < n_iterations; i++) - { - uword r = random_u32 (&seed); - uword b, ri, rj; - - ri = r / BITS (bitmap[0]); - rj = (uword) 1 << (r % BITS (bitmap[0])); - - vec_validate (bitmap, ri); - b = bitmap[ri]; - - if (b & rj) - goto repeat; - b |= rj; - bitmap[ri] = b; - - if (0 == (i & (print - 1))) - fformat (stderr, "0x%08x iterations %d repeats\n", i, repeat_count); - continue; - - repeat: - fformat (stderr, "repeat found at iteration %d/%d\n", i, n_iterations); - repeat_count++; - continue; - } - - return 0; -} - -#ifdef CLIB_UNIX -int -main (int argc, char *argv[]) -{ - unformat_input_t i; - int ret; - - clib_mem_init (0, 3ULL << 30); - - unformat_init_command_line (&i, argv); - ret = test_random_main (&i); - unformat_free (&i); - - return ret; -} -#endif /* CLIB_UNIX */ - - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/test_random_isaac.c b/vppinfra/vppinfra/test_random_isaac.c deleted file mode 100644 index 337d30ddea0..00000000000 --- a/vppinfra/vppinfra/test_random_isaac.c +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2005 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include <vppinfra/format.h> -#include <vppinfra/hash.h> -#include <vppinfra/random.h> -#include <vppinfra/random_isaac.h> - -static int verbose; -#define if_verbose(format,args...) \ - if (verbose) { clib_warning(format, ## args); } - -int -test_isaac_main (unformat_input_t * input) -{ - uword n_iterations, seed; - uword i, repeat_count; - uword *hash = 0; - uword print; - isaac_t ctx; - uword results[ISAAC_SIZE] = { 0 }; - uword n_results; - - n_iterations = 1000; - seed = 0; - print = 1 << 24; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (0 == unformat (input, "iter %d", &n_iterations) - && 0 == unformat (input, "print %d", &print) - && 0 == unformat (input, "seed %d", &seed)) - clib_error ("unknown input `%U'", format_unformat_error, input); - } - - if (!seed) - seed = random_default_seed (); - - results[0] = seed; - - if (n_iterations == 0) - n_iterations = ~0; - - if_verbose ("%d iterations, seed %d\n", n_iterations, seed); - - repeat_count = 0; - isaac_init (&ctx, results); - isaac (&ctx, results); - n_results = 0; - for (i = 0; i < n_iterations; i++) - { - uword r = results[n_results++]; - - if (!hash) - hash = hash_create (0, /* value bytes */ 0); - - if (hash_get (hash, r)) - goto repeat; - - hash_set1 (hash, r); - - if (n_results >= ARRAY_LEN (results)) - { - isaac (&ctx, results); - n_results = 0; - } - - if (verbose && 0 == (i & (print - 1))) - fformat (stderr, "0x%08x iterations %d repeats\n", i, repeat_count); - - if (hash_elts (hash) > 0x100000) - hash_free (hash); - - continue; - - repeat: - fformat (stderr, "repeat found at iteration %d/%d\n", i, n_iterations); - repeat_count++; - continue; - } - - return repeat_count > 0 ? 1 : 0; -} - -#ifdef CLIB_UNIX -int -main (int argc, char *argv[]) -{ - unformat_input_t i; - int ret; - - verbose = (argc > 1); - unformat_init_command_line (&i, argv); - ret = test_isaac_main (&i); - unformat_free (&i); - - return ret; -} -#endif /* CLIB_UNIX */ - - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/test_serialize.c b/vppinfra/vppinfra/test_serialize.c deleted file mode 100644 index e00eec3268f..00000000000 --- a/vppinfra/vppinfra/test_serialize.c +++ /dev/null @@ -1,274 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2005 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include <vppinfra/format.h> -#include <vppinfra/random.h> -#include <vppinfra/serialize.h> -#include <vppinfra/os.h> - -#define foreach_my_vector_type \ - _ (u8, a8) \ - _ (u16, a16) \ - _ (u32, a32) - -typedef struct -{ -#define _(t,f) t f; - foreach_my_vector_type -#undef _ -} my_vector_type_t; - -static void -serialize_my_vector_type_single (serialize_main_t * m, va_list * va) -{ - my_vector_type_t *v = va_arg (*va, my_vector_type_t *); - u32 n = va_arg (*va, u32); - u32 i; - - for (i = 0; i < n; i++) - { -#define _(t,f) serialize_integer (m, v[i].f, sizeof (v[i].f)); - foreach_my_vector_type; - } -#undef _ -} - -static void -unserialize_my_vector_type_single (serialize_main_t * m, va_list * va) -{ - my_vector_type_t *v = va_arg (*va, my_vector_type_t *); - u32 n = va_arg (*va, u32); - u32 i; - - for (i = 0; i < n; i++) - { -#define _(t,f) { u32 tmp; unserialize_integer (m, &tmp, sizeof (v[i].f)); v[i].f = tmp; } - foreach_my_vector_type; -#undef _ - } -} - -static void -serialize_my_vector_type_multiple (serialize_main_t * m, va_list * va) -{ - my_vector_type_t *v = va_arg (*va, my_vector_type_t *); - u32 n = va_arg (*va, u32); - -#define _(t,f) \ - serialize_multiple \ - (m, \ - &v[0].f, \ - STRUCT_SIZE_OF (my_vector_type_t, f), \ - STRUCT_STRIDE_OF (my_vector_type_t, f), \ - n); - - foreach_my_vector_type; - -#undef _ -} - -static void -unserialize_my_vector_type_multiple (serialize_main_t * m, va_list * va) -{ - my_vector_type_t *v = va_arg (*va, my_vector_type_t *); - u32 n = va_arg (*va, u32); - -#define _(t,f) \ - unserialize_multiple \ - (m, \ - &v[0].f, \ - STRUCT_SIZE_OF (my_vector_type_t, f), \ - STRUCT_STRIDE_OF (my_vector_type_t, f), \ - n); - - foreach_my_vector_type; - -#undef _ -} - -typedef struct -{ - u32 n_iter; - u32 seed; - u32 verbose; - u32 multiple; - u32 max_len; - - my_vector_type_t **test_vectors; - - char *dump_file; - - serialize_main_t serialize_main; - serialize_main_t unserialize_main; -} test_serialize_main_t; - -int -test_serialize_main (unformat_input_t * input) -{ - clib_error_t *error = 0; - test_serialize_main_t _tm, *tm = &_tm; - serialize_main_t *sm = &tm->serialize_main; - serialize_main_t *um = &tm->unserialize_main; - uword i; - - memset (tm, 0, sizeof (tm[0])); - tm->n_iter = 100; - tm->seed = 1; - tm->max_len = 128; - tm->verbose = 0; - tm->multiple = 1; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "iter %d", &tm->n_iter)) - ; - else if (unformat (input, "seed %d", &tm->seed)) - ; - else if (unformat (input, "file %s", &tm->dump_file)) - ; - else if (unformat (input, "max-len %d", &tm->max_len)) - ; - else if (unformat (input, "multiple %=", &tm->multiple, 1)) - ; - else if (unformat (input, "single %=", &tm->multiple, 0)) - ; - else if (unformat (input, "verbose %=", &tm->verbose, 1)) - ; - else - { - error = clib_error_create ("unknown input `%U'\n", - format_unformat_error, input); - goto done; - } - } - - if (tm->seed == 0) - tm->seed = random_default_seed (); - - clib_warning ("iter %d seed %d max-len %d", tm->n_iter, tm->seed, - tm->max_len); - -#ifdef CLIB_UNIX - if (tm->dump_file) - serialize_open_unix_file (sm, tm->dump_file); - else -#endif - serialize_open_vector (sm, 0); - - vec_resize (tm->test_vectors, tm->n_iter); - for (i = 0; i < tm->n_iter; i++) - { - uword l = 1 + (random_u32 (&tm->seed) % tm->max_len); - my_vector_type_t *mv; - - vec_resize (tm->test_vectors[i], l); - vec_foreach (mv, tm->test_vectors[i]) - { -#define _(t,f) mv->f = random_u32 (&tm->seed) & pow2_mask (31); - foreach_my_vector_type; -#undef _ - } - - vec_serialize (sm, tm->test_vectors[i], - tm->multiple ? serialize_my_vector_type_multiple : - serialize_my_vector_type_single); - } - - if (tm->verbose) - clib_warning ("overflow vector max bytes %d", - vec_max_len (sm->stream.overflow_buffer)); - - serialize_close (sm); - -#ifdef CLIB_UNIX - if (tm->dump_file) - { - if ((error = unserialize_open_unix_file (um, tm->dump_file))) - goto done; - } - else -#endif - { - u8 *v = serialize_close_vector (sm); - unserialize_open_data (um, v, vec_len (v)); - } - - for (i = 0; i < tm->n_iter; i++) - { - my_vector_type_t *mv0; - my_vector_type_t *mv1; - - vec_unserialize (um, &mv0, - tm->multiple ? unserialize_my_vector_type_multiple : - unserialize_my_vector_type_single); - mv1 = tm->test_vectors[i]; - - if (vec_len (mv0) != vec_len (mv1)) - os_panic (); - if (memcmp (mv0, mv1, vec_len (mv0) * sizeof (mv0[0]))) - os_panic (); - - vec_free (mv0); - } - -done: - if (error) - clib_error_report (error); - return 0; -} - -#ifdef CLIB_UNIX -int -main (int argc, char *argv[]) -{ - unformat_input_t i; - int r; - - unformat_init_command_line (&i, argv); - r = test_serialize_main (&i); - unformat_free (&i); - return r; -} -#endif - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/test_slist.c b/vppinfra/vppinfra/test_slist.c deleted file mode 100644 index 3c3cbf73ca9..00000000000 --- a/vppinfra/vppinfra/test_slist.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifdef CLIB_UNIX -#include <unistd.h> -#include <stdlib.h> -#include <stdio.h> -#endif - -#include <vppinfra/slist.h> - -typedef struct -{ - u32 *random_pool; - u32 seed; - u32 iter; - u32 verbose; - f64 branching_factor; - clib_slist_t slist; -} test_main_t; - -test_main_t test_main; - -#define foreach_simple_test \ -_(2) \ -_(4) \ -_(3) \ -_(1) - - -void -run_test (test_main_t * tm) -{ - int i; - u32 *tv; - u32 ncompares; - u64 total_compares = 0; - - if (1) - { - /* - * Add a bunch of random numbers to the skip-list, - * sorting them. - */ - for (i = 0; i < tm->iter; i++) - { - pool_get (tm->random_pool, tv); - *tv = random_u32 (&tm->seed); - clib_slist_add (&tm->slist, tv, tv - tm->random_pool); - } - /* make sure we can find each one */ - for (i = 0; i < tm->iter; i++) - { - u32 search_result; - tv = pool_elt_at_index (tm->random_pool, i); - - search_result = clib_slist_search (&tm->slist, tv, &ncompares); - ASSERT (search_result == i); - - total_compares += ncompares; - } - - fformat (stdout, "%.2f avg compares/search\n", - (f64) total_compares / (f64) i); - - fformat (stdout, "%U\n", format_slist, &tm->slist, - tm->iter < 1000 /* verbose */ ); - - /* delete half of them */ - for (i = tm->iter / 2; i < tm->iter; i++) - { - tv = pool_elt_at_index (tm->random_pool, i); - (void) clib_slist_del (&tm->slist, tv); - } - - /* make sure we can find the set we should find, and no others */ - for (i = 0; i < tm->iter; i++) - { - u32 search_result; - tv = pool_elt_at_index (tm->random_pool, i); - - search_result = clib_slist_search (&tm->slist, tv, &ncompares); - if (i >= tm->iter / 2) - ASSERT (search_result == (u32) ~ 0); - else - ASSERT (search_result == i); - - } - - fformat (stdout, "%U\n", format_slist, &tm->slist, - tm->iter < 1000 /* verbose */ ); - - /* delete the rest */ - for (i = 0; i < tm->iter; i++) - { - tv = pool_elt_at_index (tm->random_pool, i); - - (void) clib_slist_del (&tm->slist, tv); - } - - fformat (stdout, "%U\n", format_slist, &tm->slist, - tm->iter < 1000 /* verbose */ ); - } - else - { - -#define _(n) \ - do { \ - pool_get (tm->random_pool, tv); \ - *tv = n; \ - clib_slist_add (&tm->slist, tv, tv - tm->random_pool); \ - fformat(stdout, "%U\n", format_slist, &tm->slist, 1 /* verbose */); \ - } while (0); - foreach_simple_test; -#undef _ - } - - return; -} - -word -test_compare (void *key, u32 elt_index) -{ - u32 *k = (u32 *) key; - u32 elt = test_main.random_pool[elt_index]; - - if (*k < elt) - return -1; - if (*k > elt) - return 1; - return 0; -} - -u8 * -test_format (u8 * s, va_list * args) -{ - u32 elt_index = va_arg (*args, u32); - u32 elt = test_main.random_pool[elt_index]; - - return format (s, "%u", elt); -} - -void -initialize_slist (test_main_t * tm) -{ - clib_slist_init (&tm->slist, tm->branching_factor, - test_compare, test_format); -} - -int -test_slist_main (unformat_input_t * input) -{ - test_main_t *tm = &test_main; - u32 tmp; - - tm->seed = 0xbabeb00b; - tm->iter = 100000; - tm->verbose = 1; - tm->branching_factor = 1.0 / 5.0; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "seed %d", &tm->seed)) - continue; - else if (unformat (input, "iter %d", &tm->iter)) - continue; - else if (unformat (input, "verbose")) - tm->verbose = 1; - else if (unformat (input, "branch %d", &tmp)) - { - if (tmp > 0) - tm->branching_factor = 1.0 / (f64) tmp; - else - fformat (stderr, "warning: branch = 0, ignored\n"); - } - else - { - clib_error ("unknown input `%U'", format_unformat_error, input); - goto usage; - } - } - initialize_slist (tm); - run_test (tm); - - return 0; - -usage: - fformat (stderr, "usage: test_slist seed <seed> iter <iter> [verbose]\n"); - return 1; - -} - -#ifdef CLIB_UNIX -int -main (int argc, char *argv[]) -{ - unformat_input_t i; - int ret; - - clib_mem_init (0, (u64) 4 << 30); - - unformat_init_command_line (&i, argv); - ret = test_slist_main (&i); - unformat_free (&i); - - return ret; -} -#endif /* CLIB_UNIX */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/test_socket.c b/vppinfra/vppinfra/test_socket.c deleted file mode 100644 index 0b05467af80..00000000000 --- a/vppinfra/vppinfra/test_socket.c +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2005 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include <vppinfra/format.h> -#include <vppinfra/socket.h> - -static int verbose; -#define if_verbose(format,args...) \ - if (verbose) { clib_warning(format, ## args); } - -int -test_socket_main (unformat_input_t * input) -{ - clib_socket_t _s = { 0 }, *s = &_s; - char *config; - clib_error_t *error; - - s->config = "localhost:22"; - s->flags = SOCKET_IS_CLIENT; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "server %s %=", &config, - &s->flags, SOCKET_IS_SERVER)) - ; - else if (unformat (input, "client %s %=", &config, - &s->flags, SOCKET_IS_CLIENT)) - ; - else - { - error = clib_error_create ("unknown input `%U'\n", - format_unformat_error, input); - goto done; - } - } - - error = clib_socket_init (s); - if (error) - goto done; - - if (0) - { - struct - { - int a, b; - } *msg; - msg = clib_socket_tx_add (s, sizeof (msg[0])); - msg->a = 99; - msg->b = 100; - } - else - clib_socket_tx_add_formatted (s, "hello there mr server %d\n", 99); - - error = clib_socket_tx (s); - if (error) - goto done; - - while (1) - { - error = clib_socket_rx (s, 100); - if (error) - break; - - if (clib_socket_rx_end_of_file (s)) - break; - - if_verbose ("%v", s->rx_buffer); - _vec_len (s->rx_buffer) = 0; - } - - error = clib_socket_close (s); - -done: - if (error) - clib_error_report (error); - return 0; -} - -#ifdef CLIB_UNIX -int -main (int argc, char *argv[]) -{ - unformat_input_t i; - int r; - - verbose = (argc > 1); - unformat_init_command_line (&i, argv); - r = test_socket_main (&i); - unformat_free (&i); - return r; -} -#endif - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/test_time.c b/vppinfra/vppinfra/test_time.c deleted file mode 100644 index 63cfeac5b0a..00000000000 --- a/vppinfra/vppinfra/test_time.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2005 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include <vppinfra/format.h> -#include <vppinfra/time.h> -#include <vppinfra/math.h> /* for sqrt */ - -static int verbose; -#define if_verbose(format,args...) \ - if (verbose) { clib_warning(format, ## args); } - -static int -test_time_main (unformat_input_t * input) -{ - f64 wait, error; - f64 t, tu[3], ave, rms; - clib_time_t c; - int i, n, j; - - clib_time_init (&c); - wait = 1e-3; - n = 1000; - unformat (input, "%f %d", &wait, &n); - ave = rms = 0; - tu[0] = unix_time_now (); - tu[1] = unix_time_now (); - for (i = 0; i < n; i++) - { - j = 0; - t = clib_time_now (&c); - while (clib_time_now (&c) < t + wait) - j++; - t = j; - ave += t; - rms += t * t; - } - tu[2] = unix_time_now (); - ave /= n; - rms = sqrt (rms / n - ave * ave); - - error = ((tu[2] - tu[1]) - 2 * (tu[1] - tu[0]) - n * wait) / n; - if_verbose ("tested %d x %.6e sec waits, error %.6e loops %.6e +- %.6e\n", - n, wait, error, ave, rms); - - return 0; -} - -#ifdef CLIB_UNIX -int -main (int argc, char *argv[]) -{ - unformat_input_t i; - int ret; - - verbose = (argc > 1); - unformat_init_command_line (&i, argv); - ret = test_time_main (&i); - unformat_free (&i); - - return ret; -} -#endif /* CLIB_UNIX */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/test_timing_wheel.c b/vppinfra/vppinfra/test_timing_wheel.c deleted file mode 100644 index 0ce15ad88cb..00000000000 --- a/vppinfra/vppinfra/test_timing_wheel.c +++ /dev/null @@ -1,389 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include <vppinfra/bitmap.h> -#include <vppinfra/error.h> -#include <vppinfra/format.h> -#include <vppinfra/pool.h> -#include <vppinfra/random.h> -#include <vppinfra/time.h> -#include <vppinfra/timing_wheel.h> -#include <vppinfra/zvec.h> - -#include <vppinfra/math.h> - -#if __GNUC__ < 4 -#define SQRT(a) a -#else -#define SQRT(a) sqrt(a) -#endif - -typedef struct -{ - uword n_iter; - - u32 n_events; - u32 seed; - u32 verbose; - - /* Time is "synthetic" e.g. not taken from CPU timer. */ - u32 synthetic_time; - - clib_time_t time; - timing_wheel_t timing_wheel; - - u64 *events; - - f64 max_time; - f64 wait_time; - - f64 total_iterate_time; - f64 time_iterate_start; - - f64 time_per_status_update; - f64 time_next_status_update; -} test_timing_wheel_main_t; - -typedef struct -{ - f64 dt; - f64 fraction; - u64 count; -} test_timing_wheel_tmp_t; - -static void -set_event (test_timing_wheel_main_t * tm, uword i) -{ - timing_wheel_t *w = &tm->timing_wheel; - u64 cpu_time; - - cpu_time = w->current_time_index << w->log2_clocks_per_bin; - if (tm->synthetic_time) - cpu_time += random_u32 (&tm->seed) % tm->n_iter; - else - cpu_time += - random_f64 (&tm->seed) * tm->max_time * tm->time.clocks_per_second; - - timing_wheel_insert (w, cpu_time, i); - timing_wheel_validate (w); - tm->events[i] = cpu_time; -} - -static int -test_timing_wheel_tmp_cmp (void *a1, void *a2) -{ - test_timing_wheel_tmp_t *f1 = a1; - test_timing_wheel_tmp_t *f2 = a2; - - return f1->dt < f2->dt ? -1 : (f1->dt > f2->dt ? +1 : 0); -} - -clib_error_t * -test_timing_wheel_main (unformat_input_t * input) -{ - clib_error_t *error = 0; - test_timing_wheel_main_t _tm, *tm = &_tm; - timing_wheel_t *w = &tm->timing_wheel; - uword iter, i; - - memset (tm, 0, sizeof (tm[0])); - tm->n_iter = 10; - tm->time_per_status_update = 0; - tm->n_events = 100; - tm->seed = 1; - tm->synthetic_time = 1; - tm->max_time = 1; - tm->wait_time = 1e-3; - - w->validate = 0; - w->n_wheel_elt_time_bits = 32; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "iter %wd", &tm->n_iter)) - ; - else if (unformat (input, "events %d", &tm->n_events)) - ; - else - if (unformat (input, "elt-time-bits %d", &w->n_wheel_elt_time_bits)) - ; - else if (unformat (input, "seed %d", &tm->seed)) - ; - else if (unformat (input, "verbose")) - tm->verbose = 1; - else if (unformat (input, "validate")) - w->validate = 1; - - else if (unformat (input, "real-time")) - tm->synthetic_time = 0; - else if (unformat (input, "synthetic-time")) - tm->synthetic_time = 1; - else if (unformat (input, "max-time %f", &tm->max_time)) - ; - else if (unformat (input, "wait-time %f", &tm->wait_time)) - ; - else if (unformat (input, "iter-time %f", &tm->total_iterate_time)) - ; - else if (unformat (input, "print %f", &tm->time_per_status_update)) - ; - - else - { - error = clib_error_create ("unknown input `%U'\n", - format_unformat_error, input); - goto done; - } - } - - if (!tm->seed) - tm->seed = random_default_seed (); - - clib_time_init (&tm->time); - - if (tm->synthetic_time) - { - w->min_sched_time = tm->time.seconds_per_clock; - w->max_sched_time = w->min_sched_time * 256; - timing_wheel_init (w, 0, tm->time.clocks_per_second); - } - else - { - timing_wheel_init (w, clib_cpu_time_now (), tm->time.clocks_per_second); - } - - clib_warning ("iter %wd, events %d, seed %u, %U", - tm->n_iter, tm->n_events, tm->seed, - format_timing_wheel, &tm->timing_wheel, /* verbose */ 0); - - /* Make some events. */ - vec_resize (tm->events, tm->n_events); - for (i = 0; i < vec_len (tm->events); i++) - set_event (tm, i); - - { - u32 *expired = 0; - f64 ave_error = 0; - f64 rms_error = 0; - f64 max_error = 0, min_error = 1e30; - u32 *error_hist = 0; - uword n_expired = 0; - uword *expired_bitmap[2] = { 0 }; - uword n_events_in_wheel = vec_len (tm->events); - - vec_resize (expired, 32); - vec_resize (error_hist, 1024); - - tm->time_iterate_start = clib_time_now (&tm->time); - tm->time_next_status_update = - tm->time_iterate_start + tm->time_per_status_update; - - if (tm->total_iterate_time != 0) - tm->n_iter = ~0; - - for (iter = 0; iter < tm->n_iter || n_events_in_wheel > 0; iter++) - { - u64 cpu_time, min_next_time[2]; - - if (tm->synthetic_time) - cpu_time = iter << w->log2_clocks_per_bin; - else - cpu_time = clib_cpu_time_now (); - - _vec_len (expired) = 0; - expired = - timing_wheel_advance (w, cpu_time, expired, &min_next_time[0]); - timing_wheel_validate (w); - - /* Update bitmap of expired events. */ - if (w->validate) - { - for (i = 0; i < vec_len (tm->events); i++) - { - uword is_expired; - - is_expired = - (cpu_time >> w->log2_clocks_per_bin) >= - (tm->events[i] >> w->log2_clocks_per_bin); - expired_bitmap[0] = - clib_bitmap_set (expired_bitmap[0], i, is_expired); - - /* Validate min next time. */ - if (is_expired) - ASSERT (min_next_time[0] > tm->events[i]); - else - ASSERT (min_next_time[0] <= tm->events[i]); - } - } - - n_expired += vec_len (expired); - for (i = 0; i < vec_len (expired); i++) - { - word j, idt; - i64 dt_cpu; - f64 fdt_cpu; - - j = expired[i]; - expired_bitmap[1] = clib_bitmap_ori (expired_bitmap[1], j); - - dt_cpu = cpu_time - tm->events[j]; - - /* Event must be scheduled in correct bin. */ - if (tm->synthetic_time) - ASSERT (dt_cpu >= 0 && dt_cpu <= (1 << w->log2_clocks_per_bin)); - - fdt_cpu = dt_cpu * tm->time.seconds_per_clock; - - ave_error += fdt_cpu; - rms_error += fdt_cpu * fdt_cpu; - - if (fdt_cpu > max_error) - max_error = fdt_cpu; - if (fdt_cpu < min_error) - min_error = fdt_cpu; - - idt = - (cpu_time >> w->log2_clocks_per_bin) - - (tm->events[j] >> w->log2_clocks_per_bin); - idt = zvec_signed_to_unsigned (idt); - vec_validate (error_hist, idt); - error_hist[idt] += 1; - } - - if (w->validate) - for (i = 0; i < vec_len (tm->events); i++) - { - int is_expired = clib_bitmap_get (expired_bitmap[0], i); - int is_expired_w = clib_bitmap_get (expired_bitmap[1], i); - ASSERT (is_expired == is_expired_w); - } - - min_next_time[1] = ~0; - for (i = 0; i < vec_len (tm->events); i++) - { - if (!clib_bitmap_get (expired_bitmap[1], i)) - min_next_time[1] = clib_min (min_next_time[1], tm->events[i]); - } - if (min_next_time[0] != min_next_time[1]) - clib_error ("min next time wrong 0x%Lx != 0x%Lx", min_next_time[0], - min_next_time[1]); - - if (tm->time_per_status_update != 0 - && clib_time_now (&tm->time) >= tm->time_next_status_update) - { - f64 ave = 0, rms = 0; - - tm->time_next_status_update += tm->time_per_status_update; - if (n_expired > 0) - { - ave = ave_error / n_expired; - rms = SQRT (rms_error / n_expired - ave * ave); - } - - clib_warning - ("%12wd iter done %10wd expired; ave. error %.4e +- %.4e, range %.4e %.4e", - iter, n_expired, ave, rms, min_error, max_error); - } - - if (tm->total_iterate_time != 0 - && (clib_time_now (&tm->time) - tm->time_iterate_start - >= tm->total_iterate_time)) - tm->n_iter = iter; - - /* Add new events to wheel to replace expired ones. */ - n_events_in_wheel -= vec_len (expired); - if (iter < tm->n_iter) - { - for (i = 0; i < vec_len (expired); i++) - { - uword j = expired[i]; - set_event (tm, j); - expired_bitmap[1] = - clib_bitmap_andnoti (expired_bitmap[1], j); - } - n_events_in_wheel += vec_len (expired); - } - } - - ave_error /= n_expired; - rms_error = SQRT (rms_error / n_expired - ave_error * ave_error); - - clib_warning - ("%wd iter done %wd expired; ave. error %.4e +- %.4e, range %.4e %.4e", - 1 + iter, n_expired, ave_error, rms_error, min_error, max_error); - - { - test_timing_wheel_tmp_t *fs, *f; - f64 total_fraction; - - fs = 0; - for (i = 0; i < vec_len (error_hist); i++) - { - if (error_hist[i] == 0) - continue; - vec_add2 (fs, f, 1); - f->dt = - (((i64) zvec_unsigned_to_signed (i) << w->log2_clocks_per_bin) * - tm->time.seconds_per_clock); - f->fraction = (f64) error_hist[i] / (f64) n_expired; - f->count = error_hist[i]; - } - - vec_sort_with_function (fs, test_timing_wheel_tmp_cmp); - - total_fraction = 0; - vec_foreach (f, fs) - { - total_fraction += f->fraction; - if (f == fs) - fformat (stdout, "%=12s %=16s %=16s %s\n", "Error max", "Fraction", - "Total", "Count"); - fformat (stdout, "%12.4e %16.4f%% %16.4f%% %Ld\n", f->dt, - f->fraction * 100, total_fraction * 100, f->count); - } - } - - clib_warning ("%U", format_timing_wheel, w, /* verbose */ 1); - } - -done: - return error; -} - -#ifdef CLIB_UNIX -int -main (int argc, char *argv[]) -{ - unformat_input_t i; - clib_error_t *error; - - unformat_init_command_line (&i, argv); - error = test_timing_wheel_main (&i); - unformat_free (&i); - if (error) - { - clib_error_report (error); - return 1; - } - else - return 0; -} -#endif /* CLIB_UNIX */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/test_vec.c b/vppinfra/vppinfra/test_vec.c deleted file mode 100644 index f0497ac640e..00000000000 --- a/vppinfra/vppinfra/test_vec.c +++ /dev/null @@ -1,1159 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus - Written by Fred Delley <fdelley@cisco.com> . - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifdef CLIB_LINUX_KERNEL -#include <linux/unistd.h> -#endif - -#ifdef CLIB_UNIX -#include <unistd.h> -#include <stdlib.h> -#include <stdio.h> -#endif - -#include <vppinfra/clib.h> -#include <vppinfra/mheap.h> -#include <vppinfra/format.h> -#include <vppinfra/error.h> -#include <vppinfra/random.h> -#include <vppinfra/time.h> - -#include "test_vec.h" - -static int verbose; -#define if_verbose(format,args...) \ - if (verbose) { clib_warning(format, ## args); } - -#define MAX_CHANGE 100 - - -typedef enum -{ - /* Values have to be sequential and start with 0. */ - OP_IS_VEC_RESIZE = 0, - OP_IS_VEC_ADD1, - OP_IS_VEC_ADD2, - OP_IS_VEC_ADD, - OP_IS_VEC_INSERT, - OP_IS_VEC_INSERT_ELTS, - OP_IS_VEC_DELETE, - OP_IS_VEC_DUP, - OP_IS_VEC_IS_EQUAL, - OP_IS_VEC_ZERO, - OP_IS_VEC_SET, - OP_IS_VEC_VALIDATE, - OP_IS_VEC_FREE, - OP_IS_VEC_INIT, - OP_IS_VEC_CLONE, - OP_IS_VEC_APPEND, - OP_IS_VEC_PREPEND, - /* Operations on vectors with custom headers. */ - OP_IS_VEC_INIT_H, - OP_IS_VEC_RESIZE_H, - OP_IS_VEC_FREE_H, - OP_MAX, -} op_t; - -#define FIRST_VEC_OP OP_IS_VEC_RESIZE -#define LAST_VEC_OP OP_IS_VEC_PREPEND -#define FIRST_VEC_HDR_OP OP_IS_VEC_INIT_H -#define LAST_VEC_HDR_OP OP_IS_VEC_FREE_H - -uword g_prob_ratio[] = { - [OP_IS_VEC_RESIZE] = 5, - [OP_IS_VEC_ADD1] = 5, - [OP_IS_VEC_ADD2] = 5, - [OP_IS_VEC_ADD] = 5, - [OP_IS_VEC_INSERT] = 5, - [OP_IS_VEC_INSERT_ELTS] = 5, - [OP_IS_VEC_DELETE] = 30, - [OP_IS_VEC_DUP] = 5, - [OP_IS_VEC_IS_EQUAL] = 5, - [OP_IS_VEC_ZERO] = 2, - [OP_IS_VEC_SET] = 3, - [OP_IS_VEC_VALIDATE] = 5, - [OP_IS_VEC_FREE] = 5, - [OP_IS_VEC_INIT] = 5, - [OP_IS_VEC_CLONE] = 5, - [OP_IS_VEC_APPEND] = 5, - [OP_IS_VEC_PREPEND] = 5, - /* Operations on vectors with custom headers. */ - [OP_IS_VEC_INIT_H] = 5, - [OP_IS_VEC_RESIZE_H] = 5, - [OP_IS_VEC_FREE_H] = 5, -}; - -op_t *g_prob; -op_t *g_prob_wh; - -uword g_call_stats[OP_MAX]; - - -/* A structure for both vector headers and vector elements might be useful to - uncover potential alignement issues. */ - -typedef struct -{ - u8 field1[4]; - CLIB_PACKED (u32 field2); -} hdr_t; - -typedef struct -{ - u8 field1[3]; - CLIB_PACKED (u32 field2); -} elt_t; - -#ifdef CLIB_UNIX -u32 g_seed = 0xdeadbabe; -uword g_verbose = 1; -#endif - -op_t *g_op_prob; -uword g_set_verbose_at = ~0; -uword g_dump_period = ~0; - - -static u8 * -format_vec_op_type (u8 * s, va_list * args) -{ - op_t op = va_arg (*args, int); - - switch (op) - { -#define _(n) \ - case OP_IS_##n: \ - s = format (s, "OP_IS_" #n); \ - break; - - _(VEC_RESIZE); - _(VEC_ADD1); - _(VEC_ADD2); - _(VEC_ADD); - _(VEC_INSERT); - _(VEC_INSERT_ELTS); - _(VEC_DELETE); - _(VEC_DUP); - _(VEC_IS_EQUAL); - _(VEC_ZERO); - _(VEC_SET); - _(VEC_VALIDATE); - _(VEC_FREE); - _(VEC_INIT); - _(VEC_CLONE); - _(VEC_APPEND); - _(VEC_PREPEND); - _(VEC_INIT_H); - _(VEC_RESIZE_H); - _(VEC_FREE_H); - - default: - s = format (s, "Unknown vec op (%d)", op); - break; - } - -#undef _ - - return s; -} - -static void -dump_call_stats (uword * stats) -{ - uword i; - - fformat (stdout, "Call Stats\n----------\n"); - - for (i = 0; i < OP_MAX; i++) - fformat (stdout, "%-8d %U\n", stats[i], format_vec_op_type, i); -} - - -/* XXX - Purposely low value for debugging the validator. Will be set it to a - more sensible value later. */ -#define MAX_VEC_LEN 10 - -#define create_random_vec_wh(elt_type, len, hdr_bytes, seed) \ -({ \ - elt_type * _v(v) = NULL; \ - uword _v(l) = (len); \ - uword _v(h) = (hdr_bytes); \ - u8 * _v(hdr); \ - \ - if (_v(l) == 0) \ - goto __done__; \ - \ - /* ~0 means select random length between 0 and MAX_VEC_LEN. */ \ - if (_v(l) == ~0) \ - _v(l) = bounded_random_u32 (&(seed), 0, MAX_VEC_LEN); \ - \ - _v(v) = _vec_resize (NULL, _v(l), _v(l) * sizeof (elt_type), _v(h), 0); \ - fill_with_random_data (_v(v), vec_bytes (_v(v)), (seed)); \ - \ - /* Fill header with random data as well. */ \ - if (_v(h) > 0) \ - { \ - _v(hdr) = vec_header (_v(v), _v(h)); \ - fill_with_random_data (_v(hdr), _v(h), (seed)); \ - } \ - \ -__done__: \ - _v(v); \ -}) - -#define create_random_vec(elt_type, len, seed) \ -create_random_vec_wh (elt_type, len, 0, seed) - -#define compute_vec_hash(hash, vec) \ -({ \ - u8 * _v(v) = (u8 *) (vec); \ - uword _v(n) = vec_len (vec) * sizeof ((vec)[0]); \ - u8 _v(hh) = (u8) (hash); \ - \ - compute_mem_hash (_v(hh), _v(v), _v(n)); \ -}) - -static elt_t * -validate_vec_free (elt_t * vec) -{ - vec_free (vec); - ASSERT (vec == NULL); - return vec; -} - -static elt_t * -validate_vec_free_h (elt_t * vec, uword hdr_bytes) -{ - vec_free_h (vec, hdr_bytes); - ASSERT (vec == NULL); - return vec; -} - -static void -validate_vec_hdr (elt_t * vec, uword hdr_bytes) -{ - u8 *hdr; - u8 *hdr_end; - vec_header_t *vh; - - if (!vec) - return; - - vh = _vec_find (vec); - hdr = vec_header (vec, hdr_bytes); - hdr_end = vec_header_end (hdr, hdr_bytes); - - ASSERT (hdr_end == (u8 *) vec); - ASSERT ((u8 *) vh - (u8 *) hdr >= hdr_bytes); -} - -static void -validate_vec_len (elt_t * vec) -{ - u8 *ptr; - u8 *end; - uword len; - uword bytes; - uword i; - elt_t *elt; - - if (!vec) - return; - - ptr = (u8 *) vec; - end = (u8 *) vec_end (vec); - len = vec_len (vec); - bytes = sizeof (vec[0]) * len; - - ASSERT (bytes == vec_bytes (vec)); - ASSERT ((ptr + bytes) == end); - - i = 0; - - /* XXX - TODO: confirm that auto-incrementing in vec_is_member() would not - have the expected result. */ - while (vec_is_member (vec, (__typeof__ (vec[0]) *) ptr)) - { - ptr++; - i++; - } - - ASSERT (ptr == end); - ASSERT (i == bytes); - - i = 0; - - vec_foreach (elt, vec) i++; - - ASSERT (i == len); -} - -static void -validate_vec (elt_t * vec, uword hdr_bytes) -{ - validate_vec_hdr (vec, hdr_bytes); - validate_vec_len (vec); - - if (!vec || vec_len (vec) == 0) - { - VERBOSE3 ("Vector at %p has zero elements.\n\n", vec); - } - else - { - if (hdr_bytes > 0) - VERBOSE3 ("Header: %U\n", - format_hex_bytes, vec_header (vec, sizeof (vec[0])), - sizeof (vec[0])); - - VERBOSE3 ("%U\n\n", - format_hex_bytes, vec, vec_len (vec) * sizeof (vec[0])); - } -} - -static elt_t * -validate_vec_resize (elt_t * vec, uword num_elts) -{ - uword len1 = vec_len (vec); - uword len2; - u8 hash = compute_vec_hash (0, vec); - - vec_resize (vec, num_elts); - len2 = vec_len (vec); - - ASSERT (len2 == len1 + num_elts); - ASSERT (compute_vec_hash (hash, vec) == 0); - validate_vec (vec, 0); - return vec; -} - -static elt_t * -validate_vec_resize_h (elt_t * vec, uword num_elts, uword hdr_bytes) -{ - uword len1, len2; - u8 *end1, *end2; - u8 *hdr = NULL; - u8 hash, hdr_hash; - - len1 = vec_len (vec); - - if (vec) - hdr = vec_header (vec, hdr_bytes); - - hash = compute_vec_hash (0, vec); - hdr_hash = compute_mem_hash (0, hdr, hdr_bytes); - - vec_resize_ha (vec, num_elts, hdr_bytes, 0); - len2 = vec_len (vec); - - ASSERT (len2 == len1 + num_elts); - - end1 = (u8 *) (vec + len1); - end2 = (u8 *) vec_end (vec); - - while (end1 != end2) - { - ASSERT (*end1 == 0); - end1++; - } - - if (vec) - hdr = vec_header (vec, hdr_bytes); - - ASSERT (compute_vec_hash (hash, vec) == 0); - ASSERT (compute_mem_hash (hdr_hash, hdr, hdr_bytes) == 0); - validate_vec (vec, 1); - return vec; -} - -static elt_t * -generic_validate_vec_add (elt_t * vec, uword num_elts, uword is_add2) -{ - uword len1 = vec_len (vec); - uword len2; - u8 hash = compute_vec_hash (0, vec); - elt_t *new; - - if (is_add2) - { - vec_add2 (vec, new, num_elts); - } - else - { - new = create_random_vec (elt_t, num_elts, g_seed); - - VERBOSE3 ("%U\n", format_hex_bytes, new, - vec_len (new) * sizeof (new[0])); - - /* Add the hash value of the new elements to that of the old vector. */ - hash = compute_vec_hash (hash, new); - - if (num_elts == 1) - vec_add1 (vec, new[0]); - else if (num_elts > 1) - vec_add (vec, new, num_elts); - - vec_free (new); - } - - len2 = vec_len (vec); - ASSERT (len2 == len1 + num_elts); - - ASSERT (compute_vec_hash (hash, vec) == 0); - validate_vec (vec, 0); - return vec; -} - -static elt_t * -validate_vec_add1 (elt_t * vec) -{ - return generic_validate_vec_add (vec, 1, 0); -} - -static elt_t * -validate_vec_add2 (elt_t * vec, uword num_elts) -{ - return generic_validate_vec_add (vec, num_elts, 1); -} - -static elt_t * -validate_vec_add (elt_t * vec, uword num_elts) -{ - return generic_validate_vec_add (vec, num_elts, 0); -} - -static elt_t * -validate_vec_insert (elt_t * vec, uword num_elts, uword start_elt) -{ - uword len1 = vec_len (vec); - uword len2; - u8 hash; - - /* vec_insert() would not handle it properly. */ - if (start_elt > len1 || num_elts == 0) - return vec; - - hash = compute_vec_hash (0, vec); - vec_insert (vec, num_elts, start_elt); - len2 = vec_len (vec); - - ASSERT (len2 == len1 + num_elts); - ASSERT (compute_vec_hash (hash, vec) == 0); - validate_vec (vec, 0); - return vec; -} - -static elt_t * -validate_vec_insert_elts (elt_t * vec, uword num_elts, uword start_elt) -{ - uword len1 = vec_len (vec); - uword len2; - elt_t *new; - u8 hash; - - /* vec_insert_elts() would not handle it properly. */ - if (start_elt > len1 || num_elts == 0) - return vec; - - new = create_random_vec (elt_t, num_elts, g_seed); - - VERBOSE3 ("%U\n", format_hex_bytes, new, vec_len (new) * sizeof (new[0])); - - /* Add the hash value of the new elements to that of the old vector. */ - hash = compute_vec_hash (0, vec); - hash = compute_vec_hash (hash, new); - - vec_insert_elts (vec, new, num_elts, start_elt); - len2 = vec_len (vec); - - vec_free (new); - - ASSERT (len2 == len1 + num_elts); - ASSERT (compute_vec_hash (hash, vec) == 0); - validate_vec (vec, 0); - return vec; -} - -static elt_t * -validate_vec_delete (elt_t * vec, uword num_elts, uword start_elt) -{ - uword len1 = vec_len (vec); - uword len2; - u8 *start; - u8 hash; - u8 hash_del; - - /* vec_delete() would not handle it properly. */ - if (start_elt + num_elts > len1) - return vec; - - start = (u8 *) vec + (start_elt * sizeof (vec[0])); - - hash = compute_vec_hash (0, vec); - hash_del = compute_mem_hash (0, start, num_elts * sizeof (vec[0])); - hash ^= hash_del; - - vec_delete (vec, num_elts, start_elt); - len2 = vec_len (vec); - - ASSERT (len2 == len1 - num_elts); - ASSERT (compute_vec_hash (hash, vec) == 0); - validate_vec (vec, 0); - return vec; -} - -static elt_t * -validate_vec_dup (elt_t * vec) -{ - elt_t *new; - u8 hash; - - hash = compute_vec_hash (0, vec); - new = vec_dup (vec); - - ASSERT (compute_vec_hash (hash, new) == 0); - - validate_vec (new, 0); - return new; -} - -static elt_t * -validate_vec_zero (elt_t * vec) -{ - u8 *ptr; - u8 *end; - - vec_zero (vec); - - ptr = (u8 *) vec; - end = (u8 *) (vec + vec_len (vec)); - - while (ptr != end) - { - ASSERT (ptr < (u8 *) vec_end (vec)); - ASSERT (ptr[0] == 0); - ptr++; - } - - validate_vec (vec, 0); - return vec; -} - -static void -validate_vec_is_equal (elt_t * vec) -{ - elt_t *new = NULL; - - if (vec_len (vec) <= 0) - return; - - new = vec_dup (vec); - ASSERT (vec_is_equal (new, vec)); - vec_free (new); -} - -static elt_t * -validate_vec_set (elt_t * vec) -{ - uword i; - uword len = vec_len (vec); - elt_t *new; - - if (!vec) - return NULL; - - new = create_random_vec (elt_t, 1, g_seed); - - VERBOSE3 ("%U\n", format_hex_bytes, new, vec_len (new) * sizeof (new[0])); - - vec_set (vec, new[0]); - - for (i = 0; i < len; i++) - ASSERT (memcmp (&vec[i], &new[0], sizeof (vec[0])) == 0); - - vec_free (new); - validate_vec (vec, 0); - return vec; -} - -static elt_t * -validate_vec_validate (elt_t * vec, uword index) -{ - uword len = vec_len (vec); - word num_new = index - len + 1; - u8 *ptr; - u8 *end; - u8 hash = compute_vec_hash (0, vec); - - if (num_new < 0) - num_new = 0; - - vec_validate (vec, index); - - /* Old len but new vec pointer! */ - ptr = (u8 *) (vec + len); - end = (u8 *) (vec + len + num_new); - - ASSERT (len + num_new == vec_len (vec)); - ASSERT (compute_vec_hash (hash, vec) == 0); - - while (ptr != end) - { - ASSERT (ptr < (u8 *) vec_end (vec)); - ASSERT (ptr[0] == 0); - ptr++; - } - - validate_vec (vec, 0); - return vec; -} - -static elt_t * -validate_vec_init (uword num_elts) -{ - u8 *ptr; - u8 *end; - uword len; - elt_t *new; - - new = vec_new (elt_t, num_elts); - len = vec_len (new); - - ASSERT (len == num_elts); - - ptr = (u8 *) new; - end = (u8 *) (new + len); - - while (ptr != end) - { - ASSERT (ptr < (u8 *) vec_end (new)); - ASSERT (ptr[0] == 0); - ptr++; - } - - validate_vec (new, 0); - return new; -} - -static elt_t * -validate_vec_init_h (uword num_elts, uword hdr_bytes) -{ - uword i = 0; - u8 *ptr; - u8 *end; - uword len; - elt_t *new; - - new = vec_new_ha (elt_t, num_elts, hdr_bytes, 0); - len = vec_len (new); - - ASSERT (len == num_elts); - - /* We have 2 zero-regions to check: header & vec data (skip _VEC struct). */ - for (i = 0; i < 2; i++) - { - if (i == 0) - { - ptr = (u8 *) vec_header (new, hdr_bytes); - end = ptr + hdr_bytes; - } - else - { - ptr = (u8 *) new; - end = (u8 *) (new + len); - } - - while (ptr != end) - { - ASSERT (ptr < (u8 *) vec_end (new)); - ASSERT (ptr[0] == 0); - ptr++; - } - } - - validate_vec (new, 1); - return new; -} - -/* XXX - I don't understand the purpose of the vec_clone() call. */ -static elt_t * -validate_vec_clone (elt_t * vec) -{ - elt_t *new; - - vec_clone (new, vec); - - ASSERT (vec_len (new) == vec_len (vec)); - ASSERT (compute_vec_hash (0, new) == 0); - validate_vec (new, 0); - return new; -} - -static elt_t * -validate_vec_append (elt_t * vec) -{ - elt_t *new; - uword num_elts = bounded_random_u32 (&g_seed, 0, MAX_CHANGE); - uword len; - u8 hash = 0; - - new = create_random_vec (elt_t, num_elts, g_seed); - - len = vec_len (vec) + vec_len (new); - hash = compute_vec_hash (0, vec); - hash = compute_vec_hash (hash, new); - - vec_append (vec, new); - vec_free (new); - - ASSERT (vec_len (vec) == len); - ASSERT (compute_vec_hash (hash, vec) == 0); - validate_vec (vec, 0); - return vec; -} - -static elt_t * -validate_vec_prepend (elt_t * vec) -{ - elt_t *new; - uword num_elts = bounded_random_u32 (&g_seed, 0, MAX_CHANGE); - uword len; - u8 hash = 0; - - new = create_random_vec (elt_t, num_elts, g_seed); - - len = vec_len (vec) + vec_len (new); - hash = compute_vec_hash (0, vec); - hash = compute_vec_hash (hash, new); - - vec_prepend (vec, new); - vec_free (new); - - ASSERT (vec_len (vec) == len); - ASSERT (compute_vec_hash (hash, vec) == 0); - validate_vec (vec, 0); - return vec; -} - -static void -run_validator_wh (uword iter) -{ - elt_t *vec; - uword i; - uword op; - uword num_elts; - uword len; - uword dump_time; - f64 time[3]; /* [0]: start, [1]: last, [2]: current */ - - vec = create_random_vec_wh (elt_t, ~0, sizeof (hdr_t), g_seed); - validate_vec (vec, 0); - VERBOSE2 ("Start with len %d\n", vec_len (vec)); - - time[0] = unix_time_now (); - time[1] = time[0]; - dump_time = g_dump_period; - - for (i = 1; i <= iter; i++) - { - if (i >= g_set_verbose_at) - g_verbose = 2; - - op = bounded_random_u32 (&g_seed, 0, vec_len (g_prob_wh) - 1); - op = g_prob_wh[op]; - - switch (op) - { - case OP_IS_VEC_INIT_H: - num_elts = bounded_random_u32 (&g_seed, 0, MAX_CHANGE); - vec_free_h (vec, sizeof (hdr_t)); - VERBOSE2 ("vec_init_h(), new elts %d\n", num_elts); - vec = validate_vec_init_h (num_elts, sizeof (hdr_t)); - break; - - case OP_IS_VEC_RESIZE_H: - len = vec_len (vec); - num_elts = bounded_random_u32 (&g_seed, len, len + MAX_CHANGE); - VERBOSE2 ("vec_resize_h(), %d new elts.\n", num_elts); - vec = validate_vec_resize_h (vec, num_elts, sizeof (hdr_t)); - break; - - case OP_IS_VEC_FREE_H: - VERBOSE2 ("vec_free_h()\n"); - vec = validate_vec_free_h (vec, sizeof (hdr_t)); - break; - - default: - ASSERT (0); - break; - } - - g_call_stats[op]++; - - if (i == dump_time) - { - time[2] = unix_time_now (); - VERBOSE1 ("%d vec ops in %f secs. (last %d in %f secs.).\n", - i, time[2] - time[0], g_dump_period, time[2] - time[1]); - time[1] = time[2]; - dump_time += g_dump_period; - - VERBOSE1 ("vec len %d\n", vec_len (vec)); - VERBOSE2 ("%U\n\n", - format_hex_bytes, vec, vec_len (vec) * sizeof (vec[0])); - } - - VERBOSE2 ("len %d\n", vec_len (vec)); - } - - validate_vec (vec, sizeof (hdr_t)); - vec_free_h (vec, sizeof (hdr_t)); -} - -static void -run_validator (uword iter) -{ - elt_t *vec; - elt_t *new; - uword i; - uword op; - uword num_elts; - uword index; - uword len; - uword dump_time; - f64 time[3]; /* [0]: start, [1]: last, [2]: current */ - - vec = create_random_vec (elt_t, ~0, g_seed); - validate_vec (vec, 0); - VERBOSE2 ("Start with len %d\n", vec_len (vec)); - - time[0] = unix_time_now (); - time[1] = time[0]; - dump_time = g_dump_period; - - for (i = 1; i <= iter; i++) - { - if (i >= g_set_verbose_at) - g_verbose = 2; - - op = bounded_random_u32 (&g_seed, 0, vec_len (g_prob) - 1); - op = g_prob[op]; - - switch (op) - { - case OP_IS_VEC_RESIZE: - len = vec_len (vec); - num_elts = bounded_random_u32 (&g_seed, len, len + MAX_CHANGE); - VERBOSE2 ("vec_resize(), %d new elts.\n", num_elts); - vec = validate_vec_resize (vec, num_elts); - break; - - case OP_IS_VEC_ADD1: - VERBOSE2 ("vec_add1()\n"); - vec = validate_vec_add1 (vec); - break; - - case OP_IS_VEC_ADD2: - num_elts = bounded_random_u32 (&g_seed, 0, MAX_CHANGE); - VERBOSE2 ("vec_add2(), %d new elts.\n", num_elts); - vec = validate_vec_add2 (vec, num_elts); - break; - - case OP_IS_VEC_ADD: - num_elts = bounded_random_u32 (&g_seed, 0, MAX_CHANGE); - VERBOSE2 ("vec_add(), %d new elts.\n", num_elts); - vec = validate_vec_add (vec, num_elts); - break; - - case OP_IS_VEC_INSERT: - len = vec_len (vec); - num_elts = bounded_random_u32 (&g_seed, 0, MAX_CHANGE); - index = bounded_random_u32 (&g_seed, 0, - (len > 0) ? (len - 1) : (0)); - VERBOSE2 ("vec_insert(), %d new elts, index %d.\n", num_elts, - index); - vec = validate_vec_insert (vec, num_elts, index); - break; - - case OP_IS_VEC_INSERT_ELTS: - len = vec_len (vec); - num_elts = bounded_random_u32 (&g_seed, 0, MAX_CHANGE); - index = bounded_random_u32 (&g_seed, 0, - (len > 0) ? (len - 1) : (0)); - VERBOSE2 ("vec_insert_elts(), %d new elts, index %d.\n", - num_elts, index); - vec = validate_vec_insert_elts (vec, num_elts, index); - break; - - case OP_IS_VEC_DELETE: - len = vec_len (vec); - index = bounded_random_u32 (&g_seed, 0, len - 1); - num_elts = bounded_random_u32 (&g_seed, 0, - (len > index) ? (len - index) : (0)); - VERBOSE2 ("vec_delete(), %d elts, index %d.\n", num_elts, index); - vec = validate_vec_delete (vec, num_elts, index); - break; - - case OP_IS_VEC_DUP: - VERBOSE2 ("vec_dup()\n"); - new = validate_vec_dup (vec); - vec_free (new); - break; - - case OP_IS_VEC_IS_EQUAL: - VERBOSE2 ("vec_is_equal()\n"); - validate_vec_is_equal (vec); - break; - - case OP_IS_VEC_ZERO: - VERBOSE2 ("vec_zero()\n"); - vec = validate_vec_zero (vec); - break; - - case OP_IS_VEC_SET: - VERBOSE2 ("vec_set()\n"); - vec = validate_vec_set (vec); - break; - - case OP_IS_VEC_VALIDATE: - len = vec_len (vec); - index = bounded_random_u32 (&g_seed, 0, len - 1 + MAX_CHANGE); - VERBOSE2 ("vec_validate(), index %d\n", index); - vec = validate_vec_validate (vec, index); - break; - - case OP_IS_VEC_FREE: - VERBOSE2 ("vec_free()\n"); - vec = validate_vec_free (vec); - break; - - case OP_IS_VEC_INIT: - num_elts = bounded_random_u32 (&g_seed, 0, MAX_CHANGE); - vec_free (vec); - VERBOSE2 ("vec_init(), new elts %d\n", num_elts); - vec = validate_vec_init (num_elts); - break; - - case OP_IS_VEC_CLONE: - VERBOSE2 ("vec_clone()\n"); - new = validate_vec_clone (vec); - vec_free (new); - break; - - case OP_IS_VEC_APPEND: - VERBOSE2 ("vec_append()\n"); - vec = validate_vec_append (vec); - break; - - case OP_IS_VEC_PREPEND: - VERBOSE2 ("vec_prepend()\n"); - vec = validate_vec_prepend (vec); - break; - - default: - ASSERT (0); - break; - } - - g_call_stats[op]++; - - if (i == dump_time) - { - time[2] = unix_time_now (); - VERBOSE1 ("%d vec ops in %f secs. (last %d in %f secs.).\n", - i, time[2] - time[0], g_dump_period, time[2] - time[1]); - time[1] = time[2]; - dump_time += g_dump_period; - - VERBOSE1 ("vec len %d\n", vec_len (vec)); - VERBOSE2 ("%U\n\n", - format_hex_bytes, vec, vec_len (vec) * sizeof (vec[0])); - } - - VERBOSE2 ("len %d\n", vec_len (vec)); - } - - validate_vec (vec, 0); - vec_free (vec); -} - -static void -prob_init (void) -{ - uword i, j, ratio, len, index; - - /* Create the vector to implement the statistical profile: - vec [ op1 op1 op1 op2 op3 op3 op3 op4 op4 .... ] */ - for (i = FIRST_VEC_OP; i <= LAST_VEC_OP; i++) - { - ratio = g_prob_ratio[i]; - if (ratio <= 0) - continue; - - len = vec_len (g_prob); - index = len - 1 + ratio; - ASSERT (index >= 0); - - /* Pre-allocate new elements. */ - vec_validate (g_prob, index); - - for (j = len; j <= index; j++) - g_prob[j] = i; - } - - /* Operations on vectors with headers. */ - for (i = FIRST_VEC_HDR_OP; i <= LAST_VEC_HDR_OP; i++) - { - ratio = g_prob_ratio[i]; - if (ratio <= 0) - continue; - - len = vec_len (g_prob_wh); - index = len - 1 + ratio; - ASSERT (index >= 0); - - /* Pre-allocate new elements. */ - vec_validate (g_prob_wh, index); - - for (j = len; j <= index; j++) - g_prob_wh[j] = i; - } - - VERBOSE3 ("prob_vec, len %d\n%U\n", vec_len (g_prob), - format_hex_bytes, g_prob, vec_len (g_prob) * sizeof (g_prob[0])); - VERBOSE3 ("prob_vec_wh, len %d\n%U\n", vec_len (g_prob_wh), - format_hex_bytes, g_prob_wh, - vec_len (g_prob_wh) * sizeof (g_prob_wh[0])); -} - -static void -prob_free (void) -{ - vec_free (g_prob); - vec_free (g_prob_wh); -} - -int -test_vec_main (unformat_input_t * input) -{ - uword iter = 1000; - uword help = 0; - uword big = 0; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (0 == unformat (input, "iter %d", &iter) - && 0 == unformat (input, "seed %d", &g_seed) - && 0 == unformat (input, "verbose %d", &g_verbose) - && 0 == unformat (input, "set %d", &g_set_verbose_at) - && 0 == unformat (input, "dump %d", &g_dump_period) - && 0 == unformat (input, "help %=", &help, 1) - && 0 == unformat (input, "big %=", &big, 1)) - { - clib_error ("unknown input `%U'", format_unformat_error, input); - goto usage; - } - } - - if (big) - { - u8 *bigboy = 0; - u64 one_gig = (1 << 30); - u64 size; - u64 index; - - fformat (stdout, "giant vector test..."); - size = 5ULL * one_gig; - - vec_validate (bigboy, size); - - for (index = size; index >= 0; index--) - bigboy[index] = index & 0xff; - return 0; - } - - - if (help) - goto usage; - - prob_init (); - run_validator (iter); - run_validator_wh (iter); - if (verbose) - dump_call_stats (g_call_stats); - prob_free (); - - if (verbose) - { - memory_snap (); - } - return 0; - -usage: - fformat (stdout, "Usage: test_vec iter <N> seed <N> verbose <N> " - "set <N> dump <N>\n"); - if (help) - return 0; - - return -1; -} - -#ifdef CLIB_UNIX -int -main (int argc, char *argv[]) -{ - unformat_input_t i; - int ret; - - mheap_alloc (0, (uword) 10ULL << 30); - - verbose = (argc > 1); - unformat_init_command_line (&i, argv); - ret = test_vec_main (&i); - unformat_free (&i); - - return ret; -} -#endif /* CLIB_UNIX */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/test_vec.h b/vppinfra/vppinfra/test_vec.h deleted file mode 100644 index 28e8e2a081d..00000000000 --- a/vppinfra/vppinfra/test_vec.h +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_test_vec_h -#define included_test_vec_h - - -#include <vppinfra/clib.h> -#include <vppinfra/mem.h> -#include <vppinfra/format.h> -#include <vppinfra/error.h> - - -extern uword g_verbose; -extern u32 g_seed; - -always_inline u8 * -format_u32_binary (u8 * s, va_list * va) -{ - u32 val = va_arg (*va, u32); - word i = 0; - - for (i = BITS (val) - 1; i >= 0; i--) - { - if (val & (1 << i)) - s = format (s, "1"); - else - s = format (s, "0"); - } - - return s; -} - -#define VERBOSE1(fmt, args...) \ -do { \ - if (g_verbose >= 1) \ - fformat (stdout, fmt, ## args); \ -} while (0) - -#define VERBOSE2(fmt, args...) \ -do { \ - if (g_verbose >= 2) \ - fformat (stdout, fmt, ## args); \ -} while (0) - -#define VERBOSE3(fmt, args...) \ -do { \ - if (g_verbose >= 3) \ - fformat (stdout, fmt, ## args); \ -} while (0) - -#define clib_mem_free_safe(p) \ -do { \ - if (p) \ - { \ - clib_mem_free (p); \ - (p) = NULL; \ - } \ -} while (0) - -/* XXX - I get undefined symbol trying to call random_u32() <vppinfra/random.h> */ -/* Simple random number generator with period 2^31 - 1. */ -static u32 -my_random_u32 (u32 * seed_return) -{ - /* Unlikely mask value to XOR into seed. - Otherwise small seed values would give - non-random seeming smallish numbers. */ - const u32 mask = 0x12345678; - u32 seed, a, b, result; - - seed = *seed_return; - seed ^= mask; - - a = seed / 127773; - b = seed % 127773; - seed = 16807 * b - 2836 * a; - - if ((i32) seed < 0) - seed += ((u32) 1 << 31) - 1; - - result = seed; - - *seed_return = seed ^ mask; - - return result; -} - -static u32 -bounded_random_u32 (u32 * seed, uword lo, uword hi) -{ - if (lo == hi) - return lo; - - ASSERT (lo < hi); - - return ((my_random_u32 (seed) % (hi - lo + ((hi != ~0) ? (1) : (0)))) + lo); -} - -#define fill_with_random_data(ptr, bytes, seed) \ -do { \ - u8 * _v(p) = (u8 *) (ptr); \ - uword _v(b) = (bytes); \ - uword _v(i); \ - \ - for (_v(i) = 0; _v(i) < _v(b); _v(i)++) \ - _v(p)[_v(i)] = (u8) bounded_random_u32 (&(seed), 0, 255); \ - \ -} while (0) - -#define compute_mem_hash(hash, ptr, bytes) \ -({ \ - u8 * _v(p) = (u8 *) (ptr); \ - uword _v(b) = (uword) (bytes); \ - uword _v(i); \ - uword _v(h) = (u8) (hash); \ - \ - if (_v(p) && _v(b) > 0) \ - { \ - for (_v(i) = 0; _v(i) < _v(b); _v(i)++) \ - _v(h) ^= _v(p)[_v(i)]; \ - } \ - \ - _v(h); \ -}) - -#define log2_align_down(value, align) \ -({ \ - uword _v = (uword) (value); \ - uword _a = (uword) (align); \ - uword _m = (1 << _a) - 1; \ - \ - _v = _v & ~_m; \ -}) - -#define log2_align_up(value, align) \ -({ \ - uword _v = (uword) (value); \ - uword _a = (uword) (align); \ - uword _m = (1 << _a) - 1; \ - \ - _v = (_v + _m) & ~_m; \ -}) - -#define log2_align_ptr_down(ptr, align) \ -uword_to_pointer (log2_align_down (pointer_to_uword (ptr), align), void *) - -#define log2_align_ptr_up(ptr, align) \ -uword_to_pointer (log2_align_up (pointer_to_uword (ptr), align), void *) - -#define MAX_LOG2_ALIGN 6 -#define MAX_UNALIGN_OFFSET ((1 << MAX_LOG2_ALIGN) - 1) - -/* Allocates pointer to memory whose address is: - addr = <log2_align>-aligned address */ -always_inline void * -alloc_aligned (uword size, uword log2_align, void **ptr_to_free) -{ - void *p; - - if (size <= 0) - return NULL; - - p = (void *) clib_mem_alloc (size + (1 << log2_align) - 1); - - if (ptr_to_free) - *ptr_to_free = p; - - return (p) ? log2_align_ptr_up (p, log2_align) : (NULL); -} - -/* Allocates pointer to memory whose address is: - addr = MAX_LOG2_ALIGN-aligned address + <offset> */ -always_inline void * -alloc_unaligned (uword size, uword offset, void **ptr_to_free) -{ - void *p; - - if (size <= 0) - return NULL; - - ASSERT (offset <= MAX_UNALIGN_OFFSET); - - p = - alloc_aligned (size + (1 << MAX_LOG2_ALIGN), MAX_LOG2_ALIGN, ptr_to_free); - - if (!p) - return NULL; - - return (void *) ((u8 *) p + (offset % MAX_UNALIGN_OFFSET)); -} - -#define memory_snap() \ -do { \ - clib_mem_usage_t _usage = { 0 }; \ - clib_mem_usage (&_usage); \ - fformat (stdout, "%U\n", format_clib_mem_usage, _usage, 0); \ -} while (0) - - -#endif /* included_test_vec_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/test_vhash.c b/vppinfra/vppinfra/test_vhash.c deleted file mode 100644 index 7293fdde86e..00000000000 --- a/vppinfra/vppinfra/test_vhash.c +++ /dev/null @@ -1,757 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2010 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#if 0 -#ifdef __OPTIMIZE__ -#undef CLIB_DEBUG -#endif -#endif - -#include <vppinfra/bitmap.h> -#include <vppinfra/error.h> -#include <vppinfra/os.h> -#include <vppinfra/random.h> -#include <vppinfra/time.h> -#include <vppinfra/vhash.h> - -#ifdef CLIB_HAVE_VEC128 - -typedef struct -{ - u32 n_iter; - u32 seed; - u32 verbose; - u32 n_keys; - u32 log2_size; - u32 n_key_u32; - - u32 n_vectors_div_4; - u32 n_vectors_mod_4; - - u32 *keys; - u32 *results; - - u32 *vhash_get_key_indices; - u32 *vhash_get_results; - - u32 *vhash_key_indices; - u32 *vhash_results; - - vhash_t vhash; - - uword **key_hash; - - struct - { - u64 n_clocks; - u64 n_vectors; - u64 n_calls; - } get_stats, set_stats, unset_stats; -} test_vhash_main_t; - -always_inline u32 -test_vhash_key_gather (void *_tm, u32 vi, u32 wi, u32 n_key_u32s) -{ - test_vhash_main_t *tm = _tm; - ASSERT (n_key_u32s == tm->n_key_u32); - ASSERT (wi < n_key_u32s); - vi = vec_elt (tm->vhash_key_indices, vi); - return vec_elt (tm->keys, vi * n_key_u32s + wi); -} - -always_inline u32x4 -test_vhash_4key_gather (void *_tm, u32 vi, u32 wi, u32 n_key_u32s) -{ - test_vhash_main_t *tm = _tm; - u32 *p; - u32x4_union_t x; - - ASSERT (n_key_u32s == tm->n_key_u32); - ASSERT (wi < n_key_u32s); - - p = vec_elt_at_index (tm->vhash_key_indices, vi + 0); - x.as_u32[0] = tm->keys[p[0] * n_key_u32s + wi]; - x.as_u32[1] = tm->keys[p[1] * n_key_u32s + wi]; - x.as_u32[2] = tm->keys[p[2] * n_key_u32s + wi]; - x.as_u32[3] = tm->keys[p[3] * n_key_u32s + wi]; - return x.as_u32x4; -} - -always_inline u32 -test_vhash_get_result (void *_tm, - u32 vector_index, u32 result_index, u32 n_key_u32s) -{ - test_vhash_main_t *tm = _tm; - u32 *p = vec_elt_at_index (tm->vhash_results, vector_index); - p[0] = result_index; - return result_index; -} - -always_inline u32x4 -test_vhash_get_4result (void *_tm, - u32 vector_index, u32x4 results, u32 n_key_u32s) -{ - test_vhash_main_t *tm = _tm; - u32 *p = vec_elt_at_index (tm->vhash_results, vector_index); - *(u32x4 *) p = results; - return results; -} - -always_inline u32 -test_vhash_set_result (void *_tm, - u32 vector_index, u32 old_result, u32 n_key_u32s) -{ - test_vhash_main_t *tm = _tm; - u32 *p = vec_elt_at_index (tm->vhash_results, vector_index); - u32 new_result = p[0]; - p[0] = old_result; - return new_result; -} - -always_inline u32 -test_vhash_unset_result (void *_tm, u32 i, u32 old_result, u32 n_key_u32s) -{ - test_vhash_main_t *tm = _tm; - u32 *p = vec_elt_at_index (tm->vhash_results, i); - p[0] = old_result; - return 0; -} - -#define _(N_KEY_U32) \ - always_inline u32 \ - test_vhash_key_gather_##N_KEY_U32 (void * _tm, u32 vi, u32 i) \ - { return test_vhash_key_gather (_tm, vi, i, N_KEY_U32); } \ - \ - always_inline u32x4 \ - test_vhash_key_gather_4_##N_KEY_U32 (void * _tm, u32 vi, u32 i) \ - { return test_vhash_4key_gather (_tm, vi, i, N_KEY_U32); } \ - \ - clib_pipeline_stage \ - (test_vhash_gather_keys_stage_##N_KEY_U32, \ - test_vhash_main_t *, tm, i, \ - { \ - vhash_gather_4key_stage \ - (&tm->vhash, \ - /* vector_index */ i, \ - test_vhash_key_gather_4_##N_KEY_U32, \ - tm, \ - N_KEY_U32); \ - }) \ - \ - clib_pipeline_stage_no_inline \ - (test_vhash_gather_keys_mod_stage_##N_KEY_U32, \ - test_vhash_main_t *, tm, i, \ - { \ - vhash_gather_key_stage \ - (&tm->vhash, \ - /* vector_index */ tm->n_vectors_div_4, \ - /* n_vectors */ tm->n_vectors_mod_4, \ - test_vhash_key_gather_##N_KEY_U32, \ - tm, \ - N_KEY_U32); \ - }) \ - \ - clib_pipeline_stage \ - (test_vhash_hash_finalize_stage_##N_KEY_U32, \ - test_vhash_main_t *, tm, i, \ - { \ - vhash_finalize_stage (&tm->vhash, i, N_KEY_U32); \ - }) \ - \ - clib_pipeline_stage_no_inline \ - (test_vhash_hash_finalize_mod_stage_##N_KEY_U32, \ - test_vhash_main_t *, tm, i, \ - { \ - vhash_finalize_stage (&tm->vhash, tm->n_vectors_div_4, N_KEY_U32); \ - }) \ - \ - clib_pipeline_stage \ - (test_vhash_get_stage_##N_KEY_U32, \ - test_vhash_main_t *, tm, i, \ - { \ - vhash_get_4_stage (&tm->vhash, \ - /* vector_index */ i, \ - test_vhash_get_4result, \ - tm, N_KEY_U32); \ - }) \ - \ - clib_pipeline_stage_no_inline \ - (test_vhash_get_mod_stage_##N_KEY_U32, \ - test_vhash_main_t *, tm, i, \ - { \ - vhash_get_stage (&tm->vhash, \ - /* vector_index */ tm->n_vectors_div_4, \ - /* n_vectors */ tm->n_vectors_mod_4, \ - test_vhash_get_result, \ - tm, N_KEY_U32); \ - }) \ - \ - clib_pipeline_stage \ - (test_vhash_set_stage_##N_KEY_U32, \ - test_vhash_main_t *, tm, i, \ - { \ - vhash_set_stage (&tm->vhash, \ - /* vector_index */ i, \ - /* n_vectors */ VECTOR_WORD_TYPE_LEN (u32), \ - test_vhash_set_result, \ - tm, N_KEY_U32); \ - }) \ - \ - clib_pipeline_stage_no_inline \ - (test_vhash_set_mod_stage_##N_KEY_U32, \ - test_vhash_main_t *, tm, i, \ - { \ - vhash_set_stage (&tm->vhash, \ - /* vector_index */ tm->n_vectors_div_4, \ - /* n_vectors */ tm->n_vectors_mod_4, \ - test_vhash_set_result, \ - tm, N_KEY_U32); \ - }) \ - \ - clib_pipeline_stage \ - (test_vhash_unset_stage_##N_KEY_U32, \ - test_vhash_main_t *, tm, i, \ - { \ - vhash_unset_stage (&tm->vhash, \ - /* vector_index */ i, \ - /* n_vectors */ VECTOR_WORD_TYPE_LEN (u32), \ - test_vhash_unset_result, \ - tm, N_KEY_U32); \ - }) \ - \ - clib_pipeline_stage_no_inline \ - (test_vhash_unset_mod_stage_##N_KEY_U32, \ - test_vhash_main_t *, tm, i, \ - { \ - vhash_unset_stage (&tm->vhash, \ - /* vector_index */ tm->n_vectors_div_4, \ - /* n_vectors */ tm->n_vectors_mod_4, \ - test_vhash_unset_result, \ - tm, N_KEY_U32); \ - }) - -_(1); -_(2); -_(3); -_(4); -_(5); -_(6); - -#undef _ - -#define _(N_KEY_U32) \ - clib_pipeline_stage \ - (test_vhash_hash_mix_stage_##N_KEY_U32, \ - test_vhash_main_t *, tm, i, \ - { \ - vhash_mix_stage (&tm->vhash, i, N_KEY_U32); \ - }) \ - \ - clib_pipeline_stage_no_inline \ - (test_vhash_hash_mix_mod_stage_##N_KEY_U32, \ - test_vhash_main_t *, tm, i, \ - { \ - vhash_mix_stage (&tm->vhash, tm->n_vectors_div_4, N_KEY_U32); \ - }) - -_(4); -_(5); -_(6); - -#undef _ - -typedef enum -{ - GET, SET, UNSET, -} test_vhash_op_t; - -static void -test_vhash_op (test_vhash_main_t * tm, - u32 * key_indices, - u32 * results, uword n_keys, test_vhash_op_t op) -{ - vhash_validate_sizes (&tm->vhash, tm->n_key_u32, n_keys); - - tm->vhash_results = results; - tm->vhash_key_indices = key_indices; - tm->n_vectors_div_4 = n_keys / 4; - tm->n_vectors_mod_4 = n_keys % 4; - - if (tm->n_vectors_div_4 > 0) - { - switch (tm->n_key_u32) - { - default: - ASSERT (0); - break; - -#define _(N_KEY_U32) \ - case N_KEY_U32: \ - if (op == GET) \ - clib_pipeline_run_3_stage \ - (tm->n_vectors_div_4, \ - tm, \ - test_vhash_gather_keys_stage_##N_KEY_U32, \ - test_vhash_hash_finalize_stage_##N_KEY_U32, \ - test_vhash_get_stage_##N_KEY_U32); \ - else if (op == SET) \ - clib_pipeline_run_3_stage \ - (tm->n_vectors_div_4, \ - tm, \ - test_vhash_gather_keys_stage_##N_KEY_U32, \ - test_vhash_hash_finalize_stage_##N_KEY_U32, \ - test_vhash_set_stage_##N_KEY_U32); \ - else \ - clib_pipeline_run_3_stage \ - (tm->n_vectors_div_4, \ - tm, \ - test_vhash_gather_keys_stage_##N_KEY_U32, \ - test_vhash_hash_finalize_stage_##N_KEY_U32, \ - test_vhash_unset_stage_##N_KEY_U32); \ - break; - - _(1); - _(2); - _(3); - -#undef _ - -#define _(N_KEY_U32) \ - case N_KEY_U32: \ - if (op == GET) \ - clib_pipeline_run_4_stage \ - (tm->n_vectors_div_4, \ - tm, \ - test_vhash_gather_keys_stage_##N_KEY_U32, \ - test_vhash_hash_mix_stage_##N_KEY_U32, \ - test_vhash_hash_finalize_stage_##N_KEY_U32, \ - test_vhash_get_stage_##N_KEY_U32); \ - else if (op == SET) \ - clib_pipeline_run_4_stage \ - (tm->n_vectors_div_4, \ - tm, \ - test_vhash_gather_keys_stage_##N_KEY_U32, \ - test_vhash_hash_mix_stage_##N_KEY_U32, \ - test_vhash_hash_finalize_stage_##N_KEY_U32, \ - test_vhash_set_stage_##N_KEY_U32); \ - else \ - clib_pipeline_run_4_stage \ - (tm->n_vectors_div_4, \ - tm, \ - test_vhash_gather_keys_stage_##N_KEY_U32, \ - test_vhash_hash_mix_stage_##N_KEY_U32, \ - test_vhash_hash_finalize_stage_##N_KEY_U32, \ - test_vhash_unset_stage_##N_KEY_U32); \ - break; - - _(4); - _(5); - _(6); - -#undef _ - } - } - - - if (tm->n_vectors_mod_4 > 0) - { - switch (tm->n_key_u32) - { - default: - ASSERT (0); - break; - -#define _(N_KEY_U32) \ - case N_KEY_U32: \ - if (op == GET) \ - clib_pipeline_run_3_stage \ - (1, \ - tm, \ - test_vhash_gather_keys_mod_stage_##N_KEY_U32, \ - test_vhash_hash_finalize_mod_stage_##N_KEY_U32, \ - test_vhash_get_mod_stage_##N_KEY_U32); \ - else if (op == SET) \ - clib_pipeline_run_3_stage \ - (1, \ - tm, \ - test_vhash_gather_keys_mod_stage_##N_KEY_U32, \ - test_vhash_hash_finalize_mod_stage_##N_KEY_U32, \ - test_vhash_set_mod_stage_##N_KEY_U32); \ - else \ - clib_pipeline_run_3_stage \ - (1, \ - tm, \ - test_vhash_gather_keys_mod_stage_##N_KEY_U32, \ - test_vhash_hash_finalize_mod_stage_##N_KEY_U32, \ - test_vhash_unset_mod_stage_##N_KEY_U32); \ - break; - - _(1); - _(2); - _(3); - -#undef _ - -#define _(N_KEY_U32) \ - case N_KEY_U32: \ - if (op == GET) \ - clib_pipeline_run_4_stage \ - (1, \ - tm, \ - test_vhash_gather_keys_mod_stage_##N_KEY_U32, \ - test_vhash_hash_mix_mod_stage_##N_KEY_U32, \ - test_vhash_hash_finalize_mod_stage_##N_KEY_U32, \ - test_vhash_get_mod_stage_##N_KEY_U32); \ - else if (op == SET) \ - clib_pipeline_run_4_stage \ - (1, \ - tm, \ - test_vhash_gather_keys_mod_stage_##N_KEY_U32, \ - test_vhash_hash_mix_mod_stage_##N_KEY_U32, \ - test_vhash_hash_finalize_mod_stage_##N_KEY_U32, \ - test_vhash_set_mod_stage_##N_KEY_U32); \ - else \ - clib_pipeline_run_4_stage \ - (1, \ - tm, \ - test_vhash_gather_keys_mod_stage_##N_KEY_U32, \ - test_vhash_hash_mix_mod_stage_##N_KEY_U32, \ - test_vhash_hash_finalize_mod_stage_##N_KEY_U32, \ - test_vhash_unset_mod_stage_##N_KEY_U32); \ - break; - - _(4); - _(5); - _(6); - -#undef _ - } - } -} - -int -test_vhash_main (unformat_input_t * input) -{ - clib_error_t *error = 0; - test_vhash_main_t _tm, *tm = &_tm; - vhash_t *vh = &tm->vhash; - uword i, j; - - memset (tm, 0, sizeof (tm[0])); - tm->n_iter = 100; - tm->seed = 1; - tm->n_keys = 1; - tm->n_key_u32 = 1; - tm->log2_size = 8; - tm->verbose = 0; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "iter %d", &tm->n_iter)) - ; - else if (unformat (input, "seed %d", &tm->seed)) - ; - else if (unformat (input, "n-keys %d", &tm->n_keys)) - ; - else if (unformat (input, "log2-size %d", &tm->log2_size)) - ; - else if (unformat (input, "key-words %d", &tm->n_key_u32)) - ; - else if (unformat (input, "verbose %=", &tm->verbose, 1)) - ; - else - { - error = clib_error_create ("unknown input `%U'\n", - format_unformat_error, input); - goto done; - } - } - - if (tm->seed == 0) - tm->seed = random_default_seed (); - - clib_warning ("iter %d seed %d n-keys %d log2-size %d key-words %d", - tm->n_iter, tm->seed, tm->n_keys, tm->log2_size, - tm->n_key_u32); - - { - u32 seeds[3]; - seeds[0] = seeds[1] = seeds[2] = 0xdeadbeef; - vhash_init (vh, tm->log2_size, tm->n_key_u32, seeds); - } - - /* Choose unique keys. */ - vec_resize (tm->keys, tm->n_keys * tm->n_key_u32); - vec_resize (tm->key_hash, tm->n_key_u32); - for (i = j = 0; i < vec_len (tm->keys); i++, j++) - { - j = j == tm->n_key_u32 ? 0 : j; - do - { - tm->keys[i] = random_u32 (&tm->seed); - } - while (hash_get (tm->key_hash[j], tm->keys[i])); - hash_set (tm->key_hash[j], tm->keys[i], 0); - } - - vec_resize (tm->results, tm->n_keys); - for (i = 0; i < vec_len (tm->results); i++) - { - do - { - tm->results[i] = random_u32 (&tm->seed); - } - while (tm->results[i] == ~0); - } - - vec_resize_aligned (tm->vhash_get_results, tm->n_keys, - CLIB_CACHE_LINE_BYTES); - vec_clone (tm->vhash_get_key_indices, tm->results); - for (i = 0; i < vec_len (tm->vhash_get_key_indices); i++) - tm->vhash_get_key_indices[i] = i; - - { - uword *is_set_bitmap = 0; - uword *to_set_bitmap = 0; - uword *to_unset_bitmap = 0; - u32 *to_set = 0, *to_unset = 0; - u32 *to_set_results = 0, *to_unset_results = 0; - u64 t[2]; - - for (i = 0; i < tm->n_iter; i++) - { - vec_reset_length (to_set); - vec_reset_length (to_unset); - vec_reset_length (to_set_results); - vec_reset_length (to_unset_results); - - do - { - to_set_bitmap = clib_bitmap_random (to_set_bitmap, - tm->n_keys, &tm->seed); - } - while (clib_bitmap_is_zero (to_set_bitmap)); - to_unset_bitmap = clib_bitmap_dup_and (to_set_bitmap, is_set_bitmap); - to_set_bitmap = clib_bitmap_andnot (to_set_bitmap, to_unset_bitmap); - - /* *INDENT-OFF* */ - clib_bitmap_foreach (j, to_set_bitmap, ({ - vec_add1 (to_set, j); - vec_add1 (to_set_results, tm->results[j]); - })); - /* *INDENT-ON* */ - /* *INDENT-OFF* */ - clib_bitmap_foreach (j, to_unset_bitmap, ({ - vec_add1 (to_unset, j); - vec_add1 (to_unset_results, 0xdeadbeef); - })); - /* *INDENT-ON* */ - - if (vec_len (to_set) > 0) - { - t[0] = clib_cpu_time_now (); - test_vhash_op (tm, to_set, to_set_results, vec_len (to_set), SET); - t[1] = clib_cpu_time_now (); - tm->set_stats.n_clocks += t[1] - t[0]; - tm->set_stats.n_vectors += vec_len (to_set); - tm->set_stats.n_calls += 1; - is_set_bitmap = clib_bitmap_or (is_set_bitmap, to_set_bitmap); - } - - t[0] = clib_cpu_time_now (); - test_vhash_op (tm, tm->vhash_get_key_indices, - tm->vhash_get_results, - vec_len (tm->vhash_get_key_indices), GET); - t[1] = clib_cpu_time_now (); - tm->get_stats.n_clocks += t[1] - t[0]; - tm->get_stats.n_vectors += vec_len (tm->vhash_get_key_indices); - tm->get_stats.n_calls += 1; - - for (j = 0; j < vec_len (tm->vhash_get_results); j++) - { - u32 r0 = tm->vhash_get_results[j]; - u32 r1 = tm->results[j]; - if (clib_bitmap_get (is_set_bitmap, j)) - { - if (r0 != r1) - os_panic (); - } - else - { - if (r0 != ~0) - os_panic (); - } - } - - if (vh->n_elts != clib_bitmap_count_set_bits (is_set_bitmap)) - os_panic (); - - if (vec_len (to_unset) > 0) - { - t[0] = clib_cpu_time_now (); - test_vhash_op (tm, to_unset, to_unset_results, - vec_len (to_unset), UNSET); - t[1] = clib_cpu_time_now (); - tm->unset_stats.n_clocks += t[1] - t[0]; - tm->unset_stats.n_vectors += vec_len (to_unset); - tm->unset_stats.n_calls += 1; - is_set_bitmap = - clib_bitmap_andnot (is_set_bitmap, to_unset_bitmap); - } - - t[0] = clib_cpu_time_now (); - test_vhash_op (tm, tm->vhash_get_key_indices, - tm->vhash_get_results, - vec_len (tm->vhash_get_key_indices), GET); - t[1] = clib_cpu_time_now (); - tm->get_stats.n_clocks += t[1] - t[0]; - tm->get_stats.n_vectors += vec_len (tm->vhash_get_key_indices); - tm->get_stats.n_calls += 1; - - for (j = 0; j < vec_len (tm->vhash_get_results); j++) - { - u32 r0 = tm->vhash_get_results[j]; - u32 r1 = tm->results[j]; - if (clib_bitmap_get (is_set_bitmap, j)) - { - if (r0 != r1) - os_panic (); - } - else - { - if (r0 != ~0) - os_panic (); - } - } - - if (vh->n_elts != clib_bitmap_count_set_bits (is_set_bitmap)) - os_panic (); - } - - vhash_resize (vh, tm->log2_size + 1); - - test_vhash_op (tm, tm->vhash_get_key_indices, - tm->vhash_get_results, - vec_len (tm->vhash_get_key_indices), GET); - - for (j = 0; j < vec_len (tm->vhash_get_results); j++) - { - u32 r0 = tm->vhash_get_results[j]; - u32 r1 = tm->results[j]; - if (clib_bitmap_get (is_set_bitmap, j)) - { - if (r0 != r1) - os_panic (); - } - else - { - if (r0 != ~0) - os_panic (); - } - } - - if (vh->n_elts != clib_bitmap_count_set_bits (is_set_bitmap)) - os_panic (); - } - - { - clib_time_t ct; - - clib_time_init (&ct); - - clib_warning ("%.4e clocks/get %.4e gets/call %.4e gets/sec", - (f64) tm->get_stats.n_clocks / - (f64) tm->get_stats.n_vectors, - (f64) tm->get_stats.n_vectors / (f64) tm->get_stats.n_calls, - (f64) tm->get_stats.n_vectors / - (f64) (tm->get_stats.n_clocks * ct.seconds_per_clock)); - if (tm->set_stats.n_calls > 0) - clib_warning ("%.4e clocks/set %.4e sets/call %.4e sets/sec", - (f64) tm->set_stats.n_clocks / - (f64) tm->set_stats.n_vectors, - (f64) tm->set_stats.n_vectors / - (f64) tm->set_stats.n_calls, - (f64) tm->set_stats.n_vectors / - (f64) (tm->set_stats.n_clocks * ct.seconds_per_clock)); - if (tm->unset_stats.n_calls > 0) - clib_warning ("%.4e clocks/unset %.4e unsets/call %.4e unsets/sec", - (f64) tm->unset_stats.n_clocks / - (f64) tm->unset_stats.n_vectors, - (f64) tm->unset_stats.n_vectors / - (f64) tm->unset_stats.n_calls, - (f64) tm->unset_stats.n_vectors / - (f64) (tm->unset_stats.n_clocks * ct.seconds_per_clock)); - } - -done: - if (error) - clib_error_report (error); - return 0; -} - -#endif /* CLIB_HAVE_VEC128 */ - -#ifndef CLIB_HAVE_VEC128 -int -test_vhash_main (unformat_input_t * input) -{ - clib_error ("compiled without vector support"); - return 0; -} -#endif - -#ifdef CLIB_UNIX -int -main (int argc, char *argv[]) -{ - unformat_input_t i; - int r; - - unformat_init_command_line (&i, argv); - r = test_vhash_main (&i); - unformat_free (&i); - return r; -} -#endif - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/test_zvec.c b/vppinfra/vppinfra/test_zvec.c deleted file mode 100644 index 874fdefa4ad..00000000000 --- a/vppinfra/vppinfra/test_zvec.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2005 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include <vppinfra/zvec.h> -#include <vppinfra/format.h> -#include <vppinfra/random.h> - -static int verbose; -#define if_verbose(format,args...) \ - if (verbose) { clib_warning(format, ## args); } - -int -test_zvec_main (unformat_input_t * input) -{ - uword n_iterations; - uword i; - u32 seed; - - n_iterations = 1024; - seed = 0; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (0 == unformat (input, "iter %d", &n_iterations) - && 0 == unformat (input, "seed %d", &seed)) - clib_error ("unknown input `%U'", format_unformat_error, input); - } - - if_verbose ("%d iterations, seed %d\n", n_iterations, seed); - - for (i = 0; i < n_iterations; i++) - { - uword coding, data, d[2], limit, n_zdata_bits[2]; - - if (seed) - coding = random_u32 (&seed); - else - coding = i; - - limit = coding - 1; - if (limit > (1 << 16)) - limit = 1 << 16; - for (data = 0; data <= limit; data++) - { - d[0] = zvec_encode (coding, data, &n_zdata_bits[0]); - - if (coding != 0) - ASSERT ((d[0] >> n_zdata_bits[0]) == 0); - - d[1] = zvec_decode (coding, d[0], &n_zdata_bits[1]); - ASSERT (data == d[1]); - - ASSERT (n_zdata_bits[0] == n_zdata_bits[1]); - } - } - - return 0; -} - -#ifdef CLIB_UNIX -int -main (int argc, char *argv[]) -{ - unformat_input_t i; - int ret; - - verbose = (argc > 1); - unformat_init_command_line (&i, argv); - ret = test_zvec_main (&i); - unformat_free (&i); - - return ret; -} -#endif /* CLIB_UNIX */ - - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/time.c b/vppinfra/vppinfra/time.c deleted file mode 100644 index 2bdb9da4b39..00000000000 --- a/vppinfra/vppinfra/time.c +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2005 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include <vppinfra/os.h> -#include <vppinfra/time.h> -#include <vppinfra/format.h> -#include <vppinfra/cpu.h> - -#ifdef CLIB_UNIX - -#include <math.h> -#include <sys/time.h> -#include <fcntl.h> - -/* Not very accurate way of determining cpu clock frequency - for unix. Better to use /proc/cpuinfo on linux. */ -static f64 -estimate_clock_frequency (f64 sample_time) -{ - /* Round to nearest 100KHz. */ - const f64 round_to_units = 100e5; - - f64 time_now, time_start, time_limit, freq; - u64 ifreq, t[2]; - - time_start = time_now = unix_time_now (); - time_limit = time_now + sample_time; - t[0] = clib_cpu_time_now (); - while (time_now < time_limit) - time_now = unix_time_now (); - t[1] = clib_cpu_time_now (); - - freq = (t[1] - t[0]) / (time_now - time_start); - ifreq = flt_round_nearest (freq / round_to_units); - freq = ifreq * round_to_units; - - return freq; -} - -/* Fetch cpu frequency via parseing /proc/cpuinfo. - Only works for Linux. */ -static f64 -clock_frequency_from_proc_filesystem (void) -{ - f64 cpu_freq = 1e9; /* better than 40... */ - f64 ppc_timebase = 0; /* warnings be gone */ - int fd; - unformat_input_t input; - -/* $$$$ aarch64 kernel doesn't report "cpu MHz" */ -#if defined(__aarch64__) - return 0.0; -#endif - - cpu_freq = 0; - fd = open ("/proc/cpuinfo", 0); - if (fd < 0) - return cpu_freq; - - unformat_init_unix_file (&input, fd); - - ppc_timebase = 0; - while (unformat_check_input (&input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (&input, "cpu MHz : %f", &cpu_freq)) - cpu_freq *= 1e6; - else if (unformat (&input, "timebase : %f", &ppc_timebase)) - ; - else - unformat_skip_line (&input); - } - - unformat_free (&input); - - close (fd); - - /* Override CPU frequency with time base for PPC. */ - if (ppc_timebase != 0) - cpu_freq = ppc_timebase; - - return cpu_freq; -} - -/* Fetch cpu frequency via reading /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq - Only works for Linux. */ -static f64 -clock_frequency_from_sys_filesystem (void) -{ - f64 cpu_freq; - int fd; - unformat_input_t input; - - /* Time stamp always runs at max frequency. */ - cpu_freq = 0; - fd = open ("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq", 0); - if (fd < 0) - goto done; - - unformat_init_unix_file (&input, fd); - unformat (&input, "%f", &cpu_freq); - cpu_freq *= 1e3; /* measured in kHz */ - unformat_free (&input); - close (fd); -done: - return cpu_freq; -} - -f64 -os_cpu_clock_frequency (void) -{ - f64 cpu_freq; - - if (clib_cpu_supports_invariant_tsc ()) - return estimate_clock_frequency (1e-3); - - /* First try /sys version. */ - cpu_freq = clock_frequency_from_sys_filesystem (); - if (cpu_freq != 0) - return cpu_freq; - - /* Next try /proc version. */ - cpu_freq = clock_frequency_from_proc_filesystem (); - if (cpu_freq != 0) - return cpu_freq; - - /* If /proc/cpuinfo fails (e.g. not running on Linux) fall back to - gettimeofday based estimated clock frequency. */ - return estimate_clock_frequency (1e-3); -} - -#endif /* CLIB_UNIX */ - -/* Initialize time. */ -void -clib_time_init (clib_time_t * c) -{ - memset (c, 0, sizeof (c[0])); - c->clocks_per_second = os_cpu_clock_frequency (); - c->seconds_per_clock = 1 / c->clocks_per_second; - c->log2_clocks_per_second = min_log2_u64 ((u64) c->clocks_per_second); - - /* Initially verify frequency every sec */ - c->log2_clocks_per_frequency_verify = c->log2_clocks_per_second; - - c->last_verify_reference_time = unix_time_now (); - c->last_cpu_time = clib_cpu_time_now (); - c->init_cpu_time = c->last_verify_cpu_time = c->last_cpu_time; -} - -void -clib_time_verify_frequency (clib_time_t * c) -{ - f64 now_reference = unix_time_now (); - f64 dtr = now_reference - c->last_verify_reference_time; - f64 dtr_max; - u64 dtc = c->last_cpu_time - c->last_verify_cpu_time; - f64 round_units = 100e5; - - c->last_verify_cpu_time = c->last_cpu_time; - c->last_verify_reference_time = now_reference; - - /* - * Is the reported reference interval non-positive, - * or off by a factor of two - or 8 seconds - whichever is larger? - * Someone reset the clock behind our back. - */ - dtr_max = (f64) (2ULL << c->log2_clocks_per_frequency_verify) / - (f64) (1ULL << c->log2_clocks_per_second); - dtr_max = dtr_max > 8.0 ? dtr_max : 8.0; - - if (dtr <= 0.0 || dtr > dtr_max) - { - c->log2_clocks_per_frequency_verify = c->log2_clocks_per_second; - return; - } - - c->clocks_per_second = - flt_round_nearest ((f64) dtc / (dtr * round_units)) * round_units; - c->seconds_per_clock = 1 / c->clocks_per_second; - - /* Double time between verifies; max at 64 secs ~ 1 minute. */ - if (c->log2_clocks_per_frequency_verify < c->log2_clocks_per_second + 6) - c->log2_clocks_per_frequency_verify += 1; -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/time.h b/vppinfra/vppinfra/time.h deleted file mode 100644 index 3b89cf789fe..00000000000 --- a/vppinfra/vppinfra/time.h +++ /dev/null @@ -1,298 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_time_h -#define included_time_h - -#include <vppinfra/clib.h> - -typedef struct -{ - /* Total run time in clock cycles - since clib_time_init call. */ - u64 total_cpu_time; - - /* Last recorded time stamp. */ - u64 last_cpu_time; - - /* CPU clock frequency. */ - f64 clocks_per_second; - - /* 1 / cpu clock frequency: conversion factor - from clock cycles into seconds. */ - f64 seconds_per_clock; - - /* Time stamp of call to clib_time_init call. */ - u64 init_cpu_time; - - u64 last_verify_cpu_time; - - /* Same but for reference time (if present). */ - f64 last_verify_reference_time; - - u32 log2_clocks_per_second, log2_clocks_per_frequency_verify; -} clib_time_t; - -/* Return CPU time stamp as 64bit number. */ -#if defined(__x86_64__) || defined(i386) -always_inline u64 -clib_cpu_time_now (void) -{ - u32 a, d; - asm volatile ("rdtsc":"=a" (a), "=d" (d)); - return (u64) a + ((u64) d << (u64) 32); -} - -#elif defined (__powerpc64__) - -always_inline u64 -clib_cpu_time_now (void) -{ - u64 t; - asm volatile ("mftb %0":"=r" (t)); - return t; -} - -#elif defined (__SPU__) - -always_inline u64 -clib_cpu_time_now (void) -{ -#ifdef _XLC - return spu_rdch (0x8); -#else - return 0 /* __builtin_si_rdch (0x8) FIXME */ ; -#endif -} - -#elif defined (__powerpc__) - -always_inline u64 -clib_cpu_time_now (void) -{ - u32 hi1, hi2, lo; - asm volatile ("1:\n" - "mftbu %[hi1]\n" - "mftb %[lo]\n" - "mftbu %[hi2]\n" - "cmpw %[hi1],%[hi2]\n" - "bne 1b\n":[hi1] "=r" (hi1),[hi2] "=r" (hi2),[lo] "=r" (lo)); - return (u64) lo + ((u64) hi2 << (u64) 32); -} - -#elif defined (__arm__) -#if defined(__ARM_ARCH_8A__) -always_inline u64 -clib_cpu_time_now (void) /* We may run arm64 in aarch32 mode, to leverage 64bit counter */ -{ - u64 tsc; - asm volatile ("mrrc p15, 0, %Q0, %R0, c9":"=r" (tsc)); - return tsc; -} -#elif defined(__ARM_ARCH_7A__) -always_inline u64 -clib_cpu_time_now (void) -{ - u32 tsc; - asm volatile ("mrc p15, 0, %0, c9, c13, 0":"=r" (tsc)); - return (u64) tsc; -} -#else -always_inline u64 -clib_cpu_time_now (void) -{ - u32 lo; - asm volatile ("mrc p15, 0, %[lo], c15, c12, 1":[lo] "=r" (lo)); - return (u64) lo; -} -#endif - -#elif defined (__xtensa__) - -/* Stub for now. */ -always_inline u64 -clib_cpu_time_now (void) -{ - return 0; -} - -#elif defined (__TMS320C6X__) - -always_inline u64 -clib_cpu_time_now (void) -{ - u32 l, h; - - asm volatile (" dint\n" - " mvc .s2 TSCL,%0\n" - " mvc .s2 TSCH,%1\n" " rint\n":"=b" (l), "=b" (h)); - - return ((u64) h << 32) | l; -} - -#elif defined (__aarch64__) -always_inline u64 -clib_cpu_time_now (void) -{ - u64 tsc; - - /* Works on Cavium ThunderX. Other platforms: YMMV */ - asm volatile ("mrs %0, cntvct_el0":"=r" (tsc)); - - return tsc; -} - -#else -#error "don't know how to read CPU time stamp" - -#endif - -void clib_time_verify_frequency (clib_time_t * c); - -always_inline f64 -clib_time_now_internal (clib_time_t * c, u64 n) -{ - u64 l = c->last_cpu_time; - u64 t = c->total_cpu_time; - t += n - l; - c->total_cpu_time = t; - c->last_cpu_time = n; - if (PREDICT_FALSE - ((c->last_cpu_time - - c->last_verify_cpu_time) >> c->log2_clocks_per_frequency_verify)) - clib_time_verify_frequency (c); - return t * c->seconds_per_clock; -} - -always_inline f64 -clib_time_now (clib_time_t * c) -{ - return clib_time_now_internal (c, clib_cpu_time_now ()); -} - -always_inline void -clib_cpu_time_wait (u64 dt) -{ - u64 t_end = clib_cpu_time_now () + dt; - while (clib_cpu_time_now () < t_end) - ; -} - -void clib_time_init (clib_time_t * c); - -#ifdef CLIB_UNIX - -#include <time.h> -#include <sys/time.h> -#include <sys/resource.h> -#include <unistd.h> -#include <sys/syscall.h> - -/* Use 64bit floating point to represent time offset from epoch. */ -always_inline f64 -unix_time_now (void) -{ - /* clock_gettime without indirect syscall uses GLIBC wrappers which - we don't want. Just the bare metal, please. */ - struct timespec ts; - syscall (SYS_clock_gettime, CLOCK_REALTIME, &ts); - return ts.tv_sec + 1e-9 * ts.tv_nsec; -} - -/* As above but integer number of nano-seconds. */ -always_inline u64 -unix_time_now_nsec (void) -{ - struct timespec ts; - syscall (SYS_clock_gettime, CLOCK_REALTIME, &ts); - return 1e9 * ts.tv_sec + ts.tv_nsec; -} - -always_inline f64 -unix_usage_now (void) -{ - struct rusage u; - getrusage (RUSAGE_SELF, &u); - return u.ru_utime.tv_sec + 1e-6 * u.ru_utime.tv_usec - + u.ru_stime.tv_sec + 1e-6 * u.ru_stime.tv_usec; -} - -always_inline void -unix_sleep (f64 dt) -{ - struct timespec t; - t.tv_sec = dt; - t.tv_nsec = 1e9 * dt; - nanosleep (&t, 0); -} - -#else /* ! CLIB_UNIX */ - -always_inline f64 -unix_time_now (void) -{ - return 0; -} - -always_inline u64 -unix_time_now_nsec (void) -{ - return 0; -} - -always_inline f64 -unix_usage_now (void) -{ - return 0; -} - -always_inline void -unix_sleep (f64 dt) -{ -} - -#endif - -#endif /* included_time_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/timer.c b/vppinfra/vppinfra/timer.c deleted file mode 100644 index 0221cb749a1..00000000000 --- a/vppinfra/vppinfra/timer.c +++ /dev/null @@ -1,322 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include <math.h> -#include <stdlib.h> -#include <string.h> -#include <sys/param.h> - -#include <vppinfra/vec.h> -#include <vppinfra/time.h> -#include <vppinfra/timer.h> -#include <vppinfra/error.h> - -typedef struct -{ - f64 time; - timer_func_t *func; - any arg; -} timer_callback_t; - -/* Vector of currently unexpired timers. */ -static timer_callback_t *timers; - -/* Convert time from 64bit floating format to struct timeval. */ -always_inline void -f64_to_tv (f64 t, struct timeval *tv) -{ - tv->tv_sec = t; - tv->tv_usec = 1e6 * (t - tv->tv_sec); - while (tv->tv_usec >= 1000000) - { - tv->tv_usec -= 1000000; - tv->tv_sec += 1; - } -} - -/* Sort timers so that timer soonest to expire is at end. */ -static int -timer_compare (const void *_a, const void *_b) -{ - const timer_callback_t *a = _a; - const timer_callback_t *b = _b; - f64 dt = b->time - a->time; - return dt < 0 ? -1 : (dt > 0 ? +1 : 0); -} - -static inline void -sort_timers (timer_callback_t * timers) -{ - qsort (timers, vec_len (timers), sizeof (timers[0]), timer_compare); -} - -#define TIMER_SIGNAL SIGALRM - -/* Don't bother set timer if time different is less than this value. */ -/* We would like to initialize this to 0.75 / (f64) HZ, - * but HZ may not be a compile-time constant on some systems, - * so instead we do the initialization before first use. - */ -static f64 time_resolution; - -/* Interrupt handler. Call functions for all expired timers. - Set time for next timer interrupt. */ -static void -timer_interrupt (int signum) -{ - f64 now = unix_time_now (); - f64 dt; - timer_callback_t *t; - - while (1) - { - if (vec_len (timers) <= 0) - return; - - /* Consider last (earliest) timer in reverse sorted - vector of pending timers. */ - t = vec_end (timers) - 1; - - ASSERT (now >= 0 && finite (now)); - - /* Time difference between when timer goes off and now. */ - dt = t->time - now; - - /* If timer is within threshold of going off - call user's callback. */ - if (dt <= time_resolution && finite (dt)) - { - _vec_len (timers) -= 1; - (*t->func) (t->arg, -dt); - } - else - { - /* Set timer for to go off in future. */ - struct itimerval itv; - memset (&itv, 0, sizeof (itv)); - f64_to_tv (dt, &itv.it_value); - if (setitimer (ITIMER_REAL, &itv, 0) < 0) - clib_unix_error ("sititmer"); - return; - } - } -} - -void -timer_block (sigset_t * save) -{ - sigset_t block_timer; - - memset (&block_timer, 0, sizeof (block_timer)); - sigaddset (&block_timer, TIMER_SIGNAL); - sigprocmask (SIG_BLOCK, &block_timer, save); -} - -void -timer_unblock (sigset_t * save) -{ - sigprocmask (SIG_SETMASK, save, 0); -} - -/* Arrange for function to be called some time, - roughly equal to dt seconds, in the future. */ -void -timer_call (timer_func_t * func, any arg, f64 dt) -{ - timer_callback_t *t; - sigset_t save; - - /* Install signal handler on first call. */ - static word signal_installed = 0; - - if (!signal_installed) - { - struct sigaction sa; - - /* Initialize time_resolution before first call to timer_interrupt */ - time_resolution = 0.75 / (f64) HZ; - - memset (&sa, 0, sizeof (sa)); - sa.sa_handler = timer_interrupt; - - if (sigaction (TIMER_SIGNAL, &sa, 0) < 0) - clib_panic ("sigaction"); - - signal_installed = 1; - } - - timer_block (&save); - - /* Add new timer. */ - vec_add2 (timers, t, 1); - - t->time = unix_time_now () + dt; - t->func = func; - t->arg = arg; - - { - word reset_timer = vec_len (timers) == 1; - - if (_vec_len (timers) > 1) - { - reset_timer += t->time < (t - 1)->time; - sort_timers (timers); - } - - if (reset_timer) - timer_interrupt (TIMER_SIGNAL); - } - - timer_unblock (&save); -} - -#ifdef TEST - -#include <vppinfra/random.h> - -/* Compute average delay of function calls to foo. - If this is a small number over a lot of iterations we know - the code is working. */ - -static f64 ave_delay = 0; -static word ave_delay_count = 0; - -always_inline -update (f64 delay) -{ - ave_delay += delay; - ave_delay_count += 1; -} - -typedef struct -{ - f64 time_requested, time_called; -} foo_t; - -static f64 foo_base_time = 0; -static foo_t *foos = 0; - -void -foo (any arg, f64 delay) -{ - foos[arg].time_called = unix_time_now () - foo_base_time; - update (delay); -} - -typedef struct -{ - word count; - word limit; -} bar_t; - -void -bar (any arg, f64 delay) -{ - bar_t *b = (bar_t *) arg; - - fformat (stdout, "bar %d delay %g\n", b->count++, delay); - - update (delay); - if (b->count < b->limit) - timer_call (bar, arg, random_f64 ()); -} - -int -main (int argc, char *argv[]) -{ - word i, n = atoi (argv[1]); - word run_foo = argc > 2; -bar_t b = { limit:10 }; - - if (run_foo) - { - f64 time_limit; - - time_limit = atof (argv[2]); - - vec_resize (foos, n); - for (i = 0; i < n; i++) - { - foos[i].time_requested = time_limit * random_f64 (); - foos[i].time_called = 1e100; - } - - foo_base_time = unix_time_now (); - for (i = 0; i < n; i++) - timer_call (foo, i, foos[i].time_requested); - } - else - timer_call (bar, (any) & b, random_f64 ()); - - while (vec_len (timers) > 0) - sched_yield (); - - if (vec_len (foos) > 0) - { - f64 min = 1e100, max = -min; - f64 ave = 0, rms = 0; - - for (i = 0; i < n; i++) - { - f64 dt = foos[i].time_requested - foos[i].time_called; - if (dt < min) - min = dt; - if (dt > max) - max = dt; - ave += dt; - rms += dt * dt; - } - ave /= n; - rms = sqrt (rms / n - ave * ave); - fformat (stdout, "error min %g max %g ave %g +- %g\n", min, max, ave, - rms); - } - - fformat (stdout, "%d function calls, ave. timer delay %g secs\n", - ave_delay_count, ave_delay / ave_delay_count); - - return 0; -} -#endif - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/timer.h b/vppinfra/vppinfra/timer.h deleted file mode 100644 index 764103f702d..00000000000 --- a/vppinfra/vppinfra/timer.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_timer_h -#define included_timer_h - -#include <signal.h> - -typedef void (timer_func_t) (any arg, f64 delay); - -/* Arrange for function to be called after time interval (in seconds) has elapsed. */ -extern void timer_call (timer_func_t * func, any arg, f64 time_interval); - -/* Block/unblock timer interrupts. */ -extern void timer_block (sigset_t * save); -extern void timer_unblock (sigset_t * save); - -#endif /* included_timer_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/timing_wheel.c b/vppinfra/vppinfra/timing_wheel.c deleted file mode 100644 index 4c8a2c583a9..00000000000 --- a/vppinfra/vppinfra/timing_wheel.c +++ /dev/null @@ -1,750 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include <vppinfra/bitmap.h> -#include <vppinfra/hash.h> -#include <vppinfra/pool.h> -#include <vppinfra/timing_wheel.h> - -void -timing_wheel_init (timing_wheel_t * w, u64 current_cpu_time, - f64 cpu_clocks_per_second) -{ - if (w->max_sched_time <= w->min_sched_time) - { - w->min_sched_time = 1e-6; - w->max_sched_time = 1e-3; - } - - w->cpu_clocks_per_second = cpu_clocks_per_second; - w->log2_clocks_per_bin = - max_log2 (w->cpu_clocks_per_second * w->min_sched_time); - w->log2_bins_per_wheel = - max_log2 (w->cpu_clocks_per_second * w->max_sched_time); - w->log2_bins_per_wheel -= w->log2_clocks_per_bin; - w->log2_clocks_per_wheel = w->log2_bins_per_wheel + w->log2_clocks_per_bin; - w->bins_per_wheel = 1 << w->log2_bins_per_wheel; - w->bins_per_wheel_mask = w->bins_per_wheel - 1; - - w->current_time_index = current_cpu_time >> w->log2_clocks_per_bin; - - if (w->n_wheel_elt_time_bits <= 0 || - w->n_wheel_elt_time_bits >= STRUCT_BITS_OF (timing_wheel_elt_t, - cpu_time_relative_to_base)) - w->n_wheel_elt_time_bits = - STRUCT_BITS_OF (timing_wheel_elt_t, cpu_time_relative_to_base) - 1; - - w->cpu_time_base = current_cpu_time; - w->time_index_next_cpu_time_base_update - = - w->current_time_index + - ((u64) 1 << (w->n_wheel_elt_time_bits - w->log2_clocks_per_bin)); -} - -always_inline uword -get_level_and_relative_time (timing_wheel_t * w, u64 cpu_time, - uword * rtime_result) -{ - u64 dt, rtime; - uword level_index; - - dt = (cpu_time >> w->log2_clocks_per_bin); - - /* Time should always move forward. */ - ASSERT (dt >= w->current_time_index); - - dt -= w->current_time_index; - - /* Find level and offset within level. Level i has bins of size 2^((i+1)*M) */ - rtime = dt; - for (level_index = 0; (rtime >> w->log2_bins_per_wheel) != 0; level_index++) - rtime = (rtime >> w->log2_bins_per_wheel) - 1; - - /* Return offset within level and level index. */ - ASSERT (rtime < w->bins_per_wheel); - *rtime_result = rtime; - return level_index; -} - -always_inline uword -time_index_to_wheel_index (timing_wheel_t * w, uword level_index, u64 ti) -{ - return (ti >> (level_index * w->log2_bins_per_wheel)) & - w->bins_per_wheel_mask; -} - -/* Find current time on this level. */ -always_inline uword -current_time_wheel_index (timing_wheel_t * w, uword level_index) -{ - return time_index_to_wheel_index (w, level_index, w->current_time_index); -} - -/* Circular wheel indexing. */ -always_inline uword -wheel_add (timing_wheel_t * w, word x) -{ - return x & w->bins_per_wheel_mask; -} - -always_inline uword -rtime_to_wheel_index (timing_wheel_t * w, uword level_index, uword rtime) -{ - uword t = current_time_wheel_index (w, level_index); - return wheel_add (w, t + rtime); -} - -static clib_error_t * -validate_level (timing_wheel_t * w, uword level_index, uword * n_elts) -{ - timing_wheel_level_t *level; - timing_wheel_elt_t *e; - uword wi; - clib_error_t *error = 0; - -#define _(x) \ - do { \ - error = CLIB_ERROR_ASSERT (x); \ - ASSERT (! error); \ - if (error) return error; \ - } while (0) - - level = vec_elt_at_index (w->levels, level_index); - for (wi = 0; wi < vec_len (level->elts); wi++) - { - /* Validate occupancy bitmap. */ - _(clib_bitmap_get_no_check (level->occupancy_bitmap, wi) == - (vec_len (level->elts[wi]) > 0)); - - *n_elts += vec_len (level->elts[wi]); - - vec_foreach (e, level->elts[wi]) - { - /* Validate time bin and level. */ - u64 e_time; - uword e_ti, e_li, e_wi; - - e_time = e->cpu_time_relative_to_base + w->cpu_time_base; - e_li = get_level_and_relative_time (w, e_time, &e_ti); - e_wi = rtime_to_wheel_index (w, level_index, e_ti); - - if (e_li == level_index - 1) - /* If this element was scheduled on the previous level - it must be wrapped. */ - _(e_ti + current_time_wheel_index (w, level_index - 1) - >= w->bins_per_wheel); - else - { - _(e_li == level_index); - if (e_li == 0) - _(e_wi == wi); - else - _(e_wi == wi || e_wi + 1 == wi || e_wi - 1 == wi); - } - } - } - -#undef _ - - return error; -} - -void -timing_wheel_validate (timing_wheel_t * w) -{ - uword l; - clib_error_t *error = 0; - uword n_elts; - - if (!w->validate) - return; - - n_elts = pool_elts (w->overflow_pool); - for (l = 0; l < vec_len (w->levels); l++) - { - error = validate_level (w, l, &n_elts); - if (error) - clib_error_report (error); - } -} - -always_inline void -free_elt_vector (timing_wheel_t * w, timing_wheel_elt_t * ev) -{ - /* Poison free elements so we never use them by mistake. */ - if (CLIB_DEBUG > 0) - memset (ev, ~0, vec_len (ev) * sizeof (ev[0])); - _vec_len (ev) = 0; - vec_add1 (w->free_elt_vectors, ev); -} - -static timing_wheel_elt_t * -insert_helper (timing_wheel_t * w, uword level_index, uword rtime) -{ - timing_wheel_level_t *level; - timing_wheel_elt_t *e; - uword wheel_index; - - /* Circular buffer. */ - vec_validate (w->levels, level_index); - level = vec_elt_at_index (w->levels, level_index); - - if (PREDICT_FALSE (!level->elts)) - { - uword max = w->bins_per_wheel - 1; - clib_bitmap_validate (level->occupancy_bitmap, max); - vec_validate (level->elts, max); - } - - wheel_index = rtime_to_wheel_index (w, level_index, rtime); - - level->occupancy_bitmap = - clib_bitmap_ori (level->occupancy_bitmap, wheel_index); - - /* Allocate an elt vector from free list if there is one. */ - if (!level->elts[wheel_index] && vec_len (w->free_elt_vectors)) - level->elts[wheel_index] = vec_pop (w->free_elt_vectors); - - /* Add element to vector for this time bin. */ - vec_add2 (level->elts[wheel_index], e, 1); - - return e; -} - -/* Insert user data on wheel at given CPU time stamp. */ -static void -timing_wheel_insert_helper (timing_wheel_t * w, u64 insert_cpu_time, - u32 user_data) -{ - timing_wheel_elt_t *e; - u64 dt; - uword rtime, level_index; - - level_index = get_level_and_relative_time (w, insert_cpu_time, &rtime); - - dt = insert_cpu_time - w->cpu_time_base; - if (PREDICT_TRUE (0 == (dt >> BITS (e->cpu_time_relative_to_base)))) - { - e = insert_helper (w, level_index, rtime); - e->user_data = user_data; - e->cpu_time_relative_to_base = dt; - } - else - { - /* Time too far in the future: add to overflow vector. */ - timing_wheel_overflow_elt_t *oe; - pool_get (w->overflow_pool, oe); - oe->user_data = user_data; - oe->cpu_time = insert_cpu_time; - } -} - -always_inline uword -elt_is_deleted (timing_wheel_t * w, u32 user_data) -{ - return (hash_elts (w->deleted_user_data_hash) > 0 - && hash_get (w->deleted_user_data_hash, user_data)); -} - -static timing_wheel_elt_t * -delete_user_data (timing_wheel_elt_t * elts, u32 user_data) -{ - uword found_match; - timing_wheel_elt_t *e, *new_elts; - - /* Quickly scan to see if there are any elements to delete - in this bucket. */ - found_match = 0; - vec_foreach (e, elts) - { - found_match = e->user_data == user_data; - if (found_match) - break; - } - if (!found_match) - return elts; - - /* Re-scan to build vector of new elts with matching user_data deleted. */ - new_elts = 0; - vec_foreach (e, elts) - { - if (e->user_data != user_data) - vec_add1 (new_elts, e[0]); - } - - vec_free (elts); - return new_elts; -} - -/* Insert user data on wheel at given CPU time stamp. */ -void -timing_wheel_insert (timing_wheel_t * w, u64 insert_cpu_time, u32 user_data) -{ - /* Remove previously deleted elements. */ - if (elt_is_deleted (w, user_data)) - { - timing_wheel_level_t *l; - uword wi; - - /* Delete elts with given user data so that stale events don't expire. */ - vec_foreach (l, w->levels) - { - /* *INDENT-OFF* */ - clib_bitmap_foreach (wi, l->occupancy_bitmap, ({ - l->elts[wi] = delete_user_data (l->elts[wi], user_data); - if (vec_len (l->elts[wi]) == 0) - l->occupancy_bitmap = clib_bitmap_andnoti (l->occupancy_bitmap, wi); - })); - /* *INDENT-ON* */ - } - - { - timing_wheel_overflow_elt_t *oe; - /* *INDENT-OFF* */ - pool_foreach (oe, w->overflow_pool, ({ - if (oe->user_data == user_data) - pool_put (w->overflow_pool, oe); - })); - /* *INDENT-ON* */ - } - - hash_unset (w->deleted_user_data_hash, user_data); - } - - timing_wheel_insert_helper (w, insert_cpu_time, user_data); -} - -void -timing_wheel_delete (timing_wheel_t * w, u32 user_data) -{ - if (!w->deleted_user_data_hash) - w->deleted_user_data_hash = - hash_create ( /* capacity */ 0, /* value bytes */ 0); - - hash_set1 (w->deleted_user_data_hash, user_data); -} - -/* Returns time of next expiring element. */ -u64 -timing_wheel_next_expiring_elt_time (timing_wheel_t * w) -{ - timing_wheel_level_t *l; - timing_wheel_elt_t *e; - uword li, wi, wi0; - u32 min_dt; - u64 min_t; - uword wrapped = 0; - - min_dt = ~0; - min_t = ~0ULL; - vec_foreach (l, w->levels) - { - if (!l->occupancy_bitmap) - continue; - - li = l - w->levels; - wi0 = wi = current_time_wheel_index (w, li); - wrapped = 0; - while (1) - { - if (clib_bitmap_get_no_check (l->occupancy_bitmap, wi)) - { - vec_foreach (e, l->elts[wi]) - min_dt = clib_min (min_dt, e->cpu_time_relative_to_base); - - if (wrapped && li + 1 < vec_len (w->levels)) - { - uword wi1 = current_time_wheel_index (w, li + 1); - if (l[1].occupancy_bitmap - && clib_bitmap_get_no_check (l[1].occupancy_bitmap, wi1)) - { - vec_foreach (e, l[1].elts[wi1]) - { - min_dt = - clib_min (min_dt, e->cpu_time_relative_to_base); - } - } - } - - min_t = w->cpu_time_base + min_dt; - goto done; - } - - wi = wheel_add (w, wi + 1); - if (wi == wi0) - break; - - wrapped = wi != wi + 1; - } - } - - { - timing_wheel_overflow_elt_t *oe; - - if (min_dt != ~0) - min_t = w->cpu_time_base + min_dt; - - /* *INDENT-OFF* */ - pool_foreach (oe, w->overflow_pool, - ({ min_t = clib_min (min_t, oe->cpu_time); })); - /* *INDENT-ON* */ - - done: - return min_t; - } -} - -static inline void -insert_elt (timing_wheel_t * w, timing_wheel_elt_t * e) -{ - u64 t = w->cpu_time_base + e->cpu_time_relative_to_base; - timing_wheel_insert_helper (w, t, e->user_data); -} - -always_inline u64 -elt_cpu_time (timing_wheel_t * w, timing_wheel_elt_t * e) -{ - return w->cpu_time_base + e->cpu_time_relative_to_base; -} - -always_inline void -validate_expired_elt (timing_wheel_t * w, timing_wheel_elt_t * e, - u64 current_cpu_time) -{ - if (CLIB_DEBUG > 0) - { - u64 e_time = elt_cpu_time (w, e); - - /* Verify that element is actually expired. */ - ASSERT ((e_time >> w->log2_clocks_per_bin) - <= (current_cpu_time >> w->log2_clocks_per_bin)); - } -} - -static u32 * -expire_bin (timing_wheel_t * w, - uword level_index, - uword wheel_index, u64 advance_cpu_time, u32 * expired_user_data) -{ - timing_wheel_level_t *level = vec_elt_at_index (w->levels, level_index); - timing_wheel_elt_t *e; - u32 *x; - uword i, j, e_len; - - e = vec_elt (level->elts, wheel_index); - e_len = vec_len (e); - - vec_add2 (expired_user_data, x, e_len); - for (i = j = 0; i < e_len; i++) - { - validate_expired_elt (w, &e[i], advance_cpu_time); - x[j] = e[i].user_data; - - /* Only advance if elt is not to be deleted. */ - j += !elt_is_deleted (w, e[i].user_data); - } - - /* Adjust for deleted elts. */ - if (j < e_len) - _vec_len (expired_user_data) -= e_len - j; - - free_elt_vector (w, e); - - level->elts[wheel_index] = 0; - clib_bitmap_set_no_check (level->occupancy_bitmap, wheel_index, 0); - - return expired_user_data; -} - -/* Called rarely. 32 bit times should only overflow every 4 seconds or so on a fast machine. */ -static u32 * -advance_cpu_time_base (timing_wheel_t * w, u32 * expired_user_data) -{ - timing_wheel_level_t *l; - timing_wheel_elt_t *e; - u64 delta; - - w->stats.cpu_time_base_advances++; - delta = ((u64) 1 << w->n_wheel_elt_time_bits); - w->cpu_time_base += delta; - w->time_index_next_cpu_time_base_update += delta >> w->log2_clocks_per_bin; - - vec_foreach (l, w->levels) - { - uword wi; - /* *INDENT-OFF* */ - clib_bitmap_foreach (wi, l->occupancy_bitmap, ({ - vec_foreach (e, l->elts[wi]) - { - /* This should always be true since otherwise we would have already expired - this element. */ - ASSERT (e->cpu_time_relative_to_base >= delta); - e->cpu_time_relative_to_base -= delta; - } - })); - /* *INDENT-ON* */ - } - - /* See which overflow elements fit now. */ - { - timing_wheel_overflow_elt_t *oe; - /* *INDENT-OFF* */ - pool_foreach (oe, w->overflow_pool, ({ - /* It fits now into 32 bits. */ - if (0 == ((oe->cpu_time - w->cpu_time_base) >> BITS (e->cpu_time_relative_to_base))) - { - u64 ti = oe->cpu_time >> w->log2_clocks_per_bin; - if (ti < w->current_time_index) - { - /* This can happen when timing wheel is not advanced for a long time - (for example when at a gdb breakpoint for a while). */ - if (! elt_is_deleted (w, oe->user_data)) - vec_add1 (expired_user_data, oe->user_data); - } - else - timing_wheel_insert_helper (w, oe->cpu_time, oe->user_data); - pool_put (w->overflow_pool, oe); - } - })); - /* *INDENT-ON* */ - } - return expired_user_data; -} - -static u32 * -refill_level (timing_wheel_t * w, - uword level_index, - u64 advance_cpu_time, - uword from_wheel_index, - uword to_wheel_index, u32 * expired_user_data) -{ - timing_wheel_level_t *level; - timing_wheel_elt_t *to_insert = w->unexpired_elts_pending_insert; - u64 advance_time_index = advance_cpu_time >> w->log2_clocks_per_bin; - - vec_validate (w->stats.refills, level_index); - w->stats.refills[level_index] += 1; - - if (level_index + 1 >= vec_len (w->levels)) - goto done; - - level = vec_elt_at_index (w->levels, level_index + 1); - if (!level->occupancy_bitmap) - goto done; - - while (1) - { - timing_wheel_elt_t *e, *es; - - if (clib_bitmap_get_no_check - (level->occupancy_bitmap, from_wheel_index)) - { - es = level->elts[from_wheel_index]; - level->elts[from_wheel_index] = 0; - clib_bitmap_set_no_check (level->occupancy_bitmap, from_wheel_index, - 0); - - vec_foreach (e, es) - { - u64 e_time = elt_cpu_time (w, e); - u64 ti = e_time >> w->log2_clocks_per_bin; - if (ti <= advance_time_index) - { - validate_expired_elt (w, e, advance_cpu_time); - if (!elt_is_deleted (w, e->user_data)) - vec_add1 (expired_user_data, e->user_data); - } - else - vec_add1 (to_insert, e[0]); - } - free_elt_vector (w, es); - } - - if (from_wheel_index == to_wheel_index) - break; - - from_wheel_index = wheel_add (w, from_wheel_index + 1); - } - - timing_wheel_validate (w); -done: - w->unexpired_elts_pending_insert = to_insert; - return expired_user_data; -} - -/* Advance wheel and return any expired user data in vector. */ -u32 * -timing_wheel_advance (timing_wheel_t * w, u64 advance_cpu_time, - u32 * expired_user_data, - u64 * next_expiring_element_cpu_time) -{ - timing_wheel_level_t *level; - uword level_index, advance_rtime, advance_level_index, advance_wheel_index; - uword n_expired_user_data_before; - u64 current_time_index, advance_time_index; - - n_expired_user_data_before = vec_len (expired_user_data); - - /* Re-fill lower levels when time wraps. */ - current_time_index = w->current_time_index; - advance_time_index = advance_cpu_time >> w->log2_clocks_per_bin; - - { - u64 current_ti, advance_ti; - - current_ti = current_time_index >> w->log2_bins_per_wheel; - advance_ti = advance_time_index >> w->log2_bins_per_wheel; - - if (PREDICT_FALSE (current_ti != advance_ti)) - { - if (w->unexpired_elts_pending_insert) - _vec_len (w->unexpired_elts_pending_insert) = 0; - - level_index = 0; - while (current_ti != advance_ti) - { - uword c, a; - c = current_ti & (w->bins_per_wheel - 1); - a = advance_ti & (w->bins_per_wheel - 1); - if (c != a) - expired_user_data = refill_level (w, - level_index, - advance_cpu_time, - c, a, expired_user_data); - current_ti >>= w->log2_bins_per_wheel; - advance_ti >>= w->log2_bins_per_wheel; - level_index++; - } - } - } - - advance_level_index = - get_level_and_relative_time (w, advance_cpu_time, &advance_rtime); - advance_wheel_index = - rtime_to_wheel_index (w, advance_level_index, advance_rtime); - - /* Empty all occupied bins for entire levels that we advance past. */ - for (level_index = 0; level_index < advance_level_index; level_index++) - { - uword wi; - - if (level_index >= vec_len (w->levels)) - break; - - level = vec_elt_at_index (w->levels, level_index); - /* *INDENT-OFF* */ - clib_bitmap_foreach (wi, level->occupancy_bitmap, ({ - expired_user_data = expire_bin (w, level_index, wi, advance_cpu_time, - expired_user_data); - })); - /* *INDENT-ON* */ - } - - if (PREDICT_TRUE (level_index < vec_len (w->levels))) - { - uword wi; - level = vec_elt_at_index (w->levels, level_index); - wi = current_time_wheel_index (w, level_index); - if (level->occupancy_bitmap) - while (1) - { - if (clib_bitmap_get_no_check (level->occupancy_bitmap, wi)) - expired_user_data = - expire_bin (w, advance_level_index, wi, advance_cpu_time, - expired_user_data); - - if (wi == advance_wheel_index) - break; - - wi = wheel_add (w, wi + 1); - } - } - - /* Advance current time index. */ - w->current_time_index = advance_time_index; - - if (vec_len (w->unexpired_elts_pending_insert) > 0) - { - timing_wheel_elt_t *e; - vec_foreach (e, w->unexpired_elts_pending_insert) insert_elt (w, e); - _vec_len (w->unexpired_elts_pending_insert) = 0; - } - - /* Don't advance until necessary. */ - while (PREDICT_FALSE - (advance_time_index >= w->time_index_next_cpu_time_base_update)) - expired_user_data = advance_cpu_time_base (w, expired_user_data); - - if (next_expiring_element_cpu_time) - { - u64 min_t; - - /* Anything expired? If so we need to recompute next expiring elt time. */ - if (vec_len (expired_user_data) == n_expired_user_data_before - && w->cached_min_cpu_time_on_wheel != 0ULL) - min_t = w->cached_min_cpu_time_on_wheel; - else - { - min_t = timing_wheel_next_expiring_elt_time (w); - w->cached_min_cpu_time_on_wheel = min_t; - } - - *next_expiring_element_cpu_time = min_t; - } - - return expired_user_data; -} - -u8 * -format_timing_wheel (u8 * s, va_list * va) -{ - timing_wheel_t *w = va_arg (*va, timing_wheel_t *); - int verbose = va_arg (*va, int); - uword indent = format_get_indent (s); - - s = format (s, "level 0: %.4e - %.4e secs, 2^%d - 2^%d clocks", - (f64) (1 << w->log2_clocks_per_bin) / w->cpu_clocks_per_second, - (f64) (1 << w->log2_clocks_per_wheel) / - w->cpu_clocks_per_second, w->log2_clocks_per_bin, - w->log2_clocks_per_wheel); - - if (verbose) - { - int l; - - s = format (s, "\n%Utime base advances %Ld, every %.4e secs", - format_white_space, indent + 2, - w->stats.cpu_time_base_advances, - (f64) ((u64) 1 << w->n_wheel_elt_time_bits) / - w->cpu_clocks_per_second); - - for (l = 0; l < vec_len (w->levels); l++) - s = format (s, "\n%Ulevel %d: refills %Ld", - format_white_space, indent + 2, - l, - l < - vec_len (w->stats.refills) ? w->stats. - refills[l] : (u64) 0); - } - - return s; -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/timing_wheel.h b/vppinfra/vppinfra/timing_wheel.h deleted file mode 100644 index 7daea994248..00000000000 --- a/vppinfra/vppinfra/timing_wheel.h +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef included_clib_timing_wheel_h -#define included_clib_timing_wheel_h - -#include <vppinfra/format.h> - -typedef struct -{ - /* Time of this element in units cpu clock ticks relative to time - base. 32 bits should be large enough for serveral kilo-seconds - to elapse before we have to re-set time base. */ - u32 cpu_time_relative_to_base; - - /* User data to store in this bin. */ - u32 user_data; -} timing_wheel_elt_t; - -/* Overflow wheel elements where time does not fit into 32 bits. */ -typedef struct -{ - /* Absolute time of this element. */ - u64 cpu_time; - - /* User data to store in this bin. */ - u32 user_data; - - u32 pad; -} timing_wheel_overflow_elt_t; - -typedef struct -{ - /* 2^M bits: 1 means vector is non-zero else zero. */ - uword *occupancy_bitmap; - - /* 2^M element table of element vectors, one for each time bin. */ - timing_wheel_elt_t **elts; -} timing_wheel_level_t; - -typedef struct -{ - /* Vector of refill counts per level. */ - u64 *refills; - - /* Number of times cpu time base was rescaled. */ - u64 cpu_time_base_advances; -} timing_wheel_stats_t; - -typedef struct -{ - /* Each bin is a power of two clock ticks (N) - chosen so that 2^N >= min_sched_time. */ - u8 log2_clocks_per_bin; - - /* Wheels are 2^M bins where 2^(N+M) >= max_sched_time. */ - u8 log2_bins_per_wheel; - - /* N + M. */ - u8 log2_clocks_per_wheel; - - /* Number of bits to use in cpu_time_relative_to_base field - of timing_wheel_elt_t. */ - u8 n_wheel_elt_time_bits; - - /* 2^M. */ - u32 bins_per_wheel; - - /* 2^M - 1. */ - u32 bins_per_wheel_mask; - - timing_wheel_level_t *levels; - - timing_wheel_overflow_elt_t *overflow_pool; - - /* Free list of element vector so we can recycle old allocated vectors. */ - timing_wheel_elt_t **free_elt_vectors; - - timing_wheel_elt_t *unexpired_elts_pending_insert; - - /* Hash table of user data values which have been deleted but not yet re-inserted. */ - uword *deleted_user_data_hash; - - /* Enable validation for debugging. */ - u32 validate; - - /* Time index. Measures time in units of 2^N clock ticks from - when wheel starts. */ - u64 current_time_index; - - /* All times are 32 bit numbers relative to cpu_time_base. - So, roughly every 2^(32 + N) clocks we'll need to subtract from - all timing_wheel_elt_t times to make sure they never overflow. */ - u64 cpu_time_base; - - /* When current_time_index is >= this we update cpu_time_base - to avoid overflowing 32 bit cpu_time_relative_to_base - in timing_wheel_elt_t. */ - u64 time_index_next_cpu_time_base_update; - - /* Cached earliest element on wheel; 0 if not valid. */ - u64 cached_min_cpu_time_on_wheel; - - f64 min_sched_time, max_sched_time, cpu_clocks_per_second; - - timing_wheel_stats_t stats; -} timing_wheel_t; - -/* Initialization function. */ -void timing_wheel_init (timing_wheel_t * w, - u64 current_cpu_time, f64 cpu_clocks_per_second); - -/* Insert user data on wheel at given CPU time stamp. */ -void timing_wheel_insert (timing_wheel_t * w, u64 insert_cpu_time, - u32 user_data); - -/* Delete user data from wheel (until it is again inserted). */ -void timing_wheel_delete (timing_wheel_t * w, u32 user_data); - -/* Advance wheel and return any expired user data in vector. If non-zero - min_next_expiring_element_cpu_time will return a cpu time stamp - before which there are guaranteed to be no elements in the current wheel. */ -u32 *timing_wheel_advance (timing_wheel_t * w, u64 advance_cpu_time, - u32 * expired_user_data, - u64 * min_next_expiring_element_cpu_time); - -/* Returns absolute time in clock cycles of next expiring element. */ -u64 timing_wheel_next_expiring_elt_time (timing_wheel_t * w); - -/* Format a timing wheel. */ -format_function_t format_timing_wheel; - -/* Testing function to validate wheel. */ -void timing_wheel_validate (timing_wheel_t * w); - -#endif /* included_clib_timing_wheel_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/types.h b/vppinfra/vppinfra/types.h deleted file mode 100644 index f87bb48c910..00000000000 --- a/vppinfra/vppinfra/types.h +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001-2005 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_clib_types_h -#define included_clib_types_h - -/* Standard CLIB types. */ - -/* Define signed and unsigned 8, 16, 32, and 64 bit types - and machine signed/unsigned word for all architectures. */ -typedef char i8; -typedef short i16; - -/* Avoid conflicts with Linux asm/types.h when __KERNEL__ */ -#if defined(CLIB_LINUX_KERNEL) -/* Linux also defines u8/u16/u32/u64 types. */ -#include <asm/types.h> -#define CLIB_AVOID_CLASH_WITH_LINUX_TYPES - -#else /* ! CLIB_LINUX_KERNEL */ - -typedef unsigned char u8; -typedef unsigned short u16; -#endif /* ! CLIB_LINUX_KERNEL */ - -#if defined (__x86_64__) -#ifndef __COVERITY__ -typedef int i128 __attribute__ ((mode (TI))); -typedef unsigned int u128 __attribute__ ((mode (TI))); -#endif -#endif - -#if (defined(i386) || defined(_mips) || defined(powerpc) || defined (__SPU__) || defined(__sparc__) || defined(__arm__) || defined (__xtensa__) || defined(__TMS320C6X__)) -typedef int i32; -typedef long long i64; - -#ifndef CLIB_AVOID_CLASH_WITH_LINUX_TYPES -typedef unsigned int u32; -typedef unsigned long long u64; -#endif /* CLIB_AVOID_CLASH_WITH_LINUX_TYPES */ - -#elif defined(_mips) && __mips == 64 -#define log2_uword_bits 6 -#define clib_address_bits _MIPS_SZPTR - -#elif defined(alpha) || defined(__x86_64__) || defined (__powerpc64__) || defined (__aarch64__) -typedef int i32; -typedef long i64; - -#define log2_uword_bits 6 -#define clib_address_bits 64 - -#ifndef CLIB_AVOID_CLASH_WITH_LINUX_TYPES -typedef unsigned int u32; -typedef unsigned long u64; -#endif /* CLIB_AVOID_CLASH_WITH_LINUX_TYPES */ - -#else -#error "can't define types" -#endif - -/* Default to 32 bit machines with 32 bit addresses. */ -#ifndef log2_uword_bits -#define log2_uword_bits 5 -#endif - -/* #ifdef's above define log2_uword_bits. */ -#define uword_bits (1 << log2_uword_bits) - -#ifndef clib_address_bits -#define clib_address_bits 32 -#endif - -/* Word types. */ -#if uword_bits == 64 -/* 64 bit word machines. */ -typedef i64 word; -typedef u64 uword; -#else -/* 32 bit word machines. */ -typedef i32 word; -typedef u32 uword; -#endif - -/* integral type of a pointer (used to cast pointers). */ -#if clib_address_bits == 64 -typedef u64 clib_address_t; -#else -typedef u32 clib_address_t; -#endif - -/* These are needed to convert between pointers and machine words. - MIPS is currently the only machine that can have different sized - pointers and machine words (but only when compiling with 64 bit - registers and 32 bit pointers). */ -static inline __attribute__ ((always_inline)) uword -pointer_to_uword (const void *p) -{ - return (uword) (clib_address_t) p; -} - -#define uword_to_pointer(u,type) ((type) (clib_address_t) (u)) - -/* Any type: can be either word or pointer. */ -typedef word any; - -/* Floating point types. */ -typedef double f64; -typedef float f32; - -typedef __complex__ float cf32; -typedef __complex__ double cf64; - -/* Floating point word size. */ -typedef f64 fword; - -/* Can be used as either {r,l}value, e.g. these both work - clib_mem_unaligned (p, u64) = 99 - clib_mem_unaligned (p, u64) += 99 */ - -#define clib_mem_unaligned(pointer,type) \ - (((struct { CLIB_PACKED (type _data); } *) (pointer))->_data) - -/* Access memory with specified alignment depending on align argument. - As with clib_mem_unaligned, may be used as {r,l}value. */ -#define clib_mem_aligned(addr,type,align) \ - (((struct { \ - type _data \ - __attribute__ ((aligned (align), packed)); \ - } *) (addr))->_data) - -#endif /* included_clib_types_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/unformat.c b/vppinfra/vppinfra/unformat.c deleted file mode 100644 index ac8b7ddc712..00000000000 --- a/vppinfra/vppinfra/unformat.c +++ /dev/null @@ -1,1077 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include <vppinfra/format.h> - -/* Call user's function to fill input buffer. */ -uword -_unformat_fill_input (unformat_input_t * i) -{ - uword l, first_mark; - - if (i->index == UNFORMAT_END_OF_INPUT) - return i->index; - - first_mark = l = vec_len (i->buffer); - if (vec_len (i->buffer_marks) > 0) - first_mark = i->buffer_marks[0]; - - /* Re-use buffer when no marks. */ - if (first_mark > 0) - vec_delete (i->buffer, first_mark, 0); - - i->index = vec_len (i->buffer); - for (l = 0; l < vec_len (i->buffer_marks); l++) - i->buffer_marks[l] -= first_mark; - - /* Call user's function to fill the buffer. */ - if (i->fill_buffer) - i->index = i->fill_buffer (i); - - /* If input pointer is still beyond end of buffer even after - fill then we've run out of input. */ - if (i->index >= vec_len (i->buffer)) - i->index = UNFORMAT_END_OF_INPUT; - - return i->index; -} - -always_inline uword -is_white_space (uword c) -{ - switch (c) - { - case ' ': - case '\t': - case '\n': - case '\r': - return 1; - - default: - return 0; - } -} - -/* Format function for dumping input stream. */ -u8 * -format_unformat_error (u8 * s, va_list * va) -{ - unformat_input_t *i = va_arg (*va, unformat_input_t *); - uword l = vec_len (i->buffer); - - /* Only show so much of the input buffer (it could be really large). */ - uword n_max = 30; - - if (i->index < l) - { - uword n = l - i->index; - u8 *p, *p_end; - - p = i->buffer + i->index; - p_end = p + (n > n_max ? n_max : n); - - /* Skip white space at end. */ - if (n <= n_max) - { - while (p_end > p && is_white_space (p_end[-1])) - p_end--; - } - - while (p < p_end) - { - switch (*p) - { - case '\r': - vec_add (s, "\\r", 2); - break; - case '\n': - vec_add (s, "\\n", 2); - break; - case '\t': - vec_add (s, "\\t", 2); - break; - default: - vec_add1 (s, *p); - break; - } - p++; - } - - if (n > n_max) - vec_add (s, "...", 3); - } - - return s; -} - -/* Print everything: not just error context. */ -u8 * -format_unformat_input (u8 * s, va_list * va) -{ - unformat_input_t *i = va_arg (*va, unformat_input_t *); - uword l, n; - - if (i->index == UNFORMAT_END_OF_INPUT) - s = format (s, "{END_OF_INPUT}"); - else - { - l = vec_len (i->buffer); - n = l - i->index; - if (n > 0) - vec_add (s, i->buffer + i->index, n); - } - - return s; -} - -#if CLIB_DEBUG > 0 -void -di (unformat_input_t * i) -{ - fformat (stderr, "%U\n", format_unformat_input, i); -} -#endif - -/* Parse delimited vector string. If string starts with { then string - is delimited by balenced parenthesis. Other string is delimited by - white space. {} were chosen since they are special to the shell. */ -static uword -unformat_string (unformat_input_t * input, - uword delimiter_character, - uword format_character, va_list * va) -{ - u8 **string_return = va_arg (*va, u8 **); - u8 *s = 0; - word paren = 0; - word is_paren_delimited = 0; - word backslash = 0; - uword c; - - switch (delimiter_character) - { - case '%': - case ' ': - case '\t': - delimiter_character = 0; - break; - } - - while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT) - { - word add_to_vector; - - /* Null return string means to skip over delimited input. */ - add_to_vector = string_return != 0; - - if (backslash) - backslash = 0; - else - switch (c) - { - case '\\': - backslash = 1; - add_to_vector = 0; - break; - - case '{': - if (paren == 0 && vec_len (s) == 0) - { - is_paren_delimited = 1; - add_to_vector = 0; - } - paren++; - break; - - case '}': - paren--; - if (is_paren_delimited && paren == 0) - goto done; - break; - - case ' ': - case '\t': - case '\n': - case '\r': - if (!is_paren_delimited) - { - unformat_put_input (input); - goto done; - } - break; - - default: - if (!is_paren_delimited && c == delimiter_character) - { - unformat_put_input (input); - goto done; - } - } - - if (add_to_vector) - vec_add1 (s, c); - } - -done: - if (string_return) - { - /* Match the string { END-OF-INPUT as a single brace. */ - if (c == UNFORMAT_END_OF_INPUT && vec_len (s) == 0 && paren == 1) - vec_add1 (s, '{'); - - /* Don't match null string. */ - if (c == UNFORMAT_END_OF_INPUT && vec_len (s) == 0) - return 0; - - /* Null terminate C string. */ - if (format_character == 's') - vec_add1 (s, 0); - - *string_return = s; - } - else - vec_free (s); /* just to make sure */ - - return 1; -} - -uword -unformat_hex_string (unformat_input_t * input, va_list * va) -{ - u8 **hexstring_return = va_arg (*va, u8 **); - u8 *s; - uword n, d, c; - - n = 0; - d = 0; - s = 0; - while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT) - { - if (c >= '0' && c <= '9') - d = 16 * d + c - '0'; - else if (c >= 'a' && c <= 'f') - d = 16 * d + 10 + c - 'a'; - else if (c >= 'A' && c <= 'F') - d = 16 * d + 10 + c - 'A'; - else - { - unformat_put_input (input); - break; - } - n++; - - if (n == 2) - { - vec_add1 (s, d); - n = d = 0; - } - } - - /* Hex string must have even number of digits. */ - if (n % 2) - { - vec_free (s); - return 0; - } - - *hexstring_return = s; - return 1; -} - -/* unformat (input "foo%U", unformat_eof) matches terminal foo only */ -uword -unformat_eof (unformat_input_t * input, va_list * va) -{ - return unformat_check_input (input) == UNFORMAT_END_OF_INPUT; -} - -/* Parse a token containing given set of characters. */ -uword -unformat_token (unformat_input_t * input, va_list * va) -{ - u8 *token_chars = va_arg (*va, u8 *); - u8 **string_return = va_arg (*va, u8 **); - u8 *s, map[256]; - uword i, c; - - if (!token_chars) - token_chars = (u8 *) "a-zA-Z0-9_"; - - memset (map, 0, sizeof (map)); - for (s = token_chars; *s;) - { - /* Parse range. */ - if (s[0] < s[2] && s[1] == '-') - { - for (i = s[0]; i <= s[2]; i++) - map[i] = 1; - s = s + 3; - } - else - { - map[s[0]] = 1; - s = s + 1; - } - } - - s = 0; - while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT) - { - if (!map[c]) - { - unformat_put_input (input); - break; - } - - vec_add1 (s, c); - } - - if (vec_len (s) == 0) - return 0; - - *string_return = s; - return 1; -} - -/* Unformat (parse) function which reads a %s string and converts it - to and unformat_input_t. */ -uword -unformat_input (unformat_input_t * i, va_list * args) -{ - unformat_input_t *sub_input = va_arg (*args, unformat_input_t *); - u8 *s; - - if (unformat (i, "%v", &s)) - { - unformat_init_vector (sub_input, s); - return 1; - } - - return 0; -} - -/* Parse a line ending with \n and return it. */ -uword -unformat_line (unformat_input_t * i, va_list * va) -{ - u8 *line = 0, **result = va_arg (*va, u8 **); - uword c; - - while ((c = unformat_get_input (i)) != '\n' && c != UNFORMAT_END_OF_INPUT) - { - vec_add1 (line, c); - } - - *result = line; - return 1; -} - -/* Parse a line ending with \n and return it as an unformat_input_t. */ -uword -unformat_line_input (unformat_input_t * i, va_list * va) -{ - unformat_input_t *result = va_arg (*va, unformat_input_t *); - u8 *line; - unformat_user (i, unformat_line, &line); - unformat_init_vector (result, line); - return 1; -} - -/* Values for is_signed. */ -#define UNFORMAT_INTEGER_SIGNED 1 -#define UNFORMAT_INTEGER_UNSIGNED 0 - -static uword -unformat_integer (unformat_input_t * input, - va_list * va, uword base, uword is_signed, uword data_bytes) -{ - uword c, digit; - uword value = 0; - uword n_digits = 0; - uword n_input = 0; - uword sign = 0; - - /* We only support bases <= 64. */ - if (base < 2 || base > 64) - goto error; - - while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT) - { - switch (c) - { - case '-': - if (n_input == 0) - { - if (is_signed) - { - sign = 1; - goto next_digit; - } - else - /* Leading sign for unsigned number. */ - goto error; - } - /* Sign after input (e.g. 100-200). */ - goto put_input_done; - - case '+': - if (n_input > 0) - goto put_input_done; - sign = 0; - goto next_digit; - - case '0' ... '9': - digit = c - '0'; - break; - - case 'a' ... 'z': - digit = 10 + (c - 'a'); - break; - - case 'A' ... 'Z': - digit = 10 + (base >= 36 ? 26 : 0) + (c - 'A'); - break; - - case '/': - digit = 62; - break; - - case '?': - digit = 63; - break; - - default: - goto put_input_done; - } - - if (digit >= base) - { - put_input_done: - unformat_put_input (input); - goto done; - } - - { - uword new_value = base * value + digit; - - /* Check for overflow. */ - if (new_value < value) - goto error; - value = new_value; - } - n_digits += 1; - - next_digit: - n_input++; - } - -done: - if (sign) - value = -value; - - if (n_digits > 0) - { - void *v = va_arg (*va, void *); - - if (data_bytes == ~0) - data_bytes = sizeof (int); - - switch (data_bytes) - { - case 1: - *(u8 *) v = value; - break; - case 2: - *(u16 *) v = value; - break; - case 4: - *(u32 *) v = value; - break; - case 8: - *(u64 *) v = value; - break; - default: - goto error; - } - - return 1; - } - -error: - return 0; -} - -/* Return x 10^n */ -static f64 -times_power_of_ten (f64 x, int n) -{ - if (n >= 0) - { - static f64 t[8] = { 1e+0, 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, }; - while (n >= 8) - { - x *= 1e+8; - n -= 8; - } - return x * t[n]; - } - else - { - static f64 t[8] = { 1e-0, 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7, }; - while (n <= -8) - { - x *= 1e-8; - n += 8; - } - return x * t[-n]; - } - -} - -static uword -unformat_float (unformat_input_t * input, va_list * va) -{ - uword c; - u64 values[3]; - uword n_digits[3], value_index = 0; - uword signs[2], sign_index = 0; - uword n_input = 0; - - memset (values, 0, sizeof (values)); - memset (n_digits, 0, sizeof (n_digits)); - memset (signs, 0, sizeof (signs)); - - while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT) - { - switch (c) - { - case '-': - if (value_index == 2 && n_digits[2] == 0) - /* sign of exponent: it's ok. */ ; - - else if (value_index < 2 && n_digits[0] > 0) - { - /* 123- */ - unformat_put_input (input); - goto done; - } - - else if (n_input > 0) - goto error; - - signs[sign_index++] = 1; - goto next_digit; - - case '+': - if (value_index == 2 && n_digits[2] == 0) - /* sign of exponent: it's ok. */ ; - - else if (value_index < 2 && n_digits[0] > 0) - { - /* 123+ */ - unformat_put_input (input); - goto done; - } - - else if (n_input > 0) - goto error; - signs[sign_index++] = 0; - goto next_digit; - - case 'e': - case 'E': - if (n_input == 0) - goto error; - value_index = 2; - sign_index = 1; - break; - - case '.': - if (value_index > 0) - goto error; - value_index = 1; - break; - - case '0' ... '9': - { - u64 tmp; - - tmp = values[value_index] * 10 + c - '0'; - - /* Check for overflow. */ - if (tmp < values[value_index]) - goto error; - values[value_index] = tmp; - n_digits[value_index] += 1; - } - break; - - default: - unformat_put_input (input); - goto done; - } - - next_digit: - n_input++; - } - -done: - { - f64 f_values[2], *value_return; - word expon; - - /* Must have either whole or fraction digits. */ - if (n_digits[0] + n_digits[1] <= 0) - goto error; - - f_values[0] = values[0]; - if (signs[0]) - f_values[0] = -f_values[0]; - - f_values[1] = values[1]; - f_values[1] = times_power_of_ten (f_values[1], -n_digits[1]); - - f_values[0] += f_values[1]; - - expon = values[2]; - if (signs[1]) - expon = -expon; - - f_values[0] = times_power_of_ten (f_values[0], expon); - - value_return = va_arg (*va, f64 *); - *value_return = f_values[0]; - return 1; - } - -error: - return 0; -} - -static char * -match_input_with_format (unformat_input_t * input, char *f) -{ - uword cf, ci; - - ASSERT (*f != 0); - - while (1) - { - cf = *f; - if (cf == 0 || cf == '%' || cf == ' ') - break; - f++; - - ci = unformat_get_input (input); - - if (cf != ci) - return 0; - } - return f; -} - -static char * -do_percent (unformat_input_t * input, va_list * va, char *f) -{ - uword cf, n, data_bytes = ~0; - - cf = *f++; - - switch (cf) - { - default: - break; - - case 'w': - /* Word types. */ - cf = *f++; - data_bytes = sizeof (uword); - break; - - case 'l': - cf = *f++; - if (cf == 'l') - { - cf = *f++; - data_bytes = sizeof (long long); - } - else - { - data_bytes = sizeof (long); - } - break; - - case 'L': - cf = *f++; - data_bytes = sizeof (long long); - break; - } - - n = 0; - switch (cf) - { - case 'D': - data_bytes = va_arg (*va, int); - case 'd': - n = unformat_integer (input, va, 10, - UNFORMAT_INTEGER_SIGNED, data_bytes); - break; - - case 'u': - n = unformat_integer (input, va, 10, - UNFORMAT_INTEGER_UNSIGNED, data_bytes); - break; - - case 'b': - n = unformat_integer (input, va, 2, - UNFORMAT_INTEGER_UNSIGNED, data_bytes); - break; - - case 'o': - n = unformat_integer (input, va, 8, - UNFORMAT_INTEGER_UNSIGNED, data_bytes); - break; - - case 'X': - data_bytes = va_arg (*va, int); - case 'x': - n = unformat_integer (input, va, 16, - UNFORMAT_INTEGER_UNSIGNED, data_bytes); - break; - - case 'f': - n = unformat_float (input, va); - break; - - case 's': - case 'v': - n = unformat_string (input, f[0], cf, va); - break; - - case 'U': - { - unformat_function_t *f = va_arg (*va, unformat_function_t *); - n = f (input, va); - } - break; - - case '=': - case '|': - { - int *var = va_arg (*va, int *); - uword val = va_arg (*va, int); - - if (cf == '|') - val |= *var; - *var = val; - n = 1; - } - break; - } - - return n ? f : 0; -} - -uword -unformat_skip_white_space (unformat_input_t * input) -{ - uword n = 0; - uword c; - - while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT) - { - if (!is_white_space (c)) - { - unformat_put_input (input); - break; - } - n++; - } - return n; -} - -uword -va_unformat (unformat_input_t * input, char *fmt, va_list * va) -{ - char *f; - uword input_matches_format; - uword default_skip_input_white_space; - uword n_input_white_space_skipped; - uword last_non_white_space_match_percent; - uword last_non_white_space_match_format; - - vec_add1_aligned (input->buffer_marks, input->index, - sizeof (input->buffer_marks[0])); - - f = fmt; - default_skip_input_white_space = 1; - input_matches_format = 0; - last_non_white_space_match_percent = 0; - last_non_white_space_match_format = 0; - - while (1) - { - char cf; - uword is_percent, skip_input_white_space; - - cf = *f; - is_percent = 0; - - /* Always skip input white space at start of format string. - Otherwise use default skip value which can be changed by %_ - (see below). */ - skip_input_white_space = f == fmt || default_skip_input_white_space; - - /* Spaces in format request skipping input white space. */ - if (is_white_space (cf)) - { - skip_input_white_space = 1; - - /* Multiple format spaces are equivalent to a single white - space. */ - while (is_white_space (*++f)) - ; - } - else if (cf == '%') - { - /* %_ toggles whether or not to skip input white space. */ - switch (*++f) - { - case '_': - default_skip_input_white_space = - !default_skip_input_white_space; - f++; - /* For transition from skip to no-skip in middle of format - string, skip input white space. For example, the following matches: - fmt = "%_%d.%d%_->%_%d.%d%_" - input "1.2 -> 3.4" - Without this the space after -> does not get skipped. */ - if (!default_skip_input_white_space - && !(f == fmt + 2 || *f == 0)) - unformat_skip_white_space (input); - continue; - - /* %% means match % */ - case '%': - break; - - /* % at end of format string. */ - case 0: - goto parse_fail; - - default: - is_percent = 1; - break; - } - } - - n_input_white_space_skipped = 0; - if (skip_input_white_space) - n_input_white_space_skipped = unformat_skip_white_space (input); - - /* End of format string. */ - if (cf == 0) - { - /* Force parse error when format string ends and input is - not white or at end. As an example, this is to prevent - format "foo" from matching input "food". - The last_non_white_space_match_percent is to make - "foo %d" match input "foo 10,bletch" with %d matching 10. */ - if (skip_input_white_space - && !last_non_white_space_match_percent - && !last_non_white_space_match_format - && n_input_white_space_skipped == 0 - && input->index != UNFORMAT_END_OF_INPUT) - goto parse_fail; - break; - } - - last_non_white_space_match_percent = is_percent; - last_non_white_space_match_format = 0; - - /* Explicit spaces in format must match input white space. */ - if (cf == ' ' && !default_skip_input_white_space) - { - if (n_input_white_space_skipped == 0) - goto parse_fail; - } - - else if (is_percent) - { - if (!(f = do_percent (input, va, f))) - goto parse_fail; - } - - else - { - char *g = match_input_with_format (input, f); - if (!g) - goto parse_fail; - last_non_white_space_match_format = g > f; - f = g; - } - } - - input_matches_format = 1; -parse_fail: - - /* Rewind buffer marks. */ - { - uword l = vec_len (input->buffer_marks); - - /* If we did not match back up buffer to last mark. */ - if (!input_matches_format) - input->index = input->buffer_marks[l - 1]; - - _vec_len (input->buffer_marks) = l - 1; - } - - return input_matches_format; -} - -uword -unformat (unformat_input_t * input, char *fmt, ...) -{ - va_list va; - uword result; - va_start (va, fmt); - result = va_unformat (input, fmt, &va); - va_end (va); - return result; -} - -uword -unformat_user (unformat_input_t * input, unformat_function_t * func, ...) -{ - va_list va; - uword result, l; - - /* Save place in input buffer in case parse fails. */ - l = vec_len (input->buffer_marks); - vec_add1_aligned (input->buffer_marks, input->index, - sizeof (input->buffer_marks[0])); - - va_start (va, func); - result = func (input, &va); - va_end (va); - - if (!result && input->index != UNFORMAT_END_OF_INPUT) - input->index = input->buffer_marks[l]; - - _vec_len (input->buffer_marks) = l; - - return result; -} - -/* Setup for unformat of Unix style command line. */ -void -unformat_init_command_line (unformat_input_t * input, char *argv[]) -{ - uword i; - - unformat_init (input, 0, 0); - - /* Concatenate argument strings with space in between. */ - for (i = 1; argv[i]; i++) - { - vec_add (input->buffer, argv[i], strlen (argv[i])); - if (argv[i + 1]) - vec_add1 (input->buffer, ' '); - } -} - -void -unformat_init_string (unformat_input_t * input, char *string, int string_len) -{ - unformat_init (input, 0, 0); - if (string_len > 0) - vec_add (input->buffer, string, string_len); -} - -void -unformat_init_vector (unformat_input_t * input, u8 * vector_string) -{ - unformat_init (input, 0, 0); - input->buffer = vector_string; -} - -#ifdef CLIB_UNIX - -static uword -unix_file_fill_buffer (unformat_input_t * input) -{ - int fd = pointer_to_uword (input->fill_buffer_arg); - uword l, n; - - l = vec_len (input->buffer); - vec_resize (input->buffer, 4096); - n = read (fd, input->buffer + l, 4096); - if (n > 0) - _vec_len (input->buffer) = l + n; - - if (n <= 0) - return UNFORMAT_END_OF_INPUT; - else - return input->index; -} - -void -unformat_init_unix_file (unformat_input_t * input, int file_descriptor) -{ - unformat_init (input, unix_file_fill_buffer, - uword_to_pointer (file_descriptor, void *)); -} - -/* Take input from Unix environment variable. */ -uword -unformat_init_unix_env (unformat_input_t * input, char *var) -{ - char *val = getenv (var); - if (val) - unformat_init_string (input, val, strlen (val)); - return val != 0; -} - -#endif /* CLIB_UNIX */ - - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/unix-formats.c b/vppinfra/vppinfra/unix-formats.c deleted file mode 100644 index a4c81ca2f70..00000000000 --- a/vppinfra/vppinfra/unix-formats.c +++ /dev/null @@ -1,918 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifdef __KERNEL__ - -# include <linux/unistd.h> -# include <linux/signal.h> - -#else /* ! __KERNEL__ */ - -#define _GNU_SOURCE /* to get REG_* in ucontext.h */ -#include <ucontext.h> -#undef _GNU_SOURCE -#undef __USE_GNU - -#include <unistd.h> -#include <signal.h> - -#include <time.h> -#include <sys/socket.h> -#include <netdb.h> -#include <math.h> - -#include <vppinfra/time.h> - -#ifdef AF_NETLINK -#include <linux/types.h> -#include <linux/netlink.h> -#endif - -#endif /* ! __KERNEL__ */ - - -#ifdef __KERNEL__ -# include <linux/socket.h> -# include <linux/in.h> -# include <linux/ip.h> -# include <linux/tcp.h> -# include <linux/udp.h> -# include <linux/icmp.h> -# include <linux/if_ether.h> -# include <linux/if_arp.h> -#else -# include <net/if.h> /* struct ifnet may live here */ -# include <netinet/in.h> -# include <netinet/ip.h> -# include <netinet/tcp.h> -# include <netinet/udp.h> -# include <netinet/ip_icmp.h> -# include <netinet/if_ether.h> -#endif /* __KERNEL__ */ - -#include <vppinfra/bitops.h> /* foreach_set_bit */ -#include <vppinfra/format.h> -#include <vppinfra/error.h> - -/* Format unix network address family (e.g. AF_INET). */ -u8 * format_address_family (u8 * s, va_list * va) -{ - uword family = va_arg (*va, uword); - u8 * t = (u8 *) "UNKNOWN"; - switch (family) - { -#define _(x) case PF_##x: t = (u8 *) #x; break - _ (UNSPEC); - _ (UNIX); /* Unix domain sockets */ - _ (INET); /* Internet IP Protocol */ -#ifdef PF_AX25 - _ (AX25); /* Amateur Radio AX.25 */ -#endif -#ifdef PF_IPX - _ (IPX); /* Novell IPX */ -#endif -#ifdef PF_APPLETALK - _ (APPLETALK); /* AppleTalk DDP */ -#endif -#ifdef PF_NETROM - _ (NETROM); /* Amateur Radio NET/ROM */ -#endif -#ifdef PF_BRIDGE - _ (BRIDGE); /* Multiprotocol bridge */ -#endif -#ifdef PF_ATMPVC - _ (ATMPVC); /* ATM PVCs */ -#endif -#ifdef PF_X25 - _ (X25); /* Reserved for X.25 project */ -#endif -#ifdef PF_INET6 - _ (INET6); /* IP version 6 */ -#endif -#ifdef PF_ROSE - _ (ROSE); /* Amateur Radio X.25 PLP */ -#endif -#ifdef PF_DECnet - _ (DECnet); /* Reserved for DECnet project */ -#endif -#ifdef PF_NETBEUI - _ (NETBEUI); /* Reserved for 802.2LLC project*/ -#endif -#ifdef PF_SECURITY - _ (SECURITY); /* Security callback pseudo AF */ -#endif -#ifdef PF_KEY - _ (KEY); /* PF_KEY key management API */ -#endif -#ifdef PF_NETLINK - _ (NETLINK); -#endif -#ifdef PF_PACKET - _ (PACKET); /* Packet family */ -#endif -#ifdef PF_ASH - _ (ASH); /* Ash */ -#endif -#ifdef PF_ECONET - _ (ECONET); /* Acorn Econet */ -#endif -#ifdef PF_ATMSVC - _ (ATMSVC); /* ATM SVCs */ -#endif -#ifdef PF_SNA - _ (SNA); /* Linux SNA Project */ -#endif -#ifdef PF_IRDA - _ (IRDA); /* IRDA sockets */ -#endif -#undef _ - } - vec_add (s, t, strlen ((char *) t)); - return s; -} - -u8 * format_network_protocol (u8 * s, va_list * args) -{ - uword family = va_arg (*args, uword); - uword protocol = va_arg (*args, uword); - -#ifndef __KERNEL__ - struct protoent * p = getprotobynumber (protocol); - - ASSERT (family == AF_INET); - if (p) - return format (s, "%s", p->p_name); - else - return format (s, "%d", protocol); -#else - return format (s, "%d/%d", family, protocol); -#endif -} - -u8 * format_network_port (u8 * s, va_list * args) -{ - uword proto = va_arg (*args, uword); - uword port = va_arg (*args, uword); - -#ifndef __KERNEL__ - struct servent * p = getservbyport (port, proto == IPPROTO_UDP ? "udp" : "tcp"); - - if (p) - return format (s, "%s", p->s_name); - else - return format (s, "%d", port); -#else - return format (s, "%s/%d", proto == IPPROTO_UDP ? "udp" : "tcp", port); -#endif -} - -/* Format generic network address: takes two arguments family and address. - Assumes network byte order. */ -u8 * format_network_address (u8 * s, va_list * args) -{ - uword family = va_arg (*args, uword); - u8 * addr = va_arg (*args, u8 *); - - switch (family) - { - case AF_INET: - s = format (s, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]); - break; - - case AF_UNSPEC: - /* We use AF_UNSPEC for ethernet addresses. */ - s = format (s, "%02x:%02x:%02x:%02x:%02x:%02x", - addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); - break; - - default: - clib_error ("unsupported address family %d", family); - } - - return s; -} - -u8 * format_sockaddr (u8 * s, va_list * args) -{ - void * v = va_arg (*args, void *); - struct sockaddr * sa = v; - - switch (sa->sa_family) - { - case AF_INET: - { - struct sockaddr_in * i = v; - s = format (s, "%U:%U", - format_network_address, AF_INET, &i->sin_addr.s_addr, - format_network_port, IPPROTO_TCP, ntohs (i->sin_port)); - } - break; - -#ifndef __KERNEL__ -#ifdef AF_NETLINK - case AF_NETLINK: - { - struct sockaddr_nl * n = v; - s = format (s, "KERNEL-NETLINK"); - if (n->nl_groups) - s = format (s, " (groups 0x%x)", n->nl_groups); - break; - } -#endif -#endif - - default: - s = format (s, "sockaddr family %d", sa->sa_family); - break; - } - - return s; -} - -u8 * format_tcp4_packet (u8 * s, va_list * args) -{ - u8 * p = va_arg (*args, u8 *); - struct iphdr * ip = (void *) p; - struct tcphdr * tcp = (void *) (ip + 1); - - s = format (s, "tcp %U:%U -> %U:%U", - format_network_address, AF_INET, &ip->saddr, - format_network_port, IPPROTO_TCP, ntohs (tcp->source), - format_network_address, AF_INET, &ip->daddr, - format_network_port, IPPROTO_TCP, ntohs (tcp->dest)); - - s = format (s, ", seq 0x%08x -> 0x%08x", tcp->seq, tcp->ack_seq); -#define _(f) if (tcp->f) s = format (s, ", " #f); - _ (syn); _ (ack); _ (fin); _ (rst); _ (psh); _ (urg); -#undef _ - - if (tcp->window) - s = format (s, ", window 0x%04x", tcp->window); - if (tcp->urg) - s = format (s, ", urg 0x%04x", tcp->urg_ptr); - - return s; -} - -u8 * format_udp4_packet (u8 * s, va_list * args) -{ - u8 * p = va_arg (*args, u8 *); - struct iphdr * ip = (void *) p; - struct udphdr * udp = (void *) (ip + 1); - - s = format (s, "udp %U:%U -> %U:%U", - format_network_address, AF_INET, &ip->saddr, - format_network_port, IPPROTO_UDP, ntohs (udp->source), - format_network_address, AF_INET, &ip->daddr, - format_network_port, IPPROTO_UDP, ntohs (udp->dest)); - - return s; -} - -u8 * format_icmp4_type_and_code (u8 * s, va_list * args) -{ - uword icmp_type = va_arg (*args, uword); - uword icmp_code = va_arg (*args, uword); - - switch (icmp_type) - { -#define _(f,str) case ICMP_##f: s = format (s, str); break; - _ (ECHOREPLY, "echo reply"); - _ (DEST_UNREACH, "unreachable"); - _ (SOURCE_QUENCH, "source quench"); - _ (REDIRECT, "redirect"); - _ (ECHO, "echo request"); - _ (TIME_EXCEEDED, "time exceeded"); - _ (PARAMETERPROB, "parameter problem"); - _ (TIMESTAMP, "timestamp request"); - _ (TIMESTAMPREPLY, "timestamp reply"); - _ (INFO_REQUEST, "information request"); - _ (INFO_REPLY, "information reply"); - _ (ADDRESS, "address mask request"); - _ (ADDRESSREPLY, "address mask reply"); -#undef _ - default: - s = format (s, "unknown type 0x%x", icmp_type); - } - - if (icmp_type == ICMP_DEST_UNREACH) - { - switch (icmp_code) - { -#define _(f,str) case ICMP_##f: s = format (s, " " # str); break; - _ (NET_UNREACH, "network"); - _ (HOST_UNREACH, "host"); - _ (PROT_UNREACH, "protocol"); - _ (PORT_UNREACH, "port"); - _ (FRAG_NEEDED, ": fragmentation needed/DF set"); - _ (SR_FAILED, "source route failed"); - _ (NET_UNKNOWN, "network unknown"); - _ (HOST_UNKNOWN, "host unknown"); - _ (HOST_ISOLATED, "host isolated"); - _ (NET_ANO, "network: admin. prohibited"); - _ (HOST_ANO, "host: admin. prohibited"); - _ (NET_UNR_TOS, "network for type-of-service"); - _ (HOST_UNR_TOS, "host for type-of-service"); - _ (PKT_FILTERED, ": packet filtered"); - _ (PREC_VIOLATION, "precedence violation"); - _ (PREC_CUTOFF, "precedence cut off"); -#undef _ - default: - s = format (s, "unknown code 0x%x", icmp_code); - } - } - else if (icmp_type == ICMP_REDIRECT) - { - switch (icmp_code) - { -#define _(f,str) case ICMP_##f: s = format (s, " " # str); break; - _ (REDIR_NET, "network"); - _ (REDIR_HOST, "host"); - _ (REDIR_NETTOS, "network for type-of-service"); - _ (REDIR_HOSTTOS, "host for type-of-service"); -#undef _ - default: - s = format (s, "unknown code 0x%x", icmp_code); - } - } - else if (icmp_type == ICMP_TIME_EXCEEDED) - { - switch (icmp_code) - { -#define _(f,str) case ICMP_##f: s = format (s, " " # str); break; - _ (EXC_TTL, "time-to-live zero in transit"); - _ (EXC_FRAGTIME, "time-to-live zero during reassembly"); -#undef _ - default: - s = format (s, "unknown code 0x%x", icmp_code); - } - } - - return s; -} - -typedef struct { - u8 type; - u8 code; - u16 checksum; -} icmp4_t; - -u8 * format_icmp4_packet (u8 * s, va_list * args) -{ - u8 * p = va_arg (*args, u8 *); - struct iphdr * ip = (void *) p; - icmp4_t * icmp = (void *) (ip + 1); - s = format (s, "icmp %U %U -> %U", - format_icmp4_type_and_code, icmp->type, icmp->code, - format_network_address, AF_INET, &ip->saddr, - format_network_address, AF_INET, &ip->daddr); - - return s; -} - -u8 * format_ip4_tos_byte (u8 * s, va_list * args) -{ - uword tos = va_arg (*args, uword); - - if (tos & IPTOS_LOWDELAY) - s = format (s, "minimize-delay, "); - if (tos & IPTOS_MINCOST) - s = format (s, "minimize-cost, "); - if (tos & IPTOS_THROUGHPUT) - s = format (s, "maximize-throughput, "); - if (tos & IPTOS_RELIABILITY) - s = format (s, "maximize-reliability, "); - - switch (IPTOS_PREC (tos)) - { -#define _(x,y) case IPTOS_PREC_##x: s = format (s, y); break - _ (NETCONTROL, "network"); - _ (INTERNETCONTROL, "internet"); - _ (CRITIC_ECP, "critical"); - _ (FLASH, "flash"); - _ (FLASHOVERRIDE, "flash-override"); - _ (IMMEDIATE, "immediate"); - _ (PRIORITY, "priority"); - _ (ROUTINE, "routine"); -#undef _ - } - - return s; -} - -u8 * format_ip4_packet (u8 * s, va_list * args) -{ - u8 * p = va_arg (*args, u8 *); - struct iphdr * ip = (void *) p; - - static format_function_t * f[256]; - - if (! f[IPPROTO_TCP]) - { - f[IPPROTO_TCP] = format_tcp4_packet; - f[IPPROTO_UDP] = format_udp4_packet; - f[IPPROTO_ICMP] = format_icmp4_packet; - } - - if (f[ip->protocol]) - return format (s, "%U", f[ip->protocol], p); - - s = format (s, "%U: %U -> %U", - format_network_protocol, AF_INET, ip->protocol, - format_network_address, AF_INET, &ip->saddr, - format_network_address, AF_INET, &ip->daddr); - - return s; -} - -#define foreach_unix_arphrd_type \ - _ (NETROM, 0) \ - _ (ETHER, 1) \ - _ (EETHER, 2) \ - _ (AX25, 3) \ - _ (PRONET, 4) \ - _ (CHAOS, 5) \ - _ (IEEE802, 6) \ - _ (ARCNET, 7) \ - _ (APPLETLK, 8) \ - _ (DLCI, 15) \ - _ (ATM, 19) \ - _ (METRICOM, 23) \ - _ (IEEE1394, 24) \ - _ (EUI64, 27) \ - _ (INFINIBAND, 32) \ - _ (SLIP, 256) \ - _ (CSLIP, 257) \ - _ (SLIP6, 258) \ - _ (CSLIP6, 259) \ - _ (RSRVD, 260) \ - _ (ADAPT, 264) \ - _ (ROSE, 270) \ - _ (X25, 271) \ - _ (HWX25, 272) \ - _ (PPP, 512) \ - _ (HDLC, 513) \ - _ (LAPB, 516) \ - _ (DDCMP, 517) \ - _ (RAWHDLC, 518) \ - _ (TUNNEL, 768) \ - _ (TUNNEL6, 769) \ - _ (FRAD, 770) \ - _ (SKIP, 771) \ - _ (LOOPBACK, 772) \ - _ (LOCALTLK, 773) \ - _ (FDDI, 774) \ - _ (BIF, 775) \ - _ (SIT, 776) \ - _ (IPDDP, 777) \ - _ (IPGRE, 778) \ - _ (PIMREG, 779) \ - _ (HIPPI, 780) \ - _ (ASH, 781) \ - _ (ECONET, 782) \ - _ (IRDA, 783) \ - _ (FCPP, 784) \ - _ (FCAL, 785) \ - _ (FCPL, 786) \ - _ (FCFABRIC, 787) \ - _ (IEEE802_TR, 800) \ - _ (IEEE80211, 801) \ - _ (IEEE80211_PRISM, 802) \ - _ (IEEE80211_RADIOTAP, 803) \ - _ (VOID, 0xFFFF) \ - _ (NONE, 0xFFFE) - -u8 * format_unix_arphrd (u8 * s, va_list * args) -{ -#ifndef __COVERITY__ /* doesn't understand this at all... */ - u32 x = va_arg (*args, u32); - char * t; - switch (x) - { -#define _(f,n) case ARPHRD_##f: t = #f; break; - foreach_unix_arphrd_type -#undef _ - default: - t = 0; - break; - } - - if (t) - s = format (s, "%s", t); - else - s = format (s, "unknown 0x%x", x); -#endif - return s; -} - -#define foreach_unix_interface_flag \ - _ (up) \ - _ (broadcast) \ - _ (debug) \ - _ (loopback) \ - _ (pointopoint) \ - _ (notrailers) \ - _ (running) \ - _ (noarp) \ - _ (promisc) \ - _ (allmulti) \ - _ (master) \ - _ (slave) \ - _ (multicast) \ - _ (portsel) \ - _ (automedia) \ - _ (dynamic) \ - _ (lower_up) \ - _ (dormant) \ - _ (echo) - -static char * unix_interface_flag_names[] = { -#define _(f) #f, - foreach_unix_interface_flag -#undef _ -}; - -u8 * format_unix_interface_flags (u8 * s, va_list * args) -{ - u32 x = va_arg (*args, u32); - u32 i; - - if (x == 0) - s = format (s, "none"); - else foreach_set_bit (i, x, ({ - if (i < ARRAY_LEN (unix_interface_flag_names)) - s = format (s, "%s", unix_interface_flag_names[i]); - else - s = format (s, "unknown %d", i); - if (x >> (i + 1)) - s = format (s, ", "); - })); - return s; -} - -typedef struct { - u16 ar_hrd; /* format of hardware address */ - u16 ar_pro; /* format of protocol address */ - u8 ar_hln; /* length of hardware address */ - u8 ar_pln; /* length of protocol address */ - u16 ar_op; /* ARP opcode (command) */ - u8 ar_sha[6]; /* sender hardware address */ - u8 ar_spa[4]; /* sender IP address */ - u8 ar_tha[6]; /* target hardware address */ - u8 ar_tpa[4]; /* target IP address */ -} arp_ether_ip4_t; - -u8 * format_arp_packet (u8 * s, va_list * args) -{ - arp_ether_ip4_t * a = va_arg (*args, arp_ether_ip4_t *); - char * op = "unknown"; - - if (a->ar_pro != ETH_P_IP || - a->ar_hrd != ARPHRD_ETHER) - return s; - - switch (a->ar_op) - { -#define _(f) case ARPOP_##f: op = #f; break; - _ (REQUEST); - _ (REPLY); - _ (RREQUEST); - _ (RREPLY); -#undef _ - } - - s = format (s, "%s %U %U -> %U %U", - op, - format_network_address, AF_INET, a->ar_spa, - format_network_address, AF_UNSPEC, a->ar_sha, - format_network_address, AF_INET, a->ar_tpa, - format_network_address, AF_UNSPEC, a->ar_tha); - return s; -} - -u8 * format_ethernet_proto (u8 * s, va_list * args) -{ - uword type = va_arg (*args, uword); - char * t = 0; - - switch (type) - { - case 0: t = "BPDU"; break; -#define _(f) case ETH_P_##f: t = #f; break; - _ (LOOP); - _ (PUP); -#ifdef ETH_P_PUPAT - _ (PUPAT); -#endif - _ (IP); - _ (X25); - _ (ARP); - _ (BPQ); -#ifdef ETH_P_PUPAT - _ (IEEEPUP); - _ (IEEEPUPAT); -#endif - _ (DEC); - _ (DNA_DL); - _ (DNA_RC); - _ (DNA_RT); - _ (LAT); - _ (DIAG); - _ (CUST); - _ (SCA); - _ (RARP); - _ (ATALK); - _ (AARP); - _ (IPX); - _ (IPV6); -#ifdef ETH_P_PPP_DISC - _ (PPP_DISC); - _ (PPP_SES); -#endif -#ifdef ETH_P_ATMMPOA - _ (ATMMPOA); - _ (ATMFATE); -#endif - _ (802_3); - _ (AX25); - _ (ALL); - _ (802_2); - _ (SNAP); - _ (DDCMP); - _ (WAN_PPP); - _ (PPP_MP); - _ (LOCALTALK); - _ (PPPTALK); - _ (TR_802_2); - _ (MOBITEX); - _ (CONTROL); - _ (IRDA); -#ifdef ETH_P_ECONET - _ (ECONET); -#endif -#undef _ - } - - if (t) - vec_add (s, t, strlen (t)); - else - s = format (s, "ether-type 0x%x", type); - return s; -} - -u8 * format_ethernet_packet (u8 * s, va_list * args) -{ - struct ethhdr * h = va_arg (*args, struct ethhdr *); - uword proto = h->h_proto; - u8 * payload = (void *) (h + 1); - uword indent; - - /* Check for 802.2/802.3 encapsulation. */ - if (proto < ETH_DATA_LEN) - { - typedef struct { - u8 dsap, ssap, control; - u8 orig_code[3]; - u16 proto; - } ethhdr_802_t; - ethhdr_802_t * h1 = (void *) (h + 1); - proto = h1->proto; - payload = (void *) (h1 + 1); - } - - indent = format_get_indent (s); - - s = format (s, "%U: %U -> %U", - format_ethernet_proto, proto, - format_network_address, AF_UNSPEC, h->h_source, - format_network_address, AF_UNSPEC, h->h_dest); - - switch (proto) - { - case ETH_P_ARP: - s = format (s, "\n%U%U", - format_white_space, indent, - format_arp_packet, payload); - break; - } - - return s; -} - -#ifndef __KERNEL__ -u8 * format_hostname (u8 * s, va_list * args) -{ - char buffer[1024]; - char * b = buffer; - if (gethostname (b, sizeof (buffer)) < 0) - b = "noname"; - return format (s, "%s", b); -} -#endif - -#ifndef __KERNEL__ -u8 * format_timeval (u8 * s, va_list * args) -{ - char * fmt = va_arg (*args, char *); - struct timeval * tv = va_arg (*args, struct timeval *); - struct tm * tm; - word msec; - char * f, c; - - if (! fmt) - fmt = "y/m/d H:M:S:F"; - - if (! tv) - { - static struct timeval now; - gettimeofday (&now, 0); - tv = &now; - } - - msec = flt_round_nearest (1e-3 * tv->tv_usec); - if (msec >= 1000) - { msec = 0; tv->tv_sec++; } - - { - time_t t = tv->tv_sec; - tm = localtime (&t); - } - - for (f = fmt; *f; f++) - { - uword what; - char * what_fmt = "%d"; - - switch (c = *f) - { - default: - vec_add1 (s, c); - continue; - - case 'y': - what = 1900 + tm->tm_year; - what_fmt = "%4d"; - break; - case 'm': - what = tm->tm_mon + 1; - what_fmt = "%2d"; - break; - case 'd': - what = tm->tm_mday; - what_fmt = "%2d"; - break; - case 'H': - what = tm->tm_hour; - what_fmt = "%02d"; - break; - case 'M': - what = tm->tm_min; - what_fmt = "%02d"; - break; - case 'S': - what = tm->tm_sec; - what_fmt = "%02d"; - break; - case 'F': - what = msec; - what_fmt = "%03d"; - break; - } - - s = format (s, what_fmt, what); - } - - return s; -} - -u8 * format_time_float (u8 * s, va_list * args) -{ - u8 * fmt = va_arg (*args, u8 *); - f64 t = va_arg (*args, f64); - struct timeval tv; - if (t <= 0) - t = unix_time_now (); - tv.tv_sec = t; - tv.tv_usec = 1e6*(t - tv.tv_sec); - return format (s, "%U", format_timeval, fmt, &tv); -} - -u8 * format_signal (u8 * s, va_list * args) -{ - uword signum = va_arg (*args, uword); - char * t = 0; - switch (signum) - { -#define _(x) case x: t = #x; break; - _ (SIGHUP); - _ (SIGINT); - _ (SIGQUIT); - _ (SIGILL); - _ (SIGTRAP); - _ (SIGABRT); - _ (SIGBUS); - _ (SIGFPE); - _ (SIGKILL); - _ (SIGUSR1); - _ (SIGSEGV); - _ (SIGUSR2); - _ (SIGPIPE); - _ (SIGALRM); - _ (SIGTERM); -#ifdef SIGSTKFLT - _ (SIGSTKFLT); -#endif - _ (SIGCHLD); - _ (SIGCONT); - _ (SIGSTOP); - _ (SIGTSTP); - _ (SIGTTIN); - _ (SIGTTOU); - _ (SIGURG); - _ (SIGXCPU); - _ (SIGXFSZ); - _ (SIGVTALRM); - _ (SIGPROF); - _ (SIGWINCH); - _ (SIGIO); - _ (SIGPWR); -#ifdef SIGSYS - _ (SIGSYS); -#endif -#undef _ - default: - return format (s, "unknown %d", signum); - } - - vec_add (s, t, strlen (t)); - return s; -} - -u8 * format_ucontext_pc (u8 * s, va_list * args) -{ - ucontext_t * uc __attribute__((unused)); - unsigned long * regs = 0; - uword reg_no = 0; - - uc = va_arg (*args, ucontext_t *); - -#if defined (powerpc) - regs = &uc->uc_mcontext.uc_regs->gregs[0]; -#elif defined (powerpc64) - regs = &uc->uc_mcontext.uc_regs->gp_regs[0]; -#elif defined (i386) || defined (__x86_64__) - regs = (void *) &uc->uc_mcontext.gregs[0]; -#endif - -#if defined (powerpc) || defined (powerpc64) - reg_no = PT_NIP; -#elif defined (i386) - reg_no = REG_EIP; -#elif defined (__x86_64__) - reg_no = REG_RIP; -#else - reg_no = 0; - regs = 0; -#endif - - if (! regs) - return format (s, "unsupported"); - else - return format (s, "%p", regs[reg_no]); -} - -#endif /* __KERNEL__ */ diff --git a/vppinfra/vppinfra/unix-kelog.c b/vppinfra/vppinfra/unix-kelog.c deleted file mode 100644 index 88428ee8f2e..00000000000 --- a/vppinfra/vppinfra/unix-kelog.c +++ /dev/null @@ -1,415 +0,0 @@ -/* - Copyright (c) 2010 Cisco and/or its affiliates. - - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. -*/ - -#include <vppinfra/error.h> -#include <vppinfra/unix.h> -#include <vppinfra/elog.h> -#include <vppinfra/format.h> -#include <vppinfra/os.h> - -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <time.h> - -typedef enum -{ - RUNNING = 0, - WAKEUP, -} sched_event_type_t; - -typedef struct -{ - u32 cpu; - u8 *task; - u32 pid; - f64 timestamp; - sched_event_type_t type; -} sched_event_t; - -void -kelog_init (elog_main_t * em, char *kernel_tracer, u32 n_events) -{ - int enable_fd, current_tracer_fd, data_fd; - int len; - struct timespec ts, ts2; - char *trace_enable = "/debug/tracing/tracing_enabled"; - char *current_tracer = "/debug/tracing/current_tracer"; - char *trace_data = "/debug/tracing/trace"; - f64 realtime, monotonic; - f64 freq, secs_per_clock; - - ASSERT (kernel_tracer); - - /*$$$$ fixme */ - n_events = 1 << 18; - - /* init first so we won't hurt ourselves if we bail */ - elog_init (em, n_events); - - enable_fd = open (trace_enable, O_RDWR); - if (enable_fd < 0) - { - clib_warning ("Couldn't open %s", trace_enable); - return; - } - /* disable kernel tracing */ - if (write (enable_fd, "0\n", 2) != 2) - { - clib_unix_warning ("disable tracing"); - close (enable_fd); - return; - } - - /* - * open + clear the data buffer. - * see .../linux/kernel/trace/trace.c:tracing_open() - */ - data_fd = open (trace_data, O_RDWR | O_TRUNC); - if (data_fd < 0) - { - clib_warning ("Couldn't open+clear %s", trace_data); - return; - } - close (data_fd); - - /* configure tracing */ - current_tracer_fd = open (current_tracer, O_RDWR); - - if (current_tracer_fd < 0) - { - clib_warning ("Couldn't open %s", current_tracer); - close (enable_fd); - return; - } - - len = strlen (kernel_tracer); - - if (write (current_tracer_fd, kernel_tracer, len) != len) - { - clib_unix_warning ("configure trace"); - close (current_tracer_fd); - close (enable_fd); - return; - } - - close (current_tracer_fd); - - /* - * The kernel event log uses CLOCK_MONOTONIC timestamps, - * not CLOCK_REALTIME timestamps. These differ by a constant - * but the constant is not available in user mode. - * This estimate will be off by one syscall round-trip. - */ - clib_time_init (&em->cpu_timer); - em->init_time.cpu = em->cpu_timer.init_cpu_time; - syscall (SYS_clock_gettime, CLOCK_MONOTONIC, &ts); - - /* enable kernel tracing */ - if (write (enable_fd, "1\n", 2) != 2) - { - clib_unix_warning ("enable tracing"); - close (enable_fd); - return; - } - - close (enable_fd); -} - - -u8 * -format_sched_event (u8 * s, va_list * va) -{ - sched_event_t *e = va_arg (*va, sched_event_t *); - - s = format (s, "cpu %d task %10s type %s timestamp %12.6f\n", - e->cpu, e->task, e->type ? "WAKEUP " : "RUNNING", e->timestamp); - - return s; -} - -sched_event_t * -parse_sched_switch_trace (u8 * tdata, u32 * index) -{ - u8 *cp = tdata + *index; - u8 *limit = tdata + vec_len (tdata); - int colons; - static sched_event_t event; - sched_event_t *e = &event; - static u8 *task_name; - u32 secs, usecs; - int i; - -again: - /* eat leading w/s */ - while (cp < limit && (*cp == ' ' && *cp == '\t')) - cp++; - if (cp == limit) - return 0; - - /* header line */ - if (*cp == '#') - { - while (cp < limit && (*cp != '\n')) - cp++; - if (*cp == '\n') - { - cp++; - goto again; - } - clib_warning ("bugger 0"); - return 0; - } - - while (cp < limit && *cp != ']') - cp++; - - if (*cp == 0) - return 0; - - if (*cp != ']') - { - clib_warning ("bugger 0.1"); - return 0; - } - - cp++; - while (cp < limit && (*cp == ' ' && *cp == '\t')) - cp++; - if (cp == limit) - { - clib_warning ("bugger 0.2"); - return 0; - } - - secs = atoi (cp); - - while (cp < limit && (*cp != '.')) - cp++; - - if (cp == limit) - { - clib_warning ("bugger 0.3"); - return 0; - } - - cp++; - - usecs = atoi (cp); - - e->timestamp = ((f64) secs) + ((f64) usecs) * 1e-6; - - /* eat up to third colon */ - for (i = 0; i < 3; i++) - { - while (cp < limit && *cp != ':') - cp++; - cp++; - } - --cp; - if (*cp != ':') - { - clib_warning ("bugger 1"); - return 0; - } - /* aim at '>' (switch-to) / '+' (wakeup) */ - cp += 5; - if (cp >= limit) - { - clib_warning ("bugger 2"); - return 0; - } - if (*cp == '>') - e->type = RUNNING; - else if (*cp == '+') - e->type = WAKEUP; - else - { - clib_warning ("bugger 3"); - return 0; - } - - cp += 3; - if (cp >= limit) - { - clib_warning ("bugger 4"); - return 0; - } - - e->cpu = atoi (cp); - cp += 4; - - if (cp >= limit) - { - clib_warning ("bugger 4"); - return 0; - } - while (cp < limit && (*cp == ' ' || *cp == '\t')) - cp++; - - e->pid = atoi (cp); - - for (i = 0; i < 2; i++) - { - while (cp < limit && *cp != ':') - cp++; - cp++; - } - --cp; - if (*cp != ':') - { - clib_warning ("bugger 5"); - return 0; - } - - cp += 3; - if (cp >= limit) - { - clib_warning ("bugger 6"); - return 0; - } - while (cp < limit && (*cp != ' ' && *cp != '\n')) - { - vec_add1 (task_name, *cp); - cp++; - } - vec_add1 (task_name, 0); - /* _vec_len() = 0 in caller */ - e->task = task_name; - - if (cp < limit) - cp++; - - *index = cp - tdata; - return e; -} - -static u32 -elog_id_for_pid (elog_main_t * em, u8 * name, u32 pid) -{ - uword *p, r; - mhash_t *h = &em->string_table_hash; - - if (!em->string_table_hash.hash) - mhash_init (h, sizeof (uword), sizeof (pid)); - - p = mhash_get (h, &pid); - if (p) - return p[0]; - r = elog_string (em, "%s(%d)", name, pid); - mhash_set (h, &pid, r, /* old_value */ 0); - return r; -} - -void -kelog_collect_sched_switch_trace (elog_main_t * em) -{ - int enable_fd, data_fd; - char *trace_enable = "/debug/tracing/tracing_enabled"; - char *trace_data = "/debug/tracing/trace"; - u8 *data = 0; - u8 *dp; - int bytes, total_bytes; - u32 pos; - sched_event_t *evt; - u64 nsec_to_add; - u32 index; - f64 clocks_per_sec; - - enable_fd = open (trace_enable, O_RDWR); - if (enable_fd < 0) - { - clib_warning ("Couldn't open %s", trace_enable); - return; - } - /* disable kernel tracing */ - if (write (enable_fd, "0\n", 2) != 2) - { - clib_unix_warning ("disable tracing"); - close (enable_fd); - return; - } - close (enable_fd); - - /* Read the trace data */ - data_fd = open (trace_data, O_RDWR); - if (data_fd < 0) - { - clib_warning ("Couldn't open %s", trace_data); - return; - } - - /* - * Extract trace into a vector. Note that seq_printf() [kernel] - * is not guaranteed to produce 4096 bytes at a time. - */ - vec_validate (data, 4095); - total_bytes = 0; - pos = 0; - while (1) - { - bytes = read (data_fd, data + pos, 4096); - if (bytes <= 0) - break; - - total_bytes += bytes; - _vec_len (data) = total_bytes; - - pos = vec_len (data); - vec_validate (data, vec_len (data) + 4095); - } - vec_add1 (data, 0); - - /* Synthesize events */ - em->is_enabled = 1; - - index = 0; - while ((evt = parse_sched_switch_trace (data, &index))) - { - u64 fake_cpu_clock; - - fake_cpu_clock = evt->timestamp * em->cpu_timer.clocks_per_second; - { - ELOG_TYPE_DECLARE (e) = - { - .format = "%d: %s %s",.format_args = "i4T4t4",.n_enum_strings = - 2,.enum_strings = - { - "running", "wakeup",} - ,}; - struct - { - u32 cpu, string_table_offset, which; - } *ed; - - ed = elog_event_data_not_inline (em, &__ELOG_TYPE_VAR (e), - &em->default_track, fake_cpu_clock); - ed->cpu = evt->cpu; - ed->string_table_offset = elog_id_for_pid (em, evt->task, evt->pid); - ed->which = evt->type; - } - _vec_len (evt->task) = 0; - } - em->is_enabled = 0; -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/unix-misc.c b/vppinfra/vppinfra/unix-misc.c deleted file mode 100644 index 2928369d52e..00000000000 --- a/vppinfra/vppinfra/unix-misc.c +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2005 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include <vppinfra/error.h> -#include <vppinfra/os.h> -#include <vppinfra/unix.h> - -#include <sys/stat.h> -#include <sys/types.h> -#include <sys/uio.h> /* writev */ -#include <fcntl.h> -#include <stdio.h> /* for sprintf */ - -clib_error_t * -unix_file_n_bytes (char *file, uword * result) -{ - struct stat s; - - if (stat (file, &s) < 0) - return clib_error_return_unix (0, "stat `%s'", file); - - if (S_ISREG (s.st_mode)) - *result = s.st_size; - else - *result = 0; - - return /* no error */ 0; -} - -clib_error_t * -unix_file_read_contents (char *file, u8 * result, uword n_bytes) -{ - int fd = -1; - uword n_done, n_left; - clib_error_t *error = 0; - u8 *v = result; - - if ((fd = open (file, 0)) < 0) - return clib_error_return_unix (0, "open `%s'", file); - - n_left = n_bytes; - n_done = 0; - while (n_left > 0) - { - int n_read; - if ((n_read = read (fd, v + n_done, n_left)) < 0) - { - error = clib_error_return_unix (0, "open `%s'", file); - goto done; - } - - /* End of file. */ - if (n_read == 0) - break; - - n_left -= n_read; - n_done += n_read; - } - - if (n_left > 0) - { - error = - clib_error_return (0, - " `%s' expected to read %wd bytes; read only %wd", - file, n_bytes, n_bytes - n_left); - goto done; - } - -done: - close (fd); - return error; -} - -clib_error_t * -unix_file_contents (char *file, u8 ** result) -{ - uword n_bytes; - clib_error_t *error = 0; - u8 *v; - - if ((error = unix_file_n_bytes (file, &n_bytes))) - return error; - - v = 0; - vec_resize (v, n_bytes); - - error = unix_file_read_contents (file, v, n_bytes); - - if (error) - vec_free (v); - else - *result = v; - - return error; -} - -clib_error_t * -unix_proc_file_contents (char *file, u8 ** result) -{ - u8 *rv = 0; - uword pos; - int bytes, fd; - - /* Unfortunately, stat(/proc/XXX) returns zero... */ - fd = open (file, O_RDONLY); - - if (fd < 0) - return clib_error_return_unix (0, "open `%s'", file); - - vec_validate (rv, 4095); - pos = 0; - while (1) - { - bytes = read (fd, rv + pos, 4096); - if (bytes < 0) - { - close (fd); - vec_free (rv); - return clib_error_return_unix (0, "read '%s'", file); - } - - if (bytes == 0) - { - _vec_len (rv) = pos; - break; - } - pos += bytes; - vec_validate (rv, pos + 4095); - } - *result = rv; - close (fd); - return 0; -} - -void os_panic (void) __attribute__ ((weak)); - -void -os_panic (void) -{ - abort (); -} - -void os_exit (int) __attribute__ ((weak)); - -void -os_exit (int code) -{ - exit (code); -} - -void os_puts (u8 * string, uword string_length, uword is_error) - __attribute__ ((weak)); - -void -os_puts (u8 * string, uword string_length, uword is_error) -{ - int cpu = os_get_cpu_number (); - int ncpus = os_get_ncpus (); - char buf[64]; - int fd = is_error ? 2 : 1; - struct iovec iovs[2]; - int n_iovs = 0; - - if (ncpus > 1) - { - snprintf (buf, sizeof (buf), "%d: ", cpu); - - iovs[n_iovs].iov_base = buf; - iovs[n_iovs].iov_len = strlen (buf); - n_iovs++; - } - - iovs[n_iovs].iov_base = string; - iovs[n_iovs].iov_len = string_length; - n_iovs++; - - if (writev (fd, iovs, n_iovs) < 0) - ; -} - -void os_out_of_memory (void) __attribute__ ((weak)); -void -os_out_of_memory (void) -{ - os_panic (); -} - -uword os_get_cpu_number (void) __attribute__ ((weak)); -uword -os_get_cpu_number (void) -{ - return 0; -} - -uword os_get_ncpus (void) __attribute__ ((weak)); -uword -os_get_ncpus (void) -{ - return 1; -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/unix.h b/vppinfra/vppinfra/unix.h deleted file mode 100644 index 29114cfece6..00000000000 --- a/vppinfra/vppinfra/unix.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2005 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_clib_unix_h -#define included_clib_unix_h - -#include <vppinfra/error.h> - -/* Number of bytes in a Unix file. */ -clib_error_t *unix_file_n_bytes (char *file, uword * result); - -/* Read file contents into given buffer. */ -clib_error_t *unix_file_read_contents (char *file, u8 * result, - uword n_bytes); - -/* Read and return contents of Unix file. */ -clib_error_t *unix_file_contents (char *file, u8 ** result); - -/* As above but for /proc file system on Linux. */ -clib_error_t *unix_proc_file_contents (char *file, u8 ** result); - -#endif /* included_clib_unix_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/valgrind.h b/vppinfra/vppinfra/valgrind.h deleted file mode 100644 index e74d7e828be..00000000000 --- a/vppinfra/vppinfra/valgrind.h +++ /dev/null @@ -1,4030 +0,0 @@ -/* -*- c -*- - ---------------------------------------------------------------- - - Notice that the following BSD-style license applies to this one - file (valgrind.h) only. The rest of Valgrind is licensed under the - terms of the GNU General Public License, version 2, unless - otherwise indicated. See the COPYING file in the source - distribution for details. - - ---------------------------------------------------------------- - - This file is part of Valgrind, a dynamic binary instrumentation - framework. - - Copyright (C) 2000-2009 Julian Seward. All rights reserved. - - 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. The origin of this software must not be misrepresented; you must - not claim that you wrote the original software. If you use this - software in a product, an acknowledgment in the product - documentation would be appreciated but is not required. - - 3. Altered source versions must be plainly marked as such, and must - not be misrepresented as being the original software. - - 4. The name of the author may not 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. - - ---------------------------------------------------------------- - - Notice that the above BSD-style license applies to this one file - (valgrind.h) only. The entire rest of Valgrind is licensed under - the terms of the GNU General Public License, version 2. See the - COPYING file in the source distribution for details. - - ---------------------------------------------------------------- -*/ - - -/* This file is for inclusion into client (your!) code. - - You can use these macros to manipulate and query Valgrind's - execution inside your own programs. - - The resulting executables will still run without Valgrind, just a - little bit more slowly than they otherwise would, but otherwise - unchanged. When not running on valgrind, each client request - consumes very few (eg. 7) instructions, so the resulting performance - loss is negligible unless you plan to execute client requests - millions of times per second. Nevertheless, if that is still a - problem, you can compile with the NVALGRIND symbol defined (gcc - -DNVALGRIND) so that client requests are not even compiled in. */ - -#ifndef __VALGRIND_H -#define __VALGRIND_H - -#include <stdarg.h> - -/* Nb: this file might be included in a file compiled with -ansi. So - we can't use C++ style "//" comments nor the "asm" keyword (instead - use "__asm__"). */ - -/* Derive some tags indicating what the target platform is. Note - that in this file we're using the compiler's CPP symbols for - identifying architectures, which are different to the ones we use - within the rest of Valgrind. Note, __powerpc__ is active for both - 32 and 64-bit PPC, whereas __powerpc64__ is only active for the - latter (on Linux, that is). */ -#undef PLAT_x86_linux -#undef PLAT_amd64_linux -#undef PLAT_ppc32_linux -#undef PLAT_ppc64_linux -#undef PLAT_ppc32_aix5 -#undef PLAT_ppc64_aix5 - - -#if defined(_AIX) && defined(__64BIT__) -#define PLAT_ppc64_aix5 1 -#elif defined(_AIX) && !defined(__64BIT__) -#define PLAT_ppc32_aix5 1 -#elif defined(__APPLE__) && defined(__i386__) -#define PLAT_x86_darwin 1 -#elif defined(__APPLE__) && defined(__x86_64__) -#define PLAT_amd64_darwin 1 -#elif defined(__i386__) -#define PLAT_x86_linux 1 -#elif defined(__x86_64__) -#define PLAT_amd64_linux 1 -#elif defined(__powerpc__) && !defined(__powerpc64__) -#define PLAT_ppc32_linux 1 -#elif defined(__powerpc__) && defined(__powerpc64__) -#define PLAT_ppc64_linux 1 -#else -/* If we're not compiling for our target platform, don't generate - any inline asms. */ -#if !defined(NVALGRIND) -#define NVALGRIND 1 -#endif -#endif - - -/* ------------------------------------------------------------------ */ -/* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */ -/* in here of use to end-users -- skip to the next section. */ -/* ------------------------------------------------------------------ */ - -#if defined(NVALGRIND) - -/* Define NVALGRIND to completely remove the Valgrind magic sequence - from the compiled code (analogous to NDEBUG's effects on - assert()) */ -#define VALGRIND_DO_CLIENT_REQUEST( \ - _zzq_rlval, _zzq_default, _zzq_request, \ - _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ - { \ - (_zzq_rlval) = (_zzq_default); \ - } - -#else /* ! NVALGRIND */ - -/* The following defines the magic code sequences which the JITter - spots and handles magically. Don't look too closely at them as - they will rot your brain. - - The assembly code sequences for all architectures is in this one - file. This is because this file must be stand-alone, and we don't - want to have multiple files. - - For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default - value gets put in the return slot, so that everything works when - this is executed not under Valgrind. Args are passed in a memory - block, and so there's no intrinsic limit to the number that could - be passed, but it's currently five. - - The macro args are: - _zzq_rlval result lvalue - _zzq_default default value (result returned when running on real CPU) - _zzq_request request code - _zzq_arg1..5 request params - - The other two macros are used to support function wrapping, and are - a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the - guest's NRADDR pseudo-register and whatever other information is - needed to safely run the call original from the wrapper: on - ppc64-linux, the R2 value at the divert point is also needed. This - information is abstracted into a user-visible type, OrigFn. - - VALGRIND_CALL_NOREDIR_* behaves the same as the following on the - guest, but guarantees that the branch instruction will not be - redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64: - branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a - complete inline asm, since it needs to be combined with more magic - inline asm stuff to be useful. -*/ - -/* ------------------------- x86-{linux,darwin} ---------------- */ - -#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin) - -typedef struct -{ - unsigned int nraddr; /* where's the code? */ -} -OrigFn; - -#define __SPECIAL_INSTRUCTION_PREAMBLE \ - "roll $3, %%edi ; roll $13, %%edi\n\t" \ - "roll $29, %%edi ; roll $19, %%edi\n\t" - -#define VALGRIND_DO_CLIENT_REQUEST( \ - _zzq_rlval, _zzq_default, _zzq_request, \ - _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ - { volatile unsigned int _zzq_args[6]; \ - volatile unsigned int _zzq_result; \ - _zzq_args[0] = (unsigned int)(_zzq_request); \ - _zzq_args[1] = (unsigned int)(_zzq_arg1); \ - _zzq_args[2] = (unsigned int)(_zzq_arg2); \ - _zzq_args[3] = (unsigned int)(_zzq_arg3); \ - _zzq_args[4] = (unsigned int)(_zzq_arg4); \ - _zzq_args[5] = (unsigned int)(_zzq_arg5); \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %EDX = client_request ( %EAX ) */ \ - "xchgl %%ebx,%%ebx" \ - : "=d" (_zzq_result) \ - : "a" (&_zzq_args[0]), "0" (_zzq_default) \ - : "cc", "memory" \ - ); \ - _zzq_rlval = _zzq_result; \ - } - -#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ - { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ - volatile unsigned int __addr; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %EAX = guest_NRADDR */ \ - "xchgl %%ecx,%%ecx" \ - : "=a" (__addr) \ - : \ - : "cc", "memory" \ - ); \ - _zzq_orig->nraddr = __addr; \ - } - -#define VALGRIND_CALL_NOREDIR_EAX \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* call-noredir *%EAX */ \ - "xchgl %%edx,%%edx\n\t" -#endif /* PLAT_x86_linux || PLAT_x86_darwin */ - -/* ------------------------ amd64-{linux,darwin} --------------- */ - -#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin) - -typedef struct -{ - unsigned long long int nraddr; /* where's the code? */ -} -OrigFn; - -#define __SPECIAL_INSTRUCTION_PREAMBLE \ - "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \ - "rolq $61, %%rdi ; rolq $51, %%rdi\n\t" - -#define VALGRIND_DO_CLIENT_REQUEST( \ - _zzq_rlval, _zzq_default, _zzq_request, \ - _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ - { volatile unsigned long long int _zzq_args[6]; \ - volatile unsigned long long int _zzq_result; \ - _zzq_args[0] = (unsigned long long int)(_zzq_request); \ - _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \ - _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \ - _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \ - _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \ - _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %RDX = client_request ( %RAX ) */ \ - "xchgq %%rbx,%%rbx" \ - : "=d" (_zzq_result) \ - : "a" (&_zzq_args[0]), "0" (_zzq_default) \ - : "cc", "memory" \ - ); \ - _zzq_rlval = _zzq_result; \ - } - -#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ - { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ - volatile unsigned long long int __addr; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %RAX = guest_NRADDR */ \ - "xchgq %%rcx,%%rcx" \ - : "=a" (__addr) \ - : \ - : "cc", "memory" \ - ); \ - _zzq_orig->nraddr = __addr; \ - } - -#define VALGRIND_CALL_NOREDIR_RAX \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* call-noredir *%RAX */ \ - "xchgq %%rdx,%%rdx\n\t" -#endif /* PLAT_amd64_linux || PLAT_amd64_darwin */ - -/* ------------------------ ppc32-linux ------------------------ */ - -#if defined(PLAT_ppc32_linux) - -typedef struct -{ - unsigned int nraddr; /* where's the code? */ -} -OrigFn; - -#define __SPECIAL_INSTRUCTION_PREAMBLE \ - "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \ - "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t" - -#define VALGRIND_DO_CLIENT_REQUEST( \ - _zzq_rlval, _zzq_default, _zzq_request, \ - _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ - \ - { unsigned int _zzq_args[6]; \ - unsigned int _zzq_result; \ - unsigned int* _zzq_ptr; \ - _zzq_args[0] = (unsigned int)(_zzq_request); \ - _zzq_args[1] = (unsigned int)(_zzq_arg1); \ - _zzq_args[2] = (unsigned int)(_zzq_arg2); \ - _zzq_args[3] = (unsigned int)(_zzq_arg3); \ - _zzq_args[4] = (unsigned int)(_zzq_arg4); \ - _zzq_args[5] = (unsigned int)(_zzq_arg5); \ - _zzq_ptr = _zzq_args; \ - __asm__ volatile("mr 3,%1\n\t" /*default*/ \ - "mr 4,%2\n\t" /*ptr*/ \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* %R3 = client_request ( %R4 ) */ \ - "or 1,1,1\n\t" \ - "mr %0,3" /*result*/ \ - : "=b" (_zzq_result) \ - : "b" (_zzq_default), "b" (_zzq_ptr) \ - : "cc", "memory", "r3", "r4"); \ - _zzq_rlval = _zzq_result; \ - } - -#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ - { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ - unsigned int __addr; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %R3 = guest_NRADDR */ \ - "or 2,2,2\n\t" \ - "mr %0,3" \ - : "=b" (__addr) \ - : \ - : "cc", "memory", "r3" \ - ); \ - _zzq_orig->nraddr = __addr; \ - } - -#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* branch-and-link-to-noredir *%R11 */ \ - "or 3,3,3\n\t" -#endif /* PLAT_ppc32_linux */ - -/* ------------------------ ppc64-linux ------------------------ */ - -#if defined(PLAT_ppc64_linux) - -typedef struct -{ - unsigned long long int nraddr; /* where's the code? */ - unsigned long long int r2; /* what tocptr do we need? */ -} -OrigFn; - -#define __SPECIAL_INSTRUCTION_PREAMBLE \ - "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \ - "rotldi 0,0,61 ; rotldi 0,0,51\n\t" - -#define VALGRIND_DO_CLIENT_REQUEST( \ - _zzq_rlval, _zzq_default, _zzq_request, \ - _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ - \ - { unsigned long long int _zzq_args[6]; \ - register unsigned long long int _zzq_result __asm__("r3"); \ - register unsigned long long int* _zzq_ptr __asm__("r4"); \ - _zzq_args[0] = (unsigned long long int)(_zzq_request); \ - _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \ - _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \ - _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \ - _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \ - _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \ - _zzq_ptr = _zzq_args; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %R3 = client_request ( %R4 ) */ \ - "or 1,1,1" \ - : "=r" (_zzq_result) \ - : "0" (_zzq_default), "r" (_zzq_ptr) \ - : "cc", "memory"); \ - _zzq_rlval = _zzq_result; \ - } - -#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ - { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ - register unsigned long long int __addr __asm__("r3"); \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %R3 = guest_NRADDR */ \ - "or 2,2,2" \ - : "=r" (__addr) \ - : \ - : "cc", "memory" \ - ); \ - _zzq_orig->nraddr = __addr; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %R3 = guest_NRADDR_GPR2 */ \ - "or 4,4,4" \ - : "=r" (__addr) \ - : \ - : "cc", "memory" \ - ); \ - _zzq_orig->r2 = __addr; \ - } - -#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* branch-and-link-to-noredir *%R11 */ \ - "or 3,3,3\n\t" - -#endif /* PLAT_ppc64_linux */ - -/* ------------------------ ppc32-aix5 ------------------------- */ - -#if defined(PLAT_ppc32_aix5) - -typedef struct -{ - unsigned int nraddr; /* where's the code? */ - unsigned int r2; /* what tocptr do we need? */ -} -OrigFn; - -#define __SPECIAL_INSTRUCTION_PREAMBLE \ - "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \ - "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t" - -#define VALGRIND_DO_CLIENT_REQUEST( \ - _zzq_rlval, _zzq_default, _zzq_request, \ - _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ - \ - { unsigned int _zzq_args[7]; \ - register unsigned int _zzq_result; \ - register unsigned int* _zzq_ptr; \ - _zzq_args[0] = (unsigned int)(_zzq_request); \ - _zzq_args[1] = (unsigned int)(_zzq_arg1); \ - _zzq_args[2] = (unsigned int)(_zzq_arg2); \ - _zzq_args[3] = (unsigned int)(_zzq_arg3); \ - _zzq_args[4] = (unsigned int)(_zzq_arg4); \ - _zzq_args[5] = (unsigned int)(_zzq_arg5); \ - _zzq_args[6] = (unsigned int)(_zzq_default); \ - _zzq_ptr = _zzq_args; \ - __asm__ volatile("mr 4,%1\n\t" \ - "lwz 3, 24(4)\n\t" \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* %R3 = client_request ( %R4 ) */ \ - "or 1,1,1\n\t" \ - "mr %0,3" \ - : "=b" (_zzq_result) \ - : "b" (_zzq_ptr) \ - : "r3", "r4", "cc", "memory"); \ - _zzq_rlval = _zzq_result; \ - } - -#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ - { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ - register unsigned int __addr; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %R3 = guest_NRADDR */ \ - "or 2,2,2\n\t" \ - "mr %0,3" \ - : "=b" (__addr) \ - : \ - : "r3", "cc", "memory" \ - ); \ - _zzq_orig->nraddr = __addr; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %R3 = guest_NRADDR_GPR2 */ \ - "or 4,4,4\n\t" \ - "mr %0,3" \ - : "=b" (__addr) \ - : \ - : "r3", "cc", "memory" \ - ); \ - _zzq_orig->r2 = __addr; \ - } - -#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* branch-and-link-to-noredir *%R11 */ \ - "or 3,3,3\n\t" - -#endif /* PLAT_ppc32_aix5 */ - -/* ------------------------ ppc64-aix5 ------------------------- */ - -#if defined(PLAT_ppc64_aix5) - -typedef struct -{ - unsigned long long int nraddr; /* where's the code? */ - unsigned long long int r2; /* what tocptr do we need? */ -} -OrigFn; - -#define __SPECIAL_INSTRUCTION_PREAMBLE \ - "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \ - "rotldi 0,0,61 ; rotldi 0,0,51\n\t" - -#define VALGRIND_DO_CLIENT_REQUEST( \ - _zzq_rlval, _zzq_default, _zzq_request, \ - _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ - \ - { unsigned long long int _zzq_args[7]; \ - register unsigned long long int _zzq_result; \ - register unsigned long long int* _zzq_ptr; \ - _zzq_args[0] = (unsigned int long long)(_zzq_request); \ - _zzq_args[1] = (unsigned int long long)(_zzq_arg1); \ - _zzq_args[2] = (unsigned int long long)(_zzq_arg2); \ - _zzq_args[3] = (unsigned int long long)(_zzq_arg3); \ - _zzq_args[4] = (unsigned int long long)(_zzq_arg4); \ - _zzq_args[5] = (unsigned int long long)(_zzq_arg5); \ - _zzq_args[6] = (unsigned int long long)(_zzq_default); \ - _zzq_ptr = _zzq_args; \ - __asm__ volatile("mr 4,%1\n\t" \ - "ld 3, 48(4)\n\t" \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* %R3 = client_request ( %R4 ) */ \ - "or 1,1,1\n\t" \ - "mr %0,3" \ - : "=b" (_zzq_result) \ - : "b" (_zzq_ptr) \ - : "r3", "r4", "cc", "memory"); \ - _zzq_rlval = _zzq_result; \ - } - -#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ - { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ - register unsigned long long int __addr; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %R3 = guest_NRADDR */ \ - "or 2,2,2\n\t" \ - "mr %0,3" \ - : "=b" (__addr) \ - : \ - : "r3", "cc", "memory" \ - ); \ - _zzq_orig->nraddr = __addr; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %R3 = guest_NRADDR_GPR2 */ \ - "or 4,4,4\n\t" \ - "mr %0,3" \ - : "=b" (__addr) \ - : \ - : "r3", "cc", "memory" \ - ); \ - _zzq_orig->r2 = __addr; \ - } - -#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* branch-and-link-to-noredir *%R11 */ \ - "or 3,3,3\n\t" - -#endif /* PLAT_ppc64_aix5 */ - -/* Insert assembly code for other platforms here... */ - -#endif /* NVALGRIND */ - - -/* ------------------------------------------------------------------ */ -/* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */ -/* ugly. It's the least-worst tradeoff I can think of. */ -/* ------------------------------------------------------------------ */ - -/* This section defines magic (a.k.a appalling-hack) macros for doing - guaranteed-no-redirection macros, so as to get from function - wrappers to the functions they are wrapping. The whole point is to - construct standard call sequences, but to do the call itself with a - special no-redirect call pseudo-instruction that the JIT - understands and handles specially. This section is long and - repetitious, and I can't see a way to make it shorter. - - The naming scheme is as follows: - - CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc} - - 'W' stands for "word" and 'v' for "void". Hence there are - different macros for calling arity 0, 1, 2, 3, 4, etc, functions, - and for each, the possibility of returning a word-typed result, or - no result. -*/ - -/* Use these to write the name of your wrapper. NOTE: duplicates - VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. */ - -/* Use an extra level of macroisation so as to ensure the soname/fnname - args are fully macro-expanded before pasting them together. */ -#define VG_CONCAT4(_aa,_bb,_cc,_dd) _aa##_bb##_cc##_dd - -#define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \ - VG_CONCAT4(_vgwZU_,soname,_,fnname) - -#define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \ - VG_CONCAT4(_vgwZZ_,soname,_,fnname) - -/* Use this macro from within a wrapper function to collect the - context (address and possibly other info) of the original function. - Once you have that you can then use it in one of the CALL_FN_ - macros. The type of the argument _lval is OrigFn. */ -#define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval) - -/* Derivatives of the main macros below, for calling functions - returning void. */ - -#define CALL_FN_v_v(fnptr) \ - do { volatile unsigned long _junk; \ - CALL_FN_W_v(_junk,fnptr); } while (0) - -#define CALL_FN_v_W(fnptr, arg1) \ - do { volatile unsigned long _junk; \ - CALL_FN_W_W(_junk,fnptr,arg1); } while (0) - -#define CALL_FN_v_WW(fnptr, arg1,arg2) \ - do { volatile unsigned long _junk; \ - CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0) - -#define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \ - do { volatile unsigned long _junk; \ - CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0) - -#define CALL_FN_v_WWWW(fnptr, arg1,arg2,arg3,arg4) \ - do { volatile unsigned long _junk; \ - CALL_FN_W_WWWW(_junk,fnptr,arg1,arg2,arg3,arg4); } while (0) - -#define CALL_FN_v_5W(fnptr, arg1,arg2,arg3,arg4,arg5) \ - do { volatile unsigned long _junk; \ - CALL_FN_W_5W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5); } while (0) - -#define CALL_FN_v_6W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6) \ - do { volatile unsigned long _junk; \ - CALL_FN_W_6W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6); } while (0) - -#define CALL_FN_v_7W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6,arg7) \ - do { volatile unsigned long _junk; \ - CALL_FN_W_7W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6,arg7); } while (0) - -/* ------------------------- x86-{linux,darwin} ---------------- */ - -#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin) - -/* These regs are trashed by the hidden call. No need to mention eax - as gcc can already see that, plus causes gcc to bomb. */ -#define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx" - -/* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned - long) == 4. */ - -#define CALL_FN_W_v(lval, orig) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[1]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - __asm__ volatile( \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_W(lval, orig, arg1) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[2]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - __asm__ volatile( \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $4, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - __asm__ volatile( \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $8, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[4]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - __asm__ volatile( \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $12, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[5]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - __asm__ volatile( \ - "pushl 16(%%eax)\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $16, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[6]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - __asm__ volatile( \ - "pushl 20(%%eax)\n\t" \ - "pushl 16(%%eax)\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $20, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[7]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - __asm__ volatile( \ - "pushl 24(%%eax)\n\t" \ - "pushl 20(%%eax)\n\t" \ - "pushl 16(%%eax)\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $24, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[8]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - __asm__ volatile( \ - "pushl 28(%%eax)\n\t" \ - "pushl 24(%%eax)\n\t" \ - "pushl 20(%%eax)\n\t" \ - "pushl 16(%%eax)\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $28, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[9]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - __asm__ volatile( \ - "pushl 32(%%eax)\n\t" \ - "pushl 28(%%eax)\n\t" \ - "pushl 24(%%eax)\n\t" \ - "pushl 20(%%eax)\n\t" \ - "pushl 16(%%eax)\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $32, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[10]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - __asm__ volatile( \ - "pushl 36(%%eax)\n\t" \ - "pushl 32(%%eax)\n\t" \ - "pushl 28(%%eax)\n\t" \ - "pushl 24(%%eax)\n\t" \ - "pushl 20(%%eax)\n\t" \ - "pushl 16(%%eax)\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $36, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[11]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - _argvec[10] = (unsigned long)(arg10); \ - __asm__ volatile( \ - "pushl 40(%%eax)\n\t" \ - "pushl 36(%%eax)\n\t" \ - "pushl 32(%%eax)\n\t" \ - "pushl 28(%%eax)\n\t" \ - "pushl 24(%%eax)\n\t" \ - "pushl 20(%%eax)\n\t" \ - "pushl 16(%%eax)\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $40, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ - arg6,arg7,arg8,arg9,arg10, \ - arg11) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[12]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - _argvec[10] = (unsigned long)(arg10); \ - _argvec[11] = (unsigned long)(arg11); \ - __asm__ volatile( \ - "pushl 44(%%eax)\n\t" \ - "pushl 40(%%eax)\n\t" \ - "pushl 36(%%eax)\n\t" \ - "pushl 32(%%eax)\n\t" \ - "pushl 28(%%eax)\n\t" \ - "pushl 24(%%eax)\n\t" \ - "pushl 20(%%eax)\n\t" \ - "pushl 16(%%eax)\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $44, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ - arg6,arg7,arg8,arg9,arg10, \ - arg11,arg12) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[13]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - _argvec[10] = (unsigned long)(arg10); \ - _argvec[11] = (unsigned long)(arg11); \ - _argvec[12] = (unsigned long)(arg12); \ - __asm__ volatile( \ - "pushl 48(%%eax)\n\t" \ - "pushl 44(%%eax)\n\t" \ - "pushl 40(%%eax)\n\t" \ - "pushl 36(%%eax)\n\t" \ - "pushl 32(%%eax)\n\t" \ - "pushl 28(%%eax)\n\t" \ - "pushl 24(%%eax)\n\t" \ - "pushl 20(%%eax)\n\t" \ - "pushl 16(%%eax)\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $48, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#endif /* PLAT_x86_linux || PLAT_x86_darwin */ - -/* ------------------------ amd64-{linux,darwin} --------------- */ - -#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin) - -/* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */ - -/* These regs are trashed by the hidden call. */ -#define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \ - "rdi", "r8", "r9", "r10", "r11" - -/* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned - long) == 8. */ - -/* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_ - macros. In order not to trash the stack redzone, we need to drop - %rsp by 128 before the hidden call, and restore afterwards. The - nastyness is that it is only by luck that the stack still appears - to be unwindable during the hidden call - since then the behaviour - of any routine using this macro does not match what the CFI data - says. Sigh. - - Why is this important? Imagine that a wrapper has a stack - allocated local, and passes to the hidden call, a pointer to it. - Because gcc does not know about the hidden call, it may allocate - that local in the redzone. Unfortunately the hidden call may then - trash it before it comes to use it. So we must step clear of the - redzone, for the duration of the hidden call, to make it safe. - - Probably the same problem afflicts the other redzone-style ABIs too - (ppc64-linux, ppc32-aix5, ppc64-aix5); but for those, the stack is - self describing (none of this CFI nonsense) so at least messing - with the stack pointer doesn't give a danger of non-unwindable - stack. */ - -#define CALL_FN_W_v(lval, orig) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[1]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $128,%%rsp\n\t" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_W(lval, orig, arg1) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[2]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $128,%%rsp\n\t" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $128,%%rsp\n\t" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[4]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $128,%%rsp\n\t" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[5]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "movq 32(%%rax), %%rcx\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $128,%%rsp\n\t" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[6]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "movq 40(%%rax), %%r8\n\t" \ - "movq 32(%%rax), %%rcx\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $128,%%rsp\n\t" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[7]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "movq 48(%%rax), %%r9\n\t" \ - "movq 40(%%rax), %%r8\n\t" \ - "movq 32(%%rax), %%rcx\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - "addq $128,%%rsp\n\t" \ - VALGRIND_CALL_NOREDIR_RAX \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[8]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "pushq 56(%%rax)\n\t" \ - "movq 48(%%rax), %%r9\n\t" \ - "movq 40(%%rax), %%r8\n\t" \ - "movq 32(%%rax), %%rcx\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $8, %%rsp\n" \ - "addq $128,%%rsp\n\t" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[9]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "pushq 64(%%rax)\n\t" \ - "pushq 56(%%rax)\n\t" \ - "movq 48(%%rax), %%r9\n\t" \ - "movq 40(%%rax), %%r8\n\t" \ - "movq 32(%%rax), %%rcx\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $16, %%rsp\n" \ - "addq $128,%%rsp\n\t" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[10]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "pushq 72(%%rax)\n\t" \ - "pushq 64(%%rax)\n\t" \ - "pushq 56(%%rax)\n\t" \ - "movq 48(%%rax), %%r9\n\t" \ - "movq 40(%%rax), %%r8\n\t" \ - "movq 32(%%rax), %%rcx\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $24, %%rsp\n" \ - "addq $128,%%rsp\n\t" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[11]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - _argvec[10] = (unsigned long)(arg10); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "pushq 80(%%rax)\n\t" \ - "pushq 72(%%rax)\n\t" \ - "pushq 64(%%rax)\n\t" \ - "pushq 56(%%rax)\n\t" \ - "movq 48(%%rax), %%r9\n\t" \ - "movq 40(%%rax), %%r8\n\t" \ - "movq 32(%%rax), %%rcx\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $32, %%rsp\n" \ - "addq $128,%%rsp\n\t" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10,arg11) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[12]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - _argvec[10] = (unsigned long)(arg10); \ - _argvec[11] = (unsigned long)(arg11); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "pushq 88(%%rax)\n\t" \ - "pushq 80(%%rax)\n\t" \ - "pushq 72(%%rax)\n\t" \ - "pushq 64(%%rax)\n\t" \ - "pushq 56(%%rax)\n\t" \ - "movq 48(%%rax), %%r9\n\t" \ - "movq 40(%%rax), %%r8\n\t" \ - "movq 32(%%rax), %%rcx\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $40, %%rsp\n" \ - "addq $128,%%rsp\n\t" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10,arg11,arg12) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[13]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - _argvec[10] = (unsigned long)(arg10); \ - _argvec[11] = (unsigned long)(arg11); \ - _argvec[12] = (unsigned long)(arg12); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "pushq 96(%%rax)\n\t" \ - "pushq 88(%%rax)\n\t" \ - "pushq 80(%%rax)\n\t" \ - "pushq 72(%%rax)\n\t" \ - "pushq 64(%%rax)\n\t" \ - "pushq 56(%%rax)\n\t" \ - "movq 48(%%rax), %%r9\n\t" \ - "movq 40(%%rax), %%r8\n\t" \ - "movq 32(%%rax), %%rcx\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $48, %%rsp\n" \ - "addq $128,%%rsp\n\t" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#endif /* PLAT_amd64_linux || PLAT_amd64_darwin */ - -/* ------------------------ ppc32-linux ------------------------ */ - -#if defined(PLAT_ppc32_linux) - -/* This is useful for finding out about the on-stack stuff: - - extern int f9 ( int,int,int,int,int,int,int,int,int ); - extern int f10 ( int,int,int,int,int,int,int,int,int,int ); - extern int f11 ( int,int,int,int,int,int,int,int,int,int,int ); - extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int ); - - int g9 ( void ) { - return f9(11,22,33,44,55,66,77,88,99); - } - int g10 ( void ) { - return f10(11,22,33,44,55,66,77,88,99,110); - } - int g11 ( void ) { - return f11(11,22,33,44,55,66,77,88,99,110,121); - } - int g12 ( void ) { - return f12(11,22,33,44,55,66,77,88,99,110,121,132); - } -*/ - -/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ - -/* These regs are trashed by the hidden call. */ -#define __CALLER_SAVED_REGS \ - "lr", "ctr", "xer", \ - "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ - "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \ - "r11", "r12", "r13" - -/* These CALL_FN_ macros assume that on ppc32-linux, - sizeof(unsigned long) == 4. */ - -#define CALL_FN_W_v(lval, orig) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[1]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_W(lval, orig, arg1) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[2]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[4]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[5]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - _argvec[4] = (unsigned long)arg4; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 6,16(11)\n\t" /* arg4->r6 */ \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[6]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - _argvec[4] = (unsigned long)arg4; \ - _argvec[5] = (unsigned long)arg5; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 6,16(11)\n\t" /* arg4->r6 */ \ - "lwz 7,20(11)\n\t" \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[7]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - _argvec[4] = (unsigned long)arg4; \ - _argvec[5] = (unsigned long)arg5; \ - _argvec[6] = (unsigned long)arg6; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 6,16(11)\n\t" /* arg4->r6 */ \ - "lwz 7,20(11)\n\t" \ - "lwz 8,24(11)\n\t" \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[8]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - _argvec[4] = (unsigned long)arg4; \ - _argvec[5] = (unsigned long)arg5; \ - _argvec[6] = (unsigned long)arg6; \ - _argvec[7] = (unsigned long)arg7; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 6,16(11)\n\t" /* arg4->r6 */ \ - "lwz 7,20(11)\n\t" \ - "lwz 8,24(11)\n\t" \ - "lwz 9,28(11)\n\t" \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[9]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - _argvec[4] = (unsigned long)arg4; \ - _argvec[5] = (unsigned long)arg5; \ - _argvec[6] = (unsigned long)arg6; \ - _argvec[7] = (unsigned long)arg7; \ - _argvec[8] = (unsigned long)arg8; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 6,16(11)\n\t" /* arg4->r6 */ \ - "lwz 7,20(11)\n\t" \ - "lwz 8,24(11)\n\t" \ - "lwz 9,28(11)\n\t" \ - "lwz 10,32(11)\n\t" /* arg8->r10 */ \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[10]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - _argvec[4] = (unsigned long)arg4; \ - _argvec[5] = (unsigned long)arg5; \ - _argvec[6] = (unsigned long)arg6; \ - _argvec[7] = (unsigned long)arg7; \ - _argvec[8] = (unsigned long)arg8; \ - _argvec[9] = (unsigned long)arg9; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "addi 1,1,-16\n\t" \ - /* arg9 */ \ - "lwz 3,36(11)\n\t" \ - "stw 3,8(1)\n\t" \ - /* args1-8 */ \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 6,16(11)\n\t" /* arg4->r6 */ \ - "lwz 7,20(11)\n\t" \ - "lwz 8,24(11)\n\t" \ - "lwz 9,28(11)\n\t" \ - "lwz 10,32(11)\n\t" /* arg8->r10 */ \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "addi 1,1,16\n\t" \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[11]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - _argvec[4] = (unsigned long)arg4; \ - _argvec[5] = (unsigned long)arg5; \ - _argvec[6] = (unsigned long)arg6; \ - _argvec[7] = (unsigned long)arg7; \ - _argvec[8] = (unsigned long)arg8; \ - _argvec[9] = (unsigned long)arg9; \ - _argvec[10] = (unsigned long)arg10; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "addi 1,1,-16\n\t" \ - /* arg10 */ \ - "lwz 3,40(11)\n\t" \ - "stw 3,12(1)\n\t" \ - /* arg9 */ \ - "lwz 3,36(11)\n\t" \ - "stw 3,8(1)\n\t" \ - /* args1-8 */ \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 6,16(11)\n\t" /* arg4->r6 */ \ - "lwz 7,20(11)\n\t" \ - "lwz 8,24(11)\n\t" \ - "lwz 9,28(11)\n\t" \ - "lwz 10,32(11)\n\t" /* arg8->r10 */ \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "addi 1,1,16\n\t" \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10,arg11) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[12]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - _argvec[4] = (unsigned long)arg4; \ - _argvec[5] = (unsigned long)arg5; \ - _argvec[6] = (unsigned long)arg6; \ - _argvec[7] = (unsigned long)arg7; \ - _argvec[8] = (unsigned long)arg8; \ - _argvec[9] = (unsigned long)arg9; \ - _argvec[10] = (unsigned long)arg10; \ - _argvec[11] = (unsigned long)arg11; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "addi 1,1,-32\n\t" \ - /* arg11 */ \ - "lwz 3,44(11)\n\t" \ - "stw 3,16(1)\n\t" \ - /* arg10 */ \ - "lwz 3,40(11)\n\t" \ - "stw 3,12(1)\n\t" \ - /* arg9 */ \ - "lwz 3,36(11)\n\t" \ - "stw 3,8(1)\n\t" \ - /* args1-8 */ \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 6,16(11)\n\t" /* arg4->r6 */ \ - "lwz 7,20(11)\n\t" \ - "lwz 8,24(11)\n\t" \ - "lwz 9,28(11)\n\t" \ - "lwz 10,32(11)\n\t" /* arg8->r10 */ \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "addi 1,1,32\n\t" \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10,arg11,arg12) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[13]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - _argvec[4] = (unsigned long)arg4; \ - _argvec[5] = (unsigned long)arg5; \ - _argvec[6] = (unsigned long)arg6; \ - _argvec[7] = (unsigned long)arg7; \ - _argvec[8] = (unsigned long)arg8; \ - _argvec[9] = (unsigned long)arg9; \ - _argvec[10] = (unsigned long)arg10; \ - _argvec[11] = (unsigned long)arg11; \ - _argvec[12] = (unsigned long)arg12; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "addi 1,1,-32\n\t" \ - /* arg12 */ \ - "lwz 3,48(11)\n\t" \ - "stw 3,20(1)\n\t" \ - /* arg11 */ \ - "lwz 3,44(11)\n\t" \ - "stw 3,16(1)\n\t" \ - /* arg10 */ \ - "lwz 3,40(11)\n\t" \ - "stw 3,12(1)\n\t" \ - /* arg9 */ \ - "lwz 3,36(11)\n\t" \ - "stw 3,8(1)\n\t" \ - /* args1-8 */ \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 6,16(11)\n\t" /* arg4->r6 */ \ - "lwz 7,20(11)\n\t" \ - "lwz 8,24(11)\n\t" \ - "lwz 9,28(11)\n\t" \ - "lwz 10,32(11)\n\t" /* arg8->r10 */ \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "addi 1,1,32\n\t" \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#endif /* PLAT_ppc32_linux */ - -/* ------------------------ ppc64-linux ------------------------ */ - -#if defined(PLAT_ppc64_linux) - -/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ - -/* These regs are trashed by the hidden call. */ -#define __CALLER_SAVED_REGS \ - "lr", "ctr", "xer", \ - "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ - "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \ - "r11", "r12", "r13" - -/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned - long) == 8. */ - -#define CALL_FN_W_v(lval, orig) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+0]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)" /* restore tocptr */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_W(lval, orig, arg1) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+1]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)" /* restore tocptr */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+2]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)" /* restore tocptr */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+3]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)" /* restore tocptr */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+4]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)" /* restore tocptr */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+5]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)" /* restore tocptr */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+6]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)" /* restore tocptr */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+7]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)" /* restore tocptr */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+8]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)" /* restore tocptr */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+9]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "addi 1,1,-128\n\t" /* expand stack frame */ \ - /* arg9 */ \ - "ld 3,72(11)\n\t" \ - "std 3,112(1)\n\t" \ - /* args1-8 */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - "addi 1,1,128" /* restore frame */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+10]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - _argvec[2+10] = (unsigned long)arg10; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "addi 1,1,-128\n\t" /* expand stack frame */ \ - /* arg10 */ \ - "ld 3,80(11)\n\t" \ - "std 3,120(1)\n\t" \ - /* arg9 */ \ - "ld 3,72(11)\n\t" \ - "std 3,112(1)\n\t" \ - /* args1-8 */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - "addi 1,1,128" /* restore frame */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10,arg11) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+11]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - _argvec[2+10] = (unsigned long)arg10; \ - _argvec[2+11] = (unsigned long)arg11; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "addi 1,1,-144\n\t" /* expand stack frame */ \ - /* arg11 */ \ - "ld 3,88(11)\n\t" \ - "std 3,128(1)\n\t" \ - /* arg10 */ \ - "ld 3,80(11)\n\t" \ - "std 3,120(1)\n\t" \ - /* arg9 */ \ - "ld 3,72(11)\n\t" \ - "std 3,112(1)\n\t" \ - /* args1-8 */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - "addi 1,1,144" /* restore frame */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10,arg11,arg12) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+12]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - _argvec[2+10] = (unsigned long)arg10; \ - _argvec[2+11] = (unsigned long)arg11; \ - _argvec[2+12] = (unsigned long)arg12; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "addi 1,1,-144\n\t" /* expand stack frame */ \ - /* arg12 */ \ - "ld 3,96(11)\n\t" \ - "std 3,136(1)\n\t" \ - /* arg11 */ \ - "ld 3,88(11)\n\t" \ - "std 3,128(1)\n\t" \ - /* arg10 */ \ - "ld 3,80(11)\n\t" \ - "std 3,120(1)\n\t" \ - /* arg9 */ \ - "ld 3,72(11)\n\t" \ - "std 3,112(1)\n\t" \ - /* args1-8 */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - "addi 1,1,144" /* restore frame */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#endif /* PLAT_ppc64_linux */ - -/* ------------------------ ppc32-aix5 ------------------------- */ - -#if defined(PLAT_ppc32_aix5) - -/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ - -/* These regs are trashed by the hidden call. */ -#define __CALLER_SAVED_REGS \ - "lr", "ctr", "xer", \ - "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ - "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \ - "r11", "r12", "r13" - -/* Expand the stack frame, copying enough info that unwinding - still works. Trashes r3. */ - -#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \ - "addi 1,1,-" #_n_fr "\n\t" \ - "lwz 3," #_n_fr "(1)\n\t" \ - "stw 3,0(1)\n\t" - -#define VG_CONTRACT_FRAME_BY(_n_fr) \ - "addi 1,1," #_n_fr "\n\t" - -/* These CALL_FN_ macros assume that on ppc32-aix5, sizeof(unsigned - long) == 4. */ - -#define CALL_FN_W_v(lval, orig) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+0]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_W(lval, orig, arg1) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+1]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+2]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+3]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+4]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+5]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ - "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+6]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ - "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ - "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+7]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ - "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ - "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ - "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+8]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ - "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ - "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ - "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ - "lwz 10, 32(11)\n\t" /* arg8->r10 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+9]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - VG_EXPAND_FRAME_BY_trashes_r3(64) \ - /* arg9 */ \ - "lwz 3,36(11)\n\t" \ - "stw 3,56(1)\n\t" \ - /* args1-8 */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ - "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ - "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ - "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ - "lwz 10, 32(11)\n\t" /* arg8->r10 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(64) \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+10]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - _argvec[2+10] = (unsigned long)arg10; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - VG_EXPAND_FRAME_BY_trashes_r3(64) \ - /* arg10 */ \ - "lwz 3,40(11)\n\t" \ - "stw 3,60(1)\n\t" \ - /* arg9 */ \ - "lwz 3,36(11)\n\t" \ - "stw 3,56(1)\n\t" \ - /* args1-8 */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ - "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ - "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ - "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ - "lwz 10, 32(11)\n\t" /* arg8->r10 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(64) \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10,arg11) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+11]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - _argvec[2+10] = (unsigned long)arg10; \ - _argvec[2+11] = (unsigned long)arg11; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - VG_EXPAND_FRAME_BY_trashes_r3(72) \ - /* arg11 */ \ - "lwz 3,44(11)\n\t" \ - "stw 3,64(1)\n\t" \ - /* arg10 */ \ - "lwz 3,40(11)\n\t" \ - "stw 3,60(1)\n\t" \ - /* arg9 */ \ - "lwz 3,36(11)\n\t" \ - "stw 3,56(1)\n\t" \ - /* args1-8 */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ - "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ - "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ - "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ - "lwz 10, 32(11)\n\t" /* arg8->r10 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(72) \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10,arg11,arg12) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+12]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - _argvec[2+10] = (unsigned long)arg10; \ - _argvec[2+11] = (unsigned long)arg11; \ - _argvec[2+12] = (unsigned long)arg12; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - VG_EXPAND_FRAME_BY_trashes_r3(72) \ - /* arg12 */ \ - "lwz 3,48(11)\n\t" \ - "stw 3,68(1)\n\t" \ - /* arg11 */ \ - "lwz 3,44(11)\n\t" \ - "stw 3,64(1)\n\t" \ - /* arg10 */ \ - "lwz 3,40(11)\n\t" \ - "stw 3,60(1)\n\t" \ - /* arg9 */ \ - "lwz 3,36(11)\n\t" \ - "stw 3,56(1)\n\t" \ - /* args1-8 */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ - "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ - "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ - "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ - "lwz 10, 32(11)\n\t" /* arg8->r10 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(72) \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#endif /* PLAT_ppc32_aix5 */ - -/* ------------------------ ppc64-aix5 ------------------------- */ - -#if defined(PLAT_ppc64_aix5) - -/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ - -/* These regs are trashed by the hidden call. */ -#define __CALLER_SAVED_REGS \ - "lr", "ctr", "xer", \ - "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ - "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \ - "r11", "r12", "r13" - -/* Expand the stack frame, copying enough info that unwinding - still works. Trashes r3. */ - -#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \ - "addi 1,1,-" #_n_fr "\n\t" \ - "ld 3," #_n_fr "(1)\n\t" \ - "std 3,0(1)\n\t" - -#define VG_CONTRACT_FRAME_BY(_n_fr) \ - "addi 1,1," #_n_fr "\n\t" - -/* These CALL_FN_ macros assume that on ppc64-aix5, sizeof(unsigned - long) == 8. */ - -#define CALL_FN_W_v(lval, orig) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+0]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_W(lval, orig, arg1) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+1]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+2]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+3]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+4]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+5]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+6]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+7]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+8]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+9]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - VG_EXPAND_FRAME_BY_trashes_r3(128) \ - /* arg9 */ \ - "ld 3,72(11)\n\t" \ - "std 3,112(1)\n\t" \ - /* args1-8 */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(128) \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+10]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - _argvec[2+10] = (unsigned long)arg10; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - VG_EXPAND_FRAME_BY_trashes_r3(128) \ - /* arg10 */ \ - "ld 3,80(11)\n\t" \ - "std 3,120(1)\n\t" \ - /* arg9 */ \ - "ld 3,72(11)\n\t" \ - "std 3,112(1)\n\t" \ - /* args1-8 */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(128) \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10,arg11) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+11]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - _argvec[2+10] = (unsigned long)arg10; \ - _argvec[2+11] = (unsigned long)arg11; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - VG_EXPAND_FRAME_BY_trashes_r3(144) \ - /* arg11 */ \ - "ld 3,88(11)\n\t" \ - "std 3,128(1)\n\t" \ - /* arg10 */ \ - "ld 3,80(11)\n\t" \ - "std 3,120(1)\n\t" \ - /* arg9 */ \ - "ld 3,72(11)\n\t" \ - "std 3,112(1)\n\t" \ - /* args1-8 */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(144) \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10,arg11,arg12) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+12]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - _argvec[2+10] = (unsigned long)arg10; \ - _argvec[2+11] = (unsigned long)arg11; \ - _argvec[2+12] = (unsigned long)arg12; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - VG_EXPAND_FRAME_BY_trashes_r3(144) \ - /* arg12 */ \ - "ld 3,96(11)\n\t" \ - "std 3,136(1)\n\t" \ - /* arg11 */ \ - "ld 3,88(11)\n\t" \ - "std 3,128(1)\n\t" \ - /* arg10 */ \ - "ld 3,80(11)\n\t" \ - "std 3,120(1)\n\t" \ - /* arg9 */ \ - "ld 3,72(11)\n\t" \ - "std 3,112(1)\n\t" \ - /* args1-8 */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(144) \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#endif /* PLAT_ppc64_aix5 */ - - -/* ------------------------------------------------------------------ */ -/* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */ -/* */ -/* ------------------------------------------------------------------ */ - -/* Some request codes. There are many more of these, but most are not - exposed to end-user view. These are the public ones, all of the - form 0x1000 + small_number. - - Core ones are in the range 0x00000000--0x0000ffff. The non-public - ones start at 0x2000. -*/ - -/* These macros are used by tools -- they must be public, but don't - embed them into other programs. */ -#define VG_USERREQ_TOOL_BASE(a,b) \ - ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16)) -#define VG_IS_TOOL_USERREQ(a, b, v) \ - (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000)) - -/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !! - This enum comprises an ABI exported by Valgrind to programs - which use client requests. DO NOT CHANGE THE ORDER OF THESE - ENTRIES, NOR DELETE ANY -- add new ones at the end. */ -typedef enum -{ VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001, - VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002, - - /* These allow any function to be called from the simulated - CPU but run on the real CPU. Nb: the first arg passed to - the function is always the ThreadId of the running - thread! So CLIENT_CALL0 actually requires a 1 arg - function, etc. */ - VG_USERREQ__CLIENT_CALL0 = 0x1101, - VG_USERREQ__CLIENT_CALL1 = 0x1102, - VG_USERREQ__CLIENT_CALL2 = 0x1103, - VG_USERREQ__CLIENT_CALL3 = 0x1104, - - /* Can be useful in regression testing suites -- eg. can - send Valgrind's output to /dev/null and still count - errors. */ - VG_USERREQ__COUNT_ERRORS = 0x1201, - - /* These are useful and can be interpreted by any tool that - tracks malloc() et al, by using vg_replace_malloc.c. */ - VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301, - VG_USERREQ__FREELIKE_BLOCK = 0x1302, - /* Memory pool support. */ - VG_USERREQ__CREATE_MEMPOOL = 0x1303, - VG_USERREQ__DESTROY_MEMPOOL = 0x1304, - VG_USERREQ__MEMPOOL_ALLOC = 0x1305, - VG_USERREQ__MEMPOOL_FREE = 0x1306, - VG_USERREQ__MEMPOOL_TRIM = 0x1307, - VG_USERREQ__MOVE_MEMPOOL = 0x1308, - VG_USERREQ__MEMPOOL_CHANGE = 0x1309, - VG_USERREQ__MEMPOOL_EXISTS = 0x130a, - - /* Allow printfs to valgrind log. */ - VG_USERREQ__PRINTF = 0x1401, - VG_USERREQ__PRINTF_BACKTRACE = 0x1402, - - /* Stack support. */ - VG_USERREQ__STACK_REGISTER = 0x1501, - VG_USERREQ__STACK_DEREGISTER = 0x1502, - VG_USERREQ__STACK_CHANGE = 0x1503, - - /* Wine support */ - VG_USERREQ__LOAD_PDB_DEBUGINFO = 0x1601 -} Vg_ClientRequest; - -#if !defined(__GNUC__) -#define __extension__ /* */ -#endif - -/* Returns the number of Valgrinds this code is running under. That - is, 0 if running natively, 1 if running under Valgrind, 2 if - running under Valgrind which is running under another Valgrind, - etc. */ -#define RUNNING_ON_VALGRIND __extension__ \ - ({unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* if not */, \ - VG_USERREQ__RUNNING_ON_VALGRIND, \ - 0, 0, 0, 0, 0); \ - _qzz_res; \ - }) - - -/* Discard translation of code in the range [_qzz_addr .. _qzz_addr + - _qzz_len - 1]. Useful if you are debugging a JITter or some such, - since it provides a way to make sure valgrind will retranslate the - invalidated area. Returns no value. */ -#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__DISCARD_TRANSLATIONS, \ - _qzz_addr, _qzz_len, 0, 0, 0); \ - } - - -/* These requests are for getting Valgrind itself to print something. - Possibly with a backtrace. This is a really ugly hack. The return value - is the number of characters printed, excluding the "**<pid>** " part at the - start and the backtrace (if present). */ - -#if defined(NVALGRIND) - -#define VALGRIND_PRINTF(...) -#define VALGRIND_PRINTF_BACKTRACE(...) - -#else /* NVALGRIND */ - -/* Modern GCC will optimize the static routine out if unused, - and unused attribute will shut down warnings about it. */ -static int VALGRIND_PRINTF (const char *format, ...) - __attribute__ ((format (__printf__, 1, 2), __unused__)); -static int -VALGRIND_PRINTF (const char *format, ...) -{ - unsigned long _qzz_res; - va_list vargs; - va_start (vargs, format); - VALGRIND_DO_CLIENT_REQUEST (_qzz_res, 0, VG_USERREQ__PRINTF, - (unsigned long) format, (unsigned long) vargs, - 0, 0, 0); - va_end (vargs); - return (int) _qzz_res; -} - -static int VALGRIND_PRINTF_BACKTRACE (const char *format, ...) - __attribute__ ((format (__printf__, 1, 2), __unused__)); -static int -VALGRIND_PRINTF_BACKTRACE (const char *format, ...) -{ - unsigned long _qzz_res; - va_list vargs; - va_start (vargs, format); - VALGRIND_DO_CLIENT_REQUEST (_qzz_res, 0, VG_USERREQ__PRINTF_BACKTRACE, - (unsigned long) format, (unsigned long) vargs, - 0, 0, 0); - va_end (vargs); - return (int) _qzz_res; -} - -#endif /* NVALGRIND */ - - -/* These requests allow control to move from the simulated CPU to the - real CPU, calling an arbitary function. - - Note that the current ThreadId is inserted as the first argument. - So this call: - - VALGRIND_NON_SIMD_CALL2(f, arg1, arg2) - - requires f to have this signature: - - Word f(Word tid, Word arg1, Word arg2) - - where "Word" is a word-sized type. - - Note that these client requests are not entirely reliable. For example, - if you call a function with them that subsequently calls printf(), - there's a high chance Valgrind will crash. Generally, your prospects of - these working are made higher if the called function does not refer to - any global variables, and does not refer to any libc or other functions - (printf et al). Any kind of entanglement with libc or dynamic linking is - likely to have a bad outcome, for tricky reasons which we've grappled - with a lot in the past. -*/ -#define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \ - __extension__ \ - ({unsigned long _qyy_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \ - VG_USERREQ__CLIENT_CALL0, \ - _qyy_fn, \ - 0, 0, 0, 0); \ - _qyy_res; \ - }) - -#define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \ - __extension__ \ - ({unsigned long _qyy_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \ - VG_USERREQ__CLIENT_CALL1, \ - _qyy_fn, \ - _qyy_arg1, 0, 0, 0); \ - _qyy_res; \ - }) - -#define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \ - __extension__ \ - ({unsigned long _qyy_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \ - VG_USERREQ__CLIENT_CALL2, \ - _qyy_fn, \ - _qyy_arg1, _qyy_arg2, 0, 0); \ - _qyy_res; \ - }) - -#define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \ - __extension__ \ - ({unsigned long _qyy_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \ - VG_USERREQ__CLIENT_CALL3, \ - _qyy_fn, \ - _qyy_arg1, _qyy_arg2, \ - _qyy_arg3, 0); \ - _qyy_res; \ - }) - - -/* Counts the number of errors that have been recorded by a tool. Nb: - the tool must record the errors with VG_(maybe_record_error)() or - VG_(unique_error)() for them to be counted. */ -#define VALGRIND_COUNT_ERRORS \ - __extension__ \ - ({unsigned int _qyy_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \ - VG_USERREQ__COUNT_ERRORS, \ - 0, 0, 0, 0, 0); \ - _qyy_res; \ - }) - -/* Several Valgrind tools (Memcheck, Massif, Helgrind, DRD) rely on knowing - when heap blocks are allocated in order to give accurate results. This - happens automatically for the standard allocator functions such as - malloc(), calloc(), realloc(), memalign(), new, new[], free(), delete, - delete[], etc. - - But if your program uses a custom allocator, this doesn't automatically - happen, and Valgrind will not do as well. For example, if you allocate - superblocks with mmap() and then allocates chunks of the superblocks, all - Valgrind's observations will be at the mmap() level and it won't know that - the chunks should be considered separate entities. In Memcheck's case, - that means you probably won't get heap block overrun detection (because - there won't be redzones marked as unaddressable) and you definitely won't - get any leak detection. - - The following client requests allow a custom allocator to be annotated so - that it can be handled accurately by Valgrind. - - VALGRIND_MALLOCLIKE_BLOCK marks a region of memory as having been allocated - by a malloc()-like function. For Memcheck (an illustrative case), this - does two things: - - - It records that the block has been allocated. This means any addresses - within the block mentioned in error messages will be - identified as belonging to the block. It also means that if the block - isn't freed it will be detected by the leak checker. - - - It marks the block as being addressable and undefined (if 'is_zeroed' is - not set), or addressable and defined (if 'is_zeroed' is set). This - controls how accesses to the block by the program are handled. - - 'addr' is the start of the usable block (ie. after any - redzone), 'sizeB' is its size. 'rzB' is the redzone size if the allocator - can apply redzones -- these are blocks of padding at the start and end of - each block. Adding redzones is recommended as it makes it much more likely - Valgrind will spot block overruns. `is_zeroed' indicates if the memory is - zeroed (or filled with another predictable value), as is the case for - calloc(). - - VALGRIND_MALLOCLIKE_BLOCK should be put immediately after the point where a - heap block -- that will be used by the client program -- is allocated. - It's best to put it at the outermost level of the allocator if possible; - for example, if you have a function my_alloc() which calls - internal_alloc(), and the client request is put inside internal_alloc(), - stack traces relating to the heap block will contain entries for both - my_alloc() and internal_alloc(), which is probably not what you want. - - For Memcheck users: if you use VALGRIND_MALLOCLIKE_BLOCK to carve out - custom blocks from within a heap block, B, that has been allocated with - malloc/calloc/new/etc, then block B will be *ignored* during leak-checking - -- the custom blocks will take precedence. - - VALGRIND_FREELIKE_BLOCK is the partner to VALGRIND_MALLOCLIKE_BLOCK. For - Memcheck, it does two things: - - - It records that the block has been deallocated. This assumes that the - block was annotated as having been allocated via - VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued. - - - It marks the block as being unaddressable. - - VALGRIND_FREELIKE_BLOCK should be put immediately after the point where a - heap block is deallocated. - - In many cases, these two client requests will not be enough to get your - allocator working well with Memcheck. More specifically, if your allocator - writes to freed blocks in any way then a VALGRIND_MAKE_MEM_UNDEFINED call - will be necessary to mark the memory as addressable just before the zeroing - occurs, otherwise you'll get a lot of invalid write errors. For example, - you'll need to do this if your allocator recycles freed blocks, but it - zeroes them before handing them back out (via VALGRIND_MALLOCLIKE_BLOCK). - Alternatively, if your allocator reuses freed blocks for allocator-internal - data structures, VALGRIND_MAKE_MEM_UNDEFINED calls will also be necessary. - - Really, what's happening is a blurring of the lines between the client - program and the allocator... after VALGRIND_FREELIKE_BLOCK is called, the - memory should be considered unaddressable to the client program, but the - allocator knows more than the rest of the client program and so may be able - to safely access it. Extra client requests are necessary for Valgrind to - understand the distinction between the allocator and the rest of the - program. - - Note: there is currently no VALGRIND_REALLOCLIKE_BLOCK client request; it - has to be emulated with MALLOCLIKE/FREELIKE and memory copying. - - Ignored if addr == 0. -*/ -#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__MALLOCLIKE_BLOCK, \ - addr, sizeB, rzB, is_zeroed, 0); \ - (void) _qzz_res; /* compiler warning */ \ - } - -/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details. - Ignored if addr == 0. -*/ -#define VALGRIND_FREELIKE_BLOCK(addr, rzB) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__FREELIKE_BLOCK, \ - addr, rzB, 0, 0, 0); \ - (void) _qzz_res; /* compiler warning */ \ - } - -/* Create a memory pool. */ -#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__CREATE_MEMPOOL, \ - pool, rzB, is_zeroed, 0, 0); \ - } - -/* Destroy a memory pool. */ -#define VALGRIND_DESTROY_MEMPOOL(pool) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__DESTROY_MEMPOOL, \ - pool, 0, 0, 0, 0); \ - } - -/* Associate a piece of memory with a memory pool. */ -#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__MEMPOOL_ALLOC, \ - pool, addr, size, 0, 0); \ - } - -/* Disassociate a piece of memory from a memory pool. */ -#define VALGRIND_MEMPOOL_FREE(pool, addr) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__MEMPOOL_FREE, \ - pool, addr, 0, 0, 0); \ - } - -/* Disassociate any pieces outside a particular range. */ -#define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__MEMPOOL_TRIM, \ - pool, addr, size, 0, 0); \ - } - -/* Resize and/or move a piece associated with a memory pool. */ -#define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__MOVE_MEMPOOL, \ - poolA, poolB, 0, 0, 0); \ - } - -/* Resize and/or move a piece associated with a memory pool. */ -#define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__MEMPOOL_CHANGE, \ - pool, addrA, addrB, size, 0); \ - } - -/* Return 1 if a mempool exists, else 0. */ -#define VALGRIND_MEMPOOL_EXISTS(pool) \ - __extension__ \ - ({unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__MEMPOOL_EXISTS, \ - pool, 0, 0, 0, 0); \ - _qzz_res; \ - }) - -/* Mark a piece of memory as being a stack. Returns a stack id. */ -#define VALGRIND_STACK_REGISTER(start, end) \ - __extension__ \ - ({unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__STACK_REGISTER, \ - start, end, 0, 0, 0); \ - _qzz_res; \ - }) - -/* Unmark the piece of memory associated with a stack id as being a - stack. */ -#define VALGRIND_STACK_DEREGISTER(id) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__STACK_DEREGISTER, \ - id, 0, 0, 0, 0); \ - } - -/* Change the start and end address of the stack id. */ -#define VALGRIND_STACK_CHANGE(id, start, end) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__STACK_CHANGE, \ - id, start, end, 0, 0); \ - } - -/* Load PDB debug info for Wine PE image_map. */ -#define VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__LOAD_PDB_DEBUGINFO, \ - fd, ptr, total_size, delta, 0); \ - } - - -#undef PLAT_x86_linux -#undef PLAT_amd64_linux -#undef PLAT_ppc32_linux -#undef PLAT_ppc64_linux -#undef PLAT_ppc32_aix5 -#undef PLAT_ppc64_aix5 - -#endif /* __VALGRIND_H */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/vec.c b/vppinfra/vppinfra/vec.c deleted file mode 100644 index 2d7ae1d4dc6..00000000000 --- a/vppinfra/vppinfra/vec.c +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include <vppinfra/vec.h> -#include <vppinfra/mem.h> - -/* Vector resize operator. Called as needed by various macros such as - vec_add1() when we need to allocate memory. */ -void * -vec_resize_allocate_memory (void *v, - word length_increment, - uword data_bytes, - uword header_bytes, uword data_align) -{ - vec_header_t *vh = _vec_find (v); - uword old_alloc_bytes, new_alloc_bytes; - void *old, *new; - - header_bytes = vec_header_bytes (header_bytes); - - data_bytes += header_bytes; - - if (!v) - { - new = clib_mem_alloc_aligned_at_offset (data_bytes, data_align, header_bytes, 1 /* yes, call os_out_of_memory */ - ); - data_bytes = clib_mem_size (new); - memset (new, 0, data_bytes); - v = new + header_bytes; - _vec_len (v) = length_increment; - return v; - } - - vh->len += length_increment; - old = v - header_bytes; - - /* Vector header must start heap object. */ - ASSERT (clib_mem_is_heap_object (old)); - - old_alloc_bytes = clib_mem_size (old); - - /* Need to resize? */ - if (data_bytes <= old_alloc_bytes) - return v; - - new_alloc_bytes = (old_alloc_bytes * 3) / 2; - if (new_alloc_bytes < data_bytes) - new_alloc_bytes = data_bytes; - - new = - clib_mem_alloc_aligned_at_offset (new_alloc_bytes, data_align, - header_bytes, - 1 /* yes, call os_out_of_memory */ ); - - /* FIXME fail gracefully. */ - if (!new) - clib_panic - ("vec_resize fails, length increment %d, data bytes %d, alignment %d", - length_increment, data_bytes, data_align); - - clib_memcpy (new, old, old_alloc_bytes); - clib_mem_free (old); - v = new; - - /* Allocator may give a bit of extra room. */ - new_alloc_bytes = clib_mem_size (v); - - /* Zero new memory. */ - memset (v + old_alloc_bytes, 0, new_alloc_bytes - old_alloc_bytes); - - return v + header_bytes; -} - -uword -clib_mem_is_vec_h (void *v, uword header_bytes) -{ - return clib_mem_is_heap_object (vec_header (v, header_bytes)); -} - -/** \cond */ - -#ifdef TEST - -#include <stdio.h> - -void -main (int argc, char *argv[]) -{ - word n = atoi (argv[1]); - word i, *x = 0; - - typedef struct - { - word x, y, z; - } FOO; - - FOO *foos = vec_init (FOO, 10), *f; - - vec_validate (foos, 100); - foos[100].x = 99; - - _vec_len (foos) = 0; - for (i = 0; i < n; i++) - { - vec_add1 (x, i); - vec_add2 (foos, f, 1); - f->x = 2 * i; - f->y = 3 * i; - f->z = 4 * i; - } - - { - word n = 2; - word m = 42; - vec_delete (foos, n, m); - } - - { - word n = 2; - word m = 42; - vec_insert (foos, n, m); - } - - vec_free (x); - vec_free (foos); - exit (0); -} -#endif -/** \endcond */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/vec.h b/vppinfra/vppinfra/vec.h deleted file mode 100644 index eed96d6b9c2..00000000000 --- a/vppinfra/vppinfra/vec.h +++ /dev/null @@ -1,973 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_vec_h -#define included_vec_h - -#include <vppinfra/clib.h> /* word, etc */ -#include <vppinfra/mem.h> /* clib_mem_free */ -#include <vppinfra/string.h> /* memcpy, memmove */ -#include <vppinfra/vec_bootstrap.h> - -/** \file - - CLIB vectors are ubiquitous dynamically resized arrays with by user - defined "headers". Many CLIB data structures (e.g. hash, heap, - pool) are vectors with various different headers. - - The memory layout looks like this: - -~~~~~~~~ - user header (aligned to uword boundary) - vector length: number of elements - user's pointer-> vector element #0 - vector element #1 - ... -~~~~~~~~ - - The user pointer contains the address of vector element # 0. Null - pointer vectors are valid and mean a zero length vector. - - You can reset the length of an allocated vector to zero via the - vec_reset_length(v) macro, or by setting the vector length field to - zero (e.g. _vec_len (v) = 0). Vec_reset_length(v) preferred: it - understands Null pointers. - - Typically, the header is not present. Headers allow for other - data structures to be built atop CLIB vectors. - - Users may specify the alignment for data elements via the - vec_*_aligned macros. - - Vectors elements can be any C type e.g. (int, double, struct bar). - This is also true for data types built atop vectors (e.g. heap, - pool, etc.). - - Many macros have _a variants supporting alignment of vector data - and _h variants supporting non zero length vector headers. - The _ha variants support both. - - Standard programming error: memorize a pointer to the ith element - of a vector then expand it. Vectors expand by 3/2, so such code - may appear to work for a period of time. Memorize vector indices - which are invariant. - */ - -/** \brief Low-level resize allocation function, usually not called directly - - @param v pointer to a vector - @param length_increment length increment in elements - @param data_bytes requested size in bytes - @param header_bytes header size in bytes (may be zero) - @param data_align alignment (may be zero) - @return v_prime pointer to resized vector, may or may not equal v -*/ -void *vec_resize_allocate_memory (void *v, - word length_increment, - uword data_bytes, - uword header_bytes, uword data_align); - -/** \brief Low-level vector resize function, usually not called directly - - @param v pointer to a vector - @param length_increment length increment in elements - @param data_bytes requested size in bytes - @param header_bytes header size in bytes (may be zero) - @param data_align alignment (may be zero) - @return v_prime pointer to resized vector, may or may not equal v -*/ - -always_inline void * -_vec_resize (void *v, - word length_increment, - uword data_bytes, uword header_bytes, uword data_align) -{ - vec_header_t *vh = _vec_find (v); - uword new_data_bytes, aligned_header_bytes; - - aligned_header_bytes = vec_header_bytes (header_bytes); - - new_data_bytes = data_bytes + aligned_header_bytes; - - if (PREDICT_TRUE (v != 0)) - { - void *p = v - aligned_header_bytes; - - /* Vector header must start heap object. */ - ASSERT (clib_mem_is_heap_object (p)); - - /* Typically we'll not need to resize. */ - if (new_data_bytes <= clib_mem_size (p)) - { - vh->len += length_increment; - return v; - } - } - - /* Slow path: call helper function. */ - return vec_resize_allocate_memory (v, length_increment, data_bytes, - header_bytes, - clib_max (sizeof (vec_header_t), - data_align)); -} - -/** \brief Predicate function, says whether the supplied vector is a clib heap - object (general version). - - @param v pointer to a vector - @param header_bytes vector header size in bytes (may be zero) - @return 0 or 1 -*/ -uword clib_mem_is_vec_h (void *v, uword header_bytes); - - -/** \brief Predicate function, says whether the supplied vector is a clib heap - object - - @param v pointer to a vector - @return 0 or 1 -*/ -always_inline uword -clib_mem_is_vec (void *v) -{ - return clib_mem_is_vec_h (v, 0); -} - -/* Local variable naming macro (prevents collisions with other macro naming). */ -#define _v(var) _vec_##var - -/** \brief Resize a vector (general version). - Add N elements to end of given vector V, return pointer to start of vector. - Vector will have room for H header bytes and will have user's data aligned - at alignment A (rounded to next power of 2). - - @param V pointer to a vector - @param N number of elements to add - @param H header size in bytes (may be zero) - @param A alignment (may be zero) - @return V (value-result macro parameter) -*/ - -#define vec_resize_ha(V,N,H,A) \ -do { \ - word _v(n) = (N); \ - word _v(l) = vec_len (V); \ - V = _vec_resize ((V), _v(n), (_v(l) + _v(n)) * sizeof ((V)[0]), (H), (A)); \ -} while (0) - -/** \brief Resize a vector (no header, unspecified alignment) - Add N elements to end of given vector V, return pointer to start of vector. - Vector will have room for H header bytes and will have user's data aligned - at alignment A (rounded to next power of 2). - - @param V pointer to a vector - @param N number of elements to add - @return V (value-result macro parameter) -*/ -#define vec_resize(V,N) vec_resize_ha(V,N,0,0) - -/** \brief Resize a vector (no header, alignment specified). - Add N elements to end of given vector V, return pointer to start of vector. - Vector will have room for H header bytes and will have user's data aligned - at alignment A (rounded to next power of 2). - - @param V pointer to a vector - @param N number of elements to add - @param A alignment (may be zero) - @return V (value-result macro parameter) -*/ - -#define vec_resize_aligned(V,N,A) vec_resize_ha(V,N,0,A) - -/** \brief Allocate space for N more elements - - @param V pointer to a vector - @param N number of elements to add - @param H header size in bytes (may be zero) - @param A alignment (may be zero) - @return V (value-result macro parameter) -*/ - -#define vec_alloc_ha(V,N,H,A) \ -do { \ - uword _v(l) = vec_len (V); \ - vec_resize_ha (V, N, H, A); \ - _vec_len (V) = _v(l); \ -} while (0) - -/** \brief Allocate space for N more elements - (no header, unspecified alignment) - - @param V pointer to a vector - @param N number of elements to add - @return V (value-result macro parameter) -*/ -#define vec_alloc(V,N) vec_alloc_ha(V,N,0,0) - -/** \brief Allocate space for N more elements (no header, given alignment) - @param V pointer to a vector - @param N number of elements to add - @param A alignment (may be zero) - @return V (value-result macro parameter) -*/ - -#define vec_alloc_aligned(V,N,A) vec_alloc_ha(V,N,0,A) - -/** \brief Create new vector of given type and length (general version). - @param T type of elements in new vector - @param N number of elements to add - @param H header size in bytes (may be zero) - @param A alignment (may be zero) - @return V new vector -*/ -#define vec_new_ha(T,N,H,A) \ -({ \ - word _v(n) = (N); \ - _vec_resize ((T *) 0, _v(n), _v(n) * sizeof (T), (H), (A)); \ -}) - -/** \brief Create new vector of given type and length - (unspecified alignment, no header). - - @param T type of elements in new vector - @param N number of elements to add - @return V new vector -*/ -#define vec_new(T,N) vec_new_ha(T,N,0,0) -/** \brief Create new vector of given type and length - (alignment specified, no header). - - @param T type of elements in new vector - @param N number of elements to add - @param A alignment (may be zero) - @return V new vector -*/ -#define vec_new_aligned(T,N,A) vec_new_ha(T,N,0,A) - -/** \brief Free vector's memory (general version) - - @param V pointer to a vector - @param H size of header in bytes - @return V (value-result parameter, V=0) -*/ -#define vec_free_h(V,H) \ -do { \ - if (V) \ - { \ - clib_mem_free (vec_header ((V), (H))); \ - V = 0; \ - } \ -} while (0) - -/** \brief Free vector's memory (no header). - @param V pointer to a vector - @return V (value-result parameter, V=0) -*/ -#define vec_free(V) vec_free_h(V,0) - -/**\brief Free vector user header (syntactic sugar) - @param h vector header - @void -*/ -#define vec_free_header(h) clib_mem_free (h) - -/** \brief Return copy of vector (general version). - - @param V pointer to a vector - @param H size of header in bytes - @param A alignment (may be zero) - - @return Vdup copy of vector -*/ - -#define vec_dup_ha(V,H,A) \ -({ \ - __typeof__ ((V)[0]) * _v(v) = 0; \ - uword _v(l) = vec_len (V); \ - if (_v(l) > 0) \ - { \ - vec_resize_ha (_v(v), _v(l), (H), (A)); \ - clib_memcpy (_v(v), (V), _v(l) * sizeof ((V)[0]));\ - } \ - _v(v); \ -}) - -/** \brief Return copy of vector (no header, no alignment) - - @param V pointer to a vector - @return Vdup copy of vector -*/ -#define vec_dup(V) vec_dup_ha(V,0,0) - -/** \brief Return copy of vector (no header, alignment specified). - - @param V pointer to a vector - @param A alignment (may be zero) - - @return Vdup copy of vector -*/ -#define vec_dup_aligned(V,A) vec_dup_ha(V,0,A) - -/** \brief Copy a vector, memcpy wrapper. Assumes sizeof(SRC[0]) == - sizeof(DST[0]) - - @param DST destination - @param SRC source -*/ -#define vec_copy(DST,SRC) clib_memcpy (DST, SRC, vec_len (DST) * \ - sizeof ((DST)[0])) - -/** \brief Clone a vector. Make a new vector with the - same size as a given vector but possibly with a different type. - - @param NEW_V pointer to new vector - @param OLD_V pointer to old vector -*/ -#define vec_clone(NEW_V,OLD_V) \ -do { \ - (NEW_V) = 0; \ - (NEW_V) = _vec_resize ((NEW_V), vec_len (OLD_V), \ - vec_len (OLD_V) * sizeof ((NEW_V)[0]), (0), (0)); \ -} while (0) - -/** \brief Make sure vector is long enough for given index (general version). - - @param V (possibly NULL) pointer to a vector. - @param I vector index which will be valid upon return - @param H header size in bytes (may be zero) - @param A alignment (may be zero) - @return V (value-result macro parameter) -*/ - -#define vec_validate_ha(V,I,H,A) \ -do { \ - word _v(i) = (I); \ - word _v(l) = vec_len (V); \ - if (_v(i) >= _v(l)) \ - { \ - vec_resize_ha ((V), 1 + (_v(i) - _v(l)), (H), (A)); \ - /* Must zero new space since user may have previously \ - used e.g. _vec_len (v) -= 10 */ \ - memset ((V) + _v(l), 0, (1 + (_v(i) - _v(l))) * sizeof ((V)[0])); \ - } \ -} while (0) - -/** \brief Make sure vector is long enough for given index - (no header, unspecified alignment) - - @param V (possibly NULL) pointer to a vector. - @param I vector index which will be valid upon return - @return V (value-result macro parameter) -*/ -#define vec_validate(V,I) vec_validate_ha(V,I,0,0) - -/** \brief Make sure vector is long enough for given index - (no header, specified alignment) - - @param V (possibly NULL) pointer to a vector. - @param I vector index which will be valid upon return - @param A alignment (may be zero) - @return V (value-result macro parameter) -*/ - -#define vec_validate_aligned(V,I,A) vec_validate_ha(V,I,0,A) - -/** \brief Make sure vector is long enough for given index - and initialize empty space (general version) - - @param V (possibly NULL) pointer to a vector. - @param I vector index which will be valid upon return - @param INIT initial value (can be a complex expression!) - @param H header size in bytes (may be zero) - @param A alignment (may be zero) - @return V (value-result macro parameter) -*/ -#define vec_validate_init_empty_ha(V,I,INIT,H,A) \ -do { \ - word _v(i) = (I); \ - word _v(l) = vec_len (V); \ - if (_v(i) >= _v(l)) \ - { \ - vec_resize_ha ((V), 1 + (_v(i) - _v(l)), (H), (A)); \ - while (_v(l) <= _v(i)) \ - { \ - (V)[_v(l)] = (INIT); \ - _v(l)++; \ - } \ - } \ -} while (0) - -/** \brief Make sure vector is long enough for given index - and initialize empty space (no header, unspecified alignment) - - @param V (possibly NULL) pointer to a vector. - @param I vector index which will be valid upon return - @param INIT initial value (can be a complex expression!) - @param H header size in bytes (may be zero) - @param A alignment (may be zero) - @return V (value-result macro parameter) -*/ - -#define vec_validate_init_empty(V,I,INIT) \ - vec_validate_init_empty_ha(V,I,INIT,0,0) - -/** \brief Make sure vector is long enough for given index - and initialize empty space (no header, alignment alignment) - - @param V (possibly NULL) pointer to a vector. - @param I vector index which will be valid upon return - @param INIT initial value (can be a complex expression!) - @param H header size in bytes (may be zero) - @param A alignment (may be zero) - @return V (value-result macro parameter) -*/ -#define vec_validate_init_empty_aligned(V,I,A) \ - vec_validate_init_empty_ha(V,I,INIT,0,A) - -/** \brief Add 1 element to end of vector (general version). - - @param V pointer to a vector - @param E element to add - @param H header size in bytes (may be zero) - @param A alignment (may be zero) - @return V (value-result macro parameter) -*/ -#define vec_add1_ha(V,E,H,A) \ -do { \ - word _v(l) = vec_len (V); \ - V = _vec_resize ((V), 1, (_v(l) + 1) * sizeof ((V)[0]), (H), (A)); \ - (V)[_v(l)] = (E); \ -} while (0) - -/** \brief Add 1 element to end of vector (unspecified alignment). - - @param V pointer to a vector - @param E element to add - @return V (value-result macro parameter) -*/ -#define vec_add1(V,E) vec_add1_ha(V,E,0,0) - -/** \brief Add 1 element to end of vector (alignment specified). - - @param V pointer to a vector - @param E element to add - @param H header size in bytes (may be zero) - @param A alignment (may be zero) - @return V (value-result macro parameter) -*/ -#define vec_add1_aligned(V,E,A) vec_add1_ha(V,E,0,A) - -/** \brief Add N elements to end of vector V, - return pointer to new elements in P. (general version) - - @param V pointer to a vector - @param P pointer to new vector element(s) - @param N number of elements to add - @param H header size in bytes (may be zero) - @param A alignment (may be zero) - @return V and P (value-result macro parameters) -*/ -#define vec_add2_ha(V,P,N,H,A) \ -do { \ - word _v(n) = (N); \ - word _v(l) = vec_len (V); \ - V = _vec_resize ((V), _v(n), (_v(l) + _v(n)) * sizeof ((V)[0]), (H), (A)); \ - P = (V) + _v(l); \ -} while (0) - -/** \brief Add N elements to end of vector V, - return pointer to new elements in P. (no header, unspecified alignment) - - @param V pointer to a vector - @param P pointer to new vector element(s) - @param N number of elements to add - @return V and P (value-result macro parameters) -*/ - -#define vec_add2(V,P,N) vec_add2_ha(V,P,N,0,0) - -/** \brief Add N elements to end of vector V, - return pointer to new elements in P. (no header, alignment specified) - - @param V pointer to a vector - @param P pointer to new vector element(s) - @param N number of elements to add - @param A alignment (may be zero) - @return V and P (value-result macro parameters) -*/ - -#define vec_add2_aligned(V,P,N,A) vec_add2_ha(V,P,N,0,A) - -/** \brief Add N elements to end of vector V (general version) - - @param V pointer to a vector - @param E pointer to element(s) to add - @param N number of elements to add - @param H header size in bytes (may be zero) - @param A alignment (may be zero) - @return V (value-result macro parameter) -*/ -#define vec_add_ha(V,E,N,H,A) \ -do { \ - word _v(n) = (N); \ - word _v(l) = vec_len (V); \ - V = _vec_resize ((V), _v(n), (_v(l) + _v(n)) * sizeof ((V)[0]), (H), (A)); \ - clib_memcpy ((V) + _v(l), (E), _v(n) * sizeof ((V)[0])); \ -} while (0) - -/** \brief Add N elements to end of vector V (no header, unspecified alignment) - - @param V pointer to a vector - @param E pointer to element(s) to add - @param N number of elements to add - @return V (value-result macro parameter) -*/ -#define vec_add(V,E,N) vec_add_ha(V,E,N,0,0) - -/** \brief Add N elements to end of vector V (no header, specified alignment) - - @param V pointer to a vector - @param E pointer to element(s) to add - @param N number of elements to add - @param A alignment (may be zero) - @return V (value-result macro parameter) -*/ -#define vec_add_aligned(V,E,N,A) vec_add_ha(V,E,N,0,A) - -/** \brief Returns last element of a vector and decrements its length - - @param V pointer to a vector - @return E element removed from the end of the vector -*/ -#define vec_pop(V) \ -({ \ - uword _v(l) = vec_len (V); \ - ASSERT (_v(l) > 0); \ - _v(l) -= 1; \ - _vec_len (V) = _v (l); \ - (V)[_v(l)]; \ -}) - -/** \brief Set E to the last element of a vector, decrement vector length - @param V pointer to a vector - @param E pointer to the last vector element - @return E element removed from the end of the vector - (value-result macro parameter -*/ - -#define vec_pop2(V,E) \ -({ \ - uword _v(l) = vec_len (V); \ - if (_v(l) > 0) (E) = vec_pop (V); \ - _v(l) > 0; \ -}) - -/** \brief Insert N vector elements starting at element M, - initialize new elements (general version). - - @param V (possibly NULL) pointer to a vector. - @param N number of elements to insert - @param M insertion point - @param INIT initial value (can be a complex expression!) - @param H header size in bytes (may be zero) - @param A alignment (may be zero) - @return V (value-result macro parameter) -*/ -#define vec_insert_init_empty_ha(V,N,M,INIT,H,A) \ -do { \ - word _v(l) = vec_len (V); \ - word _v(n) = (N); \ - word _v(m) = (M); \ - V = _vec_resize ((V), \ - _v(n), \ - (_v(l) + _v(n))*sizeof((V)[0]), \ - (H), (A)); \ - ASSERT (_v(m) <= _v(l)); \ - memmove ((V) + _v(m) + _v(n), \ - (V) + _v(m), \ - (_v(l) - _v(m)) * sizeof ((V)[0])); \ - memset ((V) + _v(m), INIT, _v(n) * sizeof ((V)[0])); \ -} while (0) - -/** \brief Insert N vector elements starting at element M, - initialize new elements to zero (general version) - - @param V (possibly NULL) pointer to a vector. - @param N number of elements to insert - @param M insertion point - @param H header size in bytes (may be zero) - @param A alignment (may be zero) - @return V (value-result macro parameter) -*/ -#define vec_insert_ha(V,N,M,H,A) vec_insert_init_empty_ha(V,N,M,0,H,A) - -/** \brief Insert N vector elements starting at element M, - initialize new elements to zero (no header, unspecified alignment) - - @param V (possibly NULL) pointer to a vector. - @param N number of elements to insert - @param M insertion point - @return V (value-result macro parameter) -*/ -#define vec_insert(V,N,M) vec_insert_ha(V,N,M,0,0) - -/** \brief Insert N vector elements starting at element M, - initialize new elements to zero (no header, alignment specified) - - @param V (possibly NULL) pointer to a vector. - @param N number of elements to insert - @param M insertion point - @param A alignment (may be zero) - @return V (value-result macro parameter) -*/ -#define vec_insert_aligned(V,N,M,A) vec_insert_ha(V,N,M,0,A) - -/** \brief Insert N vector elements starting at element M, - initialize new elements (no header, unspecified alignment) - - @param V (possibly NULL) pointer to a vector. - @param N number of elements to insert - @param M insertion point - @param INIT initial value (can be a complex expression!) - @return V (value-result macro parameter) -*/ - -#define vec_insert_init_empty(V,N,M,INIT) \ - vec_insert_init_empty_ha(V,N,M,INIT,0,0) -/* Resize vector by N elements starting from element M, initialize new elements to INIT (alignment specified, no header). */ - -/** \brief Insert N vector elements starting at element M, - initialize new elements (no header, specified alignment) - - @param V (possibly NULL) pointer to a vector. - @param N number of elements to insert - @param M insertion point - @param INIT initial value (can be a complex expression!) - @param A alignment (may be zero) - @return V (value-result macro parameter) -*/ -#define vec_insert_init_empty_aligned(V,N,M,INIT,A) \ - vec_insert_init_empty_ha(V,N,M,INIT,0,A) - -/** \brief Insert N vector elements starting at element M, - insert given elements (general version) - - @param V (possibly NULL) pointer to a vector. - @param E element(s) to insert - @param N number of elements to insert - @param M insertion point - @param H header size in bytes (may be zero) - @param A alignment (may be zero) - @return V (value-result macro parameter) -*/ - -#define vec_insert_elts_ha(V,E,N,M,H,A) \ -do { \ - word _v(l) = vec_len (V); \ - word _v(n) = (N); \ - word _v(m) = (M); \ - V = _vec_resize ((V), \ - _v(n), \ - (_v(l) + _v(n))*sizeof((V)[0]), \ - (H), (A)); \ - ASSERT (_v(m) <= _v(l)); \ - memmove ((V) + _v(m) + _v(n), \ - (V) + _v(m), \ - (_v(l) - _v(m)) * sizeof ((V)[0])); \ - clib_memcpy ((V) + _v(m), (E), \ - _v(n) * sizeof ((V)[0])); \ -} while (0) - -/** \brief Insert N vector elements starting at element M, - insert given elements (no header, unspecified alignment) - - @param V (possibly NULL) pointer to a vector. - @param E element(s) to insert - @param N number of elements to insert - @param M insertion point - @return V (value-result macro parameter) -*/ -#define vec_insert_elts(V,E,N,M) vec_insert_elts_ha(V,E,N,M,0,0) - -/** \brief Insert N vector elements starting at element M, - insert given elements (no header, specified alignment) - - @param V (possibly NULL) pointer to a vector. - @param E element(s) to insert - @param N number of elements to insert - @param M insertion point - @param A alignment (may be zero) - @return V (value-result macro parameter) -*/ -#define vec_insert_elts_aligned(V,E,N,M,A) vec_insert_elts_ha(V,E,N,M,0,A) - -/** \brief Delete N elements starting at element M - - @param V pointer to a vector - @param N number of elements to delete - @param M first element to delete - @return V (value-result macro parameter) -*/ -#define vec_delete(V,N,M) \ -do { \ - word _v(l) = vec_len (V); \ - word _v(n) = (N); \ - word _v(m) = (M); \ - /* Copy over deleted elements. */ \ - if (_v(l) - _v(n) - _v(m) > 0) \ - memmove ((V) + _v(m), (V) + _v(m) + _v(n), \ - (_v(l) - _v(n) - _v(m)) * sizeof ((V)[0])); \ - /* Zero empty space at end (for future re-allocation). */ \ - if (_v(n) > 0) \ - memset ((V) + _v(l) - _v(n), 0, _v(n) * sizeof ((V)[0])); \ - _vec_len (V) -= _v(n); \ -} while (0) - -/** \brief Delete the element at index I - - @param V pointer to a vector - @param I index to delete -*/ -#define vec_del1(v,i) \ -do { \ - uword _vec_del_l = _vec_len (v) - 1; \ - uword _vec_del_i = (i); \ - if (_vec_del_i < _vec_del_l) \ - (v)[_vec_del_i] = (v)[_vec_del_l]; \ - _vec_len (v) = _vec_del_l; \ -} while (0) - -/** \brief Append v2 after v1. Result in v1. - @param V1 target vector - @param V2 vector to append -*/ - -#define vec_append(v1,v2) \ -do { \ - uword _v(l1) = vec_len (v1); \ - uword _v(l2) = vec_len (v2); \ - \ - v1 = _vec_resize ((v1), _v(l2), \ - (_v(l1) + _v(l2)) * sizeof ((v1)[0]), 0, 0); \ - clib_memcpy ((v1) + _v(l1), (v2), _v(l2) * sizeof ((v2)[0])); \ -} while (0) - -/** \brief Append v2 after v1. Result in v1. Specified alignment. - @param V1 target vector - @param V2 vector to append - @param align required alignment -*/ - -#define vec_append_aligned(v1,v2,align) \ -do { \ - uword _v(l1) = vec_len (v1); \ - uword _v(l2) = vec_len (v2); \ - \ - v1 = _vec_resize ((v1), _v(l2), \ - (_v(l1) + _v(l2)) * sizeof ((v1)[0]), 0, align); \ - clib_memcpy ((v1) + _v(l1), (v2), _v(l2) * sizeof ((v2)[0])); \ -} while (0) - -/** \brief Prepend v2 before v1. Result in v1. - @param V1 target vector - @param V2 vector to prepend -*/ - -#define vec_prepend(v1,v2) \ -do { \ - uword _v(l1) = vec_len (v1); \ - uword _v(l2) = vec_len (v2); \ - \ - v1 = _vec_resize ((v1), _v(l2), \ - (_v(l1) + _v(l2)) * sizeof ((v1)[0]), 0, 0); \ - memmove ((v1) + _v(l2), (v1), _v(l1) * sizeof ((v1)[0])); \ - clib_memcpy ((v1), (v2), _v(l2) * sizeof ((v2)[0])); \ -} while (0) - -/** \brief Prepend v2 before v1. Result in v1. Specified alignment - @param V1 target vector - @param V2 vector to prepend - @param align required alignment -*/ - -#define vec_prepend_aligned(v1,v2,align) \ -do { \ - uword _v(l1) = vec_len (v1); \ - uword _v(l2) = vec_len (v2); \ - \ - v1 = _vec_resize ((v1), _v(l2), \ - (_v(l1) + _v(l2)) * sizeof ((v1)[0]), 0, align); \ - memmove ((v1) + _v(l2), (v1), _v(l1) * sizeof ((v1)[0])); \ - clib_memcpy ((v1), (v2), _v(l2) * sizeof ((v2)[0])); \ -} while (0) - - -/** \brief Zero all vector elements. Null-pointer tolerant. - @param var Vector to zero -*/ -#define vec_zero(var) \ -do { \ - if (var) \ - memset ((var), 0, vec_len (var) * sizeof ((var)[0])); \ -} while (0) - -/** \brief Set all vector elements to given value. Null-pointer tolerant. - @param v vector to set - @param val value for each vector element -*/ -#define vec_set(v,val) \ -do { \ - word _v(i); \ - __typeof__ ((v)[0]) _val = (val); \ - for (_v(i) = 0; _v(i) < vec_len (v); _v(i)++) \ - (v)[_v(i)] = _val; \ -} while (0) - -#ifdef CLIB_UNIX -#include <stdlib.h> /* for qsort */ -#endif - -/** \brief Compare two vectors, not NULL-pointer tolerant - - @param v1 Pointer to a vector - @param v2 Pointer to a vector - @return 1 if equal, 0 if unequal -*/ -#define vec_is_equal(v1,v2) \ - (vec_len (v1) == vec_len (v2) && ! memcmp ((v1), (v2), vec_len (v1) * sizeof ((v1)[0]))) - -/** \brief Compare two vectors (only applicable to vectors of signed numbers). - Used in qsort compare functions. - - @param v1 Pointer to a vector - @param v2 Pointer to a vector - @return -1, 0, +1 -*/ -#define vec_cmp(v1,v2) \ -({ \ - word _v(i), _v(cmp), _v(l); \ - _v(l) = clib_min (vec_len (v1), vec_len (v2)); \ - _v(cmp) = 0; \ - for (_v(i) = 0; _v(i) < _v(l); _v(i)++) { \ - _v(cmp) = (v1)[_v(i)] - (v2)[_v(i)]; \ - if (_v(cmp)) \ - break; \ - } \ - if (_v(cmp) == 0 && _v(l) > 0) \ - _v(cmp) = vec_len(v1) - vec_len(v2); \ - (_v(cmp) < 0 ? -1 : (_v(cmp) > 0 ? +1 : 0)); \ -}) - -/** \brief Search a vector for the index of the entry that matches. - - @param v1 Pointer to a vector - @param v2 Entry to match - @return index of match or ~0 -*/ -#define vec_search(v,E) \ -({ \ - word _v(i) = 0; \ - while (_v(i) < vec_len(v)) \ - { \ - if (v[_v(i)] == E) \ - break; \ - _v(i)++; \ - } \ - if (_v(i) == vec_len(v)) \ - _v(i) = ~0; \ - _v(i); \ -}) - -/** \brief Sort a vector using the supplied element comparison function - - @param vec vector to sort - @param f comparison function -*/ -#define vec_sort_with_function(vec,f) \ -do { \ - qsort (vec, vec_len (vec), sizeof (vec[0]), (void *) (f)); \ -} while (0) - -/** \brief Make a vector containing a NULL terminated c-string. - - @param V (possibly NULL) pointer to a vector. - @param S pointer to string buffer. - @param L string length (NOT including the terminating NULL; a la strlen()) -*/ -#define vec_validate_init_c_string(V, S, L) \ - do { \ - vec_reset_length (V); \ - vec_validate ((V), (L)); \ - if ((S) && (L)) \ - clib_memcpy ((V), (S), (L)); \ - (V)[(L)] = 0; \ - } while (0) - - -/** \brief Test whether a vector is a NULL terminated c-string. - - @param V (possibly NULL) pointer to a vector. - @return BOOLEAN indicating if the vector c-string is null terminated. -*/ -#define vec_c_string_is_terminated(V) \ - (((V) != 0) && (vec_len (V) != 0) && ((V)[vec_len ((V)) - 1] == 0)) - -/** \brief (If necessary) NULL terminate a vector containing a c-string. - - @param V (possibly NULL) pointer to a vector. - @return V (value-result macro parameter) -*/ -#define vec_terminate_c_string(V) \ - do { \ - u32 vl = vec_len ((V)); \ - if (!vec_c_string_is_terminated(V)) \ - { \ - vec_validate ((V), vl); \ - (V)[vl] = 0; \ - } \ - } while (0) - -#endif /* included_vec_h */ - - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/vec_bootstrap.h b/vppinfra/vppinfra/vec_bootstrap.h deleted file mode 100644 index 3b8c770744c..00000000000 --- a/vppinfra/vppinfra/vec_bootstrap.h +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_clib_vec_bootstrap_h -#define included_clib_vec_bootstrap_h - -/** \file - Vector bootsrap header file -*/ - -/* Bootstrap include so that #include <vppinfra/mem.h> can include e.g. - <vppinfra/mheap.h> which depends on <vppinfra/vec.h>. */ - -/** \brief vector header structure - - Bookeeping header preceding vector elements in memory. - User header information may preceed standard vec header. - If you change u32 len -> u64 len, single vectors can - exceed 2**32 elements. Clib heaps are vectors. */ - -typedef struct -{ -#if CLIB_VEC64 > 0 - u64 len; -#else - u32 len; /**< Number of elements in vector (NOT its allocated length). */ -#endif - u8 vector_data[0]; /**< Vector data . */ -} vec_header_t; - -/** \brief Find the vector header - - Given the user's pointer to a vector, find the corresponding - vector header - - @param v pointer to a vector - @return pointer to the vector's vector_header_t -*/ -#define _vec_find(v) ((vec_header_t *) (v) - 1) - -#define _vec_round_size(s) \ - (((s) + sizeof (uword) - 1) &~ (sizeof (uword) - 1)) - -always_inline uword -vec_header_bytes (uword header_bytes) -{ - return round_pow2 (header_bytes + sizeof (vec_header_t), - sizeof (vec_header_t)); -} - -/** \brief Find a user vector header - - Finds the user header of a vector with unspecified alignment given - the user pointer to the vector. -*/ - -always_inline void * -vec_header (void *v, uword header_bytes) -{ - return v - vec_header_bytes (header_bytes); -} - -/** \brief Find the end of user vector header - - Finds the end of the user header of a vector with unspecified - alignment given the user pointer to the vector. -*/ - -always_inline void * -vec_header_end (void *v, uword header_bytes) -{ - return v + vec_header_bytes (header_bytes); -} - -always_inline uword -vec_aligned_header_bytes (uword header_bytes, uword align) -{ - return round_pow2 (header_bytes + sizeof (vec_header_t), align); -} - -always_inline void * -vec_aligned_header (void *v, uword header_bytes, uword align) -{ - return v - vec_aligned_header_bytes (header_bytes, align); -} - -always_inline void * -vec_aligned_header_end (void *v, uword header_bytes, uword align) -{ - return v + vec_aligned_header_bytes (header_bytes, align); -} - - -/** \brief Number of elements in vector (lvalue-capable) - - _vec_len (v) does not check for null, but can be used as a lvalue - (e.g. _vec_len (v) = 99). -*/ - -#define _vec_len(v) (_vec_find(v)->len) - -/** \brief Number of elements in vector (rvalue-only, NULL tolerant) - - vec_len (v) checks for NULL, but cannot be used as an lvalue. - If in doubt, use vec_len... -*/ - -#define vec_len(v) ((v) ? _vec_len(v) : 0) - -/** \brief Reset vector length to zero - NULL-pointer tolerant -*/ - -#define vec_reset_length(v) do { if (v) _vec_len (v) = 0; } while (0) - -/** \brief Number of data bytes in vector. */ - -#define vec_bytes(v) (vec_len (v) * sizeof (v[0])) - -/** \brief Total number of bytes that can fit in vector with current allocation. */ - -#define vec_capacity(v,b) \ -({ \ - void * _vec_capacity_v = (void *) (v); \ - uword _vec_capacity_b = (b); \ - _vec_capacity_b = sizeof (vec_header_t) + _vec_round_size (_vec_capacity_b); \ - _vec_capacity_v ? clib_mem_size (_vec_capacity_v - _vec_capacity_b) : 0; \ -}) - -/** \brief Total number of elements that can fit into vector. */ -#define vec_max_len(v) (vec_capacity(v,0) / sizeof (v[0])) - -/** \brief End (last data address) of vector. */ -#define vec_end(v) ((v) + vec_len (v)) - -/** \brief True if given pointer is within given vector. */ -#define vec_is_member(v,e) ((e) >= (v) && (e) < vec_end (v)) - -/** \brief Get vector value at index i checking that i is in bounds. */ -#define vec_elt_at_index(v,i) \ -({ \ - ASSERT ((i) < vec_len (v)); \ - (v) + (i); \ -}) - -/** \brief Get vector value at index i */ -#define vec_elt(v,i) (vec_elt_at_index(v,i))[0] - -/** \brief Vector iterator */ -#define vec_foreach(var,vec) for (var = (vec); var < vec_end (vec); var++) - -/** \brief Vector iterator (reverse) */ -#define vec_foreach_backwards(var,vec) \ -for (var = vec_end (vec) - 1; var >= (vec); var--) - -/** \brief Iterate over vector indices. */ -#define vec_foreach_index(var,v) for ((var) = 0; (var) < vec_len (v); (var)++) - -#endif /* included_clib_vec_bootstrap_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/vector.c b/vppinfra/vppinfra/vector.c deleted file mode 100644 index 68b4fdc2088..00000000000 --- a/vppinfra/vppinfra/vector.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2005 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include <vppinfra/types.h> - -#if defined (__SSE2__) -u8 u32x4_compare_word_mask_table[256] = { - [0xf0] = (1 << 1), - [0x0f] = (1 << 0), - [0xff] = (1 << 0) | (1 << 1), -}; -#endif - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/vector.h b/vppinfra/vppinfra/vector.h deleted file mode 100644 index 491e7cfe547..00000000000 --- a/vppinfra/vppinfra/vector.h +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2005 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_clib_vector_h -#define included_clib_vector_h - -#include <vppinfra/clib.h> - -/* Vector types. */ - -#if defined (__MMX__) || defined (__IWMMXT__) || defined (__aarch64__) -#define CLIB_HAVE_VEC64 -#endif - -#if defined (__SSE2__) && __GNUC__ >= 4 -#define CLIB_HAVE_VEC128 -#endif - -#if defined (__ALTIVEC__) -#define CLIB_HAVE_VEC128 -#endif - -/* 128 implies 64 */ -#ifdef CLIB_HAVE_VEC128 -#define CLIB_HAVE_VEC64 -#endif - -#define _vector_size(n) __attribute__ ((vector_size (n))) - -#if defined (__aarch64__) || defined (__arm__) -typedef unsigned int u32x4 _vector_size (16); -typedef u8 u8x16 _vector_size (16); -typedef u16 u16x8 _vector_size (16); -typedef u32 u32x4 _vector_size (16); -typedef u64 u64x2 _vector_size (16); -#endif - -#ifdef CLIB_HAVE_VEC64 -/* Signed 64 bit. */ -typedef char i8x8 _vector_size (8); -typedef short i16x4 _vector_size (8); -typedef int i32x2 _vector_size (8); - -/* Unsigned 64 bit. */ -typedef unsigned char u8x8 _vector_size (8); -typedef unsigned short u16x4 _vector_size (8); -typedef unsigned int u32x2 _vector_size (8); - -/* Floating point 64 bit. */ -typedef float f32x2 _vector_size (8); -#endif /* CLIB_HAVE_VEC64 */ - -#ifdef CLIB_HAVE_VEC128 -/* Signed 128 bit. */ -typedef i8 i8x16 _vector_size (16); -typedef i16 i16x8 _vector_size (16); -typedef i32 i32x4 _vector_size (16); -typedef long long i64x2 _vector_size (16); - -/* Unsigned 128 bit. */ -typedef u8 u8x16 _vector_size (16); -typedef u16 u16x8 _vector_size (16); -typedef u32 u32x4 _vector_size (16); -typedef u64 u64x2 _vector_size (16); - -typedef f32 f32x4 _vector_size (16); -typedef f64 f64x2 _vector_size (16); - -/* Signed 256 bit. */ -typedef i8 i8x32 _vector_size (32); -typedef i16 i16x16 _vector_size (32); -typedef i32 i32x8 _vector_size (32); -typedef long long i64x4 _vector_size (32); - -/* Unsigned 256 bit. */ -typedef u8 u8x32 _vector_size (32); -typedef u16 u16x16 _vector_size (32); -typedef u32 u32x8 _vector_size (32); -typedef u64 u64x4 _vector_size (32); - -typedef f32 f32x8 _vector_size (32); -typedef f64 f64x4 _vector_size (32); -#endif /* CLIB_HAVE_VEC128 */ - -/* Vector word sized types. */ -#ifndef CLIB_VECTOR_WORD_BITS -#ifdef CLIB_HAVE_VEC128 -#define CLIB_VECTOR_WORD_BITS 128 -#else -#define CLIB_VECTOR_WORD_BITS 64 -#endif -#endif /* CLIB_VECTOR_WORD_BITS */ - -/* Vector word sized types. */ -#if CLIB_VECTOR_WORD_BITS == 128 -typedef i8 i8x _vector_size (16); -typedef i16 i16x _vector_size (16); -typedef i32 i32x _vector_size (16); -typedef i64 i64x _vector_size (16); -typedef u8 u8x _vector_size (16); -typedef u16 u16x _vector_size (16); -typedef u32 u32x _vector_size (16); -typedef u64 u64x _vector_size (16); -#endif -#if CLIB_VECTOR_WORD_BITS == 64 -typedef i8 i8x _vector_size (8); -typedef i16 i16x _vector_size (8); -typedef i32 i32x _vector_size (8); -typedef i64 i64x _vector_size (8); -typedef u8 u8x _vector_size (8); -typedef u16 u16x _vector_size (8); -typedef u32 u32x _vector_size (8); -typedef u64 u64x _vector_size (8); -#endif - -#undef _vector_size - -#define VECTOR_WORD_TYPE(t) t##x -#define VECTOR_WORD_TYPE_LEN(t) (sizeof (VECTOR_WORD_TYPE(t)) / sizeof (t)) - -/* Union types. */ -#if (defined(CLIB_HAVE_VEC128) || defined(CLIB_HAVE_VEC64)) - -#define _(t) \ - typedef union { \ - t##x as_##t##x; \ - t as_##t[VECTOR_WORD_TYPE_LEN (t)]; \ - } t##x##_union_t; - -_(u8); -_(u16); -_(u32); -_(u64); -_(i8); -_(i16); -_(i32); -_(i64); - -#undef _ - -#endif - -#ifdef CLIB_HAVE_VEC64 - -#define _(t,n) \ - typedef union { \ - t##x##n as_##t##x##n; \ - t as_##t[n]; \ - } t##x##n##_union_t; \ - -_(u8, 8); -_(u16, 4); -_(u32, 2); -_(i8, 8); -_(i16, 4); -_(i32, 2); - -#undef _ - -#endif - -#ifdef CLIB_HAVE_VEC128 - -#define _(t,n) \ - typedef union { \ - t##x##n as_##t##x##n; \ - t as_##t[n]; \ - } t##x##n##_union_t; \ - -_(u8, 16); -_(u16, 8); -_(u32, 4); -_(u64, 2); -_(i8, 16); -_(i16, 8); -_(i32, 4); -_(i64, 2); -_(f32, 4); -_(f64, 2); - -#undef _ - -#endif - -/* When we don't have vector types, still define e.g. u32x4_union_t but as an array. */ -#if !defined(CLIB_HAVE_VEC128) && !defined(CLIB_HAVE_VEC64) - -#define _(t,n) \ - typedef union { \ - t as_##t[n]; \ - } t##x##n##_union_t; \ - -_(u8, 16); -_(u16, 8); -_(u32, 4); -_(u64, 2); -_(i8, 16); -_(i16, 8); -_(i32, 4); -_(i64, 2); - -#undef _ - -#endif - -#if defined (__SSE2__) && __GNUC__ >= 4 -#include <vppinfra/vector_sse2.h> -#endif - -#if defined (__ALTIVEC__) -#include <vppinfra/vector_altivec.h> -#endif - -#if defined (__IWMMXT__) -#include <vppinfra/vector_iwmmxt.h> -#endif - -#if defined (__aarch64__) -#include <vppinfra/vector_neon.h> -#endif - -#if (defined(CLIB_HAVE_VEC128) || defined(CLIB_HAVE_VEC64)) -#include <vppinfra/vector_funcs.h> -#endif - -#endif /* included_clib_vector_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/vector_altivec.h b/vppinfra/vppinfra/vector_altivec.h deleted file mode 100644 index 0e9de820ed8..00000000000 --- a/vppinfra/vppinfra/vector_altivec.h +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2009 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_vector_altivec_h -#define included_vector_altivec_h - -/* Splats. */ -#define _(t,n,ti,fi,tr,fr) \ - always_inline t##x##n t##x##n##_splat (t v) \ - { return (t##x##n) __builtin_altivec_##fi ((ti) v); } \ - \ - always_inline t##x##n t##x##n##_splat_word (t##x##n x, int word_index) \ - { return (t##x##n) __builtin_altivec_##fr ((tr) x, word_index); } - -#define u16x8_splat(i) ((u16x8) __builtin_altivec_vspltish (i)) -#define i16x8_splat(i) ((i16x8) __builtin_altivec_vspltish (i)) -#define u32x4_splat(i) ((u32x4) __builtin_altivec_vspltisw (i)) -#define i32x4_splat(i) ((i32x4) __builtin_altivec_vspltisw (i)) - -#define u16x8_splat_word(x,i) ((u16x8) __builtin_altivec_vsplth ((i16x8) (x), (i))) -#define i16x8_splat_word(x,i) ((i16x8) __builtin_altivec_vsplth ((i16x8) (x), (i))) -#define u32x4_splat_word(x,i) ((u32x4) __builtin_altivec_vspltw ((i32x4) (x), (i))) -#define i32x4_splat_word(x,i) ((i32x4) __builtin_altivec_vspltw ((i32x4) (x), (i))) - -#undef _ - -/* 128 bit shifts. */ -#define _(t,ti,lr,f) \ - always_inline t t##_##lr (t x, t y) \ - { return (t) __builtin_altivec_##f ((ti) x, (ti) y); } \ - \ - always_inline t t##_i##lr (t x, int i) \ - { \ - t j = {i,i,i,i}; \ - return t##_##lr (x, j); \ - } - -_(u16x8, i16x8, shift_left, vslh); -_(u32x4, i32x4, shift_left, vslw); -_(u16x8, i16x8, shift_right, vsrh); -_(u32x4, i32x4, shift_right, vsrw); -_(i16x8, i16x8, shift_right, vsrah); -_(i32x4, i32x4, shift_right, vsraw); -_(u16x8, i16x8, rotate_left, vrlh); -_(i16x8, i16x8, rotate_left, vrlh); -_(u32x4, i32x4, rotate_left, vrlw); -_(i32x4, i32x4, rotate_left, vrlw); - -#undef _ - -#define _(t,it,lr,f) \ - always_inline t t##_word_shift_##lr (t x, int n_words) \ - { \ - i32x4 n_bits = {0,0,0,n_words * BITS (it)}; \ - return (t) __builtin_altivec_##f ((i32x4) x, n_bits); \ - } - -_(u32x4, u32, left, vslo) -_(i32x4, i32, left, vslo) -_(u32x4, u32, right, vsro) -_(i32x4, i32, right, vsro) -_(u16x8, u16, left, vslo) -_(i16x8, i16, left, vslo) -_(u16x8, u16, right, vsro) _(i16x8, i16, right, vsro) -#undef _ - always_inline - u32 - u32x4_get0 (u32x4 x) -{ - u32x4_union_t y; - y.as_u32x4 = x; - return y.as_u32[3]; -} - -/* Interleave. */ -#define _(t,it,lh,f) \ - always_inline t t##_interleave_##lh (t x, t y) \ - { return (t) __builtin_altivec_##f ((it) x, (it) y); } - -_(u32x4, i32x4, lo, vmrglw) -_(i32x4, i32x4, lo, vmrglw) -_(u16x8, i16x8, lo, vmrglh) -_(i16x8, i16x8, lo, vmrglh) -_(u32x4, i32x4, hi, vmrghw) -_(i32x4, i32x4, hi, vmrghw) -_(u16x8, i16x8, hi, vmrghh) _(i16x8, i16x8, hi, vmrghh) -#undef _ -/* Unaligned loads/stores. */ -#ifndef __cplusplus -#define _(t) \ - always_inline void t##_store_unaligned (t x, t * a) \ - { clib_mem_unaligned (a, t) = x; } \ - always_inline t t##_load_unaligned (t * a) \ - { return clib_mem_unaligned (a, t); } - _(u8x16) _(u16x8) _(u32x4) _(u64x2) _(i8x16) _(i16x8) _(i32x4) _(i64x2) -#undef _ -#endif -#define _signed_binop(n,m,f,g) \ - /* Unsigned */ \ - always_inline u##n##x##m \ - u##n##x##m##_##f (u##n##x##m x, u##n##x##m y) \ - { return (u##n##x##m) __builtin_altivec_##g ((i##n##x##m) x, (i##n##x##m) y); } \ - \ - /* Signed */ \ - always_inline i##n##x##m \ - i##n##x##m##_##f (i##n##x##m x, i##n##x##m y) \ - { return (i##n##x##m) __builtin_altivec_##g ((i##n##x##m) x, (i##n##x##m) y); } -/* Compare operations. */ - _signed_binop (16, 8, is_equal, vcmpequh) -_signed_binop (32, 4, is_equal, vcmpequw) -#undef _signed_binop - always_inline u16x8 u16x8_is_zero (u16x8 x) -{ - u16x8 zero = { 0 }; - return u16x8_is_equal (x, zero); -} - -always_inline u32x4 -u32x4_is_zero (u32x4 x) -{ - u32x4 zero = { 0 }; - return u32x4_is_equal (x, zero); -} - -always_inline u32 -u32x4_zero_byte_mask (u32x4 x) -{ - u32x4 cmp = u32x4_is_zero (x); - u32x4 tmp = { 0x000f, 0x00f0, 0x0f00, 0xf000, }; - cmp &= tmp; - cmp |= u32x4_word_shift_right (cmp, 2); - cmp |= u32x4_word_shift_right (cmp, 1); - return u32x4_get0 (cmp); -} - -#endif /* included_vector_altivec_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/vector_funcs.h b/vppinfra/vppinfra/vector_funcs.h deleted file mode 100644 index db09de0f04c..00000000000 --- a/vppinfra/vppinfra/vector_funcs.h +++ /dev/null @@ -1,334 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2008 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_vector_funcs_h -#define included_vector_funcs_h - -#include <vppinfra/byte_order.h> - -/* Addition/subtraction. */ -#if CLIB_VECTOR_WORD_BITS == 128 -#define u8x_add u8x16_add -#define u16x_add u16x8_add -#define u32x_add u32x4_add -#define u64x_add u64x2_add -#define i8x_add i8x16_add -#define i16x_add i16x8_add -#define i32x_add i32x4_add -#define i64x_add i64x2_add -#define u8x_sub u8x16_sub -#define u16x_sub u16x8_sub -#define u32x_sub u32x4_sub -#define u64x_sub u64x2_sub -#define i8x_sub i8x16_sub -#define i16x_sub i16x8_sub -#define i32x_sub i32x4_sub -#define i64x_sub i64x2_sub -#endif - -#if CLIB_VECTOR_WORD_BITS == 64 -#define u8x_add u8x8_add -#define u16x_add u16x4_add -#define u32x_add u32x2_add -#define i8x_add i8x8_add -#define i16x_add i16x4_add -#define i32x_add i32x2_add -#define u8x_sub u8x8_sub -#define u16x_sub u16x4_sub -#define u32x_sub u32x2_sub -#define i8x_sub i8x8_sub -#define i16x_sub i16x4_sub -#define i32x_sub i32x2_sub -#endif - -/* Saturating addition/subtraction. */ -#if CLIB_VECTOR_WORD_BITS == 128 -#define u8x_add_saturate u8x16_add_saturate -#define u16x_add_saturate u16x8_add_saturate -#define i8x_add_saturate i8x16_add_saturate -#define i16x_add_saturate i16x8_add_saturate -#define u8x_sub_saturate u8x16_sub_saturate -#define u16x_sub_saturate u16x8_sub_saturate -#define i8x_sub_saturate i8x16_sub_saturate -#define i16x_sub_saturate i16x8_sub_saturate -#endif - -#if CLIB_VECTOR_WORD_BITS == 64 -#define u8x_add_saturate u8x8_add_saturate -#define u16x_add_saturate u16x4_add_saturate -#define i8x_add_saturate i8x8_add_saturate -#define i16x_add_saturate i16x4_add_saturate -#define u8x_sub_saturate u8x8_sub_saturate -#define u16x_sub_saturate u16x4_sub_saturate -#define i8x_sub_saturate i8x8_sub_saturate -#define i16x_sub_saturate i16x4_sub_saturate -#endif - -#define _vector_interleave(a,b,t) \ -do { \ - t _tmp_lo = t##_interleave_lo (a, b); \ - t _tmp_hi = t##_interleave_hi (a, b); \ - if (CLIB_ARCH_IS_LITTLE_ENDIAN) \ - (a) = _tmp_lo, (b) = _tmp_hi; \ - else \ - (a) = _tmp_hi, (b) = _tmp_lo; \ -} while (0) - -/* 128 bit interleaves. */ -#define u8x16_interleave(a,b) _vector_interleave(a,b,u8x16) -#define i8x16_interleave(a,b) _vector_interleave(a,b,i8x16) -#define u16x8_interleave(a,b) _vector_interleave(a,b,u16x8) -#define i16x8_interleave(a,b) _vector_interleave(a,b,i16x8) -#define u32x4_interleave(a,b) _vector_interleave(a,b,u32x4) -#define i32x4_interleave(a,b) _vector_interleave(a,b,i32x4) -#define u64x2_interleave(a,b) _vector_interleave(a,b,u64x2) -#define i64x2_interleave(a,b) _vector_interleave(a,b,i64x2) - -/* 64 bit interleaves. */ -#define u8x8_interleave(a,b) _vector_interleave(a,b,u8x8) -#define i8x8_interleave(a,b) _vector_interleave(a,b,i8x8) -#define u16x4_interleave(a,b) _vector_interleave(a,b,u16x4) -#define i16x4_interleave(a,b) _vector_interleave(a,b,i16x4) -#define u32x2_interleave(a,b) _vector_interleave(a,b,u32x2) -#define i32x2_interleave(a,b) _vector_interleave(a,b,i32x2) - -/* Word sized interleaves. */ -#if CLIB_VECTOR_WORD_BITS == 128 -#define u8x_interleave u8x16_interleave -#define u16x_interleave u16x8_interleave -#define u32x_interleave u32x4_interleave -#define u64x_interleave u64x2_interleave -#endif - -#if CLIB_VECTOR_WORD_BITS == 64 -#define u8x_interleave u8x8_interleave -#define u16x_interleave u16x4_interleave -#define u32x_interleave u32x2_interleave -#define u64x_interleave(a,b) /* do nothing */ -#endif - -/* Vector word sized shifts. */ -#if CLIB_VECTOR_WORD_BITS == 128 -#define u8x_shift_left u8x16_shift_left -#define i8x_shift_left i8x16_shift_left -#define u16x_shift_left u16x8_shift_left -#define i16x_shift_left i16x8_shift_left -#define u32x_shift_left u32x4_shift_left -#define i32x_shift_left i32x4_shift_left -#define u64x_shift_left u64x2_shift_left -#define i64x_shift_left i64x2_shift_left -#define u8x_shift_right u8x16_shift_right -#define i8x_shift_right i8x16_shift_right -#define u16x_shift_right u16x8_shift_right -#define i16x_shift_right i16x8_shift_right -#define u32x_shift_right u32x4_shift_right -#define i32x_shift_right i32x4_shift_right -#define u64x_shift_right u64x2_shift_right -#define i64x_shift_right i64x2_shift_right -#define u8x_rotate_left u8x16_rotate_left -#define i8x_rotate_left i8x16_rotate_left -#define u16x_rotate_left u16x8_rotate_left -#define i16x_rotate_left i16x8_rotate_left -#define u32x_rotate_left u32x4_rotate_left -#define i32x_rotate_left i32x4_rotate_left -#define u64x_rotate_left u64x2_rotate_left -#define i64x_rotate_left i64x2_rotate_left -#define u8x_rotate_right u8x16_rotate_right -#define i8x_rotate_right i8x16_rotate_right -#define u16x_rotate_right u16x8_rotate_right -#define i16x_rotate_right i16x8_rotate_right -#define u32x_rotate_right u32x4_rotate_right -#define i32x_rotate_right i32x4_rotate_right -#define u64x_rotate_right u64x2_rotate_right -#define i64x_rotate_right i64x2_rotate_right -#define u8x_ishift_left u8x16_ishift_left -#define i8x_ishift_left i8x16_ishift_left -#define u16x_ishift_left u16x8_ishift_left -#define i16x_ishift_left i16x8_ishift_left -#define u32x_ishift_left u32x4_ishift_left -#define i32x_ishift_left i32x4_ishift_left -#define u64x_ishift_left u64x2_ishift_left -#define i64x_ishift_left i64x2_ishift_left -#define u8x_ishift_right u8x16_ishift_right -#define i8x_ishift_right i8x16_ishift_right -#define u16x_ishift_right u16x8_ishift_right -#define i16x_ishift_right i16x8_ishift_right -#define u32x_ishift_right u32x4_ishift_right -#define i32x_ishift_right i32x4_ishift_right -#define u64x_ishift_right u64x2_ishift_right -#define i64x_ishift_right i64x2_ishift_right -#define u8x_irotate_left u8x16_irotate_left -#define i8x_irotate_left i8x16_irotate_left -#define u16x_irotate_left u16x8_irotate_left -#define i16x_irotate_left i16x8_irotate_left -#define u32x_irotate_left u32x4_irotate_left -#define i32x_irotate_left i32x4_irotate_left -#define u64x_irotate_left u64x2_irotate_left -#define i64x_irotate_left i64x2_irotate_left -#define u8x_irotate_right u8x16_irotate_right -#define i8x_irotate_right i8x16_irotate_right -#define u16x_irotate_right u16x8_irotate_right -#define i16x_irotate_right i16x8_irotate_right -#define u32x_irotate_right u32x4_irotate_right -#define i32x_irotate_right i32x4_irotate_right -#define u64x_irotate_right u64x2_irotate_right -#define i64x_irotate_right i64x2_irotate_right -#endif - -#if CLIB_VECTOR_WORD_BITS == 64 -#define u8x_shift_left u8x8_shift_left -#define i8x_shift_left i8x8_shift_left -#define u16x_shift_left u16x4_shift_left -#define i16x_shift_left i16x4_shift_left -#define u32x_shift_left u32x2_shift_left -#define i32x_shift_left i32x2_shift_left -#define u8x_shift_right u8x8_shift_right -#define i8x_shift_right i8x8_shift_right -#define u16x_shift_right u16x4_shift_right -#define i16x_shift_right i16x4_shift_right -#define u32x_shift_right u32x2_shift_right -#define i32x_shift_right i32x2_shift_right -#define u8x_rotate_left u8x8_rotate_left -#define i8x_rotate_left i8x8_rotate_left -#define u16x_rotate_left u16x4_rotate_left -#define i16x_rotate_left i16x4_rotate_left -#define u32x_rotate_left u32x2_rotate_left -#define i32x_rotate_left i32x2_rotate_left -#define u8x_rotate_right u8x8_rotate_right -#define i8x_rotate_right i8x8_rotate_right -#define u16x_rotate_right u16x4_rotate_right -#define i16x_rotate_right i16x4_rotate_right -#define u32x_rotate_right u32x2_rotate_right -#define i32x_rotate_right i32x2_rotate_right -#define u8x_ishift_left u8x8_ishift_left -#define i8x_ishift_left i8x8_ishift_left -#define u16x_ishift_left u16x4_ishift_left -#define i16x_ishift_left i16x4_ishift_left -#define u32x_ishift_left u32x2_ishift_left -#define i32x_ishift_left i32x2_ishift_left -#define u8x_ishift_right u8x8_ishift_right -#define i8x_ishift_right i8x8_ishift_right -#define u16x_ishift_right u16x4_ishift_right -#define i16x_ishift_right i16x4_ishift_right -#define u32x_ishift_right u32x2_ishift_right -#define i32x_ishift_right i32x2_ishift_right -#define u8x_irotate_left u8x8_irotate_left -#define i8x_irotate_left i8x8_irotate_left -#define u16x_irotate_left u16x4_irotate_left -#define i16x_irotate_left i16x4_irotate_left -#define u32x_irotate_left u32x2_irotate_left -#define i32x_irotate_left i32x2_irotate_left -#define u8x_irotate_right u8x8_irotate_right -#define i8x_irotate_right i8x8_irotate_right -#define u16x_irotate_right u16x4_irotate_right -#define i16x_irotate_right i16x4_irotate_right -#define u32x_irotate_right u32x2_irotate_right -#define i32x_irotate_right i32x2_irotate_right -#endif - -#if CLIB_VECTOR_WORD_BITS == 128 -#define u8x_splat u8x16_splat -#define i8x_splat i8x16_splat -#define u16x_splat u16x8_splat -#define i16x_splat i16x8_splat -#define u32x_splat u32x4_splat -#define i32x_splat i32x4_splat -#define u64x_splat u64x2_splat -#define i64x_splat i64x2_splat -#endif - -#if CLIB_VECTOR_WORD_BITS == 64 -#define u8x_splat u8x8_splat -#define i8x_splat i8x8_splat -#define u16x_splat u16x4_splat -#define i16x_splat i16x4_splat -#define u32x_splat u32x2_splat -#define i32x_splat i32x2_splat -#endif - -#define u32x4_transpose_step(x,y) \ -do { \ - u32x4 _x = (x); \ - u32x4 _y = (y); \ - (x) = u32x4_interleave_lo (_x, _y); \ - (y) = u32x4_interleave_hi (_x, _y); \ -} while (0) - -/* 4x4 transpose: x_ij -> x_ji */ -#define u32x4_transpose(x0,x1,x2,x3) \ -do { \ - u32x4 _x0 = (u32x4) (x0); \ - u32x4 _x1 = (u32x4) (x1); \ - u32x4 _x2 = (u32x4) (x2); \ - u32x4 _x3 = (u32x4) (x3); \ - u32x4_transpose_step (_x0, _x2); \ - u32x4_transpose_step (_x1, _x3); \ - u32x4_transpose_step (_x0, _x1); \ - u32x4_transpose_step (_x2, _x3); \ - (x0) = (u32x4) _x0; \ - (x1) = (u32x4) _x1; \ - (x2) = (u32x4) _x2; \ - (x3) = (u32x4) _x3; \ -} while (0) - -#define i32x4_transpose(x0,x1,x2,x3) \ -do { \ - u32x4 _x0 = (u32x4) (x0); \ - u32x4 _x1 = (u32x4) (x1); \ - u32x4 _x2 = (u32x4) (x2); \ - u32x4 _x3 = (u32x4) (x3); \ - u32x4_transpose_step (_x0, _x2); \ - u32x4_transpose_step (_x1, _x3); \ - u32x4_transpose_step (_x0, _x1); \ - u32x4_transpose_step (_x2, _x3); \ - (x0) = (i32x4) _x0; \ - (x1) = (i32x4) _x1; \ - (x2) = (i32x4) _x2; \ - (x3) = (i32x4) _x3; \ -} while (0) - -#undef _ - -#endif /* included_vector_funcs_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/vector_iwmmxt.h b/vppinfra/vppinfra/vector_iwmmxt.h deleted file mode 100644 index 8e662045655..00000000000 --- a/vppinfra/vppinfra/vector_iwmmxt.h +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2008 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_vector_iwmmxt_h -#define included_vector_iwmmxt_h - -#include <vppinfra/error.h> /* for ASSERT */ - -/* 64 bit interleaves. */ -always_inline u8x8 -u8x8_interleave_hi (u8x8 a, u8x8 b) -{ - return __builtin_arm_wunpckihb (a, b); -} - -always_inline u8x8 -u8x8_interleave_lo (u8x8 a, u8x8 b) -{ - return __builtin_arm_wunpckilb (a, b); -} - -always_inline u16x4 -u16x4_interleave_hi (u16x4 a, u16x4 b) -{ - return __builtin_arm_wunpckihh (a, b); -} - -always_inline u16x4 -u16x4_interleave_lo (u16x4 a, u16x4 b) -{ - return __builtin_arm_wunpckilh (a, b); -} - -always_inline u32x2 -u32x2_interleave_hi (u32x2 a, u32x2 b) -{ - return __builtin_arm_wunpckihw (a, b); -} - -always_inline u32x2 -u32x2_interleave_lo (u32x2 a, u32x2 b) -{ - return __builtin_arm_wunpckilw (a, b); -} - -always_inline u32x2 -u32x2_splat (u32 a) -{ - u32x2 x = { a }; - x = u32x2_interleave_lo (x, x); - return x; -} - -always_inline u16x4 -u16x4_splat (u16 a) -{ - u32 t = (u32) a | ((u32) a << 16); - return u32x2_splat (t); -} - -always_inline u8x8 -u8x8_splat (u8 a) -{ - u32 t = (u32) a | ((u32) a << 8); - t |= t << 16; - return u32x2_splat (t); -} - -#define i32x2_splat u32x2_splat -#define i16x4_splat u16x4_splat -#define i8x8_splat u8x8_splat - -/* 64 bit shifts. */ - -/* As of July 2008 the __builtin_arm shifts cause gcc-4.3.1 to crash - so we use asm versions. */ -#define _(t,u,lr,f) \ - always_inline t \ - t##_##lr (t x, int i) \ - { \ - i16x4 y; \ - asm (#f " %[y], %[x], %[shift]" \ - : [y] "=y" (y) \ - : [x] "y" (x), [shift] "i" (i * u)); \ - return y; \ - } - -_(u16x4, 1, shift_left, wsllhi) -_(u32x2, 1, shift_left, wsllwi) -_(u16x4, 1, shift_right, wsrlhi) -_(u32x2, 1, shift_right, wsrlwi) -_(i16x4, 1, shift_left, wsllhi) -_(i32x2, 1, shift_left, wsllwi) -_(i16x4, 1, shift_right, wsrahi) _(i32x2, 1, shift_right, wsrawi) -/* Word shifts. */ - _(u8x8, 8, word_shift_left, wslldi) -_(u16x4, 16, word_shift_left, wslldi) -_(u32x2, 32, word_shift_left, wslldi) -_(u8x8, 8, word_shift_right, wsrldi) -_(u16x4, 16, word_shift_right, wsrldi) -_(u32x2, 32, word_shift_right, wsrldi) -_(i8x8, 8, word_shift_left, wslldi) -_(i16x4, 16, word_shift_left, wslldi) -_(i32x2, 32, word_shift_left, wslldi) -_(i8x8, 8, word_shift_right, wsrldi) -_(i16x4, 16, word_shift_right, wsrldi) _(i32x2, 32, word_shift_right, wsrldi) -#undef _ -#endif /* included_vector_iwmmxt_h */ -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/vector_neon.h b/vppinfra/vppinfra/vector_neon.h deleted file mode 100644 index cea5275949f..00000000000 --- a/vppinfra/vppinfra/vector_neon.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef included_vector_neon_h -#define included_vector_neon_h -#include <arm_neon.h> - -/* Splats. */ - -#define u8x16_splat(i) vdupq_n_u8(i) -#define u16x8_splat(i) vdupq_n_u16(i) -#define i16x8_splat(i) vdupq_n_s16(i) -#define u32x4_splat(i) vdupq_n_u32(i) -#define i32x4_splat(i) vdupq_n_s32(i) - -/* Arithmetic */ -#define u16x8_add(a,b) vaddq_u16(a,b) -#define i16x8_add(a,b) vaddq_s16(a,b) -#define u16x8_sub_saturate(a,b) vsubq_u16(a,b) -#define i16x8_sub_saturate(a,b) vsubq_s16(a,b) - -#define u16x8_is_equal(a,b) vceqq_u16(a,b) -#define i16x8_is_equal(a,b) vceqq_i16(a,b) - -always_inline u32 -u16x8_zero_byte_mask (u16x8 input) -{ - u8x16 vall_one = vdupq_n_u8 (0x0); - u8x16 res_values = { 0x01, 0x02, 0x04, 0x08, - 0x10, 0x20, 0x40, 0x80, - 0x01, 0x02, 0x04, 0x08, - 0x10, 0x20, 0x40, 0x80 - }; - - /* input --> [0x80, 0x40, 0x01, 0xf0, ... ] */ - u8x16 test_result = - vreinterpretq_u8_u16 (vceqq_u16 (input, vreinterpretq_u16_u8 (vall_one))); - u8x16 before_merge = vminq_u8 (test_result, res_values); - /*before_merge--> [0x80, 0x00, 0x00, 0x10, ... ] */ - /* u8x16 --> [a,b,c,d, e,f,g,h, i,j,k,l, m,n,o,p] */ - /* pair add until we have 2 uint64_t */ - u16x8 merge1 = vpaddlq_u8 (before_merge); - /* u16x8--> [a+b,c+d, e+f,g+h, i+j,k+l, m+n,o+p] */ - u32x4 merge2 = vpaddlq_u16 (merge1); - /* u32x4--> [a+b+c+d, e+f+g+h, i+j+k+l, m+n+o+p] */ - u64x2 merge3 = vpaddlq_u32 (merge2); - /* u64x2--> [a+b+c+d+e+f+g+h, i+j+k+l+m+n+o+p] */ - return (u32) (vgetq_lane_u64 (merge3, 1) << 8) + vgetq_lane_u64 (merge3, 0); -} - -#endif /* included_vector_neon_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/vector_sse2.h b/vppinfra/vppinfra/vector_sse2.h deleted file mode 100644 index f782e8fd409..00000000000 --- a/vppinfra/vppinfra/vector_sse2.h +++ /dev/null @@ -1,711 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2005 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_vector_sse2_h -#define included_vector_sse2_h - -#include <vppinfra/error_bootstrap.h> /* for ASSERT */ -#include <x86intrin.h> - -/* 128 bit interleaves. */ -always_inline u8x16 -u8x16_interleave_hi (u8x16 a, u8x16 b) -{ - return (u8x16) _mm_unpackhi_epi8 ((__m128i) a, (__m128i) b); -} - -always_inline u8x16 -u8x16_interleave_lo (u8x16 a, u8x16 b) -{ - return (u8x16) _mm_unpacklo_epi8 ((__m128i) a, (__m128i) b); -} - -always_inline u16x8 -u16x8_interleave_hi (u16x8 a, u16x8 b) -{ - return (u16x8) _mm_unpackhi_epi16 ((__m128i) a, (__m128i) b); -} - -always_inline u16x8 -u16x8_interleave_lo (u16x8 a, u16x8 b) -{ - return (u16x8) _mm_unpacklo_epi16 ((__m128i) a, (__m128i) b); -} - -always_inline u32x4 -u32x4_interleave_hi (u32x4 a, u32x4 b) -{ - return (u32x4) _mm_unpackhi_epi32 ((__m128i) a, (__m128i) b); -} - -always_inline u32x4 -u32x4_interleave_lo (u32x4 a, u32x4 b) -{ - return (u32x4) _mm_unpacklo_epi32 ((__m128i) a, (__m128i) b); -} - -always_inline u64x2 -u64x2_interleave_hi (u64x2 a, u64x2 b) -{ - return (u64x2) _mm_unpackhi_epi64 ((__m128i) a, (__m128i) b); -} - -always_inline u64x2 -u64x2_interleave_lo (u64x2 a, u64x2 b) -{ - return (u64x2) _mm_unpacklo_epi64 ((__m128i) a, (__m128i) b); -} - -/* 64 bit interleaves. */ -always_inline u8x8 -u8x8_interleave_hi (u8x8 a, u8x8 b) -{ - return (u8x8) _m_punpckhbw ((__m64) a, (__m64) b); -} - -always_inline u8x8 -u8x8_interleave_lo (u8x8 a, u8x8 b) -{ - return (u8x8) _m_punpcklbw ((__m64) a, (__m64) b); -} - -always_inline u16x4 -u16x4_interleave_hi (u16x4 a, u16x4 b) -{ - return (u16x4) _m_punpckhwd ((__m64) a, (__m64) b); -} - -always_inline u16x4 -u16x4_interleave_lo (u16x4 a, u16x4 b) -{ - return (u16x4) _m_punpcklwd ((__m64) a, (__m64) b); -} - -always_inline u32x2 -u32x2_interleave_hi (u32x2 a, u32x2 b) -{ - return (u32x2) _m_punpckhdq ((__m64) a, (__m64) b); -} - -always_inline u32x2 -u32x2_interleave_lo (u32x2 a, u32x2 b) -{ - return (u32x2) _m_punpckldq ((__m64) a, (__m64) b); -} - -/* 128 bit packs. */ -always_inline u8x16 -u16x8_pack (u16x8 lo, u16x8 hi) -{ - return (u8x16) _mm_packus_epi16 ((__m128i) lo, (__m128i) hi); -} - -always_inline i8x16 -i16x8_pack (i16x8 lo, i16x8 hi) -{ - return (i8x16) _mm_packs_epi16 ((__m128i) lo, (__m128i) hi); -} - -always_inline u16x8 -u32x4_pack (u32x4 lo, u32x4 hi) -{ - return (u16x8) _mm_packs_epi32 ((__m128i) lo, (__m128i) hi); -} - -/* 64 bit packs. */ -always_inline u8x8 -u16x4_pack (u16x4 lo, u16x4 hi) -{ - return (u8x8) _m_packuswb ((__m64) lo, (__m64) hi); -} - -always_inline i8x8 -i16x4_pack (i16x4 lo, i16x4 hi) -{ - return (i8x8) _m_packsswb ((__m64) lo, (__m64) hi); -} - -always_inline u16x4 -u32x2_pack (u32x2 lo, u32x2 hi) -{ - return (u16x4) _m_packssdw ((__m64) lo, (__m64) hi); -} - -always_inline i16x4 -i32x2_pack (i32x2 lo, i32x2 hi) -{ - return (i16x4) _m_packssdw ((__m64) lo, (__m64) hi); -} - -/* Splats: replicate scalar value into vector. */ -always_inline u64x2 -u64x2_splat (u64 a) -{ - u64x2 x = { a }; - x = u64x2_interleave_lo (x, x); - return x; -} - -always_inline u32x4 -u32x4_splat (u32 a) -{ - u32x4 x = { a }; - x = u32x4_interleave_lo (x, x); - x = (u32x4) u64x2_interleave_lo ((u64x2) x, (u64x2) x); - return x; -} - -always_inline u16x8 -u16x8_splat (u16 a) -{ - u32 t = (u32) a | ((u32) a << 16); - return (u16x8) u32x4_splat (t); -} - -always_inline u8x16 -u8x16_splat (u8 a) -{ - u32 t = (u32) a | ((u32) a << 8); - t |= t << 16; - return (u8x16) u16x8_splat (t); -} - -always_inline u32x2 -u32x2_splat (u32 a) -{ - u32x2 x = { a }; - x = u32x2_interleave_lo (x, x); - return x; -} - -always_inline u16x4 -u16x4_splat (u16 a) -{ - u32 t = (u32) a | ((u32) a << 16); - return (u16x4) u32x2_splat (t); -} - -always_inline u8x8 -u8x8_splat (u8 a) -{ - u32 t = (u32) a | ((u32) a << 8); - t |= t << 16; - return (u8x8) u32x2_splat (t); -} - -#define i64x2_splat u64x2_splat -#define i32x4_splat u32x4_splat -#define i16x8_splat u16x8_splat -#define i8x16_splat u8x16_splat -#define i32x2_splat u32x2_splat -#define i16x4_splat u16x4_splat -#define i8x8_splat u8x8_splat - -#ifndef __ICC -always_inline u64x2 -u64x2_read_lo (u64x2 x, u64 * a) -{ - return (u64x2) _mm_loadl_pi ((__m128) x, (__m64 *) a); -} - -always_inline u64x2 -u64x2_read_hi (u64x2 x, u64 * a) -{ - return (u64x2) _mm_loadh_pi ((__m128) x, (__m64 *) a); -} - -always_inline void -u64x2_write_lo (u64x2 x, u64 * a) -{ - _mm_storel_pi ((__m64 *) a, (__m128) x); -} - -always_inline void -u64x2_write_hi (u64x2 x, u64 * a) -{ - _mm_storeh_pi ((__m64 *) a, (__m128) x); -} -#endif - -/* Unaligned loads/stores. */ - -#define _(t) \ - always_inline void t##_store_unaligned (t x, t * a) \ - { _mm_storeu_si128 ((__m128i *) a, (__m128i) x); } \ - always_inline t t##_load_unaligned (t * a) \ - { return (t) _mm_loadu_si128 ((__m128i *) a); } - -_(u8x16) _(u16x8) _(u32x4) _(u64x2) _(i8x16) _(i16x8) _(i32x4) _(i64x2) -#undef _ -#define _signed_binop(n,m,f,g) \ - /* Unsigned */ \ - always_inline u##n##x##m \ - u##n##x##m##_##f (u##n##x##m x, u##n##x##m y) \ - { return (u##n##x##m) _mm_##g##n ((__m128i) x, (__m128i) y); } \ - \ - /* Signed */ \ - always_inline i##n##x##m \ - i##n##x##m##_##f (i##n##x##m x, i##n##x##m y) \ - { return (i##n##x##m) _mm_##g##n ((__m128i) x, (__m128i) y); } -/* Addition/subtraction. */ - _signed_binop (8, 16, add, add_epi) -_signed_binop (16, 8, add, add_epi) -_signed_binop (32, 4, add, add_epi) -_signed_binop (64, 2, add, add_epi) -_signed_binop (8, 16, sub, sub_epi) -_signed_binop (16, 8, sub, sub_epi) -_signed_binop (32, 4, sub, sub_epi) _signed_binop (64, 2, sub, sub_epi) -/* Addition/subtraction with saturation. */ - _signed_binop (8, 16, add_saturate, adds_epu) -_signed_binop (16, 8, add_saturate, adds_epu) -_signed_binop (8, 16, sub_saturate, subs_epu) -_signed_binop (16, 8, sub_saturate, subs_epu) -/* Multiplication. */ - always_inline i16x8 i16x8_mul_lo (i16x8 x, i16x8 y) -{ - return (i16x8) _mm_mullo_epi16 ((__m128i) x, (__m128i) y); -} - -always_inline u16x8 -u16x8_mul_lo (u16x8 x, u16x8 y) -{ - return (u16x8) _mm_mullo_epi16 ((__m128i) x, (__m128i) y); -} - -always_inline i16x8 -i16x8_mul_hi (i16x8 x, i16x8 y) -{ - return (i16x8) _mm_mulhi_epu16 ((__m128i) x, (__m128i) y); -} - -always_inline u16x8 -u16x8_mul_hi (u16x8 x, u16x8 y) -{ - return (u16x8) _mm_mulhi_epu16 ((__m128i) x, (__m128i) y); -} - -/* 128 bit shifts. */ - -#define _(p,a,b,c,f) \ - always_inline p##a##x##b p##a##x##b##_ishift_##c (p##a##x##b x, int i) \ - { return (p##a##x##b) _mm_##f##i_epi##a ((__m128i) x, i); } \ - \ - always_inline p##a##x##b p##a##x##b##_shift_##c (p##a##x##b x, p##a##x##b y) \ - { return (p##a##x##b) _mm_##f##_epi##a ((__m128i) x, (__m128i) y); } - -_(u, 16, 8, left, sll) -_(u, 32, 4, left, sll) -_(u, 64, 2, left, sll) -_(u, 16, 8, right, srl) -_(u, 32, 4, right, srl) -_(u, 64, 2, right, srl) -_(i, 16, 8, left, sll) -_(i, 32, 4, left, sll) -_(i, 64, 2, left, sll) _(i, 16, 8, right, sra) _(i, 32, 4, right, sra) -#undef _ -/* 64 bit shifts. */ - always_inline u16x4 -u16x4_shift_left (u16x4 x, u16x4 i) -{ - return (u16x4) _m_psllw ((__m64) x, (__m64) i); -}; - -always_inline u32x2 -u32x2_shift_left (u32x2 x, u32x2 i) -{ - return (u32x2) _m_pslld ((__m64) x, (__m64) i); -}; - -always_inline u16x4 -u16x4_shift_right (u16x4 x, u16x4 i) -{ - return (u16x4) _m_psrlw ((__m64) x, (__m64) i); -}; - -always_inline u32x2 -u32x2_shift_right (u32x2 x, u32x2 i) -{ - return (u32x2) _m_psrld ((__m64) x, (__m64) i); -}; - -always_inline i16x4 -i16x4_shift_left (i16x4 x, i16x4 i) -{ - return (i16x4) _m_psllw ((__m64) x, (__m64) i); -}; - -always_inline i32x2 -i32x2_shift_left (i32x2 x, i32x2 i) -{ - return (i32x2) _m_pslld ((__m64) x, (__m64) i); -}; - -always_inline i16x4 -i16x4_shift_right (i16x4 x, i16x4 i) -{ - return (i16x4) _m_psraw ((__m64) x, (__m64) i); -}; - -always_inline i32x2 -i32x2_shift_right (i32x2 x, i32x2 i) -{ - return (i32x2) _m_psrad ((__m64) x, (__m64) i); -}; - -#define u8x16_word_shift_left(a,n) (u8x16) _mm_slli_si128((__m128i) a, n) -#define u8x16_word_shift_right(a,n) (u8x16) _mm_srli_si128((__m128i) a, n) - -#define i8x16_word_shift_left(a,n) \ - ((i8x16) u8x16_word_shift_left((u8x16) (a), (n))) -#define i8x16_word_shift_right(a,n) \ - ((i8x16) u8x16_word_shift_right((u8x16) (a), (n))) - -#define u16x8_word_shift_left(a,n) \ - ((u16x8) u8x16_word_shift_left((u8x16) (a), (n) * sizeof (u16))) -#define i16x8_word_shift_left(a,n) \ - ((u16x8) u8x16_word_shift_left((u8x16) (a), (n) * sizeof (u16))) -#define u16x8_word_shift_right(a,n) \ - ((u16x8) u8x16_word_shift_right((u8x16) (a), (n) * sizeof (u16))) -#define i16x8_word_shift_right(a,n) \ - ((i16x8) u8x16_word_shift_right((u8x16) (a), (n) * sizeof (u16))) - -#define u32x4_word_shift_left(a,n) \ - ((u32x4) u8x16_word_shift_left((u8x16) (a), (n) * sizeof (u32))) -#define i32x4_word_shift_left(a,n) \ - ((u32x4) u8x16_word_shift_left((u8x16) (a), (n) * sizeof (u32))) -#define u32x4_word_shift_right(a,n) \ - ((u32x4) u8x16_word_shift_right((u8x16) (a), (n) * sizeof (u32))) -#define i32x4_word_shift_right(a,n) \ - ((i32x4) u8x16_word_shift_right((u8x16) (a), (n) * sizeof (u32))) - -#define u64x2_word_shift_left(a,n) \ - ((u64x2) u8x16_word_shift_left((u8x16) (a), (n) * sizeof (u64))) -#define i64x2_word_shift_left(a,n) \ - ((u64x2) u8x16_word_shift_left((u8x16) (a), (n) * sizeof (u64))) -#define u64x2_word_shift_right(a,n) \ - ((u64x2) u8x16_word_shift_right((u8x16) (a), (n) * sizeof (u64))) -#define i64x2_word_shift_right(a,n) \ - ((i64x2) u8x16_word_shift_right((u8x16) (a), (n) * sizeof (u64))) - -/* SSE2 has no rotate instructions: use shifts to simulate them. */ -#define _(t,n,lr1,lr2) \ - always_inline t##x##n \ - t##x##n##_irotate_##lr1 (t##x##n w, int i) \ - { \ - ASSERT (i >= 0 && i <= BITS (t)); \ - return (t##x##n##_ishift_##lr1 (w, i) \ - | t##x##n##_ishift_##lr2 (w, BITS (t) - i)); \ - } \ - \ - always_inline t##x##n \ - t##x##n##_rotate_##lr1 (t##x##n w, t##x##n i) \ - { \ - t##x##n j = t##x##n##_splat (BITS (t)); \ - return (t##x##n##_shift_##lr1 (w, i) \ - | t##x##n##_shift_##lr2 (w, j - i)); \ - } - -_(u16, 8, left, right); -_(u16, 8, right, left); -_(u32, 4, left, right); -_(u32, 4, right, left); -_(u64, 2, left, right); -_(u64, 2, right, left); - -#undef _ - -#ifndef __clang__ -#define _(t,n,lr1,lr2) \ - always_inline t##x##n \ - t##x##n##_word_rotate2_##lr1 (t##x##n w0, t##x##n w1, int i) \ - { \ - int m = sizeof (t##x##n) / sizeof (t); \ - ASSERT (i >= 0 && i < m); \ - return (t##x##n##_word_shift_##lr1 (w0, i) \ - | t##x##n##_word_shift_##lr2 (w1, m - i)); \ - } \ - \ - always_inline t##x##n \ - t##x##n##_word_rotate_##lr1 (t##x##n w0, int i) \ - { return t##x##n##_word_rotate2_##lr1 (w0, w0, i); } - -_(u8, 16, left, right); -_(u8, 16, right, left); -_(u16, 8, left, right); -_(u16, 8, right, left); -_(u32, 4, left, right); -_(u32, 4, right, left); -_(u64, 2, left, right); -_(u64, 2, right, left); - -#undef _ -#endif - -/* Compare operations. */ -always_inline u8x16 -u8x16_is_equal (u8x16 x, u8x16 y) -{ - return (u8x16) _mm_cmpeq_epi8 ((__m128i) x, (__m128i) y); -} - -always_inline i8x16 -i8x16_is_equal (i8x16 x, i8x16 y) -{ - return (i8x16) _mm_cmpeq_epi8 ((__m128i) x, (__m128i) y); -} - -always_inline u16x8 -u16x8_is_equal (u16x8 x, u16x8 y) -{ - return (u16x8) _mm_cmpeq_epi16 ((__m128i) x, (__m128i) y); -} - -always_inline i16x8 -i16x8_is_equal (i16x8 x, i16x8 y) -{ - return (i16x8) _mm_cmpeq_epi16 ((__m128i) x, (__m128i) y); -} - -always_inline u32x4 -u32x4_is_equal (u32x4 x, u32x4 y) -{ - return (u32x4) _mm_cmpeq_epi32 ((__m128i) x, (__m128i) y); -} - -always_inline i32x4 -i32x4_is_equal (i32x4 x, i32x4 y) -{ - return (i32x4) _mm_cmpeq_epi32 ((__m128i) x, (__m128i) y); -} - -always_inline u8x16 -i8x16_is_greater (i8x16 x, i8x16 y) -{ - return (u8x16) _mm_cmpgt_epi8 ((__m128i) x, (__m128i) y); -} - -always_inline u16x8 -i16x8_is_greater (i16x8 x, i16x8 y) -{ - return (u16x8) _mm_cmpgt_epi16 ((__m128i) x, (__m128i) y); -} - -always_inline u32x4 -i32x4_is_greater (i32x4 x, i32x4 y) -{ - return (u32x4) _mm_cmpgt_epi32 ((__m128i) x, (__m128i) y); -} - -always_inline u8x16 -u8x16_is_zero (u8x16 x) -{ - u8x16 zero = { 0 }; - return u8x16_is_equal (x, zero); -} - -always_inline u16x8 -u16x8_is_zero (u16x8 x) -{ - u16x8 zero = { 0 }; - return u16x8_is_equal (x, zero); -} - -always_inline u32x4 -u32x4_is_zero (u32x4 x) -{ - u32x4 zero = { 0 }; - return u32x4_is_equal (x, zero); -} - -#define u32x4_select(A,MASK) \ -({ \ - u32x4 _x, _y; \ - _x = (A); \ - asm volatile ("pshufd %[mask], %[x], %[y]" \ - : /* outputs */ [y] "=x" (_y) \ - : /* inputs */ [x] "x" (_x), [mask] "i" (MASK)); \ - _y; \ -}) - -#define u32x4_splat_word(x,i) \ - u32x4_select ((x), (((i) << (2*0)) \ - | ((i) << (2*1)) \ - | ((i) << (2*2)) \ - | ((i) << (2*3)))) - -/* Extract low order 32 bit word. */ -always_inline u32 -u32x4_get0 (u32x4 x) -{ - u32 result; - asm volatile ("movd %[x], %[result]": /* outputs */ [result] "=r" (result) - : /* inputs */ [x] "x" (x)); - return result; -} - -always_inline u32x4 -u32x4_set0 (u32 x) -{ - u32x4 result; - asm volatile ("movd %[x], %[result]": /* outputs */ [result] "=x" (result) - : /* inputs */ [x] "r" (x)); - return result; -} - -always_inline i32x4 -i32x4_set0 (i32 x) -{ - return (i32x4) u32x4_set0 ((u32) x); -} - -always_inline i32 -i32x4_get0 (i32x4 x) -{ - return (i32) u32x4_get0 ((u32x4) x); -} - -/* Converts all ones/zeros compare mask to bitmap. */ -always_inline u32 -u8x16_compare_byte_mask (u8x16 x) -{ - return _mm_movemask_epi8 ((__m128i) x); -} - -extern u8 u32x4_compare_word_mask_table[256]; - -always_inline u32 -u32x4_compare_word_mask (u32x4 x) -{ - u32 m = u8x16_compare_byte_mask ((u8x16) x); - return (u32x4_compare_word_mask_table[(m >> 0) & 0xff] - | (u32x4_compare_word_mask_table[(m >> 8) & 0xff] << 2)); -} - -always_inline u32 -u8x16_zero_byte_mask (u8x16 x) -{ - u8x16 zero = { 0 }; - return u8x16_compare_byte_mask (u8x16_is_equal (x, zero)); -} - -always_inline u32 -u16x8_zero_byte_mask (u16x8 x) -{ - u16x8 zero = { 0 }; - return u8x16_compare_byte_mask ((u8x16) u16x8_is_equal (x, zero)); -} - -always_inline u32 -u32x4_zero_byte_mask (u32x4 x) -{ - u32x4 zero = { 0 }; - return u8x16_compare_byte_mask ((u8x16) u32x4_is_equal (x, zero)); -} - -always_inline u8x16 -u8x16_max (u8x16 x, u8x16 y) -{ - return (u8x16) _mm_max_epu8 ((__m128i) x, (__m128i) y); -} - -always_inline u32 -u8x16_max_scalar (u8x16 x) -{ - x = u8x16_max (x, u8x16_word_shift_right (x, 8)); - x = u8x16_max (x, u8x16_word_shift_right (x, 4)); - x = u8x16_max (x, u8x16_word_shift_right (x, 2)); - x = u8x16_max (x, u8x16_word_shift_right (x, 1)); - return _mm_extract_epi16 ((__m128i) x, 0) & 0xff; -} - -always_inline u8x16 -u8x16_min (u8x16 x, u8x16 y) -{ - return (u8x16) _mm_min_epu8 ((__m128i) x, (__m128i) y); -} - -always_inline u8 -u8x16_min_scalar (u8x16 x) -{ - x = u8x16_min (x, u8x16_word_shift_right (x, 8)); - x = u8x16_min (x, u8x16_word_shift_right (x, 4)); - x = u8x16_min (x, u8x16_word_shift_right (x, 2)); - x = u8x16_min (x, u8x16_word_shift_right (x, 1)); - return _mm_extract_epi16 ((__m128i) x, 0) & 0xff; -} - -always_inline i16x8 -i16x8_max (i16x8 x, i16x8 y) -{ - return (i16x8) _mm_max_epi16 ((__m128i) x, (__m128i) y); -} - -always_inline i16 -i16x8_max_scalar (i16x8 x) -{ - x = i16x8_max (x, i16x8_word_shift_right (x, 4)); - x = i16x8_max (x, i16x8_word_shift_right (x, 2)); - x = i16x8_max (x, i16x8_word_shift_right (x, 1)); - return _mm_extract_epi16 ((__m128i) x, 0); -} - -always_inline i16x8 -i16x8_min (i16x8 x, i16x8 y) -{ - return (i16x8) _mm_min_epi16 ((__m128i) x, (__m128i) y); -} - -always_inline i16 -i16x8_min_scalar (i16x8 x) -{ - x = i16x8_min (x, i16x8_word_shift_right (x, 4)); - x = i16x8_min (x, i16x8_word_shift_right (x, 2)); - x = i16x8_min (x, i16x8_word_shift_right (x, 1)); - return _mm_extract_epi16 ((__m128i) x, 0); -} - -#undef _signed_binop - -#endif /* included_vector_sse2_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/vhash.c b/vppinfra/vppinfra/vhash.c deleted file mode 100644 index f9dac0d9ff1..00000000000 --- a/vppinfra/vppinfra/vhash.c +++ /dev/null @@ -1,772 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2010 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include <vppinfra/vhash.h> - -#ifdef CLIB_HAVE_VEC128 - -/* Overflow search buckets have an extra u32x4 for saving key_hash data. - This makes it easier to refill main search bucket from overflow vector. */ -typedef struct -{ - /* 4 results for this bucket. */ - u32x4_union_t result; - - /* 4 hash codes for this bucket. These are used to refill main - search buckets from overflow buckets when space becomes available. */ - u32x4_union_t key_hash; - - /* n_key_u32s u32x4s of key data follow. */ - u32x4_union_t key[0]; -} vhash_overflow_search_bucket_t; - -always_inline void -set_overflow_result (vhash_overflow_search_bucket_t * b, - u32 i, u32 result, u32 key_hash) -{ - b->result.as_u32[i] = result; - b->key_hash.as_u32[i] = key_hash; -} - -always_inline void -free_overflow_bucket (vhash_overflow_buckets_t * ob, - vhash_overflow_search_bucket_t * b, u32 i) -{ - u32 o = (u32x4_union_t *) b - ob->search_buckets; - ASSERT (o < vec_len (ob->search_buckets)); - vec_add1 (ob->free_indices, 4 * o + i); -} - -always_inline vhash_overflow_search_bucket_t * -get_overflow_search_bucket (vhash_overflow_buckets_t * obs, u32 i, - u32 n_key_u32s) -{ - return ((vhash_overflow_search_bucket_t *) - vec_elt_at_index (obs->search_buckets, i)); -} - -always_inline vhash_overflow_search_bucket_t * -next_overflow_bucket (vhash_overflow_search_bucket_t * b, u32 n_key_u32s) -{ - return (vhash_overflow_search_bucket_t *) & b->key[n_key_u32s]; -} - -#define foreach_vhash_overflow_bucket(b,ob,n_key_u32s) \ - for ((b) = (vhash_overflow_search_bucket_t *) ob->search_buckets; \ - (u32x4_union_t *) (b) < vec_end (ob->search_buckets); \ - b = next_overflow_bucket (b, n_key_u32s)) - -u32 -vhash_get_overflow (vhash_t * h, u32 key_hash, u32 vi, u32 n_key_u32s) -{ - vhash_overflow_buckets_t *ob = vhash_get_overflow_buckets (h, key_hash); - vhash_overflow_search_bucket_t *b; - u32 i, result = 0; - - foreach_vhash_overflow_bucket (b, ob, n_key_u32s) - { - u32x4 r = b->result.as_u32x4; - - for (i = 0; i < n_key_u32s; i++) - r &= vhash_bucket_compare (h, &b->key[0], i, vi); - - result = vhash_merge_results (r); - if (result) - break; - } - - return result; -} - -u32 -vhash_set_overflow (vhash_t * h, - u32 key_hash, u32 vi, u32 new_result, u32 n_key_u32s) -{ - vhash_overflow_buckets_t *ob = vhash_get_overflow_buckets (h, key_hash); - vhash_overflow_search_bucket_t *b; - u32 i_set, i, old_result; - - foreach_vhash_overflow_bucket (b, ob, n_key_u32s) - { - u32x4 r; - - r = b->result.as_u32x4; - for (i = 0; i < n_key_u32s; i++) - r &= vhash_bucket_compare (h, &b->key[0], i, vi); - - old_result = vhash_merge_results (r); - if (old_result) - { - i_set = vhash_non_empty_result_index (r); - set_overflow_result (b, i_set, new_result, key_hash); - return old_result; - } - } - - /* Check free list. */ - if (vec_len (ob->free_indices) == 0) - { - /* Out of free overflow buckets. Resize. */ - u32 j, *p; - i = vec_len (ob->search_buckets); - vec_resize_aligned (ob->search_buckets, - sizeof (b[0]) / sizeof (u32x4) + n_key_u32s, - CLIB_CACHE_LINE_BYTES); - vec_add2 (ob->free_indices, p, 4); - for (j = 0; j < 4; j++) - p[j] = 4 * i + j; - } - - i = vec_pop (ob->free_indices); - - i_set = i & 3; - b = ((vhash_overflow_search_bucket_t *) - vec_elt_at_index (ob->search_buckets, i / 4)); - - /* Insert result. */ - set_overflow_result (b, i_set, new_result, key_hash); - - /* Insert key. */ - for (i = 0; i < n_key_u32s; i++) - b->key[i].as_u32[i_set] = vhash_get_key_word (h, i, vi); - - ob->n_overflow++; - h->n_elts++; - - return /* old result was invalid */ 0; -} - -u32 -vhash_unset_overflow (vhash_t * h, u32 key_hash, u32 vi, u32 n_key_u32s) -{ - vhash_overflow_buckets_t *ob = vhash_get_overflow_buckets (h, key_hash); - vhash_overflow_search_bucket_t *b; - u32 i_set, i, old_result; - - foreach_vhash_overflow_bucket (b, ob, n_key_u32s) - { - u32x4 r; - - r = b->result.as_u32x4; - for (i = 0; i < n_key_u32s; i++) - r &= vhash_bucket_compare (h, &b->key[0], i, vi); - - old_result = vhash_merge_results (r); - if (old_result) - { - i_set = vhash_non_empty_result_index (r); - - /* Invalidate result and invert key hash so that this will - never match since all keys in this overflow bucket have - matching key hashs. */ - set_overflow_result (b, i_set, 0, ~key_hash); - - free_overflow_bucket (ob, b, i_set); - - ASSERT (ob->n_overflow > 0); - ob->n_overflow--; - h->n_elts--; - return old_result; - } - } - - /* Could not find key. */ - return 0; -} - -void -vhash_unset_refill_from_overflow (vhash_t * h, - vhash_search_bucket_t * sb, - u32 key_hash, u32 n_key_u32s) -{ - vhash_overflow_buckets_t *obs = vhash_get_overflow_buckets (h, key_hash); - vhash_overflow_search_bucket_t *ob; - u32 i, j, i_refill, bucket_mask = h->bucket_mask.as_u32[0]; - - /* Find overflow element with matching key hash. */ - foreach_vhash_overflow_bucket (ob, obs, n_key_u32s) - { - for (i = 0; i < 4; i++) - { - if (!ob->result.as_u32[i]) - continue; - if ((ob->key_hash.as_u32[i] & bucket_mask) - != (key_hash & bucket_mask)) - continue; - - i_refill = vhash_empty_result_index (sb->result.as_u32x4); - sb->result.as_u32[i_refill] = ob->result.as_u32[i]; - for (j = 0; j < n_key_u32s; j++) - sb->key[j].as_u32[i_refill] = ob->key[j].as_u32[i]; - set_overflow_result (ob, i, 0, ~key_hash); - free_overflow_bucket (obs, ob, i); - return; - } - } -} - -void -vhash_init (vhash_t * h, u32 log2_n_keys, u32 n_key_u32, u32 * hash_seeds) -{ - uword i, j, m; - vhash_search_bucket_t *b; - - memset (h, 0, sizeof (h[0])); - - /* Must have at least 4 keys (e.g. one search bucket). */ - log2_n_keys = clib_max (log2_n_keys, 2); - - h->log2_n_keys = log2_n_keys; - h->n_key_u32 = n_key_u32; - m = pow2_mask (h->log2_n_keys) & ~3; - for (i = 0; i < VECTOR_WORD_TYPE_LEN (u32); i++) - h->bucket_mask.as_u32[i] = m; - - /* Allocate and zero search buckets. */ - i = (sizeof (b[0]) / sizeof (u32x4) + n_key_u32) << (log2_n_keys - 2); - vec_validate_aligned (h->search_buckets, i - 1, CLIB_CACHE_LINE_BYTES); - - for (i = 0; i < ARRAY_LEN (h->find_first_zero_table); i++) - h->find_first_zero_table[i] = min_log2 (first_set (~i)); - - for (i = 0; i < ARRAY_LEN (h->hash_seeds); i++) - for (j = 0; j < VECTOR_WORD_TYPE_LEN (u32); j++) - h->hash_seeds[i].as_u32[j] = hash_seeds[i]; -} - -static_always_inline u32 -vhash_main_key_gather (void *_vm, u32 vi, u32 wi, u32 n_key_u32) -{ - vhash_main_t *vm = _vm; - return vec_elt (vm->keys, vi * n_key_u32 + wi); -} - -static_always_inline u32x4 -vhash_main_4key_gather (void *_vm, u32 vi, u32 wi, u32 n_key_u32s) -{ - vhash_main_t *vm = _vm; - u32x4_union_t x; - - ASSERT (n_key_u32s == vm->n_key_u32); - ASSERT (wi < n_key_u32s); - - x.as_u32[0] = vec_elt (vm->keys, (vi + 0) * n_key_u32s + wi); - x.as_u32[1] = vec_elt (vm->keys, (vi + 1) * n_key_u32s + wi); - x.as_u32[2] = vec_elt (vm->keys, (vi + 2) * n_key_u32s + wi); - x.as_u32[3] = vec_elt (vm->keys, (vi + 3) * n_key_u32s + wi); - return x.as_u32x4; -} - -static_always_inline u32 -vhash_main_set_result (void *_vm, u32 vi, u32 old_result, u32 n_key_u32) -{ - vhash_main_t *vm = _vm; - u32 *p = vec_elt_at_index (vm->results, vi); - u32 new_result = p[0]; - p[0] = old_result; - return new_result; -} - -static_always_inline u32 -vhash_main_get_result (void *_vm, u32 vi, u32 old_result, u32 n_key_u32) -{ - vhash_main_t *vm = _vm; - vec_elt (vm->results, vi) = old_result; - return old_result; -} - -static_always_inline u32x4 -vhash_main_get_4result (void *_vm, u32 vi, u32x4 old_result, u32 n_key_u32) -{ - vhash_main_t *vm = _vm; - u32x4 *p = (u32x4 *) vec_elt_at_index (vm->results, vi); - p[0] = old_result; - return old_result; -} - -#define _(N_KEY_U32) \ - static_always_inline u32 \ - vhash_main_key_gather_##N_KEY_U32 (void * _vm, u32 vi, u32 i) \ - { return vhash_main_key_gather (_vm, vi, i, N_KEY_U32); } \ - \ - static_always_inline u32x4 \ - vhash_main_4key_gather_##N_KEY_U32 (void * _vm, u32 vi, u32 i) \ - { return vhash_main_4key_gather (_vm, vi, i, N_KEY_U32); } \ - \ - clib_pipeline_stage_static \ - (vhash_main_gather_keys_stage_##N_KEY_U32, \ - vhash_main_t *, vm, i, \ - { \ - vhash_gather_4key_stage \ - (vm->vhash, \ - /* vector_index */ i, \ - vhash_main_4key_gather_##N_KEY_U32, \ - vm, \ - N_KEY_U32); \ - }) \ - \ - clib_pipeline_stage_no_inline \ - (vhash_main_gather_keys_mod_stage_##N_KEY_U32, \ - vhash_main_t *, vm, i, \ - { \ - vhash_gather_key_stage \ - (vm->vhash, \ - /* vector_index */ vm->n_vectors_div_4, \ - /* n_vectors */ vm->n_vectors_mod_4, \ - vhash_main_key_gather_##N_KEY_U32, \ - vm, \ - N_KEY_U32); \ - }) \ - \ - clib_pipeline_stage \ - (vhash_main_hash_finalize_stage_##N_KEY_U32, \ - vhash_main_t *, vm, i, \ - { \ - vhash_finalize_stage (vm->vhash, i, N_KEY_U32); \ - }) \ - \ - clib_pipeline_stage_no_inline \ - (vhash_main_hash_finalize_mod_stage_##N_KEY_U32, \ - vhash_main_t *, vm, i, \ - { \ - vhash_finalize_stage (vm->vhash, vm->n_vectors_div_4, N_KEY_U32); \ - }) \ - \ - clib_pipeline_stage_static \ - (vhash_main_get_stage_##N_KEY_U32, \ - vhash_main_t *, vm, i, \ - { \ - vhash_get_4_stage (vm->vhash, \ - /* vector_index */ i, \ - vhash_main_get_4result, \ - vm, N_KEY_U32); \ - }) \ - \ - clib_pipeline_stage_no_inline \ - (vhash_main_get_mod_stage_##N_KEY_U32, \ - vhash_main_t *, vm, i, \ - { \ - vhash_get_stage (vm->vhash, \ - /* vector_index */ vm->n_vectors_div_4, \ - /* n_vectors */ vm->n_vectors_mod_4, \ - vhash_main_get_result, \ - vm, N_KEY_U32); \ - }) \ - \ - clib_pipeline_stage_static \ - (vhash_main_set_stage_##N_KEY_U32, \ - vhash_main_t *, vm, i, \ - { \ - vhash_set_stage (vm->vhash, \ - /* vector_index */ i, \ - /* n_vectors */ VECTOR_WORD_TYPE_LEN (u32), \ - vhash_main_set_result, \ - vm, N_KEY_U32); \ - }) \ - \ - clib_pipeline_stage_no_inline \ - (vhash_main_set_mod_stage_##N_KEY_U32, \ - vhash_main_t *, vm, i, \ - { \ - vhash_set_stage (vm->vhash, \ - /* vector_index */ vm->n_vectors_div_4, \ - /* n_vectors */ vm->n_vectors_mod_4, \ - vhash_main_set_result, \ - vm, N_KEY_U32); \ - }) \ - \ - clib_pipeline_stage_static \ - (vhash_main_unset_stage_##N_KEY_U32, \ - vhash_main_t *, vm, i, \ - { \ - vhash_unset_stage (vm->vhash, \ - /* vector_index */ i, \ - /* n_vectors */ VECTOR_WORD_TYPE_LEN (u32), \ - vhash_main_get_result, \ - vm, N_KEY_U32); \ - }) \ - \ - clib_pipeline_stage_no_inline \ - (vhash_main_unset_mod_stage_##N_KEY_U32, \ - vhash_main_t *, vm, i, \ - { \ - vhash_unset_stage (vm->vhash, \ - /* vector_index */ vm->n_vectors_div_4, \ - /* n_vectors */ vm->n_vectors_mod_4, \ - vhash_main_get_result, \ - vm, N_KEY_U32); \ - }) - -_(1); -_(2); -_(3); -_(4); -_(5); -_(6); - -#undef _ - -#define _(N_KEY_U32) \ - clib_pipeline_stage \ - (vhash_main_hash_mix_stage_##N_KEY_U32, \ - vhash_main_t *, vm, i, \ - { \ - vhash_mix_stage (vm->vhash, i, N_KEY_U32); \ - }) \ - \ - clib_pipeline_stage_no_inline \ - (vhash_main_hash_mix_mod_stage_##N_KEY_U32, \ - vhash_main_t *, vm, i, \ - { \ - vhash_mix_stage (vm->vhash, vm->n_vectors_div_4, N_KEY_U32); \ - }) - -_(4); -_(5); -_(6); - -#undef _ - -typedef enum -{ - GET, SET, UNSET, -} vhash_main_op_t; - -static void -vhash_main_op (vhash_main_t * vm, vhash_main_op_t op) -{ - u32 n_keys = vec_len (vm->results); - - vm->n_key_u32 = vm->vhash->n_key_u32; - - vhash_validate_sizes (vm->vhash, vm->n_key_u32, n_keys); - - vm->n_vectors_div_4 = n_keys / 4; - vm->n_vectors_mod_4 = n_keys % 4; - - if (vm->n_vectors_div_4 > 0) - { - switch (vm->n_key_u32) - { - default: - ASSERT (0); - break; - -#define _(N_KEY_U32) \ - case N_KEY_U32: \ - if (op == GET) \ - clib_pipeline_run_3_stage \ - (vm->n_vectors_div_4, \ - vm, \ - vhash_main_gather_keys_stage_##N_KEY_U32, \ - vhash_main_hash_finalize_stage_##N_KEY_U32, \ - vhash_main_get_stage_##N_KEY_U32); \ - else if (op == SET) \ - clib_pipeline_run_3_stage \ - (vm->n_vectors_div_4, \ - vm, \ - vhash_main_gather_keys_stage_##N_KEY_U32, \ - vhash_main_hash_finalize_stage_##N_KEY_U32, \ - vhash_main_set_stage_##N_KEY_U32); \ - else \ - clib_pipeline_run_3_stage \ - (vm->n_vectors_div_4, \ - vm, \ - vhash_main_gather_keys_stage_##N_KEY_U32, \ - vhash_main_hash_finalize_stage_##N_KEY_U32, \ - vhash_main_unset_stage_##N_KEY_U32); \ - break; - - _(1); - _(2); - _(3); - -#undef _ - -#define _(N_KEY_U32) \ - case N_KEY_U32: \ - if (op == GET) \ - clib_pipeline_run_4_stage \ - (vm->n_vectors_div_4, \ - vm, \ - vhash_main_gather_keys_stage_##N_KEY_U32, \ - vhash_main_hash_mix_stage_##N_KEY_U32, \ - vhash_main_hash_finalize_stage_##N_KEY_U32, \ - vhash_main_get_stage_##N_KEY_U32); \ - else if (op == SET) \ - clib_pipeline_run_4_stage \ - (vm->n_vectors_div_4, \ - vm, \ - vhash_main_gather_keys_stage_##N_KEY_U32, \ - vhash_main_hash_mix_stage_##N_KEY_U32, \ - vhash_main_hash_finalize_stage_##N_KEY_U32, \ - vhash_main_set_stage_##N_KEY_U32); \ - else \ - clib_pipeline_run_4_stage \ - (vm->n_vectors_div_4, \ - vm, \ - vhash_main_gather_keys_stage_##N_KEY_U32, \ - vhash_main_hash_mix_stage_##N_KEY_U32, \ - vhash_main_hash_finalize_stage_##N_KEY_U32, \ - vhash_main_unset_stage_##N_KEY_U32); \ - break; - - _(4); - _(5); - _(6); - -#undef _ - } - } - - - if (vm->n_vectors_mod_4 > 0) - { - switch (vm->n_key_u32) - { - default: - ASSERT (0); - break; - -#define _(N_KEY_U32) \ - case N_KEY_U32: \ - if (op == GET) \ - clib_pipeline_run_3_stage \ - (1, \ - vm, \ - vhash_main_gather_keys_mod_stage_##N_KEY_U32, \ - vhash_main_hash_finalize_mod_stage_##N_KEY_U32, \ - vhash_main_get_mod_stage_##N_KEY_U32); \ - else if (op == SET) \ - clib_pipeline_run_3_stage \ - (1, \ - vm, \ - vhash_main_gather_keys_mod_stage_##N_KEY_U32, \ - vhash_main_hash_finalize_mod_stage_##N_KEY_U32, \ - vhash_main_set_mod_stage_##N_KEY_U32); \ - else \ - clib_pipeline_run_3_stage \ - (1, \ - vm, \ - vhash_main_gather_keys_mod_stage_##N_KEY_U32, \ - vhash_main_hash_finalize_mod_stage_##N_KEY_U32, \ - vhash_main_unset_mod_stage_##N_KEY_U32); \ - break; - - _(1); - _(2); - _(3); - -#undef _ - -#define _(N_KEY_U32) \ - case N_KEY_U32: \ - if (op == GET) \ - clib_pipeline_run_4_stage \ - (1, \ - vm, \ - vhash_main_gather_keys_mod_stage_##N_KEY_U32, \ - vhash_main_hash_mix_mod_stage_##N_KEY_U32, \ - vhash_main_hash_finalize_mod_stage_##N_KEY_U32, \ - vhash_main_get_mod_stage_##N_KEY_U32); \ - else if (op == SET) \ - clib_pipeline_run_4_stage \ - (1, \ - vm, \ - vhash_main_gather_keys_mod_stage_##N_KEY_U32, \ - vhash_main_hash_mix_mod_stage_##N_KEY_U32, \ - vhash_main_hash_finalize_mod_stage_##N_KEY_U32, \ - vhash_main_set_mod_stage_##N_KEY_U32); \ - else \ - clib_pipeline_run_4_stage \ - (1, \ - vm, \ - vhash_main_gather_keys_mod_stage_##N_KEY_U32, \ - vhash_main_hash_mix_mod_stage_##N_KEY_U32, \ - vhash_main_hash_finalize_mod_stage_##N_KEY_U32, \ - vhash_main_unset_mod_stage_##N_KEY_U32); \ - break; - - _(4); - _(5); - _(6); - -#undef _ - } - } -} - -void -vhash_main_get (vhash_main_t * vm) -{ - vhash_main_op (vm, GET); -} - -void -vhash_main_set (vhash_main_t * vm) -{ - vhash_main_op (vm, SET); -} - -void -vhash_main_unset (vhash_main_t * vm) -{ - vhash_main_op (vm, UNSET); -} - -u32 -vhash_resize_incremental (vhash_resize_t * vr, u32 vector_index, - u32 n_keys_this_call) -{ - vhash_t *old = vr->old; - vhash_main_t *vm = &vr->new; - vhash_t *new = vm->vhash; - uword i, j, n_key_u32; - - n_key_u32 = old->n_key_u32; - - if (vector_index == 0) - { - u32 hash_seeds[3]; - hash_seeds[0] = old->hash_seeds[0].as_u32[0]; - hash_seeds[1] = old->hash_seeds[1].as_u32[0]; - hash_seeds[2] = old->hash_seeds[2].as_u32[0]; - vhash_init (new, old->log2_n_keys + 1, n_key_u32, hash_seeds); - } - - vec_reset_length (vm->keys); - vec_reset_length (vm->results); - - if (0 == (vector_index >> old->log2_n_keys)) - { - for (i = vector_index; 0 == (i >> (old->log2_n_keys - 2)); i++) - { - vhash_search_bucket_t *b = - vhash_get_search_bucket_with_index (old, 4 * i, n_key_u32); - u32 r, *k; - -#define _(I) \ - if ((r = b->result.as_u32[I]) != 0) \ - { \ - vec_add1 (vm->results, r - 1); \ - vec_add2 (vm->keys, k, n_key_u32); \ - for (j = 0; j < n_key_u32; j++) \ - k[j] = b->key[j].as_u32[I]; \ - } - - _(0); - _(1); - _(2); - _(3); - -#undef _ - - if (vec_len (vm->results) >= n_keys_this_call) - { - vhash_main_op (vm, SET); - return i; - } - } - } - - /* Add overflow buckets. */ - { - vhash_overflow_buckets_t *ob; - vhash_overflow_search_bucket_t *b; - - for (ob = old->overflow_buckets; - ob < old->overflow_buckets + ARRAY_LEN (old->overflow_buckets); ob++) - { - foreach_vhash_overflow_bucket (b, ob, old->n_key_u32) - { - u32 r, *k; - -#define _(I) \ - if ((r = b->result.as_u32[I]) != 0) \ - { \ - vec_add1 (vm->results, r - 1); \ - vec_add2 (vm->keys, k, n_key_u32); \ - for (j = 0; j < n_key_u32; j++) \ - k[j] = b->key[j].as_u32[I]; \ - } - - _(0); - _(1); - _(2); - _(3); - -#undef _ - } - } - } - - vhash_main_op (vm, SET); - - /* Let caller know we are done. */ - return ~0; -} - -void -vhash_resize (vhash_t * old, u32 log2_n_keys) -{ - static vhash_resize_t vr; - vhash_t new; - u32 i = 0; - - vr.old = old; - vr.new.vhash = &new; - - while (1) - { - i = vhash_resize_incremental (&vr, i, 1024); - if (i == ~0) - break; - } - - vhash_free (old); - *old = new; -} - -#endif /* CLIB_HAVE_VEC128 */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/vhash.h b/vppinfra/vppinfra/vhash.h deleted file mode 100644 index 5ab42292001..00000000000 --- a/vppinfra/vppinfra/vhash.h +++ /dev/null @@ -1,850 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2010 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_clib_vhash_h -#define included_clib_vhash_h - -#include <vppinfra/vector.h> - -#ifdef CLIB_HAVE_VEC128 - -#include <vppinfra/cache.h> -#include <vppinfra/hash.h> -#include <vppinfra/pipeline.h> - -/* Gathers 32 bits worth of key with given index. */ -typedef u32 (vhash_key_function_t) (void *state, u32 vector_index, - u32 key_word_index); -typedef u32x4 (vhash_4key_function_t) (void *state, u32 vector_index, - u32 key_word_index); -/* Sets/gets result of hash lookup. */ -typedef u32 (vhash_result_function_t) (void *state, u32 vector_index, - u32 result, u32 n_key_u32); -typedef u32x4 (vhash_4result_function_t) (void *state, u32 vector_index, - u32x4 results, u32 n_key_u32); - -typedef struct -{ - u32x4_union_t hashed_key[3]; -} vhash_hashed_key_t; - -/* Search buckets are really this structure. */ -typedef struct -{ - /* 4 results for this bucket. - Zero is used to mark empty results. This means user can't use the result ~0 - since user results differ from internal results stored in buckets by 1. - e.g. internal result = user result + 1. */ - u32x4_union_t result; - - /* n_key_u32s u32x4s of key data follow. */ - u32x4_union_t key[0]; -} vhash_search_bucket_t; - -typedef struct -{ - u32x4_union_t *search_buckets; - - /* Vector of bucket free indices. */ - u32 *free_indices; - - /* Number of entries in this overflow bucket. */ - u32 n_overflow; -} vhash_overflow_buckets_t; - -typedef struct -{ - /* 2^log2_n_keys keys grouped in groups of 4. - Each bucket contains 4 results plus 4 keys for a - total of (1 + n_key_u32) u32x4s. */ - u32x4_union_t *search_buckets; - - /* When a bucket of 4 results/keys are full we search - the overflow. hash_key is used to select which overflow - bucket. */ - vhash_overflow_buckets_t overflow_buckets[16]; - - /* Total count of occupied elements in hash table. */ - u32 n_elts; - - u32 log2_n_keys; - - /* Number of 32 bit words in a hash key. */ - u32 n_key_u32; - - u32x4_union_t bucket_mask; - - /* table[i] = min_log2 (first_set (~i)). */ - u8 find_first_zero_table[16]; - - /* Hash seeds for Jenkins hash. */ - u32x4_union_t hash_seeds[3]; - - /* Key work space is a vector of length - n_key_u32s << log2_n_key_word_len_u32x. */ - u32 log2_n_key_word_len_u32x; - - /* Work space to store keys between pipeline stages. */ - u32x4_union_t *key_work_space; - - /* Hash work space to store Jenkins hash values between - pipeline stages. */ - vhash_hashed_key_t *hash_work_space; -} vhash_t; - -always_inline vhash_overflow_buckets_t * -vhash_get_overflow_buckets (vhash_t * h, u32 key) -{ - u32 i = (((key & h->bucket_mask.as_u32[0]) >> 2) & 0xf); - ASSERT (i < ARRAY_LEN (h->overflow_buckets)); - return h->overflow_buckets + i; -} - -always_inline uword -vhash_is_non_empty_overflow_bucket (vhash_t * h, u32 key) -{ - u32 i = (((key & h->bucket_mask.as_u32[0]) >> 2) & 0xf); - ASSERT (i < ARRAY_LEN (h->overflow_buckets)); - return h->overflow_buckets[i].n_overflow > 0; -} - -always_inline void -vhash_free_overflow_buckets (vhash_overflow_buckets_t * obs) -{ - vec_free (obs->search_buckets); - vec_free (obs->free_indices); -} - -always_inline void -vhash_free (vhash_t * h) -{ - uword i; - for (i = 0; i < ARRAY_LEN (h->overflow_buckets); i++) - vhash_free_overflow_buckets (&h->overflow_buckets[i]); - vec_free (h->search_buckets); - vec_free (h->key_work_space); - vec_free (h->hash_work_space); -} - -always_inline void -vhash_set_key_word (vhash_t * h, u32 wi, u32 vi, u32 value) -{ - u32 i0 = (wi << h->log2_n_key_word_len_u32x) + (vi / 4); - u32 i1 = vi % 4; - vec_elt (h->key_work_space, i0).as_u32[i1] = value; -} - -always_inline void -vhash_set_key_word_u32x (vhash_t * h, u32 wi, u32 vi, u32x value) -{ - u32 i0 = (wi << h->log2_n_key_word_len_u32x) + (vi / 4); - vec_elt (h->key_work_space, i0).as_u32x4 = value; -} - -always_inline u32 -vhash_get_key_word (vhash_t * h, u32 wi, u32 vi) -{ - u32 i0 = (wi << h->log2_n_key_word_len_u32x) + (vi / 4); - u32 i1 = vi % 4; - return vec_elt (h->key_work_space, i0).as_u32[i1]; -} - -always_inline u32x -vhash_get_key_word_u32x (vhash_t * h, u32 wi, u32 vi) -{ - u32 i0 = (wi << h->log2_n_key_word_len_u32x) + vi; - return vec_elt (h->key_work_space, i0).as_u32x4; -} - -always_inline void -vhash_validate_sizes (vhash_t * h, u32 n_key_u32, u32 n_vectors) -{ - u32 n, l; - - n = max_pow2 (n_vectors) / 4; - n = clib_max (n, 8); - - h->log2_n_key_word_len_u32x = l = min_log2 (n); - vec_validate_aligned (h->key_work_space, (n_key_u32 << l) - 1, - CLIB_CACHE_LINE_BYTES); - vec_validate_aligned (h->hash_work_space, n - 1, CLIB_CACHE_LINE_BYTES); -} - -always_inline void -vhash_gather_key_stage (vhash_t * h, - u32 vector_index, - u32 n_vectors, - vhash_key_function_t key_function, - void *state, u32 n_key_u32s) -{ - u32 i, j, vi; - - /* Gather keys for 4 packets (for 128 bit vector length e.g. u32x4). */ - for (i = 0; i < n_vectors; i++) - { - vi = vector_index * 4 + i; - for (j = 0; j < n_key_u32s; j++) - vhash_set_key_word (h, j, vi, key_function (state, vi, j)); - } -} - -always_inline void -vhash_gather_4key_stage (vhash_t * h, - u32 vector_index, - vhash_4key_function_t key_function, - void *state, u32 n_key_u32s) -{ - u32 j, vi; - vi = vector_index * 4; - for (j = 0; j < n_key_u32s; j++) - vhash_set_key_word_u32x (h, j, vi, key_function (state, vi, j)); -} - -always_inline void -vhash_mix_stage (vhash_t * h, u32 vector_index, u32 n_key_u32s) -{ - i32 i, n_left; - u32x a, b, c; - - /* Only need to do this for keys longer than 12 bytes. */ - ASSERT (n_key_u32s > 3); - - a = h->hash_seeds[0].as_u32x4; - b = h->hash_seeds[1].as_u32x4; - c = h->hash_seeds[2].as_u32x4; - for (i = 0, n_left = n_key_u32s - 3; n_left > 0; n_left -= 3, i += 3) - { - a += - vhash_get_key_word_u32x (h, n_key_u32s - 1 - (i + 0), vector_index); - if (n_left > 1) - b += - vhash_get_key_word_u32x (h, n_key_u32s - 1 - (i + 1), vector_index); - if (n_left > 2) - c += - vhash_get_key_word_u32x (h, n_key_u32s - 1 - (i + 2), vector_index); - - hash_v3_mix_u32x (a, b, c); - } - - /* Save away a, b, c for later finalize. */ - { - vhash_hashed_key_t *hk = - vec_elt_at_index (h->hash_work_space, vector_index); - hk->hashed_key[0].as_u32x4 = a; - hk->hashed_key[1].as_u32x4 = b; - hk->hashed_key[2].as_u32x4 = c; - } -} - -always_inline vhash_search_bucket_t * -vhash_get_search_bucket_with_index (vhash_t * h, u32 i, u32 n_key_u32s) -{ - return ((vhash_search_bucket_t *) - vec_elt_at_index (h->search_buckets, - (i / 4) * - ((sizeof (vhash_search_bucket_t) / - sizeof (u32x4)) + n_key_u32s))); -} - -always_inline vhash_search_bucket_t * -vhash_get_search_bucket (vhash_t * h, u32 key_hash, u32 n_key_u32s) -{ - u32 i = key_hash & h->bucket_mask.as_u32[0]; - return vhash_get_search_bucket_with_index (h, i, n_key_u32s); -} - -always_inline u32x4 -vhash_get_4_search_bucket_byte_offsets (vhash_t * h, u32x4 key_hash, - u32 n_key_u32s) -{ - vhash_search_bucket_t *b; - u32 n_bytes_per_bucket = sizeof (b[0]) + n_key_u32s * sizeof (b->key[0]); - u32x4 r = key_hash & h->bucket_mask.as_u32x4; - - /* Multiply with shifts and adds to get bucket byte offset. */ -#define _(x) u32x4_ishift_left (r, (x) - 2) - if (n_bytes_per_bucket == (1 << 5)) - r = _(5); - else if (n_bytes_per_bucket == ((1 << 5) + (1 << 4))) - r = _(5) + _(4); - else if (n_bytes_per_bucket == (1 << 6)) - r = _(6); - else if (n_bytes_per_bucket == ((1 << 6) + (1 << 4))) - r = _(6) + _(4); - else if (n_bytes_per_bucket == ((1 << 6) + (1 << 5))) - r = _(6) + _(5); - else if (n_bytes_per_bucket == ((1 << 6) + (1 << 5) + (1 << 4))) - r = _(6) + _(5) + _(4); - else - ASSERT (0); -#undef _ - return r; -} - -always_inline void -vhash_finalize_stage (vhash_t * h, u32 vector_index, u32 n_key_u32s) -{ - i32 n_left; - u32x a, b, c; - vhash_hashed_key_t *hk = - vec_elt_at_index (h->hash_work_space, vector_index); - - if (n_key_u32s <= 3) - { - a = h->hash_seeds[0].as_u32x4; - b = h->hash_seeds[1].as_u32x4; - c = h->hash_seeds[2].as_u32x4; - n_left = n_key_u32s; - } - else - { - a = hk->hashed_key[0].as_u32x4; - b = hk->hashed_key[1].as_u32x4; - c = hk->hashed_key[2].as_u32x4; - n_left = 3; - } - - if (n_left > 0) - a += vhash_get_key_word_u32x (h, 0, vector_index); - if (n_left > 1) - b += vhash_get_key_word_u32x (h, 1, vector_index); - if (n_left > 2) - c += vhash_get_key_word_u32x (h, 2, vector_index); - - hash_v3_finalize_u32x (a, b, c); - - /* Only save away last 32 bits of hash code. */ - hk->hashed_key[2].as_u32x4 = c; - - /* Prefetch buckets. This costs a bit for small tables but saves - big for large ones. */ - { - vhash_search_bucket_t *b0, *b1, *b2, *b3; - u32x4_union_t kh; - - kh.as_u32x4 = vhash_get_4_search_bucket_byte_offsets (h, c, n_key_u32s); - hk->hashed_key[1].as_u32x4 = kh.as_u32x4; - - b0 = (void *) h->search_buckets + kh.as_u32[0]; - b1 = (void *) h->search_buckets + kh.as_u32[1]; - b2 = (void *) h->search_buckets + kh.as_u32[2]; - b3 = (void *) h->search_buckets + kh.as_u32[3]; - - CLIB_PREFETCH (b0, sizeof (b0[0]) + n_key_u32s * sizeof (b0->key[0]), - READ); - CLIB_PREFETCH (b1, sizeof (b1[0]) + n_key_u32s * sizeof (b1->key[0]), - READ); - CLIB_PREFETCH (b2, sizeof (b2[0]) + n_key_u32s * sizeof (b2->key[0]), - READ); - CLIB_PREFETCH (b3, sizeof (b3[0]) + n_key_u32s * sizeof (b3->key[0]), - READ); - } -} - -always_inline u32 -vhash_merge_results (u32x4 r) -{ - r = r | u32x4_word_shift_right (r, 2); - r = r | u32x4_word_shift_right (r, 1); - return u32x4_get0 (r); -} - -/* Bucket is full if none of its 4 results are 0. */ -always_inline u32 -vhash_search_bucket_is_full (u32x4 r) -{ - return u32x4_zero_byte_mask (r) == 0; -} - -always_inline u32 -vhash_non_empty_result_index (u32x4 x) -{ - u32 empty_mask = u32x4_zero_byte_mask (x); - ASSERT (empty_mask != 0xffff); - return min_log2 (0xffff & ~empty_mask) / 4; -} - -always_inline u32 -vhash_empty_result_index (u32x4 x) -{ - u32 empty_mask = u32x4_zero_byte_mask (x); - ASSERT (empty_mask != 0); - return min_log2 (0xffff & empty_mask) / 4; -} - -always_inline u32x4 -vhash_bucket_compare (vhash_t * h, - u32x4_union_t * bucket, u32 key_word_index, u32 vi) -{ - u32 k = vhash_get_key_word (h, key_word_index, vi); - u32x4 x = { k, k, k, k }; - return u32x4_is_equal (bucket[key_word_index].as_u32x4, x); -} - -#define vhash_bucket_compare_4(h,wi,vi,b0,b1,b2,b3,cmp0,cmp1,cmp2,cmp3) \ -do { \ - u32x4 _k4 = vhash_get_key_word_u32x ((h), (wi), (vi)); \ - u32x4 _k0 = u32x4_splat_word (_k4, 0); \ - u32x4 _k1 = u32x4_splat_word (_k4, 1); \ - u32x4 _k2 = u32x4_splat_word (_k4, 2); \ - u32x4 _k3 = u32x4_splat_word (_k4, 3); \ - \ - cmp0 = u32x4_is_equal (b0->key[wi].as_u32x4, _k0); \ - cmp1 = u32x4_is_equal (b1->key[wi].as_u32x4, _k1); \ - cmp2 = u32x4_is_equal (b2->key[wi].as_u32x4, _k2); \ - cmp3 = u32x4_is_equal (b3->key[wi].as_u32x4, _k3); \ -} while (0) - -u32 vhash_get_overflow (vhash_t * h, u32 key_hash, u32 vi, u32 n_key_u32s); - -always_inline void -vhash_get_stage (vhash_t * h, - u32 vector_index, - u32 n_vectors, - vhash_result_function_t result_function, - void *state, u32 n_key_u32s) -{ - u32 i, j; - vhash_hashed_key_t *hk = - vec_elt_at_index (h->hash_work_space, vector_index); - vhash_search_bucket_t *b; - - for (i = 0; i < n_vectors; i++) - { - u32 vi = vector_index * 4 + i; - u32 key_hash = hk->hashed_key[2].as_u32[i]; - u32 result; - u32x4 r, r0; - - b = vhash_get_search_bucket (h, key_hash, n_key_u32s); - - r = r0 = b->result.as_u32x4; - for (j = 0; j < n_key_u32s; j++) - r &= vhash_bucket_compare (h, &b->key[0], j, vi); - - /* At this point only one of 4 results should be non-zero. - So we can or all 4 together and get the valid result (if there is one). */ - result = vhash_merge_results (r); - - if (!result && vhash_search_bucket_is_full (r0)) - result = vhash_get_overflow (h, key_hash, vi, n_key_u32s); - - result_function (state, vi, result - 1, n_key_u32s); - } -} - -always_inline void -vhash_get_4_stage (vhash_t * h, - u32 vector_index, - vhash_4result_function_t result_function, - void *state, u32 n_key_u32s) -{ - u32 i, vi; - vhash_hashed_key_t *hk = - vec_elt_at_index (h->hash_work_space, vector_index); - vhash_search_bucket_t *b0, *b1, *b2, *b3; - u32x4 r0, r1, r2, r3, r0_before, r1_before, r2_before, r3_before; - u32x4_union_t kh; - - kh.as_u32x4 = hk->hashed_key[1].as_u32x4; - - b0 = (void *) h->search_buckets + kh.as_u32[0]; - b1 = (void *) h->search_buckets + kh.as_u32[1]; - b2 = (void *) h->search_buckets + kh.as_u32[2]; - b3 = (void *) h->search_buckets + kh.as_u32[3]; - - r0 = r0_before = b0->result.as_u32x4; - r1 = r1_before = b1->result.as_u32x4; - r2 = r2_before = b2->result.as_u32x4; - r3 = r3_before = b3->result.as_u32x4; - - vi = vector_index * 4; - - for (i = 0; i < n_key_u32s; i++) - { - u32x4 c0, c1, c2, c3; - vhash_bucket_compare_4 (h, i, vector_index, - b0, b1, b2, b3, c0, c1, c2, c3); - r0 &= c0; - r1 &= c1; - r2 &= c2; - r3 &= c3; - } - - u32x4_transpose (r0, r1, r2, r3); - - /* Gather together 4 results. */ - { - u32x4_union_t r; - u32x4 ones = { 1, 1, 1, 1 }; - u32 not_found_mask; - - r.as_u32x4 = r0 | r1 | r2 | r3; - not_found_mask = u32x4_zero_byte_mask (r.as_u32x4); - not_found_mask &= ((vhash_search_bucket_is_full (r0_before) << (4 * 0)) - | (vhash_search_bucket_is_full (r1_before) << (4 * 1)) - | (vhash_search_bucket_is_full (r2_before) << (4 * 2)) - | (vhash_search_bucket_is_full (r3_before) << - (4 * 3))); - if (not_found_mask) - { - u32x4_union_t key_hash; - - key_hash.as_u32x4 = - hk->hashed_key[2].as_u32x4 & h->bucket_mask.as_u32x4; - - /* Slow path: one of the buckets may have been full and we need to search overflow. */ - if (not_found_mask & (1 << (4 * 0))) - r.as_u32[0] = vhash_get_overflow (h, key_hash.as_u32[0], - vi + 0, n_key_u32s); - if (not_found_mask & (1 << (4 * 1))) - r.as_u32[1] = vhash_get_overflow (h, key_hash.as_u32[1], - vi + 1, n_key_u32s); - if (not_found_mask & (1 << (4 * 2))) - r.as_u32[2] = vhash_get_overflow (h, key_hash.as_u32[2], - vi + 2, n_key_u32s); - if (not_found_mask & (1 << (4 * 3))) - r.as_u32[3] = vhash_get_overflow (h, key_hash.as_u32[3], - vi + 3, n_key_u32s); - } - - result_function (state, vi, r.as_u32x4 - ones, n_key_u32s); - } -} - -u32 -vhash_set_overflow (vhash_t * h, - u32 key_hash, u32 vi, u32 new_result, u32 n_key_u32s); - -always_inline void -vhash_set_stage (vhash_t * h, - u32 vector_index, - u32 n_vectors, - vhash_result_function_t result_function, - void *state, u32 n_key_u32s) -{ - u32 i, j, n_new_elts = 0; - vhash_hashed_key_t *hk = - vec_elt_at_index (h->hash_work_space, vector_index); - vhash_search_bucket_t *b; - - for (i = 0; i < n_vectors; i++) - { - u32 vi = vector_index * 4 + i; - u32 key_hash = hk->hashed_key[2].as_u32[i]; - u32 old_result, new_result; - u32 i_set; - u32x4 r, r0, cmp; - - b = vhash_get_search_bucket (h, key_hash, n_key_u32s); - - cmp = vhash_bucket_compare (h, &b->key[0], 0, vi); - for (j = 1; j < n_key_u32s; j++) - cmp &= vhash_bucket_compare (h, &b->key[0], j, vi); - - r0 = b->result.as_u32x4; - r = r0 & cmp; - - /* At this point only one of 4 results should be non-zero. - So we can or all 4 together and get the valid result (if there is one). */ - old_result = vhash_merge_results (r); - - if (!old_result && vhash_search_bucket_is_full (r0)) - old_result = vhash_get_overflow (h, key_hash, vi, n_key_u32s); - - /* Get new result; possibly do something with old result. */ - new_result = result_function (state, vi, old_result - 1, n_key_u32s); - - /* User cannot use ~0 as a hash result since a result of 0 is - used to mark unused bucket entries. */ - ASSERT (new_result + 1 != 0); - new_result += 1; - - /* Set over-writes existing result. */ - if (old_result) - { - i_set = vhash_non_empty_result_index (r); - b->result.as_u32[i_set] = new_result; - } - else - { - /* Set allocates new result. */ - u32 valid_mask; - - valid_mask = (((b->result.as_u32[0] != 0) << 0) - | ((b->result.as_u32[1] != 0) << 1) - | ((b->result.as_u32[2] != 0) << 2) - | ((b->result.as_u32[3] != 0) << 3)); - - /* Rotate 4 bit valid mask so that key_hash corresponds to bit 0. */ - i_set = key_hash & 3; - valid_mask = - ((valid_mask >> i_set) | (valid_mask << (4 - i_set))) & 0xf; - - /* Insert into first empty position in bucket after key_hash. */ - i_set = (i_set + h->find_first_zero_table[valid_mask]) & 3; - - if (valid_mask != 0xf) - { - n_new_elts += 1; - - b->result.as_u32[i_set] = new_result; - - /* Insert new key into search bucket. */ - for (j = 0; j < n_key_u32s; j++) - b->key[j].as_u32[i_set] = vhash_get_key_word (h, j, vi); - } - else - vhash_set_overflow (h, key_hash, vi, new_result, n_key_u32s); - } - } - - h->n_elts += n_new_elts; -} - -u32 vhash_unset_overflow (vhash_t * h, u32 key_hash, u32 vi, u32 n_key_u32s); - -void -vhash_unset_refill_from_overflow (vhash_t * h, - vhash_search_bucket_t * b, - u32 key_hash, u32 n_key_u32s); - -/* Note: Eliot tried doing 4 unsets at once and could not get a speed up - and abandoned vhash_unset_4_stage. */ -always_inline void -vhash_unset_stage (vhash_t * h, - u32 vector_index, - u32 n_vectors, - vhash_result_function_t result_function, - void *state, u32 n_key_u32s) -{ - u32 i, j, n_elts_unset = 0; - vhash_hashed_key_t *hk = - vec_elt_at_index (h->hash_work_space, vector_index); - vhash_search_bucket_t *b; - - for (i = 0; i < n_vectors; i++) - { - u32 vi = vector_index * 4 + i; - u32 key_hash = hk->hashed_key[2].as_u32[i]; - u32 old_result; - u32x4 cmp, r0; - - b = vhash_get_search_bucket (h, key_hash, n_key_u32s); - - cmp = vhash_bucket_compare (h, &b->key[0], 0, vi); - for (j = 1; j < n_key_u32s; j++) - cmp &= vhash_bucket_compare (h, &b->key[0], j, vi); - - r0 = b->result.as_u32x4; - - /* At this point cmp is all ones where key matches and zero otherwise. - So, this will invalidate results for matching key and do nothing otherwise. */ - b->result.as_u32x4 = r0 & ~cmp; - - old_result = vhash_merge_results (r0 & cmp); - - n_elts_unset += old_result != 0; - - if (vhash_search_bucket_is_full (r0)) - { - if (old_result) - vhash_unset_refill_from_overflow (h, b, key_hash, n_key_u32s); - else - old_result = vhash_unset_overflow (h, key_hash, vi, n_key_u32s); - } - - result_function (state, vi, old_result - 1, n_key_u32s); - } - ASSERT (h->n_elts >= n_elts_unset); - h->n_elts -= n_elts_unset; -} - -void vhash_init (vhash_t * h, u32 log2_n_keys, u32 n_key_u32, - u32 * hash_seeds); - -void vhash_resize (vhash_t * old, u32 log2_n_keys); - -typedef struct -{ - vhash_t *vhash; - - union - { - struct - { - u32 *keys; - u32 *results; - }; - - /* Vector layout for get keys. */ - struct - { - u32x4_union_t *get_keys; - u32x4_union_t *get_results; - }; - }; - - u32 n_vectors_div_4; - u32 n_vectors_mod_4; - - u32 n_key_u32; - - u32 n_keys; -} vhash_main_t; - -always_inline u32 -vhash_get_alloc_keys (vhash_main_t * vm, u32 n_keys, u32 n_key_u32) -{ - u32 i, n; - - i = vm->n_keys; - vm->n_keys = i + n_keys; - - n = (round_pow2 (vm->n_keys, 4) / 4) * n_key_u32; - - vec_validate_aligned (vm->get_keys, n - 1, sizeof (vm->get_keys[0])); - vec_validate_aligned (vm->get_results, n - 1, sizeof (vm->get_results[0])); - - return i; -} - -always_inline void -vhash_get_set_key_word (vhash_main_t * vm, u32 vi, u32 wi, u32 n_key_u32, - u32 value) -{ - u32x4_union_t *k = vec_elt_at_index (vm->get_keys, (vi / 4) * n_key_u32); - ASSERT (wi < n_key_u32); - k[wi].as_u32[vi % 4] = value; -} - -always_inline u32 -vhash_get_fetch_result (vhash_main_t * vm, u32 vi) -{ - u32x4_union_t *r = vec_elt_at_index (vm->get_results, vi / 4); - return r->as_u32[vi % 4]; -} - -void vhash_main_get (vhash_main_t * vm); - -always_inline u32 -vhash_set_alloc_keys (vhash_main_t * vm, u32 n_keys, u32 n_key_u32) -{ - u32 i; - - i = vm->n_keys; - vm->n_keys = i + n_keys; - - vec_resize (vm->keys, n_keys * n_key_u32); - vec_resize (vm->results, n_keys); - - return i; -} - -always_inline void -vhash_set_set_key_word (vhash_main_t * vm, u32 vi, u32 wi, u32 n_key_u32, - u32 value) -{ - u32 *k = vec_elt_at_index (vm->keys, vi * n_key_u32); - ASSERT (wi < n_key_u32); - k[wi] = value; -} - -always_inline void -vhash_set_set_result (vhash_main_t * vm, u32 vi, u32 result) -{ - u32 *r = vec_elt_at_index (vm->results, vi); - r[0] = result; -} - -always_inline u32 -vhash_set_fetch_old_result (vhash_main_t * vm, u32 vi) -{ - u32 *r = vec_elt_at_index (vm->results, vi); - return r[0]; -} - -void vhash_main_set (vhash_main_t * vm); - -always_inline u32 -vhash_unset_alloc_keys (vhash_main_t * vm, u32 n_keys, u32 n_key_u32) -{ - return vhash_set_alloc_keys (vm, n_keys, n_key_u32); -} - -always_inline void -vhash_unset_set_key_word (vhash_main_t * vm, u32 vi, u32 wi, u32 n_key_u32, - u32 value) -{ - vhash_set_set_key_word (vm, vi, wi, n_key_u32, value); -} - -always_inline void -vhash_unset_set_result (vhash_main_t * vm, u32 vi, u32 result) -{ - vhash_set_set_result (vm, vi, result); -} - -always_inline u32 -vhash_unset_fetch_old_result (vhash_main_t * vm, u32 vi) -{ - return vhash_set_fetch_old_result (vm, vi); -} - -void vhash_main_unset (vhash_main_t * vm); - -typedef struct -{ - vhash_main_t new; - - vhash_t *old; -} vhash_resize_t; - -u32 vhash_resize_incremental (vhash_resize_t * vr, u32 vector_index, - u32 n_vectors); - -#endif /* CLIB_HAVE_VEC128 */ - -#endif /* included_clib_vhash_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/vm_linux_kernel.h b/vppinfra/vppinfra/vm_linux_kernel.h deleted file mode 100644 index fd9e6148e0a..00000000000 --- a/vppinfra/vppinfra/vm_linux_kernel.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_vm_linux_kernel_h -#define included_vm_linux_kernel_h - -#include <linux/vmalloc.h> -#include <linux/gfp.h> /* for GFP_* */ -#include <asm/pgtable.h> /* for PAGE_KERNEL */ - -/* Allocate virtual address space. */ -always_inline void * -clib_mem_vm_alloc (uword size) -{ - return vmalloc (size); -} - -always_inline void -clib_mem_vm_free (void *addr, uword size) -{ - vfree (addr); -} - -always_inline void * -clib_mem_vm_unmap (void *addr, uword size) -{ - return 0; -} - -always_inline void * -clib_mem_vm_map (void *addr, uword size) -{ - return addr; -} - -#endif /* included_vm_linux_kernel_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/vm_standalone.h b/vppinfra/vppinfra/vm_standalone.h deleted file mode 100644 index 2cd431bc46c..00000000000 --- a/vppinfra/vppinfra/vm_standalone.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_vm_standalone_h -#define included_vm_standalone_h - -/* Stubs for standalone "system" which has no VM support. */ - -always_inline void * -clib_mem_vm_alloc (uword size) -{ - return 0; -} - -always_inline void -clib_mem_vm_free (void *addr, uword size) -{ -} - -always_inline void * -clib_mem_vm_unmap (void *addr, uword size) -{ - return 0; -} - -always_inline void * -clib_mem_vm_map (void *addr, uword size) -{ - return addr; -} - -#endif /* included_vm_standalone_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/vm_unix.h b/vppinfra/vppinfra/vm_unix.h deleted file mode 100644 index 07e865166e0..00000000000 --- a/vppinfra/vppinfra/vm_unix.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_vm_unix_h -#define included_vm_unix_h - -#include <unistd.h> -#include <sys/mman.h> - -/* Allocate virtual address space. */ -always_inline void * -clib_mem_vm_alloc (uword size) -{ - void *mmap_addr; - uword flags = MAP_PRIVATE; - -#ifdef MAP_ANONYMOUS - flags |= MAP_ANONYMOUS; -#endif - - mmap_addr = mmap (0, size, PROT_READ | PROT_WRITE, flags, -1, 0); - if (mmap_addr == (void *) -1) - mmap_addr = 0; - - return mmap_addr; -} - -always_inline void -clib_mem_vm_free (void *addr, uword size) -{ - munmap (addr, size); -} - -always_inline void * -clib_mem_vm_unmap (void *addr, uword size) -{ - void *mmap_addr; - uword flags = MAP_PRIVATE | MAP_FIXED; - - /* To unmap we "map" with no protection. If we actually called - munmap then other callers could steal the address space. By - changing to PROT_NONE the kernel can free up the pages which is - really what we want "unmap" to mean. */ - mmap_addr = mmap (addr, size, PROT_NONE, flags, -1, 0); - if (mmap_addr == (void *) -1) - mmap_addr = 0; - - return mmap_addr; -} - -always_inline void * -clib_mem_vm_map (void *addr, uword size) -{ - void *mmap_addr; - uword flags = MAP_PRIVATE | MAP_FIXED; - - mmap_addr = mmap (addr, size, (PROT_READ | PROT_WRITE), flags, -1, 0); - if (mmap_addr == (void *) -1) - mmap_addr = 0; - - return mmap_addr; -} - -#endif /* included_vm_unix_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/xxhash.h b/vppinfra/vppinfra/xxhash.h deleted file mode 100644 index ea1e21bf144..00000000000 --- a/vppinfra/vppinfra/xxhash.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Original license for the code used to construct - clib_xxhash(...). - - xxHash - Fast Hash algorithm - Copyright (C) 2012-2014, Yann Collet. - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - 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. - - 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. -*/ - -#ifndef __included_xxhash_h__ -#define __included_xxhash_h__ - -#define PRIME64_1 11400714785074694791ULL -#define PRIME64_2 14029467366897019727ULL -#define PRIME64_3 1609587929392839161ULL -#define PRIME64_4 9650029242287828579ULL -#define PRIME64_5 2870177450012600261ULL -#define XXH_rotl64(x,r) ((x << r) | (x >> (64 - r))) - -static inline u64 -clib_xxhash (u64 key) -{ - u64 k1, h64; - - k1 = key; - h64 = 0x9e3779b97f4a7c13LL + PRIME64_5 + 8; - k1 *= PRIME64_2; - k1 = XXH_rotl64 (k1, 31); - k1 *= PRIME64_1; - h64 ^= k1; - h64 = XXH_rotl64 (h64, 27) * PRIME64_1 + PRIME64_4; - - h64 ^= h64 >> 33; - h64 *= PRIME64_2; - h64 ^= h64 >> 29; - h64 *= PRIME64_3; - h64 ^= h64 >> 32; - return h64; -} - -#endif /* __included_xxhash_h__ */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/xy.h b/vppinfra/vppinfra/xy.h deleted file mode 100644 index fb562161a62..00000000000 --- a/vppinfra/vppinfra/xy.h +++ /dev/null @@ -1,56 +0,0 @@ -/* (X,Y) coordinates. */ - -/* - Copyright (c) 2008 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_clib_xy_h -#define included_clib_xy_h - -#include <vppinfra/types.h> - -/* Basic definitions: coordinates and points. */ -typedef double xy_float_t; -typedef __complex__ double xy_t; -typedef __complex__ int ixy_t; - -typedef __complex__ char i8xy_t; -typedef __complex__ short i16xy_t; -typedef __complex__ int i32xy_t; - -/* X/Y components of a point: can be used as either rvalue/lvalue. */ -#define xy_x(x) __real__ (x) -#define xy_y(x) __imag__ (x) - -/* Unit vectors in x/y directions. */ -#define xy_x_unit_vector (1) -#define xy_y_unit_vector (1I) - -#endif /* included_clib_xy_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/zvec.c b/vppinfra/vppinfra/zvec.c deleted file mode 100644 index d062e5f7db1..00000000000 --- a/vppinfra/vppinfra/zvec.c +++ /dev/null @@ -1,442 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001, 2002, 2003, 2005 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include <vppinfra/bitmap.h> -#include <vppinfra/bitops.h> /* for next_with_same_number_of_set_bits */ -#include <vppinfra/error.h> /* for ASSERT */ -#include <vppinfra/mem.h> -#include <vppinfra/os.h> /* for os_panic */ -#include <vppinfra/vec.h> -#include <vppinfra/zvec.h> - -/* Consider coding as bitmap, coding = 2^c_0 + 2^c_1 + ... + 2^c_n - With c_0 < c_1 < ... < c_n. coding == 0 represents c_n = BITS (uword). - - Unsigned integers i = 0 ... are represented as follows: - - 0 <= i < 2^c_0 (i << 1) | (1 << 0) binary: i 1 - 2^c_0 <= i < 2^c_0 + 2^c_1 (i << 2) | (1 << 1) binary: i 1 0 - ... binary: i 0 ... 0 - - Smaller numbers use less bits. Coding is chosen so that encoding - of given histogram of typical values gives smallest number of bits. - The number and position of coding bits c_i are used to best fit the - histogram of typical values. -*/ - -/* Decode given compressed data. Return number of compressed data - bits used. */ -uword -zvec_decode (uword coding, uword zdata, uword * n_zdata_bits) -{ - uword c, d, result, n_bits; - uword explicit_end, implicit_end; - - result = 0; - n_bits = 0; - while (1) - { - c = first_set (coding); - implicit_end = c == coding; - explicit_end = (zdata & 1) & ~implicit_end; - d = (zdata >> explicit_end) & (c - 1); - if (explicit_end | implicit_end) - { - result += d; - n_bits += min_log2 (c) + explicit_end; - break; - } - n_bits += 1; - result += c; - coding ^= c; - zdata >>= 1; - } - - if (coding == 0) - n_bits = BITS (uword); - - *n_zdata_bits = n_bits; - return result; -} - -uword -zvec_encode (uword coding, uword data, uword * n_result_bits) -{ - uword c, shift, result; - uword explicit_end, implicit_end; - - /* Data must be in range. Note special coding == 0 - would break for data - 1 <= coding. */ - ASSERT (data <= coding - 1); - - shift = 0; - while (1) - { - c = first_set (coding); - implicit_end = c == coding; - explicit_end = ((data & (c - 1)) == data); - if (explicit_end | implicit_end) - { - uword t = explicit_end & ~implicit_end; - result = ((data << t) | t) << shift; - *n_result_bits = - /* data bits */ (c == 0 ? BITS (uword) : min_log2 (c)) - /* shift bits */ + shift + t; - return result; - } - data -= c; - coding ^= c; - shift++; - } - - /* Never reached. */ - ASSERT (0); - return ~0; -} - -always_inline uword -get_data (void *data, uword data_bytes, uword is_signed) -{ - if (data_bytes == 1) - return is_signed ? zvec_signed_to_unsigned (*(i8 *) data) : *(u8 *) data; - else if (data_bytes == 2) - return is_signed ? zvec_signed_to_unsigned (*(i16 *) data) : *(u16 *) - data; - else if (data_bytes == 4) - return is_signed ? zvec_signed_to_unsigned (*(i32 *) data) : *(u32 *) - data; - else if (data_bytes == 8) - return is_signed ? zvec_signed_to_unsigned (*(i64 *) data) : *(u64 *) - data; - else - { - os_panic (); - return ~0; - } -} - -always_inline void -put_data (void *data, uword data_bytes, uword is_signed, uword x) -{ - if (data_bytes == 1) - { - if (is_signed) - *(i8 *) data = zvec_unsigned_to_signed (x); - else - *(u8 *) data = x; - } - else if (data_bytes == 2) - { - if (is_signed) - *(i16 *) data = zvec_unsigned_to_signed (x); - else - *(u16 *) data = x; - } - else if (data_bytes == 4) - { - if (is_signed) - *(i32 *) data = zvec_unsigned_to_signed (x); - else - *(u32 *) data = x; - } - else if (data_bytes == 8) - { - if (is_signed) - *(i64 *) data = zvec_unsigned_to_signed (x); - else - *(u64 *) data = x; - } - else - { - os_panic (); - } -} - -always_inline uword * -zvec_encode_inline (uword * zvec, - uword * zvec_n_bits, - uword coding, - void *data, - uword data_stride, - uword n_data, uword data_bytes, uword is_signed) -{ - uword i; - - i = *zvec_n_bits; - while (n_data >= 1) - { - uword d0, z0, l0; - - d0 = get_data (data + 0 * data_stride, data_bytes, is_signed); - data += 1 * data_stride; - n_data -= 1; - - z0 = zvec_encode (coding, d0, &l0); - zvec = clib_bitmap_set_multiple (zvec, i, z0, l0); - i += l0; - } - - *zvec_n_bits = i; - return zvec; -} - -#define _(TYPE,IS_SIGNED) \ - uword * zvec_encode_##TYPE (uword * zvec, \ - uword * zvec_n_bits, \ - uword coding, \ - void * data, \ - uword data_stride, \ - uword n_data) \ - { \ - return zvec_encode_inline (zvec, zvec_n_bits, \ - coding, \ - data, data_stride, n_data, \ - /* data_bytes */ sizeof (TYPE), \ - /* is_signed */ IS_SIGNED); \ - } - -_(u8, /* is_signed */ 0); -_(u16, /* is_signed */ 0); -_(u32, /* is_signed */ 0); -_(u64, /* is_signed */ 0); -_(i8, /* is_signed */ 1); -_(i16, /* is_signed */ 1); -_(i32, /* is_signed */ 1); -_(i64, /* is_signed */ 1); - -#undef _ - -always_inline uword -coding_max_n_bits (uword coding) -{ - uword n_bits; - (void) zvec_decode (coding, 0, &n_bits); - return n_bits; -} - -always_inline void -zvec_decode_inline (uword * zvec, - uword * zvec_n_bits, - uword coding, - void *data, - uword data_stride, - uword n_data, uword data_bytes, uword is_signed) -{ - uword i, n_max; - - i = *zvec_n_bits; - n_max = coding_max_n_bits (coding); - while (n_data >= 1) - { - uword d0, z0, l0; - - z0 = clib_bitmap_get_multiple (zvec, i, n_max); - d0 = zvec_decode (coding, z0, &l0); - i += l0; - put_data (data + 0 * data_stride, data_bytes, is_signed, d0); - data += 1 * data_stride; - n_data -= 1; - } - *zvec_n_bits = i; -} - -#define _(TYPE,IS_SIGNED) \ - void zvec_decode_##TYPE (uword * zvec, \ - uword * zvec_n_bits, \ - uword coding, \ - void * data, \ - uword data_stride, \ - uword n_data) \ - { \ - return zvec_decode_inline (zvec, zvec_n_bits, \ - coding, \ - data, data_stride, n_data, \ - /* data_bytes */ sizeof (TYPE), \ - /* is_signed */ IS_SIGNED); \ - } - -_(u8, /* is_signed */ 0); -_(u16, /* is_signed */ 0); -_(u32, /* is_signed */ 0); -_(u64, /* is_signed */ 0); -_(i8, /* is_signed */ 1); -_(i16, /* is_signed */ 1); -_(i32, /* is_signed */ 1); -_(i64, /* is_signed */ 1); - -#undef _ - -/* Compute number of bits needed to encode given histogram. */ -static uword -zvec_coding_bits (uword coding, uword * histogram_counts, uword min_bits) -{ - uword n_type_bits, n_bits; - uword this_count, last_count, max_count_index; - uword i, b, l; - - n_bits = 0; - n_type_bits = 1; - last_count = 0; - max_count_index = vec_len (histogram_counts) - 1; - - /* Coding is not large enough to encode given data. */ - if (coding <= max_count_index) - return ~0; - - i = 0; - while (coding != 0) - { - b = first_set (coding); - l = min_log2 (b); - i += b; - - this_count = - histogram_counts[i > max_count_index ? max_count_index : i - 1]; - - /* No more data to encode? */ - if (this_count == last_count) - break; - - /* Last coding is i 0 ... 0 so we don't need an extra type bit. */ - if (coding == b) - n_type_bits--; - - n_bits += (this_count - last_count) * (n_type_bits + l); - - /* This coding cannot be minimal: so return. */ - if (n_bits >= min_bits) - return ~0; - - last_count = this_count; - coding ^= b; - n_type_bits++; - } - - return n_bits; -} - -uword -_zvec_coding_from_histogram (void *histogram, - uword histogram_len, - uword histogram_elt_count_offset, - uword histogram_elt_bytes, - uword max_value_to_encode, - zvec_coding_info_t * coding_return) -{ - uword coding, min_coding; - uword min_coding_bits, coding_bits; - uword i, n_bits_set, total_count; - uword *counts; - zvec_histogram_count_t *h_count = histogram + histogram_elt_count_offset; - - if (histogram_len < 1) - { - coding_return->coding = 0; - coding_return->min_coding_bits = 0; - coding_return->n_data = 0; - coding_return->n_codes = 0; - coding_return->ave_coding_bits = 0; - return 0; - } - - total_count = 0; - counts = vec_new (uword, histogram_len); - for (i = 0; i < histogram_len; i++) - { - zvec_histogram_count_t this_count = h_count[0]; - total_count += this_count; - counts[i] = total_count; - h_count = - (zvec_histogram_count_t *) ((void *) h_count + histogram_elt_bytes); - } - - min_coding = 0; - min_coding_bits = ~0; - - { - uword base_coding = - max_value_to_encode != - ~0 ? (1 + max_value_to_encode) : vec_len (counts); - uword max_coding = max_pow2 (2 * base_coding); - - for (n_bits_set = 1; n_bits_set <= 8; n_bits_set++) - { - for (coding = pow2_mask (n_bits_set); - coding < max_coding; - coding = next_with_same_number_of_set_bits (coding)) - { - coding_bits = zvec_coding_bits (coding, counts, min_coding_bits); - if (coding_bits >= min_coding_bits) - continue; - min_coding_bits = coding_bits; - min_coding = coding; - } - } - } - - if (coding_return) - { - coding_return->coding = min_coding; - coding_return->min_coding_bits = min_coding_bits; - coding_return->n_data = total_count; - coding_return->n_codes = vec_len (counts); - coding_return->ave_coding_bits = - (f64) min_coding_bits / (f64) total_count; - } - - vec_free (counts); - - return min_coding; -} - -u8 * -format_zvec_coding (u8 * s, va_list * args) -{ - zvec_coding_info_t *c = va_arg (*args, zvec_coding_info_t *); - return format (s, - "zvec coding 0x%x, %d elts, %d codes, %d bits total, %.4f ave bits/code", - c->coding, c->n_data, c->n_codes, c->min_coding_bits, - c->ave_coding_bits); -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/vppinfra/vppinfra/zvec.h b/vppinfra/vppinfra/zvec.h deleted file mode 100644 index 7d35a3fe41f..00000000000 --- a/vppinfra/vppinfra/zvec.h +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef included_zvec_h -#define included_zvec_h - -#include <vppinfra/clib.h> -#include <vppinfra/error.h> /* for ASSERT */ -#include <vppinfra/format.h> - -/* zvec: compressed vectors. - - Data is entropy coded with 32 bit "codings". - - Consider coding as bitmap, coding = 2^c_0 + 2^c_1 + ... + 2^c_n - With c_0 < c_1 < ... < c_n. coding == 0 represents c_n = BITS (uword). - - Unsigned integers i = 0 ... are represented as follows: - - 0 <= i < 2^c_0 (i << 1) | (1 << 0) binary: i 1 - 2^c_0 <= i < 2^c_0 + 2^c_1 (i << 2) | (1 << 1) binary: i 1 0 - ... binary: i 0 ... 0 - - Smaller numbers use less bits. Coding is chosen so that encoding - of given histogram of typical values gives smallest number of bits. - The number and position of coding bits c_i are used to best fit the - histogram of typical values. -*/ - -typedef struct -{ - /* Smallest coding for given histogram of typical data. */ - u32 coding; - - /* Number of data in histogram. */ - u32 n_data; - - /* Number of codes (unique values) in histogram. */ - u32 n_codes; - - /* Number of bits in smallest coding of data. */ - u32 min_coding_bits; - - /* Average number of bits per code. */ - f64 ave_coding_bits; -} zvec_coding_info_t; - -/* Encode/decode data. */ -uword zvec_encode (uword coding, uword data, uword * n_result_bits); -uword zvec_decode (uword coding, uword zdata, uword * n_zdata_bits); - -format_function_t format_zvec_coding; - -typedef u32 zvec_histogram_count_t; - -#define zvec_coding_from_histogram(h,count_field,len,max_value_to_encode,zc) \ - _zvec_coding_from_histogram ((h), (len), \ - STRUCT_OFFSET_OF_VAR (h, count_field), \ - sizeof (h[0]), \ - max_value_to_encode, \ - (zc)) - -uword -_zvec_coding_from_histogram (void *_histogram, - uword histogram_len, - uword histogram_elt_count_offset, - uword histogram_elt_bytes, - uword max_value_to_encode, - zvec_coding_info_t * coding_info_return); - -#define _(TYPE,IS_SIGNED) \ - uword * zvec_encode_##TYPE (uword * zvec, uword * zvec_n_bits, uword coding, \ - void * data, uword data_stride, uword n_data); - -_(u8, /* is_signed */ 0); -_(u16, /* is_signed */ 0); -_(u32, /* is_signed */ 0); -_(u64, /* is_signed */ 0); -_(i8, /* is_signed */ 1); -_(i16, /* is_signed */ 1); -_(i32, /* is_signed */ 1); -_(i64, /* is_signed */ 1); - -#undef _ - -#define _(TYPE,IS_SIGNED) \ - void zvec_decode_##TYPE (uword * zvec, \ - uword * zvec_n_bits, \ - uword coding, \ - void * data, \ - uword data_stride, \ - uword n_data) - -_(u8, /* is_signed */ 0); -_(u16, /* is_signed */ 0); -_(u32, /* is_signed */ 0); -_(u64, /* is_signed */ 0); -_(i8, /* is_signed */ 1); -_(i16, /* is_signed */ 1); -_(i32, /* is_signed */ 1); -_(i64, /* is_signed */ 1); - -#undef _ - -/* Signed <=> unsigned conversion. - -1, -2, -3, ... => 1, 3, 5, ... odds - 0, +1, +2, +3, ... => 0, 2, 4, 6, ... evens */ -always_inline uword -zvec_signed_to_unsigned (word s) -{ - uword a = s < 0; - s = 2 * s + a; - return a ? -s : s; -} - -always_inline word -zvec_unsigned_to_signed (uword u) -{ - uword a = u & 1; - u >>= 1; - return a ? -u : u; -} - -#endif /* included_zvec_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ |