Compare commits
	
		
			1 Commits
		
	
	
		
			android-6.
			...
			lollipop-m
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					023c327cbb | 
							
								
								
									
										12
									
								
								ABI-bugs.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								ABI-bugs.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
KNOWN ABI BUGS
 | 
			
		||||
--------------
 | 
			
		||||
 | 
			
		||||
  time_t is 32-bit. http://b/5819737
 | 
			
		||||
 | 
			
		||||
  off_t is 32-bit. There is off64_t, but no _FILE_OFFSET_BITS support.
 | 
			
		||||
 | 
			
		||||
  sigset_t is too small on ARM and x86 (but correct on MIPS), so support
 | 
			
		||||
  for real-time signals is broken. http://b/5828899
 | 
			
		||||
 | 
			
		||||
  atexit(3) handlers registered by a shared library aren't called on
 | 
			
		||||
  dlclose(3); this only affects ARM. http://b/4998315
 | 
			
		||||
@@ -1,2 +0,0 @@
 | 
			
		||||
set noparent
 | 
			
		||||
filter=-build/header_guard,-runtime/int,-readability/function
 | 
			
		||||
@@ -4,52 +4,40 @@ Working on bionic
 | 
			
		||||
What are the big pieces of bionic?
 | 
			
		||||
----------------------------------
 | 
			
		||||
 | 
			
		||||
#### libc/ --- libc.so, libc.a
 | 
			
		||||
libc/ --- libc.so, libc.a
 | 
			
		||||
  The C library. Stuff like fopen(3) and kill(2).
 | 
			
		||||
libm/ --- libm.so, libm.a
 | 
			
		||||
  The math library. Traditionally Unix systems kept stuff like sin(3) and
 | 
			
		||||
  cos(3) in a separate library to save space in the days before shared
 | 
			
		||||
  libraries.
 | 
			
		||||
libdl/ --- libdl.so
 | 
			
		||||
  The dynamic linker interface library. This is actually just a bunch of
 | 
			
		||||
  stubs that the dynamic linker replaces with pointers to its own
 | 
			
		||||
  implementation at runtime. This is where stuff like dlopen(3) lives.
 | 
			
		||||
libstdc++/ --- libstdc++.so
 | 
			
		||||
  The C++ ABI support functions. The C++ compiler doesn't know how to
 | 
			
		||||
  implement thread-safe static initialization and the like, so it just calls
 | 
			
		||||
  functions that are supplied by the system. Stuff like __cxa_guard_acquire
 | 
			
		||||
  and __cxa_pure_virtual live here.
 | 
			
		||||
 | 
			
		||||
The C library. Stuff like `fopen(3)` and `kill(2)`.
 | 
			
		||||
linker/ --- /system/bin/linker and /system/bin/linker64
 | 
			
		||||
  The dynamic linker. When you run a dynamically-linked executable, its ELF
 | 
			
		||||
  file has a DT_INTERP entry that says "use the following program to start me".
 | 
			
		||||
  On Android, that's either linker or linker64 (depending on whether it's a
 | 
			
		||||
  32-bit or 64-bit executable). It's responsible for loading the ELF executable
 | 
			
		||||
  into memory and resolving references to symbols (so that when your code tries
 | 
			
		||||
  to jump to fopen(3), say, it lands in the right place).
 | 
			
		||||
 | 
			
		||||
#### libm/ --- libm.so, libm.a
 | 
			
		||||
 | 
			
		||||
The math library. Traditionally Unix systems kept stuff like `sin(3)` and
 | 
			
		||||
`cos(3)` in a separate library to save space in the days before shared
 | 
			
		||||
libraries.
 | 
			
		||||
 | 
			
		||||
#### libdl/ --- libdl.so
 | 
			
		||||
 | 
			
		||||
The dynamic linker interface library. This is actually just a bunch of stubs
 | 
			
		||||
that the dynamic linker replaces with pointers to its own implementation at
 | 
			
		||||
runtime. This is where stuff like `dlopen(3)` lives.
 | 
			
		||||
 | 
			
		||||
#### libstdc++/ --- libstdc++.so
 | 
			
		||||
 | 
			
		||||
The C++ ABI support functions. The C++ compiler doesn't know how to implement
 | 
			
		||||
thread-safe static initialization and the like, so it just calls functions that
 | 
			
		||||
are supplied by the system. Stuff like `__cxa_guard_acquire` and
 | 
			
		||||
`__cxa_pure_virtual` live here.
 | 
			
		||||
 | 
			
		||||
#### linker/ --- /system/bin/linker and /system/bin/linker64
 | 
			
		||||
 | 
			
		||||
The dynamic linker. When you run a dynamically-linked executable, its ELF file
 | 
			
		||||
has a `DT_INTERP` entry that says "use the following program to start me".  On
 | 
			
		||||
Android, that's either `linker` or `linker64` (depending on whether it's a
 | 
			
		||||
32-bit or 64-bit executable). It's responsible for loading the ELF executable
 | 
			
		||||
into memory and resolving references to symbols (so that when your code tries to
 | 
			
		||||
jump to `fopen(3)`, say, it lands in the right place).
 | 
			
		||||
 | 
			
		||||
#### tests/ --- unit tests
 | 
			
		||||
 | 
			
		||||
The `tests/` directory contains unit tests. Roughly arranged as one file per
 | 
			
		||||
publicly-exported header file.
 | 
			
		||||
 | 
			
		||||
#### benchmarks/ --- benchmarks
 | 
			
		||||
 | 
			
		||||
The `benchmarks/` directory contains benchmarks.
 | 
			
		||||
tests/ --- unit tests
 | 
			
		||||
  The tests/ directory contains unit tests. Roughly arranged as one file per
 | 
			
		||||
  publicly-exported header file.
 | 
			
		||||
benchmarks/ --- benchmarks
 | 
			
		||||
  The benchmarks/ directory contains benchmarks.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
What's in libc/?
 | 
			
		||||
----------------
 | 
			
		||||
 | 
			
		||||
<pre>
 | 
			
		||||
libc/
 | 
			
		||||
  arch-arm/
 | 
			
		||||
  arch-arm64/
 | 
			
		||||
@@ -133,7 +121,6 @@ libc/
 | 
			
		||||
  zoneinfo/
 | 
			
		||||
    # Android-format time zone data.
 | 
			
		||||
    # See 'Updating tzdata' later.
 | 
			
		||||
</pre>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Adding system calls
 | 
			
		||||
@@ -173,101 +160,3 @@ This is fully automated:
 | 
			
		||||
 | 
			
		||||
  1. Run update-tzdata.py.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Verifying changes
 | 
			
		||||
-----------------
 | 
			
		||||
 | 
			
		||||
If you make a change that is likely to have a wide effect on the tree (such as a
 | 
			
		||||
libc header change), you should run `make checkbuild`. A regular `make` will
 | 
			
		||||
_not_ build the entire tree; just the minimum number of projects that are
 | 
			
		||||
required for the device. Tests, additional developer tools, and various other
 | 
			
		||||
modules will not be built. Note that `make checkbuild` will not be complete
 | 
			
		||||
either, as `make tests` covers a few additional modules, but generally speaking
 | 
			
		||||
`make checkbuild` is enough.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Running the tests
 | 
			
		||||
-----------------
 | 
			
		||||
 | 
			
		||||
The tests are all built from the tests/ directory.
 | 
			
		||||
 | 
			
		||||
### Device tests
 | 
			
		||||
 | 
			
		||||
    $ mma
 | 
			
		||||
    $ adb sync
 | 
			
		||||
    $ adb shell /data/nativetest/bionic-unit-tests/bionic-unit-tests32
 | 
			
		||||
    $ adb shell \
 | 
			
		||||
        /data/nativetest/bionic-unit-tests-static/bionic-unit-tests-static32
 | 
			
		||||
    # Only for 64-bit targets
 | 
			
		||||
    $ adb shell /data/nativetest/bionic-unit-tests/bionic-unit-tests64
 | 
			
		||||
    $ adb shell \
 | 
			
		||||
        /data/nativetest/bionic-unit-tests-static/bionic-unit-tests-static64
 | 
			
		||||
 | 
			
		||||
### Host tests
 | 
			
		||||
 | 
			
		||||
The host tests require that you have `lunch`ed either an x86 or x86_64 target.
 | 
			
		||||
 | 
			
		||||
    $ mma
 | 
			
		||||
    $ mm bionic-unit-tests-run-on-host32
 | 
			
		||||
    $ mm bionic-unit-tests-run-on-host64  # For 64-bit *targets* only.
 | 
			
		||||
 | 
			
		||||
### Against glibc
 | 
			
		||||
 | 
			
		||||
As a way to check that our tests do in fact test the correct behavior (and not
 | 
			
		||||
just the behavior we think is correct), it is possible to run the tests against
 | 
			
		||||
the host's glibc. The executables are already in your path.
 | 
			
		||||
 | 
			
		||||
    $ mma
 | 
			
		||||
    $ bionic-unit-tests-glibc32
 | 
			
		||||
    $ bionic-unit-tests-glibc64
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Gathering test coverage
 | 
			
		||||
-----------------------
 | 
			
		||||
 | 
			
		||||
For either host or target coverage, you must first:
 | 
			
		||||
 | 
			
		||||
 * `$ export NATIVE_COVERAGE=true`
 | 
			
		||||
     * Note that the build system is ignorant to this flag being toggled, i.e. if
 | 
			
		||||
       you change this flag, you will have to manually rebuild bionic.
 | 
			
		||||
 * Set `bionic_coverage=true` in `libc/Android.mk` and `libm/Android.mk`.
 | 
			
		||||
 | 
			
		||||
### Coverage from device tests
 | 
			
		||||
 | 
			
		||||
    $ mma
 | 
			
		||||
    $ adb sync
 | 
			
		||||
    $ adb shell \
 | 
			
		||||
        GCOV_PREFIX=/data/local/tmp/gcov \
 | 
			
		||||
        GCOV_PREFIX_STRIP=`echo $ANDROID_BUILD_TOP | grep -o / | wc -l` \
 | 
			
		||||
        /data/nativetest/bionic-unit-tests/bionic-unit-tests32
 | 
			
		||||
    $ acov
 | 
			
		||||
 | 
			
		||||
`acov` will pull all coverage information from the device, push it to the right
 | 
			
		||||
directories, run `lcov`, and open the coverage report in your browser.
 | 
			
		||||
 | 
			
		||||
### Coverage from host tests
 | 
			
		||||
 | 
			
		||||
First, build and run the host tests as usual (see above).
 | 
			
		||||
 | 
			
		||||
    $ croot
 | 
			
		||||
    $ lcov -c -d $ANDROID_PRODUCT_OUT -o coverage.info
 | 
			
		||||
    $ genhtml -o covreport coverage.info # or lcov --list coverage.info
 | 
			
		||||
 | 
			
		||||
The coverage report is now available at `covreport/index.html`.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
LP32 ABI bugs
 | 
			
		||||
-------------
 | 
			
		||||
 | 
			
		||||
This probably belongs in the NDK documentation rather than here, but these
 | 
			
		||||
are the known ABI bugs in LP32:
 | 
			
		||||
 | 
			
		||||
 * `time_t` is 32-bit. <http://b/5819737>
 | 
			
		||||
 | 
			
		||||
 * `off_t` is 32-bit. There is `off64_t`, but no `_FILE_OFFSET_BITS` support.
 | 
			
		||||
   Many of the `off64_t` functions are missing in older releases, and
 | 
			
		||||
   stdio uses 32-bit offsets, so there's no way to fully implement
 | 
			
		||||
   `_FILE_OFFSET_BITS`.
 | 
			
		||||
 | 
			
		||||
 * `sigset_t` is too small on ARM and x86 (but correct on MIPS), so support
 | 
			
		||||
   for real-time signals is broken. <http://b/5828899>
 | 
			
		||||
@@ -14,56 +14,23 @@
 | 
			
		||||
# limitations under the License.
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
ifneq ($(BUILD_TINY_ANDROID), true)
 | 
			
		||||
 | 
			
		||||
LOCAL_PATH := $(call my-dir)
 | 
			
		||||
 | 
			
		||||
# -----------------------------------------------------------------------------
 | 
			
		||||
# Benchmarks library, usable by projects outside this directory.
 | 
			
		||||
# -----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
benchmark_cflags := \
 | 
			
		||||
    -O2 \
 | 
			
		||||
    -fno-builtin \
 | 
			
		||||
    -Wall \
 | 
			
		||||
    -Wextra \
 | 
			
		||||
    -Werror \
 | 
			
		||||
    -Wunused \
 | 
			
		||||
 | 
			
		||||
benchmark_cppflags := \
 | 
			
		||||
    -std=gnu++11 \
 | 
			
		||||
 | 
			
		||||
benchmarklib_src_files := \
 | 
			
		||||
    Benchmark.cpp \
 | 
			
		||||
    utils.cpp \
 | 
			
		||||
    main.cpp \
 | 
			
		||||
 | 
			
		||||
include $(CLEAR_VARS)
 | 
			
		||||
LOCAL_MODULE := libbenchmark
 | 
			
		||||
LOCAL_CFLAGS := $(benchmark_cflags)
 | 
			
		||||
LOCAL_CPPFLAGS := $(benchmark_cppflags)
 | 
			
		||||
LOCAL_SRC_FILES := $(benchmarklib_src_files)
 | 
			
		||||
LOCAL_C_INCLUDES := $(benchmark_c_includes)
 | 
			
		||||
LOCAL_STATIC_LIBRARIES := libbase
 | 
			
		||||
include $(BUILD_STATIC_LIBRARY)
 | 
			
		||||
 | 
			
		||||
# Only supported on linux systems.
 | 
			
		||||
ifeq ($(HOST_OS),linux)
 | 
			
		||||
 | 
			
		||||
include $(CLEAR_VARS)
 | 
			
		||||
LOCAL_MODULE := libbenchmark
 | 
			
		||||
LOCAL_CFLAGS := $(benchmark_cflags)
 | 
			
		||||
LOCAL_CPPFLAGS := $(benchmark_cppflags)
 | 
			
		||||
LOCAL_SRC_FILES := $(benchmarklib_src_files)
 | 
			
		||||
LOCAL_C_INCLUDES := $(benchmark_c_includes)
 | 
			
		||||
LOCAL_MULTILIB := both
 | 
			
		||||
LOCAL_STATIC_LIBRARIES := libbase
 | 
			
		||||
include $(BUILD_HOST_STATIC_LIBRARY)
 | 
			
		||||
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
# -----------------------------------------------------------------------------
 | 
			
		||||
# Benchmarks.
 | 
			
		||||
# -----------------------------------------------------------------------------
 | 
			
		||||
benchmark_src_files := \
 | 
			
		||||
 | 
			
		||||
benchmark_c_flags = \
 | 
			
		||||
    -O2 \
 | 
			
		||||
    -Wall -Wextra -Wunused \
 | 
			
		||||
    -Werror \
 | 
			
		||||
    -fno-builtin \
 | 
			
		||||
    -std=gnu++11 \
 | 
			
		||||
 | 
			
		||||
benchmark_src_files = \
 | 
			
		||||
    benchmark_main.cpp \
 | 
			
		||||
    math_benchmark.cpp \
 | 
			
		||||
    property_benchmark.cpp \
 | 
			
		||||
    pthread_benchmark.cpp \
 | 
			
		||||
@@ -74,58 +41,40 @@ benchmark_src_files := \
 | 
			
		||||
    unistd_benchmark.cpp \
 | 
			
		||||
 | 
			
		||||
# Build benchmarks for the device (with bionic's .so). Run with:
 | 
			
		||||
#   adb shell bionic-benchmarks32
 | 
			
		||||
#   adb shell bionic-benchmarks64
 | 
			
		||||
#   adb shell bionic-benchmarks
 | 
			
		||||
include $(CLEAR_VARS)
 | 
			
		||||
LOCAL_MODULE := bionic-benchmarks
 | 
			
		||||
LOCAL_MODULE_STEM_32 := bionic-benchmarks32
 | 
			
		||||
LOCAL_MODULE_STEM_64 := bionic-benchmarks64
 | 
			
		||||
LOCAL_MULTILIB := both
 | 
			
		||||
LOCAL_CFLAGS := $(benchmark_cflags)
 | 
			
		||||
LOCAL_CPPFLAGS := $(benchmark_cppflags)
 | 
			
		||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 | 
			
		||||
LOCAL_CFLAGS += $(benchmark_c_flags)
 | 
			
		||||
LOCAL_C_INCLUDES += external/stlport/stlport bionic/ bionic/libstdc++/include
 | 
			
		||||
LOCAL_SHARED_LIBRARIES += libstlport
 | 
			
		||||
LOCAL_SRC_FILES := $(benchmark_src_files)
 | 
			
		||||
LOCAL_STATIC_LIBRARIES := libbenchmark libbase
 | 
			
		||||
include $(BUILD_EXECUTABLE)
 | 
			
		||||
 | 
			
		||||
# We don't build a static benchmark executable because it's not usually
 | 
			
		||||
# useful. If you're trying to run the current benchmarks on an older
 | 
			
		||||
# release, it's (so far at least) always because you want to measure the
 | 
			
		||||
# performance of the old release's libc, and a static benchmark isn't
 | 
			
		||||
# going to let you do that.
 | 
			
		||||
 | 
			
		||||
# Only supported on linux systems.
 | 
			
		||||
ifeq ($(HOST_OS),linux)
 | 
			
		||||
 | 
			
		||||
# Build benchmarks for the host (against glibc!). Run with:
 | 
			
		||||
include $(CLEAR_VARS)
 | 
			
		||||
LOCAL_MODULE := bionic-benchmarks-glibc
 | 
			
		||||
LOCAL_MODULE_STEM_32 := bionic-benchmarks-glibc32
 | 
			
		||||
LOCAL_MODULE_STEM_64 := bionic-benchmarks-glibc64
 | 
			
		||||
LOCAL_MULTILIB := both
 | 
			
		||||
LOCAL_CFLAGS := $(benchmark_cflags)
 | 
			
		||||
LOCAL_CPPFLAGS := $(benchmark_cppflags)
 | 
			
		||||
LOCAL_LDFLAGS := -lrt
 | 
			
		||||
LOCAL_SRC_FILES := $(benchmark_src_files)
 | 
			
		||||
LOCAL_STATIC_LIBRARIES := libbenchmark libbase
 | 
			
		||||
include $(BUILD_HOST_EXECUTABLE)
 | 
			
		||||
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ($(HOST_OS)-$(HOST_ARCH),$(filter $(HOST_OS)-$(HOST_ARCH),linux-x86 linux-x86_64))
 | 
			
		||||
include $(LOCAL_PATH)/../build/run-on-host.mk
 | 
			
		||||
ifeq ($(TARGET_ARCH),x86)
 | 
			
		||||
LINKER = linker
 | 
			
		||||
NATIVE_SUFFIX=32
 | 
			
		||||
else
 | 
			
		||||
LINKER = linker64
 | 
			
		||||
NATIVE_SUFFIX=64
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),x86 x86_64))
 | 
			
		||||
bionic-benchmarks-run-on-host32: bionic-benchmarks bionic-prepare-run-on-host
 | 
			
		||||
bionic-benchmarks-run-on-host: bionic-benchmarks $(TARGET_OUT_EXECUTABLES)/$(LINKER) $(TARGET_OUT_EXECUTABLES)/sh
 | 
			
		||||
	if [ ! -d /system -o ! -d /system/bin ]; then \
 | 
			
		||||
	  echo "Attempting to create /system/bin"; \
 | 
			
		||||
	  sudo mkdir -p -m 0777 /system/bin; \
 | 
			
		||||
	fi
 | 
			
		||||
	mkdir -p $(TARGET_OUT_DATA)/local/tmp
 | 
			
		||||
	cp $(TARGET_OUT_EXECUTABLES)/$(LINKER) /system/bin
 | 
			
		||||
	cp $(TARGET_OUT_EXECUTABLES)/sh /system/bin
 | 
			
		||||
	ANDROID_DATA=$(TARGET_OUT_DATA) \
 | 
			
		||||
	ANDROID_ROOT=$(TARGET_OUT) \
 | 
			
		||||
		$(TARGET_OUT_EXECUTABLES)/bionic-benchmarks32 $(BIONIC_BENCHMARKS_FLAGS)
 | 
			
		||||
endif
 | 
			
		||||
	LD_LIBRARY_PATH=$(TARGET_OUT_SHARED_LIBRARIES) \
 | 
			
		||||
		$(TARGET_OUT_EXECUTABLES)/bionic-benchmarks$(NATIVE_SUFFIX) $(BIONIC_BENCHMARKS_FLAGS)
 | 
			
		||||
endif # linux-x86
 | 
			
		||||
 | 
			
		||||
ifeq ($(TARGET_IS_64_BIT),true)
 | 
			
		||||
bionic-benchmarks-run-on-host64: bionic-benchmarks bionic-prepare-run-on-host
 | 
			
		||||
	ANDROID_DATA=$(TARGET_OUT_DATA) \
 | 
			
		||||
	ANDROID_ROOT=$(TARGET_OUT) \
 | 
			
		||||
		$(TARGET_OUT_EXECUTABLES)/bionic-benchmarks64 $(BIONIC_BENCHMARKS_FLAGS)
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
endif
 | 
			
		||||
endif # !BUILD_TINY_ANDROID
 | 
			
		||||
 
 | 
			
		||||
@@ -1,159 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2012 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * 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 <inttypes.h>
 | 
			
		||||
#include <regex.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <time.h>
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
#include <base/stringprintf.h>
 | 
			
		||||
 | 
			
		||||
#include <benchmark/Benchmark.h>
 | 
			
		||||
 | 
			
		||||
#include "utils.h"
 | 
			
		||||
 | 
			
		||||
namespace testing {
 | 
			
		||||
 | 
			
		||||
static uint64_t NanoTime() {
 | 
			
		||||
  struct timespec t;
 | 
			
		||||
  t.tv_sec = t.tv_nsec = 0;
 | 
			
		||||
  clock_gettime(CLOCK_MONOTONIC, &t);
 | 
			
		||||
  return static_cast<uint64_t>(t.tv_sec) * 1000000000LL + t.tv_nsec;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Benchmark::header_printed_;
 | 
			
		||||
 | 
			
		||||
std::vector<Benchmark*>& Benchmark::List() {
 | 
			
		||||
  static std::vector<Benchmark*> list;
 | 
			
		||||
  return list;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int Benchmark::MaxNameColumnWidth() {
 | 
			
		||||
  size_t max = 20;
 | 
			
		||||
  for (auto& benchmark : List()) {
 | 
			
		||||
    max = std::max(max, benchmark->NameColumnWidth());
 | 
			
		||||
  }
 | 
			
		||||
  return static_cast<int>(max);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
size_t Benchmark::RunAll(std::vector<regex_t*>& regs) {
 | 
			
		||||
  size_t benchmarks_run = 0;
 | 
			
		||||
  header_printed_ = false;
 | 
			
		||||
  for (auto& benchmark : List()) {
 | 
			
		||||
    benchmarks_run += benchmark->RunAllArgs(regs);
 | 
			
		||||
  }
 | 
			
		||||
  return benchmarks_run;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Benchmark::PrintHeader() {
 | 
			
		||||
  if (!header_printed_) {
 | 
			
		||||
    printf("%-*s %10s %10s\n", MaxNameColumnWidth(), "", "iterations", "ns/op");
 | 
			
		||||
    header_printed_ = true;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
bool BenchmarkT<T>::ShouldRun(std::vector<regex_t*>& regs, T arg) {
 | 
			
		||||
  if (regs.empty()) {
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  for (const auto& re : regs) {
 | 
			
		||||
    if (regexec(re, GetNameStr(arg).c_str(), 0, NULL, 0) != REG_NOMATCH) {
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Benchmark::StopBenchmarkTiming() {
 | 
			
		||||
  if (start_time_ns_ != 0) {
 | 
			
		||||
    total_time_ns_ += NanoTime() - start_time_ns_;
 | 
			
		||||
  }
 | 
			
		||||
  start_time_ns_ = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Benchmark::StartBenchmarkTiming() {
 | 
			
		||||
  if (start_time_ns_ == 0) {
 | 
			
		||||
    start_time_ns_ = NanoTime();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::string BenchmarkWithoutArg::GetNameStr(void*) {
 | 
			
		||||
  return Name();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <>
 | 
			
		||||
std::string BenchmarkWithArg<int>::GetNameStr(int arg) {
 | 
			
		||||
  return Name() + "/" + PrettyInt(arg, 2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <>
 | 
			
		||||
std::string BenchmarkWithArg<double>::GetNameStr(double arg) {
 | 
			
		||||
  return Name() + "/" + android::base::StringPrintf("%0.6f", arg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
void BenchmarkT<T>::RunWithArg(T arg) {
 | 
			
		||||
  int new_iterations = 1;
 | 
			
		||||
  int iterations;
 | 
			
		||||
  while (new_iterations < 1e8) {
 | 
			
		||||
    bytes_processed_ = 0;
 | 
			
		||||
    total_time_ns_ = 0;
 | 
			
		||||
    start_time_ns_ = 0;
 | 
			
		||||
 | 
			
		||||
    iterations = new_iterations;
 | 
			
		||||
    RunIterations(iterations, arg);
 | 
			
		||||
    if (total_time_ns_ >= 1e9) {
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (total_time_ns_/iterations == 0) {
 | 
			
		||||
      new_iterations = 1e9;
 | 
			
		||||
    } else {
 | 
			
		||||
      new_iterations = 1e9/ (total_time_ns_/iterations);
 | 
			
		||||
    }
 | 
			
		||||
    new_iterations = std::max(iterations + 1,
 | 
			
		||||
                          std::min(new_iterations + new_iterations/2, 100*iterations));
 | 
			
		||||
 | 
			
		||||
    new_iterations = Round(new_iterations);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  printf("%-*s %10s %10" PRId64, MaxNameColumnWidth(), GetNameStr(arg).c_str(),
 | 
			
		||||
         PrettyInt(iterations, 10).c_str(), total_time_ns_/iterations);
 | 
			
		||||
 | 
			
		||||
  if (total_time_ns_ > 0 && bytes_processed_ > 0) {
 | 
			
		||||
    double gib_processed = static_cast<double>(bytes_processed_)/1e9;
 | 
			
		||||
    double seconds = static_cast<double>(total_time_ns_)/1e9;
 | 
			
		||||
    printf(" %8.3f GiB/s", gib_processed/seconds);
 | 
			
		||||
  }
 | 
			
		||||
  printf("\n");
 | 
			
		||||
  fflush(stdout);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template class BenchmarkT<int>;
 | 
			
		||||
template class BenchmarkT<double>;
 | 
			
		||||
template class BenchmarkT<void*>;
 | 
			
		||||
 | 
			
		||||
template class BenchmarkWithArg<int>;
 | 
			
		||||
template class BenchmarkWithArg<double>;
 | 
			
		||||
 | 
			
		||||
}  // namespace testing
 | 
			
		||||
							
								
								
									
										61
									
								
								benchmarks/benchmark.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								benchmarks/benchmark.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,61 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2012 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * 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 <stdint.h>
 | 
			
		||||
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
namespace testing {
 | 
			
		||||
 | 
			
		||||
class Benchmark {
 | 
			
		||||
 public:
 | 
			
		||||
  Benchmark(const char* name, void (*fn)(int)) {
 | 
			
		||||
    Register(name, fn, NULL);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Benchmark(const char* name, void (*fn_range)(int, int)) {
 | 
			
		||||
    Register(name, NULL, fn_range);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Benchmark* Arg(int x);
 | 
			
		||||
 | 
			
		||||
  const char* Name();
 | 
			
		||||
 | 
			
		||||
  bool ShouldRun(int argc, char* argv[]);
 | 
			
		||||
  void Run();
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  const char* name_;
 | 
			
		||||
 | 
			
		||||
  void (*fn_)(int);
 | 
			
		||||
  void (*fn_range_)(int, int);
 | 
			
		||||
 | 
			
		||||
  std::vector<int> args_;
 | 
			
		||||
 | 
			
		||||
  void Register(const char* name, void (*fn)(int), void (*fn_range)(int, int));
 | 
			
		||||
  void RunRepeatedlyWithArg(int iterations, int arg);
 | 
			
		||||
  void RunWithArg(int arg);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace testing
 | 
			
		||||
 | 
			
		||||
void SetBenchmarkBytesProcessed(int64_t);
 | 
			
		||||
void StopBenchmarkTiming();
 | 
			
		||||
void StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
#define BENCHMARK(f) \
 | 
			
		||||
    static ::testing::Benchmark* _benchmark_##f __attribute__((unused)) = \
 | 
			
		||||
        (new ::testing::Benchmark(#f, f))
 | 
			
		||||
@@ -1,169 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2012 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * 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 BENCHMARKS_BENCHMARK_H_
 | 
			
		||||
#define BENCHMARKS_BENCHMARK_H_
 | 
			
		||||
 | 
			
		||||
#include <regex.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
namespace testing {
 | 
			
		||||
 | 
			
		||||
class Benchmark {
 | 
			
		||||
public:
 | 
			
		||||
  Benchmark() {
 | 
			
		||||
    List().push_back(this);
 | 
			
		||||
  }
 | 
			
		||||
  virtual ~Benchmark() {}
 | 
			
		||||
 | 
			
		||||
  virtual std::string Name() = 0;
 | 
			
		||||
 | 
			
		||||
  virtual size_t RunAllArgs(std::vector<regex_t*>&) = 0;
 | 
			
		||||
 | 
			
		||||
  void SetBenchmarkBytesProcessed(uint64_t bytes) { bytes_processed_ += bytes; }
 | 
			
		||||
  void StopBenchmarkTiming();
 | 
			
		||||
  void StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  // Run all of the benchmarks that have registered.
 | 
			
		||||
  static size_t RunAll(std::vector<regex_t*>&);
 | 
			
		||||
 | 
			
		||||
  static std::vector<Benchmark*>& List();
 | 
			
		||||
 | 
			
		||||
  static int MaxNameColumnWidth();
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
  virtual size_t NameColumnWidth() = 0;
 | 
			
		||||
 | 
			
		||||
  uint64_t bytes_processed_;
 | 
			
		||||
  uint64_t total_time_ns_;
 | 
			
		||||
  uint64_t start_time_ns_;
 | 
			
		||||
 | 
			
		||||
  static bool header_printed_;
 | 
			
		||||
 | 
			
		||||
  static void PrintHeader();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
class BenchmarkT : public Benchmark {
 | 
			
		||||
public:
 | 
			
		||||
  BenchmarkT() {}
 | 
			
		||||
  virtual ~BenchmarkT() {}
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
  bool ShouldRun(std::vector<regex_t*>&, T arg);
 | 
			
		||||
  void RunWithArg(T arg);
 | 
			
		||||
  virtual void RunIterations(int, T) = 0;
 | 
			
		||||
  virtual std::string GetNameStr(T) = 0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class BenchmarkWithoutArg : public BenchmarkT<void*> {
 | 
			
		||||
public:
 | 
			
		||||
  BenchmarkWithoutArg() {}
 | 
			
		||||
  virtual ~BenchmarkWithoutArg() {}
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
  virtual size_t RunAllArgs(std::vector<regex_t*>& regs) override {
 | 
			
		||||
    size_t benchmarks_run = 0;
 | 
			
		||||
    if (BenchmarkT<void*>::ShouldRun(regs, nullptr)) {
 | 
			
		||||
      PrintHeader();
 | 
			
		||||
      RunWithArg(nullptr);
 | 
			
		||||
      benchmarks_run++;
 | 
			
		||||
    }
 | 
			
		||||
    return benchmarks_run;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  virtual void RunIterations(int iters, void*) override {
 | 
			
		||||
    Run(iters);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  virtual void Run(int) = 0;
 | 
			
		||||
 | 
			
		||||
  virtual size_t NameColumnWidth() override {
 | 
			
		||||
    return Name().size();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  virtual std::string GetNameStr(void *) override;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
class BenchmarkWithArg : public BenchmarkT<T> {
 | 
			
		||||
public:
 | 
			
		||||
  BenchmarkWithArg() {}
 | 
			
		||||
  virtual ~BenchmarkWithArg() {}
 | 
			
		||||
 | 
			
		||||
  BenchmarkWithArg* Arg(T arg) {
 | 
			
		||||
    args_.push_back(arg);
 | 
			
		||||
    return this;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
  virtual size_t NameColumnWidth() override {
 | 
			
		||||
    size_t max = 0;
 | 
			
		||||
    for (const auto& arg : args_) {
 | 
			
		||||
      max = std::max(max, GetNameStr(arg).size());
 | 
			
		||||
    }
 | 
			
		||||
    return max;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  std::string GetNameStr(T arg) override;
 | 
			
		||||
 | 
			
		||||
  virtual size_t RunAllArgs(std::vector<regex_t*>& regs) override {
 | 
			
		||||
    size_t benchmarks_run = 0;
 | 
			
		||||
    for (T& arg : args_) {
 | 
			
		||||
      if (BenchmarkT<T>::ShouldRun(regs, arg)) {
 | 
			
		||||
        Benchmark::PrintHeader();
 | 
			
		||||
        BenchmarkT<T>::RunWithArg(arg);
 | 
			
		||||
        benchmarks_run++;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return benchmarks_run;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  virtual void RunIterations(int iters, T arg) override {
 | 
			
		||||
    Run(iters, arg);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  virtual void Run(int iters, T arg) = 0;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
  std::vector<T> args_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace testing
 | 
			
		||||
 | 
			
		||||
#define BENCHMARK_START(f, super_class) \
 | 
			
		||||
  class f : public super_class { \
 | 
			
		||||
  public: \
 | 
			
		||||
    f() {} \
 | 
			
		||||
    virtual ~f() {} \
 | 
			
		||||
    virtual std::string Name() override { return #f; } \
 | 
			
		||||
 | 
			
		||||
#define BENCHMARK_NO_ARG(f) \
 | 
			
		||||
  BENCHMARK_START(f, ::testing::BenchmarkWithoutArg) \
 | 
			
		||||
    virtual void Run(int) override; \
 | 
			
		||||
  }; \
 | 
			
		||||
  static ::testing::Benchmark* __benchmark_##f = new f()
 | 
			
		||||
 | 
			
		||||
#define BENCHMARK_WITH_ARG(f, arg_type) \
 | 
			
		||||
  BENCHMARK_START(f, ::testing::BenchmarkWithArg<arg_type>) \
 | 
			
		||||
    virtual void Run(int, arg_type) override; \
 | 
			
		||||
  }; \
 | 
			
		||||
  static ::testing::BenchmarkWithArg<arg_type>* __benchmark_##f = (new f())
 | 
			
		||||
 | 
			
		||||
#endif  // BENCHMARKS_BENCHMARK_H_
 | 
			
		||||
							
								
								
									
										226
									
								
								benchmarks/benchmark_main.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										226
									
								
								benchmarks/benchmark_main.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,226 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2012 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * 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 "benchmark.h"
 | 
			
		||||
 | 
			
		||||
#include <regex.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <map>
 | 
			
		||||
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
 | 
			
		||||
static int64_t g_bytes_processed;
 | 
			
		||||
static int64_t g_benchmark_total_time_ns;
 | 
			
		||||
static int64_t g_benchmark_start_time_ns;
 | 
			
		||||
 | 
			
		||||
typedef std::map<std::string, ::testing::Benchmark*> BenchmarkMap;
 | 
			
		||||
typedef BenchmarkMap::iterator BenchmarkMapIt;
 | 
			
		||||
static BenchmarkMap g_benchmarks;
 | 
			
		||||
static int g_name_column_width = 20;
 | 
			
		||||
 | 
			
		||||
static int Round(int n) {
 | 
			
		||||
  int base = 1;
 | 
			
		||||
  while (base*10 < n) {
 | 
			
		||||
    base *= 10;
 | 
			
		||||
  }
 | 
			
		||||
  if (n < 2*base) {
 | 
			
		||||
    return 2*base;
 | 
			
		||||
  }
 | 
			
		||||
  if (n < 5*base) {
 | 
			
		||||
    return 5*base;
 | 
			
		||||
  }
 | 
			
		||||
  return 10*base;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int64_t NanoTime() {
 | 
			
		||||
  struct timespec t;
 | 
			
		||||
  t.tv_sec = t.tv_nsec = 0;
 | 
			
		||||
  clock_gettime(CLOCK_MONOTONIC, &t);
 | 
			
		||||
  return static_cast<int64_t>(t.tv_sec) * 1000000000LL + t.tv_nsec;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace testing {
 | 
			
		||||
 | 
			
		||||
Benchmark* Benchmark::Arg(int arg) {
 | 
			
		||||
  args_.push_back(arg);
 | 
			
		||||
  return this;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char* Benchmark::Name() {
 | 
			
		||||
  return name_;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Benchmark::ShouldRun(int argc, char* argv[]) {
 | 
			
		||||
  if (argc == 1) {
 | 
			
		||||
    return true;  // With no arguments, we run all benchmarks.
 | 
			
		||||
  }
 | 
			
		||||
  // Otherwise, we interpret each argument as a regular expression and
 | 
			
		||||
  // see if any of our benchmarks match.
 | 
			
		||||
  for (int i = 1; i < argc; i++) {
 | 
			
		||||
    regex_t re;
 | 
			
		||||
    if (regcomp(&re, argv[i], 0) != 0) {
 | 
			
		||||
      fprintf(stderr, "couldn't compile \"%s\" as a regular expression!\n", argv[i]);
 | 
			
		||||
      exit(EXIT_FAILURE);
 | 
			
		||||
    }
 | 
			
		||||
    int match = regexec(&re, name_, 0, NULL, 0);
 | 
			
		||||
    regfree(&re);
 | 
			
		||||
    if (match != REG_NOMATCH) {
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Benchmark::Register(const char* name, void (*fn)(int), void (*fn_range)(int, int)) {
 | 
			
		||||
  name_ = name;
 | 
			
		||||
  fn_ = fn;
 | 
			
		||||
  fn_range_ = fn_range;
 | 
			
		||||
 | 
			
		||||
  if (fn_ == NULL && fn_range_ == NULL) {
 | 
			
		||||
    fprintf(stderr, "%s: missing function\n", name_);
 | 
			
		||||
    exit(EXIT_FAILURE);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  g_benchmarks.insert(std::make_pair(name, this));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Benchmark::Run() {
 | 
			
		||||
  if (fn_ != NULL) {
 | 
			
		||||
    RunWithArg(0);
 | 
			
		||||
  } else {
 | 
			
		||||
    if (args_.empty()) {
 | 
			
		||||
      fprintf(stderr, "%s: no args!\n", name_);
 | 
			
		||||
      exit(EXIT_FAILURE);
 | 
			
		||||
    }
 | 
			
		||||
    for (size_t i = 0; i < args_.size(); ++i) {
 | 
			
		||||
      RunWithArg(args_[i]);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Benchmark::RunRepeatedlyWithArg(int iterations, int arg) {
 | 
			
		||||
  g_bytes_processed = 0;
 | 
			
		||||
  g_benchmark_total_time_ns = 0;
 | 
			
		||||
  g_benchmark_start_time_ns = NanoTime();
 | 
			
		||||
  if (fn_ != NULL) {
 | 
			
		||||
    fn_(iterations);
 | 
			
		||||
  } else {
 | 
			
		||||
    fn_range_(iterations, arg);
 | 
			
		||||
  }
 | 
			
		||||
  if (g_benchmark_start_time_ns != 0) {
 | 
			
		||||
    g_benchmark_total_time_ns += NanoTime() - g_benchmark_start_time_ns;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Benchmark::RunWithArg(int arg) {
 | 
			
		||||
  // run once in case it's expensive
 | 
			
		||||
  int iterations = 1;
 | 
			
		||||
  RunRepeatedlyWithArg(iterations, arg);
 | 
			
		||||
  while (g_benchmark_total_time_ns < 1e9 && iterations < 1e9) {
 | 
			
		||||
    int last = iterations;
 | 
			
		||||
    if (g_benchmark_total_time_ns/iterations == 0) {
 | 
			
		||||
      iterations = 1e9;
 | 
			
		||||
    } else {
 | 
			
		||||
      iterations = 1e9 / (g_benchmark_total_time_ns/iterations);
 | 
			
		||||
    }
 | 
			
		||||
    iterations = std::max(last + 1, std::min(iterations + iterations/2, 100*last));
 | 
			
		||||
    iterations = Round(iterations);
 | 
			
		||||
    RunRepeatedlyWithArg(iterations, arg);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  char throughput[100];
 | 
			
		||||
  throughput[0] = '\0';
 | 
			
		||||
  if (g_benchmark_total_time_ns > 0 && g_bytes_processed > 0) {
 | 
			
		||||
    double mib_processed = static_cast<double>(g_bytes_processed)/1e6;
 | 
			
		||||
    double seconds = static_cast<double>(g_benchmark_total_time_ns)/1e9;
 | 
			
		||||
    snprintf(throughput, sizeof(throughput), " %8.2f MiB/s", mib_processed/seconds);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  char full_name[100];
 | 
			
		||||
  if (fn_range_ != NULL) {
 | 
			
		||||
    if (arg >= (1<<20)) {
 | 
			
		||||
      snprintf(full_name, sizeof(full_name), "%s/%dM", name_, arg/(1<<20));
 | 
			
		||||
    } else if (arg >= (1<<10)) {
 | 
			
		||||
      snprintf(full_name, sizeof(full_name), "%s/%dK", name_, arg/(1<<10));
 | 
			
		||||
    } else {
 | 
			
		||||
      snprintf(full_name, sizeof(full_name), "%s/%d", name_, arg);
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    snprintf(full_name, sizeof(full_name), "%s", name_);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  printf("%-*s %10d %10" PRId64 "%s\n", g_name_column_width, full_name,
 | 
			
		||||
         iterations, g_benchmark_total_time_ns/iterations, throughput);
 | 
			
		||||
  fflush(stdout);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace testing
 | 
			
		||||
 | 
			
		||||
void SetBenchmarkBytesProcessed(int64_t x) {
 | 
			
		||||
  g_bytes_processed = x;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void StopBenchmarkTiming() {
 | 
			
		||||
  if (g_benchmark_start_time_ns != 0) {
 | 
			
		||||
    g_benchmark_total_time_ns += NanoTime() - g_benchmark_start_time_ns;
 | 
			
		||||
  }
 | 
			
		||||
  g_benchmark_start_time_ns = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void StartBenchmarkTiming() {
 | 
			
		||||
  if (g_benchmark_start_time_ns == 0) {
 | 
			
		||||
    g_benchmark_start_time_ns = NanoTime();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(int argc, char* argv[]) {
 | 
			
		||||
  if (g_benchmarks.empty()) {
 | 
			
		||||
    fprintf(stderr, "No benchmarks registered!\n");
 | 
			
		||||
    exit(EXIT_FAILURE);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  for (BenchmarkMapIt it = g_benchmarks.begin(); it != g_benchmarks.end(); ++it) {
 | 
			
		||||
    int name_width = static_cast<int>(strlen(it->second->Name()));
 | 
			
		||||
    g_name_column_width = std::max(g_name_column_width, name_width);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  bool need_header = true;
 | 
			
		||||
  for (BenchmarkMapIt it = g_benchmarks.begin(); it != g_benchmarks.end(); ++it) {
 | 
			
		||||
    ::testing::Benchmark* b = it->second;
 | 
			
		||||
    if (b->ShouldRun(argc, argv)) {
 | 
			
		||||
      if (need_header) {
 | 
			
		||||
        printf("%-*s %10s %10s\n", g_name_column_width, "", "iterations", "ns/op");
 | 
			
		||||
        fflush(stdout);
 | 
			
		||||
        need_header = false;
 | 
			
		||||
      }
 | 
			
		||||
      b->Run();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (need_header) {
 | 
			
		||||
    fprintf(stderr, "No matching benchmarks!\n");
 | 
			
		||||
    fprintf(stderr, "Available benchmarks:\n");
 | 
			
		||||
    for (BenchmarkMapIt it = g_benchmarks.begin(); it != g_benchmarks.end(); ++it) {
 | 
			
		||||
      fprintf(stderr, "  %s\n", it->second->Name());
 | 
			
		||||
    }
 | 
			
		||||
    exit(EXIT_FAILURE);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,61 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2012 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * 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 <regex.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
#include <benchmark/Benchmark.h>
 | 
			
		||||
 | 
			
		||||
int main(int argc, char* argv[]) {
 | 
			
		||||
  if (::testing::Benchmark::List().empty()) {
 | 
			
		||||
    fprintf(stderr, "No benchmarks registered!\n");
 | 
			
		||||
    exit(EXIT_FAILURE);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  std::vector<regex_t*> regs;
 | 
			
		||||
  for (int i = 1; i < argc; i++) {
 | 
			
		||||
    regex_t* re = new regex_t;
 | 
			
		||||
    int errcode = regcomp(re, argv[i], 0);
 | 
			
		||||
    if (errcode != 0) {
 | 
			
		||||
      size_t errbuf_size = regerror(errcode, re, NULL, 0);
 | 
			
		||||
      if (errbuf_size > 0) {
 | 
			
		||||
        char* errbuf = new char[errbuf_size];
 | 
			
		||||
        regerror(errcode, re, errbuf, errbuf_size);
 | 
			
		||||
        fprintf(stderr, "Couldn't compile \"%s\" as a regular expression: %s\n",
 | 
			
		||||
                argv[i], errbuf);
 | 
			
		||||
      } else {
 | 
			
		||||
        fprintf(stderr, "Unknown compile error for \"%s\" as a regular expression!\n", argv[i]);
 | 
			
		||||
      }
 | 
			
		||||
      exit(EXIT_FAILURE);
 | 
			
		||||
    }
 | 
			
		||||
    regs.push_back(re);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (::testing::Benchmark::RunAll(regs) == 0) {
 | 
			
		||||
    fprintf(stderr, "No matching benchmarks!\n");
 | 
			
		||||
    fprintf(stderr, "Available benchmarks:\n");
 | 
			
		||||
    for (const auto& benchmark : ::testing::Benchmark::List()) {
 | 
			
		||||
      fprintf(stderr, "  %s\n", benchmark->Name().c_str());
 | 
			
		||||
    }
 | 
			
		||||
    exit(EXIT_FAILURE);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
@@ -14,20 +14,16 @@
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "benchmark.h"
 | 
			
		||||
 | 
			
		||||
#include <fenv.h>
 | 
			
		||||
#include <math.h>
 | 
			
		||||
 | 
			
		||||
#include <benchmark/Benchmark.h>
 | 
			
		||||
 | 
			
		||||
#define AT_COMMON_VALS \
 | 
			
		||||
    Arg(1234.0)->Arg(nan(""))->Arg(HUGE_VAL)->Arg(0.0)
 | 
			
		||||
 | 
			
		||||
// Avoid optimization.
 | 
			
		||||
volatile double d;
 | 
			
		||||
volatile double v;
 | 
			
		||||
double d;
 | 
			
		||||
double v;
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_math_sqrt);
 | 
			
		||||
void BM_math_sqrt::Run(int iters) {
 | 
			
		||||
static void BM_math_sqrt(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  d = 0.0;
 | 
			
		||||
@@ -38,9 +34,9 @@ void BM_math_sqrt::Run(int iters) {
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_math_sqrt);
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_math_log10);
 | 
			
		||||
void BM_math_log10::Run(int iters) {
 | 
			
		||||
static void BM_math_log10(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  d = 0.0;
 | 
			
		||||
@@ -51,9 +47,9 @@ void BM_math_log10::Run(int iters) {
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_math_log10);
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_math_logb);
 | 
			
		||||
void BM_math_logb::Run(int iters) {
 | 
			
		||||
static void BM_math_logb(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  d = 0.0;
 | 
			
		||||
@@ -64,22 +60,61 @@ void BM_math_logb::Run(int iters) {
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_math_logb);
 | 
			
		||||
 | 
			
		||||
BENCHMARK_WITH_ARG(BM_math_isinf, double)->AT_COMMON_VALS;
 | 
			
		||||
void BM_math_isinf::Run(int iters, double value) {
 | 
			
		||||
static void BM_math_isinf_NORMAL(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  d = 0.0;
 | 
			
		||||
  v = value;
 | 
			
		||||
  v = 1234.0; // FP_NORMAL
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    d += (isinf)(v);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_math_isinf_NORMAL);
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_math_sin_fast);
 | 
			
		||||
void BM_math_sin_fast::Run(int iters) {
 | 
			
		||||
static void BM_math_isinf_NAN(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  d = 0.0;
 | 
			
		||||
  v = nan(""); // FP_NAN
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    d += (isinf)(v);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_math_isinf_NAN);
 | 
			
		||||
 | 
			
		||||
static void BM_math_isinf_INFINITE(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  d = 0.0;
 | 
			
		||||
  v = HUGE_VAL; // FP_INFINITE
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    d += (isinf)(v);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_math_isinf_INFINITE);
 | 
			
		||||
 | 
			
		||||
static void BM_math_isinf_ZERO(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  d = 0.0;
 | 
			
		||||
  v = 0.0; // FP_ZERO
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    d += (isinf)(v);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_math_isinf_ZERO);
 | 
			
		||||
 | 
			
		||||
static void BM_math_sin_fast(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  d = 1.0;
 | 
			
		||||
@@ -89,9 +124,9 @@ void BM_math_sin_fast::Run(int iters) {
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_math_sin_fast);
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_math_sin_feupdateenv);
 | 
			
		||||
void BM_math_sin_feupdateenv::Run(int iters) {
 | 
			
		||||
static void BM_math_sin_feupdateenv(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  d = 1.0;
 | 
			
		||||
@@ -105,9 +140,9 @@ void BM_math_sin_feupdateenv::Run(int iters) {
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_math_sin_feupdateenv);
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_math_sin_fesetenv);
 | 
			
		||||
void BM_math_sin_fesetenv::Run(int iters) {
 | 
			
		||||
static void BM_math_sin_fesetenv(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  d = 1.0;
 | 
			
		||||
@@ -121,16 +156,56 @@ void BM_math_sin_fesetenv::Run(int iters) {
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_math_sin_fesetenv);
 | 
			
		||||
 | 
			
		||||
BENCHMARK_WITH_ARG(BM_math_fpclassify, double)->AT_COMMON_VALS;
 | 
			
		||||
void BM_math_fpclassify::Run(int iters, double value) {
 | 
			
		||||
static void BM_math_fpclassify_NORMAL(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  d = 0.0;
 | 
			
		||||
  v = value;
 | 
			
		||||
  v = 1234.0; // FP_NORMAL
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    d += fpclassify(v);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_math_fpclassify_NORMAL);
 | 
			
		||||
 | 
			
		||||
static void BM_math_fpclassify_NAN(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  d = 0.0;
 | 
			
		||||
  v = nan(""); // FP_NAN
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    d += fpclassify(v);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_math_fpclassify_NAN);
 | 
			
		||||
 | 
			
		||||
static void BM_math_fpclassify_INFINITE(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  d = 0.0;
 | 
			
		||||
  v = HUGE_VAL; // FP_INFINITE
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    d += fpclassify(v);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_math_fpclassify_INFINITE);
 | 
			
		||||
 | 
			
		||||
static void BM_math_fpclassify_ZERO(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  d = 0.0;
 | 
			
		||||
  v = 0.0; // FP_ZERO
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    d += fpclassify(v);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_math_fpclassify_ZERO);
 | 
			
		||||
 
 | 
			
		||||
@@ -14,21 +14,19 @@
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "benchmark.h"
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
#if defined(__BIONIC__)
 | 
			
		||||
 | 
			
		||||
#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
 | 
			
		||||
#include <sys/_system_properties.h>
 | 
			
		||||
 | 
			
		||||
#include <benchmark/Benchmark.h>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
extern void* __system_property_area__;
 | 
			
		||||
extern void *__system_property_area__;
 | 
			
		||||
 | 
			
		||||
// Do not exceed 512, that is about the largest number of properties
 | 
			
		||||
// that can be created with the current property area size.
 | 
			
		||||
@@ -36,198 +34,200 @@ extern void* __system_property_area__;
 | 
			
		||||
    Arg(1)->Arg(4)->Arg(16)->Arg(64)->Arg(128)->Arg(256)->Arg(512)
 | 
			
		||||
 | 
			
		||||
struct LocalPropertyTestState {
 | 
			
		||||
  LocalPropertyTestState(int nprops) : nprops(nprops), valid(false) {
 | 
			
		||||
    static const char prop_name_chars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_.";
 | 
			
		||||
    LocalPropertyTestState(int nprops) : nprops(nprops), valid(false) {
 | 
			
		||||
        static const char prop_name_chars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_.";
 | 
			
		||||
 | 
			
		||||
    const char* android_data = getenv("ANDROID_DATA");
 | 
			
		||||
    if (android_data == NULL) {
 | 
			
		||||
      printf("ANDROID_DATA environment variable not set\n");
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    char dir_template[PATH_MAX];
 | 
			
		||||
    snprintf(dir_template, sizeof(dir_template), "%s/local/tmp/prop-XXXXXX", android_data);
 | 
			
		||||
    char* dirname = mkdtemp(dir_template);
 | 
			
		||||
    if (!dirname) {
 | 
			
		||||
      printf("making temp file for test state failed (is %s/local/tmp writable?): %s\n",
 | 
			
		||||
             android_data, strerror(errno));
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    old_pa = __system_property_area__;
 | 
			
		||||
    __system_property_area__ = NULL;
 | 
			
		||||
 | 
			
		||||
    pa_dirname = dirname;
 | 
			
		||||
    pa_filename = pa_dirname + "/__properties__";
 | 
			
		||||
 | 
			
		||||
    __system_property_set_filename(pa_filename.c_str());
 | 
			
		||||
    __system_property_area_init();
 | 
			
		||||
 | 
			
		||||
    names = new char* [nprops];
 | 
			
		||||
    name_lens = new int[nprops];
 | 
			
		||||
    values = new char* [nprops];
 | 
			
		||||
    value_lens = new int[nprops];
 | 
			
		||||
 | 
			
		||||
    srandom(nprops);
 | 
			
		||||
 | 
			
		||||
    for (int i = 0; i < nprops; i++) {
 | 
			
		||||
      // Make sure the name has at least 10 characters to make
 | 
			
		||||
      // it very unlikely to generate the same random name.
 | 
			
		||||
      name_lens[i] = (random() % (PROP_NAME_MAX - 10)) + 10;
 | 
			
		||||
      names[i] = new char[PROP_NAME_MAX + 1];
 | 
			
		||||
      size_t prop_name_len = sizeof(prop_name_chars) - 1;
 | 
			
		||||
      for (int j = 0; j < name_lens[i]; j++) {
 | 
			
		||||
        if (j == 0 || names[i][j-1] == '.' || j == name_lens[i] - 1) {
 | 
			
		||||
          // Certain values are not allowed:
 | 
			
		||||
          // - Don't start name with '.'
 | 
			
		||||
          // - Don't allow '.' to appear twice in a row
 | 
			
		||||
          // - Don't allow the name to end with '.'
 | 
			
		||||
          // This assumes that '.' is the last character in the
 | 
			
		||||
          // array so that decrementing the length by one removes
 | 
			
		||||
          // the value from the possible values.
 | 
			
		||||
          prop_name_len--;
 | 
			
		||||
        const char* android_data = getenv("ANDROID_DATA");
 | 
			
		||||
        if (android_data == NULL) {
 | 
			
		||||
          printf("ANDROID_DATA environment variable not set\n");
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        char dir_template[PATH_MAX];
 | 
			
		||||
        snprintf(dir_template, sizeof(dir_template), "%s/local/tmp/prop-XXXXXX", android_data);
 | 
			
		||||
        char *dirname = mkdtemp(dir_template);
 | 
			
		||||
        if (!dirname) {
 | 
			
		||||
            printf("making temp file for test state failed (is %s/local/tmp writable?): %s\n",
 | 
			
		||||
                   android_data, strerror(errno));
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        names[i][j] = prop_name_chars[random() % prop_name_len];
 | 
			
		||||
      }
 | 
			
		||||
      names[i][name_lens[i]] = 0;
 | 
			
		||||
 | 
			
		||||
      // Make sure the value contains at least 1 character.
 | 
			
		||||
      value_lens[i] = (random() % (PROP_VALUE_MAX - 1)) + 1;
 | 
			
		||||
      values[i] = new char[PROP_VALUE_MAX];
 | 
			
		||||
      for (int j = 0; j < value_lens[i]; j++) {
 | 
			
		||||
        values[i][j] = prop_name_chars[random() % (sizeof(prop_name_chars) - 1)];
 | 
			
		||||
      }
 | 
			
		||||
        old_pa = __system_property_area__;
 | 
			
		||||
        __system_property_area__ = NULL;
 | 
			
		||||
 | 
			
		||||
      if (__system_property_add(names[i], name_lens[i], values[i], value_lens[i]) < 0) {
 | 
			
		||||
        printf("Failed to add a property, terminating...\n");
 | 
			
		||||
        printf("%s = %.*s\n", names[i], value_lens[i], values[i]);
 | 
			
		||||
        exit(1);
 | 
			
		||||
      }
 | 
			
		||||
        pa_dirname = dirname;
 | 
			
		||||
        pa_filename = pa_dirname + "/__properties__";
 | 
			
		||||
 | 
			
		||||
        __system_property_set_filename(pa_filename.c_str());
 | 
			
		||||
        __system_property_area_init();
 | 
			
		||||
 | 
			
		||||
        names = new char* [nprops];
 | 
			
		||||
        name_lens = new int[nprops];
 | 
			
		||||
        values = new char* [nprops];
 | 
			
		||||
        value_lens = new int[nprops];
 | 
			
		||||
 | 
			
		||||
        srandom(nprops);
 | 
			
		||||
 | 
			
		||||
        for (int i = 0; i < nprops; i++) {
 | 
			
		||||
            // Make sure the name has at least 10 characters to make
 | 
			
		||||
            // it very unlikely to generate the same random name.
 | 
			
		||||
            name_lens[i] = (random() % (PROP_NAME_MAX - 10)) + 10;
 | 
			
		||||
            names[i] = new char[PROP_NAME_MAX + 1];
 | 
			
		||||
            size_t prop_name_len = sizeof(prop_name_chars) - 1;
 | 
			
		||||
            for (int j = 0; j < name_lens[i]; j++) {
 | 
			
		||||
                if (j == 0 || names[i][j-1] == '.' || j == name_lens[i] - 1) {
 | 
			
		||||
                    // Certain values are not allowed:
 | 
			
		||||
                    // - Don't start name with '.'
 | 
			
		||||
                    // - Don't allow '.' to appear twice in a row
 | 
			
		||||
                    // - Don't allow the name to end with '.'
 | 
			
		||||
                    // This assumes that '.' is the last character in the
 | 
			
		||||
                    // array so that decrementing the length by one removes
 | 
			
		||||
                    // the value from the possible values.
 | 
			
		||||
                    prop_name_len--;
 | 
			
		||||
                }
 | 
			
		||||
                names[i][j] = prop_name_chars[random() % prop_name_len];
 | 
			
		||||
            }
 | 
			
		||||
            names[i][name_lens[i]] = 0;
 | 
			
		||||
 | 
			
		||||
            // Make sure the value contains at least 1 character.
 | 
			
		||||
            value_lens[i] = (random() % (PROP_VALUE_MAX - 1)) + 1;
 | 
			
		||||
            values[i] = new char[PROP_VALUE_MAX];
 | 
			
		||||
            for (int j = 0; j < value_lens[i]; j++) {
 | 
			
		||||
                values[i][j] = prop_name_chars[random() % (sizeof(prop_name_chars) - 1)];
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (__system_property_add(names[i], name_lens[i], values[i], value_lens[i]) < 0) {
 | 
			
		||||
                printf("Failed to add a property, terminating...\n");
 | 
			
		||||
                printf("%s = %.*s\n", names[i], value_lens[i], values[i]);
 | 
			
		||||
                exit(1);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        valid = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    valid = true;
 | 
			
		||||
  }
 | 
			
		||||
    ~LocalPropertyTestState() {
 | 
			
		||||
        if (!valid)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
  ~LocalPropertyTestState() {
 | 
			
		||||
    if (!valid)
 | 
			
		||||
      return;
 | 
			
		||||
        __system_property_area__ = old_pa;
 | 
			
		||||
 | 
			
		||||
    __system_property_area__ = old_pa;
 | 
			
		||||
        __system_property_set_filename(PROP_FILENAME);
 | 
			
		||||
        unlink(pa_filename.c_str());
 | 
			
		||||
        rmdir(pa_dirname.c_str());
 | 
			
		||||
 | 
			
		||||
    __system_property_set_filename(PROP_FILENAME);
 | 
			
		||||
    unlink(pa_filename.c_str());
 | 
			
		||||
    rmdir(pa_dirname.c_str());
 | 
			
		||||
 | 
			
		||||
    for (int i = 0; i < nprops; i++) {
 | 
			
		||||
      delete names[i];
 | 
			
		||||
      delete values[i];
 | 
			
		||||
        for (int i = 0; i < nprops; i++) {
 | 
			
		||||
            delete names[i];
 | 
			
		||||
            delete values[i];
 | 
			
		||||
        }
 | 
			
		||||
        delete[] names;
 | 
			
		||||
        delete[] name_lens;
 | 
			
		||||
        delete[] values;
 | 
			
		||||
        delete[] value_lens;
 | 
			
		||||
    }
 | 
			
		||||
    delete[] names;
 | 
			
		||||
    delete[] name_lens;
 | 
			
		||||
    delete[] values;
 | 
			
		||||
    delete[] value_lens;
 | 
			
		||||
  }
 | 
			
		||||
public:
 | 
			
		||||
  const int nprops;
 | 
			
		||||
  char** names;
 | 
			
		||||
  int* name_lens;
 | 
			
		||||
  char** values;
 | 
			
		||||
  int* value_lens;
 | 
			
		||||
  bool valid;
 | 
			
		||||
    const int nprops;
 | 
			
		||||
    char **names;
 | 
			
		||||
    int *name_lens;
 | 
			
		||||
    char **values;
 | 
			
		||||
    int *value_lens;
 | 
			
		||||
    bool valid;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
  std::string pa_dirname;
 | 
			
		||||
  std::string pa_filename;
 | 
			
		||||
  void* old_pa;
 | 
			
		||||
    std::string pa_dirname;
 | 
			
		||||
    std::string pa_filename;
 | 
			
		||||
    void *old_pa;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
BENCHMARK_WITH_ARG(BM_property_get, int)->TEST_NUM_PROPS;
 | 
			
		||||
void BM_property_get::Run(int iters, int nprops) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
static void BM_property_get(int iters, int nprops)
 | 
			
		||||
{
 | 
			
		||||
    StopBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  LocalPropertyTestState pa(nprops);
 | 
			
		||||
  char value[PROP_VALUE_MAX];
 | 
			
		||||
    LocalPropertyTestState pa(nprops);
 | 
			
		||||
    char value[PROP_VALUE_MAX];
 | 
			
		||||
 | 
			
		||||
  if (!pa.valid)
 | 
			
		||||
    return;
 | 
			
		||||
    if (!pa.valid)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
  srandom(iters * nprops);
 | 
			
		||||
    srandom(iters * nprops);
 | 
			
		||||
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
    StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; i++) {
 | 
			
		||||
    __system_property_get(pa.names[random() % nprops], value);
 | 
			
		||||
  }
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
    for (int i = 0; i < iters; i++) {
 | 
			
		||||
        __system_property_get(pa.names[random() % nprops], value);
 | 
			
		||||
    }
 | 
			
		||||
    StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_property_get)->TEST_NUM_PROPS;
 | 
			
		||||
 | 
			
		||||
BENCHMARK_WITH_ARG(BM_property_find, int)->TEST_NUM_PROPS;
 | 
			
		||||
void BM_property_find::Run(int iters, int nprops) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
static void BM_property_find(int iters, int nprops)
 | 
			
		||||
{
 | 
			
		||||
    StopBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  LocalPropertyTestState pa(nprops);
 | 
			
		||||
    LocalPropertyTestState pa(nprops);
 | 
			
		||||
 | 
			
		||||
  if (!pa.valid)
 | 
			
		||||
    return;
 | 
			
		||||
    if (!pa.valid)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
  srandom(iters * nprops);
 | 
			
		||||
    srandom(iters * nprops);
 | 
			
		||||
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
    StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; i++) {
 | 
			
		||||
    __system_property_find(pa.names[random() % nprops]);
 | 
			
		||||
  }
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
    for (int i = 0; i < iters; i++) {
 | 
			
		||||
        __system_property_find(pa.names[random() % nprops]);
 | 
			
		||||
    }
 | 
			
		||||
    StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_property_find)->TEST_NUM_PROPS;
 | 
			
		||||
 | 
			
		||||
BENCHMARK_WITH_ARG(BM_property_read, int)->TEST_NUM_PROPS;
 | 
			
		||||
void BM_property_read::Run(int iters, int nprops) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
static void BM_property_read(int iters, int nprops)
 | 
			
		||||
{
 | 
			
		||||
    StopBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  LocalPropertyTestState pa(nprops);
 | 
			
		||||
    LocalPropertyTestState pa(nprops);
 | 
			
		||||
 | 
			
		||||
  if (!pa.valid)
 | 
			
		||||
    return;
 | 
			
		||||
    if (!pa.valid)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
  srandom(iters * nprops);
 | 
			
		||||
  const prop_info** pinfo = new const prop_info*[iters];
 | 
			
		||||
  char propvalue[PROP_VALUE_MAX];
 | 
			
		||||
    srandom(iters * nprops);
 | 
			
		||||
    const prop_info** pinfo = new const prop_info*[iters];
 | 
			
		||||
    char propvalue[PROP_VALUE_MAX];
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; i++) {
 | 
			
		||||
    pinfo[i] = __system_property_find(pa.names[random() % nprops]);
 | 
			
		||||
  }
 | 
			
		||||
    for (int i = 0; i < iters; i++) {
 | 
			
		||||
        pinfo[i] = __system_property_find(pa.names[random() % nprops]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
  for (int i = 0; i < iters; i++) {
 | 
			
		||||
    __system_property_read(pinfo[i], 0, propvalue);
 | 
			
		||||
  }
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
    StartBenchmarkTiming();
 | 
			
		||||
    for (int i = 0; i < iters; i++) {
 | 
			
		||||
        __system_property_read(pinfo[i], 0, propvalue);
 | 
			
		||||
    }
 | 
			
		||||
    StopBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  delete[] pinfo;
 | 
			
		||||
    delete[] pinfo;
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_property_read)->TEST_NUM_PROPS;
 | 
			
		||||
 | 
			
		||||
BENCHMARK_WITH_ARG(BM_property_serial, int)->TEST_NUM_PROPS;
 | 
			
		||||
void BM_property_serial::Run(int iters, int nprops) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
static void BM_property_serial(int iters, int nprops)
 | 
			
		||||
{
 | 
			
		||||
    StopBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  LocalPropertyTestState pa(nprops);
 | 
			
		||||
    LocalPropertyTestState pa(nprops);
 | 
			
		||||
 | 
			
		||||
  if (!pa.valid)
 | 
			
		||||
    return;
 | 
			
		||||
    if (!pa.valid)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
  srandom(iters * nprops);
 | 
			
		||||
  const prop_info** pinfo = new const prop_info*[iters];
 | 
			
		||||
    srandom(iters * nprops);
 | 
			
		||||
    const prop_info** pinfo = new const prop_info*[iters];
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; i++) {
 | 
			
		||||
    pinfo[i] = __system_property_find(pa.names[random() % nprops]);
 | 
			
		||||
  }
 | 
			
		||||
    for (int i = 0; i < iters; i++) {
 | 
			
		||||
        pinfo[i] = __system_property_find(pa.names[random() % nprops]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
  for (int i = 0; i < iters; i++) {
 | 
			
		||||
    __system_property_serial(pinfo[i]);
 | 
			
		||||
  }
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
    StartBenchmarkTiming();
 | 
			
		||||
    for (int i = 0; i < iters; i++) {
 | 
			
		||||
        __system_property_serial(pinfo[i]);
 | 
			
		||||
    }
 | 
			
		||||
    StopBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  delete[] pinfo;
 | 
			
		||||
    delete[] pinfo;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif  // __BIONIC__
 | 
			
		||||
BENCHMARK(BM_property_serial)->TEST_NUM_PROPS;
 | 
			
		||||
 
 | 
			
		||||
@@ -14,15 +14,14 @@
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
#include "benchmark.h"
 | 
			
		||||
 | 
			
		||||
#include <benchmark/Benchmark.h>
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
 | 
			
		||||
// Stop GCC optimizing out our pure function.
 | 
			
		||||
/* Must not be static! */ pthread_t (*pthread_self_fp)() = pthread_self;
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_pthread_self);
 | 
			
		||||
void BM_pthread_self::Run(int iters) {
 | 
			
		||||
static void BM_pthread_self(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
@@ -31,9 +30,9 @@ void BM_pthread_self::Run(int iters) {
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_pthread_self);
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_pthread_getspecific);
 | 
			
		||||
void BM_pthread_getspecific::Run(int iters) {
 | 
			
		||||
static void BM_pthread_getspecific(int iters) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  pthread_key_t key;
 | 
			
		||||
  pthread_key_create(&key, NULL);
 | 
			
		||||
@@ -46,27 +45,12 @@ void BM_pthread_getspecific::Run(int iters) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  pthread_key_delete(key);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_pthread_setspecific);
 | 
			
		||||
void BM_pthread_setspecific::Run(int iters) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  pthread_key_t key;
 | 
			
		||||
  pthread_key_create(&key, NULL);
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    pthread_setspecific(key, NULL);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  pthread_key_delete(key);
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_pthread_getspecific);
 | 
			
		||||
 | 
			
		||||
static void DummyPthreadOnceInitFunction() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_pthread_once);
 | 
			
		||||
void BM_pthread_once::Run(int iters) {
 | 
			
		||||
static void BM_pthread_once(int iters) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  pthread_once_t once = PTHREAD_ONCE_INIT;
 | 
			
		||||
  pthread_once(&once, DummyPthreadOnceInitFunction);
 | 
			
		||||
@@ -78,9 +62,9 @@ void BM_pthread_once::Run(int iters) {
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_pthread_once);
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_pthread_mutex_lock);
 | 
			
		||||
void BM_pthread_mutex_lock::Run(int iters) {
 | 
			
		||||
static void BM_pthread_mutex_lock(int iters) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
@@ -92,11 +76,11 @@ void BM_pthread_mutex_lock::Run(int iters) {
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_pthread_mutex_lock);
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_pthread_mutex_lock_ERRORCHECK);
 | 
			
		||||
void BM_pthread_mutex_lock_ERRORCHECK::Run(int iters) {
 | 
			
		||||
static void BM_pthread_mutex_lock_ERRORCHECK(int iters) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  pthread_mutex_t mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
 | 
			
		||||
  pthread_mutex_t mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER;
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
@@ -106,11 +90,11 @@ void BM_pthread_mutex_lock_ERRORCHECK::Run(int iters) {
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_pthread_mutex_lock_ERRORCHECK);
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_pthread_mutex_lock_RECURSIVE);
 | 
			
		||||
void BM_pthread_mutex_lock_RECURSIVE::Run(int iters) {
 | 
			
		||||
static void BM_pthread_mutex_lock_RECURSIVE(int iters) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
 | 
			
		||||
  pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER;
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
@@ -120,114 +104,4 @@ void BM_pthread_mutex_lock_RECURSIVE::Run(int iters) {
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_pthread_rwlock_read);
 | 
			
		||||
void BM_pthread_rwlock_read::Run(int iters) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  pthread_rwlock_t lock;
 | 
			
		||||
  pthread_rwlock_init(&lock, NULL);
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    pthread_rwlock_rdlock(&lock);
 | 
			
		||||
    pthread_rwlock_unlock(&lock);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  pthread_rwlock_destroy(&lock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_pthread_rwlock_write);
 | 
			
		||||
void BM_pthread_rwlock_write::Run(int iters) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  pthread_rwlock_t lock;
 | 
			
		||||
  pthread_rwlock_init(&lock, NULL);
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    pthread_rwlock_wrlock(&lock);
 | 
			
		||||
    pthread_rwlock_unlock(&lock);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  pthread_rwlock_destroy(&lock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void* IdleThread(void*) {
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_pthread_create);
 | 
			
		||||
void BM_pthread_create::Run(int iters) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  pthread_t thread;
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    StartBenchmarkTiming();
 | 
			
		||||
    pthread_create(&thread, NULL, IdleThread, NULL);
 | 
			
		||||
    StopBenchmarkTiming();
 | 
			
		||||
    pthread_join(thread, NULL);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void* RunThread(void* arg) {
 | 
			
		||||
  ::testing::Benchmark* benchmark = reinterpret_cast<::testing::Benchmark*>(arg);
 | 
			
		||||
  benchmark->StopBenchmarkTiming();
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_pthread_create_and_run);
 | 
			
		||||
void BM_pthread_create_and_run::Run(int iters) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  pthread_t thread;
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    StartBenchmarkTiming();
 | 
			
		||||
    pthread_create(&thread, NULL, RunThread, this);
 | 
			
		||||
    pthread_join(thread, NULL);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void* ExitThread(void* arg) {
 | 
			
		||||
  ::testing::Benchmark* benchmark = reinterpret_cast<::testing::Benchmark*>(arg);
 | 
			
		||||
  benchmark->StartBenchmarkTiming();
 | 
			
		||||
  pthread_exit(NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_pthread_exit_and_join);
 | 
			
		||||
void BM_pthread_exit_and_join::Run(int iters) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  pthread_t thread;
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    pthread_create(&thread, NULL, ExitThread, this);
 | 
			
		||||
    pthread_join(thread, NULL);
 | 
			
		||||
    StopBenchmarkTiming();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_pthread_key_create);
 | 
			
		||||
void BM_pthread_key_create::Run(int iters) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  pthread_key_t key;
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    StartBenchmarkTiming();
 | 
			
		||||
    pthread_key_create(&key, NULL);
 | 
			
		||||
    StopBenchmarkTiming();
 | 
			
		||||
    pthread_key_delete(key);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_pthread_key_delete);
 | 
			
		||||
void BM_pthread_key_delete::Run(int iters) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  pthread_key_t key;
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    pthread_key_create(&key, NULL);
 | 
			
		||||
    StartBenchmarkTiming();
 | 
			
		||||
    pthread_key_delete(key);
 | 
			
		||||
    StopBenchmarkTiming();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_pthread_mutex_lock_RECURSIVE);
 | 
			
		||||
 
 | 
			
		||||
@@ -14,15 +14,11 @@
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
#include "benchmark.h"
 | 
			
		||||
 | 
			
		||||
#include <semaphore.h>
 | 
			
		||||
#include <stdatomic.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
#include <benchmark/Benchmark.h>
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_semaphore_sem_getvalue);
 | 
			
		||||
void BM_semaphore_sem_getvalue::Run(int iters) {
 | 
			
		||||
static void BM_semaphore_sem_getvalue(int iters) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  sem_t semaphore;
 | 
			
		||||
  sem_init(&semaphore, 1, 1);
 | 
			
		||||
@@ -35,9 +31,9 @@ void BM_semaphore_sem_getvalue::Run(int iters) {
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_semaphore_sem_getvalue);
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_semaphore_sem_wait_sem_post);
 | 
			
		||||
void BM_semaphore_sem_wait_sem_post::Run(int iters) {
 | 
			
		||||
static void BM_semaphore_sem_wait_sem_post(int iters) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  sem_t semaphore;
 | 
			
		||||
  sem_init(&semaphore, 1, 1);
 | 
			
		||||
@@ -50,94 +46,4 @@ void BM_semaphore_sem_wait_sem_post::Run(int iters) {
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 *    This test reports the overhead of the underlying futex wake syscall on
 | 
			
		||||
 * the producer. It does not report the overhead from issuing the wake to the
 | 
			
		||||
 * point where the posted consumer thread wakes up. It suffers from
 | 
			
		||||
 * clock_gettime syscall overhead. Lock the CPU speed for consistent results
 | 
			
		||||
 * as we may not reach >50% cpu utilization.
 | 
			
		||||
 *
 | 
			
		||||
 *    We will run a background thread that catches the sem_post wakeup and
 | 
			
		||||
 * loops immediately returning back to sleep in sem_wait for the next one. This
 | 
			
		||||
 * thread is run with policy SCHED_OTHER (normal policy), a middle policy.
 | 
			
		||||
 *
 | 
			
		||||
 *    The primary thread will run at SCHED_IDLE (lowest priority policy) when
 | 
			
		||||
 * monitoring the background thread to detect when it hits sem_wait sleep. It
 | 
			
		||||
 * will do so with no clock running. Once we are ready, we will switch to
 | 
			
		||||
 * SCHED_FIFO (highest priority policy) to time the act of running sem_post
 | 
			
		||||
 * with the benchmark clock running. This ensures nothing else in the system
 | 
			
		||||
 * can preempt our timed activity, including the background thread. We are
 | 
			
		||||
 * also protected with the scheduling policy of letting a process hit a
 | 
			
		||||
 * resource limit rather than get hit with a context switch.
 | 
			
		||||
 *
 | 
			
		||||
 *    The background thread will start executing either on another CPU, or
 | 
			
		||||
 * after we back down from SCHED_FIFO, but certainly not in the context of
 | 
			
		||||
 * the timing of the sem_post.
 | 
			
		||||
 */
 | 
			
		||||
static atomic_int BM_semaphore_sem_post_running;
 | 
			
		||||
 | 
			
		||||
static void *BM_semaphore_sem_post_start_thread(void *obj) {
 | 
			
		||||
    sem_t *semaphore = reinterpret_cast<sem_t *>(obj);
 | 
			
		||||
 | 
			
		||||
    while ((BM_semaphore_sem_post_running > 0) && !sem_wait(semaphore)) {
 | 
			
		||||
        ;
 | 
			
		||||
    }
 | 
			
		||||
    BM_semaphore_sem_post_running = -1;
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_semaphore_sem_post);
 | 
			
		||||
void BM_semaphore_sem_post::Run(int iters) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  sem_t semaphore;
 | 
			
		||||
  sem_init(&semaphore, 0, 0);
 | 
			
		||||
 | 
			
		||||
  pthread_attr_t attr;
 | 
			
		||||
  pthread_attr_init(&attr);
 | 
			
		||||
  BM_semaphore_sem_post_running = 1;
 | 
			
		||||
  struct sched_param param = { 0, };
 | 
			
		||||
  pthread_attr_setschedparam(&attr, ¶m);
 | 
			
		||||
  pthread_attr_setschedpolicy(&attr, SCHED_OTHER);
 | 
			
		||||
  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 | 
			
		||||
  pthread_t pthread;
 | 
			
		||||
  pthread_create(&pthread, &attr, BM_semaphore_sem_post_start_thread, &semaphore);
 | 
			
		||||
  pthread_attr_destroy(&attr);
 | 
			
		||||
 | 
			
		||||
  sched_setscheduler((pid_t)0, SCHED_IDLE, ¶m);
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    int trys = 3, dummy = 0;
 | 
			
		||||
    do {
 | 
			
		||||
      if (BM_semaphore_sem_post_running < 0) {
 | 
			
		||||
        sched_setscheduler((pid_t)0, SCHED_OTHER, ¶m);
 | 
			
		||||
        fprintf(stderr, "BM_semaphore_sem_post: start_thread died unexpectedly\n");
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      sched_yield();
 | 
			
		||||
      sem_getvalue(&semaphore, &dummy);
 | 
			
		||||
      if (dummy < 0) {  // POSIX.1-2001 possibility 1
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      if (dummy == 0) { // POSIX.1-2001 possibility 2
 | 
			
		||||
        --trys;
 | 
			
		||||
      }
 | 
			
		||||
    } while (trys);
 | 
			
		||||
    param.sched_priority = 1;
 | 
			
		||||
    sched_setscheduler((pid_t)0, SCHED_FIFO, ¶m);
 | 
			
		||||
    StartBenchmarkTiming();
 | 
			
		||||
    sem_post(&semaphore);
 | 
			
		||||
    StopBenchmarkTiming(); // Remember to subtract clock syscall overhead
 | 
			
		||||
    param.sched_priority = 0;
 | 
			
		||||
    sched_setscheduler((pid_t)0, SCHED_IDLE, ¶m);
 | 
			
		||||
  }
 | 
			
		||||
  sched_setscheduler((pid_t)0, SCHED_OTHER, ¶m);
 | 
			
		||||
 | 
			
		||||
  if (BM_semaphore_sem_post_running > 0) {
 | 
			
		||||
    BM_semaphore_sem_post_running = 0;
 | 
			
		||||
  }
 | 
			
		||||
  do {
 | 
			
		||||
    sem_post(&semaphore);
 | 
			
		||||
    sched_yield();
 | 
			
		||||
  } while (!BM_semaphore_sem_post_running);
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_semaphore_sem_wait_sem_post);
 | 
			
		||||
 
 | 
			
		||||
@@ -14,10 +14,9 @@
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdio_ext.h>
 | 
			
		||||
#include "benchmark.h"
 | 
			
		||||
 | 
			
		||||
#include <benchmark/Benchmark.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
#define KB 1024
 | 
			
		||||
#define MB 1024*KB
 | 
			
		||||
@@ -26,68 +25,37 @@
 | 
			
		||||
    Arg(1)->Arg(2)->Arg(3)->Arg(4)->Arg(8)->Arg(16)->Arg(32)->Arg(64)->Arg(512)-> \
 | 
			
		||||
    Arg(1*KB)->Arg(4*KB)->Arg(8*KB)->Arg(16*KB)->Arg(64*KB)
 | 
			
		||||
 | 
			
		||||
template <typename Fn>
 | 
			
		||||
void ReadWriteTest(::testing::Benchmark* benchmark, int iters, int chunk_size, Fn f, bool buffered) {
 | 
			
		||||
  benchmark->StopBenchmarkTiming();
 | 
			
		||||
static void BM_stdio_fread(int iters, int chunk_size) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  FILE* fp = fopen("/dev/zero", "rw");
 | 
			
		||||
  __fsetlocking(fp, FSETLOCKING_BYCALLER);
 | 
			
		||||
  char* buf = new char[chunk_size];
 | 
			
		||||
  benchmark->StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  if (!buffered) {
 | 
			
		||||
    setvbuf(fp, 0, _IONBF, 0);
 | 
			
		||||
  }
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    f(buf, chunk_size, 1, fp);
 | 
			
		||||
    fread(buf, chunk_size, 1, fp);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  benchmark->StopBenchmarkTiming();
 | 
			
		||||
  benchmark->SetBenchmarkBytesProcessed(int64_t(iters) * int64_t(chunk_size));
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  SetBenchmarkBytesProcessed(int64_t(iters) * int64_t(chunk_size));
 | 
			
		||||
  delete[] buf;
 | 
			
		||||
  fclose(fp);
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_stdio_fread)->AT_COMMON_SIZES;
 | 
			
		||||
 | 
			
		||||
BENCHMARK_WITH_ARG(BM_stdio_fread, int)->AT_COMMON_SIZES;
 | 
			
		||||
void BM_stdio_fread::Run(int iters, int chunk_size) {
 | 
			
		||||
  ReadWriteTest(this, iters, chunk_size, fread, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_WITH_ARG(BM_stdio_fwrite, int)->AT_COMMON_SIZES;
 | 
			
		||||
void BM_stdio_fwrite::Run(int iters, int chunk_size) {
 | 
			
		||||
  ReadWriteTest(this, iters, chunk_size, fwrite, true);
 | 
			
		||||
}
 | 
			
		||||
static void BM_stdio_fwrite(int iters, int chunk_size) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  FILE* fp = fopen("/dev/zero", "rw");
 | 
			
		||||
  char* buf = new char[chunk_size];
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
BENCHMARK_WITH_ARG(BM_stdio_fread_unbuffered, int)->AT_COMMON_SIZES;
 | 
			
		||||
void BM_stdio_fread_unbuffered::Run(int iters, int chunk_size) {
 | 
			
		||||
  ReadWriteTest(this, iters, chunk_size, fread, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_WITH_ARG(BM_stdio_fwrite_unbuffered, int)->AT_COMMON_SIZES;
 | 
			
		||||
void BM_stdio_fwrite_unbuffered::Run(int iters, int chunk_size) {
 | 
			
		||||
  ReadWriteTest(this, iters, chunk_size, fwrite, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void FopenFgetsFclose(int iters, bool no_locking) {
 | 
			
		||||
  char buf[1024];
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    FILE* fp = fopen("/proc/version", "re");
 | 
			
		||||
    if (no_locking) __fsetlocking(fp, FSETLOCKING_BYCALLER);
 | 
			
		||||
    fgets(buf, sizeof(buf), fp);
 | 
			
		||||
    fclose(fp);
 | 
			
		||||
      fwrite(buf, chunk_size, 1, fp);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_stdio_fopen_fgets_fclose_locking);
 | 
			
		||||
void BM_stdio_fopen_fgets_fclose_locking::Run(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
  FopenFgetsFclose(iters, false);
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_stdio_fopen_fgets_fclose_no_locking);
 | 
			
		||||
void BM_stdio_fopen_fgets_fclose_no_locking::Run(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
  FopenFgetsFclose(iters, true);
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  SetBenchmarkBytesProcessed(int64_t(iters) * int64_t(chunk_size));
 | 
			
		||||
  delete[] buf;
 | 
			
		||||
  fclose(fp);
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_stdio_fwrite)->AT_COMMON_SIZES;
 | 
			
		||||
 
 | 
			
		||||
@@ -14,10 +14,9 @@
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include "benchmark.h"
 | 
			
		||||
 | 
			
		||||
#include <benchmark/Benchmark.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#define KB 1024
 | 
			
		||||
#define MB 1024*KB
 | 
			
		||||
@@ -27,8 +26,7 @@
 | 
			
		||||
 | 
			
		||||
// TODO: test unaligned operation too? (currently everything will be 8-byte aligned by malloc.)
 | 
			
		||||
 | 
			
		||||
BENCHMARK_WITH_ARG(BM_string_memcmp, int)->AT_COMMON_SIZES;
 | 
			
		||||
void BM_string_memcmp::Run(int iters, int nbytes) {
 | 
			
		||||
static void BM_string_memcmp(int iters, int nbytes) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  char* src = new char[nbytes]; char* dst = new char[nbytes];
 | 
			
		||||
  memset(src, 'x', nbytes);
 | 
			
		||||
@@ -41,13 +39,13 @@ void BM_string_memcmp::Run(int iters, int nbytes) {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  SetBenchmarkBytesProcessed(uint64_t(iters) * uint64_t(nbytes));
 | 
			
		||||
  SetBenchmarkBytesProcessed(int64_t(iters) * int64_t(nbytes));
 | 
			
		||||
  delete[] src;
 | 
			
		||||
  delete[] dst;
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_string_memcmp)->AT_COMMON_SIZES;
 | 
			
		||||
 | 
			
		||||
BENCHMARK_WITH_ARG(BM_string_memcpy, int)->AT_COMMON_SIZES;
 | 
			
		||||
void BM_string_memcpy::Run(int iters, int nbytes) {
 | 
			
		||||
static void BM_string_memcpy(int iters, int nbytes) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  char* src = new char[nbytes]; char* dst = new char[nbytes];
 | 
			
		||||
  memset(src, 'x', nbytes);
 | 
			
		||||
@@ -58,13 +56,13 @@ void BM_string_memcpy::Run(int iters, int nbytes) {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  SetBenchmarkBytesProcessed(uint64_t(iters) * uint64_t(nbytes));
 | 
			
		||||
  SetBenchmarkBytesProcessed(int64_t(iters) * int64_t(nbytes));
 | 
			
		||||
  delete[] src;
 | 
			
		||||
  delete[] dst;
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_string_memcpy)->AT_COMMON_SIZES;
 | 
			
		||||
 | 
			
		||||
BENCHMARK_WITH_ARG(BM_string_memmove, int)->AT_COMMON_SIZES;
 | 
			
		||||
void BM_string_memmove::Run(int iters, int nbytes) {
 | 
			
		||||
static void BM_string_memmove(int iters, int nbytes) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  char* buf = new char[nbytes + 64];
 | 
			
		||||
  memset(buf, 'x', nbytes + 64);
 | 
			
		||||
@@ -75,12 +73,12 @@ void BM_string_memmove::Run(int iters, int nbytes) {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  SetBenchmarkBytesProcessed(uint64_t(iters) * uint64_t(nbytes));
 | 
			
		||||
  SetBenchmarkBytesProcessed(int64_t(iters) * int64_t(nbytes));
 | 
			
		||||
  delete[] buf;
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_string_memmove)->AT_COMMON_SIZES;
 | 
			
		||||
 | 
			
		||||
BENCHMARK_WITH_ARG(BM_string_memset, int)->AT_COMMON_SIZES;
 | 
			
		||||
void BM_string_memset::Run(int iters, int nbytes) {
 | 
			
		||||
static void BM_string_memset(int iters, int nbytes) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  char* dst = new char[nbytes];
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
@@ -90,12 +88,12 @@ void BM_string_memset::Run(int iters, int nbytes) {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  SetBenchmarkBytesProcessed(uint64_t(iters) * uint64_t(nbytes));
 | 
			
		||||
  SetBenchmarkBytesProcessed(int64_t(iters) * int64_t(nbytes));
 | 
			
		||||
  delete[] dst;
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_string_memset)->AT_COMMON_SIZES;
 | 
			
		||||
 | 
			
		||||
BENCHMARK_WITH_ARG(BM_string_strlen, int)->AT_COMMON_SIZES;
 | 
			
		||||
void BM_string_strlen::Run(int iters, int nbytes) {
 | 
			
		||||
static void BM_string_strlen(int iters, int nbytes) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  char* s = new char[nbytes];
 | 
			
		||||
  memset(s, 'x', nbytes);
 | 
			
		||||
@@ -108,6 +106,7 @@ void BM_string_strlen::Run(int iters, int nbytes) {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  SetBenchmarkBytesProcessed(uint64_t(iters) * uint64_t(nbytes));
 | 
			
		||||
  SetBenchmarkBytesProcessed(int64_t(iters) * int64_t(nbytes));
 | 
			
		||||
  delete[] s;
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_string_strlen)->AT_COMMON_SIZES;
 | 
			
		||||
 
 | 
			
		||||
@@ -14,14 +14,12 @@
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "benchmark.h"
 | 
			
		||||
 | 
			
		||||
#include <sys/syscall.h>
 | 
			
		||||
#include <sys/time.h>
 | 
			
		||||
#include <time.h>
 | 
			
		||||
 | 
			
		||||
#include <benchmark/Benchmark.h>
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_time_clock_gettime);
 | 
			
		||||
void BM_time_clock_gettime::Run(int iters) {
 | 
			
		||||
static void BM_time_clock_gettime(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  timespec t;
 | 
			
		||||
@@ -31,9 +29,9 @@ void BM_time_clock_gettime::Run(int iters) {
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_time_clock_gettime);
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_time_clock_gettime_syscall);
 | 
			
		||||
void BM_time_clock_gettime_syscall::Run(int iters) {
 | 
			
		||||
static void BM_time_clock_gettime_syscall(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  timespec t;
 | 
			
		||||
@@ -43,9 +41,9 @@ void BM_time_clock_gettime_syscall::Run(int iters) {
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_time_clock_gettime_syscall);
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_time_gettimeofday);
 | 
			
		||||
void BM_time_gettimeofday::Run(int iters) {
 | 
			
		||||
static void BM_time_gettimeofday(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  timeval tv;
 | 
			
		||||
@@ -55,9 +53,9 @@ void BM_time_gettimeofday::Run(int iters) {
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_time_gettimeofday);
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_time_gettimeofday_syscall);
 | 
			
		||||
void BM_time_gettimeofday_syscall::Run(int iters) {
 | 
			
		||||
static void BM_time_gettimeofday_syscall(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  timeval tv;
 | 
			
		||||
@@ -67,9 +65,9 @@ void BM_time_gettimeofday_syscall::Run(int iters) {
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_time_gettimeofday_syscall);
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_time_time);
 | 
			
		||||
void BM_time_time::Run(int iters) {
 | 
			
		||||
static void BM_time_time(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
@@ -78,3 +76,4 @@ void BM_time_time::Run(int iters) {
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_time_time);
 | 
			
		||||
 
 | 
			
		||||
@@ -14,13 +14,12 @@
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "benchmark.h"
 | 
			
		||||
 | 
			
		||||
#include <sys/syscall.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
#include <benchmark/Benchmark.h>
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_unistd_getpid);
 | 
			
		||||
void BM_unistd_getpid::Run(int iters) {
 | 
			
		||||
static void BM_unistd_getpid(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
@@ -29,9 +28,9 @@ void BM_unistd_getpid::Run(int iters) {
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_unistd_getpid);
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_unistd_getpid_syscall);
 | 
			
		||||
void BM_unistd_getpid_syscall::Run(int iters) {
 | 
			
		||||
static void BM_unistd_getpid_syscall(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
@@ -40,14 +39,12 @@ void BM_unistd_getpid_syscall::Run(int iters) {
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if defined(__BIONIC__)
 | 
			
		||||
BENCHMARK(BM_unistd_getpid_syscall);
 | 
			
		||||
 | 
			
		||||
// Stop GCC optimizing out our pure function.
 | 
			
		||||
/* Must not be static! */ pid_t (*gettid_fp)() = gettid;
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_unistd_gettid);
 | 
			
		||||
void BM_unistd_gettid::Run(int iters) {
 | 
			
		||||
static void BM_unistd_gettid(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
@@ -56,11 +53,9 @@ void BM_unistd_gettid::Run(int iters) {
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_unistd_gettid);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_unistd_gettid_syscall);
 | 
			
		||||
void BM_unistd_gettid_syscall::Run(int iters) {
 | 
			
		||||
static void BM_unistd_gettid_syscall(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
@@ -69,3 +64,4 @@ void BM_unistd_gettid_syscall::Run(int iters) {
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_unistd_gettid_syscall);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,81 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2012 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * 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 <inttypes.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
#include "utils.h"
 | 
			
		||||
 | 
			
		||||
int Round(int n) {
 | 
			
		||||
  int base = 1;
 | 
			
		||||
  while (base*10 < n) {
 | 
			
		||||
    base *= 10;
 | 
			
		||||
  }
 | 
			
		||||
  if (n < 2*base) {
 | 
			
		||||
    return 2*base;
 | 
			
		||||
  }
 | 
			
		||||
  if (n < 5*base) {
 | 
			
		||||
    return 5*base;
 | 
			
		||||
  }
 | 
			
		||||
  return 10*base;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Similar to the code in art, but supporting both binary and decimal prefixes.
 | 
			
		||||
std::string PrettyInt(long value, size_t base) {
 | 
			
		||||
  if (base != 2 && base != 10) abort();
 | 
			
		||||
 | 
			
		||||
  uint64_t count = static_cast<uint64_t>(value);
 | 
			
		||||
  bool negative_number = false;
 | 
			
		||||
  if (value < 0) {
 | 
			
		||||
    negative_number = true;
 | 
			
		||||
    count = static_cast<uint64_t>(-value);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // The byte thresholds at which we display amounts. A count is displayed
 | 
			
		||||
  // in unit U when kUnitThresholds[U] <= bytes < kUnitThresholds[U+1].
 | 
			
		||||
  static const uint64_t kUnitThresholds2[] = {
 | 
			
		||||
    1024*1024*1024 /* Gi */, 2*1024*1024 /* Mi */, 3*1024 /* Ki */, 0,
 | 
			
		||||
  };
 | 
			
		||||
  static const uint64_t kUnitThresholds10[] = {
 | 
			
		||||
    1000*1000*1000 /* G */, 2*1000*1000 /* M */, 3*1000 /* k */, 0,
 | 
			
		||||
  };
 | 
			
		||||
  static const uint64_t kAmountPerUnit2[] = { 1024*1024*1024, 1024*1024, 1024, 1 };
 | 
			
		||||
  static const uint64_t kAmountPerUnit10[] = { 1000*1000*1000, 1000*1000, 1000, 1 };
 | 
			
		||||
  static const char* const kUnitStrings2[] = { "Gi", "Mi", "Ki", "" };
 | 
			
		||||
  static const char* const kUnitStrings10[] = { "G", "M", "k", "" };
 | 
			
		||||
 | 
			
		||||
  // Which set are we using?
 | 
			
		||||
  const uint64_t* kUnitThresholds = ((base == 2) ? kUnitThresholds2 : kUnitThresholds10);
 | 
			
		||||
  const uint64_t* kAmountPerUnit = ((base == 2) ? kAmountPerUnit2 : kAmountPerUnit10);
 | 
			
		||||
  const char* const* kUnitStrings = ((base == 2) ? kUnitStrings2 : kUnitStrings10);
 | 
			
		||||
 | 
			
		||||
  size_t i = 0;
 | 
			
		||||
  for (; kUnitThresholds[i] != 0; ++i) {
 | 
			
		||||
    if (count >= kUnitThresholds[i]) {
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  char* s = NULL;
 | 
			
		||||
  asprintf(&s, "%s%" PRId64 "%s", (negative_number ? "-" : ""),
 | 
			
		||||
           count / kAmountPerUnit[i], kUnitStrings[i]);
 | 
			
		||||
  std::string result(s);
 | 
			
		||||
  free(s);
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,26 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2012 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * 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 BENCHMARKS_UTILS_H
 | 
			
		||||
#define BENCHMARKS_UTILS_H
 | 
			
		||||
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
int Round(int n);
 | 
			
		||||
std::string PrettyInt(long value, size_t base);
 | 
			
		||||
 | 
			
		||||
#endif  // BENCHMARKS_UTILS_H
 | 
			
		||||
@@ -1,44 +0,0 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2014 The Android Open Source Project
 | 
			
		||||
#
 | 
			
		||||
# 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 once
 | 
			
		||||
ifneq ($(bionic_run_on_host_mk_included),true)
 | 
			
		||||
bionic_run_on_host_mk_included:=true
 | 
			
		||||
 | 
			
		||||
ifneq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),arm mips x86))
 | 
			
		||||
LINKER = linker64
 | 
			
		||||
else
 | 
			
		||||
LINKER = linker
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),x86 x86_64))
 | 
			
		||||
# gtest needs ANDROID_DATA/local/tmp for death test output.
 | 
			
		||||
# Make sure to create ANDROID_DATA/local/tmp if doesn't exist.
 | 
			
		||||
# bionic itself should always work relative to ANDROID_DATA or ANDROID_ROOT.
 | 
			
		||||
bionic-prepare-run-on-host: $(TARGET_OUT_EXECUTABLES)/$(LINKER) $(TARGET_OUT)/etc/hosts $(TARGET_OUT_EXECUTABLES)/sh
 | 
			
		||||
	if [ ! -d /system ]; then \
 | 
			
		||||
	  echo "Attempting to create /system"; \
 | 
			
		||||
	  sudo mkdir -p -m 0777 /system; \
 | 
			
		||||
	fi
 | 
			
		||||
	mkdir -p $(TARGET_OUT_DATA)/local/tmp
 | 
			
		||||
	ln -fs `realpath $(TARGET_OUT)/bin` /system/
 | 
			
		||||
	ln -fs `realpath $(TARGET_OUT)/etc` /system/
 | 
			
		||||
	ln -fs `realpath $(TARGET_OUT)/lib` /system/
 | 
			
		||||
	if [ -d "$(TARGET_OUT)/lib64" ]; then \
 | 
			
		||||
	  ln -fs `realpath $(TARGET_OUT)/lib64` /system/; \
 | 
			
		||||
	fi
 | 
			
		||||
endif
 | 
			
		||||
endif
 | 
			
		||||
							
								
								
									
										599
									
								
								libc/Android.mk
									
									
									
									
									
								
							
							
						
						
									
										599
									
								
								libc/Android.mk
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										444
									
								
								libc/NOTICE
									
									
									
									
									
								
							
							
						
						
									
										444
									
								
								libc/NOTICE
									
									
									
									
									
								
							@@ -307,6 +307,34 @@ SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (C) 2008-2010 The Android Open Source Project
 | 
			
		||||
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.
 | 
			
		||||
 | 
			
		||||
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.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (C) 2009 The Android Open Source Project
 | 
			
		||||
 | 
			
		||||
Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
@@ -426,6 +454,22 @@ Android adaptation and tweak by Jim Huang <jserv@0xlab.org>.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (C) 2011 The Android Open Source Project
 | 
			
		||||
 | 
			
		||||
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) 2011 The Android Open Source Project
 | 
			
		||||
All rights reserved.
 | 
			
		||||
 | 
			
		||||
@@ -644,50 +688,6 @@ SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (C) 2015 The Android Open Source Project
 | 
			
		||||
 | 
			
		||||
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) 2015 The Android Open Source Project
 | 
			
		||||
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.
 | 
			
		||||
 | 
			
		||||
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.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 1980, 1983, 1988, 1993
 | 
			
		||||
   The Regents of the University of California.  All rights reserved.
 | 
			
		||||
 | 
			
		||||
@@ -1679,6 +1679,35 @@ SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 1990 Regents of the University of California.
 | 
			
		||||
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. Neither the name of the University 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 REGENTS 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 REGENTS 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.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 1990 The Regents of the University of California.
 | 
			
		||||
All rights reserved.
 | 
			
		||||
 | 
			
		||||
@@ -2481,6 +2510,35 @@ SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 1993
 | 
			
		||||
     The Regents of the University of California.  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. Neither the name of the University 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 REGENTS 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 REGENTS 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.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 1993
 | 
			
		||||
   The Regents of the University of California.  All rights reserved.
 | 
			
		||||
 | 
			
		||||
@@ -2510,6 +2568,33 @@ SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 1993 Christopher G. Demetriou
 | 
			
		||||
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 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.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 1993 Martin Birgmeier
 | 
			
		||||
All rights reserved.
 | 
			
		||||
 | 
			
		||||
@@ -2550,6 +2635,33 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 1995, 1996 Carnegie-Mellon University.
 | 
			
		||||
All rights reserved.
 | 
			
		||||
 | 
			
		||||
Author: Chris G. Demetriou
 | 
			
		||||
 | 
			
		||||
Permission to use, copy, modify and distribute this software and
 | 
			
		||||
its documentation is hereby granted, provided that both the copyright
 | 
			
		||||
notice and this permission notice appear in all copies of the
 | 
			
		||||
software, derivative works or modified versions, and any portions
 | 
			
		||||
thereof, and that both notices appear in supporting documentation.
 | 
			
		||||
 | 
			
		||||
CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 | 
			
		||||
CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
 | 
			
		||||
FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 | 
			
		||||
 | 
			
		||||
Carnegie Mellon requests users of this software to return to
 | 
			
		||||
 | 
			
		||||
 Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 | 
			
		||||
 School of Computer Science
 | 
			
		||||
 Carnegie Mellon University
 | 
			
		||||
 Pittsburgh PA 15213-3890
 | 
			
		||||
 | 
			
		||||
any improvements or extensions that they make and grant Carnegie the
 | 
			
		||||
rights to redistribute these changes.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 1996 by Internet Software Consortium.
 | 
			
		||||
 | 
			
		||||
Permission to use, copy, modify, and distribute this software for any
 | 
			
		||||
@@ -2602,6 +2714,63 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 1996-2004 Per Fogelstrom, Opsycon AB
 | 
			
		||||
 | 
			
		||||
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.
 | 
			
		||||
 | 
			
		||||
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.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 1997 Mark Brinicombe
 | 
			
		||||
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. All advertising materials mentioning features or use of this software
 | 
			
		||||
   must display the following acknowledgement:
 | 
			
		||||
   This product includes software developed by Mark Brinicombe
 | 
			
		||||
4. Neither the name of the University 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 AUTHOR 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 AUTHOR 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.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 1997 Mark Brinicombe
 | 
			
		||||
Copyright (c) 2010 Android Open Source Project.
 | 
			
		||||
All rights reserved.
 | 
			
		||||
@@ -2962,6 +3131,38 @@ SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 1999 Kungliga Tekniska Högskolan
 | 
			
		||||
(Royal Institute of Technology, Stockholm, Sweden).
 | 
			
		||||
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. Neither the name of KTH 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 KTH AND ITS 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 KTH OR ITS 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
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2000 Ben Harris.
 | 
			
		||||
Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
 | 
			
		||||
All rights reserved.
 | 
			
		||||
@@ -3225,6 +3426,34 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2002 Opsycon AB  (www.opsycon.se / www.opsycon.com)
 | 
			
		||||
 | 
			
		||||
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. Neither the name of Opsycon AB 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 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.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2002 The NetBSD Foundation, Inc.
 | 
			
		||||
All rights reserved.
 | 
			
		||||
 | 
			
		||||
@@ -3768,22 +3997,6 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2007 Todd C. Miller <Todd.Miller@courtesan.com>
 | 
			
		||||
 | 
			
		||||
Permission to use, copy, modify, and distribute this software for any
 | 
			
		||||
purpose with or without fee is hereby granted, provided that the above
 | 
			
		||||
copyright notice and this permission notice appear in all copies.
 | 
			
		||||
 | 
			
		||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
			
		||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
			
		||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
			
		||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
			
		||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 | 
			
		||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 | 
			
		||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2007-2008  Michael G Schwern
 | 
			
		||||
 | 
			
		||||
This software originally derived from Paul Sheer's pivotal_gmtime_r.c.
 | 
			
		||||
@@ -3873,22 +4086,6 @@ SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
 | 
			
		||||
 | 
			
		||||
Permission to use, copy, modify, and distribute this software for any
 | 
			
		||||
purpose with or without fee is hereby granted, provided that the above
 | 
			
		||||
copyright notice and this permission notice appear in all copies.
 | 
			
		||||
 | 
			
		||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
			
		||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
			
		||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
			
		||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
			
		||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 | 
			
		||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 | 
			
		||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2008 Todd C. Miller <millert@openbsd.org>
 | 
			
		||||
 | 
			
		||||
Permission to use, copy, modify, and distribute this software for any
 | 
			
		||||
@@ -4225,39 +4422,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2011 Martin Pieuchot <mpi@openbsd.org>
 | 
			
		||||
 | 
			
		||||
Permission to use, copy, modify, and distribute this software for any
 | 
			
		||||
purpose with or without fee is hereby granted, provided that the above
 | 
			
		||||
copyright notice and this permission notice appear in all copies.
 | 
			
		||||
 | 
			
		||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
			
		||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
			
		||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
			
		||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
			
		||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 | 
			
		||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 | 
			
		||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2011 Martin Pieuchot <mpi@openbsd.org>
 | 
			
		||||
Copyright (c) 2009 Ted Unangst
 | 
			
		||||
 | 
			
		||||
Permission to use, copy, modify, and distribute this software for any
 | 
			
		||||
purpose with or without fee is hereby granted, provided that the above
 | 
			
		||||
copyright notice and this permission notice appear in all copies.
 | 
			
		||||
 | 
			
		||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
			
		||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
			
		||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
			
		||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
			
		||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 | 
			
		||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 | 
			
		||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2011 The Android Open Source Project
 | 
			
		||||
Copyright (c) 2008 ARM Ltd
 | 
			
		||||
All rights reserved.
 | 
			
		||||
@@ -4475,32 +4639,35 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2013 The NetBSD Foundation, Inc.
 | 
			
		||||
All rights reserved.
 | 
			
		||||
Copyright (c) 2013, Linaro Limited
 | 
			
		||||
   All rights reserved.
 | 
			
		||||
 | 
			
		||||
This code is derived from software contributed to The NetBSD Foundation
 | 
			
		||||
by Christos Zoulas.
 | 
			
		||||
   Redistribution and use in source and binary forms, with or without
 | 
			
		||||
   modification, are permitted provided that the following conditions
 | 
			
		||||
   are met:
 | 
			
		||||
 | 
			
		||||
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.
 | 
			
		||||
      * Redistributions of source code must retain the above copyright
 | 
			
		||||
      notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 | 
			
		||||
THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
 | 
			
		||||
      * 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 Linaro Limited 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
 | 
			
		||||
   HOLDER 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.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
@@ -4686,20 +4853,9 @@ SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
 | 
			
		||||
Copyright 2008 Damien Miller <djm@openbsd.org>
 | 
			
		||||
Copyright 2000 David E. O'Brien, John D. Polstra.
 | 
			
		||||
All rights reserved.
 | 
			
		||||
 | 
			
		||||
Theo de Raadt <deraadt@openbsd.org> came up with the idea of using
 | 
			
		||||
such a mathematical system to generate more random (yet non-repeating)
 | 
			
		||||
ids to solve the resolver/named problem.  But Niels designed the
 | 
			
		||||
actual system based on the constraints.
 | 
			
		||||
 | 
			
		||||
Later modified by Damien Miller to wrap the LCG output in a 15-bit
 | 
			
		||||
permutation generator based on a Luby-Rackoff block cipher. This
 | 
			
		||||
ensures the output is non-repeating and preserves the MSB twiddle
 | 
			
		||||
trick, but makes it more resistant to LCG prediction.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions
 | 
			
		||||
are met:
 | 
			
		||||
 
 | 
			
		||||
@@ -95,13 +95,13 @@ ssize_t     pread64(int, void*, size_t, off64_t) arm,mips,x86
 | 
			
		||||
ssize_t     pread64|pread(int, void*, size_t, off_t) arm64,mips64,x86_64
 | 
			
		||||
ssize_t     pwrite64(int, void*, size_t, off64_t) arm,mips,x86
 | 
			
		||||
ssize_t     pwrite64|pwrite(int, void*, size_t, off_t) arm64,mips64,x86_64
 | 
			
		||||
int         ___close:close(int)  all
 | 
			
		||||
int         close(int)                      all
 | 
			
		||||
pid_t       __getpid:getpid()  all
 | 
			
		||||
int         munmap(void*, size_t)  all
 | 
			
		||||
void*       mremap(void*, size_t, size_t, unsigned long)  all
 | 
			
		||||
int         msync(const void*, size_t, int)    all
 | 
			
		||||
int         mprotect(const void*, size_t, int)  all
 | 
			
		||||
int         madvise(void*, size_t, int)  all
 | 
			
		||||
int         madvise(const void*, size_t, int)  all
 | 
			
		||||
int         mlock(const void* addr, size_t len)    all
 | 
			
		||||
int         munlock(const void* addr, size_t len)   all
 | 
			
		||||
int         mlockall(int flags)   all
 | 
			
		||||
@@ -113,7 +113,7 @@ int         writev(int, const struct iovec*, int)  all
 | 
			
		||||
int         __fcntl64:fcntl64(int, int, void*)  arm,mips,x86
 | 
			
		||||
int         fcntl(int, int, void*)  arm64,mips64,x86_64
 | 
			
		||||
int         flock(int, int)   all
 | 
			
		||||
int         ___fchmod:fchmod(int, mode_t)  all
 | 
			
		||||
int         fchmod(int, mode_t)  all
 | 
			
		||||
int         dup(int)  all
 | 
			
		||||
int         pipe2(int*, int) all
 | 
			
		||||
int         dup3(int, int, int)   all
 | 
			
		||||
@@ -122,19 +122,19 @@ int         fdatasync(int) all
 | 
			
		||||
int         fchown:fchown32(int, uid_t, gid_t)  arm,x86
 | 
			
		||||
int         fchown:fchown(int, uid_t, gid_t)    arm64,mips,mips64,x86_64
 | 
			
		||||
void        sync(void)  all
 | 
			
		||||
int         ___fsetxattr:fsetxattr(int, const char*, const void*, size_t, int) all
 | 
			
		||||
ssize_t     ___fgetxattr:fgetxattr(int, const char*, void*, size_t) all
 | 
			
		||||
int         fsetxattr(int, const char*, const void*, size_t, int) all
 | 
			
		||||
ssize_t     fgetxattr(int, const char*, void*, size_t) all
 | 
			
		||||
ssize_t     flistxattr(int, char*, size_t) all
 | 
			
		||||
int         fremovexattr(int, const char*) all
 | 
			
		||||
 | 
			
		||||
int __getdents64:getdents64(unsigned int, struct dirent*, unsigned int)   arm,arm64,mips,mips64,x86,x86_64
 | 
			
		||||
 | 
			
		||||
int __openat:openat(int, const char*, int, mode_t) all
 | 
			
		||||
int ___faccessat:faccessat(int, const char*, int)  all
 | 
			
		||||
int ___fchmodat:fchmodat(int, const char*, mode_t)  all
 | 
			
		||||
int faccessat(int, const char*, int, int)  all
 | 
			
		||||
int fchmodat(int, const char*, mode_t, int)  all
 | 
			
		||||
int fchownat(int, const char*, uid_t, gid_t, int)  all
 | 
			
		||||
int fstatat64|fstatat:fstatat64(int, const char*, struct stat*, int)   arm,mips,x86
 | 
			
		||||
int fstatat64|fstatat:newfstatat(int, const char*, struct stat*, int)  arm64,x86_64
 | 
			
		||||
int fstatat64|fstatat:newfstatat(int, const char*, struct stat*, int)  arm64,mips64,x86_64
 | 
			
		||||
int linkat(int, const char*, int, const char*, int)  all
 | 
			
		||||
int mkdirat(int, const char*, mode_t)  all
 | 
			
		||||
int mknodat(int, const char*, mode_t, dev_t)  all
 | 
			
		||||
@@ -151,6 +151,7 @@ int utimensat(int, const char*, const struct timespec times[2], int)  all
 | 
			
		||||
off_t lseek(int, off_t, int) arm,mips,x86
 | 
			
		||||
int __llseek:_llseek(int, unsigned long, unsigned long, off64_t*, int) arm,mips,x86
 | 
			
		||||
off_t lseek|lseek64(int, off_t, int) arm64,mips64,x86_64
 | 
			
		||||
int ftruncate(int, off_t) arm,mips,x86
 | 
			
		||||
int ftruncate64(int, off64_t) arm,mips,x86
 | 
			
		||||
int ftruncate|ftruncate64(int, off_t) arm64,mips64,x86_64
 | 
			
		||||
ssize_t sendfile(int out_fd, int in_fd, off_t* offset, size_t count) arm,mips,x86
 | 
			
		||||
@@ -173,12 +174,12 @@ int __fadvise64:fadvise64_64(int, off64_t, off64_t, int) x86
 | 
			
		||||
int __fadvise64:fadvise64(int, off64_t, off64_t, int) arm64,mips,mips64,x86_64
 | 
			
		||||
 | 
			
		||||
int __fstatfs64:fstatfs64(int, size_t, struct statfs*)  arm,mips,x86
 | 
			
		||||
int __fstatfs:fstatfs(int, struct statfs*)  arm64,mips64,x86_64
 | 
			
		||||
int fstatfs64|fstatfs:fstatfs(int, struct statfs*)  arm64,mips64,x86_64
 | 
			
		||||
int __statfs64:statfs64(const char*, size_t, struct statfs*)  arm,mips,x86
 | 
			
		||||
int __statfs:statfs(const char*, struct statfs*)  arm64,mips64,x86_64
 | 
			
		||||
int statfs64|statfs:statfs(const char*, struct statfs*)  arm64,mips64,x86_64
 | 
			
		||||
 | 
			
		||||
int     fstat64|fstat:fstat64(int, struct stat*)    arm,mips,x86
 | 
			
		||||
int     fstat64|fstat:fstat(int, struct stat*)    arm64,x86_64
 | 
			
		||||
int     fstat64|fstat:fstat(int, struct stat*)    arm64,mips64,x86_64
 | 
			
		||||
 | 
			
		||||
# file system
 | 
			
		||||
int     chdir(const char*)              all
 | 
			
		||||
@@ -201,9 +202,9 @@ int     swapoff(const char*) all
 | 
			
		||||
int           settimeofday(const struct timeval*, const struct timezone*)   all
 | 
			
		||||
clock_t       times(struct tms*)       all
 | 
			
		||||
int           nanosleep(const struct timespec*, struct timespec*)   all
 | 
			
		||||
int           clock_settime(clockid_t, const struct timespec*)  all
 | 
			
		||||
int           clock_getres(clockid_t, struct timespec*)   all
 | 
			
		||||
int           ___clock_nanosleep:clock_nanosleep(clockid_t, int, const struct timespec*, struct timespec*)  all
 | 
			
		||||
int           clock_settime(clockid_t clk_id, const struct timespec* tp)  all
 | 
			
		||||
int           clock_getres(clockid_t clk_id, struct timespec* res)   all
 | 
			
		||||
int           clock_nanosleep(clockid_t clock_id, int flags, const struct timespec* req, struct timespec* rem)  all
 | 
			
		||||
int           getitimer(int, const struct itimerval*)   all
 | 
			
		||||
int           setitimer(int, const struct itimerval*, struct itimerval*)  all
 | 
			
		||||
int           __timer_create:timer_create(clockid_t clockid, struct sigevent* evp, __kernel_timer_t* timerid)    all
 | 
			
		||||
@@ -222,7 +223,6 @@ int     __rt_sigpending:rt_sigpending(sigset_t*, size_t)  all
 | 
			
		||||
int     __rt_sigprocmask:rt_sigprocmask(int, const sigset_t*, sigset_t*, size_t)  all
 | 
			
		||||
int     __rt_sigsuspend:rt_sigsuspend(const sigset_t*, size_t)  all
 | 
			
		||||
int     __rt_sigtimedwait:rt_sigtimedwait(const sigset_t*, struct siginfo_t*, struct timespec_t*, size_t)  all
 | 
			
		||||
int     ___rt_sigqueueinfo:rt_sigqueueinfo(pid_t, int, siginfo_t*)  all
 | 
			
		||||
int     __signalfd4:signalfd4(int, const sigset_t*, size_t, int)  all
 | 
			
		||||
 | 
			
		||||
# sockets
 | 
			
		||||
@@ -308,16 +308,11 @@ int inotify_rm_watch(int, unsigned int)  all
 | 
			
		||||
int __pselect6:pselect6(int, fd_set*, fd_set*, fd_set*, timespec*, void*)  all
 | 
			
		||||
int __ppoll:ppoll(pollfd*, unsigned int, timespec*, const sigset_t*, size_t)  all
 | 
			
		||||
 | 
			
		||||
ssize_t process_vm_readv(pid_t, const struct iovec*, unsigned long, const struct iovec*, unsigned long, unsigned long)  all
 | 
			
		||||
ssize_t process_vm_writev(pid_t, const struct iovec*, unsigned long, const struct iovec*, unsigned long, unsigned long)  all
 | 
			
		||||
 | 
			
		||||
int __set_tid_address:set_tid_address(int*)  all
 | 
			
		||||
 | 
			
		||||
int setfsgid(gid_t)  all
 | 
			
		||||
int setfsuid(uid_t)  all
 | 
			
		||||
 | 
			
		||||
int sethostname(const char*, size_t)  all
 | 
			
		||||
 | 
			
		||||
pid_t wait4(pid_t, int*, int, struct rusage*)  all
 | 
			
		||||
int __waitid:waitid(int, pid_t, struct siginfo_t*, int, void*)  all
 | 
			
		||||
 | 
			
		||||
@@ -326,7 +321,7 @@ int     __set_tls:__ARM_NR_set_tls(void*)                                 arm
 | 
			
		||||
int     cacheflush:__ARM_NR_cacheflush(long start, long end, long flags)  arm
 | 
			
		||||
 | 
			
		||||
# MIPS-specific
 | 
			
		||||
int     _flush_cache:cacheflush(char* addr, const int nbytes, const int op) mips
 | 
			
		||||
int     _flush_cache:cacheflush(char* addr, const int nbytes, const int op) mips,mips64
 | 
			
		||||
int     __set_tls:set_thread_area(void*) mips,mips64
 | 
			
		||||
 | 
			
		||||
# x86-specific
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,30 @@
 | 
			
		||||
# 32-bit arm.
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Various kinds of LP32 cruft.
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
libc_bionic_src_files_arm += \
 | 
			
		||||
    bionic/mmap.cpp \
 | 
			
		||||
 | 
			
		||||
libc_common_src_files_arm += \
 | 
			
		||||
    bionic/legacy_32_bit_support.cpp \
 | 
			
		||||
    bionic/ndk_cruft.cpp \
 | 
			
		||||
    bionic/time64.c \
 | 
			
		||||
 | 
			
		||||
libc_netbsd_src_files_arm += \
 | 
			
		||||
    upstream-netbsd/common/lib/libc/hash/sha1/sha1.c \
 | 
			
		||||
 | 
			
		||||
libc_openbsd_src_files_arm += \
 | 
			
		||||
    upstream-openbsd/lib/libc/stdio/putw.c \
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Default implementations of functions that are commonly optimized.
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
libc_bionic_src_files_arm += \
 | 
			
		||||
    bionic/memchr.c \
 | 
			
		||||
    bionic/memrchr.c \
 | 
			
		||||
    bionic/strchr.cpp \
 | 
			
		||||
    bionic/strnlen.c \
 | 
			
		||||
    bionic/strrchr.cpp \
 | 
			
		||||
@@ -20,8 +40,7 @@ libc_freebsd_src_files_arm += \
 | 
			
		||||
    upstream-freebsd/lib/libc/string/wmemmove.c \
 | 
			
		||||
 | 
			
		||||
libc_openbsd_src_files_arm += \
 | 
			
		||||
    upstream-openbsd/lib/libc/string/memchr.c \
 | 
			
		||||
    upstream-openbsd/lib/libc/string/memrchr.c \
 | 
			
		||||
    upstream-openbsd/lib/libc/string/bcopy.c \
 | 
			
		||||
    upstream-openbsd/lib/libc/string/stpncpy.c \
 | 
			
		||||
    upstream-openbsd/lib/libc/string/strlcat.c \
 | 
			
		||||
    upstream-openbsd/lib/libc/string/strlcpy.c \
 | 
			
		||||
@@ -39,8 +58,11 @@ libc_bionic_src_files_arm += \
 | 
			
		||||
    arch-arm/bionic/__bionic_clone.S \
 | 
			
		||||
    arch-arm/bionic/_exit_with_stack_teardown.S \
 | 
			
		||||
    arch-arm/bionic/libgcc_compat.c \
 | 
			
		||||
    arch-arm/bionic/memcmp.S \
 | 
			
		||||
    arch-arm/bionic/__restore.S \
 | 
			
		||||
    arch-arm/bionic/_setjmp.S \
 | 
			
		||||
    arch-arm/bionic/setjmp.S \
 | 
			
		||||
    arch-arm/bionic/sigsetjmp.S \
 | 
			
		||||
    arch-arm/bionic/syscall.S \
 | 
			
		||||
 | 
			
		||||
libc_arch_static_src_files_arm := arch-arm/bionic/exidx_static.c
 | 
			
		||||
 
 | 
			
		||||
@@ -39,9 +39,6 @@
 | 
			
		||||
 | 
			
		||||
extern int __cxa_atexit(void (*)(void*), void*, void*);
 | 
			
		||||
 | 
			
		||||
// All of these are weak symbols to avoid multiple definition errors when
 | 
			
		||||
// linking with libstdc++-v3 or compiler-rt.
 | 
			
		||||
 | 
			
		||||
/* The "C++ ABI for ARM" document states that static C++ constructors,
 | 
			
		||||
 * which are called from the .init_array, should manually call
 | 
			
		||||
 * __aeabi_atexit() to register static destructors explicitly.
 | 
			
		||||
@@ -50,35 +47,35 @@ extern int __cxa_atexit(void (*)(void*), void*, void*);
 | 
			
		||||
 * variable from the shared object that contains the constructor/destructor
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
// Make this a weak symbol to avoid a multiple definition error when linking with libstdc++-v3.
 | 
			
		||||
int __attribute__((weak))
 | 
			
		||||
__aeabi_atexit(void *object, void (*destructor) (void *), void *dso_handle) {
 | 
			
		||||
    return __cxa_atexit(destructor, object, dso_handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void __attribute__((weak))
 | 
			
		||||
__aeabi_memcpy8(void *dest, const void *src, size_t n) {
 | 
			
		||||
void __aeabi_memcpy8(void *dest, const void *src, size_t n) {
 | 
			
		||||
    memcpy(dest, src, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __attribute__((weak)) __aeabi_memcpy4(void *dest, const void *src, size_t n) {
 | 
			
		||||
void __aeabi_memcpy4(void *dest, const void *src, size_t n) {
 | 
			
		||||
    memcpy(dest, src, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __attribute__((weak)) __aeabi_memcpy(void *dest, const void *src, size_t n) {
 | 
			
		||||
void __aeabi_memcpy(void *dest, const void *src, size_t n) {
 | 
			
		||||
    memcpy(dest, src, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void __attribute__((weak)) __aeabi_memmove8(void *dest, const void *src, size_t n) {
 | 
			
		||||
void __aeabi_memmove8(void *dest, const void *src, size_t n) {
 | 
			
		||||
    memmove(dest, src, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __attribute__((weak)) __aeabi_memmove4(void *dest, const void *src, size_t n) {
 | 
			
		||||
void __aeabi_memmove4(void *dest, const void *src, size_t n) {
 | 
			
		||||
    memmove(dest, src, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __attribute__((weak)) __aeabi_memmove(void *dest, const void *src, size_t n) {
 | 
			
		||||
void __aeabi_memmove(void *dest, const void *src, size_t n) {
 | 
			
		||||
    memmove(dest, src, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -87,27 +84,27 @@ void __attribute__((weak)) __aeabi_memmove(void *dest, const void *src, size_t n
 | 
			
		||||
 *  This allows __aeabi_memclr to tail-call __aeabi_memset
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
void __attribute__((weak)) __aeabi_memset8(void *dest, size_t n, int c) {
 | 
			
		||||
void __aeabi_memset8(void *dest, size_t n, int c) {
 | 
			
		||||
    memset(dest, c, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __attribute__((weak)) __aeabi_memset4(void *dest, size_t n, int c) {
 | 
			
		||||
void __aeabi_memset4(void *dest, size_t n, int c) {
 | 
			
		||||
    memset(dest, c, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __attribute__((weak)) __aeabi_memset(void *dest, size_t n, int c) {
 | 
			
		||||
void __aeabi_memset(void *dest, size_t n, int c) {
 | 
			
		||||
    memset(dest, c, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void __attribute__((weak)) __aeabi_memclr8(void *dest, size_t n) {
 | 
			
		||||
void __aeabi_memclr8(void *dest, size_t n) {
 | 
			
		||||
    __aeabi_memset8(dest, n, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __attribute__((weak)) __aeabi_memclr4(void *dest, size_t n) {
 | 
			
		||||
void __aeabi_memclr4(void *dest, size_t n) {
 | 
			
		||||
    __aeabi_memset4(dest, n, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __attribute__((weak)) __aeabi_memclr(void *dest, size_t n) {
 | 
			
		||||
void __aeabi_memclr(void *dest, size_t n) {
 | 
			
		||||
    __aeabi_memset(dest, n, 0);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2008 The Android Open Source Project
 | 
			
		||||
 * Copyright (C) 2008-2010 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
@@ -42,14 +42,13 @@ ENTRY(__bionic_clone)
 | 
			
		||||
    # load extra parameters
 | 
			
		||||
    ldmfd   ip, {r4, r5, r6}
 | 
			
		||||
 | 
			
		||||
    # Push 'fn' and 'arg' onto the child stack.
 | 
			
		||||
    stmdb   r1!, {r5, r6}
 | 
			
		||||
    # store 'fn' and 'arg' to the child stack
 | 
			
		||||
    str     r5, [r1, #-4]
 | 
			
		||||
    str     r6, [r1, #-8]
 | 
			
		||||
 | 
			
		||||
    # Make the system call.
 | 
			
		||||
    # System call
 | 
			
		||||
    ldr     r7, =__NR_clone
 | 
			
		||||
    swi     #0
 | 
			
		||||
 | 
			
		||||
    # Are we the child?
 | 
			
		||||
    movs    r0, r0
 | 
			
		||||
    beq     1f
 | 
			
		||||
 | 
			
		||||
@@ -63,8 +62,8 @@ ENTRY(__bionic_clone)
 | 
			
		||||
1:  # The child.
 | 
			
		||||
    # Setting lr to 0 will make the unwinder stop at __start_thread
 | 
			
		||||
    mov    lr, #0
 | 
			
		||||
    # Call __start_thread with the 'fn' and 'arg' we stored on the child stack.
 | 
			
		||||
    pop    {r0, r1}
 | 
			
		||||
    ldr    r0, [sp, #-4]
 | 
			
		||||
    ldr    r1, [sp, #-8]
 | 
			
		||||
    b      __start_thread
 | 
			
		||||
END(__bionic_clone)
 | 
			
		||||
.hidden __bionic_clone
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										113
									
								
								libc/arch-arm/bionic/_setjmp.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								libc/arch-arm/bionic/_setjmp.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,113 @@
 | 
			
		||||
/*	$OpenBSD: _setjmp.S,v 1.2 2004/02/01 05:40:52 drahn Exp $	*/
 | 
			
		||||
/*	$NetBSD: _setjmp.S,v 1.5 2003/04/05 23:08:51 bjh21 Exp $	*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 1997 Mark Brinicombe
 | 
			
		||||
 * Copyright (c) 2010 Android Open Source Project.
 | 
			
		||||
 * 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. All advertising materials mentioning features or use of this software
 | 
			
		||||
 *    must display the following acknowledgement:
 | 
			
		||||
 *	This product includes software developed by Mark Brinicombe
 | 
			
		||||
 * 4. Neither the name of the University 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 AUTHOR 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 AUTHOR 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
#include <machine/setjmp.h>
 | 
			
		||||
#include <machine/cpu-features.h>
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * C library -- _setjmp, _longjmp
 | 
			
		||||
 *
 | 
			
		||||
 *	_longjmp(a,v)
 | 
			
		||||
 * will generate a "return(v)" from the last call to
 | 
			
		||||
 *	_setjmp(a)
 | 
			
		||||
 * by restoring registers from the stack.
 | 
			
		||||
 * The previous signal state is NOT restored.
 | 
			
		||||
 *
 | 
			
		||||
 * Note: r0 is the return value
 | 
			
		||||
 *       r1-r3 are scratch registers in functions
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
ENTRY(_setjmp)
 | 
			
		||||
	ldr	r1, .L_setjmp_magic
 | 
			
		||||
	str	r1, [r0, #(_JB_MAGIC * 4)]
 | 
			
		||||
 | 
			
		||||
	/* Store core registers */
 | 
			
		||||
	add     r1, r0, #(_JB_CORE_BASE * 4)
 | 
			
		||||
	stmia   r1, {r4-r14}
 | 
			
		||||
 | 
			
		||||
#ifdef __ARM_HAVE_VFP
 | 
			
		||||
	/* Store floating-point registers */
 | 
			
		||||
	add     r1, r0, #(_JB_FLOAT_BASE * 4)
 | 
			
		||||
	vstmia  r1, {d8-d15}
 | 
			
		||||
	/* Store floating-point state */
 | 
			
		||||
	fmrx    r1, fpscr
 | 
			
		||||
	str     r1, [r0, #(_JB_FLOAT_STATE * 4)]
 | 
			
		||||
#endif  /* __ARM_HAVE_VFP */
 | 
			
		||||
 | 
			
		||||
        mov	r0, #0x00000000
 | 
			
		||||
        bx      lr
 | 
			
		||||
END(_setjmp)
 | 
			
		||||
 | 
			
		||||
.L_setjmp_magic:
 | 
			
		||||
	.word	_JB_MAGIC__SETJMP
 | 
			
		||||
 | 
			
		||||
ENTRY(_longjmp)
 | 
			
		||||
	ldr	r2, .L_setjmp_magic
 | 
			
		||||
	ldr	r3, [r0, #(_JB_MAGIC * 4)]
 | 
			
		||||
	teq	r2, r3
 | 
			
		||||
	bne	botch
 | 
			
		||||
 | 
			
		||||
#ifdef __ARM_HAVE_VFP
 | 
			
		||||
	/* Restore floating-point registers */
 | 
			
		||||
	add     r2, r0, #(_JB_FLOAT_BASE * 4)
 | 
			
		||||
	vldmia  r2, {d8-d15}
 | 
			
		||||
	/* Restore floating-point state */
 | 
			
		||||
	ldr     r2, [r0, #(_JB_FLOAT_STATE * 4)]
 | 
			
		||||
	fmxr    fpscr, r2
 | 
			
		||||
#endif /* __ARM_HAVE_VFP */
 | 
			
		||||
 | 
			
		||||
	/* Restore core registers */
 | 
			
		||||
	add     r2, r0, #(_JB_CORE_BASE * 4)
 | 
			
		||||
	ldmia   r2, {r4-r14}
 | 
			
		||||
 | 
			
		||||
	/* Validate sp and r14 */
 | 
			
		||||
	teq	sp, #0
 | 
			
		||||
	teqne	r14, #0
 | 
			
		||||
	beq	botch
 | 
			
		||||
 | 
			
		||||
	/* Set return value */
 | 
			
		||||
	mov	r0, r1
 | 
			
		||||
	teq	r0, #0x00000000
 | 
			
		||||
	moveq	r0, #0x00000001
 | 
			
		||||
	bx      lr
 | 
			
		||||
 | 
			
		||||
	/* validation failed, die die die. */
 | 
			
		||||
botch:
 | 
			
		||||
	bl	PIC_SYM(longjmperror, PLT)
 | 
			
		||||
	bl	PIC_SYM(abort, PLT)
 | 
			
		||||
	b	. - 8		/* Cannot get here */
 | 
			
		||||
END(_longjmp)
 | 
			
		||||
@@ -40,5 +40,5 @@ ENTRY(abort)
 | 
			
		||||
    .cfi_def_cfa_offset 8
 | 
			
		||||
    .cfi_rel_offset r3, 0
 | 
			
		||||
    .cfi_rel_offset r14, 4
 | 
			
		||||
    bl      __libc_android_abort
 | 
			
		||||
    bl      PIC_SYM(__libc_android_abort, PLT)
 | 
			
		||||
END(abort)
 | 
			
		||||
 
 | 
			
		||||
@@ -40,8 +40,6 @@
 | 
			
		||||
 * Optimized memcmp() for Cortex-A9.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
.syntax unified
 | 
			
		||||
 | 
			
		||||
ENTRY(memcmp)
 | 
			
		||||
        pld         [r0, #(CACHE_LINE_SIZE * 0)]
 | 
			
		||||
        pld         [r0, #(CACHE_LINE_SIZE * 1)]
 | 
			
		||||
@@ -163,25 +161,25 @@ ENTRY(memcmp)
 | 
			
		||||
        eors        r0, r0, ip
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        ldreq       ip, [r1, #4]!
 | 
			
		||||
        eorseq      r0, r0, lr
 | 
			
		||||
        eoreqs      r0, r0, lr
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        ldreq       lr, [r1, #4]!
 | 
			
		||||
        eorseq      r0, r0, ip
 | 
			
		||||
        eoreqs      r0, r0, ip
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        ldreq       ip, [r1, #4]!
 | 
			
		||||
        eorseq      r0, r0, lr
 | 
			
		||||
        eoreqs      r0, r0, lr
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        ldreq       lr, [r1, #4]!
 | 
			
		||||
        eorseq      r0, r0, ip
 | 
			
		||||
        eoreqs      r0, r0, ip
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        ldreq       ip, [r1, #4]!
 | 
			
		||||
        eorseq      r0, r0, lr
 | 
			
		||||
        eoreqs      r0, r0, lr
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        ldreq       lr, [r1, #4]!
 | 
			
		||||
        eorseq      r0, r0, ip
 | 
			
		||||
        eoreqs      r0, r0, ip
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        ldreq       ip, [r1, #4]!
 | 
			
		||||
        eorseq      r0, r0, lr
 | 
			
		||||
        eoreqs      r0, r0, lr
 | 
			
		||||
        bne         2f
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        bhs         0b
 | 
			
		||||
@@ -265,17 +263,17 @@ ENTRY(memcmp)
 | 
			
		||||
        ldreq       lr, [r1], #4
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        orreq       ip, ip, lr, lsl #16
 | 
			
		||||
        eorseq      r0, r0, ip
 | 
			
		||||
        eoreqs      r0, r0, ip
 | 
			
		||||
        moveq       ip, lr, lsr #16
 | 
			
		||||
        ldreq       lr, [r1], #4
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        orreq       ip, ip, lr, lsl #16
 | 
			
		||||
        eorseq      r0, r0, ip
 | 
			
		||||
        eoreqs      r0, r0, ip
 | 
			
		||||
        moveq       ip, lr, lsr #16
 | 
			
		||||
        ldreq       lr, [r1], #4
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        orreq       ip, ip, lr, lsl #16
 | 
			
		||||
        eorseq      r0, r0, ip
 | 
			
		||||
        eoreqs      r0, r0, ip
 | 
			
		||||
        bne         7f
 | 
			
		||||
        subs        r2, r2, #16
 | 
			
		||||
        bhs         6b
 | 
			
		||||
@@ -319,7 +317,7 @@ ENTRY(memcmp)
 | 
			
		||||
        ldreq       r7, [r1], #4
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        orreq       ip, ip, r7, lsl r6
 | 
			
		||||
        eorseq      r0, r0, ip
 | 
			
		||||
        eoreqs      r0, r0, ip
 | 
			
		||||
        bne         7f
 | 
			
		||||
        subs        r2, r2, #8
 | 
			
		||||
        bhs         6b
 | 
			
		||||
							
								
								
									
										686
									
								
								libc/arch-arm/bionic/memcpy.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										686
									
								
								libc/arch-arm/bionic/memcpy.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,686 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2008 The Android Open Source Project
 | 
			
		||||
 * 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.
 | 
			
		||||
 *
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <machine/cpu-features.h>
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
#if defined(__ARM_NEON__) && !defined(ARCH_ARM_USE_NON_NEON_MEMCPY)
 | 
			
		||||
 | 
			
		||||
        .text
 | 
			
		||||
        .fpu    neon
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_32_BYTE_CACHE_LINE
 | 
			
		||||
/* a prefetch distance of 2 cache-lines */
 | 
			
		||||
#define CACHE_LINE_SIZE     32
 | 
			
		||||
#else
 | 
			
		||||
/* a prefetch distance of 4 cache-lines works best experimentally */
 | 
			
		||||
#define CACHE_LINE_SIZE     64
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
ENTRY(memcpy)
 | 
			
		||||
        .save       {r0, lr}
 | 
			
		||||
        /* start preloading as early as possible */
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 0)]
 | 
			
		||||
        stmfd       sp!, {r0, lr}
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 1)]
 | 
			
		||||
 | 
			
		||||
/* If Neon supports unaligned access then remove the align code,
 | 
			
		||||
 * unless a size limit has been specified.
 | 
			
		||||
 */
 | 
			
		||||
#ifndef NEON_UNALIGNED_ACCESS
 | 
			
		||||
        /* do we have at least 16-bytes to copy (needed for alignment below) */
 | 
			
		||||
        cmp         r2, #16
 | 
			
		||||
        blo         5f
 | 
			
		||||
 | 
			
		||||
        /* check if buffers are aligned. If so, run arm-only version */
 | 
			
		||||
        eor         r3, r0, r1
 | 
			
		||||
        ands        r3, r3, #0x3
 | 
			
		||||
        beq         11f
 | 
			
		||||
 | 
			
		||||
        /* align destination to cache-line for the write-buffer */
 | 
			
		||||
        rsb         r3, r0, #0
 | 
			
		||||
        ands        r3, r3, #0xF
 | 
			
		||||
        beq         2f
 | 
			
		||||
 | 
			
		||||
        /* copy up to 15-bytes (count in r3) */
 | 
			
		||||
        sub         r2, r2, r3
 | 
			
		||||
        movs        ip, r3, lsl #31
 | 
			
		||||
        ldrmib      lr, [r1], #1
 | 
			
		||||
        strmib      lr, [r0], #1
 | 
			
		||||
        ldrcsb      ip, [r1], #1
 | 
			
		||||
        ldrcsb      lr, [r1], #1
 | 
			
		||||
        strcsb      ip, [r0], #1
 | 
			
		||||
        strcsb      lr, [r0], #1
 | 
			
		||||
        movs        ip, r3, lsl #29
 | 
			
		||||
        bge         1f
 | 
			
		||||
        // copies 4 bytes, destination 32-bits aligned
 | 
			
		||||
        vld4.8      {d0[0], d1[0], d2[0], d3[0]}, [r1]!
 | 
			
		||||
        vst4.8      {d0[0], d1[0], d2[0], d3[0]}, [r0, :32]!
 | 
			
		||||
1:      bcc         2f
 | 
			
		||||
        // copies 8 bytes, destination 64-bits aligned
 | 
			
		||||
        vld1.8      {d0}, [r1]!
 | 
			
		||||
        vst1.8      {d0}, [r0, :64]!
 | 
			
		||||
2:
 | 
			
		||||
        /* preload immediately the next cache line, which we may need */
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 0)]
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 1)]
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_32_BYTE_CACHE_LINE
 | 
			
		||||
        /* make sure we have at least 32 bytes to copy */
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        blo         4f
 | 
			
		||||
 | 
			
		||||
        /* preload all the cache lines we need.
 | 
			
		||||
         * NOTE: the number of pld below depends on PREFETCH_DISTANCE,
 | 
			
		||||
         * ideally would would increase the distance in the main loop to
 | 
			
		||||
         * avoid the goofy code below. In practice this doesn't seem to make
 | 
			
		||||
         * a big difference.
 | 
			
		||||
         */
 | 
			
		||||
        pld         [r1, #(PREFETCH_DISTANCE)]
 | 
			
		||||
 | 
			
		||||
1:      /* The main loop copies 32 bytes at a time */
 | 
			
		||||
        vld1.8      {d0  - d3},   [r1]!
 | 
			
		||||
        pld         [r1, #(PREFETCH_DISTANCE)]
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        vst1.8      {d0  - d3},   [r0, :128]!
 | 
			
		||||
        bhs         1b
 | 
			
		||||
#else
 | 
			
		||||
        /* make sure we have at least 64 bytes to copy */
 | 
			
		||||
        subs        r2, r2, #64
 | 
			
		||||
        blo         2f
 | 
			
		||||
 | 
			
		||||
        /* preload all the cache lines we need. */
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 2)]
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 3)]
 | 
			
		||||
 | 
			
		||||
1:      /* The main loop copies 64 bytes at a time */
 | 
			
		||||
        vld1.8      {d0 - d3}, [r1]!
 | 
			
		||||
        vld1.8      {d4 - d7}, [r1]!
 | 
			
		||||
#ifdef  HAVE_32_BYTE_CACHE_LINE
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 2)]
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 3)]
 | 
			
		||||
#else
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 3)]
 | 
			
		||||
#endif
 | 
			
		||||
        subs        r2, r2, #64
 | 
			
		||||
        vst1.8      {d0 - d3}, [r0, :128]!
 | 
			
		||||
        vst1.8      {d4 - d7}, [r0, :128]!
 | 
			
		||||
        bhs         1b
 | 
			
		||||
 | 
			
		||||
2:      /* fix-up the remaining count and make sure we have >= 32 bytes left */
 | 
			
		||||
        add         r2, r2, #64
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        blo         4f
 | 
			
		||||
 | 
			
		||||
3:      /* 32 bytes at a time. These cache lines were already preloaded */
 | 
			
		||||
        vld1.8      {d0 - d3}, [r1]!
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        vst1.8      {d0 - d3}, [r0, :128]!
 | 
			
		||||
        bhs         3b
 | 
			
		||||
#endif
 | 
			
		||||
4:      /* less than 32 left */
 | 
			
		||||
        add         r2, r2, #32
 | 
			
		||||
        tst         r2, #0x10
 | 
			
		||||
        beq         5f
 | 
			
		||||
        // copies 16 bytes, 128-bits aligned
 | 
			
		||||
        vld1.8      {d0, d1}, [r1]!
 | 
			
		||||
        vst1.8      {d0, d1}, [r0, :128]!
 | 
			
		||||
5:      /* copy up to 15-bytes (count in r2) */
 | 
			
		||||
        movs        ip, r2, lsl #29
 | 
			
		||||
        bcc         1f
 | 
			
		||||
        vld1.8      {d0}, [r1]!
 | 
			
		||||
        vst1.8      {d0}, [r0]!
 | 
			
		||||
1:      bge         2f
 | 
			
		||||
        vld4.8      {d0[0], d1[0], d2[0], d3[0]}, [r1]!
 | 
			
		||||
        vst4.8      {d0[0], d1[0], d2[0], d3[0]}, [r0]!
 | 
			
		||||
2:      movs        ip, r2, lsl #31
 | 
			
		||||
        ldrmib      r3, [r1], #1
 | 
			
		||||
        ldrcsb      ip, [r1], #1
 | 
			
		||||
        ldrcsb      lr, [r1], #1
 | 
			
		||||
        strmib      r3, [r0], #1
 | 
			
		||||
        strcsb      ip, [r0], #1
 | 
			
		||||
        strcsb      lr, [r0], #1
 | 
			
		||||
 | 
			
		||||
        ldmfd       sp!, {r0, lr}
 | 
			
		||||
        bx          lr
 | 
			
		||||
 | 
			
		||||
#else   /* NEON_UNALIGNED_ACCESS */
 | 
			
		||||
 | 
			
		||||
        // Check so divider is at least 16 bytes, needed for alignment code.
 | 
			
		||||
        cmp         r2, #16
 | 
			
		||||
        blo         5f
 | 
			
		||||
 | 
			
		||||
#ifdef NEON_MEMCPY_ALIGNMENT_DIVIDER
 | 
			
		||||
        /* Check the upper size limit for Neon unaligned memory access in memcpy */
 | 
			
		||||
#if NEON_MEMCPY_ALIGNMENT_DIVIDER >= 16
 | 
			
		||||
        cmp         r2, #NEON_MEMCPY_ALIGNMENT_DIVIDER
 | 
			
		||||
        blo         3f
 | 
			
		||||
#endif
 | 
			
		||||
        /* check if buffers are aligned. If so, run arm-only version */
 | 
			
		||||
        eor         r3, r0, r1
 | 
			
		||||
        ands        r3, r3, #0x3
 | 
			
		||||
        beq         11f
 | 
			
		||||
 | 
			
		||||
        /* align destination to 16 bytes for the write-buffer */
 | 
			
		||||
        rsb         r3, r0, #0
 | 
			
		||||
        ands        r3, r3, #0xF
 | 
			
		||||
        beq         3f
 | 
			
		||||
 | 
			
		||||
        /* copy up to 15-bytes (count in r3) */
 | 
			
		||||
        sub         r2, r2, r3
 | 
			
		||||
        movs        ip, r3, lsl #31
 | 
			
		||||
        ldrmib      lr, [r1], #1
 | 
			
		||||
        strmib      lr, [r0], #1
 | 
			
		||||
        ldrcsb      ip, [r1], #1
 | 
			
		||||
        ldrcsb      lr, [r1], #1
 | 
			
		||||
        strcsb      ip, [r0], #1
 | 
			
		||||
        strcsb      lr, [r0], #1
 | 
			
		||||
        movs        ip, r3, lsl #29
 | 
			
		||||
        bge         1f
 | 
			
		||||
        // copies 4 bytes, destination 32-bits aligned
 | 
			
		||||
        vld1.32     {d0[0]}, [r1]!
 | 
			
		||||
        vst1.32     {d0[0]}, [r0, :32]!
 | 
			
		||||
1:      bcc         2f
 | 
			
		||||
        // copies 8 bytes, destination 64-bits aligned
 | 
			
		||||
        vld1.8      {d0}, [r1]!
 | 
			
		||||
        vst1.8      {d0}, [r0, :64]!
 | 
			
		||||
2:
 | 
			
		||||
        /* preload immediately the next cache line, which we may need */
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 0)]
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 1)]
 | 
			
		||||
3:
 | 
			
		||||
#endif
 | 
			
		||||
        /* make sure we have at least 64 bytes to copy */
 | 
			
		||||
        subs        r2, r2, #64
 | 
			
		||||
        blo         2f
 | 
			
		||||
 | 
			
		||||
        /* preload all the cache lines we need */
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 2)]
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 3)]
 | 
			
		||||
 | 
			
		||||
1:      /* The main loop copies 64 bytes at a time */
 | 
			
		||||
        vld1.8      {d0 - d3}, [r1]!
 | 
			
		||||
        vld1.8      {d4 - d7}, [r1]!
 | 
			
		||||
#ifdef  HAVE_32_BYTE_CACHE_LINE
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 2)]
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 3)]
 | 
			
		||||
#else
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 3)]
 | 
			
		||||
#endif
 | 
			
		||||
        subs        r2, r2, #64
 | 
			
		||||
        vst1.8      {d0 - d3}, [r0]!
 | 
			
		||||
        vst1.8      {d4 - d7}, [r0]!
 | 
			
		||||
        bhs         1b
 | 
			
		||||
 | 
			
		||||
2:      /* fix-up the remaining count and make sure we have >= 32 bytes left */
 | 
			
		||||
        add         r2, r2, #64
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        blo         4f
 | 
			
		||||
 | 
			
		||||
3:      /* 32 bytes at a time. These cache lines were already preloaded */
 | 
			
		||||
        vld1.8      {d0 - d3}, [r1]!
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        vst1.8      {d0 - d3}, [r0]!
 | 
			
		||||
        bhs         3b
 | 
			
		||||
 | 
			
		||||
4:      /* less than 32 left */
 | 
			
		||||
        add         r2, r2, #32
 | 
			
		||||
        tst         r2, #0x10
 | 
			
		||||
        beq         5f
 | 
			
		||||
        // copies 16 bytes, 128-bits aligned
 | 
			
		||||
        vld1.8      {d0, d1}, [r1]!
 | 
			
		||||
        vst1.8      {d0, d1}, [r0]!
 | 
			
		||||
5:      /* copy up to 15-bytes (count in r2) */
 | 
			
		||||
        movs        ip, r2, lsl #29
 | 
			
		||||
        bcc         1f
 | 
			
		||||
        vld1.8      {d0}, [r1]!
 | 
			
		||||
        vst1.8      {d0}, [r0]!
 | 
			
		||||
1:      bge         2f
 | 
			
		||||
        vld1.32     {d0[0]}, [r1]!
 | 
			
		||||
        vst1.32     {d0[0]}, [r0]!
 | 
			
		||||
2:      movs        ip, r2, lsl #31
 | 
			
		||||
        ldrmib      r3, [r1], #1
 | 
			
		||||
        ldrcsb      ip, [r1], #1
 | 
			
		||||
        ldrcsb      lr, [r1], #1
 | 
			
		||||
        strmib      r3, [r0], #1
 | 
			
		||||
        strcsb      ip, [r0], #1
 | 
			
		||||
        strcsb      lr, [r0], #1
 | 
			
		||||
 | 
			
		||||
        ldmfd       sp!, {r0, lr}
 | 
			
		||||
        bx          lr
 | 
			
		||||
#endif  /* NEON_UNALIGNED_ACCESS */
 | 
			
		||||
11:
 | 
			
		||||
        /* Simple arm-only copy loop to handle aligned copy operations */
 | 
			
		||||
        stmfd       sp!, {r4, r5, r6, r7, r8}
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 2)]
 | 
			
		||||
 | 
			
		||||
        /* Check alignment */
 | 
			
		||||
        rsb         r3, r1, #0
 | 
			
		||||
        ands        r3, #3
 | 
			
		||||
        beq         2f
 | 
			
		||||
 | 
			
		||||
        /* align source to 32 bits. We need to insert 2 instructions between
 | 
			
		||||
         * a ldr[b|h] and str[b|h] because byte and half-word instructions
 | 
			
		||||
         * stall 2 cycles.
 | 
			
		||||
         */
 | 
			
		||||
        movs        r12, r3, lsl #31
 | 
			
		||||
        sub         r2, r2, r3      /* we know that r3 <= r2 because r2 >= 4 */
 | 
			
		||||
        ldrmib      r3, [r1], #1
 | 
			
		||||
        ldrcsb      r4, [r1], #1
 | 
			
		||||
        ldrcsb      r5, [r1], #1
 | 
			
		||||
        strmib      r3, [r0], #1
 | 
			
		||||
        strcsb      r4, [r0], #1
 | 
			
		||||
        strcsb      r5, [r0], #1
 | 
			
		||||
2:
 | 
			
		||||
        subs        r2, #32
 | 
			
		||||
        blt         5f
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 3)]
 | 
			
		||||
3:      /* Main copy loop, copying 32 bytes at a time */
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 4)]
 | 
			
		||||
        ldmia       r1!, {r3, r4, r5, r6, r7, r8, r12, lr}
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        stmia       r0!, {r3, r4, r5, r6, r7, r8, r12, lr}
 | 
			
		||||
        bge         3b
 | 
			
		||||
5:      /* Handle any remaining bytes */
 | 
			
		||||
        adds        r2, #32
 | 
			
		||||
        beq         6f
 | 
			
		||||
 | 
			
		||||
        movs        r12, r2, lsl #28
 | 
			
		||||
        ldmcsia     r1!, {r3, r4, r5, r6}   /* 16 bytes */
 | 
			
		||||
        ldmmiia     r1!, {r7, r8}           /*  8 bytes */
 | 
			
		||||
        stmcsia     r0!, {r3, r4, r5, r6}
 | 
			
		||||
        stmmiia     r0!, {r7, r8}
 | 
			
		||||
        movs        r12, r2, lsl #30
 | 
			
		||||
        ldrcs       r3, [r1], #4            /*  4 bytes */
 | 
			
		||||
        ldrmih      r4, [r1], #2            /*  2 bytes */
 | 
			
		||||
        strcs       r3, [r0], #4
 | 
			
		||||
        strmih      r4, [r0], #2
 | 
			
		||||
        tst         r2, #0x1
 | 
			
		||||
        ldrneb      r3, [r1]                /*  last byte  */
 | 
			
		||||
        strneb      r3, [r0]
 | 
			
		||||
6:
 | 
			
		||||
        ldmfd       sp!, {r4, r5, r6, r7, r8}
 | 
			
		||||
        ldmfd       sp!, {r0, pc}
 | 
			
		||||
END(memcpy)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#else   /* __ARM_ARCH__ < 7 */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
		 * Optimized memcpy() for ARM.
 | 
			
		||||
         *
 | 
			
		||||
		 * note that memcpy() always returns the destination pointer,
 | 
			
		||||
		 * so we have to preserve R0.
 | 
			
		||||
		 */
 | 
			
		||||
 | 
			
		||||
ENTRY(memcpy)
 | 
			
		||||
		/* The stack must always be 64-bits aligned to be compliant with the
 | 
			
		||||
		 * ARM ABI. Since we have to save R0, we might as well save R4
 | 
			
		||||
		 * which we can use for better pipelining of the reads below
 | 
			
		||||
		 */
 | 
			
		||||
        .save       {r0, r4, lr}
 | 
			
		||||
        stmfd       sp!, {r0, r4, lr}
 | 
			
		||||
        /* Making room for r5-r11 which will be spilled later */
 | 
			
		||||
        .pad        #28
 | 
			
		||||
        sub         sp, sp, #28
 | 
			
		||||
 | 
			
		||||
        // preload the destination because we'll align it to a cache line
 | 
			
		||||
        // with small writes. Also start the source "pump".
 | 
			
		||||
        pld         [r0, #0]
 | 
			
		||||
        pld         [r1, #0]
 | 
			
		||||
        pld         [r1, #32]
 | 
			
		||||
 | 
			
		||||
		/* it simplifies things to take care of len<4 early */
 | 
			
		||||
		cmp			r2, #4
 | 
			
		||||
		blo			copy_last_3_and_return
 | 
			
		||||
 | 
			
		||||
		/* compute the offset to align the source
 | 
			
		||||
		 * offset = (4-(src&3))&3 = -src & 3
 | 
			
		||||
		 */
 | 
			
		||||
		rsb			r3, r1, #0
 | 
			
		||||
		ands		r3, r3, #3
 | 
			
		||||
		beq			src_aligned
 | 
			
		||||
 | 
			
		||||
		/* align source to 32 bits. We need to insert 2 instructions between
 | 
			
		||||
		 * a ldr[b|h] and str[b|h] because byte and half-word instructions
 | 
			
		||||
		 * stall 2 cycles.
 | 
			
		||||
		 */
 | 
			
		||||
		movs		r12, r3, lsl #31
 | 
			
		||||
		sub			r2, r2, r3		/* we know that r3 <= r2 because r2 >= 4 */
 | 
			
		||||
		ldrmib		r3, [r1], #1
 | 
			
		||||
		ldrcsb		r4, [r1], #1
 | 
			
		||||
		ldrcsb		r12,[r1], #1
 | 
			
		||||
        strmib		r3, [r0], #1
 | 
			
		||||
		strcsb		r4, [r0], #1
 | 
			
		||||
		strcsb		r12,[r0], #1
 | 
			
		||||
 | 
			
		||||
src_aligned:
 | 
			
		||||
 | 
			
		||||
		/* see if src and dst are aligned together (congruent) */
 | 
			
		||||
		eor			r12, r0, r1
 | 
			
		||||
		tst			r12, #3
 | 
			
		||||
		bne			non_congruent
 | 
			
		||||
 | 
			
		||||
        /* Use post-incriment mode for stm to spill r5-r11 to reserved stack
 | 
			
		||||
         * frame. Don't update sp.
 | 
			
		||||
         */
 | 
			
		||||
        stmea		sp, {r5-r11}
 | 
			
		||||
 | 
			
		||||
		/* align the destination to a cache-line */
 | 
			
		||||
		rsb         r3, r0, #0
 | 
			
		||||
		ands		r3, r3, #0x1C
 | 
			
		||||
		beq         congruent_aligned32
 | 
			
		||||
		cmp         r3, r2
 | 
			
		||||
		andhi		r3, r2, #0x1C
 | 
			
		||||
 | 
			
		||||
		/* conditionnaly copies 0 to 7 words (length in r3) */
 | 
			
		||||
		movs		r12, r3, lsl #28
 | 
			
		||||
		ldmcsia		r1!, {r4, r5, r6, r7}	/* 16 bytes */
 | 
			
		||||
		ldmmiia		r1!, {r8, r9}			/*  8 bytes */
 | 
			
		||||
		stmcsia		r0!, {r4, r5, r6, r7}
 | 
			
		||||
		stmmiia		r0!, {r8, r9}
 | 
			
		||||
		tst         r3, #0x4
 | 
			
		||||
		ldrne		r10,[r1], #4			/*  4 bytes */
 | 
			
		||||
		strne		r10,[r0], #4
 | 
			
		||||
		sub         r2, r2, r3
 | 
			
		||||
 | 
			
		||||
congruent_aligned32:
 | 
			
		||||
		/*
 | 
			
		||||
		 * here source is aligned to 32 bytes.
 | 
			
		||||
		 */
 | 
			
		||||
 | 
			
		||||
cached_aligned32:
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        blo         less_than_32_left
 | 
			
		||||
 | 
			
		||||
        /*
 | 
			
		||||
         * We preload a cache-line up to 64 bytes ahead. On the 926, this will
 | 
			
		||||
         * stall only until the requested world is fetched, but the linefill
 | 
			
		||||
         * continues in the the background.
 | 
			
		||||
         * While the linefill is going, we write our previous cache-line
 | 
			
		||||
         * into the write-buffer (which should have some free space).
 | 
			
		||||
         * When the linefill is done, the writebuffer will
 | 
			
		||||
         * start dumping its content into memory
 | 
			
		||||
         *
 | 
			
		||||
         * While all this is going, we then load a full cache line into
 | 
			
		||||
         * 8 registers, this cache line should be in the cache by now
 | 
			
		||||
         * (or partly in the cache).
 | 
			
		||||
         *
 | 
			
		||||
         * This code should work well regardless of the source/dest alignment.
 | 
			
		||||
         *
 | 
			
		||||
         */
 | 
			
		||||
 | 
			
		||||
        // Align the preload register to a cache-line because the cpu does
 | 
			
		||||
        // "critical word first" (the first word requested is loaded first).
 | 
			
		||||
        bic         r12, r1, #0x1F
 | 
			
		||||
        add         r12, r12, #64
 | 
			
		||||
 | 
			
		||||
1:      ldmia       r1!, { r4-r11 }
 | 
			
		||||
        pld         [r12, #64]
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
 | 
			
		||||
        // NOTE: if r12 is more than 64 ahead of r1, the following ldrhi
 | 
			
		||||
        // for ARM9 preload will not be safely guarded by the preceding subs.
 | 
			
		||||
        // When it is safely guarded the only possibility to have SIGSEGV here
 | 
			
		||||
        // is because the caller overstates the length.
 | 
			
		||||
        ldrhi       r3, [r12], #32      /* cheap ARM9 preload */
 | 
			
		||||
        stmia       r0!, { r4-r11 }
 | 
			
		||||
		bhs         1b
 | 
			
		||||
 | 
			
		||||
        add         r2, r2, #32
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
less_than_32_left:
 | 
			
		||||
		/*
 | 
			
		||||
		 * less than 32 bytes left at this point (length in r2)
 | 
			
		||||
		 */
 | 
			
		||||
 | 
			
		||||
		/* skip all this if there is nothing to do, which should
 | 
			
		||||
		 * be a common case (if not executed the code below takes
 | 
			
		||||
		 * about 16 cycles)
 | 
			
		||||
		 */
 | 
			
		||||
		tst			r2, #0x1F
 | 
			
		||||
		beq			1f
 | 
			
		||||
 | 
			
		||||
		/* conditionnaly copies 0 to 31 bytes */
 | 
			
		||||
		movs		r12, r2, lsl #28
 | 
			
		||||
		ldmcsia		r1!, {r4, r5, r6, r7}	/* 16 bytes */
 | 
			
		||||
		ldmmiia		r1!, {r8, r9}			/*  8 bytes */
 | 
			
		||||
		stmcsia		r0!, {r4, r5, r6, r7}
 | 
			
		||||
		stmmiia		r0!, {r8, r9}
 | 
			
		||||
		movs		r12, r2, lsl #30
 | 
			
		||||
		ldrcs		r3, [r1], #4			/*  4 bytes */
 | 
			
		||||
		ldrmih		r4, [r1], #2			/*  2 bytes */
 | 
			
		||||
		strcs		r3, [r0], #4
 | 
			
		||||
		strmih		r4, [r0], #2
 | 
			
		||||
		tst         r2, #0x1
 | 
			
		||||
		ldrneb		r3, [r1]				/*  last byte  */
 | 
			
		||||
		strneb		r3, [r0]
 | 
			
		||||
 | 
			
		||||
		/* we're done! restore everything and return */
 | 
			
		||||
1:		ldmfd		sp!, {r5-r11}
 | 
			
		||||
		ldmfd		sp!, {r0, r4, lr}
 | 
			
		||||
		bx			lr
 | 
			
		||||
 | 
			
		||||
		/********************************************************************/
 | 
			
		||||
 | 
			
		||||
non_congruent:
 | 
			
		||||
		/*
 | 
			
		||||
		 * here source is aligned to 4 bytes
 | 
			
		||||
		 * but destination is not.
 | 
			
		||||
		 *
 | 
			
		||||
		 * in the code below r2 is the number of bytes read
 | 
			
		||||
		 * (the number of bytes written is always smaller, because we have
 | 
			
		||||
		 * partial words in the shift queue)
 | 
			
		||||
		 */
 | 
			
		||||
		cmp			r2, #4
 | 
			
		||||
		blo			copy_last_3_and_return
 | 
			
		||||
 | 
			
		||||
        /* Use post-incriment mode for stm to spill r5-r11 to reserved stack
 | 
			
		||||
         * frame. Don't update sp.
 | 
			
		||||
         */
 | 
			
		||||
        stmea		sp, {r5-r11}
 | 
			
		||||
 | 
			
		||||
		/* compute shifts needed to align src to dest */
 | 
			
		||||
		rsb			r5, r0, #0
 | 
			
		||||
		and			r5, r5, #3			/* r5 = # bytes in partial words */
 | 
			
		||||
		mov			r12, r5, lsl #3		/* r12 = right */
 | 
			
		||||
		rsb			lr, r12, #32		/* lr = left  */
 | 
			
		||||
 | 
			
		||||
		/* read the first word */
 | 
			
		||||
		ldr			r3, [r1], #4
 | 
			
		||||
		sub			r2, r2, #4
 | 
			
		||||
 | 
			
		||||
		/* write a partial word (0 to 3 bytes), such that destination
 | 
			
		||||
		 * becomes aligned to 32 bits (r5 = nb of words to copy for alignment)
 | 
			
		||||
		 */
 | 
			
		||||
		movs		r5, r5, lsl #31
 | 
			
		||||
		strmib		r3, [r0], #1
 | 
			
		||||
		movmi		r3, r3, lsr #8
 | 
			
		||||
		strcsb		r3, [r0], #1
 | 
			
		||||
		movcs		r3, r3, lsr #8
 | 
			
		||||
		strcsb		r3, [r0], #1
 | 
			
		||||
		movcs		r3, r3, lsr #8
 | 
			
		||||
 | 
			
		||||
		cmp			r2, #4
 | 
			
		||||
		blo			partial_word_tail
 | 
			
		||||
 | 
			
		||||
		/* Align destination to 32 bytes (cache line boundary) */
 | 
			
		||||
1:		tst			r0, #0x1c
 | 
			
		||||
		beq			2f
 | 
			
		||||
		ldr			r5, [r1], #4
 | 
			
		||||
		sub         r2, r2, #4
 | 
			
		||||
		orr			r4, r3, r5,		lsl lr
 | 
			
		||||
		mov			r3, r5,			lsr r12
 | 
			
		||||
		str			r4, [r0], #4
 | 
			
		||||
        cmp         r2, #4
 | 
			
		||||
		bhs			1b
 | 
			
		||||
		blo			partial_word_tail
 | 
			
		||||
 | 
			
		||||
		/* copy 32 bytes at a time */
 | 
			
		||||
2:		subs		r2, r2, #32
 | 
			
		||||
		blo			less_than_thirtytwo
 | 
			
		||||
 | 
			
		||||
		/* Use immediate mode for the shifts, because there is an extra cycle
 | 
			
		||||
		 * for register shifts, which could account for up to 50% of
 | 
			
		||||
		 * performance hit.
 | 
			
		||||
		 */
 | 
			
		||||
 | 
			
		||||
        cmp			r12, #24
 | 
			
		||||
		beq			loop24
 | 
			
		||||
		cmp			r12, #8
 | 
			
		||||
		beq			loop8
 | 
			
		||||
 | 
			
		||||
loop16:
 | 
			
		||||
        ldr         r12, [r1], #4
 | 
			
		||||
1:      mov         r4, r12
 | 
			
		||||
		ldmia		r1!, {   r5,r6,r7,  r8,r9,r10,r11}
 | 
			
		||||
        pld         [r1, #64]
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        ldrhs       r12, [r1], #4
 | 
			
		||||
		orr			r3, r3, r4,		lsl #16
 | 
			
		||||
		mov			r4, r4,			lsr #16
 | 
			
		||||
		orr			r4, r4, r5,		lsl #16
 | 
			
		||||
		mov			r5, r5,			lsr #16
 | 
			
		||||
		orr			r5, r5, r6,		lsl #16
 | 
			
		||||
		mov			r6, r6,			lsr #16
 | 
			
		||||
		orr			r6, r6, r7,		lsl #16
 | 
			
		||||
		mov			r7, r7,			lsr #16
 | 
			
		||||
		orr			r7, r7, r8,		lsl #16
 | 
			
		||||
		mov			r8, r8,			lsr #16
 | 
			
		||||
		orr			r8, r8, r9,		lsl #16
 | 
			
		||||
		mov			r9, r9,			lsr #16
 | 
			
		||||
		orr			r9, r9, r10,	lsl #16
 | 
			
		||||
		mov			r10, r10,		lsr #16
 | 
			
		||||
		orr			r10, r10, r11,	lsl #16
 | 
			
		||||
		stmia		r0!, {r3,r4,r5,r6, r7,r8,r9,r10}
 | 
			
		||||
		mov			r3, r11,		lsr #16
 | 
			
		||||
		bhs			1b
 | 
			
		||||
		b			less_than_thirtytwo
 | 
			
		||||
 | 
			
		||||
loop8:
 | 
			
		||||
        ldr         r12, [r1], #4
 | 
			
		||||
1:      mov         r4, r12
 | 
			
		||||
		ldmia		r1!, {   r5,r6,r7,  r8,r9,r10,r11}
 | 
			
		||||
        pld         [r1, #64]
 | 
			
		||||
		subs		r2, r2, #32
 | 
			
		||||
        ldrhs       r12, [r1], #4
 | 
			
		||||
		orr			r3, r3, r4,		lsl #24
 | 
			
		||||
		mov			r4, r4,			lsr #8
 | 
			
		||||
		orr			r4, r4, r5,		lsl #24
 | 
			
		||||
		mov			r5, r5,			lsr #8
 | 
			
		||||
		orr			r5, r5, r6,		lsl #24
 | 
			
		||||
		mov			r6, r6,			lsr #8
 | 
			
		||||
		orr			r6, r6, r7,		lsl #24
 | 
			
		||||
		mov			r7, r7,			lsr #8
 | 
			
		||||
		orr			r7, r7, r8,		lsl #24
 | 
			
		||||
		mov			r8, r8,			lsr #8
 | 
			
		||||
		orr			r8, r8, r9,		lsl #24
 | 
			
		||||
		mov			r9, r9,			lsr #8
 | 
			
		||||
		orr			r9, r9, r10,	lsl #24
 | 
			
		||||
		mov			r10, r10,		lsr #8
 | 
			
		||||
		orr			r10, r10, r11,	lsl #24
 | 
			
		||||
		stmia		r0!, {r3,r4,r5,r6, r7,r8,r9,r10}
 | 
			
		||||
		mov			r3, r11,		lsr #8
 | 
			
		||||
		bhs			1b
 | 
			
		||||
		b			less_than_thirtytwo
 | 
			
		||||
 | 
			
		||||
loop24:
 | 
			
		||||
        ldr         r12, [r1], #4
 | 
			
		||||
1:      mov         r4, r12
 | 
			
		||||
		ldmia		r1!, {   r5,r6,r7,  r8,r9,r10,r11}
 | 
			
		||||
        pld         [r1, #64]
 | 
			
		||||
		subs		r2, r2, #32
 | 
			
		||||
        ldrhs       r12, [r1], #4
 | 
			
		||||
		orr			r3, r3, r4,		lsl #8
 | 
			
		||||
		mov			r4, r4,			lsr #24
 | 
			
		||||
		orr			r4, r4, r5,		lsl #8
 | 
			
		||||
		mov			r5, r5,			lsr #24
 | 
			
		||||
		orr			r5, r5, r6,		lsl #8
 | 
			
		||||
		mov			r6, r6,			lsr #24
 | 
			
		||||
		orr			r6, r6, r7,		lsl #8
 | 
			
		||||
		mov			r7, r7,			lsr #24
 | 
			
		||||
		orr			r7, r7, r8,		lsl #8
 | 
			
		||||
		mov			r8, r8,			lsr #24
 | 
			
		||||
		orr			r8, r8, r9,		lsl #8
 | 
			
		||||
		mov			r9, r9,			lsr #24
 | 
			
		||||
		orr			r9, r9, r10,	lsl #8
 | 
			
		||||
		mov			r10, r10,		lsr #24
 | 
			
		||||
		orr			r10, r10, r11,	lsl #8
 | 
			
		||||
		stmia		r0!, {r3,r4,r5,r6, r7,r8,r9,r10}
 | 
			
		||||
		mov			r3, r11,		lsr #24
 | 
			
		||||
		bhs			1b
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
less_than_thirtytwo:
 | 
			
		||||
		/* copy the last 0 to 31 bytes of the source */
 | 
			
		||||
		rsb			r12, lr, #32		/* we corrupted r12, recompute it  */
 | 
			
		||||
		add			r2, r2, #32
 | 
			
		||||
		cmp			r2, #4
 | 
			
		||||
		blo			partial_word_tail
 | 
			
		||||
 | 
			
		||||
1:		ldr			r5, [r1], #4
 | 
			
		||||
		sub         r2, r2, #4
 | 
			
		||||
		orr			r4, r3, r5,		lsl lr
 | 
			
		||||
		mov			r3,	r5,			lsr r12
 | 
			
		||||
		str			r4, [r0], #4
 | 
			
		||||
        cmp         r2, #4
 | 
			
		||||
		bhs			1b
 | 
			
		||||
 | 
			
		||||
partial_word_tail:
 | 
			
		||||
		/* we have a partial word in the input buffer */
 | 
			
		||||
		movs		r5, lr, lsl #(31-3)
 | 
			
		||||
		strmib		r3, [r0], #1
 | 
			
		||||
		movmi		r3, r3, lsr #8
 | 
			
		||||
		strcsb		r3, [r0], #1
 | 
			
		||||
		movcs		r3, r3, lsr #8
 | 
			
		||||
		strcsb		r3, [r0], #1
 | 
			
		||||
 | 
			
		||||
		/* Refill spilled registers from the stack. Don't update sp. */
 | 
			
		||||
		ldmfd		sp, {r5-r11}
 | 
			
		||||
 | 
			
		||||
copy_last_3_and_return:
 | 
			
		||||
		movs		r2, r2, lsl #31	/* copy remaining 0, 1, 2 or 3 bytes */
 | 
			
		||||
		ldrmib		r2, [r1], #1
 | 
			
		||||
		ldrcsb		r3, [r1], #1
 | 
			
		||||
		ldrcsb		r12,[r1]
 | 
			
		||||
		strmib		r2, [r0], #1
 | 
			
		||||
		strcsb		r3, [r0], #1
 | 
			
		||||
		strcsb		r12,[r0]
 | 
			
		||||
 | 
			
		||||
        /* we're done! restore sp and spilled registers and return */
 | 
			
		||||
        add         sp,  sp, #28
 | 
			
		||||
		ldmfd		sp!, {r0, r4, lr}
 | 
			
		||||
		bx			lr
 | 
			
		||||
END(memcpy)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif    /* __ARM_ARCH__ < 7 */
 | 
			
		||||
							
								
								
									
										614
									
								
								libc/arch-arm/bionic/memcpy.a9.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										614
									
								
								libc/arch-arm/bionic/memcpy.a9.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,614 @@
 | 
			
		||||
/* Copyright (c) 2013, Linaro Limited
 | 
			
		||||
   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 Linaro Limited 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
 | 
			
		||||
   HOLDER 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.
 | 
			
		||||
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
   This memcpy routine is optimised for Cortex-A15 cores and takes advantage
 | 
			
		||||
   of VFP or NEON when built with the appropriate flags.
 | 
			
		||||
 | 
			
		||||
   Assumptions:
 | 
			
		||||
 | 
			
		||||
    ARMv6 (ARMv7-a if using Neon)
 | 
			
		||||
    ARM state
 | 
			
		||||
    Unaligned accesses
 | 
			
		||||
    LDRD/STRD support unaligned word accesses
 | 
			
		||||
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <machine/cpu-features.h>
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
	.syntax unified
 | 
			
		||||
	/* This implementation requires ARM state.  */
 | 
			
		||||
	.arm
 | 
			
		||||
 | 
			
		||||
#ifdef __ARM_NEON__
 | 
			
		||||
 | 
			
		||||
	.fpu	neon
 | 
			
		||||
	.arch	armv7-a
 | 
			
		||||
# define FRAME_SIZE	4
 | 
			
		||||
# define USE_VFP
 | 
			
		||||
# define USE_NEON
 | 
			
		||||
 | 
			
		||||
#elif !defined (__SOFTFP__)
 | 
			
		||||
 | 
			
		||||
	.arch	armv6
 | 
			
		||||
	.fpu	vfpv2
 | 
			
		||||
# define FRAME_SIZE	32
 | 
			
		||||
# define USE_VFP
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
	.arch	armv6
 | 
			
		||||
# define FRAME_SIZE    32
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Old versions of GAS incorrectly implement the NEON align semantics.  */
 | 
			
		||||
#ifdef BROKEN_ASM_NEON_ALIGN
 | 
			
		||||
#define ALIGN(addr, align) addr,:align
 | 
			
		||||
#else
 | 
			
		||||
#define ALIGN(addr, align) addr:align
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define PC_OFFSET	8	/* PC pipeline compensation.  */
 | 
			
		||||
#define INSN_SIZE	4
 | 
			
		||||
 | 
			
		||||
/* Call parameters.  */
 | 
			
		||||
#define dstin	r0
 | 
			
		||||
#define src	r1
 | 
			
		||||
#define count	r2
 | 
			
		||||
 | 
			
		||||
/* Locals.  */
 | 
			
		||||
#define tmp1	r3
 | 
			
		||||
#define dst	ip
 | 
			
		||||
#define tmp2	r10
 | 
			
		||||
 | 
			
		||||
#ifndef USE_NEON
 | 
			
		||||
/* For bulk copies using GP registers.  */
 | 
			
		||||
#define	A_l	r2		/* Call-clobbered.  */
 | 
			
		||||
#define	A_h	r3		/* Call-clobbered.  */
 | 
			
		||||
#define	B_l	r4
 | 
			
		||||
#define	B_h	r5
 | 
			
		||||
#define	C_l	r6
 | 
			
		||||
#define	C_h	r7
 | 
			
		||||
#define	D_l	r8
 | 
			
		||||
#define	D_h	r9
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Number of lines ahead to pre-fetch data.  If you change this the code
 | 
			
		||||
   below will need adjustment to compensate.  */
 | 
			
		||||
 | 
			
		||||
#define prefetch_lines	5
 | 
			
		||||
 | 
			
		||||
#ifdef USE_VFP
 | 
			
		||||
	.macro	cpy_line_vfp vreg, base
 | 
			
		||||
	vstr	\vreg, [dst, #\base]
 | 
			
		||||
	vldr	\vreg, [src, #\base]
 | 
			
		||||
	vstr	d0, [dst, #\base + 8]
 | 
			
		||||
	vldr	d0, [src, #\base + 8]
 | 
			
		||||
	vstr	d1, [dst, #\base + 16]
 | 
			
		||||
	vldr	d1, [src, #\base + 16]
 | 
			
		||||
	vstr	d2, [dst, #\base + 24]
 | 
			
		||||
	vldr	d2, [src, #\base + 24]
 | 
			
		||||
	vstr	\vreg, [dst, #\base + 32]
 | 
			
		||||
	vldr	\vreg, [src, #\base + prefetch_lines * 64 - 32]
 | 
			
		||||
	vstr	d0, [dst, #\base + 40]
 | 
			
		||||
	vldr	d0, [src, #\base + 40]
 | 
			
		||||
	vstr	d1, [dst, #\base + 48]
 | 
			
		||||
	vldr	d1, [src, #\base + 48]
 | 
			
		||||
	vstr	d2, [dst, #\base + 56]
 | 
			
		||||
	vldr	d2, [src, #\base + 56]
 | 
			
		||||
	.endm
 | 
			
		||||
 | 
			
		||||
	.macro	cpy_tail_vfp vreg, base
 | 
			
		||||
	vstr	\vreg, [dst, #\base]
 | 
			
		||||
	vldr	\vreg, [src, #\base]
 | 
			
		||||
	vstr	d0, [dst, #\base + 8]
 | 
			
		||||
	vldr	d0, [src, #\base + 8]
 | 
			
		||||
	vstr	d1, [dst, #\base + 16]
 | 
			
		||||
	vldr	d1, [src, #\base + 16]
 | 
			
		||||
	vstr	d2, [dst, #\base + 24]
 | 
			
		||||
	vldr	d2, [src, #\base + 24]
 | 
			
		||||
	vstr	\vreg, [dst, #\base + 32]
 | 
			
		||||
	vstr	d0, [dst, #\base + 40]
 | 
			
		||||
	vldr	d0, [src, #\base + 40]
 | 
			
		||||
	vstr	d1, [dst, #\base + 48]
 | 
			
		||||
	vldr	d1, [src, #\base + 48]
 | 
			
		||||
	vstr	d2, [dst, #\base + 56]
 | 
			
		||||
	vldr	d2, [src, #\base + 56]
 | 
			
		||||
	.endm
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	.p2align 6
 | 
			
		||||
ENTRY(memcpy)
 | 
			
		||||
 | 
			
		||||
	mov	dst, dstin	/* Preserve dstin, we need to return it.  */
 | 
			
		||||
	cmp	count, #64
 | 
			
		||||
	bge	.Lcpy_not_short
 | 
			
		||||
	/* Deal with small copies quickly by dropping straight into the
 | 
			
		||||
	   exit block.  */
 | 
			
		||||
 | 
			
		||||
.Ltail63unaligned:
 | 
			
		||||
#ifdef USE_NEON
 | 
			
		||||
	and	tmp1, count, #0x38
 | 
			
		||||
	rsb	tmp1, tmp1, #(56 - PC_OFFSET + INSN_SIZE)
 | 
			
		||||
	add	pc, pc, tmp1
 | 
			
		||||
	vld1.8	{d0}, [src]!	/* 14 words to go.  */
 | 
			
		||||
	vst1.8	{d0}, [dst]!
 | 
			
		||||
	vld1.8	{d0}, [src]!	/* 12 words to go.  */
 | 
			
		||||
	vst1.8	{d0}, [dst]!
 | 
			
		||||
	vld1.8	{d0}, [src]!	/* 10 words to go.  */
 | 
			
		||||
	vst1.8	{d0}, [dst]!
 | 
			
		||||
	vld1.8	{d0}, [src]!	/* 8 words to go.  */
 | 
			
		||||
	vst1.8	{d0}, [dst]!
 | 
			
		||||
	vld1.8	{d0}, [src]!	/* 6 words to go.  */
 | 
			
		||||
	vst1.8	{d0}, [dst]!
 | 
			
		||||
	vld1.8	{d0}, [src]!	/* 4 words to go.  */
 | 
			
		||||
	vst1.8	{d0}, [dst]!
 | 
			
		||||
	vld1.8	{d0}, [src]!	/* 2 words to go.  */
 | 
			
		||||
	vst1.8	{d0}, [dst]!
 | 
			
		||||
 | 
			
		||||
	tst	count, #4
 | 
			
		||||
	ldrne	tmp1, [src], #4
 | 
			
		||||
	strne	tmp1, [dst], #4
 | 
			
		||||
#else
 | 
			
		||||
	/* Copy up to 15 full words of data.  May not be aligned.  */
 | 
			
		||||
	/* Cannot use VFP for unaligned data.  */
 | 
			
		||||
	and	tmp1, count, #0x3c
 | 
			
		||||
	add	dst, dst, tmp1
 | 
			
		||||
	add	src, src, tmp1
 | 
			
		||||
	rsb	tmp1, tmp1, #(60 - PC_OFFSET/2 + INSN_SIZE/2)
 | 
			
		||||
	/* Jump directly into the sequence below at the correct offset.  */
 | 
			
		||||
	add	pc, pc, tmp1, lsl #1
 | 
			
		||||
 | 
			
		||||
	ldr	tmp1, [src, #-60]	/* 15 words to go.  */
 | 
			
		||||
	str	tmp1, [dst, #-60]
 | 
			
		||||
 | 
			
		||||
	ldr	tmp1, [src, #-56]	/* 14 words to go.  */
 | 
			
		||||
	str	tmp1, [dst, #-56]
 | 
			
		||||
	ldr	tmp1, [src, #-52]
 | 
			
		||||
	str	tmp1, [dst, #-52]
 | 
			
		||||
 | 
			
		||||
	ldr	tmp1, [src, #-48]	/* 12 words to go.  */
 | 
			
		||||
	str	tmp1, [dst, #-48]
 | 
			
		||||
	ldr	tmp1, [src, #-44]
 | 
			
		||||
	str	tmp1, [dst, #-44]
 | 
			
		||||
 | 
			
		||||
	ldr	tmp1, [src, #-40]	/* 10 words to go.  */
 | 
			
		||||
	str	tmp1, [dst, #-40]
 | 
			
		||||
	ldr	tmp1, [src, #-36]
 | 
			
		||||
	str	tmp1, [dst, #-36]
 | 
			
		||||
 | 
			
		||||
	ldr	tmp1, [src, #-32]	/* 8 words to go.  */
 | 
			
		||||
	str	tmp1, [dst, #-32]
 | 
			
		||||
	ldr	tmp1, [src, #-28]
 | 
			
		||||
	str	tmp1, [dst, #-28]
 | 
			
		||||
 | 
			
		||||
	ldr	tmp1, [src, #-24]	/* 6 words to go.  */
 | 
			
		||||
	str	tmp1, [dst, #-24]
 | 
			
		||||
	ldr	tmp1, [src, #-20]
 | 
			
		||||
	str	tmp1, [dst, #-20]
 | 
			
		||||
 | 
			
		||||
	ldr	tmp1, [src, #-16]	/* 4 words to go.  */
 | 
			
		||||
	str	tmp1, [dst, #-16]
 | 
			
		||||
	ldr	tmp1, [src, #-12]
 | 
			
		||||
	str	tmp1, [dst, #-12]
 | 
			
		||||
 | 
			
		||||
	ldr	tmp1, [src, #-8]	/* 2 words to go.  */
 | 
			
		||||
	str	tmp1, [dst, #-8]
 | 
			
		||||
	ldr	tmp1, [src, #-4]
 | 
			
		||||
	str	tmp1, [dst, #-4]
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	lsls	count, count, #31
 | 
			
		||||
	ldrhcs	tmp1, [src], #2
 | 
			
		||||
	ldrbne	src, [src]		/* Src is dead, use as a scratch.  */
 | 
			
		||||
	strhcs	tmp1, [dst], #2
 | 
			
		||||
	strbne	src, [dst]
 | 
			
		||||
	bx	lr
 | 
			
		||||
 | 
			
		||||
.Lcpy_not_short:
 | 
			
		||||
	/* At least 64 bytes to copy, but don't know the alignment yet.  */
 | 
			
		||||
	str	tmp2, [sp, #-FRAME_SIZE]!
 | 
			
		||||
	and	tmp2, src, #7
 | 
			
		||||
	and	tmp1, dst, #7
 | 
			
		||||
	cmp	tmp1, tmp2
 | 
			
		||||
	bne	.Lcpy_notaligned
 | 
			
		||||
 | 
			
		||||
#ifdef USE_VFP
 | 
			
		||||
	/* Magic dust alert!  Force VFP on Cortex-A9.  Experiments show
 | 
			
		||||
	   that the FP pipeline is much better at streaming loads and
 | 
			
		||||
	   stores.  This is outside the critical loop.  */
 | 
			
		||||
	vmov.f32	s0, s0
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	/* SRC and DST have the same mutual 32-bit alignment, but we may
 | 
			
		||||
	   still need to pre-copy some bytes to get to natural alignment.
 | 
			
		||||
	   We bring DST into full 64-bit alignment.  */
 | 
			
		||||
	lsls	tmp2, dst, #29
 | 
			
		||||
	beq	1f
 | 
			
		||||
	rsbs	tmp2, tmp2, #0
 | 
			
		||||
	sub	count, count, tmp2, lsr #29
 | 
			
		||||
	ldrmi	tmp1, [src], #4
 | 
			
		||||
	strmi	tmp1, [dst], #4
 | 
			
		||||
	lsls	tmp2, tmp2, #2
 | 
			
		||||
	ldrhcs	tmp1, [src], #2
 | 
			
		||||
	ldrbne	tmp2, [src], #1
 | 
			
		||||
	strhcs	tmp1, [dst], #2
 | 
			
		||||
	strbne	tmp2, [dst], #1
 | 
			
		||||
 | 
			
		||||
1:
 | 
			
		||||
	subs	tmp2, count, #64	/* Use tmp2 for count.  */
 | 
			
		||||
	blt	.Ltail63aligned
 | 
			
		||||
 | 
			
		||||
	cmp	tmp2, #512
 | 
			
		||||
	bge	.Lcpy_body_long
 | 
			
		||||
 | 
			
		||||
.Lcpy_body_medium:			/* Count in tmp2.  */
 | 
			
		||||
#ifdef USE_VFP
 | 
			
		||||
1:
 | 
			
		||||
	vldr	d0, [src, #0]
 | 
			
		||||
	subs	tmp2, tmp2, #64
 | 
			
		||||
	vldr	d1, [src, #8]
 | 
			
		||||
	vstr	d0, [dst, #0]
 | 
			
		||||
	vldr	d0, [src, #16]
 | 
			
		||||
	vstr	d1, [dst, #8]
 | 
			
		||||
	vldr	d1, [src, #24]
 | 
			
		||||
	vstr	d0, [dst, #16]
 | 
			
		||||
	vldr	d0, [src, #32]
 | 
			
		||||
	vstr	d1, [dst, #24]
 | 
			
		||||
	vldr	d1, [src, #40]
 | 
			
		||||
	vstr	d0, [dst, #32]
 | 
			
		||||
	vldr	d0, [src, #48]
 | 
			
		||||
	vstr	d1, [dst, #40]
 | 
			
		||||
	vldr	d1, [src, #56]
 | 
			
		||||
	vstr	d0, [dst, #48]
 | 
			
		||||
	add	src, src, #64
 | 
			
		||||
	vstr	d1, [dst, #56]
 | 
			
		||||
	add	dst, dst, #64
 | 
			
		||||
	bge	1b
 | 
			
		||||
	tst	tmp2, #0x3f
 | 
			
		||||
	beq	.Ldone
 | 
			
		||||
 | 
			
		||||
.Ltail63aligned:			/* Count in tmp2.  */
 | 
			
		||||
	and	tmp1, tmp2, #0x38
 | 
			
		||||
	add	dst, dst, tmp1
 | 
			
		||||
	add	src, src, tmp1
 | 
			
		||||
	rsb	tmp1, tmp1, #(56 - PC_OFFSET + INSN_SIZE)
 | 
			
		||||
	add	pc, pc, tmp1
 | 
			
		||||
 | 
			
		||||
	vldr	d0, [src, #-56]	/* 14 words to go.  */
 | 
			
		||||
	vstr	d0, [dst, #-56]
 | 
			
		||||
	vldr	d0, [src, #-48]	/* 12 words to go.  */
 | 
			
		||||
	vstr	d0, [dst, #-48]
 | 
			
		||||
	vldr	d0, [src, #-40]	/* 10 words to go.  */
 | 
			
		||||
	vstr	d0, [dst, #-40]
 | 
			
		||||
	vldr	d0, [src, #-32]	/* 8 words to go.  */
 | 
			
		||||
	vstr	d0, [dst, #-32]
 | 
			
		||||
	vldr	d0, [src, #-24]	/* 6 words to go.  */
 | 
			
		||||
	vstr	d0, [dst, #-24]
 | 
			
		||||
	vldr	d0, [src, #-16]	/* 4 words to go.  */
 | 
			
		||||
	vstr	d0, [dst, #-16]
 | 
			
		||||
	vldr	d0, [src, #-8]	/* 2 words to go.  */
 | 
			
		||||
	vstr	d0, [dst, #-8]
 | 
			
		||||
#else
 | 
			
		||||
	sub	src, src, #8
 | 
			
		||||
	sub	dst, dst, #8
 | 
			
		||||
1:
 | 
			
		||||
	ldrd	A_l, A_h, [src, #8]
 | 
			
		||||
	strd	A_l, A_h, [dst, #8]
 | 
			
		||||
	ldrd	A_l, A_h, [src, #16]
 | 
			
		||||
	strd	A_l, A_h, [dst, #16]
 | 
			
		||||
	ldrd	A_l, A_h, [src, #24]
 | 
			
		||||
	strd	A_l, A_h, [dst, #24]
 | 
			
		||||
	ldrd	A_l, A_h, [src, #32]
 | 
			
		||||
	strd	A_l, A_h, [dst, #32]
 | 
			
		||||
	ldrd	A_l, A_h, [src, #40]
 | 
			
		||||
	strd	A_l, A_h, [dst, #40]
 | 
			
		||||
	ldrd	A_l, A_h, [src, #48]
 | 
			
		||||
	strd	A_l, A_h, [dst, #48]
 | 
			
		||||
	ldrd	A_l, A_h, [src, #56]
 | 
			
		||||
	strd	A_l, A_h, [dst, #56]
 | 
			
		||||
	ldrd	A_l, A_h, [src, #64]!
 | 
			
		||||
	strd	A_l, A_h, [dst, #64]!
 | 
			
		||||
	subs	tmp2, tmp2, #64
 | 
			
		||||
	bge	1b
 | 
			
		||||
	tst	tmp2, #0x3f
 | 
			
		||||
	bne	1f
 | 
			
		||||
	ldr	tmp2,[sp], #FRAME_SIZE
 | 
			
		||||
	bx	lr
 | 
			
		||||
1:
 | 
			
		||||
	add	src, src, #8
 | 
			
		||||
	add	dst, dst, #8
 | 
			
		||||
 | 
			
		||||
.Ltail63aligned:			/* Count in tmp2.  */
 | 
			
		||||
	/* Copy up to 7 d-words of data.  Similar to Ltail63unaligned, but
 | 
			
		||||
	   we know that the src and dest are 32-bit aligned so we can use
 | 
			
		||||
	   LDRD/STRD to improve efficiency.  */
 | 
			
		||||
	/* TMP2 is now negative, but we don't care about that.  The bottom
 | 
			
		||||
	   six bits still tell us how many bytes are left to copy.  */
 | 
			
		||||
 | 
			
		||||
	and	tmp1, tmp2, #0x38
 | 
			
		||||
	add	dst, dst, tmp1
 | 
			
		||||
	add	src, src, tmp1
 | 
			
		||||
	rsb	tmp1, tmp1, #(56 - PC_OFFSET + INSN_SIZE)
 | 
			
		||||
	add	pc, pc, tmp1
 | 
			
		||||
	ldrd	A_l, A_h, [src, #-56]	/* 14 words to go.  */
 | 
			
		||||
	strd	A_l, A_h, [dst, #-56]
 | 
			
		||||
	ldrd	A_l, A_h, [src, #-48]	/* 12 words to go.  */
 | 
			
		||||
	strd	A_l, A_h, [dst, #-48]
 | 
			
		||||
	ldrd	A_l, A_h, [src, #-40]	/* 10 words to go.  */
 | 
			
		||||
	strd	A_l, A_h, [dst, #-40]
 | 
			
		||||
	ldrd	A_l, A_h, [src, #-32]	/* 8 words to go.  */
 | 
			
		||||
	strd	A_l, A_h, [dst, #-32]
 | 
			
		||||
	ldrd	A_l, A_h, [src, #-24]	/* 6 words to go.  */
 | 
			
		||||
	strd	A_l, A_h, [dst, #-24]
 | 
			
		||||
	ldrd	A_l, A_h, [src, #-16]	/* 4 words to go.  */
 | 
			
		||||
	strd	A_l, A_h, [dst, #-16]
 | 
			
		||||
	ldrd	A_l, A_h, [src, #-8]	/* 2 words to go.  */
 | 
			
		||||
	strd	A_l, A_h, [dst, #-8]
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
	tst	tmp2, #4
 | 
			
		||||
	ldrne	tmp1, [src], #4
 | 
			
		||||
	strne	tmp1, [dst], #4
 | 
			
		||||
	lsls	tmp2, tmp2, #31		/* Count (tmp2) now dead. */
 | 
			
		||||
	ldrhcs	tmp1, [src], #2
 | 
			
		||||
	ldrbne	tmp2, [src]
 | 
			
		||||
	strhcs	tmp1, [dst], #2
 | 
			
		||||
	strbne	tmp2, [dst]
 | 
			
		||||
 | 
			
		||||
.Ldone:
 | 
			
		||||
	ldr	tmp2, [sp], #FRAME_SIZE
 | 
			
		||||
	bx	lr
 | 
			
		||||
 | 
			
		||||
.Lcpy_body_long:			/* Count in tmp2.  */
 | 
			
		||||
 | 
			
		||||
	/* Long copy.  We know that there's at least (prefetch_lines * 64)
 | 
			
		||||
	   bytes to go.  */
 | 
			
		||||
#ifdef USE_VFP
 | 
			
		||||
	/* Don't use PLD.  Instead, read some data in advance of the current
 | 
			
		||||
	   copy position into a register.  This should act like a PLD
 | 
			
		||||
	   operation but we won't have to repeat the transfer.  */
 | 
			
		||||
 | 
			
		||||
	vldr	d3, [src, #0]
 | 
			
		||||
	vldr	d4, [src, #64]
 | 
			
		||||
	vldr	d5, [src, #128]
 | 
			
		||||
	vldr	d6, [src, #192]
 | 
			
		||||
	vldr	d7, [src, #256]
 | 
			
		||||
 | 
			
		||||
	vldr	d0, [src, #8]
 | 
			
		||||
	vldr	d1, [src, #16]
 | 
			
		||||
	vldr	d2, [src, #24]
 | 
			
		||||
	add	src, src, #32
 | 
			
		||||
 | 
			
		||||
	subs	tmp2, tmp2, #prefetch_lines * 64 * 2
 | 
			
		||||
	blt	2f
 | 
			
		||||
1:
 | 
			
		||||
	cpy_line_vfp	d3, 0
 | 
			
		||||
	cpy_line_vfp	d4, 64
 | 
			
		||||
	cpy_line_vfp	d5, 128
 | 
			
		||||
	add	dst, dst, #3 * 64
 | 
			
		||||
	add	src, src, #3 * 64
 | 
			
		||||
	cpy_line_vfp	d6, 0
 | 
			
		||||
	cpy_line_vfp	d7, 64
 | 
			
		||||
	add	dst, dst, #2 * 64
 | 
			
		||||
	add	src, src, #2 * 64
 | 
			
		||||
	subs	tmp2, tmp2, #prefetch_lines * 64
 | 
			
		||||
	bge	1b
 | 
			
		||||
 | 
			
		||||
2:
 | 
			
		||||
	cpy_tail_vfp	d3, 0
 | 
			
		||||
	cpy_tail_vfp	d4, 64
 | 
			
		||||
	cpy_tail_vfp	d5, 128
 | 
			
		||||
	add	src, src, #3 * 64
 | 
			
		||||
	add	dst, dst, #3 * 64
 | 
			
		||||
	cpy_tail_vfp	d6, 0
 | 
			
		||||
	vstr	d7, [dst, #64]
 | 
			
		||||
	vldr	d7, [src, #64]
 | 
			
		||||
	vstr	d0, [dst, #64 + 8]
 | 
			
		||||
	vldr	d0, [src, #64 + 8]
 | 
			
		||||
	vstr	d1, [dst, #64 + 16]
 | 
			
		||||
	vldr	d1, [src, #64 + 16]
 | 
			
		||||
	vstr	d2, [dst, #64 + 24]
 | 
			
		||||
	vldr	d2, [src, #64 + 24]
 | 
			
		||||
	vstr	d7, [dst, #64 + 32]
 | 
			
		||||
	add	src, src, #96
 | 
			
		||||
	vstr	d0, [dst, #64 + 40]
 | 
			
		||||
	vstr	d1, [dst, #64 + 48]
 | 
			
		||||
	vstr	d2, [dst, #64 + 56]
 | 
			
		||||
	add	dst, dst, #128
 | 
			
		||||
	add	tmp2, tmp2, #prefetch_lines * 64
 | 
			
		||||
	b	.Lcpy_body_medium
 | 
			
		||||
#else
 | 
			
		||||
	/* Long copy.  Use an SMS style loop to maximize the I/O
 | 
			
		||||
	   bandwidth of the core.  We don't have enough spare registers
 | 
			
		||||
	   to synthesise prefetching, so use PLD operations.  */
 | 
			
		||||
	/* Pre-bias src and dst.  */
 | 
			
		||||
	sub	src, src, #8
 | 
			
		||||
	sub	dst, dst, #8
 | 
			
		||||
	pld	[src, #8]
 | 
			
		||||
	pld	[src, #72]
 | 
			
		||||
	subs	tmp2, tmp2, #64
 | 
			
		||||
	pld	[src, #136]
 | 
			
		||||
	ldrd	A_l, A_h, [src, #8]
 | 
			
		||||
	strd	B_l, B_h, [sp, #8]
 | 
			
		||||
	ldrd	B_l, B_h, [src, #16]
 | 
			
		||||
	strd	C_l, C_h, [sp, #16]
 | 
			
		||||
	ldrd	C_l, C_h, [src, #24]
 | 
			
		||||
	strd	D_l, D_h, [sp, #24]
 | 
			
		||||
	pld	[src, #200]
 | 
			
		||||
	ldrd	D_l, D_h, [src, #32]!
 | 
			
		||||
	b	1f
 | 
			
		||||
	.p2align	6
 | 
			
		||||
2:
 | 
			
		||||
	pld	[src, #232]
 | 
			
		||||
	strd	A_l, A_h, [dst, #40]
 | 
			
		||||
	ldrd	A_l, A_h, [src, #40]
 | 
			
		||||
	strd	B_l, B_h, [dst, #48]
 | 
			
		||||
	ldrd	B_l, B_h, [src, #48]
 | 
			
		||||
	strd	C_l, C_h, [dst, #56]
 | 
			
		||||
	ldrd	C_l, C_h, [src, #56]
 | 
			
		||||
	strd	D_l, D_h, [dst, #64]!
 | 
			
		||||
	ldrd	D_l, D_h, [src, #64]!
 | 
			
		||||
	subs	tmp2, tmp2, #64
 | 
			
		||||
1:
 | 
			
		||||
	strd	A_l, A_h, [dst, #8]
 | 
			
		||||
	ldrd	A_l, A_h, [src, #8]
 | 
			
		||||
	strd	B_l, B_h, [dst, #16]
 | 
			
		||||
	ldrd	B_l, B_h, [src, #16]
 | 
			
		||||
	strd	C_l, C_h, [dst, #24]
 | 
			
		||||
	ldrd	C_l, C_h, [src, #24]
 | 
			
		||||
	strd	D_l, D_h, [dst, #32]
 | 
			
		||||
	ldrd	D_l, D_h, [src, #32]
 | 
			
		||||
	bcs	2b
 | 
			
		||||
	/* Save the remaining bytes and restore the callee-saved regs.  */
 | 
			
		||||
	strd	A_l, A_h, [dst, #40]
 | 
			
		||||
	add	src, src, #40
 | 
			
		||||
	strd	B_l, B_h, [dst, #48]
 | 
			
		||||
	ldrd	B_l, B_h, [sp, #8]
 | 
			
		||||
	strd	C_l, C_h, [dst, #56]
 | 
			
		||||
	ldrd	C_l, C_h, [sp, #16]
 | 
			
		||||
	strd	D_l, D_h, [dst, #64]
 | 
			
		||||
	ldrd	D_l, D_h, [sp, #24]
 | 
			
		||||
	add	dst, dst, #72
 | 
			
		||||
	tst	tmp2, #0x3f
 | 
			
		||||
	bne	.Ltail63aligned
 | 
			
		||||
	ldr	tmp2, [sp], #FRAME_SIZE
 | 
			
		||||
	bx	lr
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
.Lcpy_notaligned:
 | 
			
		||||
	pld	[src]
 | 
			
		||||
	pld	[src, #64]
 | 
			
		||||
	/* There's at least 64 bytes to copy, but there is no mutual
 | 
			
		||||
	   alignment.  */
 | 
			
		||||
	/* Bring DST to 64-bit alignment.  */
 | 
			
		||||
	lsls	tmp2, dst, #29
 | 
			
		||||
	pld	[src, #(2 * 64)]
 | 
			
		||||
	beq	1f
 | 
			
		||||
	rsbs	tmp2, tmp2, #0
 | 
			
		||||
	sub	count, count, tmp2, lsr #29
 | 
			
		||||
	ldrmi	tmp1, [src], #4
 | 
			
		||||
	strmi	tmp1, [dst], #4
 | 
			
		||||
	lsls	tmp2, tmp2, #2
 | 
			
		||||
	ldrbne	tmp1, [src], #1
 | 
			
		||||
	ldrhcs	tmp2, [src], #2
 | 
			
		||||
	strbne	tmp1, [dst], #1
 | 
			
		||||
	strhcs	tmp2, [dst], #2
 | 
			
		||||
1:
 | 
			
		||||
	pld	[src, #(3 * 64)]
 | 
			
		||||
	subs	count, count, #64
 | 
			
		||||
	ldrmi	tmp2, [sp], #FRAME_SIZE
 | 
			
		||||
	bmi	.Ltail63unaligned
 | 
			
		||||
	pld	[src, #(4 * 64)]
 | 
			
		||||
 | 
			
		||||
#ifdef USE_NEON
 | 
			
		||||
	vld1.8	{d0-d3}, [src]!
 | 
			
		||||
	vld1.8	{d4-d7}, [src]!
 | 
			
		||||
	subs	count, count, #64
 | 
			
		||||
	bmi	2f
 | 
			
		||||
1:
 | 
			
		||||
	pld	[src, #(4 * 64)]
 | 
			
		||||
	vst1.8	{d0-d3}, [ALIGN (dst, 64)]!
 | 
			
		||||
	vld1.8	{d0-d3}, [src]!
 | 
			
		||||
	vst1.8	{d4-d7}, [ALIGN (dst, 64)]!
 | 
			
		||||
	vld1.8	{d4-d7}, [src]!
 | 
			
		||||
	subs	count, count, #64
 | 
			
		||||
	bpl	1b
 | 
			
		||||
2:
 | 
			
		||||
	vst1.8	{d0-d3}, [ALIGN (dst, 64)]!
 | 
			
		||||
	vst1.8	{d4-d7}, [ALIGN (dst, 64)]!
 | 
			
		||||
	ands	count, count, #0x3f
 | 
			
		||||
#else
 | 
			
		||||
	/* Use an SMS style loop to maximize the I/O bandwidth.  */
 | 
			
		||||
	sub	src, src, #4
 | 
			
		||||
	sub	dst, dst, #8
 | 
			
		||||
	subs	tmp2, count, #64	/* Use tmp2 for count.  */
 | 
			
		||||
	ldr	A_l, [src, #4]
 | 
			
		||||
	ldr	A_h, [src, #8]
 | 
			
		||||
	strd	B_l, B_h, [sp, #8]
 | 
			
		||||
	ldr	B_l, [src, #12]
 | 
			
		||||
	ldr	B_h, [src, #16]
 | 
			
		||||
	strd	C_l, C_h, [sp, #16]
 | 
			
		||||
	ldr	C_l, [src, #20]
 | 
			
		||||
	ldr	C_h, [src, #24]
 | 
			
		||||
	strd	D_l, D_h, [sp, #24]
 | 
			
		||||
	ldr	D_l, [src, #28]
 | 
			
		||||
	ldr	D_h, [src, #32]!
 | 
			
		||||
	b	1f
 | 
			
		||||
	.p2align	6
 | 
			
		||||
2:
 | 
			
		||||
	pld	[src, #(5 * 64) - (32 - 4)]
 | 
			
		||||
	strd	A_l, A_h, [dst, #40]
 | 
			
		||||
	ldr	A_l, [src, #36]
 | 
			
		||||
	ldr	A_h, [src, #40]
 | 
			
		||||
	strd	B_l, B_h, [dst, #48]
 | 
			
		||||
	ldr	B_l, [src, #44]
 | 
			
		||||
	ldr	B_h, [src, #48]
 | 
			
		||||
	strd	C_l, C_h, [dst, #56]
 | 
			
		||||
	ldr	C_l, [src, #52]
 | 
			
		||||
	ldr	C_h, [src, #56]
 | 
			
		||||
	strd	D_l, D_h, [dst, #64]!
 | 
			
		||||
	ldr	D_l, [src, #60]
 | 
			
		||||
	ldr	D_h, [src, #64]!
 | 
			
		||||
	subs	tmp2, tmp2, #64
 | 
			
		||||
1:
 | 
			
		||||
	strd	A_l, A_h, [dst, #8]
 | 
			
		||||
	ldr	A_l, [src, #4]
 | 
			
		||||
	ldr	A_h, [src, #8]
 | 
			
		||||
	strd	B_l, B_h, [dst, #16]
 | 
			
		||||
	ldr	B_l, [src, #12]
 | 
			
		||||
	ldr	B_h, [src, #16]
 | 
			
		||||
	strd	C_l, C_h, [dst, #24]
 | 
			
		||||
	ldr	C_l, [src, #20]
 | 
			
		||||
	ldr	C_h, [src, #24]
 | 
			
		||||
	strd	D_l, D_h, [dst, #32]
 | 
			
		||||
	ldr	D_l, [src, #28]
 | 
			
		||||
	ldr	D_h, [src, #32]
 | 
			
		||||
	bcs	2b
 | 
			
		||||
 | 
			
		||||
	/* Save the remaining bytes and restore the callee-saved regs.  */
 | 
			
		||||
	strd	A_l, A_h, [dst, #40]
 | 
			
		||||
	add	src, src, #36
 | 
			
		||||
	strd	B_l, B_h, [dst, #48]
 | 
			
		||||
	ldrd	B_l, B_h, [sp, #8]
 | 
			
		||||
	strd	C_l, C_h, [dst, #56]
 | 
			
		||||
	ldrd	C_l, C_h, [sp, #16]
 | 
			
		||||
	strd	D_l, D_h, [dst, #64]
 | 
			
		||||
	ldrd	D_l, D_h, [sp, #24]
 | 
			
		||||
	add	dst, dst, #72
 | 
			
		||||
	ands	count, tmp2, #0x3f
 | 
			
		||||
#endif
 | 
			
		||||
	ldr	tmp2, [sp], #FRAME_SIZE
 | 
			
		||||
	bne	.Ltail63unaligned
 | 
			
		||||
	bx	lr
 | 
			
		||||
END(memcpy)
 | 
			
		||||
@@ -1,3 +1,6 @@
 | 
			
		||||
/*	$OpenBSD: setjmp.S,v 1.2 2004/02/01 05:40:52 drahn Exp $	*/
 | 
			
		||||
/*	$NetBSD: setjmp.S,v 1.5 2003/04/05 23:08:51 bjh21 Exp $	*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 1997 Mark Brinicombe
 | 
			
		||||
 * Copyright (c) 2010 Android Open Source Project.
 | 
			
		||||
@@ -32,142 +35,119 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
#include <machine/setjmp.h>
 | 
			
		||||
#include <machine/cpu-features.h>
 | 
			
		||||
 | 
			
		||||
// According to the ARM AAPCS document, we only need to save
 | 
			
		||||
// the following registers:
 | 
			
		||||
//
 | 
			
		||||
//  Core   r4-r14
 | 
			
		||||
//
 | 
			
		||||
//  VFP    d8-d15  (see section 5.1.2.1)
 | 
			
		||||
//
 | 
			
		||||
//      Registers s16-s31 (d8-d15, q4-q7) must be preserved across subroutine
 | 
			
		||||
//      calls; registers s0-s15 (d0-d7, q0-q3) do not need to be preserved
 | 
			
		||||
//      (and can be used for passing arguments or returning results in standard
 | 
			
		||||
//      procedure-call variants). Registers d16-d31 (q8-q15), if present, do
 | 
			
		||||
//      not need to be preserved.
 | 
			
		||||
//
 | 
			
		||||
//  FPSCR  saved because glibc does.
 | 
			
		||||
 | 
			
		||||
// The internal structure of a jmp_buf is totally private.
 | 
			
		||||
// Current layout (may change in the future):
 | 
			
		||||
//
 | 
			
		||||
// word   name         description
 | 
			
		||||
// 0      magic        magic number
 | 
			
		||||
// 1      sigmask      signal mask (not used with _setjmp / _longjmp)
 | 
			
		||||
// 2      float_base   base of float registers (d8 to d15)
 | 
			
		||||
// 18     float_state  floating-point status and control register
 | 
			
		||||
// 19     core_base    base of core registers (r4 to r14)
 | 
			
		||||
// 30     reserved     reserved entries (room to grow)
 | 
			
		||||
// 64
 | 
			
		||||
//
 | 
			
		||||
// NOTE: float_base must be at an even word index, since the
 | 
			
		||||
//       FP registers will be loaded/stored with instructions
 | 
			
		||||
//       that expect 8-byte alignment.
 | 
			
		||||
 | 
			
		||||
#define _JB_SIGFLAG     0
 | 
			
		||||
#define _JB_SIGMASK     (_JB_SIGFLAG+1)
 | 
			
		||||
#define _JB_FLOAT_BASE  (_JB_SIGMASK+1)
 | 
			
		||||
#define _JB_FLOAT_STATE (_JB_FLOAT_BASE + (15-8+1)*2)
 | 
			
		||||
#define _JB_CORE_BASE   (_JB_FLOAT_STATE+1)
 | 
			
		||||
/*
 | 
			
		||||
 * C library -- setjmp, longjmp
 | 
			
		||||
 *
 | 
			
		||||
 *	longjmp(a,v)
 | 
			
		||||
 * will generate a "return(v)" from the last call to
 | 
			
		||||
 *	setjmp(a)
 | 
			
		||||
 * by restoring registers from the stack.
 | 
			
		||||
 * The previous signal state is restored.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
ENTRY(setjmp)
 | 
			
		||||
  mov r1, #1
 | 
			
		||||
  b sigsetjmp
 | 
			
		||||
	/* Block all signals and retrieve the old signal mask */
 | 
			
		||||
	stmfd	sp!, {r0, r14}
 | 
			
		||||
	.cfi_def_cfa_offset 8
 | 
			
		||||
	.cfi_rel_offset r0, 0
 | 
			
		||||
	.cfi_rel_offset r14, 4
 | 
			
		||||
	mov	r0, #0x00000000
 | 
			
		||||
 | 
			
		||||
	bl	PIC_SYM(sigblock, PLT)
 | 
			
		||||
	mov	r1, r0
 | 
			
		||||
 | 
			
		||||
	ldmfd	sp!, {r0, r14}
 | 
			
		||||
	.cfi_def_cfa_offset 0
 | 
			
		||||
 | 
			
		||||
	/* Store signal mask */
 | 
			
		||||
	str	r1, [r0, #(_JB_SIGMASK * 4)]
 | 
			
		||||
 | 
			
		||||
	ldr	r1, .Lsetjmp_magic
 | 
			
		||||
	str	r1, [r0, #(_JB_MAGIC * 4)]
 | 
			
		||||
 | 
			
		||||
	/* Store core registers */
 | 
			
		||||
	add     r1, r0, #(_JB_CORE_BASE * 4)
 | 
			
		||||
	stmia   r1, {r4-r14}
 | 
			
		||||
 | 
			
		||||
#ifdef __ARM_HAVE_VFP
 | 
			
		||||
	/* Store floating-point registers */
 | 
			
		||||
	add     r1, r0, #(_JB_FLOAT_BASE * 4)
 | 
			
		||||
	vstmia  r1, {d8-d15}
 | 
			
		||||
	/* Store floating-point state */
 | 
			
		||||
	fmrx    r1, fpscr
 | 
			
		||||
	str     r1, [r0, #(_JB_FLOAT_STATE * 4)]
 | 
			
		||||
#endif  /* __ARM_HAVE_VFP */
 | 
			
		||||
 | 
			
		||||
	mov	r0, #0x00000000
 | 
			
		||||
	bx      lr
 | 
			
		||||
END(setjmp)
 | 
			
		||||
 | 
			
		||||
ENTRY(_setjmp)
 | 
			
		||||
  mov r1, #0
 | 
			
		||||
  b sigsetjmp
 | 
			
		||||
END(_setjmp)
 | 
			
		||||
.Lsetjmp_magic:
 | 
			
		||||
	.word	_JB_MAGIC_SETJMP
 | 
			
		||||
 | 
			
		||||
// int sigsetjmp(sigjmp_buf env, int save_signal_mask);
 | 
			
		||||
ENTRY(sigsetjmp)
 | 
			
		||||
  // Record whether or not we're saving the signal mask.
 | 
			
		||||
  str r1, [r0, #(_JB_SIGFLAG * 4)]
 | 
			
		||||
 | 
			
		||||
  // Do we need to save the signal mask?
 | 
			
		||||
  teq r1, #0
 | 
			
		||||
  beq 1f
 | 
			
		||||
ENTRY(longjmp)
 | 
			
		||||
	ldr	r2, .Lsetjmp_magic
 | 
			
		||||
	ldr	r3, [r0, #(_JB_MAGIC * 4)]
 | 
			
		||||
	teq	r2, r3
 | 
			
		||||
	bne	botch
 | 
			
		||||
 | 
			
		||||
  // Get current signal mask.
 | 
			
		||||
  stmfd sp!, {r0, r14}
 | 
			
		||||
  .cfi_def_cfa_offset 8
 | 
			
		||||
  .cfi_rel_offset r0, 0
 | 
			
		||||
  .cfi_rel_offset r14, 4
 | 
			
		||||
  mov r0, #0
 | 
			
		||||
  bl sigblock
 | 
			
		||||
  mov r1, r0
 | 
			
		||||
  ldmfd sp!, {r0, r14}
 | 
			
		||||
  .cfi_def_cfa_offset 0
 | 
			
		||||
	/* Fetch signal mask */
 | 
			
		||||
	ldr	r2, [r0, #(_JB_SIGMASK * 4)]
 | 
			
		||||
 | 
			
		||||
  // Save the signal mask.
 | 
			
		||||
  str r1, [r0, #(_JB_SIGMASK * 4)]
 | 
			
		||||
	/* Set signal mask */
 | 
			
		||||
	stmfd	sp!, {r0, r1, r14}
 | 
			
		||||
	.cfi_def_cfa_offset 12
 | 
			
		||||
	.cfi_rel_offset r0, 0
 | 
			
		||||
	.cfi_rel_offset r1, 4
 | 
			
		||||
	.cfi_rel_offset r14, 8
 | 
			
		||||
	sub	sp, sp, #4	/* align the stack */
 | 
			
		||||
	.cfi_adjust_cfa_offset 4
 | 
			
		||||
 | 
			
		||||
1:
 | 
			
		||||
  // Save core registers.
 | 
			
		||||
  add r1, r0, #(_JB_CORE_BASE * 4)
 | 
			
		||||
  stmia r1, {r4-r14}
 | 
			
		||||
	mov	r0, r2
 | 
			
		||||
	bl	PIC_SYM(sigsetmask, PLT)
 | 
			
		||||
 | 
			
		||||
  // Save floating-point registers.
 | 
			
		||||
  add r1, r0, #(_JB_FLOAT_BASE * 4)
 | 
			
		||||
  vstmia  r1, {d8-d15}
 | 
			
		||||
	add	sp, sp, #4	/* unalign the stack */
 | 
			
		||||
	.cfi_adjust_cfa_offset -4
 | 
			
		||||
	ldmfd	sp!, {r0, r1, r14}
 | 
			
		||||
	.cfi_def_cfa_offset 0
 | 
			
		||||
 | 
			
		||||
  // Save floating-point state.
 | 
			
		||||
  fmrx r1, fpscr
 | 
			
		||||
  str r1, [r0, #(_JB_FLOAT_STATE * 4)]
 | 
			
		||||
#ifdef __ARM_HAVE_VFP
 | 
			
		||||
	/* Restore floating-point registers */
 | 
			
		||||
	add     r2, r0, #(_JB_FLOAT_BASE * 4)
 | 
			
		||||
	vldmia  r2, {d8-d15}
 | 
			
		||||
	/* Restore floating-point state */
 | 
			
		||||
	ldr     r2, [r0, #(_JB_FLOAT_STATE * 4)]
 | 
			
		||||
	fmxr    fpscr, r2
 | 
			
		||||
#endif /* __ARM_HAVE_VFP */
 | 
			
		||||
 | 
			
		||||
  mov r0, #0
 | 
			
		||||
  bx lr
 | 
			
		||||
END(sigsetjmp)
 | 
			
		||||
	/* Restore core registers */
 | 
			
		||||
	add     r2, r0, #(_JB_CORE_BASE * 4)
 | 
			
		||||
	ldmia   r2, {r4-r14}
 | 
			
		||||
 | 
			
		||||
// void siglongjmp(sigjmp_buf env, int value);
 | 
			
		||||
ENTRY(siglongjmp)
 | 
			
		||||
  // Do we need to restore the signal mask?
 | 
			
		||||
  ldr r2, [r0, #(_JB_SIGFLAG * 4)]
 | 
			
		||||
  teq r2, #0
 | 
			
		||||
  beq 1f
 | 
			
		||||
	/* Validate sp and r14 */
 | 
			
		||||
	teq	sp, #0
 | 
			
		||||
	teqne	r14, #0
 | 
			
		||||
	beq	botch
 | 
			
		||||
 | 
			
		||||
  // Restore the signal mask.
 | 
			
		||||
  stmfd sp!, {r0, r1, r14}
 | 
			
		||||
  .cfi_def_cfa_offset 12
 | 
			
		||||
  .cfi_rel_offset r0, 0
 | 
			
		||||
  .cfi_rel_offset r1, 4
 | 
			
		||||
  .cfi_rel_offset r14, 8
 | 
			
		||||
  sub sp, sp, #4 // Align the stack.
 | 
			
		||||
  .cfi_adjust_cfa_offset 4
 | 
			
		||||
	/* Set return value */
 | 
			
		||||
 | 
			
		||||
  ldr r0, [r0, #(_JB_SIGMASK * 4)]
 | 
			
		||||
  bl sigsetmask
 | 
			
		||||
	mov	r0, r1
 | 
			
		||||
	teq	r0, #0x00000000
 | 
			
		||||
	moveq	r0, #0x00000001
 | 
			
		||||
        bx      lr
 | 
			
		||||
#ifdef __ARM_26__
 | 
			
		||||
	mov	r15, r14
 | 
			
		||||
#else
 | 
			
		||||
	mov	r15, r14
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  add sp, sp, #4 // Unalign the stack.
 | 
			
		||||
  .cfi_adjust_cfa_offset -4
 | 
			
		||||
  ldmfd sp!, {r0, r1, r14}
 | 
			
		||||
  .cfi_def_cfa_offset 0
 | 
			
		||||
 | 
			
		||||
1:
 | 
			
		||||
  // Restore floating-point registers.
 | 
			
		||||
  add r2, r0, #(_JB_FLOAT_BASE * 4)
 | 
			
		||||
  vldmia r2, {d8-d15}
 | 
			
		||||
 | 
			
		||||
  // Restore floating-point state.
 | 
			
		||||
  ldr r2, [r0, #(_JB_FLOAT_STATE * 4)]
 | 
			
		||||
  fmxr fpscr, r2
 | 
			
		||||
 | 
			
		||||
  // Restore core registers.
 | 
			
		||||
  add r2, r0, #(_JB_CORE_BASE * 4)
 | 
			
		||||
  ldmia r2, {r4-r14}
 | 
			
		||||
 | 
			
		||||
  // Validate sp and r14.
 | 
			
		||||
  teq sp, #0
 | 
			
		||||
  teqne r14, #0
 | 
			
		||||
  bleq longjmperror
 | 
			
		||||
 | 
			
		||||
  // Set return value.
 | 
			
		||||
  mov r0, r1
 | 
			
		||||
  teq r0, #0
 | 
			
		||||
  moveq r0, #1
 | 
			
		||||
  bx lr
 | 
			
		||||
END(siglongjmp)
 | 
			
		||||
 | 
			
		||||
ALIAS_SYMBOL(longjmp, siglongjmp)
 | 
			
		||||
ALIAS_SYMBOL(_longjmp, siglongjmp)
 | 
			
		||||
	/* validation failed, die die die. */
 | 
			
		||||
botch:
 | 
			
		||||
	bl	PIC_SYM(longjmperror, PLT)
 | 
			
		||||
	bl	PIC_SYM(abort, PLT)
 | 
			
		||||
	b	. - 8		/* Cannot get here */
 | 
			
		||||
END(longjmp)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										66
									
								
								libc/arch-arm/bionic/sigsetjmp.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								libc/arch-arm/bionic/sigsetjmp.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,66 @@
 | 
			
		||||
/*	$OpenBSD: sigsetjmp.S,v 1.2 2004/02/01 05:40:52 drahn Exp $	*/
 | 
			
		||||
/*	$NetBSD: sigsetjmp.S,v 1.3 2002/08/17 19:54:30 thorpej Exp $	*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 1997 Mark Brinicombe
 | 
			
		||||
 * 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. All advertising materials mentioning features or use of this software
 | 
			
		||||
 *    must display the following acknowledgement:
 | 
			
		||||
 *	This product includes software developed by Mark Brinicombe
 | 
			
		||||
 * 4. Neither the name of the University 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 AUTHOR 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 AUTHOR 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define _ALIGN_TEXT .align 0
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
#include <machine/setjmp.h>
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * C library -- sigsetjmp, siglongjmp
 | 
			
		||||
 *
 | 
			
		||||
 *	longjmp(a,v)
 | 
			
		||||
 * will generate a "return(v)" from the last call to
 | 
			
		||||
 *	setjmp(a, m)
 | 
			
		||||
 * by restoring registers from the stack.
 | 
			
		||||
 * The previous signal state is restored.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
ENTRY(sigsetjmp)
 | 
			
		||||
	teq	r1, #0
 | 
			
		||||
	beq	PIC_SYM(_setjmp, PLT)
 | 
			
		||||
	b	PIC_SYM(setjmp, PLT)
 | 
			
		||||
END(sigsetjmp)
 | 
			
		||||
 | 
			
		||||
.L_setjmp_magic:
 | 
			
		||||
	.word	_JB_MAGIC__SETJMP
 | 
			
		||||
 | 
			
		||||
ENTRY(siglongjmp)
 | 
			
		||||
	ldr	r2, .L_setjmp_magic
 | 
			
		||||
	ldr	r3, [r0]
 | 
			
		||||
	teq	r2, r3
 | 
			
		||||
	beq	PIC_SYM(_longjmp, PLT)
 | 
			
		||||
	b	PIC_SYM(longjmp, PLT)
 | 
			
		||||
END(siglongjmp)
 | 
			
		||||
							
								
								
									
										317
									
								
								libc/arch-arm/bionic/strcmp.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										317
									
								
								libc/arch-arm/bionic/strcmp.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,317 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2011 The Android Open Source Project
 | 
			
		||||
 * Copyright (c) 2008 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <machine/cpu-features.h>
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
	.text
 | 
			
		||||
 | 
			
		||||
#ifdef __ARMEB__
 | 
			
		||||
#define SHFT2LSB lsl
 | 
			
		||||
#define SHFT2LSBEQ lsleq
 | 
			
		||||
#define SHFT2MSB lsr
 | 
			
		||||
#define SHFT2MSBEQ lsreq
 | 
			
		||||
#define MSB 0x000000ff
 | 
			
		||||
#define LSB 0xff000000
 | 
			
		||||
#else
 | 
			
		||||
#define SHFT2LSB lsr
 | 
			
		||||
#define SHFT2LSBEQ lsreq
 | 
			
		||||
#define SHFT2MSB lsl
 | 
			
		||||
#define SHFT2MSBEQ lsleq
 | 
			
		||||
#define MSB 0xff000000
 | 
			
		||||
#define LSB 0x000000ff
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define magic1(REG) REG
 | 
			
		||||
#define magic2(REG) REG, lsl #7
 | 
			
		||||
 | 
			
		||||
ENTRY(strcmp)
 | 
			
		||||
	pld	[r0, #0]
 | 
			
		||||
	pld	[r1, #0]
 | 
			
		||||
	eor	r2, r0, r1
 | 
			
		||||
	tst	r2, #3
 | 
			
		||||
 | 
			
		||||
	/* Strings not at same byte offset from a word boundary.  */
 | 
			
		||||
	bne	.Lstrcmp_unaligned
 | 
			
		||||
	ands	r2, r0, #3
 | 
			
		||||
	bic	r0, r0, #3
 | 
			
		||||
	bic	r1, r1, #3
 | 
			
		||||
	ldr	ip, [r0], #4
 | 
			
		||||
	it	eq
 | 
			
		||||
	ldreq	r3, [r1], #4
 | 
			
		||||
	beq	1f
 | 
			
		||||
 | 
			
		||||
	/* Although s1 and s2 have identical initial alignment, they are
 | 
			
		||||
	 * not currently word aligned.  Rather than comparing bytes,
 | 
			
		||||
	 * make sure that any bytes fetched from before the addressed
 | 
			
		||||
	 * bytes are forced to 0xff.  Then they will always compare
 | 
			
		||||
	 * equal.
 | 
			
		||||
	 */
 | 
			
		||||
	eor	r2, r2, #3
 | 
			
		||||
	lsl	r2, r2, #3
 | 
			
		||||
	mvn	r3, #MSB
 | 
			
		||||
	SHFT2LSB	r2, r3, r2
 | 
			
		||||
	ldr	r3, [r1], #4
 | 
			
		||||
	orr	ip, ip, r2
 | 
			
		||||
	orr	r3, r3, r2
 | 
			
		||||
1:
 | 
			
		||||
	/* Load the 'magic' constant 0x01010101. */
 | 
			
		||||
	str	r4, [sp, #-4]!
 | 
			
		||||
	mov	r4, #1
 | 
			
		||||
	orr	r4, r4, r4, lsl #8
 | 
			
		||||
	orr	r4, r4, r4, lsl #16
 | 
			
		||||
	.p2align	2
 | 
			
		||||
4:
 | 
			
		||||
	pld	[r0, #8]
 | 
			
		||||
	pld	[r1, #8]
 | 
			
		||||
	sub	r2, ip, magic1(r4)
 | 
			
		||||
	cmp	ip, r3
 | 
			
		||||
	itttt	eq
 | 
			
		||||
 | 
			
		||||
	/* check for any zero bytes in first word */
 | 
			
		||||
	biceq	r2, r2, ip
 | 
			
		||||
	tsteq	r2, magic2(r4)
 | 
			
		||||
	ldreq	ip, [r0], #4
 | 
			
		||||
	ldreq	r3, [r1], #4
 | 
			
		||||
	beq	4b
 | 
			
		||||
2:
 | 
			
		||||
	/* There's a zero or a different byte in the word */
 | 
			
		||||
	SHFT2MSB	r0, ip, #24
 | 
			
		||||
	SHFT2LSB	ip, ip, #8
 | 
			
		||||
	cmp	r0, #1
 | 
			
		||||
	it	cs
 | 
			
		||||
	cmpcs	r0, r3, SHFT2MSB #24
 | 
			
		||||
	it	eq
 | 
			
		||||
	SHFT2LSBEQ r3, r3, #8
 | 
			
		||||
	beq	2b
 | 
			
		||||
	/* On a big-endian machine, r0 contains the desired byte in bits
 | 
			
		||||
	 * 0-7; on a little-endian machine they are in bits 24-31.  In
 | 
			
		||||
	 * both cases the other bits in r0 are all zero.  For r3 the
 | 
			
		||||
	 * interesting byte is at the other end of the word, but the
 | 
			
		||||
	 * other bits are not necessarily zero.  We need a signed result
 | 
			
		||||
	 * representing the differnece in the unsigned bytes, so for the
 | 
			
		||||
	 * little-endian case we can't just shift the interesting bits up.
 | 
			
		||||
	 */
 | 
			
		||||
#ifdef __ARMEB__
 | 
			
		||||
	sub	r0, r0, r3, lsr #24
 | 
			
		||||
#else
 | 
			
		||||
	and	r3, r3, #255
 | 
			
		||||
	/* No RSB instruction in Thumb2 */
 | 
			
		||||
#ifdef __thumb2__
 | 
			
		||||
	lsr	r0, r0, #24
 | 
			
		||||
	sub	r0, r0, r3
 | 
			
		||||
#else
 | 
			
		||||
	rsb	r0, r3, r0, lsr #24
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
	ldr	r4, [sp], #4
 | 
			
		||||
	bx	lr
 | 
			
		||||
 | 
			
		||||
.Lstrcmp_unaligned:
 | 
			
		||||
	wp1 .req r0
 | 
			
		||||
	wp2 .req r1
 | 
			
		||||
	b1  .req r2
 | 
			
		||||
	w1  .req r4
 | 
			
		||||
	w2  .req r5
 | 
			
		||||
	t1  .req ip
 | 
			
		||||
	@ r3 is scratch
 | 
			
		||||
 | 
			
		||||
	/* First of all, compare bytes until wp1(sp1) is word-aligned. */
 | 
			
		||||
1:
 | 
			
		||||
	tst	wp1, #3
 | 
			
		||||
	beq	2f
 | 
			
		||||
	ldrb	r2, [wp1], #1
 | 
			
		||||
	ldrb	r3, [wp2], #1
 | 
			
		||||
	cmp	r2, #1
 | 
			
		||||
	it	cs
 | 
			
		||||
	cmpcs	r2, r3
 | 
			
		||||
	beq	1b
 | 
			
		||||
	sub	r0, r2, r3
 | 
			
		||||
	bx	lr
 | 
			
		||||
 | 
			
		||||
2:
 | 
			
		||||
	str	r5, [sp, #-4]!
 | 
			
		||||
	str	r4, [sp, #-4]!
 | 
			
		||||
	mov	b1, #1
 | 
			
		||||
	orr	b1, b1, b1, lsl #8
 | 
			
		||||
	orr	b1, b1, b1, lsl #16
 | 
			
		||||
 | 
			
		||||
	and	t1, wp2, #3
 | 
			
		||||
	bic	wp2, wp2, #3
 | 
			
		||||
	ldr	w1, [wp1], #4
 | 
			
		||||
	ldr	w2, [wp2], #4
 | 
			
		||||
	cmp	t1, #2
 | 
			
		||||
	beq	2f
 | 
			
		||||
	bhi	3f
 | 
			
		||||
 | 
			
		||||
	/* Critical inner Loop: Block with 3 bytes initial overlap */
 | 
			
		||||
	.p2align	2
 | 
			
		||||
1:
 | 
			
		||||
	bic	t1, w1, #MSB
 | 
			
		||||
	cmp	t1, w2, SHFT2LSB #8
 | 
			
		||||
	sub	r3, w1, b1
 | 
			
		||||
	bic	r3, r3, w1
 | 
			
		||||
	bne	4f
 | 
			
		||||
	ands	r3, r3, b1, lsl #7
 | 
			
		||||
	it	eq
 | 
			
		||||
	ldreq	w2, [wp2], #4
 | 
			
		||||
	bne	5f
 | 
			
		||||
	eor	t1, t1, w1
 | 
			
		||||
	cmp	t1, w2, SHFT2MSB #24
 | 
			
		||||
	bne	6f
 | 
			
		||||
	ldr	w1, [wp1], #4
 | 
			
		||||
	b	1b
 | 
			
		||||
4:
 | 
			
		||||
	SHFT2LSB	w2, w2, #8
 | 
			
		||||
	b	8f
 | 
			
		||||
 | 
			
		||||
5:
 | 
			
		||||
#ifdef __ARMEB__
 | 
			
		||||
	/* The syndrome value may contain false ones if the string ends
 | 
			
		||||
	 * with the bytes 0x01 0x00
 | 
			
		||||
	 */
 | 
			
		||||
	tst	w1, #0xff000000
 | 
			
		||||
	itt	ne
 | 
			
		||||
	tstne	w1, #0x00ff0000
 | 
			
		||||
	tstne	w1, #0x0000ff00
 | 
			
		||||
	beq	7f
 | 
			
		||||
#else
 | 
			
		||||
	bics	r3, r3, #0xff000000
 | 
			
		||||
	bne	7f
 | 
			
		||||
#endif
 | 
			
		||||
	ldrb	w2, [wp2]
 | 
			
		||||
	SHFT2LSB	t1, w1, #24
 | 
			
		||||
#ifdef __ARMEB__
 | 
			
		||||
	lsl	w2, w2, #24
 | 
			
		||||
#endif
 | 
			
		||||
	b	8f
 | 
			
		||||
 | 
			
		||||
6:
 | 
			
		||||
	SHFT2LSB	t1, w1, #24
 | 
			
		||||
	and	w2, w2, #LSB
 | 
			
		||||
	b	8f
 | 
			
		||||
 | 
			
		||||
	/* Critical inner Loop: Block with 2 bytes initial overlap */
 | 
			
		||||
	.p2align	2
 | 
			
		||||
2:
 | 
			
		||||
	SHFT2MSB	t1, w1, #16
 | 
			
		||||
	sub	r3, w1, b1
 | 
			
		||||
	SHFT2LSB	t1, t1, #16
 | 
			
		||||
	bic	r3, r3, w1
 | 
			
		||||
	cmp	t1, w2, SHFT2LSB #16
 | 
			
		||||
	bne	4f
 | 
			
		||||
	ands	r3, r3, b1, lsl #7
 | 
			
		||||
	it	eq
 | 
			
		||||
	ldreq	w2, [wp2], #4
 | 
			
		||||
	bne	5f
 | 
			
		||||
	eor	t1, t1, w1
 | 
			
		||||
	cmp	t1, w2, SHFT2MSB #16
 | 
			
		||||
	bne	6f
 | 
			
		||||
	ldr	w1, [wp1], #4
 | 
			
		||||
	b	2b
 | 
			
		||||
 | 
			
		||||
5:
 | 
			
		||||
#ifdef __ARMEB__
 | 
			
		||||
	/* The syndrome value may contain false ones if the string ends
 | 
			
		||||
	 * with the bytes 0x01 0x00
 | 
			
		||||
	 */
 | 
			
		||||
	tst	w1, #0xff000000
 | 
			
		||||
	it	ne
 | 
			
		||||
	tstne	w1, #0x00ff0000
 | 
			
		||||
	beq	7f
 | 
			
		||||
#else
 | 
			
		||||
	lsls	r3, r3, #16
 | 
			
		||||
	bne	7f
 | 
			
		||||
#endif
 | 
			
		||||
	ldrh	w2, [wp2]
 | 
			
		||||
	SHFT2LSB	t1, w1, #16
 | 
			
		||||
#ifdef __ARMEB__
 | 
			
		||||
	lsl	w2, w2, #16
 | 
			
		||||
#endif
 | 
			
		||||
	b	8f
 | 
			
		||||
 | 
			
		||||
6:
 | 
			
		||||
	SHFT2MSB	w2, w2, #16
 | 
			
		||||
	SHFT2LSB	t1, w1, #16
 | 
			
		||||
4:
 | 
			
		||||
	SHFT2LSB	w2, w2, #16
 | 
			
		||||
	b	8f
 | 
			
		||||
 | 
			
		||||
	/* Critical inner Loop: Block with 1 byte initial overlap */
 | 
			
		||||
	.p2align	2
 | 
			
		||||
3:
 | 
			
		||||
	and	t1, w1, #LSB
 | 
			
		||||
	cmp	t1, w2, SHFT2LSB #24
 | 
			
		||||
	sub	r3, w1, b1
 | 
			
		||||
	bic	r3, r3, w1
 | 
			
		||||
	bne	4f
 | 
			
		||||
	ands	r3, r3, b1, lsl #7
 | 
			
		||||
	it	eq
 | 
			
		||||
	ldreq	w2, [wp2], #4
 | 
			
		||||
	bne	5f
 | 
			
		||||
	eor	t1, t1, w1
 | 
			
		||||
	cmp	t1, w2, SHFT2MSB #8
 | 
			
		||||
	bne	6f
 | 
			
		||||
	ldr	w1, [wp1], #4
 | 
			
		||||
	b	3b
 | 
			
		||||
4:
 | 
			
		||||
	SHFT2LSB	w2, w2, #24
 | 
			
		||||
	b	8f
 | 
			
		||||
5:
 | 
			
		||||
	/* The syndrome value may contain false ones if the string ends
 | 
			
		||||
	 * with the bytes 0x01 0x00
 | 
			
		||||
	 */
 | 
			
		||||
	tst	w1, #LSB
 | 
			
		||||
	beq	7f
 | 
			
		||||
	ldr	w2, [wp2], #4
 | 
			
		||||
6:
 | 
			
		||||
	SHFT2LSB	t1, w1, #8
 | 
			
		||||
	bic	w2, w2, #MSB
 | 
			
		||||
	b	8f
 | 
			
		||||
7:
 | 
			
		||||
	mov	r0, #0
 | 
			
		||||
	ldr	r4, [sp], #4
 | 
			
		||||
	ldr	r5, [sp], #4
 | 
			
		||||
	bx	lr
 | 
			
		||||
 | 
			
		||||
8:
 | 
			
		||||
	and	r2, t1, #LSB
 | 
			
		||||
	and	r0, w2, #LSB
 | 
			
		||||
	cmp	r0, #1
 | 
			
		||||
	it	cs
 | 
			
		||||
	cmpcs	r0, r2
 | 
			
		||||
	itt	eq
 | 
			
		||||
	SHFT2LSBEQ	t1, t1, #8
 | 
			
		||||
	SHFT2LSBEQ	w2, w2, #8
 | 
			
		||||
	beq	8b
 | 
			
		||||
	sub	r0, r2, r0
 | 
			
		||||
	ldr	r4, [sp], #4
 | 
			
		||||
	ldr	r5, [sp], #4
 | 
			
		||||
	bx	lr
 | 
			
		||||
END(strcmp)
 | 
			
		||||
@@ -8,9 +8,4 @@ libc_bionic_src_files_arm += \
 | 
			
		||||
    arch-arm/cortex-a15/bionic/strcpy.S \
 | 
			
		||||
    arch-arm/cortex-a15/bionic/__strcpy_chk.S \
 | 
			
		||||
    arch-arm/cortex-a15/bionic/strlen.S \
 | 
			
		||||
 | 
			
		||||
libc_bionic_src_files_arm += \
 | 
			
		||||
    arch-arm/generic/bionic/memcmp.S \
 | 
			
		||||
 | 
			
		||||
libc_bionic_src_files_arm += \
 | 
			
		||||
    arch-arm/denver/bionic/memmove.S \
 | 
			
		||||
    bionic/memmove.c \
 | 
			
		||||
 
 | 
			
		||||
@@ -1 +0,0 @@
 | 
			
		||||
include bionic/libc/arch-arm/cortex-a7/cortex-a7.mk
 | 
			
		||||
@@ -35,7 +35,6 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
    .fpu    neon
 | 
			
		||||
    .syntax unified
 | 
			
		||||
 | 
			
		||||
ENTRY(__memset_chk)
 | 
			
		||||
        cmp         r2, r3
 | 
			
		||||
@@ -101,9 +100,9 @@ ENTRY(memset)
 | 
			
		||||
1:      bge         2f
 | 
			
		||||
        vst1.32     {d0[0]}, [r0]!
 | 
			
		||||
2:      movs        ip, r2, lsl #31
 | 
			
		||||
        strbmi      r1, [r0], #1
 | 
			
		||||
        strbcs      r1, [r0], #1
 | 
			
		||||
        strbcs      r1, [r0], #1
 | 
			
		||||
        strmib      r1, [r0], #1
 | 
			
		||||
        strcsb      r1, [r0], #1
 | 
			
		||||
        strcsb      r1, [r0], #1
 | 
			
		||||
        ldmfd       sp!, {r0}
 | 
			
		||||
        bx          lr
 | 
			
		||||
END(memset)
 | 
			
		||||
@@ -132,11 +131,11 @@ ENTRY_PRIVATE(__memset_large_copy)
 | 
			
		||||
        orr         r1, r1, r1, lsr #16
 | 
			
		||||
 | 
			
		||||
        movs        r12, r3, lsl #31
 | 
			
		||||
        strbcs      r1, [r0], #1    /* can't use strh (alignment unknown) */
 | 
			
		||||
        strbcs      r1, [r0], #1
 | 
			
		||||
        strbmi      r1, [r0], #1
 | 
			
		||||
        strcsb      r1, [r0], #1    /* can't use strh (alignment unknown) */
 | 
			
		||||
        strcsb      r1, [r0], #1
 | 
			
		||||
        strmib      r1, [r0], #1
 | 
			
		||||
        subs        r2, r2, r3
 | 
			
		||||
        popls       {r0, r4-r7, lr}   /* return */
 | 
			
		||||
        ldmlsfd     sp!, {r0, r4-r7, lr}   /* return */
 | 
			
		||||
        bxls        lr
 | 
			
		||||
 | 
			
		||||
        /* align the destination to a cache-line */
 | 
			
		||||
@@ -156,9 +155,9 @@ ENTRY_PRIVATE(__memset_large_copy)
 | 
			
		||||
 | 
			
		||||
        /* conditionally writes 0 to 7 words (length in r3) */
 | 
			
		||||
        movs        r3, r3, lsl #28
 | 
			
		||||
        stmcs       r0!, {r1, lr}
 | 
			
		||||
        stmcs       r0!, {r1, lr}
 | 
			
		||||
        stmmi       r0!, {r1, lr}
 | 
			
		||||
        stmcsia     r0!, {r1, lr}
 | 
			
		||||
        stmcsia     r0!, {r1, lr}
 | 
			
		||||
        stmmiia     r0!, {r1, lr}
 | 
			
		||||
        movs        r3, r3, lsl #2
 | 
			
		||||
        strcs       r1, [r0], #4
 | 
			
		||||
 | 
			
		||||
@@ -173,13 +172,13 @@ ENTRY_PRIVATE(__memset_large_copy)
 | 
			
		||||
 | 
			
		||||
        /* conditionally stores 0 to 31 bytes */
 | 
			
		||||
        movs        r2, r2, lsl #28
 | 
			
		||||
        stmcs       r0!, {r1,r3,r12,lr}
 | 
			
		||||
        stmmi       r0!, {r1, lr}
 | 
			
		||||
        stmcsia     r0!, {r1,r3,r12,lr}
 | 
			
		||||
        stmmiia     r0!, {r1, lr}
 | 
			
		||||
        movs        r2, r2, lsl #2
 | 
			
		||||
        strcs       r1, [r0], #4
 | 
			
		||||
        strhmi      r1, [r0], #2
 | 
			
		||||
        strmih      r1, [r0], #2
 | 
			
		||||
        movs        r2, r2, lsl #2
 | 
			
		||||
        strbcs      r1, [r0]
 | 
			
		||||
        strcsb      r1, [r0]
 | 
			
		||||
        ldmfd       sp!, {r0, r4-r7, lr}
 | 
			
		||||
        bx          lr
 | 
			
		||||
END(__memset_large_copy)
 | 
			
		||||
 
 | 
			
		||||
@@ -8,9 +8,4 @@ libc_bionic_src_files_arm += \
 | 
			
		||||
    arch-arm/cortex-a9/bionic/strcpy.S \
 | 
			
		||||
    arch-arm/cortex-a9/bionic/__strcpy_chk.S \
 | 
			
		||||
    arch-arm/cortex-a9/bionic/strlen.S \
 | 
			
		||||
 | 
			
		||||
libc_bionic_src_files_arm += \
 | 
			
		||||
    arch-arm/generic/bionic/memcmp.S \
 | 
			
		||||
 | 
			
		||||
libc_bionic_src_files_arm += \
 | 
			
		||||
    arch-arm/denver/bionic/memmove.S \
 | 
			
		||||
    bionic/memmove.c \
 | 
			
		||||
 
 | 
			
		||||
@@ -37,7 +37,6 @@
 | 
			
		||||
         * memset() returns its first argument.
 | 
			
		||||
         */
 | 
			
		||||
 | 
			
		||||
        .cpu        cortex-a15
 | 
			
		||||
        .fpu        neon
 | 
			
		||||
        .syntax     unified
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,4 @@
 | 
			
		||||
libc_bionic_src_files_arm += \
 | 
			
		||||
    arch-arm/generic/bionic/memcmp.S \
 | 
			
		||||
    arch-arm/denver/bionic/memcpy.S \
 | 
			
		||||
    arch-arm/denver/bionic/memmove.S \
 | 
			
		||||
    arch-arm/denver/bionic/memset.S \
 | 
			
		||||
 
 | 
			
		||||
@@ -37,8 +37,6 @@
 | 
			
		||||
         * so we have to preserve R0.
 | 
			
		||||
         */
 | 
			
		||||
 | 
			
		||||
         .syntax unified
 | 
			
		||||
 | 
			
		||||
ENTRY(__memcpy_chk)
 | 
			
		||||
        cmp         r2, r3
 | 
			
		||||
        bhi         __memcpy_chk_fail
 | 
			
		||||
@@ -83,12 +81,12 @@ ENTRY(memcpy)
 | 
			
		||||
         */
 | 
			
		||||
        movs        r12, r3, lsl #31
 | 
			
		||||
        sub         r2, r2, r3      /* we know that r3 <= r2 because r2 >= 4 */
 | 
			
		||||
        ldrbmi      r3, [r1], #1
 | 
			
		||||
        ldrbcs      r4, [r1], #1
 | 
			
		||||
        ldrbcs      r12,[r1], #1
 | 
			
		||||
        strbmi      r3, [r0], #1
 | 
			
		||||
        strbcs      r4, [r0], #1
 | 
			
		||||
        strbcs      r12,[r0], #1
 | 
			
		||||
        ldrmib      r3, [r1], #1
 | 
			
		||||
        ldrcsb      r4, [r1], #1
 | 
			
		||||
        ldrcsb      r12,[r1], #1
 | 
			
		||||
        strmib      r3, [r0], #1
 | 
			
		||||
        strcsb      r4, [r0], #1
 | 
			
		||||
        strcsb      r12,[r0], #1
 | 
			
		||||
 | 
			
		||||
.Lsrc_aligned:
 | 
			
		||||
 | 
			
		||||
@@ -111,10 +109,10 @@ ENTRY(memcpy)
 | 
			
		||||
 | 
			
		||||
        /* conditionally copies 0 to 7 words (length in r3) */
 | 
			
		||||
        movs        r12, r3, lsl #28
 | 
			
		||||
        ldmcs       r1!, {r4, r5, r6, r7}   /* 16 bytes */
 | 
			
		||||
        ldmmi       r1!, {r8, r9}           /*  8 bytes */
 | 
			
		||||
        stmcs       r0!, {r4, r5, r6, r7}
 | 
			
		||||
        stmmi       r0!, {r8, r9}
 | 
			
		||||
        ldmcsia     r1!, {r4, r5, r6, r7}   /* 16 bytes */
 | 
			
		||||
        ldmmiia     r1!, {r8, r9}           /*  8 bytes */
 | 
			
		||||
        stmcsia     r0!, {r4, r5, r6, r7}
 | 
			
		||||
        stmmiia     r0!, {r8, r9}
 | 
			
		||||
        tst         r3, #0x4
 | 
			
		||||
        ldrne       r10,[r1], #4            /*  4 bytes */
 | 
			
		||||
        strne       r10,[r0], #4
 | 
			
		||||
@@ -179,18 +177,18 @@ ENTRY(memcpy)
 | 
			
		||||
 | 
			
		||||
        /* conditionnaly copies 0 to 31 bytes */
 | 
			
		||||
        movs        r12, r2, lsl #28
 | 
			
		||||
        ldmcs       r1!, {r4, r5, r6, r7}   /* 16 bytes */
 | 
			
		||||
        ldmmi       r1!, {r8, r9}           /*  8 bytes */
 | 
			
		||||
        stmcs       r0!, {r4, r5, r6, r7}
 | 
			
		||||
        stmmi       r0!, {r8, r9}
 | 
			
		||||
        ldmcsia     r1!, {r4, r5, r6, r7}   /* 16 bytes */
 | 
			
		||||
        ldmmiia     r1!, {r8, r9}           /*  8 bytes */
 | 
			
		||||
        stmcsia     r0!, {r4, r5, r6, r7}
 | 
			
		||||
        stmmiia     r0!, {r8, r9}
 | 
			
		||||
        movs        r12, r2, lsl #30
 | 
			
		||||
        ldrcs       r3, [r1], #4            /*  4 bytes */
 | 
			
		||||
        ldrhmi      r4, [r1], #2            /*  2 bytes */
 | 
			
		||||
        ldrmih      r4, [r1], #2            /*  2 bytes */
 | 
			
		||||
        strcs       r3, [r0], #4
 | 
			
		||||
        strhmi      r4, [r0], #2
 | 
			
		||||
        strmih      r4, [r0], #2
 | 
			
		||||
        tst         r2, #0x1
 | 
			
		||||
        ldrbne      r3, [r1]                /*  last byte  */
 | 
			
		||||
        strbne      r3, [r0]
 | 
			
		||||
        ldrneb      r3, [r1]                /*  last byte  */
 | 
			
		||||
        strneb      r3, [r0]
 | 
			
		||||
 | 
			
		||||
        /* we're done! restore everything and return */
 | 
			
		||||
1:      ldmfd       sp!, {r5-r11}
 | 
			
		||||
@@ -230,11 +228,11 @@ ENTRY(memcpy)
 | 
			
		||||
         * becomes aligned to 32 bits (r5 = nb of words to copy for alignment)
 | 
			
		||||
         */
 | 
			
		||||
        movs        r5, r5, lsl #31
 | 
			
		||||
        strbmi      r3, [r0], #1
 | 
			
		||||
        strmib      r3, [r0], #1
 | 
			
		||||
        movmi       r3, r3, lsr #8
 | 
			
		||||
        strbcs      r3, [r0], #1
 | 
			
		||||
        strcsb      r3, [r0], #1
 | 
			
		||||
        movcs       r3, r3, lsr #8
 | 
			
		||||
        strbcs      r3, [r0], #1
 | 
			
		||||
        strcsb      r3, [r0], #1
 | 
			
		||||
        movcs       r3, r3, lsr #8
 | 
			
		||||
 | 
			
		||||
        cmp         r2, #4
 | 
			
		||||
@@ -365,23 +363,23 @@ ENTRY(memcpy)
 | 
			
		||||
.Lpartial_word_tail:
 | 
			
		||||
        /* we have a partial word in the input buffer */
 | 
			
		||||
        movs        r5, lr, lsl #(31-3)
 | 
			
		||||
        strbmi      r3, [r0], #1
 | 
			
		||||
        strmib      r3, [r0], #1
 | 
			
		||||
        movmi       r3, r3, lsr #8
 | 
			
		||||
        strbcs      r3, [r0], #1
 | 
			
		||||
        strcsb      r3, [r0], #1
 | 
			
		||||
        movcs       r3, r3, lsr #8
 | 
			
		||||
        strbcs      r3, [r0], #1
 | 
			
		||||
        strcsb      r3, [r0], #1
 | 
			
		||||
 | 
			
		||||
        /* Refill spilled registers from the stack. Don't update sp. */
 | 
			
		||||
        ldmfd       sp, {r5-r11}
 | 
			
		||||
 | 
			
		||||
.Lcopy_last_3_and_return:
 | 
			
		||||
        movs        r2, r2, lsl #31 /* copy remaining 0, 1, 2 or 3 bytes */
 | 
			
		||||
        ldrbmi      r2, [r1], #1
 | 
			
		||||
        ldrbcs      r3, [r1], #1
 | 
			
		||||
        ldrbcs      r12,[r1]
 | 
			
		||||
        strbmi      r2, [r0], #1
 | 
			
		||||
        strbcs      r3, [r0], #1
 | 
			
		||||
        strbcs      r12,[r0]
 | 
			
		||||
        ldrmib      r2, [r1], #1
 | 
			
		||||
        ldrcsb      r3, [r1], #1
 | 
			
		||||
        ldrcsb      r12,[r1]
 | 
			
		||||
        strmib      r2, [r0], #1
 | 
			
		||||
        strcsb      r3, [r0], #1
 | 
			
		||||
        strcsb      r12,[r0]
 | 
			
		||||
 | 
			
		||||
        /* we're done! restore sp and spilled registers and return */
 | 
			
		||||
        add         sp,  sp, #28
 | 
			
		||||
 
 | 
			
		||||
@@ -35,8 +35,6 @@
 | 
			
		||||
         * memset() returns its first argument.
 | 
			
		||||
         */
 | 
			
		||||
 | 
			
		||||
         .syntax unified
 | 
			
		||||
 | 
			
		||||
ENTRY(__memset_chk)
 | 
			
		||||
        cmp         r2, r3
 | 
			
		||||
        bls         done
 | 
			
		||||
@@ -78,11 +76,11 @@ ENTRY(memset)
 | 
			
		||||
        orr         r1, r1, r1, lsr #16
 | 
			
		||||
 | 
			
		||||
        movs        r12, r3, lsl #31
 | 
			
		||||
        strbcs      r1, [r0], #1    /* can't use strh (alignment unknown) */
 | 
			
		||||
        strbcs      r1, [r0], #1
 | 
			
		||||
        strbmi      r1, [r0], #1
 | 
			
		||||
        strcsb      r1, [r0], #1    /* can't use strh (alignment unknown) */
 | 
			
		||||
        strcsb      r1, [r0], #1
 | 
			
		||||
        strmib      r1, [r0], #1
 | 
			
		||||
        subs        r2, r2, r3
 | 
			
		||||
        popls       {r0, r4-r7, lr}    /* return */
 | 
			
		||||
        ldmlsfd     sp!, {r0, r4-r7, lr}    /* return */
 | 
			
		||||
        bxls        lr
 | 
			
		||||
 | 
			
		||||
        /* align the destination to a cache-line */
 | 
			
		||||
@@ -102,9 +100,9 @@ ENTRY(memset)
 | 
			
		||||
 | 
			
		||||
        /* conditionally writes 0 to 7 words (length in r3) */
 | 
			
		||||
        movs        r3, r3, lsl #28
 | 
			
		||||
        stmcs       r0!, {r1, lr}
 | 
			
		||||
        stmcs       r0!, {r1, lr}
 | 
			
		||||
        stmmi       r0!, {r1, lr}
 | 
			
		||||
        stmcsia     r0!, {r1, lr}
 | 
			
		||||
        stmcsia     r0!, {r1, lr}
 | 
			
		||||
        stmmiia     r0!, {r1, lr}
 | 
			
		||||
        movs        r3, r3, lsl #2
 | 
			
		||||
        strcs       r1, [r0], #4
 | 
			
		||||
 | 
			
		||||
@@ -119,13 +117,13 @@ ENTRY(memset)
 | 
			
		||||
 | 
			
		||||
        /* conditionally stores 0 to 31 bytes */
 | 
			
		||||
        movs        r2, r2, lsl #28
 | 
			
		||||
        stmcs       r0!, {r1,r3,r12,lr}
 | 
			
		||||
        stmmi       r0!, {r1, lr}
 | 
			
		||||
        stmcsia     r0!, {r1,r3,r12,lr}
 | 
			
		||||
        stmmiia     r0!, {r1, lr}
 | 
			
		||||
        movs        r2, r2, lsl #2
 | 
			
		||||
        strcs       r1, [r0], #4
 | 
			
		||||
        strhmi      r1, [r0], #2
 | 
			
		||||
        strmih      r1, [r0], #2
 | 
			
		||||
        movs        r2, r2, lsl #2
 | 
			
		||||
        strbcs      r1, [r0]
 | 
			
		||||
        strcsb      r1, [r0]
 | 
			
		||||
        ldmfd       sp!, {r0, r4-r7, lr}
 | 
			
		||||
        bx          lr
 | 
			
		||||
END(memset)
 | 
			
		||||
 
 | 
			
		||||
@@ -32,8 +32,6 @@
 | 
			
		||||
#include <machine/cpu-features.h>
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
.syntax unified
 | 
			
		||||
 | 
			
		||||
ENTRY(strcpy)
 | 
			
		||||
	pld	[r1, #0]
 | 
			
		||||
	eor	r2, r0, r1
 | 
			
		||||
@@ -110,15 +108,15 @@ ENTRY(strcpy)
 | 
			
		||||
#ifdef __ARMEB__
 | 
			
		||||
	tst	r2, #0xff00
 | 
			
		||||
	iteet	ne
 | 
			
		||||
	strhne	r2, [ip], #2
 | 
			
		||||
	strneh	r2, [ip], #2
 | 
			
		||||
	lsreq	r2, r2, #8
 | 
			
		||||
	strbeq	r2, [ip]
 | 
			
		||||
	streqb	r2, [ip]
 | 
			
		||||
	tstne	r2, #0xff
 | 
			
		||||
#else
 | 
			
		||||
	tst	r2, #0xff
 | 
			
		||||
	itet	ne
 | 
			
		||||
	strhne	r2, [ip], #2
 | 
			
		||||
	strbeq	r2, [ip]
 | 
			
		||||
	strneh	r2, [ip], #2
 | 
			
		||||
	streqb	r2, [ip]
 | 
			
		||||
	tstne	r2, #0xff00
 | 
			
		||||
#endif
 | 
			
		||||
	bne	5b
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,11 @@
 | 
			
		||||
libc_bionic_src_files_arm += \
 | 
			
		||||
    arch-arm/generic/bionic/memcmp.S \
 | 
			
		||||
    arch-arm/generic/bionic/memcpy.S \
 | 
			
		||||
    arch-arm/generic/bionic/memset.S \
 | 
			
		||||
    arch-arm/generic/bionic/strcmp.S \
 | 
			
		||||
    arch-arm/generic/bionic/strcpy.S \
 | 
			
		||||
    arch-arm/generic/bionic/strlen.c \
 | 
			
		||||
    bionic/memmove.c \
 | 
			
		||||
    bionic/__strcat_chk.cpp \
 | 
			
		||||
    bionic/__strcpy_chk.cpp \
 | 
			
		||||
 | 
			
		||||
libc_openbsd_src_files_arm += \
 | 
			
		||||
    upstream-openbsd/lib/libc/string/memmove.c \
 | 
			
		||||
    upstream-openbsd/lib/libc/string/stpcpy.c \
 | 
			
		||||
    upstream-openbsd/lib/libc/string/strcat.c \
 | 
			
		||||
 
 | 
			
		||||
@@ -38,7 +38,9 @@
 | 
			
		||||
#ifndef _ARM32_ASM_H_
 | 
			
		||||
#define _ARM32_ASM_H_
 | 
			
		||||
 | 
			
		||||
#define __bionic_asm_align 0
 | 
			
		||||
#ifndef _ALIGN_TEXT
 | 
			
		||||
# define _ALIGN_TEXT .align 0
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#undef __bionic_asm_custom_entry
 | 
			
		||||
#undef __bionic_asm_custom_end
 | 
			
		||||
@@ -48,4 +50,10 @@
 | 
			
		||||
#undef __bionic_asm_function_type
 | 
			
		||||
#define __bionic_asm_function_type #function
 | 
			
		||||
 | 
			
		||||
#if defined(__ELF__) && defined(PIC)
 | 
			
		||||
#define PIC_SYM(x,y) x ## ( ## y ## )
 | 
			
		||||
#else
 | 
			
		||||
#define PIC_SYM(x,y) x
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* !_ARM_ASM_H_ */
 | 
			
		||||
 
 | 
			
		||||
@@ -28,6 +28,14 @@
 | 
			
		||||
#ifndef _ARM_MACHINE_CPU_FEATURES_H
 | 
			
		||||
#define _ARM_MACHINE_CPU_FEATURES_H
 | 
			
		||||
 | 
			
		||||
/* The purpose of this file is to define several macros corresponding
 | 
			
		||||
 * to CPU features that may or may not be available at build time on
 | 
			
		||||
 * on the target CPU.
 | 
			
		||||
 *
 | 
			
		||||
 * This is done to abstract us from the various ARM Architecture
 | 
			
		||||
 * quirks and alphabet soup.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* __ARM_ARCH__ is a number corresponding to the ARM revision
 | 
			
		||||
 * we're going to support. Our toolchain doesn't define __ARM_ARCH__
 | 
			
		||||
 * so try to guess it.
 | 
			
		||||
@@ -45,4 +53,31 @@
 | 
			
		||||
#  endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* define __ARM_HAVE_HALFWORD_MULTIPLY when half-word multiply instructions
 | 
			
		||||
 * this means variants of: smul, smulw, smla, smlaw, smlal
 | 
			
		||||
 */
 | 
			
		||||
#define  __ARM_HAVE_HALFWORD_MULTIPLY  1
 | 
			
		||||
 | 
			
		||||
/* define __ARM_HAVE_LDREXD for ARMv7 architecture
 | 
			
		||||
 * (also present in ARMv6K, but not implemented in ARMv7-M, neither of which
 | 
			
		||||
 * we care about)
 | 
			
		||||
 */
 | 
			
		||||
#if __ARM_ARCH__ >= 7
 | 
			
		||||
#  define __ARM_HAVE_LDREXD
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* define _ARM_HAVE_VFP if we have VFPv3
 | 
			
		||||
 */
 | 
			
		||||
#if __ARM_ARCH__ >= 7 && defined __VFP_FP__
 | 
			
		||||
#  define __ARM_HAVE_VFP
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* define _ARM_HAVE_NEON for ARMv7 architecture if we support the
 | 
			
		||||
 * Neon SIMD instruction set extensions. This also implies
 | 
			
		||||
 * that VFPv3-D32 is supported.
 | 
			
		||||
 */
 | 
			
		||||
#if __ARM_ARCH__ >= 7 && defined __ARM_NEON__
 | 
			
		||||
#  define __ARM_HAVE_NEON
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* _ARM_MACHINE_CPU_FEATURES_H */
 | 
			
		||||
 
 | 
			
		||||
@@ -102,8 +102,6 @@
 | 
			
		||||
 | 
			
		||||
/* 112-127 are reserved for private experiments. */
 | 
			
		||||
 | 
			
		||||
#define R_ARM_IRELATIVE   160
 | 
			
		||||
 | 
			
		||||
#define R_ARM_RXPC25		249
 | 
			
		||||
#define R_ARM_RSBREL32		250
 | 
			
		||||
#define R_ARM_THM_RPC22		251
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										79
									
								
								libc/arch-arm/include/machine/endian.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								libc/arch-arm/include/machine/endian.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,79 @@
 | 
			
		||||
/*	$OpenBSD: endian.h,v 1.3 2005/12/13 00:35:23 millert Exp $	*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2010 The Android Open Source Project
 | 
			
		||||
 * 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.
 | 
			
		||||
 *
 | 
			
		||||
 * 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 _ARM_ENDIAN_H_
 | 
			
		||||
#define _ARM_ENDIAN_H_
 | 
			
		||||
 | 
			
		||||
#ifdef __GNUC__
 | 
			
		||||
 | 
			
		||||
/* According to RealView Assembler User's Guide, REV and REV16 are available
 | 
			
		||||
 * in Thumb code and 16-bit instructions when used in Thumb-2 code.
 | 
			
		||||
 *
 | 
			
		||||
 * REV Rd, Rm
 | 
			
		||||
 *   Rd and Rm must both be Lo registers.
 | 
			
		||||
 *
 | 
			
		||||
 * REV16 Rd, Rm
 | 
			
		||||
 *   Rd and Rm must both be Lo registers.
 | 
			
		||||
 *
 | 
			
		||||
 * The +l constraint takes care of this without constraining us in ARM mode.
 | 
			
		||||
 */
 | 
			
		||||
#define __swap16md(x) ({                                        \
 | 
			
		||||
    register u_int16_t _x = (x);                                \
 | 
			
		||||
    __asm__ __volatile__("rev16 %0, %0" : "+l" (_x));           \
 | 
			
		||||
    _x;                                                         \
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
#define __swap32md(x) ({                                        \
 | 
			
		||||
    register u_int32_t _x = (x);                                \
 | 
			
		||||
    __asm__ __volatile__("rev %0, %0" : "+l" (_x));             \
 | 
			
		||||
    _x;                                                         \
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
#define __swap64md(x) ({                                        \
 | 
			
		||||
    u_int64_t _swap64md_x = (x);                                \
 | 
			
		||||
    (u_int64_t) __swap32md(_swap64md_x >> 32) |                 \
 | 
			
		||||
        (u_int64_t) __swap32md(_swap64md_x & 0xffffffff) << 32; \
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
/* Tell sys/endian.h we have MD variants of the swap macros.  */
 | 
			
		||||
#define MD_SWAP
 | 
			
		||||
 | 
			
		||||
#endif  /* __GNUC__ */
 | 
			
		||||
 | 
			
		||||
#if defined(__ARMEB__)
 | 
			
		||||
#define _BYTE_ORDER _BIG_ENDIAN
 | 
			
		||||
#else
 | 
			
		||||
#define _BYTE_ORDER _LITTLE_ENDIAN
 | 
			
		||||
#endif
 | 
			
		||||
#define __STRICT_ALIGNMENT
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/endian.h>
 | 
			
		||||
 | 
			
		||||
#endif  /* !_ARM_ENDIAN_H_ */
 | 
			
		||||
							
								
								
									
										50
									
								
								libc/arch-arm/include/machine/exec.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								libc/arch-arm/include/machine/exec.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,50 @@
 | 
			
		||||
/*	$OpenBSD: exec.h,v 1.9 2003/04/17 03:42:14 drahn Exp $	*/
 | 
			
		||||
/*	$NetBSD: exec.h,v 1.6 1994/10/27 04:16:05 cgd Exp $	*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 1993 Christopher G. Demetriou
 | 
			
		||||
 * 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 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _ARM_EXEC_H_
 | 
			
		||||
#define _ARM_EXEC_H_
 | 
			
		||||
 | 
			
		||||
#define __LDPGSZ	4096
 | 
			
		||||
 | 
			
		||||
#define NATIVE_EXEC_ELF
 | 
			
		||||
 | 
			
		||||
#define ARCH_ELFSIZE		32
 | 
			
		||||
 | 
			
		||||
#define ELF_TARG_CLASS		ELFCLASS32
 | 
			
		||||
#define ELF_TARG_DATA		ELFDATA2LSB
 | 
			
		||||
#define ELF_TARG_MACH		EM_ARM
 | 
			
		||||
 | 
			
		||||
#define _NLIST_DO_AOUT
 | 
			
		||||
#define _NLIST_DO_ELF
 | 
			
		||||
 | 
			
		||||
#define _KERN_DO_AOUT
 | 
			
		||||
#define _KERN_DO_ELF
 | 
			
		||||
 | 
			
		||||
#endif  /* _ARM_EXEC_H_ */
 | 
			
		||||
@@ -26,6 +26,10 @@
 | 
			
		||||
 * SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * machine/setjmp.h: machine dependent setjmp-related information.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* _JBLEN is the size of a jmp_buf in longs.
 | 
			
		||||
 * Do not modify this value or you will break the ABI !
 | 
			
		||||
 *
 | 
			
		||||
@@ -33,3 +37,46 @@
 | 
			
		||||
 * that was replaced by this one.
 | 
			
		||||
 */
 | 
			
		||||
#define _JBLEN  64
 | 
			
		||||
 | 
			
		||||
/* According to the ARM AAPCS document, we only need to save
 | 
			
		||||
 * the following registers:
 | 
			
		||||
 *
 | 
			
		||||
 *  Core   r4-r14
 | 
			
		||||
 *
 | 
			
		||||
 *  VFP    d8-d15  (see section 5.1.2.1)
 | 
			
		||||
 *
 | 
			
		||||
 *      Registers s16-s31 (d8-d15, q4-q7) must be preserved across subroutine
 | 
			
		||||
 *      calls; registers s0-s15 (d0-d7, q0-q3) do not need to be preserved
 | 
			
		||||
 *      (and can be used for passing arguments or returning results in standard
 | 
			
		||||
 *      procedure-call variants). Registers d16-d31 (q8-q15), if present, do
 | 
			
		||||
 *      not need to be preserved.
 | 
			
		||||
 *
 | 
			
		||||
 *  FPSCR  saved because GLibc does saves it too.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* The internal structure of a jmp_buf is totally private.
 | 
			
		||||
 * Current layout (may change in the future):
 | 
			
		||||
 *
 | 
			
		||||
 * word   name         description
 | 
			
		||||
 * 0      magic        magic number
 | 
			
		||||
 * 1      sigmask      signal mask (not used with _setjmp / _longjmp)
 | 
			
		||||
 * 2      float_base   base of float registers (d8 to d15)
 | 
			
		||||
 * 18     float_state  floating-point status and control register
 | 
			
		||||
 * 19     core_base    base of core registers (r4 to r14)
 | 
			
		||||
 * 30     reserved     reserved entries (room to grow)
 | 
			
		||||
 * 64
 | 
			
		||||
 *
 | 
			
		||||
 * NOTE: float_base must be at an even word index, since the
 | 
			
		||||
 *       FP registers will be loaded/stored with instructions
 | 
			
		||||
 *       that expect 8-byte alignment.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define _JB_MAGIC       0
 | 
			
		||||
#define _JB_SIGMASK     (_JB_MAGIC+1)
 | 
			
		||||
#define _JB_FLOAT_BASE  (_JB_SIGMASK+1)
 | 
			
		||||
#define _JB_FLOAT_STATE (_JB_FLOAT_BASE + (15-8+1)*2)
 | 
			
		||||
#define _JB_CORE_BASE   (_JB_FLOAT_STATE+1)
 | 
			
		||||
 | 
			
		||||
#define _JB_MAGIC__SETJMP	0x4278f500
 | 
			
		||||
#define _JB_MAGIC_SETJMP	0x4278f501
 | 
			
		||||
 
 | 
			
		||||
@@ -37,7 +37,6 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
    .fpu    neon
 | 
			
		||||
    .syntax unified
 | 
			
		||||
 | 
			
		||||
ENTRY(__memset_chk)
 | 
			
		||||
        cmp         r2, r3
 | 
			
		||||
@@ -99,9 +98,9 @@ ENTRY(memset)
 | 
			
		||||
1:      bge         2f
 | 
			
		||||
        vst1.32     {d0[0]}, [r0]!
 | 
			
		||||
2:      movs        ip, r2, lsl #31
 | 
			
		||||
        strbmi      r1, [r0], #1
 | 
			
		||||
        strbcs      r1, [r0], #1
 | 
			
		||||
        strbcs      r1, [r0], #1
 | 
			
		||||
        strmib      r1, [r0], #1
 | 
			
		||||
        strcsb      r1, [r0], #1
 | 
			
		||||
        strcsb      r1, [r0], #1
 | 
			
		||||
        ldmfd       sp!, {r0}
 | 
			
		||||
        bx          lr
 | 
			
		||||
END(memset)
 | 
			
		||||
 
 | 
			
		||||
@@ -11,9 +11,4 @@ libc_bionic_src_files_arm += \
 | 
			
		||||
    arch-arm/cortex-a15/bionic/strcat.S \
 | 
			
		||||
    arch-arm/cortex-a15/bionic/strcpy.S \
 | 
			
		||||
    arch-arm/cortex-a15/bionic/strlen.S \
 | 
			
		||||
 | 
			
		||||
libc_bionic_src_files_arm += \
 | 
			
		||||
    arch-arm/generic/bionic/memcmp.S \
 | 
			
		||||
 | 
			
		||||
libc_bionic_src_files_arm += \
 | 
			
		||||
    arch-arm/denver/bionic/memmove.S \
 | 
			
		||||
    bionic/memmove.c \
 | 
			
		||||
 
 | 
			
		||||
@@ -1,15 +0,0 @@
 | 
			
		||||
/* Generated by gensyscalls.py. Do not edit. */
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(___rt_sigqueueinfo)
 | 
			
		||||
    mov     ip, r7
 | 
			
		||||
    ldr     r7, =__NR_rt_sigqueueinfo
 | 
			
		||||
    swi     #0
 | 
			
		||||
    mov     r7, ip
 | 
			
		||||
    cmn     r0, #(MAX_ERRNO + 1)
 | 
			
		||||
    bxls    lr
 | 
			
		||||
    neg     r0, r0
 | 
			
		||||
    b       __set_errno_internal
 | 
			
		||||
END(___rt_sigqueueinfo)
 | 
			
		||||
.hidden ___rt_sigqueueinfo
 | 
			
		||||
@@ -13,4 +13,5 @@ ENTRY(_exit)
 | 
			
		||||
    b       __set_errno_internal
 | 
			
		||||
END(_exit)
 | 
			
		||||
 | 
			
		||||
ALIAS_SYMBOL(_Exit, _exit)
 | 
			
		||||
    .globl _Exit
 | 
			
		||||
    .equ _Exit, _exit
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(___clock_nanosleep)
 | 
			
		||||
ENTRY(clock_nanosleep)
 | 
			
		||||
    mov     ip, r7
 | 
			
		||||
    ldr     r7, =__NR_clock_nanosleep
 | 
			
		||||
    swi     #0
 | 
			
		||||
@@ -11,5 +11,4 @@ ENTRY(___clock_nanosleep)
 | 
			
		||||
    bxls    lr
 | 
			
		||||
    neg     r0, r0
 | 
			
		||||
    b       __set_errno_internal
 | 
			
		||||
END(___clock_nanosleep)
 | 
			
		||||
.hidden ___clock_nanosleep
 | 
			
		||||
END(clock_nanosleep)
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(___close)
 | 
			
		||||
ENTRY(close)
 | 
			
		||||
    mov     ip, r7
 | 
			
		||||
    ldr     r7, =__NR_close
 | 
			
		||||
    swi     #0
 | 
			
		||||
@@ -11,5 +11,4 @@ ENTRY(___close)
 | 
			
		||||
    bxls    lr
 | 
			
		||||
    neg     r0, r0
 | 
			
		||||
    b       __set_errno_internal
 | 
			
		||||
END(___close)
 | 
			
		||||
.hidden ___close
 | 
			
		||||
END(close)
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(___faccessat)
 | 
			
		||||
ENTRY(faccessat)
 | 
			
		||||
    mov     ip, r7
 | 
			
		||||
    ldr     r7, =__NR_faccessat
 | 
			
		||||
    swi     #0
 | 
			
		||||
@@ -11,5 +11,4 @@ ENTRY(___faccessat)
 | 
			
		||||
    bxls    lr
 | 
			
		||||
    neg     r0, r0
 | 
			
		||||
    b       __set_errno_internal
 | 
			
		||||
END(___faccessat)
 | 
			
		||||
.hidden ___faccessat
 | 
			
		||||
END(faccessat)
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(___fchmod)
 | 
			
		||||
ENTRY(fchmod)
 | 
			
		||||
    mov     ip, r7
 | 
			
		||||
    ldr     r7, =__NR_fchmod
 | 
			
		||||
    swi     #0
 | 
			
		||||
@@ -11,5 +11,4 @@ ENTRY(___fchmod)
 | 
			
		||||
    bxls    lr
 | 
			
		||||
    neg     r0, r0
 | 
			
		||||
    b       __set_errno_internal
 | 
			
		||||
END(___fchmod)
 | 
			
		||||
.hidden ___fchmod
 | 
			
		||||
END(fchmod)
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(___fchmodat)
 | 
			
		||||
ENTRY(fchmodat)
 | 
			
		||||
    mov     ip, r7
 | 
			
		||||
    ldr     r7, =__NR_fchmodat
 | 
			
		||||
    swi     #0
 | 
			
		||||
@@ -11,5 +11,4 @@ ENTRY(___fchmodat)
 | 
			
		||||
    bxls    lr
 | 
			
		||||
    neg     r0, r0
 | 
			
		||||
    b       __set_errno_internal
 | 
			
		||||
END(___fchmodat)
 | 
			
		||||
.hidden ___fchmodat
 | 
			
		||||
END(fchmodat)
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(___fgetxattr)
 | 
			
		||||
ENTRY(fgetxattr)
 | 
			
		||||
    mov     ip, r7
 | 
			
		||||
    ldr     r7, =__NR_fgetxattr
 | 
			
		||||
    swi     #0
 | 
			
		||||
@@ -11,5 +11,4 @@ ENTRY(___fgetxattr)
 | 
			
		||||
    bxls    lr
 | 
			
		||||
    neg     r0, r0
 | 
			
		||||
    b       __set_errno_internal
 | 
			
		||||
END(___fgetxattr)
 | 
			
		||||
.hidden ___fgetxattr
 | 
			
		||||
END(fgetxattr)
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(___fsetxattr)
 | 
			
		||||
ENTRY(fsetxattr)
 | 
			
		||||
    mov     ip, sp
 | 
			
		||||
    stmfd   sp!, {r4, r5, r6, r7}
 | 
			
		||||
    .cfi_def_cfa_offset 16
 | 
			
		||||
@@ -19,5 +19,4 @@ ENTRY(___fsetxattr)
 | 
			
		||||
    bxls    lr
 | 
			
		||||
    neg     r0, r0
 | 
			
		||||
    b       __set_errno_internal
 | 
			
		||||
END(___fsetxattr)
 | 
			
		||||
.hidden ___fsetxattr
 | 
			
		||||
END(fsetxattr)
 | 
			
		||||
@@ -13,4 +13,5 @@ ENTRY(fstat64)
 | 
			
		||||
    b       __set_errno_internal
 | 
			
		||||
END(fstat64)
 | 
			
		||||
 | 
			
		||||
ALIAS_SYMBOL(fstat, fstat64)
 | 
			
		||||
    .globl fstat
 | 
			
		||||
    .equ fstat, fstat64
 | 
			
		||||
 
 | 
			
		||||
@@ -13,4 +13,5 @@ ENTRY(fstatat64)
 | 
			
		||||
    b       __set_errno_internal
 | 
			
		||||
END(fstatat64)
 | 
			
		||||
 | 
			
		||||
ALIAS_SYMBOL(fstatat, fstatat64)
 | 
			
		||||
    .globl fstatat
 | 
			
		||||
    .equ fstatat, fstatat64
 | 
			
		||||
 
 | 
			
		||||
@@ -2,13 +2,13 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(sethostname)
 | 
			
		||||
ENTRY(ftruncate)
 | 
			
		||||
    mov     ip, r7
 | 
			
		||||
    ldr     r7, =__NR_sethostname
 | 
			
		||||
    ldr     r7, =__NR_ftruncate
 | 
			
		||||
    swi     #0
 | 
			
		||||
    mov     r7, ip
 | 
			
		||||
    cmn     r0, #(MAX_ERRNO + 1)
 | 
			
		||||
    bxls    lr
 | 
			
		||||
    neg     r0, r0
 | 
			
		||||
    b       __set_errno_internal
 | 
			
		||||
END(sethostname)
 | 
			
		||||
END(ftruncate)
 | 
			
		||||
@@ -1,22 +0,0 @@
 | 
			
		||||
/* Generated by gensyscalls.py. Do not edit. */
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(process_vm_readv)
 | 
			
		||||
    mov     ip, sp
 | 
			
		||||
    stmfd   sp!, {r4, r5, r6, r7}
 | 
			
		||||
    .cfi_def_cfa_offset 16
 | 
			
		||||
    .cfi_rel_offset r4, 0
 | 
			
		||||
    .cfi_rel_offset r5, 4
 | 
			
		||||
    .cfi_rel_offset r6, 8
 | 
			
		||||
    .cfi_rel_offset r7, 12
 | 
			
		||||
    ldmfd   ip, {r4, r5, r6}
 | 
			
		||||
    ldr     r7, =__NR_process_vm_readv
 | 
			
		||||
    swi     #0
 | 
			
		||||
    ldmfd   sp!, {r4, r5, r6, r7}
 | 
			
		||||
    .cfi_def_cfa_offset 0
 | 
			
		||||
    cmn     r0, #(MAX_ERRNO + 1)
 | 
			
		||||
    bxls    lr
 | 
			
		||||
    neg     r0, r0
 | 
			
		||||
    b       __set_errno_internal
 | 
			
		||||
END(process_vm_readv)
 | 
			
		||||
@@ -1,22 +0,0 @@
 | 
			
		||||
/* Generated by gensyscalls.py. Do not edit. */
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(process_vm_writev)
 | 
			
		||||
    mov     ip, sp
 | 
			
		||||
    stmfd   sp!, {r4, r5, r6, r7}
 | 
			
		||||
    .cfi_def_cfa_offset 16
 | 
			
		||||
    .cfi_rel_offset r4, 0
 | 
			
		||||
    .cfi_rel_offset r5, 4
 | 
			
		||||
    .cfi_rel_offset r6, 8
 | 
			
		||||
    .cfi_rel_offset r7, 12
 | 
			
		||||
    ldmfd   ip, {r4, r5, r6}
 | 
			
		||||
    ldr     r7, =__NR_process_vm_writev
 | 
			
		||||
    swi     #0
 | 
			
		||||
    ldmfd   sp!, {r4, r5, r6, r7}
 | 
			
		||||
    .cfi_def_cfa_offset 0
 | 
			
		||||
    cmn     r0, #(MAX_ERRNO + 1)
 | 
			
		||||
    bxls    lr
 | 
			
		||||
    neg     r0, r0
 | 
			
		||||
    b       __set_errno_internal
 | 
			
		||||
END(process_vm_writev)
 | 
			
		||||
@@ -8,6 +8,7 @@ libc_bionic_src_files_arm64 += \
 | 
			
		||||
    bionic/__memset_chk.cpp \
 | 
			
		||||
    bionic/__strcpy_chk.cpp \
 | 
			
		||||
    bionic/__strcat_chk.cpp \
 | 
			
		||||
    bionic/memrchr.c \
 | 
			
		||||
    bionic/strrchr.cpp \
 | 
			
		||||
 | 
			
		||||
libc_freebsd_src_files_arm64 += \
 | 
			
		||||
@@ -20,7 +21,6 @@ libc_freebsd_src_files_arm64 += \
 | 
			
		||||
    upstream-freebsd/lib/libc/string/wmemcmp.c \
 | 
			
		||||
 | 
			
		||||
libc_openbsd_src_files_arm64 += \
 | 
			
		||||
    upstream-openbsd/lib/libc/string/memrchr.c \
 | 
			
		||||
    upstream-openbsd/lib/libc/string/stpncpy.c \
 | 
			
		||||
    upstream-openbsd/lib/libc/string/strcat.c \
 | 
			
		||||
    upstream-openbsd/lib/libc/string/strlcat.c \
 | 
			
		||||
@@ -35,8 +35,10 @@ libc_openbsd_src_files_arm64 += \
 | 
			
		||||
libc_bionic_src_files_arm64 += \
 | 
			
		||||
    arch-arm64/bionic/__bionic_clone.S \
 | 
			
		||||
    arch-arm64/bionic/_exit_with_stack_teardown.S \
 | 
			
		||||
    arch-arm64/bionic/_setjmp.S \
 | 
			
		||||
    arch-arm64/bionic/setjmp.S \
 | 
			
		||||
    arch-arm64/bionic/__set_tls.c \
 | 
			
		||||
    arch-arm64/bionic/sigsetjmp.S \
 | 
			
		||||
    arch-arm64/bionic/syscall.S \
 | 
			
		||||
    arch-arm64/bionic/vfork.S \
 | 
			
		||||
 | 
			
		||||
@@ -59,6 +61,6 @@ ifeq ($(wildcard $(cpu_variant_mk)),)
 | 
			
		||||
$(error "TARGET_CPU_VARIANT not set or set to an unknown value. Possible values are generic, denver64. Use generic for devices that do not have a CPU similar to any of the supported cpu variants.")
 | 
			
		||||
endif
 | 
			
		||||
include $(cpu_variant_mk)
 | 
			
		||||
libc_common_additional_dependencies += $(cpu_variant_mk)
 | 
			
		||||
libc_common_additional_dependencies += $(cpu_variank_mk)
 | 
			
		||||
 | 
			
		||||
cpu_variant_mk :=
 | 
			
		||||
 
 | 
			
		||||
@@ -31,8 +31,8 @@
 | 
			
		||||
// pid_t __bionic_clone(int flags, void* child_stack, pid_t* parent_tid, void* tls, pid_t* child_tid, int (*fn)(void*), void* arg);
 | 
			
		||||
 | 
			
		||||
ENTRY(__bionic_clone)
 | 
			
		||||
    # Push 'fn' and 'arg' onto the child stack.
 | 
			
		||||
    stp     x5, x6, [x1, #-16]!
 | 
			
		||||
    # Copy 'fn' and 'arg' onto the child stack.
 | 
			
		||||
    stp     x5, x6, [x1, #-16]
 | 
			
		||||
 | 
			
		||||
    # Make the system call.
 | 
			
		||||
    mov     x8, __NR_clone
 | 
			
		||||
@@ -49,12 +49,12 @@ ENTRY(__bionic_clone)
 | 
			
		||||
    ret
 | 
			
		||||
 | 
			
		||||
.L_bc_child:
 | 
			
		||||
    # We're in the child now. Set the end of the frame record chain.
 | 
			
		||||
    mov     x29, #0
 | 
			
		||||
    # Setting x30 to 0 will make the unwinder stop at __start_thread.
 | 
			
		||||
    mov     x30, #0
 | 
			
		||||
    # Call __start_thread with the 'fn' and 'arg' we stored on the child stack.
 | 
			
		||||
    ldp     x0, x1, [sp], #16
 | 
			
		||||
    # We're in the child now. Set the end of the frame record chain...
 | 
			
		||||
    mov     x29, xzr
 | 
			
		||||
    # Setting x30 to 0 will make the unwinder stop at __start_thread
 | 
			
		||||
    mov     x30, xzr
 | 
			
		||||
    # ...and call __start_thread with the 'fn' and 'arg' we stored on the child stack.
 | 
			
		||||
    ldp     x0, x1, [sp, #-16]
 | 
			
		||||
    b       __start_thread
 | 
			
		||||
END(__bionic_clone)
 | 
			
		||||
.hidden __bionic_clone
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										111
									
								
								libc/arch-arm64/bionic/_setjmp.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								libc/arch-arm64/bionic/_setjmp.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,111 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2013 The Android Open Source Project
 | 
			
		||||
 * 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.
 | 
			
		||||
 *
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
#include <machine/setjmp.h>
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * C library - _setjmp, _longjmp
 | 
			
		||||
 *
 | 
			
		||||
 * _longjmp(jmp_buf state, int value)
 | 
			
		||||
 * will generate a "return(v)" from the last call to _setjmp(state) by restoring
 | 
			
		||||
 * registers from the stack. The previous signal state is NOT restored.
 | 
			
		||||
 *
 | 
			
		||||
 * NOTE: x0 return value
 | 
			
		||||
 *       x9-x15 temporary registers
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
ENTRY(_setjmp)
 | 
			
		||||
    /* store magic number */
 | 
			
		||||
    ldr     w9, .L_setjmp_magic
 | 
			
		||||
    str     w9, [x0, #(_JB_MAGIC * 4)]
 | 
			
		||||
 | 
			
		||||
    /* store core registers */
 | 
			
		||||
    mov     x10, sp
 | 
			
		||||
    stp     x30, x10, [x0, #(_JB_CORE_BASE * 4 + 16 * 0)]
 | 
			
		||||
    stp     x28, x29, [x0, #(_JB_CORE_BASE * 4 + 16 * 1)]
 | 
			
		||||
    stp     x26, x27, [x0, #(_JB_CORE_BASE * 4 + 16 * 2)]
 | 
			
		||||
    stp     x24, x25, [x0, #(_JB_CORE_BASE * 4 + 16 * 3)]
 | 
			
		||||
    stp     x22, x23, [x0, #(_JB_CORE_BASE * 4 + 16 * 4)]
 | 
			
		||||
    stp     x20, x21, [x0, #(_JB_CORE_BASE * 4 + 16 * 5)]
 | 
			
		||||
    str     x19,      [x0, #(_JB_CORE_BASE * 4 + 16 * 6)]
 | 
			
		||||
 | 
			
		||||
    /* store floating point registers */
 | 
			
		||||
    stp     d14, d15, [x0, #(_JB_FLOAT_BASE * 4 + 16 * 0)]
 | 
			
		||||
    stp     d12, d13, [x0, #(_JB_FLOAT_BASE * 4 + 16 * 1)]
 | 
			
		||||
    stp     d10, d11, [x0, #(_JB_FLOAT_BASE * 4 + 16 * 2)]
 | 
			
		||||
    stp     d8,  d9,  [x0, #(_JB_FLOAT_BASE * 4 + 16 * 3)]
 | 
			
		||||
 | 
			
		||||
    mov     w0, wzr
 | 
			
		||||
    ret
 | 
			
		||||
END(_setjmp)
 | 
			
		||||
 | 
			
		||||
.L_setjmp_magic:
 | 
			
		||||
    .word   _JB_MAGIC__SETJMP
 | 
			
		||||
 | 
			
		||||
ENTRY(_longjmp)
 | 
			
		||||
    /* check magic */
 | 
			
		||||
    ldr     w9, .L_setjmp_magic
 | 
			
		||||
    ldr     w10, [x0, #(_JB_MAGIC * 4)]
 | 
			
		||||
    cmp     w9, w10
 | 
			
		||||
    b.ne    .L_fail
 | 
			
		||||
 | 
			
		||||
    /* restore core registers */
 | 
			
		||||
    ldp     x30, x10, [x0, #(_JB_CORE_BASE * 4 + 16 * 0)]
 | 
			
		||||
    mov     sp, x10
 | 
			
		||||
    ldp     x28, x29, [x0, #(_JB_CORE_BASE * 4 + 16 * 1)]
 | 
			
		||||
    ldp     x26, x27, [x0, #(_JB_CORE_BASE * 4 + 16 * 2)]
 | 
			
		||||
    ldp     x24, x25, [x0, #(_JB_CORE_BASE * 4 + 16 * 3)]
 | 
			
		||||
    ldp     x22, x23, [x0, #(_JB_CORE_BASE * 4 + 16 * 4)]
 | 
			
		||||
    ldp     x20, x21, [x0, #(_JB_CORE_BASE * 4 + 16 * 5)]
 | 
			
		||||
    ldr     x19,      [x0, #(_JB_CORE_BASE * 4 + 16 * 6)]
 | 
			
		||||
 | 
			
		||||
    /* restore floating point registers */
 | 
			
		||||
    ldp     d14, d15, [x0, #(_JB_FLOAT_BASE * 4 + 16 * 0)]
 | 
			
		||||
    ldp     d12, d13, [x0, #(_JB_FLOAT_BASE * 4 + 16 * 1)]
 | 
			
		||||
    ldp     d10, d11, [x0, #(_JB_FLOAT_BASE * 4 + 16 * 2)]
 | 
			
		||||
    ldp     d8,  d9,  [x0, #(_JB_FLOAT_BASE * 4 + 16 * 3)]
 | 
			
		||||
 | 
			
		||||
    /* validate sp (sp mod 16 = 0) and lr (lr mod 4 = 0) */
 | 
			
		||||
    tst     x30, #3
 | 
			
		||||
    b.ne    .L_fail
 | 
			
		||||
    mov     x10, sp
 | 
			
		||||
    tst     x10, #15
 | 
			
		||||
    b.ne    .L_fail
 | 
			
		||||
 | 
			
		||||
    /* set return value */
 | 
			
		||||
    cmp     w1, wzr
 | 
			
		||||
    csinc   w0, w1, wzr, ne
 | 
			
		||||
    ret
 | 
			
		||||
 | 
			
		||||
    /* validation failed, die die die */
 | 
			
		||||
.L_fail:
 | 
			
		||||
    bl      PIC_SYM(longjmperror, PLT)
 | 
			
		||||
    bl      PIC_SYM(abort, PLT)
 | 
			
		||||
    b        . - 8       /* Cannot get here */
 | 
			
		||||
END(_longjmp)
 | 
			
		||||
@@ -67,4 +67,3 @@ __asm__ (
 | 
			
		||||
 | 
			
		||||
#include "../../arch-common/bionic/__dso_handle.h"
 | 
			
		||||
#include "../../arch-common/bionic/atexit.h"
 | 
			
		||||
#include "../../arch-common/bionic/pthread_atfork.h"
 | 
			
		||||
 
 | 
			
		||||
@@ -27,124 +27,97 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
#include <machine/setjmp.h>
 | 
			
		||||
 | 
			
		||||
// According to AARCH64 PCS document we need to save the following
 | 
			
		||||
// registers:
 | 
			
		||||
//
 | 
			
		||||
// Core     x19 - x30, sp (see section 5.1.1)
 | 
			
		||||
// VFP      d8 - d15 (see section 5.1.2)
 | 
			
		||||
//
 | 
			
		||||
// NOTE: All the registers saved here will have 64 bit vales.
 | 
			
		||||
//       AAPCS mandates that the higher part of q registers do not need to
 | 
			
		||||
//       be saved by the callee.
 | 
			
		||||
 | 
			
		||||
#define _JB_SIGFLAG     0
 | 
			
		||||
#define _JB_SIGMASK     (_JB_SIGFLAG + 1)
 | 
			
		||||
#define _JB_X30_SP      (_JB_SIGMASK + 1)
 | 
			
		||||
#define _JB_X28_X29     (_JB_X30_SP  + 2)
 | 
			
		||||
#define _JB_X26_X27     (_JB_X28_X29 + 2)
 | 
			
		||||
#define _JB_X24_X25     (_JB_X26_X27 + 2)
 | 
			
		||||
#define _JB_X22_X23     (_JB_X24_X25 + 2)
 | 
			
		||||
#define _JB_X20_X21     (_JB_X22_X23 + 2)
 | 
			
		||||
#define _JB_X19         (_JB_X20_X21 + 2)
 | 
			
		||||
#define _JB_D14_D15     (_JB_X19 + 1)
 | 
			
		||||
#define _JB_D12_D13     (_JB_D14_D15 + 2)
 | 
			
		||||
#define _JB_D10_D11     (_JB_D12_D13 + 2)
 | 
			
		||||
#define _JB_D8_D9       (_JB_D10_D11 + 2)
 | 
			
		||||
/*
 | 
			
		||||
 * C library - _setjmp, _longjmp
 | 
			
		||||
 *
 | 
			
		||||
 * _longjmp(jmp_buf state, int value)
 | 
			
		||||
 * will generate a "return(v)" from the last call to _setjmp(state) by restoring
 | 
			
		||||
 * registers from the stack. The previous signal state is NOT restored.
 | 
			
		||||
 *
 | 
			
		||||
 * NOTE: x0 return value
 | 
			
		||||
 *       x9-x15 temporary registers
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
ENTRY(setjmp)
 | 
			
		||||
  mov w1, #1
 | 
			
		||||
  b sigsetjmp
 | 
			
		||||
    /* block all signals an retrieve signal mask */
 | 
			
		||||
    stp     x0, x30, [sp, #-16]!
 | 
			
		||||
 | 
			
		||||
    mov     x0, xzr
 | 
			
		||||
    bl      PIC_SYM(sigblock, PLT)
 | 
			
		||||
    mov     w1, w0
 | 
			
		||||
 | 
			
		||||
    ldp     x0, x30, [sp], #16
 | 
			
		||||
 | 
			
		||||
    /* store signal mask */
 | 
			
		||||
    str     w1, [x0, #(_JB_SIGMASK *4)]
 | 
			
		||||
 | 
			
		||||
    /* store magic number */
 | 
			
		||||
    ldr     w9, .L_setjmp_magic
 | 
			
		||||
    str     w9, [x0, #(_JB_MAGIC * 4)]
 | 
			
		||||
 | 
			
		||||
    /* store core registers */
 | 
			
		||||
    mov     x10, sp
 | 
			
		||||
    stp     x30, x10, [x0, #(_JB_CORE_BASE * 4 + 16 * 0)]
 | 
			
		||||
    stp     x28, x29, [x0, #(_JB_CORE_BASE * 4 + 16 * 1)]
 | 
			
		||||
    stp     x26, x27, [x0, #(_JB_CORE_BASE * 4 + 16 * 2)]
 | 
			
		||||
    stp     x24, x25, [x0, #(_JB_CORE_BASE * 4 + 16 * 3)]
 | 
			
		||||
    stp     x22, x23, [x0, #(_JB_CORE_BASE * 4 + 16 * 4)]
 | 
			
		||||
    stp     x20, x21, [x0, #(_JB_CORE_BASE * 4 + 16 * 5)]
 | 
			
		||||
    str     x19,      [x0, #(_JB_CORE_BASE * 4 + 16 * 6)]
 | 
			
		||||
 | 
			
		||||
    /* store floating point registers */
 | 
			
		||||
    stp     d14, d15, [x0, #(_JB_FLOAT_BASE * 4 + 16 * 0)]
 | 
			
		||||
    stp     d12, d13, [x0, #(_JB_FLOAT_BASE * 4 + 16 * 1)]
 | 
			
		||||
    stp     d10, d11, [x0, #(_JB_FLOAT_BASE * 4 + 16 * 2)]
 | 
			
		||||
    stp     d8,  d9,  [x0, #(_JB_FLOAT_BASE * 4 + 16 * 3)]
 | 
			
		||||
 | 
			
		||||
    mov     w0, wzr
 | 
			
		||||
    ret
 | 
			
		||||
END(setjmp)
 | 
			
		||||
 | 
			
		||||
ENTRY(_setjmp)
 | 
			
		||||
  mov w1, #0
 | 
			
		||||
  b sigsetjmp
 | 
			
		||||
END(_setjmp)
 | 
			
		||||
.L_setjmp_magic:
 | 
			
		||||
    .word   _JB_MAGIC__SETJMP
 | 
			
		||||
 | 
			
		||||
// int sigsetjmp(sigjmp_buf env, int save_signal_mask);
 | 
			
		||||
ENTRY(sigsetjmp)
 | 
			
		||||
  // Record whether or not we're saving the signal mask.
 | 
			
		||||
  str w1, [x0, #(_JB_SIGFLAG * 8)]
 | 
			
		||||
ENTRY(longjmp)
 | 
			
		||||
    /* check magic */
 | 
			
		||||
    ldr     w9, .L_setjmp_magic
 | 
			
		||||
    ldr     w10, [x0, #(_JB_MAGIC * 4)]
 | 
			
		||||
    cmp     w9, w10
 | 
			
		||||
    b.ne    .L_fail
 | 
			
		||||
 | 
			
		||||
  // Do we need to save the signal mask?
 | 
			
		||||
  cbz w1, 1f
 | 
			
		||||
    /* restore core registers */
 | 
			
		||||
    ldp     x30, x10, [x0, #(_JB_CORE_BASE * 4 + 16 * 0)]
 | 
			
		||||
    mov     sp, x10
 | 
			
		||||
    ldp     x28, x29, [x0, #(_JB_CORE_BASE * 4 + 16 * 1)]
 | 
			
		||||
    ldp     x26, x27, [x0, #(_JB_CORE_BASE * 4 + 16 * 2)]
 | 
			
		||||
    ldp     x24, x25, [x0, #(_JB_CORE_BASE * 4 + 16 * 3)]
 | 
			
		||||
    ldp     x22, x23, [x0, #(_JB_CORE_BASE * 4 + 16 * 4)]
 | 
			
		||||
    ldp     x20, x21, [x0, #(_JB_CORE_BASE * 4 + 16 * 5)]
 | 
			
		||||
    ldr     x19,      [x0, #(_JB_CORE_BASE * 4 + 16 * 6)]
 | 
			
		||||
 | 
			
		||||
  // Save current signal mask.
 | 
			
		||||
  stp x0, x30, [sp, #-16]!
 | 
			
		||||
  // The 'how' argument is ignored if new_mask is NULL.
 | 
			
		||||
  mov x1, #0 // NULL.
 | 
			
		||||
  add x2, x0, #(_JB_SIGMASK * 8) // old_mask.
 | 
			
		||||
  bl sigprocmask
 | 
			
		||||
  ldp x0, x30, [sp], #16
 | 
			
		||||
    /* restore floating point registers */
 | 
			
		||||
    ldp     d14, d15, [x0, #(_JB_FLOAT_BASE * 4 + 16 * 0)]
 | 
			
		||||
    ldp     d12, d13, [x0, #(_JB_FLOAT_BASE * 4 + 16 * 1)]
 | 
			
		||||
    ldp     d10, d11, [x0, #(_JB_FLOAT_BASE * 4 + 16 * 2)]
 | 
			
		||||
    ldp     d8,  d9,  [x0, #(_JB_FLOAT_BASE * 4 + 16 * 3)]
 | 
			
		||||
 | 
			
		||||
1:
 | 
			
		||||
  // Save core registers.
 | 
			
		||||
  mov x10, sp
 | 
			
		||||
  stp x30, x10, [x0, #(_JB_X30_SP  * 8)]
 | 
			
		||||
  stp x28, x29, [x0, #(_JB_X28_X29 * 8)]
 | 
			
		||||
  stp x26, x27, [x0, #(_JB_X26_X27 * 8)]
 | 
			
		||||
  stp x24, x25, [x0, #(_JB_X24_X25 * 8)]
 | 
			
		||||
  stp x22, x23, [x0, #(_JB_X22_X23 * 8)]
 | 
			
		||||
  stp x20, x21, [x0, #(_JB_X20_X21 * 8)]
 | 
			
		||||
  str x19,      [x0, #(_JB_X19     * 8)]
 | 
			
		||||
    /* validate sp (sp mod 16 = 0) and lr (lr mod 4 = 0) */
 | 
			
		||||
    tst     x30, #3
 | 
			
		||||
    b.ne    .L_fail
 | 
			
		||||
    mov     x10, sp
 | 
			
		||||
    tst     x10, #15
 | 
			
		||||
    b.ne    .L_fail
 | 
			
		||||
 | 
			
		||||
  // Save floating point registers.
 | 
			
		||||
  stp d14, d15, [x0, #(_JB_D14_D15 * 8)]
 | 
			
		||||
  stp d12, d13, [x0, #(_JB_D12_D13 * 8)]
 | 
			
		||||
  stp d10, d11, [x0, #(_JB_D10_D11 * 8)]
 | 
			
		||||
  stp d8,  d9,  [x0, #(_JB_D8_D9   * 8)]
 | 
			
		||||
    /* set return value */
 | 
			
		||||
    cmp     w1, wzr
 | 
			
		||||
    csinc   w0, w1, wzr, ne
 | 
			
		||||
    ret
 | 
			
		||||
 | 
			
		||||
  mov w0, #0
 | 
			
		||||
  ret
 | 
			
		||||
END(sigsetjmp)
 | 
			
		||||
 | 
			
		||||
// void siglongjmp(sigjmp_buf env, int value);
 | 
			
		||||
ENTRY(siglongjmp)
 | 
			
		||||
  // Do we need to restore the signal mask?
 | 
			
		||||
  ldr w9, [x0, #(_JB_SIGFLAG * 8)]
 | 
			
		||||
  cbz w9, 1f
 | 
			
		||||
 | 
			
		||||
  // Restore signal mask.
 | 
			
		||||
  stp x0, x30, [sp, #-16]!
 | 
			
		||||
  mov x19, x1 // Save 'value'.
 | 
			
		||||
  mov x2, x0
 | 
			
		||||
  mov x0, #2 // SIG_SETMASK
 | 
			
		||||
  add x1, x2, #(_JB_SIGMASK * 8) // new_mask.
 | 
			
		||||
  mov x2, #0 // NULL.
 | 
			
		||||
  bl sigprocmask
 | 
			
		||||
  mov x1, x19 // Restore 'value'.
 | 
			
		||||
  ldp x0, x30, [sp], #16
 | 
			
		||||
 | 
			
		||||
1:
 | 
			
		||||
  // Restore core registers.
 | 
			
		||||
  ldp x30, x10, [x0, #(_JB_X30_SP  * 8)]
 | 
			
		||||
  mov sp, x10
 | 
			
		||||
  ldp x28, x29, [x0, #(_JB_X28_X29 * 8)]
 | 
			
		||||
  ldp x26, x27, [x0, #(_JB_X26_X27 * 8)]
 | 
			
		||||
  ldp x24, x25, [x0, #(_JB_X24_X25 * 8)]
 | 
			
		||||
  ldp x22, x23, [x0, #(_JB_X22_X23 * 8)]
 | 
			
		||||
  ldp x20, x21, [x0, #(_JB_X20_X21 * 8)]
 | 
			
		||||
  ldr x19,      [x0, #(_JB_X19     * 8)]
 | 
			
		||||
 | 
			
		||||
  // Restore floating point registers.
 | 
			
		||||
  ldp d14, d15, [x0, #(_JB_D14_D15 * 8)]
 | 
			
		||||
  ldp d12, d13, [x0, #(_JB_D12_D13 * 8)]
 | 
			
		||||
  ldp d10, d11, [x0, #(_JB_D10_D11 * 8)]
 | 
			
		||||
  ldp d8,  d9,  [x0, #(_JB_D8_D9   * 8)]
 | 
			
		||||
 | 
			
		||||
  // Validate sp (sp mod 16 = 0) and lr (lr mod 4 = 0).
 | 
			
		||||
  tst x30, #3
 | 
			
		||||
  b.ne longjmperror
 | 
			
		||||
  mov x10, sp
 | 
			
		||||
  tst x10, #15
 | 
			
		||||
  b.ne longjmperror
 | 
			
		||||
 | 
			
		||||
  // Set return value.
 | 
			
		||||
  cmp w1, wzr
 | 
			
		||||
  csinc w0, w1, wzr, ne
 | 
			
		||||
  ret
 | 
			
		||||
END(siglongjmp)
 | 
			
		||||
 | 
			
		||||
ALIAS_SYMBOL(longjmp, siglongjmp)
 | 
			
		||||
ALIAS_SYMBOL(_longjmp, siglongjmp)
 | 
			
		||||
    /* validation failed, die die die */
 | 
			
		||||
.L_fail:
 | 
			
		||||
    bl      PIC_SYM(longjmperror, PLT)
 | 
			
		||||
    bl      PIC_SYM(abort, PLT)
 | 
			
		||||
    b       . - 8       /* Cannot get here */
 | 
			
		||||
END(longjmp)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2014 The Android Open Source Project
 | 
			
		||||
 * Copyright (C) 2013 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
@@ -26,21 +26,26 @@
 | 
			
		||||
 * SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _MACHINE_TIMESPEC_H_
 | 
			
		||||
#define _MACHINE_TIMESPEC_H_
 | 
			
		||||
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
#include <machine/setjmp.h>
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This file is used to include timespec definition without introducing the whole
 | 
			
		||||
 * <linux/time.h>, <sys/time.h> or <time.h>.
 | 
			
		||||
 * int sigsetjmp(sigjmp_buf env, int savesigs);
 | 
			
		||||
 * void siglongjmp(sigjmp_buf env, int val);
 | 
			
		||||
 */
 | 
			
		||||
#ifndef _STRUCT_TIMESPEC
 | 
			
		||||
#define _STRUCT_TIMESPEC
 | 
			
		||||
struct timespec {
 | 
			
		||||
  time_t tv_sec;
 | 
			
		||||
  long tv_nsec;
 | 
			
		||||
};
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* _MACHINE_TIMESPEC_H_ */
 | 
			
		||||
ENTRY(sigsetjmp)
 | 
			
		||||
    cbz     w1, PIC_SYM(_setjmp, PLT)
 | 
			
		||||
    b       PIC_SYM(setjmp, PLT)
 | 
			
		||||
END(sigsetjmp)
 | 
			
		||||
 | 
			
		||||
.L_setjmp_magic:
 | 
			
		||||
    .word   _JB_MAGIC__SETJMP
 | 
			
		||||
 | 
			
		||||
ENTRY(siglongjmp)
 | 
			
		||||
    ldr     w2, .L_setjmp_magic
 | 
			
		||||
    ldr     w3, [x0]
 | 
			
		||||
    cmp     w2, w3
 | 
			
		||||
    b.eq    PIC_SYM(_longjmp, PLT)
 | 
			
		||||
    b       PIC_SYM(longjmp, PLT)
 | 
			
		||||
END(siglongjmp)
 | 
			
		||||
@@ -1 +0,0 @@
 | 
			
		||||
include bionic/libc/arch-arm64/generic/generic.mk
 | 
			
		||||
@@ -101,7 +101,7 @@ ENTRY(memchr)
 | 
			
		||||
	and	vhas_chr2.16b, vhas_chr2.16b, vrepmask.16b
 | 
			
		||||
	addp	vend.16b, vhas_chr1.16b, vhas_chr2.16b		/* 256->128 */
 | 
			
		||||
	addp	vend.16b, vend.16b, vend.16b			/* 128->64 */
 | 
			
		||||
	mov	synd, vend.d[0]
 | 
			
		||||
	mov	synd, vend.2d[0]
 | 
			
		||||
	/* Clear the soff*2 lower bits */
 | 
			
		||||
	lsl	tmp, soff, #1
 | 
			
		||||
	lsr	synd, synd, tmp
 | 
			
		||||
@@ -121,7 +121,7 @@ ENTRY(memchr)
 | 
			
		||||
	/* Use a fast check for the termination condition */
 | 
			
		||||
	orr	vend.16b, vhas_chr1.16b, vhas_chr2.16b
 | 
			
		||||
	addp	vend.2d, vend.2d, vend.2d
 | 
			
		||||
	mov	synd, vend.d[0]
 | 
			
		||||
	mov	synd, vend.2d[0]
 | 
			
		||||
	/* We're not out of data, loop if we haven't found the character */
 | 
			
		||||
	cbz	synd, .Lloop
 | 
			
		||||
 | 
			
		||||
@@ -131,7 +131,7 @@ ENTRY(memchr)
 | 
			
		||||
	and	vhas_chr2.16b, vhas_chr2.16b, vrepmask.16b
 | 
			
		||||
	addp	vend.16b, vhas_chr1.16b, vhas_chr2.16b		/* 256->128 */
 | 
			
		||||
	addp	vend.16b, vend.16b, vend.16b			/* 128->64 */
 | 
			
		||||
	mov	synd, vend.d[0]
 | 
			
		||||
	mov	synd, vend.2d[0]
 | 
			
		||||
	/* Only do the clear for the last possible block */
 | 
			
		||||
	b.hi	.Ltail
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -109,7 +109,7 @@ ENTRY(strchr)
 | 
			
		||||
	addp	vend1.16b, vend1.16b, vend2.16b		// 128->64
 | 
			
		||||
	lsr	tmp1, tmp3, tmp1
 | 
			
		||||
 | 
			
		||||
	mov	tmp3, vend1.d[0]
 | 
			
		||||
	mov	tmp3, vend1.2d[0]
 | 
			
		||||
	bic	tmp1, tmp3, tmp1	// Mask padding bits.
 | 
			
		||||
	cbnz	tmp1, .Ltail
 | 
			
		||||
 | 
			
		||||
@@ -124,7 +124,7 @@ ENTRY(strchr)
 | 
			
		||||
	orr	vend2.16b, vhas_nul2.16b, vhas_chr2.16b
 | 
			
		||||
	orr	vend1.16b, vend1.16b, vend2.16b
 | 
			
		||||
	addp	vend1.2d, vend1.2d, vend1.2d
 | 
			
		||||
	mov	tmp1, vend1.d[0]
 | 
			
		||||
	mov	tmp1, vend1.2d[0]
 | 
			
		||||
	cbz	tmp1, .Lloop
 | 
			
		||||
 | 
			
		||||
	/* Termination condition found.  Now need to establish exactly why
 | 
			
		||||
@@ -138,7 +138,7 @@ ENTRY(strchr)
 | 
			
		||||
	addp	vend1.16b, vend1.16b, vend2.16b		// 256->128
 | 
			
		||||
	addp	vend1.16b, vend1.16b, vend2.16b		// 128->64
 | 
			
		||||
 | 
			
		||||
	mov	tmp1, vend1.d[0]
 | 
			
		||||
	mov	tmp1, vend1.2d[0]
 | 
			
		||||
.Ltail:
 | 
			
		||||
	/* Count the trailing zeros, by bit reversing...  */
 | 
			
		||||
	rbit	tmp1, tmp1
 | 
			
		||||
 
 | 
			
		||||
@@ -38,9 +38,17 @@
 | 
			
		||||
#ifndef _AARCH64_ASM_H_
 | 
			
		||||
#define _AARCH64_ASM_H_
 | 
			
		||||
 | 
			
		||||
#define __bionic_asm_align 0
 | 
			
		||||
#ifndef _ALIGN_TEXT
 | 
			
		||||
# define _ALIGN_TEXT .align 0
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#undef __bionic_asm_function_type
 | 
			
		||||
#define __bionic_asm_function_type %function
 | 
			
		||||
 | 
			
		||||
#if defined(__ELF__) && defined(PIC)
 | 
			
		||||
#define PIC_SYM(x,y) x ## ( ## y ## )
 | 
			
		||||
#else
 | 
			
		||||
#define PIC_SYM(x,y) x
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* _AARCH64_ASM_H_ */
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										58
									
								
								libc/arch-arm64/include/machine/endian.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								libc/arch-arm64/include/machine/endian.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,58 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2013 The Android Open Source Project
 | 
			
		||||
 * 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.
 | 
			
		||||
 *
 | 
			
		||||
 * 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 _AARCH64_ENDIAN_H_
 | 
			
		||||
#define _AARCH64_ENDIAN_H_
 | 
			
		||||
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/endian.h>
 | 
			
		||||
 | 
			
		||||
#ifdef __GNUC__
 | 
			
		||||
 | 
			
		||||
#define __swap16md(x) ({                                        \
 | 
			
		||||
    register u_int16_t _x = (x);                                \
 | 
			
		||||
    __asm volatile ("rev16 %0, %0" : "+r" (_x));                \
 | 
			
		||||
    _x;                                                         \
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
/* Use GCC builtins */
 | 
			
		||||
#define __swap32md(x) __builtin_bswap32(x)
 | 
			
		||||
#define __swap64md(x) __builtin_bswap64(x)
 | 
			
		||||
 | 
			
		||||
/* Tell sys/endian.h we have MD variants of the swap macros.  */
 | 
			
		||||
#define MD_SWAP
 | 
			
		||||
 | 
			
		||||
#endif  /* __GNUC__ */
 | 
			
		||||
 | 
			
		||||
#if defined(__AARCH64EB__)
 | 
			
		||||
#define _BYTE_ORDER _BIG_ENDIAN
 | 
			
		||||
#else
 | 
			
		||||
#define _BYTE_ORDER _LITTLE_ENDIAN
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* _AARCH64_ENDIAN_H_ */
 | 
			
		||||
							
								
								
									
										50
									
								
								libc/arch-arm64/include/machine/exec.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								libc/arch-arm64/include/machine/exec.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,50 @@
 | 
			
		||||
/*	$OpenBSD: exec.h,v 1.9 2003/04/17 03:42:14 drahn Exp $	*/
 | 
			
		||||
/*	$NetBSD: exec.h,v 1.6 1994/10/27 04:16:05 cgd Exp $	*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 1993 Christopher G. Demetriou
 | 
			
		||||
 * 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 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _AARCH64_EXEC_H_
 | 
			
		||||
#define _AARCH64_EXEC_H_
 | 
			
		||||
 | 
			
		||||
#define	__LDPGSZ		4096
 | 
			
		||||
 | 
			
		||||
#define	NATIVE_EXEC_ELF
 | 
			
		||||
 | 
			
		||||
#define	ARCH_ELFSIZE		64
 | 
			
		||||
 | 
			
		||||
#define	ELF_TARG_CLASS		ELFCLASS64		/* 64-bit objects */
 | 
			
		||||
#define	ELF_TARG_DATA		ELFDATA2LSB
 | 
			
		||||
#define	ELF_TARG_MACH		EM_AARCH64
 | 
			
		||||
 | 
			
		||||
#define	_NLIST_DO_AOUT
 | 
			
		||||
#define	_NLIST_DO_ELF
 | 
			
		||||
 | 
			
		||||
#define	_KERN_DO_AOUT
 | 
			
		||||
#define	_KERN_DO_ELF64
 | 
			
		||||
 | 
			
		||||
#endif  /* _AARCH64_EXEC_H_ */
 | 
			
		||||
@@ -26,5 +26,48 @@
 | 
			
		||||
 * SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* _JBLEN is the size of a jmp_buf in longs (64bit on AArch64) */
 | 
			
		||||
/*
 | 
			
		||||
 * machine/setjmp.h: machine dependent setjmp-related information.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* _JBLEN is the size of a jmp_buf in longs(64bit on AArch64) */
 | 
			
		||||
#define _JBLEN 32
 | 
			
		||||
 | 
			
		||||
/* According to AARCH64 PCS document we need to save the following
 | 
			
		||||
 * registers:
 | 
			
		||||
 *
 | 
			
		||||
 * Core     x19 - x30, sp (see section 5.1.1)
 | 
			
		||||
 * VFP      d8 - d15 (see section 5.1.2)
 | 
			
		||||
 *
 | 
			
		||||
 * NOTE: All the registers saved here will have 64bit vales (except FPSR).
 | 
			
		||||
 *       AAPCS mandates that the higher part of q registers does not need to
 | 
			
		||||
 *       be saveved by the callee.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* The structure of jmp_buf for AArch64:
 | 
			
		||||
 *
 | 
			
		||||
 * NOTE: _JBLEN is the size of jmp_buf in longs(64bit on AArch64)! The table
 | 
			
		||||
 *      below computes the offsets in words(32bit).
 | 
			
		||||
 *
 | 
			
		||||
 *  word        name            description
 | 
			
		||||
 *  0       magic           magic number
 | 
			
		||||
 *  1       sigmask         signal mask (not used with _setjmp / _longjmp)
 | 
			
		||||
 *  2       core_base       base of core registers (x19-x30, sp)
 | 
			
		||||
 *  28      float_base      base of float registers (d8-d15)
 | 
			
		||||
 *  44      reserved        reserved entries (room to grow)
 | 
			
		||||
 *  64
 | 
			
		||||
 *
 | 
			
		||||
 *
 | 
			
		||||
 *  NOTE: The instructions that load/store core/vfp registers expect 8-byte
 | 
			
		||||
 *        alignment. Contrary to the previous setjmp header for ARM we do not
 | 
			
		||||
 *        need to save status/control registers for VFP (it is not a
 | 
			
		||||
 *        requirement for setjmp).
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define _JB_MAGIC       0
 | 
			
		||||
#define _JB_SIGMASK     (_JB_MAGIC+1)
 | 
			
		||||
#define _JB_CORE_BASE   (_JB_SIGMASK+1)
 | 
			
		||||
#define _JB_FLOAT_BASE  (_JB_CORE_BASE + (31-19+1)*2)
 | 
			
		||||
 | 
			
		||||
#define _JB_MAGIC__SETJMP   0x53657200
 | 
			
		||||
#define _JB_MAGIC_SETJMP    0x53657201
 | 
			
		||||
 
 | 
			
		||||
@@ -1,15 +0,0 @@
 | 
			
		||||
/* Generated by gensyscalls.py. Do not edit. */
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(___rt_sigqueueinfo)
 | 
			
		||||
    mov     x8, __NR_rt_sigqueueinfo
 | 
			
		||||
    svc     #0
 | 
			
		||||
 | 
			
		||||
    cmn     x0, #(MAX_ERRNO + 1)
 | 
			
		||||
    cneg    x0, x0, hi
 | 
			
		||||
    b.hi    __set_errno_internal
 | 
			
		||||
 | 
			
		||||
    ret
 | 
			
		||||
END(___rt_sigqueueinfo)
 | 
			
		||||
.hidden ___rt_sigqueueinfo
 | 
			
		||||
@@ -13,4 +13,5 @@ ENTRY(_exit)
 | 
			
		||||
    ret
 | 
			
		||||
END(_exit)
 | 
			
		||||
 | 
			
		||||
ALIAS_SYMBOL(_Exit, _exit)
 | 
			
		||||
    .globl _Exit
 | 
			
		||||
    .equ _Exit, _exit
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(___clock_nanosleep)
 | 
			
		||||
ENTRY(clock_nanosleep)
 | 
			
		||||
    mov     x8, __NR_clock_nanosleep
 | 
			
		||||
    svc     #0
 | 
			
		||||
 | 
			
		||||
@@ -11,5 +11,4 @@ ENTRY(___clock_nanosleep)
 | 
			
		||||
    b.hi    __set_errno_internal
 | 
			
		||||
 | 
			
		||||
    ret
 | 
			
		||||
END(___clock_nanosleep)
 | 
			
		||||
.hidden ___clock_nanosleep
 | 
			
		||||
END(clock_nanosleep)
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(___close)
 | 
			
		||||
ENTRY(close)
 | 
			
		||||
    mov     x8, __NR_close
 | 
			
		||||
    svc     #0
 | 
			
		||||
 | 
			
		||||
@@ -11,5 +11,4 @@ ENTRY(___close)
 | 
			
		||||
    b.hi    __set_errno_internal
 | 
			
		||||
 | 
			
		||||
    ret
 | 
			
		||||
END(___close)
 | 
			
		||||
.hidden ___close
 | 
			
		||||
END(close)
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(___faccessat)
 | 
			
		||||
ENTRY(faccessat)
 | 
			
		||||
    mov     x8, __NR_faccessat
 | 
			
		||||
    svc     #0
 | 
			
		||||
 | 
			
		||||
@@ -11,5 +11,4 @@ ENTRY(___faccessat)
 | 
			
		||||
    b.hi    __set_errno_internal
 | 
			
		||||
 | 
			
		||||
    ret
 | 
			
		||||
END(___faccessat)
 | 
			
		||||
.hidden ___faccessat
 | 
			
		||||
END(faccessat)
 | 
			
		||||
@@ -13,4 +13,5 @@ ENTRY(fallocate)
 | 
			
		||||
    ret
 | 
			
		||||
END(fallocate)
 | 
			
		||||
 | 
			
		||||
ALIAS_SYMBOL(fallocate64, fallocate)
 | 
			
		||||
    .globl fallocate64
 | 
			
		||||
    .equ fallocate64, fallocate
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(___fchmod)
 | 
			
		||||
ENTRY(fchmod)
 | 
			
		||||
    mov     x8, __NR_fchmod
 | 
			
		||||
    svc     #0
 | 
			
		||||
 | 
			
		||||
@@ -11,5 +11,4 @@ ENTRY(___fchmod)
 | 
			
		||||
    b.hi    __set_errno_internal
 | 
			
		||||
 | 
			
		||||
    ret
 | 
			
		||||
END(___fchmod)
 | 
			
		||||
.hidden ___fchmod
 | 
			
		||||
END(fchmod)
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(___fchmodat)
 | 
			
		||||
ENTRY(fchmodat)
 | 
			
		||||
    mov     x8, __NR_fchmodat
 | 
			
		||||
    svc     #0
 | 
			
		||||
 | 
			
		||||
@@ -11,5 +11,4 @@ ENTRY(___fchmodat)
 | 
			
		||||
    b.hi    __set_errno_internal
 | 
			
		||||
 | 
			
		||||
    ret
 | 
			
		||||
END(___fchmodat)
 | 
			
		||||
.hidden ___fchmodat
 | 
			
		||||
END(fchmodat)
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(___fgetxattr)
 | 
			
		||||
ENTRY(fgetxattr)
 | 
			
		||||
    mov     x8, __NR_fgetxattr
 | 
			
		||||
    svc     #0
 | 
			
		||||
 | 
			
		||||
@@ -11,5 +11,4 @@ ENTRY(___fgetxattr)
 | 
			
		||||
    b.hi    __set_errno_internal
 | 
			
		||||
 | 
			
		||||
    ret
 | 
			
		||||
END(___fgetxattr)
 | 
			
		||||
.hidden ___fgetxattr
 | 
			
		||||
END(fgetxattr)
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(___fsetxattr)
 | 
			
		||||
ENTRY(fsetxattr)
 | 
			
		||||
    mov     x8, __NR_fsetxattr
 | 
			
		||||
    svc     #0
 | 
			
		||||
 | 
			
		||||
@@ -11,5 +11,4 @@ ENTRY(___fsetxattr)
 | 
			
		||||
    b.hi    __set_errno_internal
 | 
			
		||||
 | 
			
		||||
    ret
 | 
			
		||||
END(___fsetxattr)
 | 
			
		||||
.hidden ___fsetxattr
 | 
			
		||||
END(fsetxattr)
 | 
			
		||||
@@ -13,4 +13,5 @@ ENTRY(fstat64)
 | 
			
		||||
    ret
 | 
			
		||||
END(fstat64)
 | 
			
		||||
 | 
			
		||||
ALIAS_SYMBOL(fstat, fstat64)
 | 
			
		||||
    .globl fstat
 | 
			
		||||
    .equ fstat, fstat64
 | 
			
		||||
 
 | 
			
		||||
@@ -13,4 +13,5 @@ ENTRY(fstatat64)
 | 
			
		||||
    ret
 | 
			
		||||
END(fstatat64)
 | 
			
		||||
 | 
			
		||||
ALIAS_SYMBOL(fstatat, fstatat64)
 | 
			
		||||
    .globl fstatat
 | 
			
		||||
    .equ fstatat, fstatat64
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(__fstatfs)
 | 
			
		||||
ENTRY(fstatfs64)
 | 
			
		||||
    mov     x8, __NR_fstatfs
 | 
			
		||||
    svc     #0
 | 
			
		||||
 | 
			
		||||
@@ -11,5 +11,7 @@ ENTRY(__fstatfs)
 | 
			
		||||
    b.hi    __set_errno_internal
 | 
			
		||||
 | 
			
		||||
    ret
 | 
			
		||||
END(__fstatfs)
 | 
			
		||||
.hidden __fstatfs
 | 
			
		||||
END(fstatfs64)
 | 
			
		||||
 | 
			
		||||
    .globl fstatfs
 | 
			
		||||
    .equ fstatfs, fstatfs64
 | 
			
		||||
@@ -13,4 +13,5 @@ ENTRY(ftruncate)
 | 
			
		||||
    ret
 | 
			
		||||
END(ftruncate)
 | 
			
		||||
 | 
			
		||||
ALIAS_SYMBOL(ftruncate64, ftruncate)
 | 
			
		||||
    .globl ftruncate64
 | 
			
		||||
    .equ ftruncate64, ftruncate
 | 
			
		||||
 
 | 
			
		||||
@@ -13,4 +13,5 @@ ENTRY(getrlimit)
 | 
			
		||||
    ret
 | 
			
		||||
END(getrlimit)
 | 
			
		||||
 | 
			
		||||
ALIAS_SYMBOL(getrlimit64, getrlimit)
 | 
			
		||||
    .globl getrlimit64
 | 
			
		||||
    .equ getrlimit64, getrlimit
 | 
			
		||||
 
 | 
			
		||||
@@ -13,4 +13,5 @@ ENTRY(lseek)
 | 
			
		||||
    ret
 | 
			
		||||
END(lseek)
 | 
			
		||||
 | 
			
		||||
ALIAS_SYMBOL(lseek64, lseek)
 | 
			
		||||
    .globl lseek64
 | 
			
		||||
    .equ lseek64, lseek
 | 
			
		||||
 
 | 
			
		||||
@@ -13,4 +13,5 @@ ENTRY(mmap)
 | 
			
		||||
    ret
 | 
			
		||||
END(mmap)
 | 
			
		||||
 | 
			
		||||
ALIAS_SYMBOL(mmap64, mmap)
 | 
			
		||||
    .globl mmap64
 | 
			
		||||
    .equ mmap64, mmap
 | 
			
		||||
 
 | 
			
		||||
@@ -13,4 +13,5 @@ ENTRY(pread64)
 | 
			
		||||
    ret
 | 
			
		||||
END(pread64)
 | 
			
		||||
 | 
			
		||||
ALIAS_SYMBOL(pread, pread64)
 | 
			
		||||
    .globl pread
 | 
			
		||||
    .equ pread, pread64
 | 
			
		||||
 
 | 
			
		||||
@@ -13,4 +13,5 @@ ENTRY(prlimit64)
 | 
			
		||||
    ret
 | 
			
		||||
END(prlimit64)
 | 
			
		||||
 | 
			
		||||
ALIAS_SYMBOL(prlimit, prlimit64)
 | 
			
		||||
    .globl prlimit
 | 
			
		||||
    .equ prlimit, prlimit64
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +0,0 @@
 | 
			
		||||
/* Generated by gensyscalls.py. Do not edit. */
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(process_vm_readv)
 | 
			
		||||
    mov     x8, __NR_process_vm_readv
 | 
			
		||||
    svc     #0
 | 
			
		||||
 | 
			
		||||
    cmn     x0, #(MAX_ERRNO + 1)
 | 
			
		||||
    cneg    x0, x0, hi
 | 
			
		||||
    b.hi    __set_errno_internal
 | 
			
		||||
 | 
			
		||||
    ret
 | 
			
		||||
END(process_vm_readv)
 | 
			
		||||
@@ -1,14 +0,0 @@
 | 
			
		||||
/* Generated by gensyscalls.py. Do not edit. */
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(process_vm_writev)
 | 
			
		||||
    mov     x8, __NR_process_vm_writev
 | 
			
		||||
    svc     #0
 | 
			
		||||
 | 
			
		||||
    cmn     x0, #(MAX_ERRNO + 1)
 | 
			
		||||
    cneg    x0, x0, hi
 | 
			
		||||
    b.hi    __set_errno_internal
 | 
			
		||||
 | 
			
		||||
    ret
 | 
			
		||||
END(process_vm_writev)
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user