Compare commits

..

216 Commits

Author SHA1 Message Date
Elliott Hughes
a8d06766c7 Merge "[MIPS] __dso_handle.S and __dso_handle_so.S not needed." 2013-07-24 01:05:18 +00:00
Rom Lemarchand
061246b600 Merge "Restore dlmalloc mmap threshold to 64k" 2013-07-23 20:49:46 +00:00
Rom Lemarchand
d0f2a6014c Restore dlmalloc mmap threshold to 64k
Restoring DEFAULT_MMAP_THRESHOLD to 64k, the way it was before
999089181e.

This forces allocations in the 64k-256k range to be mmaped.

Change-Id: Iace55ed638edd272b3e94fa6cd2ddd349042be84
Signed-off-by: Rom Lemarchand <romlem@google.com>
2013-07-23 13:48:39 -07:00
Pete Delaney
0995a7b322 [MIPS] __dso_handle.S and __dso_handle_so.S not needed.
Global hidden variable __dso_handle is now declared in:
       bionic/libc/private/__dso_handle.h

Change-Id: I8e951a8d7c65877bafc1be23a7fff6d44d3a2846
Signed-off-by: Pete Delaney  <piet.delaney@imgtec.com>
Signed-off-by: Chao-Ying Fu  <chao-ying.fu@imgtec.com>
2013-07-22 23:16:02 -07:00
Elliott Hughes
6fe4a58f84 Merge "Move stuff only needed by pthread-timers.c into pthread-timers.c." 2013-07-20 00:10:32 +00:00
Elliott Hughes
4cf1395217 Move stuff only needed by pthread-timers.c into pthread-timers.c.
Change-Id: I4915b3fff9c4f5a36b4f51027fb22019c11607b0
2013-07-19 16:42:27 -07:00
Elliott Hughes
e8bd8c2ed9 Merge "Upgrade mktemp.c to the current upstream version." 2013-07-19 23:35:29 +00:00
Elliott Hughes
284f788032 Upgrade mktemp.c to the current upstream version.
Yet another archaic relic containing bugs that had been fixed years before the
Android project even started...

Bug: 9935113
Change-Id: I3c9d019a216efd609ee568cf8c70bc360f357403
2013-07-19 15:20:31 -07:00
Elliott Hughes
f8a66bb312 Merge "Remove some non-unused makefile generality." 2013-07-18 00:39:35 +00:00
Elliott Hughes
4c6b925bac Remove some non-unused makefile generality.
MIPS uses .c files like ARM and x86 now.

Change-Id: Ie580647e385121c380316c443ec199dabf657ff8
2013-07-17 17:38:45 -07:00
Elliott Hughes
8fa9081f48 Merge "[MIPS] Rewrite MIPS crtbegin* as C files." 2013-07-18 00:34:22 +00:00
Pete Delaney
368860124c [MIPS] Rewrite MIPS crtbegin* as C files.
This updates the MIPS arch to be much more in
sync with the commit Nick Kralevich made last
June; see 9d40326830.

    Rewrite
     crtbegin.S        -> crtbegin.c
     crtbegin_so.S     -> crtbegin_so.c
     __dso_handle.S    -> __dso_handle.c
     __dso_handle_so.S -> __dso_handle_so.c
     atexit.S          -> atexit.c

Previously __do_global_dtors_aux was in the tasks
__FINI_ARRAY__ linked with crtbegin.S and it now being
removed as there is no need to call a destructor just
before terminating a process.

Shared libraries, on the other hand, are linked with
crtbegin_so.c and have a hidden destructor declared
to allow the bionic linker to call __on_dlclose().

Change-Id: Ieb4da5199b54573de05743990e309db381a11cb8
Signed-off-by: Pete Delaney  <piet.delaney@imgtec.com>
Signed-off-by: Chao-Ying Fu  <chao-ying.fu@imgtec.com>
Signed-off-by: Chris Dearman <chris.dearman@imgtec.com>
2013-07-17 14:23:29 -07:00
Elliott Hughes
2be511d405 Merge "Improve stack overflow diagnostics (take 2)." 2013-07-17 20:48:25 +00:00
Elliott Hughes
84114c8dd5 Improve stack overflow diagnostics (take 2).
This reverts commits eb1b07469f and
d14dc3b87f, and fixes the bug where
we were calling mmap (which might cause errno to be set) before
__set_tls (which is required to implement errno).

Bug: 8557703
Change-Id: I2c36d00240c56e156e1bb430d8c22a73a068b70c
2013-07-17 13:33:19 -07:00
Elliott Hughes
40e7a87864 Merge "Prevent the madvise(MADV_MERGEABLE) mmap hack from affecting errno." 2013-07-17 20:20:41 +00:00
Elliott Hughes
107cdd406b Prevent the madvise(MADV_MERGEABLE) mmap hack from affecting errno.
Bug: 9889616
Change-Id: I4a7323e0ae5aeb5cbe0da1b2bc7501d83b3a2aa4
2013-07-17 13:12:26 -07:00
Elliott Hughes
b7b36b819e Merge "mmap: Reinstate passing MADV_MERGEABLE on private anonymous maps" 2013-07-17 20:02:11 +00:00
Rom Lemarchand
e459bba398 mmap: Reinstate passing MADV_MERGEABLE on private anonymous maps
Reinstate mmap calling madvise(MADV_MERGEABLE) removed in
635df850e5

(cherry-pick of c702a904679a36511bead29c51eeac15d81f4fd2.)

Change-Id: I18803fb54701b2b3d8186dff5c678211ee3efa1f
2013-07-17 13:00:45 -07:00
Guang Zhu
2cf5a6f662 Merge "Revert "Improve stack overflow diagnostics."" 2013-07-17 03:17:19 +00:00
Guang Zhu
d14dc3b87f Revert "Improve stack overflow diagnostics."
This reverts commit aa754dca90.

Change-Id: Ifa76eee31f7f44075eb3a48554315b2693062f44
2013-07-17 03:17:05 +00:00
Guang Zhu
8c1b96681a Merge "Revert "Clean up our alternate signal stacks."" 2013-07-17 03:16:52 +00:00
Guang Zhu
eb1b07469f Revert "Clean up our alternate signal stacks."
This reverts commit 5cf87951ab.

Change-Id: Idd6ca7d80a018755da3bd315d91193723ce7f3bf
2013-07-17 03:16:04 +00:00
Christopher Ferris
f63c28f033 Merge "Fix assembler errors in generic arm strlen.c." 2013-07-17 00:19:42 +00:00
Christopher Ferris
6f4fed74cb Merge "Add new optimized strlen for arm." 2013-07-17 00:19:30 +00:00
Christopher Ferris
9ad2a73ed6 Fix assembler errors in generic arm strlen.c.
Tested using a static version of the strlen libc_test program
on a nexus7 that uses the generic code.

Merge from internal master.

(cherry-picked from d8d10a8994)

Change-Id: I88f7dc01dc5b5c3ac2d5580d92153bc1bc36c564
2013-07-16 16:47:54 -07:00
Christopher Ferris
0aa9b52efa Add new optimized strlen for arm.
This optimized version is primarily targeted at cortex-a15.

Tested on all nexus devices using the system/extras/libc_test strlen test.
Tested alignments from 1 to 32 that are powers of 2.
Tested that strlen does not cross page boundaries at all alignments.

Speed improvements listed below:

cortex-a15
- Sizes >= 32 bytes, ~75% improvement.
- Sizes >= 1024 bytes, ~250% improvement.

cortex-a9
- Sizes >= 32 bytes, ~75% improvement.
- Sizes >= 1024 bytes, ~85% improvement.

krait
- Sizes >= 32 bytes, ~95% improvement.
- Sizes >= 1024 bytes, ~160% improvement.

Merge from internal master.

(cherry-picked from 2fc0717977)

Change-Id: I1ceceb4e745fd68e9d946f96d1d42e0cdaff6ccf
2013-07-16 16:47:37 -07:00
Elliott Hughes
f35e0c149f Merge "Clean up our alternate signal stacks." 2013-07-16 22:47:41 +00:00
Elliott Hughes
5cf87951ab Clean up our alternate signal stacks.
Bug: 8557703
Change-Id: Ie93901dd1c29e9d3bf795b0f0400616d9ef08f75
2013-07-16 14:35:52 -07:00
Elliott Hughes
026867c7dc Merge "Improve stack overflow diagnostics." 2013-07-16 20:38:55 +00:00
Elliott Hughes
aa754dca90 Improve stack overflow diagnostics.
We notify debuggerd of problems by installing signal handlers. That's
fine except for when the signal is caused by us running off the end of
a thread's stack and into the guard page.

Bug: 8557703
Change-Id: I1ef65b4bb3bbca7e9a9743056177094921e60ed3
2013-07-16 13:14:24 -07:00
Elliott Hughes
9562d38df1 Merge "Clean up __builtin_expect usage." 2013-07-16 19:52:30 +00:00
Elliott Hughes
d4e753fea9 Clean up __builtin_expect usage.
Also remove some dead code; our malloc debugging doesn't use this
any more.

Change-Id: Id69cf182371f5f37d40b5bbd08f2744ade286e66
2013-07-16 12:45:46 -07:00
Elliott Hughes
f152e386fc Merge "EABI syscall cleanup." 2013-07-16 19:35:58 +00:00
Elliott Hughes
da4a3e6515 EABI syscall cleanup.
We cleaned up the auto-generated ones a while back to not touch
the stack unnecessarily if they have <= 4 arguments. This patch
cleans up some hand-crafted ones.

Also improve comments in clone.S.

Change-Id: I8850bf98f2b26829385315304472a760e6880ed8
2013-07-16 11:52:24 -07:00
Elliott Hughes
67750c8515 Merge "Fix pthread_getattr_np, pthread_attr_setguardsize, and pthread_attr_setstacksize." 2013-07-15 23:39:39 +00:00
Elliott Hughes
b95cf0d23a Fix pthread_getattr_np, pthread_attr_setguardsize, and pthread_attr_setstacksize.
pthread_getattr_np was reporting the values supplied to us, not the values we
actually used, which is kinda the whole point of pthread_getattr_np.

pthread_attr_setguardsize and pthread_attr_setstacksize were reporting EINVAL
for any size that wasn't a multiple of the system page size. This is
unnecessary. We can just round like POSIX suggests and glibc already does.

Also improve the error reporting for pthread_create failures.

Change-Id: I7ebc518628a8a1161ec72e111def911d500bba71
2013-07-15 14:51:07 -07:00
Elliott Hughes
59ed029b28 Merge "Upgrade to tzcode2013d." 2013-07-15 17:08:41 +00:00
Elliott Hughes
ce4783ce76 Upgrade to tzcode2013d.
Well, kinda... localtime.c still contains a bunch of Android-specific
hacks, as does strftime.c. But the other files are now exactly the same
as upstream.

This catches up with several years of bug fixes, and fixes most of the
compiler warnings that were in this code. (Just two remain.)

Bug: 1744909
Change-Id: I2ddfecb6fd408c847397c17afb0fff859e27feef
2013-07-12 17:52:44 -07:00
Elliott Hughes
3db1f359e9 Merge "Add a trivial gmtime(3) test." 2013-07-12 21:23:48 +00:00
Elliott Hughes
ee178bfb79 Add a trivial gmtime(3) test.
Change-Id: I849f200a455cd6971646fa45766ab22ba19fb866
2013-07-12 11:25:20 -07:00
Elliott Hughes
8a363692be Merge "Add TCP_INFO state enum values." 2013-07-11 23:58:48 +00:00
Elliott Hughes
0dff43cab4 Add TCP_INFO state enum values.
Bug: https://code.google.com/p/android/issues/detail?id=38881
Change-Id: Ie22816c666474e6441e0ec3afd2a6eb04d64a673
2013-07-11 16:21:32 -07:00
Nick Kralevich
d30877ae28 Merge "syslog.h: add __printflike to syslog functions" 2013-07-11 15:32:49 +00:00
Nick Kralevich
6b1dd1797e syslog.h: add __printflike to syslog functions
Allow the compiler to detect formating bugs.

Change-Id: I6a4af6cae59dc3adf14b075431a41885213a649a
2013-07-10 07:37:11 -07:00
Elliott Hughes
b7f4923752 Merge "Fix MIPS build." 2013-07-09 21:19:15 +00:00
Elliott Hughes
6184c1feaa Fix MIPS build.
Change-Id: I583b1794dbc12fcded8c4f57f367593a742ab33f
2013-07-09 14:18:36 -07:00
Elliott Hughes
9d476716c2 Merge "Add <sys/statvfs.h>." 2013-07-09 20:43:13 +00:00
Elliott Hughes
06040fd75c Add <sys/statvfs.h>.
Bug: 2512019
Change-Id: I6e7fd3fa281977cc4bc270481a95416b5b2dc351
2013-07-09 13:25:03 -07:00
Elliott Hughes
4fc8a0c116 Merge "Remove <netinet/icmp6.h> ni_* macros." 2013-07-08 22:08:12 +00:00
Elliott Hughes
c2cd33efc4 Remove <netinet/icmp6.h> ni_* macros.
glibc doesn't have these, and they prevent ping from building out of
the box because it assumes it can define them.

Bug: 9671560
Change-Id: I815f2a9c4fd96a0ea2952eb5a71ddf51e0763660
2013-07-08 15:07:41 -07:00
Elliott Hughes
ff145277da Merge "Upgrade to tzdata2013d." 2013-07-08 21:53:02 +00:00
Elliott Hughes
5149de09ad Upgrade to tzdata2013d.
From the release notes:

  Changes affecting future time stamps:

    Morocco's midsummer transitions this year are July 7 and August 10,
    not July 9 and August 8.  (Thanks to Andrew Paprocki.)

    Israel now falls back on the last Sunday of October.
    (Thanks to Ephraim Silverberg.)

  Changes affecting past time stamps:

    Specify Jerusalem's location more precisely; this changes the pre-1880
    times by 2 s.

  Changing affecting metadata only:

    Fix typos in the entries for country codes BQ and SX.

Change-Id: I87f992e4c406d4f254dc274f206536e9484024a2
2013-07-08 14:51:15 -07:00
Elliott Hughes
e31c45c9fa Merge "Make bionic's <netinet/icmp6.h> standalone, like glibc's." 2013-07-08 18:17:57 +00:00
Elliott Hughes
3a040d8379 Make bionic's <netinet/icmp6.h> standalone, like glibc's.
This removes the need for a bionic-specific hack in external/iproute2.

Bug: 9671560
Change-Id: I9f15be0711d26bca863bd66be9a39606500fb948
2013-07-08 11:16:24 -07:00
Elliott Hughes
6b33f31b09 Merge "Fix IPv6 filtering definitions in netinet/icmp6.h." 2013-07-08 17:32:17 +00:00
Lorenzo Colitti
bfc6a59556 Fix IPv6 filtering definitions in netinet/icmp6.h.
Linux and *BSD kernels use opposite values to indicate pass/block
in ICMPv6 filters, and assign a different value to the
ICMP6_FILTER sockopt.

Bug: 9671560
Bug: 9469682
Change-Id: Ic0f1fcd48891add992acf97632f60aebd172c1d7
2013-07-08 10:31:29 -07:00
Elliott Hughes
e63ea6aca7 Merge "Clean up <sys/mount.h>/<linux/fs.h> duplication." 2013-07-08 17:08:52 +00:00
Elliott Hughes
e42e51d563 Clean up <sys/mount.h>/<linux/fs.h> duplication.
Roll on uapi...

Bug: 6340120
Change-Id: Ic9521905683946e836574e4d768e34853ea777fa
2013-07-03 14:58:04 -07:00
Nick Kralevich
84983592ad Merge "bionic_atomic_arm.h: Remove < ARMv6 support" 2013-07-03 21:25:35 +00:00
Nick Kralevich
e91f71783b bionic_atomic_arm.h: Remove < ARMv6 support
This is dead code for most modern Android devices.

Bug: 9674955
Change-Id: Ic63a66b0331a0f07b9183f14a1d5e678c25e4b12
2013-07-03 14:14:06 -07:00
Elliott Hughes
de2781d906 Merge changes I01345c23,I3b57517c
* changes:
  Include linux/termios.h from sys/ioctl.h.
  Update linux/types.h to linux 2.6.20.
2013-07-03 20:37:28 +00:00
Lorenzo Colitti
f936ef1a9f Include linux/termios.h from sys/ioctl.h.
On NetBSD and glibc, including sys/ioctl.h provides some
terminal ioctl data structures such as struct winsize. For
compatibility, provide these via sys/ioctl.h in bionic as well.
bionic does not have its own definitions for these structures, so
get them from the Linux kernel definitions.

Change-Id: I01345c23c0bebd60b0a80fc33668e7c0ad7356c3
2013-07-03 13:35:18 -07:00
Lorenzo Colitti
d7b0d6e1e1 Update linux/types.h to linux 2.6.20.
This picks up the source kernel header change
I984154487c38f6fa827bd78234f7fc2e4e1c383f .

Bug: 9469682
Change-Id: I3b57517cc6442ba4d0b8003d7398617e8226233f
2013-07-03 13:15:20 -07:00
Elliott Hughes
ebc8ce1de6 Merge "libc/arch-arm/bionic/memcpy.a9.S: memcpy from cortex-strings." 2013-07-03 17:21:47 +00:00
Will Newton
2753e12af5 libc/arch-arm/bionic/memcpy.a9.S: memcpy from cortex-strings.
This memcpy code uses NEON/VFP to achieve very good performance
on ARMv7-A processors. It is specifically tuned for A15 but should
provide good performance on A9 also. It is equivalent to the code
in cortex-strings rev 116.

This patch is a follow up the existing gerrit change:

I7f6f77995f3ca903ad9c66d14261441667a2a935

This version includes a tweak for performance on misaligned
buffers and splits the header comment into license and
documentation sections.

Change-Id: Ibd2e23c8d8e01357ba0247be1d05192de3ceba69
Signed-off-by: Will Newton <will.newton@linaro.org>
2013-07-03 10:20:43 -07:00
Elliott Hughes
87b4286f09 Merge "Expose dn_comp and dn_expand to system C code." 2013-07-02 23:00:38 +00:00
Lorenzo Colitti
b8e435c1d5 Expose dn_comp and dn_expand to system C code.
This is needed to compile open-source code that wants to
expand/compress domain names itself, such as ping6.

Bug: 9469682
Change-Id: I339c6538936d05c031bc6fb0a8793aaf1429dea4
2013-07-02 15:57:57 -07:00
Elliott Hughes
feec97a7c7 Merge "Fix inttypes.h PRI?PTR and SCN?PTR macros." 2013-07-02 22:42:49 +00:00
Elliott Hughes
74f0833df6 Fix inttypes.h PRI?PTR and SCN?PTR macros.
Our intptr_t and uintptr_t aren't "long". Add a compilation test so we remember
to fix this to cope with 32- and 64-bit later.

Bug: http://code.google.com/p/android/issues/detail?id=57218
Change-Id: I2f816d339edb4f7d57e4418b818fb4c602093f38
2013-07-02 15:35:27 -07:00
Elliott Hughes
1ba3a2c269 Merge "Update icmp6.h to current NetBSD." 2013-07-02 16:40:42 +00:00
Lorenzo Colitti
ce7c404dc7 Update icmp6.h to current NetBSD.
This adds a few bits we need such as RFC 6106 support and the
definition of MLD_LISTENER_REDUCTION.

http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/netinet/icmp6.h?rev=1.47

Bug: 9469682
Change-Id: I97a4c2f0893012ce315334367c055097d0f8bb10
2013-07-02 09:38:59 -07:00
Christopher Ferris
7c14d67bc1 Merge "libc/arch-arm/bionic/memcpy.a9.S: memcpy from cortex-strings." 2013-07-01 17:29:07 +00:00
Nick Kralevich
413eef716f Merge "More FORTIFY_SOURCE functions under clang" 2013-07-01 16:57:05 +00:00
Will Newton
b61103dff4 libc/arch-arm/bionic/memcpy.a9.S: memcpy from cortex-strings.
This memcpy code uses NEON/VFP to achieve very good performance
on ARMv7-A processors. It is specifically tuned for A15 but should
provide good performance on A9 also. It is equivalent to the code
in cortex-strings rev 116.

This patch is a follow up the existing gerrit change:

I7f6f77995f3ca903ad9c66d14261441667a2a935

But this version includes a tweak for performance on misaligned
buffers.

Change-Id: I285abac0068f8ae29a1cbf7862ea8590aadaf0a7
Signed-off-by: Will Newton <will.newton@linaro.org>
2013-07-01 11:15:27 +01:00
Nick Kralevich
a6cde39276 More FORTIFY_SOURCE functions under clang
* bzero
* umask
* strlcat

Change-Id: I65065208e0b8b37e10f6a266d5305de8fa9e59fc
2013-06-29 08:16:22 -07:00
Nick Kralevich
227b47a461 Merge "resolv_private.h: remove #define b64_ntop and b64_pton" 2013-06-28 20:31:11 +00:00
Nick Kralevich
ca43d73d23 resolv_private.h: remove #define b64_ntop and b64_pton
This was gated off of "#ifndef ADNROID_CHANGES" (note mispelling)
and is unconditionally defined in libc/include/resolv.h
(which this file includes). No need for duplicate definitions.

Change-Id: I00719bcf39eaa26eb96ab4274f171f3d2b5bae61
2013-06-28 13:18:32 -07:00
Nick Kralevich
394df35e64 Merge "Reorganize FORTIFY_SOURCE tests." 2013-06-28 20:05:57 +00:00
Nick Kralevich
5bcf39842e Reorganize FORTIFY_SOURCE tests.
Get rid of a lot of the duplication in the various FORTIFY_SOURCE
tests. Instead, we build 4 separate static libraries, with
4 different compile time options, and link them into the final test
binary.

Change-Id: Idb0b7cccc8dd837adb037bf4ddfe8942ae138230
2013-06-28 11:54:29 -07:00
Nick Kralevich
78a7bf998d Merge "stdio.h: enable vs?printf clang FORTIFY_SOURCE" 2013-06-27 17:13:25 +00:00
Nick Kralevich
c8ae8bd941 stdio.h: enable vs?printf clang FORTIFY_SOURCE
Enable FORTIFY_SOURCE protections under clang for the following
functions:

  * vsprintf
  * vsnprintf

and add unittests.

Change-Id: I90f8a27f7b202c78b5dd8ebf53050bf9e33496f7
2013-06-27 09:17:48 -07:00
Colin Cross
fbec57d46c Merge changes Ib496e818,I074204e9
* changes:
  bionic: add compatibility mode for properties
  bionic: use the size of the file to determine property area size
2013-06-26 00:03:24 +00:00
Colin Cross
5e9a086145 bionic: add compatibility mode for properties
Allow a new bionic to work with an old init property area by supporting
the old format.

(cherry picked from commit ad76c85b9c)

Change-Id: Ib496e818a62a5834d40c71eb4745783d998be893
2013-06-25 16:52:40 -07:00
Colin Cross
1ec20a086c bionic: use the size of the file to determine property area size
On the reader size, don't assume that the property size is PA_SIZE,
read it from the size of the file.  Allows init to use a different
property size without recompiling statically linked executables.

(cherry picked from commit 285b42a04c)

Change-Id: I074204e9e6591b35faf7c1c58fb11ec162aff7bf
2013-06-25 16:52:34 -07:00
Elliott Hughes
b116bf7628 Merge "Switch to current upstream getopt_long." 2013-06-25 22:56:59 +00:00
Rom Lemarchand
995f17e6a9 Merge "libc: add swapon and swapoff syscalls" 2013-06-25 22:25:31 +00:00
Elliott Hughes
d278b828fe Switch to current upstream getopt_long.
Change-Id: I4c646dcb8be9e88dd54d069a03bbc5fbfd92de03
2013-06-25 14:56:17 -07:00
Elliott Hughes
c76550b337 Merge "Update x86 machine/endian.h from upstream" 2013-06-25 21:20:18 +00:00
Pavel Chupin
64a4f6adf7 Update x86 machine/endian.h from upstream
After download new version from upstream (OpenBSD 1.17) did the
following:
 * changed all u_int* types to uint*
 * add #include <sys/types.h>

All these changes are Android-specific and had been done before for
previous version (1.14).

Bug: http://code.google.com/p/android/issues/detail?id=54465
Change-Id: Ieb44e7fce4e794d997bb00ee0dd417fb61521720
Signed-off-by: Pavel Chupin <pavel.v.chupin@intel.com>
2013-06-25 14:17:58 -07:00
Rom Lemarchand
d206b560e7 libc: add swapon and swapoff syscalls
Change-Id: Ie79dc8e3f2ff1cd427dd6d95e3850920c4b407b0
Signed-off-by: Rom Lemarchand <romlem@google.com>
2013-06-25 13:18:03 -07:00
Elliott Hughes
7d624e9aff Merge "Kernel dso support for 'dl_iterate_phdr' function" 2013-06-25 20:15:30 +00:00
Sergey Melnikov
c45087bffa Kernel dso support for 'dl_iterate_phdr' function
Kernel provides virtual DSO for stack unwinding/exception handlind info for
signal usage case. Stack unwinding routines use 'dl_iterate_phdr' function
for additional DWARF info gathering from DSOs. Patch enables virtual DSO
enumeration via dl_iterate_phdr function.

Signed-off-by: Sergey Melnikov <sergey.melnikov@intel.com>
Change-Id: Ic2882b28f40b456a088bc1e63c50cbfda7e4a102
2013-06-25 13:12:39 -07:00
Nick Kralevich
bfacb603e4 Merge "libc: enable FORTIFY_SOURCE snprintf under clang" 2013-06-25 17:26:20 +00:00
Nick Kralevich
621b19dddb libc: enable FORTIFY_SOURCE snprintf under clang
Change-Id: I8b8059782a720104722b0841994b38f873ed02aa
2013-06-25 10:02:35 -07:00
Colin Cross
1642edb520 Merge changes Ib074192d,I6df3afed,I69070455,Icbe31908,Id3fa4526,I038d451f
* changes:
  bionic: store property names as variable-length strings
  bionic: prevent root processes from calling __system_property_add
  bionic: revert to a single (larger) property area
  bionic: reimplement property area as hybrid trie/binary tree
  bionic: add missing memory barriers to system properties
  bionic: make property area expandable
2013-06-25 00:07:53 +00:00
Greg Hackmann
836dbf65e4 bionic: store property names as variable-length strings
Names are immutable, so the fixed-sized arrays can be replaced with
variable-length ones to save memory (especially on internal tree nodes).

Signed-off-by: Greg Hackmann <ghackmann@google.com>

(cherry picked from commit 492ce95d9f)

Change-Id: Ib074192d1b71150233d78c58e9ffcf7ecf688b6b
2013-06-24 16:35:46 -07:00
Colin Cross
1d36ee1a6e bionic: prevent root processes from calling __system_property_add
If a root process other than init calls __system_property_add, which
it should never do, it will break the design assumption that there is
only one mutator.

Pass O_EXCL to open() in map_prop_region_rw to ensure that only one
process ever has the property pages open for write.

(cherry picked from commit fb9b7b436f)

Change-Id: I6df3afedbfb5d07891b095aa24b78278381a5aaf
2013-06-24 16:35:41 -07:00
Greg Hackmann
1540f601be bionic: revert to a single (larger) property area
d329697 is too complicated.  Change the multiple property pages back to
a single 128K property area that's mapped in entirely at initialization
(the memory will not get allocated until the pages are touched).

d329697 has other changes useful for testing (moving property area
initialization inside bionic and adding __system_property_set_filename)
so undo the change manually rather than with git revert.

Signed-off-by: Greg Hackmann <ghackmann@google.com>

(cherry picked from commit 5f05348c18)

Change-Id: I690704552afc07a4dd410277893ca9c40bc13e5f
2013-06-24 16:35:37 -07:00
Greg Hackmann
996cdc4b1a bionic: reimplement property area as hybrid trie/binary tree
See the comments for an explanation of how properties are stored.

The trie structure is designed to scale better than the previous
array-based implementation.  Searching an array with n properties
required average O(n) string compares of the entire key; searching the
trie requires average O(log n) string compares of each token (substrings
between '.' characters).

Signed-off-by: Greg Hackmann <ghackmann@google.com>

(cherry picked from commit 6ac8e6a46d)

Change-Id: Icbe31908572f33b4d9b85d5b62ac837cbd0f85e0
2013-06-24 16:35:32 -07:00
Greg Hackmann
f7511e3bc9 bionic: add missing memory barriers to system properties
1) Reading the value must finish before checking whether it's intact

2) Setting the serial's dirty bit must visible before modifying the
value

3) The modified value must be visible before clearing the serial's dirty
bit

4) New properties and their TOC entries must be visible before updating
the property count

Signed-off-by: Greg Hackmann <ghackmann@google.com>

(cherry picked from commit 5bfa3ee8b3)

Change-Id: Id3fa45261fc2df2ae493ab5194bc2b6bff04e966
2013-06-24 16:35:27 -07:00
Greg Hackmann
cb215a7e9e bionic: make property area expandable
The property area is initially one 4K region, automatically expanding as
needed up to 64 regions.

To avoid duplicating code, __system_property_area_init() now allocates
and initializes the first region (previously it was allocated in init's
init_property_area() and initialized in bionic).  For testing purposes,
__system_property_set_filename() may be used to override the file used
to map in regions.

Signed-off-by: Greg Hackmann <ghackmann@google.com>

(cherry picked from commit d32969701b)

Change-Id: I038d451fe8849b0c4863663eec6f57f6521bf4a7
2013-06-24 16:35:15 -07:00
Nick Kralevich
0ea1d5c0ae Merge "libc: enable sprintf FORTIFY_SOURCE under clang" 2013-06-24 22:15:12 +00:00
Nick Kralevich
c6eb985454 libc: enable sprintf FORTIFY_SOURCE under clang
clang doesn't support __builtin_va_arg_pack(), so we have
to use #define instead.

Change-Id: I2ee75e6267d60cdf997fee6b9b0547bf68f062a1
2013-06-24 14:10:29 -07:00
Nick Kralevich
53ddcc9070 Merge "linker: Emit a warning on text relocations" 2013-06-21 22:36:50 +00:00
Nick Kralevich
c9084427aa linker: Emit a warning on text relocations
Text relocations unnecessarily mark pages as dirty, preventing them
from being swapped out, wasting memory. Also, text relocations
prevent the code from running on certain hardened systems.

Print a message in logcat and stderr when we see a text relocation,
to encourage developers to fix their code.

Change-Id: I6051a7463911e090ae5727a355397d539669d5b9
2013-06-21 15:33:15 -07:00
Nick Kralevich
6819773103 Merge "libc_logging: don't keep file descriptors open forever" 2013-06-21 21:26:09 +00:00
Nick Kralevich
17fc25d20f libc_logging: don't keep file descriptors open forever
Avoid keeping unnecessary file descriptors around when they're not
needed. Libc doesn't log so much that opening / closing overhead
matters.

Change-Id: I590ec5c27562db9bac025f781c48ec9a7724ce77
2013-06-21 13:28:42 -07:00
Nick Kralevich
0ce28d20ea Merge "libc: enable FORTIFY_SOURCE clang strlcpy" 2013-06-20 19:27:48 +00:00
Nick Kralevich
8bafa7452e libc: enable FORTIFY_SOURCE clang strlcpy
Change-Id: Idcfe08f5afc3dde592416df9eba83f64e130c7c2
2013-06-20 12:17:44 -07:00
Elliott Hughes
4eed65090b Merge "stdint.h header is not fully compatible with C99(ISO9899:1999)" 2013-06-19 19:45:09 +00:00
Nick Kralevich
02ca0e3142 Merge "Fix FORTIFY_SOURCE unittests." 2013-06-19 17:33:57 +00:00
Colin Cross
3225f49848 Merge "bionic: add __system_property_foreach" 2013-06-19 17:26:17 +00:00
Nick Kralevich
3cd4cac2ce Fix FORTIFY_SOURCE unittests.
The compiler is too damn smart.

Change-Id: Ibef3ef41ec99f8cd9c06f1dbca535819f9a08197
2013-06-19 10:25:44 -07:00
Sergey Melnikov
dc5d3426d8 stdint.h header is not fully compatible with C99(ISO9899:1999)
stdint.h provides macros with incorrect type:
  * UINT8_C
  * UINT16_C
  * UINT8_MAX
  * UINT16_MAX

Signed-off-by: Sergey Melnikov <sergey.melnikov@intel.com>
Change-Id: I2d130c782d4485bf6c9e9f068de0bdaa4ba7303f
2013-06-19 12:33:31 +04:00
Greg Hackmann
c6ff844d75 bionic: add __system_property_foreach
find_nth() will be inefficient on a trie.  Since find_nth() is only used
internally and only for enumerating properties, we can add a foreach()
function to do this directly.

Signed-off-by: Greg Hackmann <ghackmann@google.com>

(cherry picked from commit 577418403d)

Change-Id: Iaca97d1182ce2c28863ba85241cbb5cf6185eb2f
2013-06-18 19:24:29 -07:00
Elliott Hughes
c656d732c7 Merge "Always use v1 for MIPS TLS access." 2013-06-18 20:56:25 +00:00
Elliott Hughes
a33dc57c7c Always use v1 for MIPS TLS access.
Change-Id: Ic2850b90185cfbc5b0eff804c8b74a1c553c0852
2013-06-18 13:26:22 -07:00
Nick Kralevich
0846109c96 Merge "libc: Rename fortify error functions." 2013-06-18 20:24:04 +00:00
Nick Kralevich
dd0880fec3 Merge "libc: add limited FORTIFY_SOURCE support for clang" 2013-06-18 20:23:49 +00:00
Elliott Hughes
6807af773f Merge "Make LD_PRELOAD failures just warnings." 2013-06-18 20:23:07 +00:00
Colin Cross
02002443d4 Merge "bionic: fix deleting property arrays in property benchmark" 2013-06-18 20:22:25 +00:00
Nick Kralevich
e2fb05b45b Merge "libc: Introduce __errordecl()" 2013-06-18 20:15:33 +00:00
Elliott Hughes
7e5a8cc523 Make LD_PRELOAD failures just warnings.
This matches glibc and makes life easier for developers who want to
sometimes preload a library from init (which has no conditionals); they
can simply move/remove the library to disable.

Change-Id: I579b8633f958235af6e46bb53b378b9e363afb1f
2013-06-18 13:15:00 -07:00
Colin Cross
7d06813d93 bionic: fix deleting property arrays in property benchmark
Use delete[] to delete arrays allocated with new []

Change-Id: Icc2a6b23df09049c008f7f1f50ed93a277174308
2013-06-18 13:08:28 -07:00
Nick Kralevich
a641c18f0c libc: Rename fortify error functions.
__umask_error -> __umask_invalid_mode
__creat_error -> __creat_missing_mode
__too_many_args_error -> __creat_too_many_args

Change-Id: I4036f344a3a93628e70f2e948ad73cfed3a967ea
2013-06-18 13:07:18 -07:00
Colin Cross
0005b3544b Merge "bionic: change properties benchmarks to read a single property" 2013-06-18 20:01:05 +00:00
Colin Cross
7d90cfa6b5 bionic: change properties benchmarks to read a single property
The properties benchmarks were reading n properties from a property
area with n properties in it, which was making it hard to compare
the time between runs of different sizes.  Change the benchmark
to read a random property per iteration so the numbers between
runs are comparable.

Change-Id: Ib1648ce0948d9038fce76d209608427376cfb8da
2013-06-18 12:55:52 -07:00
Nick Kralevich
16d1af167f libc: add limited FORTIFY_SOURCE support for clang
In 829c089f83, we disabled all
FORTIFY_SOURCE support when compiling under clang. At the time,
we didn't have proper test cases, and couldn't easily create targeted
clang tests.

This change re-enables FORTIFY_SOURCE support under clang for a
limited set of functions, where we have explicit unittests available.
The functions are:

* memcpy
* memmove
* strcpy
* strncpy
* strcat
* strncat
* memset
* strlen (with modifications)
* strchr (with modifications)
* strrchr (with modifications)

It may be possible, in the future, to enable other functions. However,
I need to write unittests first.

For strlen, strchr, and strrchr, clang unconditionally calls the
fortified version of the relevant function. If it doesn't know the
size of the buffer it's dealing with, it passes in ((size_t) -1),
which is the largest possible size_t.

I added two new clang specific unittest files, primarily copied
from fortify?_test.cpp.

I've also rebuild the entire system with these changes, and didn't
observe any obvious problems.

Change-Id: If12a15089bb0ffe93824b485290d05b14355fcaa
2013-06-18 12:14:20 -07:00
Nick Kralevich
b24c0637d0 libc: Introduce __errordecl()
Define __errordecl and replace __attribute__((__error__("foo")))
with __errordecl. Make sure __errordecl is a no-op on clang, as it
generates a compile time warning.

Change-Id: Ifa1a2d3afd6881de9d479fc2adac6737871a2949
2013-06-18 12:13:52 -07:00
Colin Cross
977a33137d Merge changes Iac00ce10,I192d3825
* changes:
  bionic: add tests for properties
  bionic: move system property writing from init to bionic
2013-06-18 01:11:58 +00:00
Colin Cross
b27e200ad6 bionic: add tests for properties
(cherry picked from commit 37d9f75dde)

Change-Id: Iac00ce10a4272032a1cbdbc4204277d6876e3365
2013-06-17 16:58:47 -07:00
Colin Cross
5cf32de7a0 bionic: move system property writing from init to bionic
Move the implementation of writing to the system property area
from init to bionic, next to the reader implementation.  This
will allow full property testing to be added to bionic tests.

Add new accessor and waiting functions to hide the implementation
from watchprops and various bionic users.

Also hide some of the implementation details of the property area
from init by moving them into _system_properties.h, and other details
from everybody by moving them into system_properties.h.

(cherry picked from commit dc1038b790)

Change-Id: I192d3825ee276c5047bc751039fe6cfe226a7cca
2013-06-17 16:58:43 -07:00
Elliott Hughes
5995bf880e Merge "don't hardcode register r0/v1 when reading the TLS" 2013-06-17 21:51:50 +00:00
Mathias Agopian
b6e340080a don't hardcode register r0/v1 when reading the TLS
this leads to much improved code when calling __get_tls()

Change-Id: I21d870fb33c33a921ca55c4e100772e0f7a8d1e4
2013-06-17 14:50:30 -07:00
Elliott Hughes
657d0da751 Merge "Slight script cleanup; make gensyscalls work from any directory." 2013-06-17 18:16:36 +00:00
Elliott Hughes
18bc975bfe Slight script cleanup; make gensyscalls work from any directory.
Also remove a ton of dead code.

Change-Id: I1315623695a004f643b155f121cbafe24b715b8a
2013-06-17 10:39:33 -07:00
Elliott Hughes
560e9f7e7a Merge "Ensure that <stdint.h> defines SIZE_MAX and friends." 2013-06-13 23:19:09 +00:00
Elliott Hughes
7c89506e3a Ensure that <stdint.h> defines SIZE_MAX and friends.
We were missing SIG_ATOMIC_MAX, SIG_ATOMIC_MIN, SIZE_MAX,
WCHAR_MAX, WCHAR_MIN, WINT_MAX, and WINT_MIN.

Change-Id: I2535f36bc220fbaea009b483599b7af811c4cb5c
2013-06-13 16:02:53 -07:00
Elliott Hughes
c843a3e7b2 Merge "Fix the qsort copyright notice (fixed upstream this afternoon)." 2013-06-13 00:44:05 +00:00
Elliott Hughes
4eeec44e29 Fix the qsort copyright notice (fixed upstream this afternoon).
Change-Id: I786feb42719bceaa7da91565e350c1333b0d301f
2013-06-12 17:42:43 -07:00
Elliott Hughes
c843d7667a Merge "Handles spurious wake-ups in pthread_join()" 2013-06-13 00:31:50 +00:00
msg555
0f020d18b1 Handles spurious wake-ups in pthread_join()
Removed 'join_count' from pthread_internal_t and switched to using the flag
PTHREAD_ATTR_FLAG_JOINED to indicate if a thread is being joined. Combined with
a switch to a while loop in pthread_join, this fixes spurious wake-ups but
prevents a thread from being joined multiple times. This is fine for
two reasons:

1) The pthread_join specification allows for undefined behavior when multiple
   threads try to join a single thread.

2) There is no thread safe way to allow multiple threads to join a single
   thread with the pthread interface.  The second thread calling pthread_join
   could be pre-empted until the thread is destroyed and its handle reused for
   a different thread.  Therefore multi-join is always an error.

Bug: https://code.google.com/p/android/issues/detail?id=52255
Change-Id: I8b6784d47620ffdcdbfb14524e7402e21d46c5f7
2013-06-12 17:30:58 -07:00
Elliott Hughes
92e841d0aa Merge "Take upstream libm changes." 2013-06-13 00:29:21 +00:00
Elliott Hughes
78419467a2 Take upstream libm changes.
Mostly workarounds for GCC and Clang bugs.

Change-Id: I4ef428a42d4ac6d622659053711a8cc416925727
2013-06-12 16:37:58 -07:00
Elliott Hughes
6a44d2271f Merge "Take some fixed upstream copyright headers and regenerate NOTICE." 2013-06-12 23:13:34 +00:00
Elliott Hughes
2815b1dd45 Take some fixed upstream copyright headers and regenerate NOTICE.
Change-Id: Ifff41d69c13322dbc6f928ce7d4c65f76fe36772
2013-06-12 16:00:41 -07:00
Elliott Hughes
55189a0fbd Merge "Switch to current upstream stdio makebuf.c and setvbuf.c." 2013-06-12 22:56:20 +00:00
Elliott Hughes
677ee56477 Switch to current upstream stdio makebuf.c and setvbuf.c.
Change-Id: I4761b5e94459815520f01062eef39abf62af621f
2013-06-12 15:24:15 -07:00
Elliott Hughes
f1867d47cb Merge "Revert "Add SIZE_MAX to <stdint.h> in a way that might actually work."" 2013-06-12 22:19:03 +00:00
Elliott Hughes
9248d3a58c Revert "Add SIZE_MAX to <stdint.h> in a way that might actually work."
This reverts commit d8627af159 which caused build breakage:

In file included from bionic/libc/include/limits.h:86:0,
                 from bionic/libc/include/stdint.h:33,
                 from bionic/libc/arch-arm/bionic/crtbegin.c:31:
bionic/libc/include/sys/limits.h:30:26: fatal error: linux/limits.h: No such file or directory
compilation terminated.
make: *** [out/target/product/generic/obj/lib/crtbegin_dynamic1.o] Error 1

Change-Id: I128095ecb99df92626e1f57e34c61e08c98a4078
2013-06-12 22:18:47 +00:00
Elliott Hughes
55c5ec64bd Merge "Add SIZE_MAX to <stdint.h> in a way that might actually work." 2013-06-12 22:05:10 +00:00
Elliott Hughes
d8627af159 Add SIZE_MAX to <stdint.h> in a way that might actually work.
Take two.

Change-Id: I7d08b6d14c82a171312a7f5898270b4441d5cfa2
2013-06-12 14:54:16 -07:00
Elliott Hughes
944ea1a320 Merge "Clean up abort." 2013-06-12 21:53:58 +00:00
Elliott Hughes
61e699a133 Clean up abort.
* A dlmalloc usage error shouldn't call abort(3) because we want to
  cause a SIGSEGV by writing the address dlmalloc didn't like to an
  address the kernel won't like, so that debuggerd will dump the
  memory around the address that upset dlmalloc.

* Switch to the simpler FreeBSD/NetBSD style of registering stdio
  cleanup. Hopefully this will let us simplify more of the stdio
  implementation.

* Clear the stdio cleanup handler before we abort because of a dlmalloc
  corruption error. This fixes the reported bug, where we'd hang inside
  dlmalloc because the stdio cleanup reentered dlmalloc.

Bug: 9301265
Change-Id: Ief31b389455d6876e5a68f0f5429567d37277dbc
2013-06-12 14:14:53 -07:00
Elliott Hughes
5cde15eb17 Merge "<stdint.h> should expose SIZE_MAX." 2013-06-12 17:56:24 +00:00
Elliott Hughes
2c157aec9b <stdint.h> should expose SIZE_MAX.
Change-Id: Id27222c24955c83f29ad953933cbdc48b6f1e900
2013-06-12 10:28:26 -07:00
Nick Kralevich
b6e880200d Merge "fix unittests." 2013-06-11 22:52:54 +00:00
Nick Kralevich
fd0325bd98 fix unittests.
7e6ce1a3c5 fixed abort() to raise
SIGABRT rather than causing SIGSEGV. However, the unittests were
not updated.

Fix unittests.

Change-Id: I73db194127b9b9e9440358aa94273863765a736b
2013-06-11 15:45:23 -07:00
Ben Cheng
fc104f899d Merge "Fix abort(3) to raise SIGABRT rather than causing SIGSEGV." 2013-06-11 00:22:14 +00:00
Ben Cheng
7e6ce1a3c5 Fix abort(3) to raise SIGABRT rather than causing SIGSEGV.
tgkill() needs the .save stack unwinding directive to get the complete
stack trace.

BUG: https://code.google.com/p/android/issues/detail?id=16672

Change-Id: Ifb447dca2147a592c48baf32769dfc175d8aea72
2013-06-10 17:17:46 -07:00
Brian Carlstrom
8252b8e4b7 Merge "Honor p_vaddr if set" 2013-06-10 22:39:07 +00:00
Elliott Hughes
2fbc9dda34 Merge "bionic/x86: Optimization for string routines" 2013-06-08 00:45:07 +00:00
Elliott Hughes
157c42997b Merge "Revert "libc x86: Remove strcat.S"" 2013-06-08 00:42:44 +00:00
Elliott Hughes
06708df6fb Revert "libc x86: Remove strcat.S"
This reverts commit 4fe461b3a6

Change-Id: Ibeb76e24f054abd7c96ad6899366c2f9bfc2a5ad
2013-06-08 00:42:35 +00:00
Christopher Ferris
9647f797d5 Merge "Implement malloc_usable_size for debug impls." 2013-06-07 22:15:33 +00:00
Christopher Ferris
885f3b9cad Implement malloc_usable_size for debug impls.
- Implemented chk_memalign.
- Fixed a few bugs in leak_memalign.
- Implemented {leak,fill,check,qemu}_malloc_usable_size.
- Make malloc_usable_size update at run time.
- Add malloc_test.cpp as a small set of tests for the
  malloc debug routines.
- Fix the qemu routines since it's been broken since it moved to C++.
- Add support for the %u format to the out_vformat in libc_logging.cpp.
  This is used by the emulator code.

Tested using the bionic-unit-tests with setprop libc.debug.malloc
set to 1, 5, and 10.

I tested as much as possible on the emulator, but tracing doesn't appear
to be working properly.

Bug: 6143477

Merge change from internal master.

(cherry-picked from commit 3d594c2580)

Change-Id: I4ae00fffba82315a8c283f35893fd554460722fb
2013-06-07 14:55:32 -07:00
Brian Carlstrom
e7dffe150b Honor p_vaddr if set
(cherry picked from commit 88ff15c2c279d2bbe3569101b36cd2aa0931a0a9)

Change-Id: I4aabbe911d30aea8ace69e29bb6e980a4e89de90
2013-06-07 12:47:58 -07:00
Elliott Hughes
b7b4f5b838 Merge "update signal.h to be C90 compatable" 2013-06-06 01:06:41 +00:00
Erik Gilling
156ccf42ff update signal.h to be C90 compatable
sigismember, sigaddset, and sigdelset had mixed code and declarations
which are not allowed in C90 and before.

Change-Id: I662af944fc1489e34bed228ce592e41f50d00e17
Signed-off-by: Erik Gilling <konkers@android.com>
2013-06-05 18:05:36 -07:00
Elliott Hughes
18af450393 Merge "Ensure header files using __BEGIN_DECLS include sys/cdefs.h." 2013-06-06 01:04:13 +00:00
Elliott Hughes
36fa67bcdd Ensure header files using __BEGIN_DECLS include sys/cdefs.h.
We keep fixing these one-by-one; let's fix them all at once.

Found thus:

  find . -name *.h | xargs grep -L sys/cdefs.h | xargs grep -l BEGIN_DECL | xargs grep -L sys/types

Change-Id: I188842aa2484dc6176e96556d57c38a0f785b59b
2013-06-05 17:58:08 -07:00
Elliott Hughes
c5bfb62433 Merge "sys/personality.h: include <sys/cdefs.h>" 2013-06-06 00:28:07 +00:00
Elliott Hughes
8d36050ac2 Merge "Clean up useless declaration in thread_private.h" 2013-06-06 00:00:40 +00:00
Kito Cheng
328223230b sys/personality.h: include <sys/cdefs.h>
Change-Id: Ia3fa558a38e0cffe5287bc454e85d5d3bdaa6ba1
2013-06-05 11:30:17 +08:00
Kito Cheng
94d0daa2dd Clean up useless declaration in thread_private.h
Change-Id: Ie7bcdc7195a3fcbcd09a95f73b0c49e8897ad50b
2013-06-05 11:26:24 +08:00
Elliott Hughes
4c001859fe Merge "Fix declaration of malloc_usable_size()" 2013-06-05 01:58:26 +00:00
Nick Kralevich
a24e81efd3 Merge "Add tests for __strcpy_chk()" 2013-06-04 19:05:33 +00:00
Nick Kralevich
13476deec4 Add tests for __strcpy_chk()
Change-Id: I5675d04fcd471732c1b87b83879a54fbcd27762e
2013-06-04 11:55:08 -07:00
Brian Carlstrom
0671393072 Merge "Small cleanup of soinfo_elf_lookup." 2013-06-04 03:18:23 +00:00
Christopher Ferris
6bec5b792a Small cleanup of soinfo_elf_lookup.
- Remove unnecessary line.
- Move declarations to first use.

Change-Id: I1d8398d6c13f7cb86bffe0b68af849e35a4b234d
2013-06-03 20:15:14 -07:00
Ben Cheng
404d491eb6 Merge "Use bl instead of blx to support interworking properly." 2013-05-31 21:40:37 +00:00
Ben Cheng
a123b5d319 Use bl instead of blx to support interworking properly.
(cherry picked from commit 9e1905794b in
master)

Change-Id: I9b8c35ea9e201e00f84315f9f105013c23c94d85
2013-05-31 14:39:23 -07:00
Nick Kralevich
8539961ff2 Merge "FORTIFY_SOURCE: strcat / strncat optimize" 2013-05-31 18:13:23 +00:00
Nick Kralevich
cf870199d5 FORTIFY_SOURCE: strcat / strncat optimize
__strcat_chk and __strncat_chk are slightly inefficient,
because they end up traversing over the same memory region
two times.

This change optimizes __strcat_chk / __strncat_chk so they
only access the memory once. Although I haven't benchmarked these
changes, it should improve the performance of these functions.

__strlen_chk - expose this function, even if -D_FORTIFY_SOURCE
isn't defined. This is needed to compile libc itself without
-D_FORTIFY_SOURCE.

Change-Id: Id2c70dff55a276b47c59db27a03734d659f84b74
2013-05-31 09:07:46 -07:00
Liubov Dmitrieva
0a490665a3 bionic/x86: Optimization for string routines
Optimized strcpy, strcat,
strncpy, strncat, strlcpy, strlcat,
memchr, memrchr, strchr, strrchr, index,
strnlen, strlen, wcslen, wmemcmp, wcscmp,
wcschr, wcsrchr, wcscpy, wcscat

Change-Id: I82b29132edf9a2e144e0bb3ee4ff5217df8d2a6d
Signed-off-by: Liubov Dmitrieva <liubov.dmitrieva@intel.com>
2013-05-31 13:37:03 +04:00
Nick Kralevich
72f59c84fd Merge "Add strncpy FORTIFY_SOURCE tests." 2013-05-30 20:33:02 +00:00
Nick Kralevich
8cc145edf4 Add strncpy FORTIFY_SOURCE tests.
Change-Id: Id108b1d72b44d7e5fb911268e80bbdf896808f60
2013-05-30 13:21:14 -07:00
Nick Kralevich
d515f46888 Merge "libc x86: Remove strcat.S" 2013-05-30 19:59:38 +00:00
Nick Kralevich
4fe461b3a6 libc x86: Remove strcat.S
This file is never used.

Change-Id: Iae4bba4a5a12a86a775af05e7477fb7b6511480b
2013-05-30 11:15:40 -07:00
Nick Kralevich
8d79fd1c94 Merge "libc x86: Remove index.S, strcpy.S, strchr.S" 2013-05-24 18:34:57 +00:00
Nick Kralevich
e4c4ada580 libc x86: Remove index.S, strcpy.S, strchr.S
These files are never used.

Change-Id: Iab8474bdff3bd4d225597c62b3c0f0849f808818
2013-05-24 10:50:05 -07:00
Nick Kralevich
2317275f85 Merge "libc: delete x86 memchr.S" 2013-05-24 17:27:47 +00:00
Nick Kralevich
615684c256 libc: delete x86 memchr.S
This file is never used.

Change-Id: Ief08ad176713b5194048852609613801969e1364
2013-05-24 08:52:04 -07:00
David 'Digit' Turner
25a87f7641 Fix declaration of malloc_usable_size()
The function should take a 'const void*' parameter, instead of 'void*'.
Note that the implementation in upstream-dlmalloc/malloc.c already does
this.

For context, see http://b.android.com/55725

Change-Id: Iefd55cdb8996699189e0545f9195972490306227
2013-05-23 10:02:02 +02:00
Brian Carlstrom
f5f29de6ae Merge "Fix bionic linker to support segments with zero p_filesz" 2013-05-21 23:59:52 +00:00
Brian Carlstrom
82dcc7910d Fix bionic linker to support segments with zero p_filesz
(cherry picked from commit 96362fb9d11beef6233aa03db396f25688e70860)

Change-Id: Ib075a6dfc45d5d0746d8b278f317dd9b8d772f2a
2013-05-21 16:57:55 -07:00
Erik Gilling
2e317075b0 Merge "libc/arm: add cortex-a8 cpu variant" 2013-05-16 19:57:28 +00:00
Rom Lemarchand
22bda4bd67 libc/arm: add cortex-a8 cpu variant
Change-Id: I30e8dd6d4b2e7889aea8f5ed21182a5941bfb489
2013-05-15 20:13:28 -07:00
Elliott Hughes
5217fb528c Merge "Fix sysconf(3) for _SC_GETGR_R_SIZE_MAX and _SC_GETPW_R_SIZE_MAX." 2013-05-15 00:56:06 +00:00
Elliott Hughes
d35106fd55 Fix sysconf(3) for _SC_GETGR_R_SIZE_MAX and _SC_GETPW_R_SIZE_MAX.
Change-Id: Ie16cb21c1a5a2bdce8502b5974e2c4dbb1d679ce
2013-05-14 17:20:34 -07:00
Elliott Hughes
6f502bc743 Merge "Add more __restricts, clean up __format__ attributes." 2013-05-14 23:45:49 +00:00
Elliott Hughes
d04c183979 Add more __restricts, clean up __format__ attributes.
Change-Id: I7e2d270cc722d339d221eaea92747eaff3b51403
2013-05-14 16:08:43 -07:00
Elliott Hughes
349ef893e8 Merge "Pull upstream FreeBSD revision 249810." 2013-05-14 23:06:34 +00:00
Elliott Hughes
b2e1abda05 Pull upstream FreeBSD revision 249810.
Fix license clause numbering.

Convert libc/stdio from K&R to ANSI C.

And add '__restrict' where it appeared in the header prototypes.

Change-Id: I5fdb22f79d3effa2298d03f9aa8412b4b087da04
Upstream: http://svnweb.freebsd.org/base?view=revision&revision=249810
2013-05-14 15:02:16 -07:00
Elliott Hughes
5b7b2809a2 Merge "epoll: add EPOLLRDHUP, EPOLLWAKEUP, and EPOLLONESHOT events" 2013-05-14 21:49:09 +00:00
Todd Poynor
b0a2fc35d6 epoll: add EPOLLRDHUP, EPOLLWAKEUP, and EPOLLONESHOT events
(cherry-pick of d1ad4f6dab06189d4d3dcfa19ae4bc301481eb3f.)

Change-Id: I4a8476bff068951533d4188de94097c8b84bc489
2013-05-14 14:48:43 -07:00
Elliott Hughes
f0f4fa3fb1 Merge "libc: add timerfd calls" 2013-05-14 21:45:29 +00:00
Todd Poynor
4200e6203a libc: add timerfd calls
(cherry-pick of 04c0ac14a49e0969333008a9522b64046d58fbdc.)

Change-Id: I06d0b6c2a8781602362b81f48faf1cca76b9ec05
2013-05-14 14:45:02 -07:00
Elliott Hughes
e1c58ab5bb Merge "libc: remove obsolete CLOCK_REALTIME_HR and CLOCK_MONOTONIC_HR" 2013-05-14 21:44:28 +00:00
Todd Poynor
5c4340b2ab libc: remove obsolete CLOCK_REALTIME_HR and CLOCK_MONOTONIC_HR
Add CLOCK_MONOTONIC_RAW, CLOCK_REALTIME_COARSE, and CLOCK_MONOTONIC_COARSE
as supported by recent linux kernels.

(cherry-pick of 60e5144ca312b210b54ac8e6966108da0c97ff80.)

Bug: 8895727
Change-Id: If79a4d05d1301108f49a37588f9416c4be19277a
2013-05-14 14:43:59 -07:00
Elliott Hughes
7cb82791ca Merge "libc: add clock ids CLOCK_REALTIME_ALARM and CLOCK_BOOTTIME_ALARM" 2013-05-14 21:43:37 +00:00
Todd Poynor
23b9fd2c1d libc: add clock ids CLOCK_REALTIME_ALARM and CLOCK_BOOTTIME_ALARM
(cherry-pick of b928bda83d4413b703329f607e2706602f15293f.)

Change-Id: Ica6aad84299819ffc5e57ae4891e057d2e401fa1
2013-05-14 14:43:09 -07:00
Elliott Hughes
d8a9cccb4d Merge "Fix all printf warnings in res_send.c." 2013-05-14 17:10:21 +00:00
Kito Cheng
bb0b09cad6 Fix all printf warnings in res_send.c.
Change-Id: I4bf959140b5a5475897bd80704e64e3c4645fc3f
2013-05-14 10:09:23 -07:00
Elliott Hughes
98f7659d7e Merge "Don't fail to run DT_INIT and DT_INIT_ARRAY constructors if a shared library has DT_PREINIT_ARRAY constructors." 2013-05-09 22:30:21 +00:00
Elliott Hughes
8147d3c284 Don't fail to run DT_INIT and DT_INIT_ARRAY constructors if a shared library has DT_PREINIT_ARRAY constructors.
The GNU dynamic linker silently ignores a DT_PREINIT_ARRAY section
in a shared library. We had ineffectual code that tried to report
an error, which I tried to fix but got wrong --- my version still
wouldn't report the error to the caller, but would prevent us from
continuing to call constructors.

Bug: 8825226
Change-Id: I4fd8450ecc44d8767a1cb808aeecfbfbfc77c070
2013-05-09 15:29:54 -07:00
251 changed files with 20641 additions and 3943 deletions

View File

@@ -6,11 +6,9 @@ include $(LOCAL_PATH)/arch-$(TARGET_ARCH)/syscalls.mk
# =========================================================
libc_common_src_files := \
$(syscall_src) \
unistd/abort.c \
unistd/alarm.c \
unistd/exec.c \
unistd/fnmatch.c \
unistd/getopt_long.c \
unistd/syslog.c \
unistd/system.c \
unistd/time.c \
@@ -27,13 +25,10 @@ libc_common_src_files := \
stdio/ftell.c \
stdio/fvwrite.c \
stdio/gets.c \
stdio/makebuf.c \
stdio/mktemp.c \
stdio/printf.c \
stdio/refill.c \
stdio/rewind.c \
stdio/scanf.c \
stdio/setvbuf.c \
stdio/snprintf.c\
stdio/sprintf.c \
stdio/sscanf.c \
@@ -63,28 +58,17 @@ libc_common_src_files := \
stdlib/strtoumax.c \
stdlib/tolower_.c \
stdlib/toupper_.c \
string/index.c \
string/strcasecmp.c \
string/strcat.c \
string/strcspn.c \
string/strdup.c \
string/strlcat.c \
string/strlcpy.c \
string/strncat.c \
string/strncpy.c \
string/strpbrk.c \
string/strrchr.c \
string/__strrchr_chk.c \
string/strsep.c \
string/strspn.c \
string/strstr.c \
string/strtok.c \
wchar/wcswidth.c \
wchar/wcsxfrm.c \
tzcode/asctime.c \
tzcode/difftime.c \
tzcode/localtime.c \
tzcode/strftime.c \
tzcode/strptime.c \
bionic/arc4random.c \
bionic/atoi.c \
bionic/atol.c \
@@ -119,11 +103,8 @@ libc_common_src_files := \
bionic/ldexp.c \
bionic/lseek64.c \
bionic/md5.c \
bionic/memchr.c \
bionic/memmem.c \
bionic/memrchr.c \
bionic/memswap.c \
bionic/mmap.c \
bionic/openat.c \
bionic/open.c \
bionic/pathconf.c \
@@ -157,11 +138,11 @@ libc_common_src_files := \
bionic/sleep.c \
bionic/statfs.c \
bionic/strndup.c \
bionic/strnlen.c \
bionic/strntoimax.c \
bionic/strntoumax.c \
bionic/strtotimeval.c \
bionic/system_properties.c \
bionic/system_properties_compat.c \
bionic/tcgetpgrp.c \
bionic/tcsetpgrp.c \
bionic/thread_atexit.c \
@@ -201,6 +182,7 @@ libc_common_src_files := \
netbsd/nameser/ns_samedomain.c \
libc_bionic_src_files := \
bionic/abort.cpp \
bionic/assert.cpp \
bionic/brk.cpp \
bionic/dirent.cpp \
@@ -216,6 +198,7 @@ libc_bionic_src_files := \
bionic/__memcpy_chk.cpp \
bionic/__memmove_chk.cpp \
bionic/__memset_chk.cpp \
bionic/mmap.cpp \
bionic/pthread_attr.cpp \
bionic/pthread_detach.cpp \
bionic/pthread_equal.cpp \
@@ -236,8 +219,9 @@ libc_bionic_src_files := \
bionic/setlocale.cpp \
bionic/signalfd.cpp \
bionic/sigwait.cpp \
bionic/statvfs.cpp \
bionic/__strcat_chk.cpp \
bionic/strchr.cpp \
bionic/__strchr_chk.cpp \
bionic/__strcpy_chk.cpp \
bionic/strerror.cpp \
bionic/strerror_r.cpp \
@@ -257,6 +241,13 @@ libc_bionic_src_files := \
bionic/wait.cpp \
bionic/wchar.cpp \
libc_tzcode_src_files := \
tzcode/asctime.c \
tzcode/difftime.c \
tzcode/localtime.c \
tzcode/strftime.c \
tzcode/strptime.c \
libc_upstream_freebsd_src_files := \
upstream-freebsd/lib/libc/stdio/clrerr.c \
upstream-freebsd/lib/libc/stdio/fclose.c \
@@ -277,6 +268,8 @@ libc_upstream_freebsd_src_files := \
upstream-freebsd/lib/libc/stdio/fwrite.c \
upstream-freebsd/lib/libc/stdio/getc.c \
upstream-freebsd/lib/libc/stdio/getchar.c \
upstream-freebsd/lib/libc/stdio/makebuf.c \
upstream-freebsd/lib/libc/stdio/mktemp.c \
upstream-freebsd/lib/libc/stdio/putc.c \
upstream-freebsd/lib/libc/stdio/putchar.c \
upstream-freebsd/lib/libc/stdio/puts.c \
@@ -285,35 +278,30 @@ libc_upstream_freebsd_src_files := \
upstream-freebsd/lib/libc/stdio/rget.c \
upstream-freebsd/lib/libc/stdio/setbuf.c \
upstream-freebsd/lib/libc/stdio/setbuffer.c \
upstream-freebsd/lib/libc/stdio/setvbuf.c \
upstream-freebsd/lib/libc/stdio/tempnam.c \
upstream-freebsd/lib/libc/stdio/tmpnam.c \
upstream-freebsd/lib/libc/stdio/wsetup.c \
upstream-freebsd/lib/libc/stdlib/getopt_long.c \
upstream-freebsd/lib/libc/stdlib/qsort.c \
upstream-freebsd/lib/libc/stdlib/realpath.c \
upstream-freebsd/lib/libc/string/wcpcpy.c \
upstream-freebsd/lib/libc/string/wcpncpy.c \
upstream-freebsd/lib/libc/string/wcscasecmp.c \
upstream-freebsd/lib/libc/string/wcscat.c \
upstream-freebsd/lib/libc/string/wcschr.c \
upstream-freebsd/lib/libc/string/wcscmp.c \
upstream-freebsd/lib/libc/string/wcscpy.c \
upstream-freebsd/lib/libc/string/wcscspn.c \
upstream-freebsd/lib/libc/string/wcsdup.c \
upstream-freebsd/lib/libc/string/wcslcat.c \
upstream-freebsd/lib/libc/string/wcslcpy.c \
upstream-freebsd/lib/libc/string/wcslen.c \
upstream-freebsd/lib/libc/string/wcsncasecmp.c \
upstream-freebsd/lib/libc/string/wcsncat.c \
upstream-freebsd/lib/libc/string/wcsncmp.c \
upstream-freebsd/lib/libc/string/wcsncpy.c \
upstream-freebsd/lib/libc/string/wcsnlen.c \
upstream-freebsd/lib/libc/string/wcspbrk.c \
upstream-freebsd/lib/libc/string/wcsrchr.c \
upstream-freebsd/lib/libc/string/wcsspn.c \
upstream-freebsd/lib/libc/string/wcsstr.c \
upstream-freebsd/lib/libc/string/wcstok.c \
upstream-freebsd/lib/libc/string/wmemchr.c \
upstream-freebsd/lib/libc/string/wmemcmp.c \
upstream-freebsd/lib/libc/string/wmemcpy.c \
upstream-freebsd/lib/libc/string/wmemmove.c \
upstream-freebsd/lib/libc/string/wmemset.c \
@@ -369,6 +357,24 @@ libc_common_src_files += \
bionic/memmove.c.arm \
string/bcopy.c \
string/strncmp.c \
string/strcat.c \
string/strncat.c \
string/strncpy.c \
bionic/strchr.cpp \
string/strrchr.c \
bionic/memchr.c \
bionic/memrchr.c \
string/index.c \
bionic/strnlen.c \
string/strlcat.c \
string/strlcpy.c \
upstream-freebsd/lib/libc/string/wcschr.c \
upstream-freebsd/lib/libc/string/wcsrchr.c \
upstream-freebsd/lib/libc/string/wcscmp.c \
upstream-freebsd/lib/libc/string/wcscpy.c \
upstream-freebsd/lib/libc/string/wmemcmp.c \
upstream-freebsd/lib/libc/string/wcslen.c \
upstream-freebsd/lib/libc/string/wcscat.c
# These files need to be arm so that gdbserver
# can set breakpoints in them without messing
@@ -392,7 +398,6 @@ libc_common_src_files += \
bionic/pthread-rwlocks.c \
bionic/pthread-timers.c \
bionic/ptrace.c \
string/strcpy.c \
libc_static_common_src_files += \
bionic/pthread.c \
@@ -407,7 +412,25 @@ libc_common_src_files += \
string/bcopy.c \
string/strcmp.c \
string/strcpy.c \
string/strncmp.c
string/strncmp.c \
string/strcat.c \
string/strncat.c \
string/strncpy.c \
bionic/strchr.cpp \
string/strrchr.c \
bionic/memchr.c \
bionic/memrchr.c \
string/index.c \
bionic/strnlen.c \
string/strlcat.c \
string/strlcpy.c \
upstream-freebsd/lib/libc/string/wcschr.c \
upstream-freebsd/lib/libc/string/wcsrchr.c \
upstream-freebsd/lib/libc/string/wcscmp.c \
upstream-freebsd/lib/libc/string/wcscpy.c \
upstream-freebsd/lib/libc/string/wmemcmp.c \
upstream-freebsd/lib/libc/string/wcslen.c \
upstream-freebsd/lib/libc/string/wcscat.c
libc_common_src_files += \
bionic/pthread-atfork.c \
@@ -469,14 +492,6 @@ libc_common_cflags := \
-DLOG_ON_HEAP_ERROR \
-Wall -Wextra
# these macro definitions are required to implement the
# 'timezone' and 'daylight' global variables, as well as
# properly update the 'tm_gmtoff' field in 'struct tm'.
#
libc_common_cflags += \
-DTM_GMTOFF=tm_gmtoff \
-DUSG_COMPAT=1
ifeq ($(strip $(DEBUG_BIONIC_LIBC)),true)
libc_common_cflags += -DDEBUG
endif
@@ -554,23 +569,17 @@ libc_crt_target_cflags += \
# static C++ destructors are properly called on dlclose().
#
ifeq ($(TARGET_ARCH),arm)
libc_crtbegin_extension := c
libc_crt_target_so_cflags :=
endif
ifeq ($(TARGET_ARCH),mips)
libc_crtbegin_extension := S
libc_crt_target_so_cflags := -fPIC
endif
ifeq ($(TARGET_ARCH),x86)
libc_crtbegin_extension := c
libc_crt_target_so_cflags := -fPIC
endif
ifeq ($(libc_crtbegin_extension),)
$(error $(TARGET_ARCH) not supported)
endif
libc_crt_target_so_cflags += $(libc_crt_target_cflags)
libc_crt_target_crtbegin_file := $(LOCAL_PATH)/arch-$(TARGET_ARCH)/bionic/crtbegin.$(libc_crtbegin_extension)
libc_crt_target_crtbegin_so_file := $(LOCAL_PATH)/arch-$(TARGET_ARCH)/bionic/crtbegin_so.$(libc_crtbegin_extension)
libc_crt_target_crtbegin_file := $(LOCAL_PATH)/arch-$(TARGET_ARCH)/bionic/crtbegin.c
libc_crt_target_crtbegin_so_file := $(LOCAL_PATH)/arch-$(TARGET_ARCH)/bionic/crtbegin_so.c
# See the comment in crtbrand.c for the reason why we need to generate
# crtbrand.s before generating crtbrand.o.
@@ -686,6 +695,28 @@ LOCAL_SYSTEM_SHARED_LIBRARIES :=
include $(BUILD_STATIC_LIBRARY)
# ========================================================
# libc_tzcode.a - upstream 'tzcode' code
# ========================================================
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(libc_tzcode_src_files)
LOCAL_CFLAGS := \
$(libc_common_cflags) \
-std=gnu99 \
-DSTD_INSPIRED=1 \
-DTZDIR=\"/system/usr/share/zoneinfo\" \
-DTM_GMTOFF=tm_gmtoff \
-DUSG_COMPAT=1
LOCAL_C_INCLUDES := $(libc_common_c_includes)
LOCAL_MODULE := libc_tzcode
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
LOCAL_SYSTEM_SHARED_LIBRARIES :=
include $(BUILD_STATIC_LIBRARY)
# ========================================================
# libc_freebsd.a - upstream FreeBSD C library code
# ========================================================
@@ -761,7 +792,12 @@ LOCAL_CFLAGS := $(libc_common_cflags) \
LOCAL_C_INCLUDES := $(libc_common_c_includes)
LOCAL_MODULE := libc_common
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
LOCAL_WHOLE_STATIC_LIBRARIES := libbionic_ssp libc_bionic libc_freebsd libc_netbsd
LOCAL_WHOLE_STATIC_LIBRARIES := \
libbionic_ssp \
libc_bionic \
libc_freebsd \
libc_netbsd \
libc_tzcode
LOCAL_SYSTEM_SHARED_LIBRARIES :=
include $(BUILD_STATIC_LIBRARY)

View File

@@ -1673,38 +1673,6 @@ SUCH DAMAGE.
-------------------------------------------------------------------
Copyright (c) 1990, 1993
The Regents of the University of California. All rights reserved.
This code is derived from software contributed to Berkeley by
Chris Torek.
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.
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 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, 1993
The Regents of the University of California. All rights reserved.
@@ -2852,7 +2820,7 @@ are met:
2. Redistributions in binary form must reproduce the above copyright
notices, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
4. Neither the name of the University nor the names of its contributors
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.
@@ -3092,13 +3060,6 @@ are met:
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 the NetBSD
Foundation, Inc. and its contributors.
4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
@@ -3916,6 +3877,36 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-------------------------------------------------------------------
Copyright (c) 2010, 2011 Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
Neither the name of Intel Corporation nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-------------------------------------------------------------------
Copyright (c) 2010, Intel Corporation
All rights reserved.
@@ -3946,6 +3937,36 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-------------------------------------------------------------------
Copyright (c) 2011 Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
Neither the name of Intel Corporation nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-------------------------------------------------------------------
Copyright (c) 2011 The Android Open Source Project
Copyright (c) 2008 ARM Ltd
All rights reserved.
@@ -3975,6 +3996,36 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-------------------------------------------------------------------
Copyright (c) 2011, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
Neither the name of Intel Corporation nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-------------------------------------------------------------------
Copyright (c) 2011, VMware, Inc.
All rights reserved.
@@ -4058,6 +4109,38 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-------------------------------------------------------------------
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.
-------------------------------------------------------------------
Copyright (c)1999 Citrus Project,
All rights reserved.

View File

@@ -201,6 +201,8 @@ int removexattr(const char *, const char *) 1
int lremovexattr(const char *, const char *) 1
int __statfs64:statfs64(const char *, size_t, struct statfs *) 1
long unshare(unsigned long) 1
int swapon(const char *, int) 1
int swapoff(const char *) 1
# time
int pause () 1
@@ -221,6 +223,9 @@ int __timer_getoverrun:timer_getoverrun(timer_t)
int __timer_delete:timer_delete(timer_t) 1
int utimes(const char*, const struct timeval tvp[2]) 1
int utimensat(int, const char *, const struct timespec times[2], int) 1
int timerfd_create(clockid_t, int) 1
int timerfd_settime(int, int, const struct itimerspec *, struct itimerspec *) 1
int timerfd_gettime(int, struct itimerspec *) 1
# signals
int sigaction(int, const struct sigaction *, struct sigaction *) 1

View File

@@ -15,7 +15,6 @@ _LIBC_ARCH_COMMON_SRC_FILES := \
arch-arm/bionic/setjmp.S \
arch-arm/bionic/sigsetjmp.S \
arch-arm/bionic/strcpy.S \
arch-arm/bionic/strlen.c.arm \
arch-arm/bionic/syscall.S \
arch-arm/bionic/tgkill.S \
arch-arm/bionic/tkill.S \
@@ -29,7 +28,7 @@ _LIBC_ARCH_DYNAMIC_SRC_FILES := \
arch-arm/bionic/exidx_dynamic.c
ifeq ($(strip $(wildcard bionic/libc/arch-arm/$(TARGET_CPU_VARIANT)/$(TARGET_CPU_VARIANT).mk)),)
$(error "TARGET_CPU_VARIANT not set or set to an unknown value. Possible values are cortex-a9, cortex-a15, krait. Use generic for devices that do not have a CPU similar to any of the supported cpu variants.")
$(error "TARGET_CPU_VARIANT not set or set to an unknown value. Possible values are cortex-a7, cortex-a8, cortex-a9, cortex-a15, krait. Use generic for devices that do not have a CPU similar to any of the supported cpu variants.")
endif
include bionic/libc/arch-arm/$(TARGET_CPU_VARIANT)/$(TARGET_CPU_VARIANT).mk

View File

@@ -38,5 +38,5 @@
ENTRY(abort)
.save {r3, r14}
stmfd sp!, {r3, r14}
blx PIC_SYM(_C_LABEL(__libc_android_abort), PLT)
bl PIC_SYM(_C_LABEL(__libc_android_abort), PLT)
END(abort)

View File

@@ -32,33 +32,33 @@
// int __pthread_clone(void* (*fn)(void*), void* child_stack, int flags, void* arg);
ENTRY(__pthread_clone)
# Copy the args onto the new stack.
# Push 'fn' and 'arg' onto 'child_stack'.
stmdb r1!, {r0, r3}
# The sys_clone system call only takes two arguments: 'flags' and 'child_stack'.
# 'child_stack' is already in r1, but we need to move 'flags' into position.
mov r0, r2
stmfd sp!, {r4, r7}
# System call.
mov ip, r7
ldr r7, =__NR_clone
swi #0
# Child?
movs r0, r0
beq 1f
# In parent, reload saved registers then either return or set errno.
ldmfd sp!, {r4, r7}
# Parent.
mov r7, ip
cmn r0, #(MAX_ERRNO + 1)
bxls lr
neg r0, r0
b __set_errno
1: # The child.
# pick the function arg and call address off the stack and jump
# to the C __thread_entry function which does some setup and then
# calls the thread's start function
1: # Child.
# Pop 'fn' and 'arg' back off the stack and call __thread_entry.
pop {r0, r1}
# __thread_entry needs the TLS pointer
# __thread_entry also needs our stack pointer.
mov r2, sp
b __thread_entry
END(__pthread_clone)

View File

@@ -34,11 +34,10 @@
// __futex_syscall3(*ftx, op, val)
ENTRY(__futex_syscall3)
stmdb sp!, {r4, r7}
.save {r4, r7}
mov ip, r7
ldr r7, =__NR_futex
swi #0
ldmia sp!, {r4, r7}
mov r7, ip
bx lr
END(__futex_syscall3)
@@ -49,25 +48,23 @@ END(__futex_syscall4)
// __futex_wait(*ftx, val, *timespec)
ENTRY(__futex_wait)
stmdb sp!, {r4, r7}
.save {r4, r7}
mov ip, r7
mov r3, r2
mov r2, r1
mov r1, #FUTEX_WAIT
ldr r7, =__NR_futex
swi #0
ldmia sp!, {r4, r7}
mov r7, ip
bx lr
END(__futex_wait)
// __futex_wake(*ftx, counter)
ENTRY(__futex_wake)
.save {r4, r7}
stmdb sp!, {r4, r7}
mov ip, r7
mov r2, r1
mov r1, #FUTEX_WAKE
ldr r7, =__NR_futex
swi #0
ldmia sp!, {r4, r7}
mov r7, ip
bx lr
END(__futex_wake)

View 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 <machine/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)

View File

@@ -39,6 +39,7 @@
*/
ENTRY(tgkill)
.save {r4-r7, ip, lr}
stmfd sp!, {r4-r7, ip, lr}
ldr r7, =__NR_tgkill
swi #0

View File

@@ -0,0 +1,151 @@
/*
* 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.
*/
/*
* Copyright (c) 2013 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/asm.h>
.syntax unified
.thumb
.thumb_func
ENTRY(strlen)
pld [r1, #128]
mov r1, r0
rsb r3, r0, #0
ands r3, r3, #7
beq mainloop
// Align to a double word (64 bits).
ands ip, r3, #1
beq align_to_32
ldrb r2, [r1], #1
cmp r2, #0
beq update_count_and_return
align_to_32:
ands ip, r3, #2
beq align_to_64
ldrb r2, [r1], #1
cmp r2, #0
beq update_count_and_return
ldrb r2, [r1], #1
cmp r2, #0
beq update_count_and_return
align_to_64:
ands ip, r3, #4
beq mainloop
ldr r3, [r1], #4
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
bne zero_in_second_register
mainloop:
ldrd r2, r3, [r1], #8
pld [r1, #64]
sub ip, r2, #0x01010101
bic ip, ip, r2
ands ip, ip, #0x80808080
bne zero_in_first_register
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
bne zero_in_second_register
b mainloop
zero_in_first_register:
sub r1, r1, #4
zero_in_second_register:
sub r0, r1, r0
// Check for zero in byte 0.
ands r1, ip, #0x80
beq check_byte1
sub r0, r0, #4
bx lr
check_byte1:
// Check for zero in byte 1.
ands r1, ip, #0x8000
beq check_byte2
sub r0, r0, #3
bx lr
check_byte2:
// Check for zero in byte 2.
ands r1, ip, #0x800000
beq return
sub r0, r0, #2
bx lr
update_count_and_return:
sub r0, r1, r0
return:
sub r0, r0, #1
bx lr
END(strlen)

View File

@@ -1,5 +1,6 @@
$(call libc-add-cpu-variant-src,MEMCPY,arch-arm/cortex-a15/bionic/memcpy.S)
$(call libc-add-cpu-variant-src,MEMSET,arch-arm/cortex-a15/bionic/memset.S)
$(call libc-add-cpu-variant-src,STRCMP,arch-arm/cortex-a15/bionic/strcmp.S)
$(call libc-add-cpu-variant-src,STRLEN,arch-arm/cortex-a15/bionic/strlen.S)
include bionic/libc/arch-arm/generic/generic.mk

View File

@@ -0,0 +1 @@
include bionic/libc/arch-arm/cortex-a15/cortex-a15.mk

View File

@@ -1,5 +1,7 @@
$(call libc-add-cpu-variant-src,MEMCPY,arch-arm/cortex-a9/bionic/memcpy.S)
$(call libc-add-cpu-variant-src,MEMSET,arch-arm/cortex-a9/bionic/memset.S)
$(call libc-add-cpu-variant-src,STRCMP,arch-arm/cortex-a9/bionic/strcmp.S)
# Use cortex-a15 version of strlen.
$(call libc-add-cpu-variant-src,STRLEN,arch-arm/cortex-a15/bionic/strlen.S)
include bionic/libc/arch-arm/generic/generic.mk

View File

@@ -33,16 +33,16 @@ size_t strlen(const char *s)
{
__builtin_prefetch(s);
__builtin_prefetch(s+32);
union {
const char *b;
const uint32_t *w;
uintptr_t i;
} u;
// these are some scratch variables for the asm code below
uint32_t v, t;
// initialize the string length to zero
size_t l = 0;
@@ -69,42 +69,50 @@ size_t strlen(const char *s)
"sub %[t], %[v], %[mask], lsr #7\n"
"and %[t], %[t], %[mask] \n"
"bics %[t], %[t], %[v] \n"
"it eq \n"
"ldreq %[v], [%[s]], #4 \n"
#if !defined(__OPTIMIZE_SIZE__)
"bne 1f \n"
"sub %[t], %[v], %[mask], lsr #7\n"
"and %[t], %[t], %[mask] \n"
"bics %[t], %[t], %[v] \n"
"it eq \n"
"ldreq %[v], [%[s]], #4 \n"
"bne 1f \n"
"sub %[t], %[v], %[mask], lsr #7\n"
"and %[t], %[t], %[mask] \n"
"bics %[t], %[t], %[v] \n"
"it eq \n"
"ldreq %[v], [%[s]], #4 \n"
"bne 1f \n"
"sub %[t], %[v], %[mask], lsr #7\n"
"and %[t], %[t], %[mask] \n"
"bics %[t], %[t], %[v] \n"
"it eq \n"
"ldreq %[v], [%[s]], #4 \n"
"bne 1f \n"
"sub %[t], %[v], %[mask], lsr #7\n"
"and %[t], %[t], %[mask] \n"
"bics %[t], %[t], %[v] \n"
"it eq \n"
"ldreq %[v], [%[s]], #4 \n"
"bne 1f \n"
"sub %[t], %[v], %[mask], lsr #7\n"
"and %[t], %[t], %[mask] \n"
"bics %[t], %[t], %[v] \n"
"it eq \n"
"ldreq %[v], [%[s]], #4 \n"
"bne 1f \n"
"sub %[t], %[v], %[mask], lsr #7\n"
"and %[t], %[t], %[mask] \n"
"bics %[t], %[t], %[v] \n"
"it eq \n"
"ldreq %[v], [%[s]], #4 \n"
"bne 1f \n"
"sub %[t], %[v], %[mask], lsr #7\n"
"and %[t], %[t], %[mask] \n"
"bics %[t], %[t], %[v] \n"
"it eq \n"
"ldreq %[v], [%[s]], #4 \n"
#endif
"beq 0b \n"
@@ -117,13 +125,14 @@ size_t strlen(const char *s)
"beq 2f \n"
"add %[l], %[l], #1 \n"
"tst %[v], #0xFF0000 \n"
"it ne \n"
"addne %[l], %[l], #1 \n"
"2: \n"
: [l]"=&r"(l), [v]"=&r"(v), [t]"=&r"(t), [s]"=&r"(u.b)
: "%[l]"(l), "%[s]"(u.b), [mask]"r"(0x80808080UL)
: "cc"
);
done:
return l;
}

View File

@@ -1,3 +1,4 @@
$(call libc-add-cpu-variant-src,MEMCPY,arch-arm/generic/bionic/memcpy.S)
$(call libc-add-cpu-variant-src,MEMSET,arch-arm/generic/bionic/memset.S)
$(call libc-add-cpu-variant-src,STRCMP,arch-arm/generic/bionic/strcmp.S)
$(call libc-add-cpu-variant-src,STRLEN,arch-arm/generic/bionic/strlen.c)

View File

@@ -1,5 +1,7 @@
$(call libc-add-cpu-variant-src,MEMCPY,arch-arm/krait/bionic/memcpy.S)
$(call libc-add-cpu-variant-src,MEMSET,arch-arm/krait/bionic/memset.S)
$(call libc-add-cpu-variant-src,STRCMP,arch-arm/krait/bionic/strcmp.S)
# Use cortex-a15 version of strlen.
$(call libc-add-cpu-variant-src,STRLEN,arch-arm/cortex-a15/bionic/strlen.S)
include bionic/libc/arch-arm/generic/generic.mk

View File

@@ -126,6 +126,8 @@ syscall_src += arch-arm/syscalls/removexattr.S
syscall_src += arch-arm/syscalls/lremovexattr.S
syscall_src += arch-arm/syscalls/__statfs64.S
syscall_src += arch-arm/syscalls/unshare.S
syscall_src += arch-arm/syscalls/swapon.S
syscall_src += arch-arm/syscalls/swapoff.S
syscall_src += arch-arm/syscalls/pause.S
syscall_src += arch-arm/syscalls/gettimeofday.S
syscall_src += arch-arm/syscalls/settimeofday.S
@@ -144,6 +146,9 @@ syscall_src += arch-arm/syscalls/__timer_getoverrun.S
syscall_src += arch-arm/syscalls/__timer_delete.S
syscall_src += arch-arm/syscalls/utimes.S
syscall_src += arch-arm/syscalls/utimensat.S
syscall_src += arch-arm/syscalls/timerfd_create.S
syscall_src += arch-arm/syscalls/timerfd_settime.S
syscall_src += arch-arm/syscalls/timerfd_gettime.S
syscall_src += arch-arm/syscalls/sigaction.S
syscall_src += arch-arm/syscalls/sigprocmask.S
syscall_src += arch-arm/syscalls/__sigsuspend.S

View File

@@ -0,0 +1,15 @@
/* autogenerated by gensyscalls.py */
#include <asm/unistd.h>
#include <linux/err.h>
#include <machine/asm.h>
ENTRY(swapoff)
mov ip, r7
ldr r7, =__NR_swapoff
swi #0
mov r7, ip
cmn r0, #(MAX_ERRNO + 1)
bxls lr
neg r0, r0
b __set_errno
END(swapoff)

View File

@@ -0,0 +1,15 @@
/* autogenerated by gensyscalls.py */
#include <asm/unistd.h>
#include <linux/err.h>
#include <machine/asm.h>
ENTRY(swapon)
mov ip, r7
ldr r7, =__NR_swapon
swi #0
mov r7, ip
cmn r0, #(MAX_ERRNO + 1)
bxls lr
neg r0, r0
b __set_errno
END(swapon)

View File

@@ -0,0 +1,15 @@
/* autogenerated by gensyscalls.py */
#include <asm/unistd.h>
#include <linux/err.h>
#include <machine/asm.h>
ENTRY(timerfd_create)
mov ip, r7
ldr r7, =__NR_timerfd_create
swi #0
mov r7, ip
cmn r0, #(MAX_ERRNO + 1)
bxls lr
neg r0, r0
b __set_errno
END(timerfd_create)

View File

@@ -0,0 +1,15 @@
/* autogenerated by gensyscalls.py */
#include <asm/unistd.h>
#include <linux/err.h>
#include <machine/asm.h>
ENTRY(timerfd_gettime)
mov ip, r7
ldr r7, =__NR_timerfd_gettime
swi #0
mov r7, ip
cmn r0, #(MAX_ERRNO + 1)
bxls lr
neg r0, r0
b __set_errno
END(timerfd_gettime)

View File

@@ -0,0 +1,15 @@
/* autogenerated by gensyscalls.py */
#include <asm/unistd.h>
#include <linux/err.h>
#include <machine/asm.h>
ENTRY(timerfd_settime)
mov ip, r7
ldr r7, =__NR_timerfd_settime
swi #0
mov r7, ip
cmn r0, #(MAX_ERRNO + 1)
bxls lr
neg r0, r0
b __set_errno
END(timerfd_settime)

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2010 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,13 +26,11 @@
* SUCH DAMAGE.
*/
# The __dso_handle global variable is used by static
# C++ constructors and destructors in the binary.
# See http://www.codesourcery.com/public/cxx-abi/abi.html#dso-dtor
#
.data
.align 4
.hidden __dso_handle
.globl __dso_handle
__dso_handle:
.long __dso_handle
extern void *__dso_handle;
extern int __cxa_atexit(void (*func)(void *), void *arg, void *dso);
__attribute__ ((visibility ("hidden")))
int atexit(void (*func)(void))
{
return (__cxa_atexit((void (*)(void *))func, (void *)0, &__dso_handle));
}

View File

@@ -1,146 +0,0 @@
/*
* 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.
*/
.text
.align 4
.type __start,@function
.globl __start
.globl _start
# this is the small startup code that is first run when
# any executable that is statically-linked with Bionic
# runs.
#
# it's purpose is to call __libc_init with appropriate
# arguments, which are:
#
# - the address of the raw data block setup by the Linux
# kernel ELF loader
#
# - address of an "onexit" function, not used on any
# platform supported by Bionic
#
# - address of the "main" function of the program.
#
# - address of the constructor list
#
.ent __start
__start:
_start:
bal 1f
1:
.set noreorder
.cpload $ra
.set reorder
move $a0, $sp
move $a1, $0
la $a2, main
la $a3, 1f
subu $sp, 32
la $t9, __libc_init
j $t9
.end __start
1: .long __PREINIT_ARRAY__
.long __INIT_ARRAY__
.long __FINI_ARRAY__
.section .preinit_array, "aw"
.type __PREINIT_ARRAY__, @object
.globl __PREINIT_ARRAY__
__PREINIT_ARRAY__:
.long -1
.section .init_array, "aw"
.type __INIT_ARRAY__, @object
.globl __INIT_ARRAY__
__INIT_ARRAY__:
.long -1
.section .fini_array, "aw"
.type __FINI_ARRAY__, @object
.globl __FINI_ARRAY__
__FINI_ARRAY__:
.long -1
.long __do_global_dtors_aux
.abicalls
.text
.align 2
.set nomips16
.ent __do_global_dtors_aux
.type __do_global_dtors_aux, @function
__do_global_dtors_aux:
.frame $sp,32,$31 # vars= 0, regs= 1/0, args= 16, gp= 8
.mask 0x80000000,-4
.fmask 0x00000000,0
.set noreorder
.cpload $25
.set nomacro
addiu $sp,$sp,-32
sw $31,28($sp)
.cprestore 16
lw $2,%got(completed.1269)($28)
lbu $2,%lo(completed.1269)($2)
bne $2,$0,$L8
nop
$L4:
lw $2,%got(__cxa_finalize)($28)
beq $2,$0,$L6
nop
lw $2,%got(__dso_handle)($28)
lw $4,0($2)
lw $25,%call16(__cxa_finalize)($28)
.reloc 1f,R_MIPS_JALR,__cxa_finalize
1: jalr $25
nop
lw $28,16($sp)
$L6:
lw $2,%got(completed.1269)($28)
li $3,1 # 0x1
sb $3,%lo(completed.1269)($2)
$L8:
lw $31,28($sp)
addiu $sp,$sp,32
j $31
nop
.set macro
.set reorder
.end __do_global_dtors_aux
.size __do_global_dtors_aux, .-__do_global_dtors_aux
.local completed.1269
.comm completed.1269,1,1
.weak __cxa_finalize
#include "__dso_handle.S"
#include "atexit.S"

View File

@@ -0,0 +1,94 @@
/*
* 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 "../../bionic/libc_init_common.h"
#include <stddef.h>
#include <stdint.h>
__attribute__ ((section (".preinit_array")))
void (*__PREINIT_ARRAY__)(void) = (void (*)(void)) -1;
__attribute__ ((section (".init_array")))
void (*__INIT_ARRAY__)(void) = (void (*)(void)) -1;
__attribute__ ((section (".fini_array")))
void (*__FINI_ARRAY__)(void) = (void (*)(void)) -1;
__LIBC_HIDDEN__ void do_mips_start(void *raw_args) {
structors_array_t array;
array.preinit_array = &__PREINIT_ARRAY__;
array.init_array = &__INIT_ARRAY__;
array.fini_array = &__FINI_ARRAY__;
__libc_init(raw_args, NULL, &main, &array);
}
/*
* This function prepares the return address with a branch-and-link
* instruction (bal) and then uses a .cpload to compute the Global
* Offset Table (GOT) pointer ($gp). The $gp is then used to load
* the address of _do_start() into $t9 just before calling it.
* Terminating the stack with a NULL return address.
*/
__asm__ (
" .set push \n"
" \n"
" .text \n"
" .align 4 \n"
" .type __start,@function \n"
" .globl __start \n"
" .globl _start \n"
" \n"
" .ent __start \n"
"__start: \n"
" _start: \n"
" .frame $sp,32,$ra \n"
" .mask 0x80000000,-4 \n"
" \n"
" .set noreorder \n"
" bal 1f \n"
" nop \n"
"1: \n"
" .cpload $ra \n"
" .set reorder \n"
" \n"
" move $a0, $sp \n"
" addiu $sp, $sp, (-32) \n"
" sw $0, 28($sp) \n"
" la $t9, do_mips_start \n"
" jalr $t9 \n"
" \n"
"2: b 2b \n"
" .end __start \n"
" \n"
" .set pop \n"
);
#include "__dso_handle.h"
#include "atexit.h"

View File

@@ -1,94 +0,0 @@
/*
* 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.
*/
.section .init_array, "aw"
.type __INIT_ARRAY__, @object
.globl __INIT_ARRAY__
__INIT_ARRAY__:
.long -1
.section .fini_array, "aw"
.type __FINI_ARRAY__, @object
.globl __FINI_ARRAY__
__FINI_ARRAY__:
.long -1
.long __do_global_dtors_aux
.abicalls
.text
.align 2
.set nomips16
.ent __do_global_dtors_aux
.type __do_global_dtors_aux, @function
__do_global_dtors_aux:
.frame $sp,32,$31 # vars= 0, regs= 1/0, args= 16, gp= 8
.mask 0x80000000,-4
.fmask 0x00000000,0
.set noreorder
.cpload $25
.set nomacro
addiu $sp,$sp,-32
sw $31,28($sp)
.cprestore 16
lw $2,%got(completed.1269)($28)
lbu $2,%lo(completed.1269)($2)
bne $2,$0,$L8
nop
$L4:
lw $2,%got(__cxa_finalize)($28)
beq $2,$0,$L6
nop
lw $2,%got(__dso_handle)($28)
lw $4,0($2)
lw $25,%call16(__cxa_finalize)($28)
.reloc 1f,R_MIPS_JALR,__cxa_finalize
1: jalr $25
nop
lw $28,16($sp)
$L6:
lw $2,%got(completed.1269)($28)
li $3,1 # 0x1
sb $3,%lo(completed.1269)($2)
$L8:
lw $31,28($sp)
addiu $sp,$sp,32
j $31
nop
.set macro
.set reorder
.end __do_global_dtors_aux
.size __do_global_dtors_aux, .-__do_global_dtors_aux
.local completed.1269
.comm completed.1269,1,1
.weak __cxa_finalize
#include "__dso_handle_so.S"
#include "atexit.S"

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2008 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
@@ -25,19 +25,14 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
.text
.globl atexit
.hidden atexit
.type atexit, @function
.align 4
.ent atexit
atexit:
.set noreorder
.cpload $t9
.set reorder
la $t9, __cxa_atexit
move $a1, $0
la $a2, __dso_handle
j $t9
.size atexit, .-atexit
.end atexit
extern void __cxa_finalize(void *);
extern void *__dso_handle;
__attribute__((visibility("hidden"),destructor))
void __on_dlclose() {
__cxa_finalize(&__dso_handle);
}
#include "__dso_handle_so.h"
#include "atexit.h"

View File

@@ -129,6 +129,8 @@ syscall_src += arch-mips/syscalls/removexattr.S
syscall_src += arch-mips/syscalls/lremovexattr.S
syscall_src += arch-mips/syscalls/__statfs64.S
syscall_src += arch-mips/syscalls/unshare.S
syscall_src += arch-mips/syscalls/swapon.S
syscall_src += arch-mips/syscalls/swapoff.S
syscall_src += arch-mips/syscalls/pause.S
syscall_src += arch-mips/syscalls/gettimeofday.S
syscall_src += arch-mips/syscalls/settimeofday.S
@@ -147,6 +149,9 @@ syscall_src += arch-mips/syscalls/__timer_getoverrun.S
syscall_src += arch-mips/syscalls/__timer_delete.S
syscall_src += arch-mips/syscalls/utimes.S
syscall_src += arch-mips/syscalls/utimensat.S
syscall_src += arch-mips/syscalls/timerfd_create.S
syscall_src += arch-mips/syscalls/timerfd_settime.S
syscall_src += arch-mips/syscalls/timerfd_gettime.S
syscall_src += arch-mips/syscalls/sigaction.S
syscall_src += arch-mips/syscalls/sigprocmask.S
syscall_src += arch-mips/syscalls/__sigsuspend.S

View File

@@ -0,0 +1,22 @@
/* autogenerated by gensyscalls.py */
#include <asm/unistd.h>
.text
.globl swapoff
.align 4
.ent swapoff
swapoff:
.set noreorder
.cpload $t9
li $v0, __NR_swapoff
syscall
bnez $a3, 1f
move $a0, $v0
j $ra
nop
1:
la $t9,__set_errno
j $t9
nop
.set reorder
.end swapoff

View File

@@ -0,0 +1,22 @@
/* autogenerated by gensyscalls.py */
#include <asm/unistd.h>
.text
.globl swapon
.align 4
.ent swapon
swapon:
.set noreorder
.cpload $t9
li $v0, __NR_swapon
syscall
bnez $a3, 1f
move $a0, $v0
j $ra
nop
1:
la $t9,__set_errno
j $t9
nop
.set reorder
.end swapon

View File

@@ -0,0 +1,22 @@
/* autogenerated by gensyscalls.py */
#include <asm/unistd.h>
.text
.globl timerfd_create
.align 4
.ent timerfd_create
timerfd_create:
.set noreorder
.cpload $t9
li $v0, __NR_timerfd_create
syscall
bnez $a3, 1f
move $a0, $v0
j $ra
nop
1:
la $t9,__set_errno
j $t9
nop
.set reorder
.end timerfd_create

View File

@@ -0,0 +1,22 @@
/* autogenerated by gensyscalls.py */
#include <asm/unistd.h>
.text
.globl timerfd_gettime
.align 4
.ent timerfd_gettime
timerfd_gettime:
.set noreorder
.cpload $t9
li $v0, __NR_timerfd_gettime
syscall
bnez $a3, 1f
move $a0, $v0
j $ra
nop
1:
la $t9,__set_errno
j $t9
nop
.set reorder
.end timerfd_gettime

View File

@@ -0,0 +1,22 @@
/* autogenerated by gensyscalls.py */
#include <asm/unistd.h>
.text
.globl timerfd_settime
.align 4
.ent timerfd_settime
timerfd_settime:
.set noreorder
.cpload $t9
li $v0, __NR_timerfd_settime
syscall
bnez $a3, 1f
move $a0, $v0
j $ra
nop
1:
la $t9,__set_errno
j $t9
nop
.set reorder
.end timerfd_settime

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: endian.h,v 1.14 2005/12/13 00:35:23 millert Exp $ */
/* $OpenBSD: endian.h,v 1.17 2011/03/12 04:03:04 guenther Exp $ */
/*-
* Copyright (c) 1997 Niklas Hallqvist. All rights reserved.
@@ -24,38 +24,28 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _I386_ENDIAN_H_
#define _I386_ENDIAN_H_
#ifndef _MACHINE_ENDIAN_H_
#define _MACHINE_ENDIAN_H_
#ifdef __GNUC__
#if defined(_KERNEL) && !defined(I386_CPU)
#define __swap32md(x) ({ \
#define __swap32md(x) __statement({ \
uint32_t __swap32md_x = (x); \
\
__asm ("bswap %1" : "+r" (__swap32md_x)); \
__asm ("bswap %0" : "+r" (__swap32md_x)); \
__swap32md_x; \
})
#else
#define __swap32md(x) ({ \
uint32_t __swap32md_x = (x); \
\
__asm ("rorw $8, %w1; rorl $16, %1; rorw $8, %w1" : \
"+r" (__swap32md_x)); \
__swap32md_x; \
})
#endif /* _KERNEL && !I386_CPU */
#define __swap64md(x) ({ \
#define __swap64md(x) __statement({ \
uint64_t __swap64md_x = (x); \
\
(uint64_t)__swap32md(__swap64md_x >> 32) | \
(uint64_t)__swap32md(__swap64md_x & 0xffffffff) << 32; \
})
#define __swap16md(x) ({ \
#define __swap16md(x) __statement({ \
uint16_t __swap16md_x = (x); \
\
__asm ("rorw $8, %w1" : "+r" (__swap16md_x)); \
__asm ("rorw $8, %w0" : "+r" (__swap16md_x)); \
__swap16md_x; \
})
@@ -68,4 +58,4 @@
#include <sys/types.h>
#include <sys/endian.h>
#endif /* _I386_ENDIAN_H_ */
#endif /* _MACHINE_ENDIAN_H_ */

View File

@@ -1,43 +0,0 @@
/*
Copyright (c) 2010, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if defined(USE_SSE2)
# include "cache_wrapper.S"
# undef __i686
# define USE_AS_BZERO
# define sse2_memset5_atom bzero
# include "sse2-memset5-atom.S"
#else
# include "bzero.S"
#endif

View File

@@ -1,26 +0,0 @@
/* $OpenBSD: index.S,v 1.4 2005/08/07 11:30:38 espie Exp $ */
/*
* Written by J.T. Conklin <jtc@netbsd.org>.
* Public domain.
*/
#include <machine/asm.h>
#ifdef STRCHR
ENTRY(strchr)
#else
ENTRY(index)
#endif
movl 4(%esp),%eax
movb 8(%esp),%cl
.align 2,0x90
L1:
movb (%eax),%dl
cmpb %dl,%cl /* found char??? */
je L2
incl %eax
testb %dl,%dl /* null terminator??? */
jnz L1
xorl %eax,%eax
L2:
ret

View File

@@ -1,27 +0,0 @@
/* $OpenBSD: memchr.S,v 1.3 2005/08/07 11:30:38 espie Exp $ */
/*
* Written by J.T. Conklin <jtc@netbsd.org>.
* Public domain.
*/
#include <machine/asm.h>
ENTRY(memchr)
pushl %edi
movl 8(%esp),%edi /* string address */
movl 12(%esp),%eax /* set character to search for */
movl 16(%esp),%ecx /* set length of search */
testl %ecx,%ecx /* test for len == 0 */
jz L1
cld /* set search forward */
repne /* search! */
scasb
jne L1 /* scan failed, return null */
leal -1(%edi),%eax /* adjust result of scan */
popl %edi
ret
.align 2,0x90
L1: xorl %eax,%eax
popl %edi
ret
END(memchr)

View File

@@ -1,43 +0,0 @@
/*
Copyright (c) 2010, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if defined(USE_SSSE3)
# include "cache_wrapper.S"
# undef __i686
# define MEMCPY memcpy
# define USE_AS_MEMMOVE
# include "ssse3-memcpy5.S"
#else
# include "memcpy.S"
#endif

View File

@@ -1,43 +0,0 @@
/*
Copyright (c) 2010, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if defined(USE_SSSE3)
# include "cache_wrapper.S"
# undef __i686
# define MEMCPY memmove
# define USE_AS_MEMMOVE
# include "ssse3-memcpy5.S"
#else
# include "memmove.S"
#endif

View File

@@ -1,42 +0,0 @@
/*
Copyright (c) 2010, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if defined(USE_SSE2)
# include "cache_wrapper.S"
# undef __i686
# define sse2_memset5_atom memset
# include "sse2-memset5-atom.S"
#else
# include "memset.S"
#endif

View File

@@ -28,15 +28,6 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if defined(USE_SSSE3)
# define USE_AS_STRNCMP
# define ssse3_strcmp_latest strncmp
# include "ssse3-strcmp-latest.S"
#else
# include "strncmp.S"
#endif
#define USE_AS_BZERO
#define MEMSET bzero
#include "sse2-memset-atom.S"

View File

@@ -0,0 +1,32 @@
/*
Copyright (c) 2011, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#define strchr index
#include "sse2-strchr-atom.S"

View File

@@ -0,0 +1,556 @@
/*
Copyright (c) 2011, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef L
# define L(label) .L##label
#endif
#ifndef cfi_startproc
# define cfi_startproc .cfi_startproc
#endif
#ifndef cfi_endproc
# define cfi_endproc .cfi_endproc
#endif
#ifndef cfi_rel_offset
# define cfi_rel_offset(reg, off) .cfi_rel_offset reg, off
#endif
#ifndef cfi_restore
# define cfi_restore(reg) .cfi_restore reg
#endif
#ifndef cfi_adjust_cfa_offset
# define cfi_adjust_cfa_offset(off) .cfi_adjust_cfa_offset off
#endif
#ifndef ENTRY
# define ENTRY(name) \
.type name, @function; \
.globl name; \
.p2align 4; \
name: \
cfi_startproc
#endif
#ifndef END
# define END(name) \
cfi_endproc; \
.size name, .-name
#endif
#define CFI_PUSH(REG) \
cfi_adjust_cfa_offset (4); \
cfi_rel_offset (REG, 0)
#define CFI_POP(REG) \
cfi_adjust_cfa_offset (-4); \
cfi_restore (REG)
#define PUSH(REG) pushl REG; CFI_PUSH (REG)
#define POP(REG) popl REG; CFI_POP (REG)
#define ENTRANCE PUSH (%edi);
#define PARMS 8
#define RETURN POP (%edi); ret; CFI_PUSH (%edi);
#define STR1 PARMS
#define STR2 STR1+4
#define LEN STR2+4
.text
ENTRY (memchr)
ENTRANCE
mov STR1(%esp), %ecx
movd STR2(%esp), %xmm1
mov LEN(%esp), %edx
test %edx, %edx
jz L(return_null)
punpcklbw %xmm1, %xmm1
mov %ecx, %edi
punpcklbw %xmm1, %xmm1
and $63, %ecx
pshufd $0, %xmm1, %xmm1
cmp $48, %ecx
ja L(crosscache)
movdqu (%edi), %xmm0
pcmpeqb %xmm1, %xmm0
pmovmskb %xmm0, %eax
test %eax, %eax
jnz L(match_case2_prolog)
sub $16, %edx
jbe L(return_null)
lea 16(%edi), %edi
and $15, %ecx
and $-16, %edi
add %ecx, %edx
sub $64, %edx
jbe L(exit_loop)
jmp L(loop_prolog)
.p2align 4
L(crosscache):
and $15, %ecx
and $-16, %edi
movdqa (%edi), %xmm0
pcmpeqb %xmm1, %xmm0
pmovmskb %xmm0, %eax
sar %cl, %eax
test %eax, %eax
jnz L(match_case2_prolog1)
lea -16(%edx), %edx
add %ecx, %edx
jle L(return_null)
lea 16(%edi), %edi
sub $64, %edx
jbe L(exit_loop)
.p2align 4
L(loop_prolog):
movdqa (%edi), %xmm0
pcmpeqb %xmm1, %xmm0
xor %ecx, %ecx
pmovmskb %xmm0, %eax
test %eax, %eax
jnz L(match_case1)
movdqa 16(%edi), %xmm2
pcmpeqb %xmm1, %xmm2
lea 16(%ecx), %ecx
pmovmskb %xmm2, %eax
test %eax, %eax
jnz L(match_case1)
movdqa 32(%edi), %xmm3
pcmpeqb %xmm1, %xmm3
lea 16(%ecx), %ecx
pmovmskb %xmm3, %eax
test %eax, %eax
jnz L(match_case1)
movdqa 48(%edi), %xmm4
pcmpeqb %xmm1, %xmm4
lea 16(%ecx), %ecx
pmovmskb %xmm4, %eax
test %eax, %eax
jnz L(match_case1)
lea 64(%edi), %edi
sub $64, %edx
jbe L(exit_loop)
movdqa (%edi), %xmm0
pcmpeqb %xmm1, %xmm0
xor %ecx, %ecx
pmovmskb %xmm0, %eax
test %eax, %eax
jnz L(match_case1)
movdqa 16(%edi), %xmm2
pcmpeqb %xmm1, %xmm2
lea 16(%ecx), %ecx
pmovmskb %xmm2, %eax
test %eax, %eax
jnz L(match_case1)
movdqa 32(%edi), %xmm3
pcmpeqb %xmm1, %xmm3
lea 16(%ecx), %ecx
pmovmskb %xmm3, %eax
test %eax, %eax
jnz L(match_case1)
movdqa 48(%edi), %xmm4
pcmpeqb %xmm1, %xmm4
lea 16(%ecx), %ecx
pmovmskb %xmm4, %eax
test %eax, %eax
jnz L(match_case1)
lea 64(%edi), %edi
mov %edi, %ecx
and $-64, %edi
and $63, %ecx
add %ecx, %edx
.p2align 4
L(align64_loop):
sub $64, %edx
jbe L(exit_loop)
movdqa (%edi), %xmm0
movdqa 16(%edi), %xmm2
movdqa 32(%edi), %xmm3
movdqa 48(%edi), %xmm4
pcmpeqb %xmm1, %xmm0
pcmpeqb %xmm1, %xmm2
pcmpeqb %xmm1, %xmm3
pcmpeqb %xmm1, %xmm4
pmaxub %xmm0, %xmm3
pmaxub %xmm2, %xmm4
pmaxub %xmm3, %xmm4
add $64, %edi
pmovmskb %xmm4, %eax
test %eax, %eax
jz L(align64_loop)
sub $64, %edi
pmovmskb %xmm0, %eax
xor %ecx, %ecx
test %eax, %eax
jnz L(match_case1)
pmovmskb %xmm2, %eax
lea 16(%ecx), %ecx
test %eax, %eax
jnz L(match_case1)
movdqa 32(%edi), %xmm3
pcmpeqb %xmm1, %xmm3
pmovmskb %xmm3, %eax
lea 16(%ecx), %ecx
test %eax, %eax
jnz L(match_case1)
pcmpeqb 48(%edi), %xmm1
pmovmskb %xmm1, %eax
lea 16(%ecx), %ecx
.p2align 4
L(match_case1):
add %ecx, %edi
test %al, %al
jz L(match_case1_high)
mov %al, %cl
and $15, %cl
jz L(match_case1_8)
test $0x01, %al
jnz L(exit_case1_1)
test $0x02, %al
jnz L(exit_case1_2)
test $0x04, %al
jnz L(exit_case1_3)
lea 3(%edi), %eax
RETURN
.p2align 4
L(match_case1_8):
test $0x10, %al
jnz L(exit_case1_5)
test $0x20, %al
jnz L(exit_case1_6)
test $0x40, %al
jnz L(exit_case1_7)
lea 7(%edi), %eax
RETURN
.p2align 4
L(match_case1_high):
mov %ah, %ch
and $15, %ch
jz L(match_case1_high_8)
test $0x01, %ah
jnz L(exit_case1_9)
test $0x02, %ah
jnz L(exit_case1_10)
test $0x04, %ah
jnz L(exit_case1_11)
lea 11(%edi), %eax
RETURN
.p2align 4
L(match_case1_high_8):
test $0x10, %ah
jnz L(exit_case1_13)
test $0x20, %ah
jnz L(exit_case1_14)
test $0x40, %ah
jnz L(exit_case1_15)
lea 15(%edi), %eax
RETURN
.p2align 4
L(exit_loop):
add $64, %edx
movdqa (%edi), %xmm0
pcmpeqb %xmm1, %xmm0
xor %ecx, %ecx
pmovmskb %xmm0, %eax
test %eax, %eax
jnz L(match_case2)
cmp $16, %edx
jbe L(return_null)
movdqa 16(%edi), %xmm2
pcmpeqb %xmm1, %xmm2
lea 16(%ecx), %ecx
pmovmskb %xmm2, %eax
test %eax, %eax
jnz L(match_case2)
cmp $32, %edx
jbe L(return_null)
movdqa 32(%edi), %xmm3
pcmpeqb %xmm1, %xmm3
lea 16(%ecx), %ecx
pmovmskb %xmm3, %eax
test %eax, %eax
jnz L(match_case2)
cmp $48, %edx
jbe L(return_null)
pcmpeqb 48(%edi), %xmm1
lea 16(%ecx), %ecx
pmovmskb %xmm1, %eax
test %eax, %eax
jnz L(match_case2)
xor %eax, %eax
RETURN
.p2align 4
L(exit_case1_1):
mov %edi, %eax
RETURN
.p2align 4
L(exit_case1_2):
lea 1(%edi), %eax
RETURN
.p2align 4
L(exit_case1_3):
lea 2(%edi), %eax
RETURN
.p2align 4
L(exit_case1_5):
lea 4(%edi), %eax
RETURN
.p2align 4
L(exit_case1_6):
lea 5(%edi), %eax
RETURN
.p2align 4
L(exit_case1_7):
lea 6(%edi), %eax
RETURN
.p2align 4
L(exit_case1_9):
lea 8(%edi), %eax
RETURN
.p2align 4
L(exit_case1_10):
lea 9(%edi), %eax
RETURN
.p2align 4
L(exit_case1_11):
lea 10(%edi), %eax
RETURN
.p2align 4
L(exit_case1_13):
lea 12(%edi), %eax
RETURN
.p2align 4
L(exit_case1_14):
lea 13(%edi), %eax
RETURN
.p2align 4
L(exit_case1_15):
lea 14(%edi), %eax
RETURN
.p2align 4
L(match_case2):
sub %ecx, %edx
L(match_case2_prolog1):
add %ecx, %edi
L(match_case2_prolog):
test %al, %al
jz L(match_case2_high)
mov %al, %cl
and $15, %cl
jz L(match_case2_8)
test $0x01, %al
jnz L(exit_case2_1)
test $0x02, %al
jnz L(exit_case2_2)
test $0x04, %al
jnz L(exit_case2_3)
sub $4, %edx
jb L(return_null)
lea 3(%edi), %eax
RETURN
.p2align 4
L(match_case2_8):
test $0x10, %al
jnz L(exit_case2_5)
test $0x20, %al
jnz L(exit_case2_6)
test $0x40, %al
jnz L(exit_case2_7)
sub $8, %edx
jb L(return_null)
lea 7(%edi), %eax
RETURN
.p2align 4
L(match_case2_high):
mov %ah, %ch
and $15, %ch
jz L(match_case2_high_8)
test $0x01, %ah
jnz L(exit_case2_9)
test $0x02, %ah
jnz L(exit_case2_10)
test $0x04, %ah
jnz L(exit_case2_11)
sub $12, %edx
jb L(return_null)
lea 11(%edi), %eax
RETURN
.p2align 4
L(match_case2_high_8):
test $0x10, %ah
jnz L(exit_case2_13)
test $0x20, %ah
jnz L(exit_case2_14)
test $0x40, %ah
jnz L(exit_case2_15)
sub $16, %edx
jb L(return_null)
lea 15(%edi), %eax
RETURN
.p2align 4
L(exit_case2_1):
mov %edi, %eax
RETURN
.p2align 4
L(exit_case2_2):
sub $2, %edx
jb L(return_null)
lea 1(%edi), %eax
RETURN
.p2align 4
L(exit_case2_3):
sub $3, %edx
jb L(return_null)
lea 2(%edi), %eax
RETURN
.p2align 4
L(exit_case2_5):
sub $5, %edx
jb L(return_null)
lea 4(%edi), %eax
RETURN
.p2align 4
L(exit_case2_6):
sub $6, %edx
jb L(return_null)
lea 5(%edi), %eax
RETURN
.p2align 4
L(exit_case2_7):
sub $7, %edx
jb L(return_null)
lea 6(%edi), %eax
RETURN
.p2align 4
L(exit_case2_9):
sub $9, %edx
jb L(return_null)
lea 8(%edi), %eax
RETURN
.p2align 4
L(exit_case2_10):
sub $10, %edx
jb L(return_null)
lea 9(%edi), %eax
RETURN
.p2align 4
L(exit_case2_11):
sub $11, %edx
jb L(return_null)
lea 10(%edi), %eax
RETURN
.p2align 4
L(exit_case2_13):
sub $13, %edx
jb L(return_null)
lea 12(%edi), %eax
RETURN
.p2align 4
L(exit_case2_14):
sub $14, %edx
jb L(return_null)
lea 13(%edi), %eax
RETURN
.p2align 4
L(exit_case2_15):
sub $15, %edx
jb L(return_null)
lea 14(%edi), %eax
RETURN
.p2align 4
L(return_null):
xor %eax, %eax
RETURN
END (memchr)

View File

@@ -0,0 +1,778 @@
/*
Copyright (c) 2011, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef L
# define L(label) .L##label
#endif
#ifndef cfi_startproc
# define cfi_startproc .cfi_startproc
#endif
#ifndef cfi_endproc
# define cfi_endproc .cfi_endproc
#endif
#ifndef cfi_rel_offset
# define cfi_rel_offset(reg, off) .cfi_rel_offset reg, off
#endif
#ifndef cfi_restore
# define cfi_restore(reg) .cfi_restore reg
#endif
#ifndef cfi_adjust_cfa_offset
# define cfi_adjust_cfa_offset(off) .cfi_adjust_cfa_offset off
#endif
#ifndef ENTRY
# define ENTRY(name) \
.type name, @function; \
.globl name; \
.p2align 4; \
name: \
cfi_startproc
#endif
#ifndef END
# define END(name) \
cfi_endproc; \
.size name, .-name
#endif
#define CFI_PUSH(REG) \
cfi_adjust_cfa_offset (4); \
cfi_rel_offset (REG, 0)
#define CFI_POP(REG) \
cfi_adjust_cfa_offset (-4); \
cfi_restore (REG)
#define PUSH(REG) pushl REG; CFI_PUSH (REG)
#define POP(REG) popl REG; CFI_POP (REG)
#define PARMS 4
#define STR1 PARMS
#define STR2 STR1+4
#define LEN STR2+4
.text
ENTRY (memrchr)
mov STR1(%esp), %ecx
movd STR2(%esp), %xmm1
mov LEN(%esp), %edx
test %edx, %edx
jz L(return_null)
sub $16, %edx
jbe L(length_less16)
punpcklbw %xmm1, %xmm1
add %edx, %ecx
punpcklbw %xmm1, %xmm1
movdqu (%ecx), %xmm0
pshufd $0, %xmm1, %xmm1
pcmpeqb %xmm1, %xmm0
pmovmskb %xmm0, %eax
test %eax, %eax
jnz L(exit_dispatch)
sub $64, %ecx
mov %ecx, %eax
and $15, %eax
jz L(loop_prolog)
add $16, %ecx
add $16, %edx
and $-16, %ecx
sub %eax, %edx
.p2align 4
/* Loop start on aligned string. */
L(loop_prolog):
sub $64, %edx
jbe L(exit_loop)
movdqa 48(%ecx), %xmm0
pcmpeqb %xmm1, %xmm0
pmovmskb %xmm0, %eax
test %eax, %eax
jnz L(matches48)
movdqa 32(%ecx), %xmm2
pcmpeqb %xmm1, %xmm2
pmovmskb %xmm2, %eax
test %eax, %eax
jnz L(matches32)
movdqa 16(%ecx), %xmm3
pcmpeqb %xmm1, %xmm3
pmovmskb %xmm3, %eax
test %eax, %eax
jnz L(matches16)
movdqa (%ecx), %xmm4
pcmpeqb %xmm1, %xmm4
pmovmskb %xmm4, %eax
test %eax, %eax
jnz L(exit_dispatch)
sub $64, %ecx
sub $64, %edx
jbe L(exit_loop)
movdqa 48(%ecx), %xmm0
pcmpeqb %xmm1, %xmm0
pmovmskb %xmm0, %eax
test %eax, %eax
jnz L(matches48)
movdqa 32(%ecx), %xmm2
pcmpeqb %xmm1, %xmm2
pmovmskb %xmm2, %eax
test %eax, %eax
jnz L(matches32)
movdqa 16(%ecx), %xmm3
pcmpeqb %xmm1, %xmm3
pmovmskb %xmm3, %eax
test %eax, %eax
jnz L(matches16)
movdqa (%ecx), %xmm3
pcmpeqb %xmm1, %xmm3
pmovmskb %xmm3, %eax
test %eax, %eax
jnz L(exit_dispatch)
mov %ecx, %eax
and $63, %eax
test %eax, %eax
jz L(align64_loop)
add $64, %ecx
add $64, %edx
and $-64, %ecx
sub %eax, %edx
.p2align 4
L(align64_loop):
sub $64, %ecx
sub $64, %edx
jbe L(exit_loop)
movdqa (%ecx), %xmm0
movdqa 16(%ecx), %xmm2
movdqa 32(%ecx), %xmm3
movdqa 48(%ecx), %xmm4
pcmpeqb %xmm1, %xmm0
pcmpeqb %xmm1, %xmm2
pcmpeqb %xmm1, %xmm3
pcmpeqb %xmm1, %xmm4
pmaxub %xmm3, %xmm0
pmaxub %xmm4, %xmm2
pmaxub %xmm0, %xmm2
pmovmskb %xmm2, %eax
test %eax, %eax
jz L(align64_loop)
pmovmskb %xmm4, %eax
test %eax, %eax
jnz L(matches48)
pmovmskb %xmm3, %eax
test %eax, %eax
jnz L(matches32)
movdqa 16(%ecx), %xmm2
pcmpeqb %xmm1, %xmm2
pcmpeqb (%ecx), %xmm1
pmovmskb %xmm2, %eax
test %eax, %eax
jnz L(matches16)
pmovmskb %xmm1, %eax
test %ah, %ah
jnz L(exit_dispatch_high)
mov %al, %dl
and $15 << 4, %dl
jnz L(exit_dispatch_8)
test $0x08, %al
jnz L(exit_4)
test $0x04, %al
jnz L(exit_3)
test $0x02, %al
jnz L(exit_2)
mov %ecx, %eax
ret
.p2align 4
L(exit_loop):
add $64, %edx
cmp $32, %edx
jbe L(exit_loop_32)
movdqa 48(%ecx), %xmm0
pcmpeqb %xmm1, %xmm0
pmovmskb %xmm0, %eax
test %eax, %eax
jnz L(matches48)
movdqa 32(%ecx), %xmm2
pcmpeqb %xmm1, %xmm2
pmovmskb %xmm2, %eax
test %eax, %eax
jnz L(matches32)
movdqa 16(%ecx), %xmm3
pcmpeqb %xmm1, %xmm3
pmovmskb %xmm3, %eax
test %eax, %eax
jnz L(matches16_1)
cmp $48, %edx
jbe L(return_null)
pcmpeqb (%ecx), %xmm1
pmovmskb %xmm1, %eax
test %eax, %eax
jnz L(matches0_1)
xor %eax, %eax
ret
.p2align 4
L(exit_loop_32):
movdqa 48(%ecx), %xmm0
pcmpeqb %xmm1, %xmm0
pmovmskb %xmm0, %eax
test %eax, %eax
jnz L(matches48_1)
cmp $16, %edx
jbe L(return_null)
pcmpeqb 32(%ecx), %xmm1
pmovmskb %xmm1, %eax
test %eax, %eax
jnz L(matches32_1)
xor %eax, %eax
ret
.p2align 4
L(matches16):
lea 16(%ecx), %ecx
test %ah, %ah
jnz L(exit_dispatch_high)
mov %al, %dl
and $15 << 4, %dl
jnz L(exit_dispatch_8)
test $0x08, %al
jnz L(exit_4)
test $0x04, %al
jnz L(exit_3)
test $0x02, %al
jnz L(exit_2)
mov %ecx, %eax
ret
.p2align 4
L(matches32):
lea 32(%ecx), %ecx
test %ah, %ah
jnz L(exit_dispatch_high)
mov %al, %dl
and $15 << 4, %dl
jnz L(exit_dispatch_8)
test $0x08, %al
jnz L(exit_4)
test $0x04, %al
jnz L(exit_3)
test $0x02, %al
jnz L(exit_2)
mov %ecx, %eax
ret
.p2align 4
L(matches48):
lea 48(%ecx), %ecx
.p2align 4
L(exit_dispatch):
test %ah, %ah
jnz L(exit_dispatch_high)
mov %al, %dl
and $15 << 4, %dl
jnz L(exit_dispatch_8)
test $0x08, %al
jnz L(exit_4)
test $0x04, %al
jnz L(exit_3)
test $0x02, %al
jnz L(exit_2)
mov %ecx, %eax
ret
.p2align 4
L(exit_dispatch_8):
test $0x80, %al
jnz L(exit_8)
test $0x40, %al
jnz L(exit_7)
test $0x20, %al
jnz L(exit_6)
lea 4(%ecx), %eax
ret
.p2align 4
L(exit_dispatch_high):
mov %ah, %dh
and $15 << 4, %dh
jnz L(exit_dispatch_high_8)
test $0x08, %ah
jnz L(exit_12)
test $0x04, %ah
jnz L(exit_11)
test $0x02, %ah
jnz L(exit_10)
lea 8(%ecx), %eax
ret
.p2align 4
L(exit_dispatch_high_8):
test $0x80, %ah
jnz L(exit_16)
test $0x40, %ah
jnz L(exit_15)
test $0x20, %ah
jnz L(exit_14)
lea 12(%ecx), %eax
ret
.p2align 4
L(exit_2):
lea 1(%ecx), %eax
ret
.p2align 4
L(exit_3):
lea 2(%ecx), %eax
ret
.p2align 4
L(exit_4):
lea 3(%ecx), %eax
ret
.p2align 4
L(exit_6):
lea 5(%ecx), %eax
ret
.p2align 4
L(exit_7):
lea 6(%ecx), %eax
ret
.p2align 4
L(exit_8):
lea 7(%ecx), %eax
ret
.p2align 4
L(exit_10):
lea 9(%ecx), %eax
ret
.p2align 4
L(exit_11):
lea 10(%ecx), %eax
ret
.p2align 4
L(exit_12):
lea 11(%ecx), %eax
ret
.p2align 4
L(exit_14):
lea 13(%ecx), %eax
ret
.p2align 4
L(exit_15):
lea 14(%ecx), %eax
ret
.p2align 4
L(exit_16):
lea 15(%ecx), %eax
ret
.p2align 4
L(matches0_1):
lea -64(%edx), %edx
test %ah, %ah
jnz L(exit_dispatch_1_high)
mov %al, %ah
and $15 << 4, %ah
jnz L(exit_dispatch_1_8)
test $0x08, %al
jnz L(exit_1_4)
test $0x04, %al
jnz L(exit_1_3)
test $0x02, %al
jnz L(exit_1_2)
add $0, %edx
jl L(return_null)
mov %ecx, %eax
ret
.p2align 4
L(matches16_1):
lea -48(%edx), %edx
lea 16(%ecx), %ecx
test %ah, %ah
jnz L(exit_dispatch_1_high)
mov %al, %ah
and $15 << 4, %ah
jnz L(exit_dispatch_1_8)
test $0x08, %al
jnz L(exit_1_4)
test $0x04, %al
jnz L(exit_1_3)
test $0x02, %al
jnz L(exit_1_2)
add $0, %edx
jl L(return_null)
mov %ecx, %eax
ret
.p2align 4
L(matches32_1):
lea -32(%edx), %edx
lea 32(%ecx), %ecx
test %ah, %ah
jnz L(exit_dispatch_1_high)
mov %al, %ah
and $15 << 4, %ah
jnz L(exit_dispatch_1_8)
test $0x08, %al
jnz L(exit_1_4)
test $0x04, %al
jnz L(exit_1_3)
test $0x02, %al
jnz L(exit_1_2)
add $0, %edx
jl L(return_null)
mov %ecx, %eax
ret
.p2align 4
L(matches48_1):
lea -16(%edx), %edx
lea 48(%ecx), %ecx
.p2align 4
L(exit_dispatch_1):
test %ah, %ah
jnz L(exit_dispatch_1_high)
mov %al, %ah
and $15 << 4, %ah
jnz L(exit_dispatch_1_8)
test $0x08, %al
jnz L(exit_1_4)
test $0x04, %al
jnz L(exit_1_3)
test $0x02, %al
jnz L(exit_1_2)
add $0, %edx
jl L(return_null)
mov %ecx, %eax
ret
.p2align 4
L(exit_dispatch_1_8):
test $0x80, %al
jnz L(exit_1_8)
test $0x40, %al
jnz L(exit_1_7)
test $0x20, %al
jnz L(exit_1_6)
add $4, %edx
jl L(return_null)
lea 4(%ecx), %eax
ret
.p2align 4
L(exit_dispatch_1_high):
mov %ah, %al
and $15 << 4, %al
jnz L(exit_dispatch_1_high_8)
test $0x08, %ah
jnz L(exit_1_12)
test $0x04, %ah
jnz L(exit_1_11)
test $0x02, %ah
jnz L(exit_1_10)
add $8, %edx
jl L(return_null)
lea 8(%ecx), %eax
ret
.p2align 4
L(exit_dispatch_1_high_8):
test $0x80, %ah
jnz L(exit_1_16)
test $0x40, %ah
jnz L(exit_1_15)
test $0x20, %ah
jnz L(exit_1_14)
add $12, %edx
jl L(return_null)
lea 12(%ecx), %eax
ret
.p2align 4
L(exit_1_2):
add $1, %edx
jl L(return_null)
lea 1(%ecx), %eax
ret
.p2align 4
L(exit_1_3):
add $2, %edx
jl L(return_null)
lea 2(%ecx), %eax
ret
.p2align 4
L(exit_1_4):
add $3, %edx
jl L(return_null)
lea 3(%ecx), %eax
ret
.p2align 4
L(exit_1_6):
add $5, %edx
jl L(return_null)
lea 5(%ecx), %eax
ret
.p2align 4
L(exit_1_7):
add $6, %edx
jl L(return_null)
lea 6(%ecx), %eax
ret
.p2align 4
L(exit_1_8):
add $7, %edx
jl L(return_null)
lea 7(%ecx), %eax
ret
.p2align 4
L(exit_1_10):
add $9, %edx
jl L(return_null)
lea 9(%ecx), %eax
ret
.p2align 4
L(exit_1_11):
add $10, %edx
jl L(return_null)
lea 10(%ecx), %eax
ret
.p2align 4
L(exit_1_12):
add $11, %edx
jl L(return_null)
lea 11(%ecx), %eax
ret
.p2align 4
L(exit_1_14):
add $13, %edx
jl L(return_null)
lea 13(%ecx), %eax
ret
.p2align 4
L(exit_1_15):
add $14, %edx
jl L(return_null)
lea 14(%ecx), %eax
ret
.p2align 4
L(exit_1_16):
add $15, %edx
jl L(return_null)
lea 15(%ecx), %eax
ret
.p2align 4
L(return_null):
xor %eax, %eax
ret
.p2align 4
L(length_less16_offset0):
mov %dl, %cl
pcmpeqb (%eax), %xmm1
mov $1, %edx
sal %cl, %edx
sub $1, %edx
mov %eax, %ecx
pmovmskb %xmm1, %eax
and %edx, %eax
test %eax, %eax
jnz L(exit_dispatch)
xor %eax, %eax
ret
.p2align 4
L(length_less16):
punpcklbw %xmm1, %xmm1
add $16, %edx
punpcklbw %xmm1, %xmm1
mov %ecx, %eax
pshufd $0, %xmm1, %xmm1
and $15, %ecx
jz L(length_less16_offset0)
PUSH (%edi)
mov %cl, %dh
add %dl, %dh
and $-16, %eax
sub $16, %dh
ja L(length_less16_part2)
pcmpeqb (%eax), %xmm1
pmovmskb %xmm1, %edi
sar %cl, %edi
add %ecx, %eax
mov %dl, %cl
mov $1, %edx
sal %cl, %edx
sub $1, %edx
and %edx, %edi
test %edi, %edi
jz L(ret_null)
bsr %edi, %edi
add %edi, %eax
POP (%edi)
ret
CFI_PUSH (%edi)
.p2align 4
L(length_less16_part2):
movdqa 16(%eax), %xmm2
pcmpeqb %xmm1, %xmm2
pmovmskb %xmm2, %edi
mov %cl, %ch
mov %dh, %cl
mov $1, %edx
sal %cl, %edx
sub $1, %edx
and %edx, %edi
test %edi, %edi
jnz L(length_less16_part2_return)
pcmpeqb (%eax), %xmm1
pmovmskb %xmm1, %edi
mov %ch, %cl
sar %cl, %edi
test %edi, %edi
jz L(ret_null)
bsr %edi, %edi
add %edi, %eax
xor %ch, %ch
add %ecx, %eax
POP (%edi)
ret
CFI_PUSH (%edi)
.p2align 4
L(length_less16_part2_return):
bsr %edi, %edi
lea 16(%eax, %edi), %eax
POP (%edi)
ret
CFI_PUSH (%edi)
.p2align 4
L(ret_null):
xor %eax, %eax
POP (%edi)
ret
END (memrchr)

View File

@@ -28,6 +28,9 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "cache.h"
#undef __i686
#ifndef L
# define L(label) .L##label
#endif
@@ -136,9 +139,13 @@ __i686.get_pc_thunk.bx:
jmp *TABLE(,%ecx,4)
#endif
#ifndef MEMSET
# define MEMSET memset
#endif
.section .text.sse2,"ax",@progbits
ALIGN (4)
ENTRY (sse2_memset5_atom)
ENTRY (MEMSET)
ENTRANCE
movl LEN(%esp), %ecx
@@ -911,4 +918,4 @@ L(aligned_16_15bytes):
SETRTNVAL
RETURN_END
END (sse2_memset5_atom)
END (MEMSET)

View File

@@ -0,0 +1,391 @@
/*
Copyright (c) 2011, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef L
# define L(label) .L##label
#endif
#ifndef cfi_startproc
# define cfi_startproc .cfi_startproc
#endif
#ifndef cfi_endproc
# define cfi_endproc .cfi_endproc
#endif
#ifndef cfi_rel_offset
# define cfi_rel_offset(reg, off) .cfi_rel_offset reg, off
#endif
#ifndef cfi_restore
# define cfi_restore(reg) .cfi_restore reg
#endif
#ifndef cfi_adjust_cfa_offset
# define cfi_adjust_cfa_offset(off) .cfi_adjust_cfa_offset off
#endif
#ifndef ENTRY
# define ENTRY(name) \
.type name, @function; \
.globl name; \
.p2align 4; \
name: \
cfi_startproc
#endif
#ifndef END
# define END(name) \
cfi_endproc; \
.size name, .-name
#endif
#define CFI_PUSH(REG) \
cfi_adjust_cfa_offset (4); \
cfi_rel_offset (REG, 0)
#define CFI_POP(REG) \
cfi_adjust_cfa_offset (-4); \
cfi_restore (REG)
#define PUSH(REG) pushl REG; CFI_PUSH (REG)
#define POP(REG) popl REG; CFI_POP (REG)
#define PARMS 8
#define ENTRANCE PUSH(%edi)
#define RETURN POP (%edi); ret; CFI_PUSH (%edi);
#define STR1 PARMS
#define STR2 STR1+4
.text
ENTRY (strchr)
ENTRANCE
mov STR1(%esp), %ecx
movd STR2(%esp), %xmm1
pxor %xmm2, %xmm2
mov %ecx, %edi
punpcklbw %xmm1, %xmm1
punpcklbw %xmm1, %xmm1
/* ECX has OFFSET. */
and $15, %ecx
pshufd $0, %xmm1, %xmm1
je L(loop)
/* Handle unaligned string. */
and $-16, %edi
movdqa (%edi), %xmm0
pcmpeqb %xmm0, %xmm2
pcmpeqb %xmm1, %xmm0
/* Find where NULL is. */
pmovmskb %xmm2, %edx
/* Check if there is a match. */
pmovmskb %xmm0, %eax
/* Remove the leading bytes. */
sarl %cl, %edx
sarl %cl, %eax
test %eax, %eax
jz L(unaligned_no_match)
add %ecx, %edi
test %edx, %edx
jz L(match_case1)
jmp L(match_case2)
.p2align 4
L(unaligned_no_match):
test %edx, %edx
jne L(return_null)
pxor %xmm2, %xmm2
add $16, %edi
.p2align 4
/* Loop start on aligned string. */
L(loop):
movdqa (%edi), %xmm0
pcmpeqb %xmm0, %xmm2
pcmpeqb %xmm1, %xmm0
pmovmskb %xmm2, %edx
pmovmskb %xmm0, %eax
test %eax, %eax
jnz L(matches)
test %edx, %edx
jnz L(return_null)
add $16, %edi
movdqa (%edi), %xmm0
pcmpeqb %xmm0, %xmm2
pcmpeqb %xmm1, %xmm0
pmovmskb %xmm2, %edx
pmovmskb %xmm0, %eax
test %eax, %eax
jnz L(matches)
test %edx, %edx
jnz L(return_null)
add $16, %edi
movdqa (%edi), %xmm0
pcmpeqb %xmm0, %xmm2
pcmpeqb %xmm1, %xmm0
pmovmskb %xmm2, %edx
pmovmskb %xmm0, %eax
test %eax, %eax
jnz L(matches)
test %edx, %edx
jnz L(return_null)
add $16, %edi
movdqa (%edi), %xmm0
pcmpeqb %xmm0, %xmm2
pcmpeqb %xmm1, %xmm0
pmovmskb %xmm2, %edx
pmovmskb %xmm0, %eax
test %eax, %eax
jnz L(matches)
test %edx, %edx
jnz L(return_null)
add $16, %edi
jmp L(loop)
L(matches):
/* There is a match. First find where NULL is. */
test %edx, %edx
jz L(match_case1)
.p2align 4
L(match_case2):
test %al, %al
jz L(match_higth_case2)
mov %al, %cl
and $15, %cl
jnz L(match_case2_4)
mov %dl, %ch
and $15, %ch
jnz L(return_null)
test $0x10, %al
jnz L(Exit5)
test $0x10, %dl
jnz L(return_null)
test $0x20, %al
jnz L(Exit6)
test $0x20, %dl
jnz L(return_null)
test $0x40, %al
jnz L(Exit7)
test $0x40, %dl
jnz L(return_null)
lea 7(%edi), %eax
RETURN
.p2align 4
L(match_case2_4):
test $0x01, %al
jnz L(Exit1)
test $0x01, %dl
jnz L(return_null)
test $0x02, %al
jnz L(Exit2)
test $0x02, %dl
jnz L(return_null)
test $0x04, %al
jnz L(Exit3)
test $0x04, %dl
jnz L(return_null)
lea 3(%edi), %eax
RETURN
.p2align 4
L(match_higth_case2):
test %dl, %dl
jnz L(return_null)
mov %ah, %cl
and $15, %cl
jnz L(match_case2_12)
mov %dh, %ch
and $15, %ch
jnz L(return_null)
test $0x10, %ah
jnz L(Exit13)
test $0x10, %dh
jnz L(return_null)
test $0x20, %ah
jnz L(Exit14)
test $0x20, %dh
jnz L(return_null)
test $0x40, %ah
jnz L(Exit15)
test $0x40, %dh
jnz L(return_null)
lea 15(%edi), %eax
RETURN
.p2align 4
L(match_case2_12):
test $0x01, %ah
jnz L(Exit9)
test $0x01, %dh
jnz L(return_null)
test $0x02, %ah
jnz L(Exit10)
test $0x02, %dh
jnz L(return_null)
test $0x04, %ah
jnz L(Exit11)
test $0x04, %dh
jnz L(return_null)
lea 11(%edi), %eax
RETURN
.p2align 4
L(match_case1):
test %al, %al
jz L(match_higth_case1)
test $0x01, %al
jnz L(Exit1)
test $0x02, %al
jnz L(Exit2)
test $0x04, %al
jnz L(Exit3)
test $0x08, %al
jnz L(Exit4)
test $0x10, %al
jnz L(Exit5)
test $0x20, %al
jnz L(Exit6)
test $0x40, %al
jnz L(Exit7)
lea 7(%edi), %eax
RETURN
.p2align 4
L(match_higth_case1):
test $0x01, %ah
jnz L(Exit9)
test $0x02, %ah
jnz L(Exit10)
test $0x04, %ah
jnz L(Exit11)
test $0x08, %ah
jnz L(Exit12)
test $0x10, %ah
jnz L(Exit13)
test $0x20, %ah
jnz L(Exit14)
test $0x40, %ah
jnz L(Exit15)
lea 15(%edi), %eax
RETURN
.p2align 4
L(Exit1):
lea (%edi), %eax
RETURN
.p2align 4
L(Exit2):
lea 1(%edi), %eax
RETURN
.p2align 4
L(Exit3):
lea 2(%edi), %eax
RETURN
.p2align 4
L(Exit4):
lea 3(%edi), %eax
RETURN
.p2align 4
L(Exit5):
lea 4(%edi), %eax
RETURN
.p2align 4
L(Exit6):
lea 5(%edi), %eax
RETURN
.p2align 4
L(Exit7):
lea 6(%edi), %eax
RETURN
.p2align 4
L(Exit9):
lea 8(%edi), %eax
RETURN
.p2align 4
L(Exit10):
lea 9(%edi), %eax
RETURN
.p2align 4
L(Exit11):
lea 10(%edi), %eax
RETURN
.p2align 4
L(Exit12):
lea 11(%edi), %eax
RETURN
.p2align 4
L(Exit13):
lea 12(%edi), %eax
RETURN
.p2align 4
L(Exit14):
lea 13(%edi), %eax
RETURN
.p2align 4
L(Exit15):
lea 14(%edi), %eax
RETURN
.p2align 4
L(return_null):
xor %eax, %eax
RETURN
END (strchr)

View File

@@ -1,71 +1,112 @@
#define STRLEN sse2_strlen_atom
/*
Copyright (c) 2011, Intel Corporation
All rights reserved.
#ifndef L
# define L(label) .L##label
#endif
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
#ifndef cfi_startproc
# define cfi_startproc .cfi_startproc
#endif
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
#ifndef cfi_endproc
# define cfi_endproc .cfi_endproc
#endif
* 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.
#ifndef cfi_rel_offset
# define cfi_rel_offset(reg, off) .cfi_rel_offset reg, off
#endif
* Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
#ifndef cfi_restore
# define cfi_restore(reg) .cfi_restore reg
#endif
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 cfi_adjust_cfa_offset
# define cfi_adjust_cfa_offset(off) .cfi_adjust_cfa_offset off
#endif
#ifndef USE_AS_STRCAT
#ifndef cfi_remember_state
# define cfi_remember_state .cfi_remember_state
#endif
# ifndef STRLEN
# define STRLEN strlen
# endif
#ifndef cfi_restore_state
# define cfi_restore_state .cfi_restore_state
#endif
# ifndef L
# define L(label) .L##label
# endif
#ifndef ENTRY
# define ENTRY(name) \
.type name, @function; \
.globl name; \
.p2align 4; \
name: \
# ifndef cfi_startproc
# define cfi_startproc .cfi_startproc
# endif
# ifndef cfi_endproc
# define cfi_endproc .cfi_endproc
# endif
/* calee safe register only for strnlen is required */
# ifdef USE_AS_STRNLEN
# ifndef cfi_rel_offset
# define cfi_rel_offset(reg, off) .cfi_rel_offset reg, off
# endif
# ifndef cfi_restore
# define cfi_restore(reg) .cfi_restore reg
# endif
# ifndef cfi_adjust_cfa_offset
# define cfi_adjust_cfa_offset(off) .cfi_adjust_cfa_offset off
# endif
# endif
# ifndef ENTRY
# define ENTRY(name) \
.type name, @function; \
.globl name; \
.p2align 4; \
name: \
cfi_startproc
#endif
# endif
#ifndef END
# define END(name) \
cfi_endproc; \
# ifndef END
# define END(name) \
cfi_endproc; \
.size name, .-name
#endif
# endif
#define CFI_PUSH(REG) \
cfi_adjust_cfa_offset (4); \
cfi_rel_offset (REG, 0)
# define PARMS 4
# define STR PARMS
# define RETURN ret
#define CFI_POP(REG) \
cfi_adjust_cfa_offset (-4); \
cfi_restore (REG)
# ifdef USE_AS_STRNLEN
# define LEN PARMS + 8
# define CFI_PUSH(REG) \
cfi_adjust_cfa_offset (4); \
cfi_rel_offset (REG, 0)
#define PUSH(REG) pushl REG; CFI_PUSH (REG)
#define POP(REG) popl REG; CFI_POP (REG)
#define PARMS 4
#define STR PARMS
#define ENTRANCE
#define RETURN ret
# define CFI_POP(REG) \
cfi_adjust_cfa_offset (-4); \
cfi_restore (REG)
# define PUSH(REG) pushl REG; CFI_PUSH (REG)
# define POP(REG) popl REG; CFI_POP (REG)
# undef RETURN
# define RETURN POP (%edi); ret; CFI_PUSH(%edi);
# endif
.text
ENTRY (STRLEN)
ENTRANCE
mov STR(%esp), %edx
# ifdef USE_AS_STRNLEN
PUSH (%edi)
movl LEN(%esp), %edi
sub $4, %edi
jbe L(len_less4_prolog)
# endif
#endif
xor %eax, %eax
cmpb $0, (%edx)
jz L(exit_tail0)
@@ -75,6 +116,12 @@ ENTRY (STRLEN)
jz L(exit_tail2)
cmpb $0, 3(%edx)
jz L(exit_tail3)
#ifdef USE_AS_STRNLEN
sub $4, %edi
jbe L(len_less8_prolog)
#endif
cmpb $0, 4(%edx)
jz L(exit_tail4)
cmpb $0, 5(%edx)
@@ -83,6 +130,12 @@ ENTRY (STRLEN)
jz L(exit_tail6)
cmpb $0, 7(%edx)
jz L(exit_tail7)
#ifdef USE_AS_STRNLEN
sub $4, %edi
jbe L(len_less12_prolog)
#endif
cmpb $0, 8(%edx)
jz L(exit_tail8)
cmpb $0, 9(%edx)
@@ -91,6 +144,12 @@ ENTRY (STRLEN)
jz L(exit_tail10)
cmpb $0, 11(%edx)
jz L(exit_tail11)
#ifdef USE_AS_STRNLEN
sub $4, %edi
jbe L(len_less16_prolog)
#endif
cmpb $0, 12(%edx)
jz L(exit_tail12)
cmpb $0, 13(%edx)
@@ -99,211 +158,531 @@ ENTRY (STRLEN)
jz L(exit_tail14)
cmpb $0, 15(%edx)
jz L(exit_tail15)
pxor %xmm0, %xmm0
mov %edx, %eax
mov %edx, %ecx
lea 16(%edx), %eax
mov %eax, %ecx
and $-16, %eax
add $16, %ecx
add $16, %eax
#ifdef USE_AS_STRNLEN
and $15, %edx
add %edx, %edi
sub $64, %edi
jbe L(len_less64)
#endif
pcmpeqb (%eax), %xmm0
pmovmskb %xmm0, %edx
pxor %xmm1, %xmm1
test %edx, %edx
lea 16(%eax), %eax
test %edx, %edx
jnz L(exit)
pcmpeqb (%eax), %xmm1
pmovmskb %xmm1, %edx
pxor %xmm2, %xmm2
test %edx, %edx
lea 16(%eax), %eax
test %edx, %edx
jnz L(exit)
pcmpeqb (%eax), %xmm2
pmovmskb %xmm2, %edx
pxor %xmm3, %xmm3
test %edx, %edx
lea 16(%eax), %eax
test %edx, %edx
jnz L(exit)
pcmpeqb (%eax), %xmm3
pmovmskb %xmm3, %edx
test %edx, %edx
lea 16(%eax), %eax
test %edx, %edx
jnz L(exit)
#ifdef USE_AS_STRNLEN
sub $64, %edi
jbe L(len_less64)
#endif
pcmpeqb (%eax), %xmm0
pmovmskb %xmm0, %edx
test %edx, %edx
lea 16(%eax), %eax
test %edx, %edx
jnz L(exit)
pcmpeqb (%eax), %xmm1
pmovmskb %xmm1, %edx
test %edx, %edx
lea 16(%eax), %eax
test %edx, %edx
jnz L(exit)
pcmpeqb (%eax), %xmm2
pmovmskb %xmm2, %edx
test %edx, %edx
lea 16(%eax), %eax
test %edx, %edx
jnz L(exit)
pcmpeqb (%eax), %xmm3
pmovmskb %xmm3, %edx
test %edx, %edx
lea 16(%eax), %eax
test %edx, %edx
jnz L(exit)
#ifdef USE_AS_STRNLEN
sub $64, %edi
jbe L(len_less64)
#endif
pcmpeqb (%eax), %xmm0
pmovmskb %xmm0, %edx
test %edx, %edx
lea 16(%eax), %eax
test %edx, %edx
jnz L(exit)
pcmpeqb (%eax), %xmm1
pmovmskb %xmm1, %edx
test %edx, %edx
lea 16(%eax), %eax
test %edx, %edx
jnz L(exit)
pcmpeqb (%eax), %xmm2
pmovmskb %xmm2, %edx
test %edx, %edx
lea 16(%eax), %eax
test %edx, %edx
jnz L(exit)
pcmpeqb (%eax), %xmm3
pmovmskb %xmm3, %edx
test %edx, %edx
lea 16(%eax), %eax
test %edx, %edx
jnz L(exit)
#ifdef USE_AS_STRNLEN
sub $64, %edi
jbe L(len_less64)
#endif
pcmpeqb (%eax), %xmm0
pmovmskb %xmm0, %edx
test %edx, %edx
lea 16(%eax), %eax
test %edx, %edx
jnz L(exit)
pcmpeqb (%eax), %xmm1
pmovmskb %xmm1, %edx
test %edx, %edx
lea 16(%eax), %eax
test %edx, %edx
jnz L(exit)
pcmpeqb (%eax), %xmm2
pmovmskb %xmm2, %edx
test %edx, %edx
lea 16(%eax), %eax
test %edx, %edx
jnz L(exit)
pcmpeqb (%eax), %xmm3
pmovmskb %xmm3, %edx
test %edx, %edx
lea 16(%eax), %eax
test %edx, %edx
jnz L(exit)
#ifdef USE_AS_STRNLEN
mov %eax, %edx
and $63, %edx
add %edx, %edi
#endif
and $-0x40, %eax
PUSH (%esi)
PUSH (%edi)
PUSH (%ebx)
PUSH (%ebp)
xor %ebp, %ebp
L(aligned_64):
pcmpeqb (%eax), %xmm0
pcmpeqb 16(%eax), %xmm1
pcmpeqb 32(%eax), %xmm2
pcmpeqb 48(%eax), %xmm3
pmovmskb %xmm0, %edx
pmovmskb %xmm1, %esi
pmovmskb %xmm2, %edi
pmovmskb %xmm3, %ebx
or %edx, %ebp
or %esi, %ebp
or %edi, %ebp
or %ebx, %ebp
.p2align 4
L(aligned_64_loop):
#ifdef USE_AS_STRNLEN
sub $64, %edi
jbe L(len_less64)
#endif
movaps (%eax), %xmm0
movaps 16(%eax), %xmm1
movaps 32(%eax), %xmm2
movaps 48(%eax), %xmm6
pminub %xmm1, %xmm0
pminub %xmm6, %xmm2
pminub %xmm0, %xmm2
pcmpeqb %xmm3, %xmm2
pmovmskb %xmm2, %edx
lea 64(%eax), %eax
jz L(aligned_64)
L(48leave):
test %edx, %edx
jnz L(aligned_64_exit_16)
test %esi, %esi
jnz L(aligned_64_exit_32)
test %edi, %edi
jnz L(aligned_64_exit_48)
mov %ebx, %edx
lea (%eax), %eax
jmp L(aligned_64_exit)
L(aligned_64_exit_48):
lea -16(%eax), %eax
mov %edi, %edx
jmp L(aligned_64_exit)
L(aligned_64_exit_32):
lea -32(%eax), %eax
mov %esi, %edx
jmp L(aligned_64_exit)
L(aligned_64_exit_16):
lea -48(%eax), %eax
L(aligned_64_exit):
POP (%ebp)
POP (%ebx)
POP (%edi)
POP (%esi)
jz L(aligned_64_loop)
pcmpeqb -64(%eax), %xmm3
pmovmskb %xmm3, %edx
lea 48(%ecx), %ecx
test %edx, %edx
jnz L(exit)
pcmpeqb %xmm1, %xmm3
pmovmskb %xmm3, %edx
lea -16(%ecx), %ecx
test %edx, %edx
jnz L(exit)
pcmpeqb -32(%eax), %xmm3
pmovmskb %xmm3, %edx
lea -16(%ecx), %ecx
test %edx, %edx
jnz L(exit)
pcmpeqb %xmm6, %xmm3
pmovmskb %xmm3, %edx
lea -16(%ecx), %ecx
L(exit):
sub %ecx, %eax
test %dl, %dl
jz L(exit_high)
mov %dl, %cl
and $15, %cl
jz L(exit_8)
test $0x01, %dl
jnz L(exit_tail0)
test $0x02, %dl
jnz L(exit_tail1)
test $0x04, %dl
jnz L(exit_tail2)
add $3, %eax
RETURN
test $0x08, %dl
jnz L(exit_tail3)
.p2align 4
L(exit_8):
test $0x10, %dl
jnz L(exit_tail4)
test $0x20, %dl
jnz L(exit_tail5)
test $0x40, %dl
jnz L(exit_tail6)
add $7, %eax
RETURN
.p2align 4
L(exit_high):
mov %dh, %ch
and $15, %ch
jz L(exit_high_8)
test $0x01, %dh
jnz L(exit_tail8)
test $0x02, %dh
jnz L(exit_tail9)
test $0x04, %dh
jnz L(exit_tail10)
add $11, %eax
RETURN
.p2align 4
L(exit_high_8):
test $0x10, %dh
jnz L(exit_tail12)
test $0x20, %dh
jnz L(exit_tail13)
test $0x40, %dh
jnz L(exit_tail14)
add $15, %eax
L(exit_tail0):
RETURN
L(exit_high):
add $8, %eax
test $0x01, %dh
jnz L(exit_tail0)
#ifdef USE_AS_STRNLEN
test $0x02, %dh
jnz L(exit_tail1)
.p2align 4
L(len_less64):
pxor %xmm0, %xmm0
add $64, %edi
test $0x04, %dh
jnz L(exit_tail2)
pcmpeqb (%eax), %xmm0
pmovmskb %xmm0, %edx
pxor %xmm1, %xmm1
lea 16(%eax), %eax
test %edx, %edx
jnz L(strnlen_exit)
test $0x08, %dh
jnz L(exit_tail3)
sub $16, %edi
jbe L(return_start_len)
test $0x10, %dh
jnz L(exit_tail4)
pcmpeqb (%eax), %xmm1
pmovmskb %xmm1, %edx
lea 16(%eax), %eax
test %edx, %edx
jnz L(strnlen_exit)
test $0x20, %dh
jnz L(exit_tail5)
sub $16, %edi
jbe L(return_start_len)
test $0x40, %dh
jnz L(exit_tail6)
add $7, %eax
pcmpeqb (%eax), %xmm0
pmovmskb %xmm0, %edx
lea 16(%eax), %eax
test %edx, %edx
jnz L(strnlen_exit)
sub $16, %edi
jbe L(return_start_len)
pcmpeqb (%eax), %xmm1
pmovmskb %xmm1, %edx
lea 16(%eax), %eax
test %edx, %edx
jnz L(strnlen_exit)
#ifndef USE_AS_STRLCAT
movl LEN(%esp), %eax
RETURN
#else
jmp L(return_start_len)
#endif
.p2align 4
L(strnlen_exit):
sub %ecx, %eax
test %dl, %dl
jz L(strnlen_exit_high)
mov %dl, %cl
and $15, %cl
jz L(strnlen_exit_8)
test $0x01, %dl
jnz L(exit_tail0)
test $0x02, %dl
jnz L(strnlen_exit_tail1)
test $0x04, %dl
jnz L(strnlen_exit_tail2)
sub $4, %edi
jb L(return_start_len)
lea 3(%eax), %eax
RETURN
.p2align 4
L(strnlen_exit_8):
test $0x10, %dl
jnz L(strnlen_exit_tail4)
test $0x20, %dl
jnz L(strnlen_exit_tail5)
test $0x40, %dl
jnz L(strnlen_exit_tail6)
sub $8, %edi
jb L(return_start_len)
lea 7(%eax), %eax
RETURN
.p2align 4
L(strnlen_exit_high):
mov %dh, %ch
and $15, %ch
jz L(strnlen_exit_high_8)
test $0x01, %dh
jnz L(strnlen_exit_tail8)
test $0x02, %dh
jnz L(strnlen_exit_tail9)
test $0x04, %dh
jnz L(strnlen_exit_tail10)
sub $12, %edi
jb L(return_start_len)
lea 11(%eax), %eax
RETURN
.p2align 4
L(strnlen_exit_high_8):
test $0x10, %dh
jnz L(strnlen_exit_tail12)
test $0x20, %dh
jnz L(strnlen_exit_tail13)
test $0x40, %dh
jnz L(strnlen_exit_tail14)
sub $16, %edi
jb L(return_start_len)
lea 15(%eax), %eax
RETURN
.p2align 4
L(strnlen_exit_tail1):
sub $2, %edi
jb L(return_start_len)
lea 1(%eax), %eax
RETURN
.p2align 4
L(strnlen_exit_tail2):
sub $3, %edi
jb L(return_start_len)
lea 2(%eax), %eax
RETURN
.p2align 4
L(strnlen_exit_tail4):
sub $5, %edi
jb L(return_start_len)
lea 4(%eax), %eax
RETURN
.p2align 4
L(strnlen_exit_tail5):
sub $6, %edi
jb L(return_start_len)
lea 5(%eax), %eax
RETURN
.p2align 4
L(strnlen_exit_tail6):
sub $7, %edi
jb L(return_start_len)
lea 6(%eax), %eax
RETURN
.p2align 4
L(strnlen_exit_tail8):
sub $9, %edi
jb L(return_start_len)
lea 8(%eax), %eax
RETURN
.p2align 4
L(strnlen_exit_tail9):
sub $10, %edi
jb L(return_start_len)
lea 9(%eax), %eax
RETURN
.p2align 4
L(strnlen_exit_tail10):
sub $11, %edi
jb L(return_start_len)
lea 10(%eax), %eax
RETURN
.p2align 4
L(strnlen_exit_tail12):
sub $13, %edi
jb L(return_start_len)
lea 12(%eax), %eax
RETURN
.p2align 4
L(strnlen_exit_tail13):
sub $14, %edi
jb L(return_start_len)
lea 13(%eax), %eax
RETURN
.p2align 4
L(strnlen_exit_tail14):
sub $15, %edi
jb L(return_start_len)
lea 14(%eax), %eax
RETURN
#ifndef USE_AS_STRLCAT
.p2align 4
L(return_start_len):
movl LEN(%esp), %eax
RETURN
#endif
/* for prolog only */
.p2align 4
L(len_less4_prolog):
xor %eax, %eax
add $4, %edi
jz L(exit_tail0)
cmpb $0, (%edx)
jz L(exit_tail0)
cmp $1, %edi
je L(exit_tail1)
cmpb $0, 1(%edx)
jz L(exit_tail1)
cmp $2, %edi
je L(exit_tail2)
cmpb $0, 2(%edx)
jz L(exit_tail2)
cmp $3, %edi
je L(exit_tail3)
cmpb $0, 3(%edx)
jz L(exit_tail3)
mov %edi, %eax
RETURN
.p2align 4
L(len_less8_prolog):
add $4, %edi
cmpb $0, 4(%edx)
jz L(exit_tail4)
cmp $1, %edi
je L(exit_tail5)
cmpb $0, 5(%edx)
jz L(exit_tail5)
cmp $2, %edi
je L(exit_tail6)
cmpb $0, 6(%edx)
jz L(exit_tail6)
cmp $3, %edi
je L(exit_tail7)
cmpb $0, 7(%edx)
jz L(exit_tail7)
mov $8, %eax
RETURN
.p2align 4
L(len_less12_prolog):
add $4, %edi
cmpb $0, 8(%edx)
jz L(exit_tail8)
cmp $1, %edi
je L(exit_tail9)
cmpb $0, 9(%edx)
jz L(exit_tail9)
cmp $2, %edi
je L(exit_tail10)
cmpb $0, 10(%edx)
jz L(exit_tail10)
cmp $3, %edi
je L(exit_tail11)
cmpb $0, 11(%edx)
jz L(exit_tail11)
mov $12, %eax
RETURN
.p2align 4
L(len_less16_prolog):
add $4, %edi
cmpb $0, 12(%edx)
jz L(exit_tail12)
cmp $1, %edi
je L(exit_tail13)
cmpb $0, 13(%edx)
jz L(exit_tail13)
cmp $2, %edi
je L(exit_tail14)
cmpb $0, 14(%edx)
jz L(exit_tail14)
cmp $3, %edi
je L(exit_tail15)
cmpb $0, 15(%edx)
jz L(exit_tail15)
mov $16, %eax
RETURN
#endif
.p2align 4
L(exit_tail1):
@@ -364,6 +743,7 @@ L(exit_tail14):
L(exit_tail15):
add $15, %eax
ret
#ifndef USE_AS_STRCAT
RETURN
END (STRLEN)
#endif

View File

@@ -0,0 +1,33 @@
/*
Copyright (c) 2011, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#define USE_AS_STRNLEN 1
#define STRLEN strnlen
#include "sse2-strlen-atom.S"

View File

@@ -0,0 +1,753 @@
/*
Copyright (c) 2011, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef L
# define L(label) .L##label
#endif
#ifndef cfi_startproc
# define cfi_startproc .cfi_startproc
#endif
#ifndef cfi_endproc
# define cfi_endproc .cfi_endproc
#endif
#ifndef cfi_rel_offset
# define cfi_rel_offset(reg, off) .cfi_rel_offset reg, off
#endif
#ifndef cfi_restore
# define cfi_restore(reg) .cfi_restore reg
#endif
#ifndef cfi_adjust_cfa_offset
# define cfi_adjust_cfa_offset(off) .cfi_adjust_cfa_offset off
#endif
#ifndef ENTRY
# define ENTRY(name) \
.type name, @function; \
.globl name; \
.p2align 4; \
name: \
cfi_startproc
#endif
#ifndef END
# define END(name) \
cfi_endproc; \
.size name, .-name
#endif
#define CFI_PUSH(REG) \
cfi_adjust_cfa_offset (4); \
cfi_rel_offset (REG, 0)
#define CFI_POP(REG) \
cfi_adjust_cfa_offset (-4); \
cfi_restore (REG)
#define PUSH(REG) pushl REG; CFI_PUSH (REG)
#define POP(REG) popl REG; CFI_POP (REG)
#define PARMS 8
#define ENTRANCE PUSH(%edi);
#define RETURN POP (%edi); ret; CFI_PUSH (%edi);
#define STR1 PARMS
#define STR2 STR1+4
.text
ENTRY (strrchr)
ENTRANCE
mov STR1(%esp), %ecx
movd STR2(%esp), %xmm1
pxor %xmm2, %xmm2
mov %ecx, %edi
punpcklbw %xmm1, %xmm1
punpcklbw %xmm1, %xmm1
/* ECX has OFFSET. */
and $63, %ecx
pshufd $0, %xmm1, %xmm1
cmp $48, %ecx
ja L(crosscache)
/* unaligned string. */
movdqu (%edi), %xmm0
pcmpeqb %xmm0, %xmm2
pcmpeqb %xmm1, %xmm0
/* Find where NULL is. */
pmovmskb %xmm2, %ecx
/* Check if there is a match. */
pmovmskb %xmm0, %eax
add $16, %edi
test %eax, %eax
jnz L(unaligned_match1)
test %ecx, %ecx
jnz L(return_null)
and $-16, %edi
PUSH (%esi)
PUSH (%ebx)
xor %ebx, %ebx
jmp L(loop)
CFI_POP (%esi)
CFI_POP (%ebx)
.p2align 4
L(unaligned_match1):
test %ecx, %ecx
jnz L(prolog_find_zero_1)
PUSH (%esi)
PUSH (%ebx)
mov %eax, %ebx
mov %edi, %esi
and $-16, %edi
jmp L(loop)
CFI_POP (%esi)
CFI_POP (%ebx)
.p2align 4
L(crosscache):
/* Hancle unaligned string. */
and $15, %ecx
and $-16, %edi
pxor %xmm3, %xmm3
movdqa (%edi), %xmm0
pcmpeqb %xmm0, %xmm3
pcmpeqb %xmm1, %xmm0
/* Find where NULL is. */
pmovmskb %xmm3, %edx
/* Check if there is a match. */
pmovmskb %xmm0, %eax
/* Remove the leading bytes. */
shr %cl, %edx
shr %cl, %eax
add $16, %edi
test %eax, %eax
jnz L(unaligned_match)
test %edx, %edx
jnz L(return_null)
PUSH (%esi)
PUSH (%ebx)
xor %ebx, %ebx
jmp L(loop)
CFI_POP (%esi)
CFI_POP (%ebx)
.p2align 4
L(unaligned_match):
test %edx, %edx
jnz L(prolog_find_zero)
PUSH (%esi)
PUSH (%ebx)
mov %eax, %ebx
lea (%edi, %ecx), %esi
/* Loop start on aligned string. */
.p2align 4
L(loop):
movdqa (%edi), %xmm0
pcmpeqb %xmm0, %xmm2
add $16, %edi
pcmpeqb %xmm1, %xmm0
pmovmskb %xmm2, %ecx
pmovmskb %xmm0, %eax
or %eax, %ecx
jnz L(matches)
movdqa (%edi), %xmm0
pcmpeqb %xmm0, %xmm2
add $16, %edi
pcmpeqb %xmm1, %xmm0
pmovmskb %xmm2, %ecx
pmovmskb %xmm0, %eax
or %eax, %ecx
jnz L(matches)
movdqa (%edi), %xmm0
pcmpeqb %xmm0, %xmm2
add $16, %edi
pcmpeqb %xmm1, %xmm0
pmovmskb %xmm2, %ecx
pmovmskb %xmm0, %eax
or %eax, %ecx
jnz L(matches)
movdqa (%edi), %xmm0
pcmpeqb %xmm0, %xmm2
add $16, %edi
pcmpeqb %xmm1, %xmm0
pmovmskb %xmm2, %ecx
pmovmskb %xmm0, %eax
or %eax, %ecx
jz L(loop)
L(matches):
test %eax, %eax
jnz L(match)
L(return_value):
test %ebx, %ebx
jz L(return_null_1)
mov %ebx, %eax
mov %esi, %edi
POP (%ebx)
POP (%esi)
jmp L(match_case1)
CFI_PUSH (%ebx)
CFI_PUSH (%esi)
.p2align 4
L(return_null_1):
POP (%ebx)
POP (%esi)
xor %eax, %eax
RETURN
CFI_PUSH (%ebx)
CFI_PUSH (%esi)
.p2align 4
L(match):
pmovmskb %xmm2, %ecx
test %ecx, %ecx
jnz L(find_zero)
mov %eax, %ebx
mov %edi, %esi
jmp L(loop)
.p2align 4
L(find_zero):
test %cl, %cl
jz L(find_zero_high)
mov %cl, %dl
and $15, %dl
jz L(find_zero_8)
test $0x01, %cl
jnz L(FindZeroExit1)
test $0x02, %cl
jnz L(FindZeroExit2)
test $0x04, %cl
jnz L(FindZeroExit3)
and $1 << 4 - 1, %eax
jz L(return_value)
POP (%ebx)
POP (%esi)
jmp L(match_case1)
CFI_PUSH (%ebx)
CFI_PUSH (%esi)
.p2align 4
L(find_zero_8):
test $0x10, %cl
jnz L(FindZeroExit5)
test $0x20, %cl
jnz L(FindZeroExit6)
test $0x40, %cl
jnz L(FindZeroExit7)
and $1 << 8 - 1, %eax
jz L(return_value)
POP (%ebx)
POP (%esi)
jmp L(match_case1)
CFI_PUSH (%ebx)
CFI_PUSH (%esi)
.p2align 4
L(find_zero_high):
mov %ch, %dh
and $15, %dh
jz L(find_zero_high_8)
test $0x01, %ch
jnz L(FindZeroExit9)
test $0x02, %ch
jnz L(FindZeroExit10)
test $0x04, %ch
jnz L(FindZeroExit11)
and $1 << 12 - 1, %eax
jz L(return_value)
POP (%ebx)
POP (%esi)
jmp L(match_case1)
CFI_PUSH (%ebx)
CFI_PUSH (%esi)
.p2align 4
L(find_zero_high_8):
test $0x10, %ch
jnz L(FindZeroExit13)
test $0x20, %ch
jnz L(FindZeroExit14)
test $0x40, %ch
jnz L(FindZeroExit15)
and $1 << 16 - 1, %eax
jz L(return_value)
POP (%ebx)
POP (%esi)
jmp L(match_case1)
CFI_PUSH (%ebx)
CFI_PUSH (%esi)
.p2align 4
L(FindZeroExit1):
and $1, %eax
jz L(return_value)
POP (%ebx)
POP (%esi)
jmp L(match_case1)
CFI_PUSH (%ebx)
CFI_PUSH (%esi)
.p2align 4
L(FindZeroExit2):
and $1 << 2 - 1, %eax
jz L(return_value)
POP (%ebx)
POP (%esi)
jmp L(match_case1)
CFI_PUSH (%ebx)
CFI_PUSH (%esi)
.p2align 4
L(FindZeroExit3):
and $1 << 3 - 1, %eax
jz L(return_value)
POP (%ebx)
POP (%esi)
jmp L(match_case1)
CFI_PUSH (%ebx)
CFI_PUSH (%esi)
.p2align 4
L(FindZeroExit5):
and $1 << 5 - 1, %eax
jz L(return_value)
POP (%ebx)
POP (%esi)
jmp L(match_case1)
CFI_PUSH (%ebx)
CFI_PUSH (%esi)
.p2align 4
L(FindZeroExit6):
and $1 << 6 - 1, %eax
jz L(return_value)
POP (%ebx)
POP (%esi)
jmp L(match_case1)
CFI_PUSH (%ebx)
CFI_PUSH (%esi)
.p2align 4
L(FindZeroExit7):
and $1 << 7 - 1, %eax
jz L(return_value)
POP (%ebx)
POP (%esi)
jmp L(match_case1)
CFI_PUSH (%ebx)
CFI_PUSH (%esi)
.p2align 4
L(FindZeroExit9):
and $1 << 9 - 1, %eax
jz L(return_value)
POP (%ebx)
POP (%esi)
jmp L(match_case1)
CFI_PUSH (%ebx)
CFI_PUSH (%esi)
.p2align 4
L(FindZeroExit10):
and $1 << 10 - 1, %eax
jz L(return_value)
POP (%ebx)
POP (%esi)
jmp L(match_case1)
CFI_PUSH (%ebx)
CFI_PUSH (%esi)
.p2align 4
L(FindZeroExit11):
and $1 << 11 - 1, %eax
jz L(return_value)
POP (%ebx)
POP (%esi)
jmp L(match_case1)
CFI_PUSH (%ebx)
CFI_PUSH (%esi)
.p2align 4
L(FindZeroExit13):
and $1 << 13 - 1, %eax
jz L(return_value)
POP (%ebx)
POP (%esi)
jmp L(match_case1)
CFI_PUSH (%ebx)
CFI_PUSH (%esi)
.p2align 4
L(FindZeroExit14):
and $1 << 14 - 1, %eax
jz L(return_value)
POP (%ebx)
POP (%esi)
jmp L(match_case1)
CFI_PUSH (%ebx)
CFI_PUSH (%esi)
.p2align 4
L(FindZeroExit15):
and $1 << 15 - 1, %eax
jz L(return_value)
POP (%ebx)
POP (%esi)
.p2align 4
L(match_case1):
test %ah, %ah
jnz L(match_case1_high)
mov %al, %dl
and $15 << 4, %dl
jnz L(match_case1_8)
test $0x08, %al
jnz L(Exit4)
test $0x04, %al
jnz L(Exit3)
test $0x02, %al
jnz L(Exit2)
lea -16(%edi), %eax
RETURN
.p2align 4
L(match_case1_8):
test $0x80, %al
jnz L(Exit8)
test $0x40, %al
jnz L(Exit7)
test $0x20, %al
jnz L(Exit6)
lea -12(%edi), %eax
RETURN
.p2align 4
L(match_case1_high):
mov %ah, %dh
and $15 << 4, %dh
jnz L(match_case1_high_8)
test $0x08, %ah
jnz L(Exit12)
test $0x04, %ah
jnz L(Exit11)
test $0x02, %ah
jnz L(Exit10)
lea -8(%edi), %eax
RETURN
.p2align 4
L(match_case1_high_8):
test $0x80, %ah
jnz L(Exit16)
test $0x40, %ah
jnz L(Exit15)
test $0x20, %ah
jnz L(Exit14)
lea -4(%edi), %eax
RETURN
.p2align 4
L(Exit2):
lea -15(%edi), %eax
RETURN
.p2align 4
L(Exit3):
lea -14(%edi), %eax
RETURN
.p2align 4
L(Exit4):
lea -13(%edi), %eax
RETURN
.p2align 4
L(Exit6):
lea -11(%edi), %eax
RETURN
.p2align 4
L(Exit7):
lea -10(%edi), %eax
RETURN
.p2align 4
L(Exit8):
lea -9(%edi), %eax
RETURN
.p2align 4
L(Exit10):
lea -7(%edi), %eax
RETURN
.p2align 4
L(Exit11):
lea -6(%edi), %eax
RETURN
.p2align 4
L(Exit12):
lea -5(%edi), %eax
RETURN
.p2align 4
L(Exit14):
lea -3(%edi), %eax
RETURN
.p2align 4
L(Exit15):
lea -2(%edi), %eax
RETURN
.p2align 4
L(Exit16):
lea -1(%edi), %eax
RETURN
/* Return NULL. */
.p2align 4
L(return_null):
xor %eax, %eax
RETURN
.p2align 4
L(prolog_find_zero):
add %ecx, %edi
mov %edx, %ecx
L(prolog_find_zero_1):
test %cl, %cl
jz L(prolog_find_zero_high)
mov %cl, %dl
and $15, %dl
jz L(prolog_find_zero_8)
test $0x01, %cl
jnz L(PrologFindZeroExit1)
test $0x02, %cl
jnz L(PrologFindZeroExit2)
test $0x04, %cl
jnz L(PrologFindZeroExit3)
and $1 << 4 - 1, %eax
jnz L(match_case1)
xor %eax, %eax
RETURN
.p2align 4
L(prolog_find_zero_8):
test $0x10, %cl
jnz L(PrologFindZeroExit5)
test $0x20, %cl
jnz L(PrologFindZeroExit6)
test $0x40, %cl
jnz L(PrologFindZeroExit7)
and $1 << 8 - 1, %eax
jnz L(match_case1)
xor %eax, %eax
RETURN
.p2align 4
L(prolog_find_zero_high):
mov %ch, %dh
and $15, %dh
jz L(prolog_find_zero_high_8)
test $0x01, %ch
jnz L(PrologFindZeroExit9)
test $0x02, %ch
jnz L(PrologFindZeroExit10)
test $0x04, %ch
jnz L(PrologFindZeroExit11)
and $1 << 12 - 1, %eax
jnz L(match_case1)
xor %eax, %eax
RETURN
.p2align 4
L(prolog_find_zero_high_8):
test $0x10, %ch
jnz L(PrologFindZeroExit13)
test $0x20, %ch
jnz L(PrologFindZeroExit14)
test $0x40, %ch
jnz L(PrologFindZeroExit15)
and $1 << 16 - 1, %eax
jnz L(match_case1)
xor %eax, %eax
RETURN
.p2align 4
L(PrologFindZeroExit1):
and $1, %eax
jnz L(match_case1)
xor %eax, %eax
RETURN
.p2align 4
L(PrologFindZeroExit2):
and $1 << 2 - 1, %eax
jnz L(match_case1)
xor %eax, %eax
RETURN
.p2align 4
L(PrologFindZeroExit3):
and $1 << 3 - 1, %eax
jnz L(match_case1)
xor %eax, %eax
RETURN
.p2align 4
L(PrologFindZeroExit5):
and $1 << 5 - 1, %eax
jnz L(match_case1)
xor %eax, %eax
RETURN
.p2align 4
L(PrologFindZeroExit6):
and $1 << 6 - 1, %eax
jnz L(match_case1)
xor %eax, %eax
RETURN
.p2align 4
L(PrologFindZeroExit7):
and $1 << 7 - 1, %eax
jnz L(match_case1)
xor %eax, %eax
RETURN
.p2align 4
L(PrologFindZeroExit9):
and $1 << 9 - 1, %eax
jnz L(match_case1)
xor %eax, %eax
RETURN
.p2align 4
L(PrologFindZeroExit10):
and $1 << 10 - 1, %eax
jnz L(match_case1)
xor %eax, %eax
RETURN
.p2align 4
L(PrologFindZeroExit11):
and $1 << 11 - 1, %eax
jnz L(match_case1)
xor %eax, %eax
RETURN
.p2align 4
L(PrologFindZeroExit13):
and $1 << 13 - 1, %eax
jnz L(match_case1)
xor %eax, %eax
RETURN
.p2align 4
L(PrologFindZeroExit14):
and $1 << 14 - 1, %eax
jnz L(match_case1)
xor %eax, %eax
RETURN
.p2align 4
L(PrologFindZeroExit15):
and $1 << 15 - 1, %eax
jnz L(match_case1)
xor %eax, %eax
RETURN
END (strrchr)

View File

@@ -0,0 +1,267 @@
/*
Copyright (c) 2011 Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef L
# define L(label) .L##label
#endif
#ifndef cfi_startproc
# define cfi_startproc .cfi_startproc
#endif
#ifndef cfi_endproc
# define cfi_endproc .cfi_endproc
#endif
#ifndef cfi_rel_offset
# define cfi_rel_offset(reg, off) .cfi_rel_offset reg, off
#endif
#ifndef cfi_restore
# define cfi_restore(reg) .cfi_restore reg
#endif
#ifndef cfi_adjust_cfa_offset
# define cfi_adjust_cfa_offset(off) .cfi_adjust_cfa_offset off
#endif
#ifndef ENTRY
# define ENTRY(name) \
.type name, @function; \
.globl name; \
.p2align 4; \
name: \
cfi_startproc
#endif
#ifndef END
# define END(name) \
cfi_endproc; \
.size name, .-name
#endif
#define CFI_PUSH(REG) \
cfi_adjust_cfa_offset (4); \
cfi_rel_offset (REG, 0)
#define CFI_POP(REG) \
cfi_adjust_cfa_offset (-4); \
cfi_restore (REG)
#define PUSH(REG) pushl REG; CFI_PUSH (REG)
#define POP(REG) popl REG; CFI_POP (REG)
#define PARMS 4
#define STR1 PARMS
#define STR2 STR1+4
.text
ENTRY (wcschr)
mov STR1(%esp), %ecx
movd STR2(%esp), %xmm1
mov %ecx, %eax
punpckldq %xmm1, %xmm1
pxor %xmm2, %xmm2
punpckldq %xmm1, %xmm1
and $63, %eax
cmp $48, %eax
ja L(cross_cache)
movdqu (%ecx), %xmm0
pcmpeqd %xmm0, %xmm2
pcmpeqd %xmm1, %xmm0
pmovmskb %xmm2, %edx
pmovmskb %xmm0, %eax
or %eax, %edx
jnz L(matches)
and $-16, %ecx
jmp L(loop)
.p2align 4
L(cross_cache):
PUSH (%edi)
mov %ecx, %edi
mov %eax, %ecx
and $-16, %edi
and $15, %ecx
movdqa (%edi), %xmm0
pcmpeqd %xmm0, %xmm2
pcmpeqd %xmm1, %xmm0
pmovmskb %xmm2, %edx
pmovmskb %xmm0, %eax
sarl %cl, %edx
sarl %cl, %eax
test %eax, %eax
jz L(unaligned_no_match)
add %edi, %ecx
POP (%edi)
test %edx, %edx
jz L(match_case1)
test %al, %al
jz L(match_higth_case2)
test $15, %al
jnz L(match_case2_4)
test $15, %dl
jnz L(return_null)
lea 4(%ecx), %eax
ret
CFI_PUSH (%edi)
.p2align 4
L(unaligned_no_match):
mov %edi, %ecx
POP (%edi)
test %edx, %edx
jnz L(return_null)
pxor %xmm2, %xmm2
/* Loop start on aligned string. */
.p2align 4
L(loop):
add $16, %ecx
movdqa (%ecx), %xmm0
pcmpeqd %xmm0, %xmm2
pcmpeqd %xmm1, %xmm0
pmovmskb %xmm2, %edx
pmovmskb %xmm0, %eax
or %eax, %edx
jnz L(matches)
add $16, %ecx
movdqa (%ecx), %xmm0
pcmpeqd %xmm0, %xmm2
pcmpeqd %xmm1, %xmm0
pmovmskb %xmm2, %edx
pmovmskb %xmm0, %eax
or %eax, %edx
jnz L(matches)
add $16, %ecx
movdqa (%ecx), %xmm0
pcmpeqd %xmm0, %xmm2
pcmpeqd %xmm1, %xmm0
pmovmskb %xmm2, %edx
pmovmskb %xmm0, %eax
or %eax, %edx
jnz L(matches)
add $16, %ecx
movdqa (%ecx), %xmm0
pcmpeqd %xmm0, %xmm2
pcmpeqd %xmm1, %xmm0
pmovmskb %xmm2, %edx
pmovmskb %xmm0, %eax
or %eax, %edx
jz L(loop)
.p2align 4
L(matches):
pmovmskb %xmm2, %edx
test %eax, %eax
jz L(return_null)
test %edx, %edx
jz L(match_case1)
.p2align 4
L(match_case2):
test %al, %al
jz L(match_higth_case2)
test $15, %al
jnz L(match_case2_4)
test $15, %dl
jnz L(return_null)
lea 4(%ecx), %eax
ret
.p2align 4
L(match_case2_4):
mov %ecx, %eax
ret
.p2align 4
L(match_higth_case2):
test %dl, %dl
jnz L(return_null)
test $15, %ah
jnz L(match_case2_12)
test $15, %dh
jnz L(return_null)
lea 12(%ecx), %eax
ret
.p2align 4
L(match_case2_12):
lea 8(%ecx), %eax
ret
.p2align 4
L(match_case1):
test %al, %al
jz L(match_higth_case1)
test $0x01, %al
jnz L(exit0)
lea 4(%ecx), %eax
ret
.p2align 4
L(match_higth_case1):
test $0x01, %ah
jnz L(exit3)
lea 12(%ecx), %eax
ret
.p2align 4
L(exit0):
mov %ecx, %eax
ret
.p2align 4
L(exit3):
lea 8(%ecx), %eax
ret
.p2align 4
L(return_null):
xor %eax, %eax
ret
END (wcschr)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,306 @@
/*
Copyright (c) 2011 Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef USE_AS_WCSCAT
# ifndef L
# define L(label) .L##label
# endif
# ifndef cfi_startproc
# define cfi_startproc .cfi_startproc
# endif
# ifndef cfi_endproc
# define cfi_endproc .cfi_endproc
# endif
# ifndef ENTRY
# define ENTRY(name) \
.type name, @function; \
.globl name; \
.p2align 4; \
name: \
cfi_startproc
# endif
# ifndef END
# define END(name) \
cfi_endproc; \
.size name, .-name
# endif
# define PARMS 4
# define STR PARMS
# define RETURN ret
.text
ENTRY (wcslen)
mov STR(%esp), %edx
#endif
cmp $0, (%edx)
jz L(exit_tail0)
cmp $0, 4(%edx)
jz L(exit_tail1)
cmp $0, 8(%edx)
jz L(exit_tail2)
cmp $0, 12(%edx)
jz L(exit_tail3)
cmp $0, 16(%edx)
jz L(exit_tail4)
cmp $0, 20(%edx)
jz L(exit_tail5)
cmp $0, 24(%edx)
jz L(exit_tail6)
cmp $0, 28(%edx)
jz L(exit_tail7)
pxor %xmm0, %xmm0
lea 32(%edx), %eax
lea -16(%eax), %ecx
and $-16, %eax
pcmpeqd (%eax), %xmm0
pmovmskb %xmm0, %edx
pxor %xmm1, %xmm1
lea 16(%eax), %eax
test %edx, %edx
jnz L(exit)
pcmpeqd (%eax), %xmm1
pmovmskb %xmm1, %edx
pxor %xmm2, %xmm2
lea 16(%eax), %eax
test %edx, %edx
jnz L(exit)
pcmpeqd (%eax), %xmm2
pmovmskb %xmm2, %edx
pxor %xmm3, %xmm3
lea 16(%eax), %eax
test %edx, %edx
jnz L(exit)
pcmpeqd (%eax), %xmm3
pmovmskb %xmm3, %edx
lea 16(%eax), %eax
test %edx, %edx
jnz L(exit)
pcmpeqd (%eax), %xmm0
pmovmskb %xmm0, %edx
lea 16(%eax), %eax
test %edx, %edx
jnz L(exit)
pcmpeqd (%eax), %xmm1
pmovmskb %xmm1, %edx
lea 16(%eax), %eax
test %edx, %edx
jnz L(exit)
pcmpeqd (%eax), %xmm2
pmovmskb %xmm2, %edx
lea 16(%eax), %eax
test %edx, %edx
jnz L(exit)
pcmpeqd (%eax), %xmm3
pmovmskb %xmm3, %edx
lea 16(%eax), %eax
test %edx, %edx
jnz L(exit)
pcmpeqd (%eax), %xmm0
pmovmskb %xmm0, %edx
lea 16(%eax), %eax
test %edx, %edx
jnz L(exit)
pcmpeqd (%eax), %xmm1
pmovmskb %xmm1, %edx
lea 16(%eax), %eax
test %edx, %edx
jnz L(exit)
pcmpeqd (%eax), %xmm2
pmovmskb %xmm2, %edx
lea 16(%eax), %eax
test %edx, %edx
jnz L(exit)
pcmpeqd (%eax), %xmm3
pmovmskb %xmm3, %edx
lea 16(%eax), %eax
test %edx, %edx
jnz L(exit)
pcmpeqd (%eax), %xmm0
pmovmskb %xmm0, %edx
lea 16(%eax), %eax
test %edx, %edx
jnz L(exit)
pcmpeqd (%eax), %xmm1
pmovmskb %xmm1, %edx
lea 16(%eax), %eax
test %edx, %edx
jnz L(exit)
pcmpeqd (%eax), %xmm2
pmovmskb %xmm2, %edx
lea 16(%eax), %eax
test %edx, %edx
jnz L(exit)
pcmpeqd (%eax), %xmm3
pmovmskb %xmm3, %edx
lea 16(%eax), %eax
test %edx, %edx
jnz L(exit)
and $-0x40, %eax
.p2align 4
L(aligned_64_loop):
movaps (%eax), %xmm0
movaps 16(%eax), %xmm1
movaps 32(%eax), %xmm2
movaps 48(%eax), %xmm6
pminub %xmm1, %xmm0
pminub %xmm6, %xmm2
pminub %xmm0, %xmm2
pcmpeqd %xmm3, %xmm2
pmovmskb %xmm2, %edx
lea 64(%eax), %eax
test %edx, %edx
jz L(aligned_64_loop)
pcmpeqd -64(%eax), %xmm3
pmovmskb %xmm3, %edx
lea 48(%ecx), %ecx
test %edx, %edx
jnz L(exit)
pcmpeqd %xmm1, %xmm3
pmovmskb %xmm3, %edx
lea -16(%ecx), %ecx
test %edx, %edx
jnz L(exit)
pcmpeqd -32(%eax), %xmm3
pmovmskb %xmm3, %edx
lea -16(%ecx), %ecx
test %edx, %edx
jnz L(exit)
pcmpeqd %xmm6, %xmm3
pmovmskb %xmm3, %edx
lea -16(%ecx), %ecx
test %edx, %edx
jnz L(exit)
jmp L(aligned_64_loop)
.p2align 4
L(exit):
sub %ecx, %eax
shr $2, %eax
test %dl, %dl
jz L(exit_high)
mov %dl, %cl
and $15, %cl
jz L(exit_1)
RETURN
.p2align 4
L(exit_high):
mov %dh, %ch
and $15, %ch
jz L(exit_3)
add $2, %eax
RETURN
.p2align 4
L(exit_1):
add $1, %eax
RETURN
.p2align 4
L(exit_3):
add $3, %eax
RETURN
.p2align 4
L(exit_tail0):
xor %eax, %eax
RETURN
.p2align 4
L(exit_tail1):
mov $1, %eax
RETURN
.p2align 4
L(exit_tail2):
mov $2, %eax
RETURN
.p2align 4
L(exit_tail3):
mov $3, %eax
RETURN
.p2align 4
L(exit_tail4):
mov $4, %eax
RETURN
.p2align 4
L(exit_tail5):
mov $5, %eax
RETURN
.p2align 4
L(exit_tail6):
mov $6, %eax
RETURN
.p2align 4
L(exit_tail7):
mov $7, %eax
#ifndef USE_AS_WCSCAT
RETURN
END (wcslen)
#endif

View File

@@ -0,0 +1,402 @@
/*
Copyright (c) 2011 Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef L
# define L(label) .L##label
#endif
#ifndef cfi_startproc
# define cfi_startproc .cfi_startproc
#endif
#ifndef cfi_endproc
# define cfi_endproc .cfi_endproc
#endif
#ifndef cfi_rel_offset
# define cfi_rel_offset(reg, off) .cfi_rel_offset reg, off
#endif
#ifndef cfi_restore
# define cfi_restore(reg) .cfi_restore reg
#endif
#ifndef cfi_adjust_cfa_offset
# define cfi_adjust_cfa_offset(off) .cfi_adjust_cfa_offset off
#endif
#ifndef ENTRY
# define ENTRY(name) \
.type name, @function; \
.globl name; \
.p2align 4; \
name: \
cfi_startproc
#endif
#ifndef END
# define END(name) \
cfi_endproc; \
.size name, .-name
#endif
#define CFI_PUSH(REG) \
cfi_adjust_cfa_offset (4); \
cfi_rel_offset (REG, 0)
#define CFI_POP(REG) \
cfi_adjust_cfa_offset (-4); \
cfi_restore (REG)
#define PUSH(REG) pushl REG; CFI_PUSH (REG)
#define POP(REG) popl REG; CFI_POP (REG)
#define PARMS 8
#define ENTRANCE PUSH(%edi);
#define RETURN POP(%edi); ret; CFI_PUSH(%edi);
#define STR1 PARMS
#define STR2 STR1+4
.text
ENTRY (wcsrchr)
ENTRANCE
mov STR1(%esp), %ecx
movd STR2(%esp), %xmm1
mov %ecx, %edi
punpckldq %xmm1, %xmm1
pxor %xmm2, %xmm2
punpckldq %xmm1, %xmm1
/* ECX has OFFSET. */
and $63, %ecx
cmp $48, %ecx
ja L(crosscache)
/* unaligned string. */
movdqu (%edi), %xmm0
pcmpeqd %xmm0, %xmm2
pcmpeqd %xmm1, %xmm0
/* Find where NULL is. */
pmovmskb %xmm2, %ecx
/* Check if there is a match. */
pmovmskb %xmm0, %eax
add $16, %edi
test %eax, %eax
jnz L(unaligned_match1)
test %ecx, %ecx
jnz L(return_null)
and $-16, %edi
PUSH (%esi)
xor %edx, %edx
jmp L(loop)
CFI_POP (%esi)
.p2align 4
L(unaligned_match1):
test %ecx, %ecx
jnz L(prolog_find_zero_1)
PUSH (%esi)
/* Save current match */
mov %eax, %edx
mov %edi, %esi
and $-16, %edi
jmp L(loop)
CFI_POP (%esi)
.p2align 4
L(crosscache):
/* Hancle unaligned string. */
and $15, %ecx
and $-16, %edi
pxor %xmm3, %xmm3
movdqa (%edi), %xmm0
pcmpeqd %xmm0, %xmm3
pcmpeqd %xmm1, %xmm0
/* Find where NULL is. */
pmovmskb %xmm3, %edx
/* Check if there is a match. */
pmovmskb %xmm0, %eax
/* Remove the leading bytes. */
shr %cl, %edx
shr %cl, %eax
add $16, %edi
test %eax, %eax
jnz L(unaligned_match)
test %edx, %edx
jnz L(return_null)
PUSH (%esi)
xor %edx, %edx
jmp L(loop)
CFI_POP (%esi)
.p2align 4
L(unaligned_match):
test %edx, %edx
jnz L(prolog_find_zero)
PUSH (%esi)
mov %eax, %edx
lea (%edi, %ecx), %esi
/* Loop start on aligned string. */
.p2align 4
L(loop):
movdqa (%edi), %xmm0
pcmpeqd %xmm0, %xmm2
add $16, %edi
pcmpeqd %xmm1, %xmm0
pmovmskb %xmm2, %ecx
pmovmskb %xmm0, %eax
or %eax, %ecx
jnz L(matches)
movdqa (%edi), %xmm3
pcmpeqd %xmm3, %xmm2
add $16, %edi
pcmpeqd %xmm1, %xmm3
pmovmskb %xmm2, %ecx
pmovmskb %xmm3, %eax
or %eax, %ecx
jnz L(matches)
movdqa (%edi), %xmm4
pcmpeqd %xmm4, %xmm2
add $16, %edi
pcmpeqd %xmm1, %xmm4
pmovmskb %xmm2, %ecx
pmovmskb %xmm4, %eax
or %eax, %ecx
jnz L(matches)
movdqa (%edi), %xmm5
pcmpeqd %xmm5, %xmm2
add $16, %edi
pcmpeqd %xmm1, %xmm5
pmovmskb %xmm2, %ecx
pmovmskb %xmm5, %eax
or %eax, %ecx
jz L(loop)
.p2align 4
L(matches):
test %eax, %eax
jnz L(match)
L(return_value):
test %edx, %edx
jz L(return_null_1)
mov %edx, %eax
mov %esi, %edi
POP (%esi)
test %ah, %ah
jnz L(match_third_or_fourth_wchar)
test $15 << 4, %al
jnz L(match_second_wchar)
lea -16(%edi), %eax
RETURN
CFI_PUSH (%esi)
.p2align 4
L(return_null_1):
POP (%esi)
xor %eax, %eax
RETURN
CFI_PUSH (%esi)
.p2align 4
L(match):
pmovmskb %xmm2, %ecx
test %ecx, %ecx
jnz L(find_zero)
/* save match info */
mov %eax, %edx
mov %edi, %esi
jmp L(loop)
.p2align 4
L(find_zero):
test %cl, %cl
jz L(find_zero_in_third_or_fourth_wchar)
test $15, %cl
jz L(find_zero_in_second_wchar)
and $1, %eax
jz L(return_value)
POP (%esi)
lea -16(%edi), %eax
RETURN
CFI_PUSH (%esi)
.p2align 4
L(find_zero_in_second_wchar):
and $1 << 5 - 1, %eax
jz L(return_value)
POP (%esi)
test $15 << 4, %al
jnz L(match_second_wchar)
lea -16(%edi), %eax
RETURN
CFI_PUSH (%esi)
.p2align 4
L(find_zero_in_third_or_fourth_wchar):
test $15, %ch
jz L(find_zero_in_fourth_wchar)
and $1 << 9 - 1, %eax
jz L(return_value)
POP (%esi)
test %ah, %ah
jnz L(match_third_wchar)
test $15 << 4, %al
jnz L(match_second_wchar)
lea -16(%edi), %eax
RETURN
CFI_PUSH (%esi)
.p2align 4
L(find_zero_in_fourth_wchar):
POP (%esi)
test %ah, %ah
jnz L(match_third_or_fourth_wchar)
test $15 << 4, %al
jnz L(match_second_wchar)
lea -16(%edi), %eax
RETURN
CFI_PUSH (%esi)
.p2align 4
L(match_second_wchar):
lea -12(%edi), %eax
RETURN
.p2align 4
L(match_third_or_fourth_wchar):
test $15 << 4, %ah
jnz L(match_fourth_wchar)
lea -8(%edi), %eax
RETURN
.p2align 4
L(match_third_wchar):
lea -8(%edi), %eax
RETURN
.p2align 4
L(match_fourth_wchar):
lea -4(%edi), %eax
RETURN
.p2align 4
L(return_null):
xor %eax, %eax
RETURN
.p2align 4
L(prolog_find_zero):
add %ecx, %edi
mov %edx, %ecx
L(prolog_find_zero_1):
test %cl, %cl
jz L(prolog_find_zero_in_third_or_fourth_wchar)
test $15, %cl
jz L(prolog_find_zero_in_second_wchar)
and $1, %eax
jz L(return_null)
lea -16(%edi), %eax
RETURN
.p2align 4
L(prolog_find_zero_in_second_wchar):
and $1 << 5 - 1, %eax
jz L(return_null)
test $15 << 4, %al
jnz L(match_second_wchar)
lea -16(%edi), %eax
RETURN
.p2align 4
L(prolog_find_zero_in_third_or_fourth_wchar):
test $15, %ch
jz L(prolog_find_zero_in_fourth_wchar)
and $1 << 9 - 1, %eax
jz L(return_null)
test %ah, %ah
jnz L(match_third_wchar)
test $15 << 4, %al
jnz L(match_second_wchar)
lea -16(%edi), %eax
RETURN
.p2align 4
L(prolog_find_zero_in_fourth_wchar):
test %ah, %ah
jnz L(match_third_or_fourth_wchar)
test $15 << 4, %al
jnz L(match_second_wchar)
lea -16(%edi), %eax
RETURN
END (wcsrchr)

View File

@@ -28,13 +28,8 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if defined(USE_SSE2)
# define sse2_strlen_atom strlen
# include "sse2-strlen-atom.S"
#else
# include "strlen.S"
#endif
#define MEMCPY bcopy
#define USE_AS_MEMMOVE
#define USE_AS_BCOPY
#include "ssse3-memcpy-atom.S"

View File

@@ -28,8 +28,11 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "cache.h"
#undef __i686
#ifndef MEMCPY
# define MEMCPY ssse3_memcpy5
# define MEMCPY memcpy
#endif
#ifndef L

View File

@@ -28,13 +28,7 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if defined(USE_SSSE3)
# define ssse3_strcmp_latest strcmp
# include "ssse3-strcmp-latest.S"
#else
# include "strcmp.S"
#endif
#define MEMCPY memmove
#define USE_AS_MEMMOVE
#include "ssse3-memcpy-atom.S"

View File

@@ -0,0 +1,620 @@
/*
Copyright (c) 2011, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef L
# define L(label) .L##label
#endif
#ifndef cfi_startproc
# define cfi_startproc .cfi_startproc
#endif
#ifndef cfi_endproc
# define cfi_endproc .cfi_endproc
#endif
#ifndef cfi_rel_offset
# define cfi_rel_offset(reg, off) .cfi_rel_offset reg, off
#endif
#ifndef cfi_restore
# define cfi_restore(reg) .cfi_restore reg
#endif
#ifndef cfi_adjust_cfa_offset
# define cfi_adjust_cfa_offset(off) .cfi_adjust_cfa_offset off
#endif
#ifndef cfi_remember_state
# define cfi_remember_state .cfi_remember_state
#endif
#ifndef cfi_restore_state
# define cfi_restore_state .cfi_restore_state
#endif
#ifndef ENTRY
# define ENTRY(name) \
.type name, @function; \
.globl name; \
.p2align 4; \
name: \
cfi_startproc
#endif
#ifndef END
# define END(name) \
cfi_endproc; \
.size name, .-name
#endif
#define CFI_PUSH(REG) \
cfi_adjust_cfa_offset (4); \
cfi_rel_offset (REG, 0)
#define CFI_POP(REG) \
cfi_adjust_cfa_offset (-4); \
cfi_restore (REG)
#define PUSH(REG) pushl REG; CFI_PUSH (REG)
#define POP(REG) popl REG; CFI_POP (REG)
#ifndef STRCAT
# define STRCAT strcat
#endif
#define PARMS 4
#define STR1 PARMS+4
#define STR2 STR1+4
#ifdef USE_AS_STRNCAT
# define LEN STR2+8
#endif
#define USE_AS_STRCAT
.section .text.ssse3,"ax",@progbits
ENTRY (STRCAT)
PUSH (%edi)
mov STR1(%esp), %edi
mov %edi, %edx
#define RETURN jmp L(StrcpyAtom)
#include "sse2-strlen-atom.S"
L(StrcpyAtom):
mov STR2(%esp), %ecx
lea (%edi, %eax), %edx
#ifdef USE_AS_STRNCAT
PUSH (%ebx)
mov LEN(%esp), %ebx
test %ebx, %ebx
jz L(StrncatExit0)
cmp $8, %ebx
jbe L(StrncpyExit8Bytes)
#endif
cmpb $0, (%ecx)
jz L(Exit1)
cmpb $0, 1(%ecx)
jz L(Exit2)
cmpb $0, 2(%ecx)
jz L(Exit3)
cmpb $0, 3(%ecx)
jz L(Exit4)
cmpb $0, 4(%ecx)
jz L(Exit5)
cmpb $0, 5(%ecx)
jz L(Exit6)
cmpb $0, 6(%ecx)
jz L(Exit7)
cmpb $0, 7(%ecx)
jz L(Exit8)
cmpb $0, 8(%ecx)
jz L(Exit9)
#ifdef USE_AS_STRNCAT
cmp $16, %ebx
jb L(StrncpyExit15Bytes)
#endif
cmpb $0, 9(%ecx)
jz L(Exit10)
cmpb $0, 10(%ecx)
jz L(Exit11)
cmpb $0, 11(%ecx)
jz L(Exit12)
cmpb $0, 12(%ecx)
jz L(Exit13)
cmpb $0, 13(%ecx)
jz L(Exit14)
cmpb $0, 14(%ecx)
jz L(Exit15)
cmpb $0, 15(%ecx)
jz L(Exit16)
#ifdef USE_AS_STRNCAT
cmp $16, %ebx
je L(StrncatExit16)
# define RETURN1 POP (%ebx); POP (%edi); ret; \
CFI_PUSH (%ebx); CFI_PUSH (%edi)
# define USE_AS_STRNCPY
#else
# define RETURN1 POP(%edi); ret; CFI_PUSH(%edi)
#endif
#include "ssse3-strcpy-atom.S"
.p2align 4
L(CopyFrom1To16Bytes):
add %esi, %edx
add %esi, %ecx
POP (%esi)
test %al, %al
jz L(ExitHigh)
test $0x01, %al
jnz L(Exit1)
test $0x02, %al
jnz L(Exit2)
test $0x04, %al
jnz L(Exit3)
test $0x08, %al
jnz L(Exit4)
test $0x10, %al
jnz L(Exit5)
test $0x20, %al
jnz L(Exit6)
test $0x40, %al
jnz L(Exit7)
movlpd (%ecx), %xmm0
movlpd %xmm0, (%edx)
movl %edi, %eax
RETURN1
.p2align 4
L(ExitHigh):
test $0x01, %ah
jnz L(Exit9)
test $0x02, %ah
jnz L(Exit10)
test $0x04, %ah
jnz L(Exit11)
test $0x08, %ah
jnz L(Exit12)
test $0x10, %ah
jnz L(Exit13)
test $0x20, %ah
jnz L(Exit14)
test $0x40, %ah
jnz L(Exit15)
movlpd (%ecx), %xmm0
movlpd 8(%ecx), %xmm1
movlpd %xmm0, (%edx)
movlpd %xmm1, 8(%edx)
movl %edi, %eax
RETURN1
.p2align 4
L(StrncatExit1):
movb %bh, 1(%edx)
L(Exit1):
movb (%ecx), %al
movb %al, (%edx)
movl %edi, %eax
RETURN1
.p2align 4
L(StrncatExit2):
movb %bh, 2(%edx)
L(Exit2):
movw (%ecx), %ax
movw %ax, (%edx)
movl %edi, %eax
RETURN1
.p2align 4
L(StrncatExit3):
movb %bh, 3(%edx)
L(Exit3):
movw (%ecx), %ax
movw %ax, (%edx)
movb 2(%ecx), %al
movb %al, 2(%edx)
movl %edi, %eax
RETURN1
.p2align 4
L(StrncatExit4):
movb %bh, 4(%edx)
L(Exit4):
movl (%ecx), %eax
movl %eax, (%edx)
movl %edi, %eax
RETURN1
.p2align 4
L(StrncatExit5):
movb %bh, 5(%edx)
L(Exit5):
movl (%ecx), %eax
movl %eax, (%edx)
movb 4(%ecx), %al
movb %al, 4(%edx)
movl %edi, %eax
RETURN1
.p2align 4
L(StrncatExit6):
movb %bh, 6(%edx)
L(Exit6):
movl (%ecx), %eax
movl %eax, (%edx)
movw 4(%ecx), %ax
movw %ax, 4(%edx)
movl %edi, %eax
RETURN1
.p2align 4
L(StrncatExit7):
movb %bh, 7(%edx)
L(Exit7):
movl (%ecx), %eax
movl %eax, (%edx)
movl 3(%ecx), %eax
movl %eax, 3(%edx)
movl %edi, %eax
RETURN1
.p2align 4
L(StrncatExit8):
movb %bh, 8(%edx)
L(Exit8):
movlpd (%ecx), %xmm0
movlpd %xmm0, (%edx)
movl %edi, %eax
RETURN1
.p2align 4
L(StrncatExit9):
movb %bh, 9(%edx)
L(Exit9):
movlpd (%ecx), %xmm0
movlpd %xmm0, (%edx)
movb 8(%ecx), %al
movb %al, 8(%edx)
movl %edi, %eax
RETURN1
.p2align 4
L(StrncatExit10):
movb %bh, 10(%edx)
L(Exit10):
movlpd (%ecx), %xmm0
movlpd %xmm0, (%edx)
movw 8(%ecx), %ax
movw %ax, 8(%edx)
movl %edi, %eax
RETURN1
.p2align 4
L(StrncatExit11):
movb %bh, 11(%edx)
L(Exit11):
movlpd (%ecx), %xmm0
movlpd %xmm0, (%edx)
movl 7(%ecx), %eax
movl %eax, 7(%edx)
movl %edi, %eax
RETURN1
.p2align 4
L(StrncatExit12):
movb %bh, 12(%edx)
L(Exit12):
movlpd (%ecx), %xmm0
movlpd %xmm0, (%edx)
movl 8(%ecx), %eax
movl %eax, 8(%edx)
movl %edi, %eax
RETURN1
.p2align 4
L(StrncatExit13):
movb %bh, 13(%edx)
L(Exit13):
movlpd (%ecx), %xmm0
movlpd %xmm0, (%edx)
movlpd 5(%ecx), %xmm0
movlpd %xmm0, 5(%edx)
movl %edi, %eax
RETURN1
.p2align 4
L(StrncatExit14):
movb %bh, 14(%edx)
L(Exit14):
movlpd (%ecx), %xmm0
movlpd %xmm0, (%edx)
movlpd 6(%ecx), %xmm0
movlpd %xmm0, 6(%edx)
movl %edi, %eax
RETURN1
.p2align 4
L(StrncatExit15):
movb %bh, 15(%edx)
L(Exit15):
movlpd (%ecx), %xmm0
movlpd %xmm0, (%edx)
movlpd 7(%ecx), %xmm0
movlpd %xmm0, 7(%edx)
movl %edi, %eax
RETURN1
.p2align 4
L(StrncatExit16):
movb %bh, 16(%edx)
L(Exit16):
movlpd (%ecx), %xmm0
movlpd 8(%ecx), %xmm1
movlpd %xmm0, (%edx)
movlpd %xmm1, 8(%edx)
movl %edi, %eax
RETURN1
#ifdef USE_AS_STRNCPY
CFI_PUSH(%esi)
.p2align 4
L(CopyFrom1To16BytesCase2):
add $16, %ebx
add %esi, %ecx
lea (%esi, %edx), %esi
lea -9(%ebx), %edx
and $1<<7, %dh
or %al, %dh
lea (%esi), %edx
POP (%esi)
jz L(ExitHighCase2)
test $0x01, %al
jnz L(Exit1)
cmp $1, %ebx
je L(StrncatExit1)
test $0x02, %al
jnz L(Exit2)
cmp $2, %ebx
je L(StrncatExit2)
test $0x04, %al
jnz L(Exit3)
cmp $3, %ebx
je L(StrncatExit3)
test $0x08, %al
jnz L(Exit4)
cmp $4, %ebx
je L(StrncatExit4)
test $0x10, %al
jnz L(Exit5)
cmp $5, %ebx
je L(StrncatExit5)
test $0x20, %al
jnz L(Exit6)
cmp $6, %ebx
je L(StrncatExit6)
test $0x40, %al
jnz L(Exit7)
cmp $7, %ebx
je L(StrncatExit7)
movlpd (%ecx), %xmm0
movlpd %xmm0, (%edx)
lea 7(%edx), %eax
cmpb $1, (%eax)
sbb $-1, %eax
xor %cl, %cl
movb %cl, (%eax)
movl %edi, %eax
RETURN1
.p2align 4
L(ExitHighCase2):
test $0x01, %ah
jnz L(Exit9)
cmp $9, %ebx
je L(StrncatExit9)
test $0x02, %ah
jnz L(Exit10)
cmp $10, %ebx
je L(StrncatExit10)
test $0x04, %ah
jnz L(Exit11)
cmp $11, %ebx
je L(StrncatExit11)
test $0x8, %ah
jnz L(Exit12)
cmp $12, %ebx
je L(StrncatExit12)
test $0x10, %ah
jnz L(Exit13)
cmp $13, %ebx
je L(StrncatExit13)
test $0x20, %ah
jnz L(Exit14)
cmp $14, %ebx
je L(StrncatExit14)
test $0x40, %ah
jnz L(Exit15)
cmp $15, %ebx
je L(StrncatExit15)
movlpd (%ecx), %xmm0
movlpd %xmm0, (%edx)
movlpd 8(%ecx), %xmm1
movlpd %xmm1, 8(%edx)
movl %edi, %eax
RETURN1
CFI_PUSH(%esi)
L(CopyFrom1To16BytesCase2OrCase3):
test %eax, %eax
jnz L(CopyFrom1To16BytesCase2)
.p2align 4
L(CopyFrom1To16BytesCase3):
add $16, %ebx
add %esi, %edx
add %esi, %ecx
POP (%esi)
cmp $8, %ebx
ja L(ExitHighCase3)
cmp $1, %ebx
je L(StrncatExit1)
cmp $2, %ebx
je L(StrncatExit2)
cmp $3, %ebx
je L(StrncatExit3)
cmp $4, %ebx
je L(StrncatExit4)
cmp $5, %ebx
je L(StrncatExit5)
cmp $6, %ebx
je L(StrncatExit6)
cmp $7, %ebx
je L(StrncatExit7)
movlpd (%ecx), %xmm0
movlpd %xmm0, (%edx)
movb %bh, 8(%edx)
movl %edi, %eax
RETURN1
.p2align 4
L(ExitHighCase3):
cmp $9, %ebx
je L(StrncatExit9)
cmp $10, %ebx
je L(StrncatExit10)
cmp $11, %ebx
je L(StrncatExit11)
cmp $12, %ebx
je L(StrncatExit12)
cmp $13, %ebx
je L(StrncatExit13)
cmp $14, %ebx
je L(StrncatExit14)
cmp $15, %ebx
je L(StrncatExit15)
movlpd (%ecx), %xmm0
movlpd %xmm0, (%edx)
movlpd 8(%ecx), %xmm1
movlpd %xmm1, 8(%edx)
movb %bh, 16(%edx)
movl %edi, %eax
RETURN1
.p2align 4
L(StrncatExit0):
movl %edi, %eax
RETURN1
.p2align 4
L(StrncpyExit15Bytes):
cmp $9, %ebx
je L(StrncatExit9)
cmpb $0, 9(%ecx)
jz L(Exit10)
cmp $10, %ebx
je L(StrncatExit10)
cmpb $0, 10(%ecx)
jz L(Exit11)
cmp $11, %ebx
je L(StrncatExit11)
cmpb $0, 11(%ecx)
jz L(Exit12)
cmp $12, %ebx
je L(StrncatExit12)
cmpb $0, 12(%ecx)
jz L(Exit13)
cmp $13, %ebx
je L(StrncatExit13)
cmpb $0, 13(%ecx)
jz L(Exit14)
cmp $14, %ebx
je L(StrncatExit14)
movlpd (%ecx), %xmm0
movlpd %xmm0, (%edx)
movlpd 7(%ecx), %xmm0
movlpd %xmm0, 7(%edx)
lea 14(%edx), %eax
cmpb $1, (%eax)
sbb $-1, %eax
movb %bh, (%eax)
movl %edi, %eax
RETURN1
.p2align 4
L(StrncpyExit8Bytes):
cmpb $0, (%ecx)
jz L(Exit1)
cmp $1, %ebx
je L(StrncatExit1)
cmpb $0, 1(%ecx)
jz L(Exit2)
cmp $2, %ebx
je L(StrncatExit2)
cmpb $0, 2(%ecx)
jz L(Exit3)
cmp $3, %ebx
je L(StrncatExit3)
cmpb $0, 3(%ecx)
jz L(Exit4)
cmp $4, %ebx
je L(StrncatExit4)
cmpb $0, 4(%ecx)
jz L(Exit5)
cmp $5, %ebx
je L(StrncatExit5)
cmpb $0, 5(%ecx)
jz L(Exit6)
cmp $6, %ebx
je L(StrncatExit6)
cmpb $0, 6(%ecx)
jz L(Exit7)
cmp $7, %ebx
je L(StrncatExit7)
movlpd (%ecx), %xmm0
movlpd %xmm0, (%edx)
lea 7(%edx), %eax
cmpb $1, (%eax)
sbb $-1, %eax
movb %bh, (%eax)
movl %edi, %eax
RETURN1
#endif
END (STRCAT)

View File

@@ -107,8 +107,12 @@ name: \
sub %esi, %ebp
#endif
#ifndef STRCMP
# define STRCMP strcmp
#endif
.section .text.ssse3,"ax",@progbits
ENTRY (ssse3_strcmp_latest)
ENTRY (STRCMP)
#ifdef USE_AS_STRNCMP
PUSH (%ebp)
#endif
@@ -2271,4 +2275,4 @@ L(less16bytes_sncmp):
ret
#endif
END (ssse3_strcmp_latest)
END (STRCMP)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,34 @@
/*
Copyright (c) 2011, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#define STRCAT strncat
#define USE_AS_STRNCAT
#include "ssse3-strcat-atom.S"

View File

@@ -28,13 +28,8 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if defined(USE_SSSE3)
# define MEMCMP memcmp
# include "ssse3-memcmp3-new.S"
#define USE_AS_STRNCMP
#define STRCMP strncmp
#include "ssse3-strcmp-atom.S"
#else
# include "memcmp.S"
#endif

View File

@@ -0,0 +1,33 @@
/*
Copyright (c) 2011, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#define USE_AS_STRNCPY
#define STRCPY strncpy
#include "ssse3-strcpy-atom.S"

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2010, Intel Corporation
Copyright (c) 2011 Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -28,18 +28,87 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if defined(USE_SSSE3)
# include "cache_wrapper.S"
# undef __i686
# define MEMCPY bcopy
# define USE_AS_MEMMOVE
# define USE_AS_BCOPY
# include "ssse3-memcpy5.S"
#else
# include "bcopy.S"
#ifndef L
# define L(label) .L##label
#endif
#ifndef cfi_startproc
# define cfi_startproc .cfi_startproc
#endif
#ifndef cfi_endproc
# define cfi_endproc .cfi_endproc
#endif
#ifndef cfi_rel_offset
# define cfi_rel_offset(reg, off) .cfi_rel_offset reg, off
#endif
#ifndef cfi_restore
# define cfi_restore(reg) .cfi_restore reg
#endif
#ifndef cfi_adjust_cfa_offset
# define cfi_adjust_cfa_offset(off) .cfi_adjust_cfa_offset off
#endif
#ifndef ENTRY
# define ENTRY(name) \
.type name, @function; \
.globl name; \
.p2align 4; \
name: \
cfi_startproc
#endif
#ifndef END
# define END(name) \
cfi_endproc; \
.size name, .-name
#endif
#define CFI_PUSH(REG) \
cfi_adjust_cfa_offset (4); \
cfi_rel_offset (REG, 0)
#define CFI_POP(REG) \
cfi_adjust_cfa_offset (-4); \
cfi_restore (REG)
#define PUSH(REG) pushl REG; CFI_PUSH (REG)
#define POP(REG) popl REG; CFI_POP (REG)
#define PARMS 4
#define STR1 PARMS+4
#define STR2 STR1+4
#define USE_AS_WCSCAT
.text
ENTRY (wcscat)
PUSH (%edi)
mov STR1(%esp), %edi
mov %edi, %edx
#define RETURN jmp L(WcscpyAtom)
#include "sse2-wcslen-atom.S"
L(WcscpyAtom):
shl $2, %eax
mov STR2(%esp), %ecx
lea (%edi, %eax), %edx
cmp $0, (%ecx)
jz L(Exit4)
cmp $0, 4(%ecx)
jz L(Exit8)
cmp $0, 8(%ecx)
jz L(Exit12)
cmp $0, 12(%ecx)
jz L(Exit16)
#undef RETURN
#define RETURN POP(%edi); ret; CFI_PUSH(%edi)
#include "ssse3-wcscpy-atom.S"
END (wcscat)

View File

@@ -0,0 +1,652 @@
/*
Copyright (c) 2011, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef USE_AS_WCSCAT
# ifndef L
# define L(label) .L##label
# endif
# ifndef cfi_startproc
# define cfi_startproc .cfi_startproc
# endif
# ifndef cfi_endproc
# define cfi_endproc .cfi_endproc
# endif
# ifndef cfi_rel_offset
# define cfi_rel_offset(reg, off) .cfi_rel_offset reg, off
# endif
# ifndef cfi_restore
# define cfi_restore(reg) .cfi_restore reg
# endif
# ifndef cfi_adjust_cfa_offset
# define cfi_adjust_cfa_offset(off) .cfi_adjust_cfa_offset off
# endif
# ifndef ENTRY
# define ENTRY(name) \
.type name, @function; \
.globl name; \
.p2align 4; \
name: \
cfi_startproc
# endif
# ifndef END
# define END(name) \
cfi_endproc; \
.size name, .-name
# endif
# define CFI_PUSH(REG) \
cfi_adjust_cfa_offset (4); \
cfi_rel_offset (REG, 0)
# define CFI_POP(REG) \
cfi_adjust_cfa_offset (-4); \
cfi_restore (REG)
# define PUSH(REG) pushl REG; CFI_PUSH (REG)
# define POP(REG) popl REG; CFI_POP (REG)
# define PARMS 4
# define RETURN POP (%edi); ret; CFI_PUSH (%edi)
# define STR1 PARMS
# define STR2 STR1+4
# define LEN STR2+4
.text
ENTRY (wcscpy)
mov STR1(%esp), %edx
mov STR2(%esp), %ecx
cmp $0, (%ecx)
jz L(ExitTail4)
cmp $0, 4(%ecx)
jz L(ExitTail8)
cmp $0, 8(%ecx)
jz L(ExitTail12)
cmp $0, 12(%ecx)
jz L(ExitTail16)
PUSH (%edi)
mov %edx, %edi
#endif
PUSH (%esi)
lea 16(%ecx), %esi
and $-16, %esi
pxor %xmm0, %xmm0
pcmpeqd (%esi), %xmm0
movdqu (%ecx), %xmm1
movdqu %xmm1, (%edx)
pmovmskb %xmm0, %eax
sub %ecx, %esi
test %eax, %eax
jnz L(CopyFrom1To16Bytes)
mov %edx, %eax
lea 16(%edx), %edx
and $-16, %edx
sub %edx, %eax
sub %eax, %ecx
mov %ecx, %eax
and $0xf, %eax
mov $0, %esi
jz L(Align16Both)
cmp $4, %eax
je L(Shl4)
cmp $8, %eax
je L(Shl8)
jmp L(Shl12)
L(Align16Both):
movaps (%ecx), %xmm1
movaps 16(%ecx), %xmm2
movaps %xmm1, (%edx)
pcmpeqd %xmm2, %xmm0
pmovmskb %xmm0, %eax
lea 16(%esi), %esi
test %eax, %eax
jnz L(CopyFrom1To16Bytes)
movaps 16(%ecx, %esi), %xmm3
movaps %xmm2, (%edx, %esi)
pcmpeqd %xmm3, %xmm0
pmovmskb %xmm0, %eax
lea 16(%esi), %esi
test %eax, %eax
jnz L(CopyFrom1To16Bytes)
movaps 16(%ecx, %esi), %xmm4
movaps %xmm3, (%edx, %esi)
pcmpeqd %xmm4, %xmm0
pmovmskb %xmm0, %eax
lea 16(%esi), %esi
test %eax, %eax
jnz L(CopyFrom1To16Bytes)
movaps 16(%ecx, %esi), %xmm1
movaps %xmm4, (%edx, %esi)
pcmpeqd %xmm1, %xmm0
pmovmskb %xmm0, %eax
lea 16(%esi), %esi
test %eax, %eax
jnz L(CopyFrom1To16Bytes)
movaps 16(%ecx, %esi), %xmm2
movaps %xmm1, (%edx, %esi)
pcmpeqd %xmm2, %xmm0
pmovmskb %xmm0, %eax
lea 16(%esi), %esi
test %eax, %eax
jnz L(CopyFrom1To16Bytes)
movaps 16(%ecx, %esi), %xmm3
movaps %xmm2, (%edx, %esi)
pcmpeqd %xmm3, %xmm0
pmovmskb %xmm0, %eax
lea 16(%esi), %esi
test %eax, %eax
jnz L(CopyFrom1To16Bytes)
movaps %xmm3, (%edx, %esi)
mov %ecx, %eax
lea 16(%ecx, %esi), %ecx
and $-0x40, %ecx
sub %ecx, %eax
sub %eax, %edx
mov $-0x40, %esi
L(Aligned64Loop):
movaps (%ecx), %xmm2
movaps 32(%ecx), %xmm3
movaps %xmm2, %xmm4
movaps 16(%ecx), %xmm5
movaps %xmm3, %xmm6
movaps 48(%ecx), %xmm7
pminub %xmm5, %xmm2
pminub %xmm7, %xmm3
pminub %xmm2, %xmm3
lea 64(%edx), %edx
pcmpeqd %xmm0, %xmm3
lea 64(%ecx), %ecx
pmovmskb %xmm3, %eax
test %eax, %eax
jnz L(Aligned64Leave)
movaps %xmm4, -64(%edx)
movaps %xmm5, -48(%edx)
movaps %xmm6, -32(%edx)
movaps %xmm7, -16(%edx)
jmp L(Aligned64Loop)
L(Aligned64Leave):
pcmpeqd %xmm4, %xmm0
pmovmskb %xmm0, %eax
test %eax, %eax
jnz L(CopyFrom1To16Bytes)
pcmpeqd %xmm5, %xmm0
pmovmskb %xmm0, %eax
movaps %xmm4, -64(%edx)
lea 16(%esi), %esi
test %eax, %eax
jnz L(CopyFrom1To16Bytes)
pcmpeqd %xmm6, %xmm0
pmovmskb %xmm0, %eax
movaps %xmm5, -48(%edx)
lea 16(%esi), %esi
test %eax, %eax
jnz L(CopyFrom1To16Bytes)
movaps %xmm6, -32(%edx)
pcmpeqd %xmm7, %xmm0
pmovmskb %xmm0, %eax
lea 16(%esi), %esi
test %eax, %eax
jnz L(CopyFrom1To16Bytes)
mov $-0x40, %esi
movaps %xmm7, -16(%edx)
jmp L(Aligned64Loop)
.p2align 4
L(Shl4):
movaps -4(%ecx), %xmm1
movaps 12(%ecx), %xmm2
L(Shl4Start):
pcmpeqd %xmm2, %xmm0
pmovmskb %xmm0, %eax
movaps %xmm2, %xmm3
test %eax, %eax
jnz L(Shl4LoopExit)
palignr $4, %xmm1, %xmm2
movaps %xmm2, (%edx)
movaps 28(%ecx), %xmm2
pcmpeqd %xmm2, %xmm0
lea 16(%edx), %edx
pmovmskb %xmm0, %eax
lea 16(%ecx), %ecx
movaps %xmm2, %xmm1
test %eax, %eax
jnz L(Shl4LoopExit)
palignr $4, %xmm3, %xmm2
movaps %xmm2, (%edx)
movaps 28(%ecx), %xmm2
pcmpeqd %xmm2, %xmm0
lea 16(%edx), %edx
pmovmskb %xmm0, %eax
lea 16(%ecx), %ecx
movaps %xmm2, %xmm3
test %eax, %eax
jnz L(Shl4LoopExit)
palignr $4, %xmm1, %xmm2
movaps %xmm2, (%edx)
movaps 28(%ecx), %xmm2
pcmpeqd %xmm2, %xmm0
lea 16(%edx), %edx
pmovmskb %xmm0, %eax
lea 16(%ecx), %ecx
test %eax, %eax
jnz L(Shl4LoopExit)
palignr $4, %xmm3, %xmm2
movaps %xmm2, (%edx)
lea 28(%ecx), %ecx
lea 16(%edx), %edx
mov %ecx, %eax
and $-0x40, %ecx
sub %ecx, %eax
lea -12(%ecx), %ecx
sub %eax, %edx
movaps -4(%ecx), %xmm1
L(Shl4LoopStart):
movaps 12(%ecx), %xmm2
movaps 28(%ecx), %xmm3
movaps %xmm3, %xmm6
movaps 44(%ecx), %xmm4
movaps %xmm4, %xmm7
movaps 60(%ecx), %xmm5
pminub %xmm2, %xmm6
pminub %xmm5, %xmm7
pminub %xmm6, %xmm7
pcmpeqd %xmm0, %xmm7
pmovmskb %xmm7, %eax
movaps %xmm5, %xmm7
palignr $4, %xmm4, %xmm5
palignr $4, %xmm3, %xmm4
test %eax, %eax
jnz L(Shl4Start)
palignr $4, %xmm2, %xmm3
lea 64(%ecx), %ecx
palignr $4, %xmm1, %xmm2
movaps %xmm7, %xmm1
movaps %xmm5, 48(%edx)
movaps %xmm4, 32(%edx)
movaps %xmm3, 16(%edx)
movaps %xmm2, (%edx)
lea 64(%edx), %edx
jmp L(Shl4LoopStart)
L(Shl4LoopExit):
movlpd (%ecx), %xmm0
movl 8(%ecx), %esi
movlpd %xmm0, (%edx)
movl %esi, 8(%edx)
POP (%esi)
add $12, %edx
add $12, %ecx
test %al, %al
jz L(ExitHigh)
test $0x01, %al
jnz L(Exit4)
movlpd (%ecx), %xmm0
movlpd %xmm0, (%edx)
movl %edi, %eax
RETURN
CFI_PUSH (%esi)
.p2align 4
L(Shl8):
movaps -8(%ecx), %xmm1
movaps 8(%ecx), %xmm2
L(Shl8Start):
pcmpeqd %xmm2, %xmm0
pmovmskb %xmm0, %eax
movaps %xmm2, %xmm3
test %eax, %eax
jnz L(Shl8LoopExit)
palignr $8, %xmm1, %xmm2
movaps %xmm2, (%edx)
movaps 24(%ecx), %xmm2
pcmpeqd %xmm2, %xmm0
lea 16(%edx), %edx
pmovmskb %xmm0, %eax
lea 16(%ecx), %ecx
movaps %xmm2, %xmm1
test %eax, %eax
jnz L(Shl8LoopExit)
palignr $8, %xmm3, %xmm2
movaps %xmm2, (%edx)
movaps 24(%ecx), %xmm2
pcmpeqd %xmm2, %xmm0
lea 16(%edx), %edx
pmovmskb %xmm0, %eax
lea 16(%ecx), %ecx
movaps %xmm2, %xmm3
test %eax, %eax
jnz L(Shl8LoopExit)
palignr $8, %xmm1, %xmm2
movaps %xmm2, (%edx)
movaps 24(%ecx), %xmm2
pcmpeqd %xmm2, %xmm0
lea 16(%edx), %edx
pmovmskb %xmm0, %eax
lea 16(%ecx), %ecx
test %eax, %eax
jnz L(Shl8LoopExit)
palignr $8, %xmm3, %xmm2
movaps %xmm2, (%edx)
lea 24(%ecx), %ecx
lea 16(%edx), %edx
mov %ecx, %eax
and $-0x40, %ecx
sub %ecx, %eax
lea -8(%ecx), %ecx
sub %eax, %edx
movaps -8(%ecx), %xmm1
L(Shl8LoopStart):
movaps 8(%ecx), %xmm2
movaps 24(%ecx), %xmm3
movaps %xmm3, %xmm6
movaps 40(%ecx), %xmm4
movaps %xmm4, %xmm7
movaps 56(%ecx), %xmm5
pminub %xmm2, %xmm6
pminub %xmm5, %xmm7
pminub %xmm6, %xmm7
pcmpeqd %xmm0, %xmm7
pmovmskb %xmm7, %eax
movaps %xmm5, %xmm7
palignr $8, %xmm4, %xmm5
palignr $8, %xmm3, %xmm4
test %eax, %eax
jnz L(Shl8Start)
palignr $8, %xmm2, %xmm3
lea 64(%ecx), %ecx
palignr $8, %xmm1, %xmm2
movaps %xmm7, %xmm1
movaps %xmm5, 48(%edx)
movaps %xmm4, 32(%edx)
movaps %xmm3, 16(%edx)
movaps %xmm2, (%edx)
lea 64(%edx), %edx
jmp L(Shl8LoopStart)
L(Shl8LoopExit):
movlpd (%ecx), %xmm0
movlpd %xmm0, (%edx)
POP (%esi)
add $8, %edx
add $8, %ecx
test %al, %al
jz L(ExitHigh)
test $0x01, %al
jnz L(Exit4)
movlpd (%ecx), %xmm0
movlpd %xmm0, (%edx)
movl %edi, %eax
RETURN
CFI_PUSH (%esi)
.p2align 4
L(Shl12):
movaps -12(%ecx), %xmm1
movaps 4(%ecx), %xmm2
L(Shl12Start):
pcmpeqd %xmm2, %xmm0
pmovmskb %xmm0, %eax
movaps %xmm2, %xmm3
test %eax, %eax
jnz L(Shl12LoopExit)
palignr $12, %xmm1, %xmm2
movaps %xmm2, (%edx)
movaps 20(%ecx), %xmm2
pcmpeqd %xmm2, %xmm0
lea 16(%edx), %edx
pmovmskb %xmm0, %eax
lea 16(%ecx), %ecx
movaps %xmm2, %xmm1
test %eax, %eax
jnz L(Shl12LoopExit)
palignr $12, %xmm3, %xmm2
movaps %xmm2, (%edx)
movaps 20(%ecx), %xmm2
pcmpeqd %xmm2, %xmm0
lea 16(%edx), %edx
pmovmskb %xmm0, %eax
lea 16(%ecx), %ecx
movaps %xmm2, %xmm3
test %eax, %eax
jnz L(Shl12LoopExit)
palignr $12, %xmm1, %xmm2
movaps %xmm2, (%edx)
movaps 20(%ecx), %xmm2
pcmpeqd %xmm2, %xmm0
lea 16(%edx), %edx
pmovmskb %xmm0, %eax
lea 16(%ecx), %ecx
test %eax, %eax
jnz L(Shl12LoopExit)
palignr $12, %xmm3, %xmm2
movaps %xmm2, (%edx)
lea 20(%ecx), %ecx
lea 16(%edx), %edx
mov %ecx, %eax
and $-0x40, %ecx
sub %ecx, %eax
lea -4(%ecx), %ecx
sub %eax, %edx
movaps -12(%ecx), %xmm1
L(Shl12LoopStart):
movaps 4(%ecx), %xmm2
movaps 20(%ecx), %xmm3
movaps %xmm3, %xmm6
movaps 36(%ecx), %xmm4
movaps %xmm4, %xmm7
movaps 52(%ecx), %xmm5
pminub %xmm2, %xmm6
pminub %xmm5, %xmm7
pminub %xmm6, %xmm7
pcmpeqd %xmm0, %xmm7
pmovmskb %xmm7, %eax
movaps %xmm5, %xmm7
palignr $12, %xmm4, %xmm5
palignr $12, %xmm3, %xmm4
test %eax, %eax
jnz L(Shl12Start)
palignr $12, %xmm2, %xmm3
lea 64(%ecx), %ecx
palignr $12, %xmm1, %xmm2
movaps %xmm7, %xmm1
movaps %xmm5, 48(%edx)
movaps %xmm4, 32(%edx)
movaps %xmm3, 16(%edx)
movaps %xmm2, (%edx)
lea 64(%edx), %edx
jmp L(Shl12LoopStart)
L(Shl12LoopExit):
movl (%ecx), %esi
movl %esi, (%edx)
mov $4, %esi
.p2align 4
L(CopyFrom1To16Bytes):
add %esi, %edx
add %esi, %ecx
POP (%esi)
test %al, %al
jz L(ExitHigh)
test $0x01, %al
jnz L(Exit4)
L(Exit8):
movlpd (%ecx), %xmm0
movlpd %xmm0, (%edx)
movl %edi, %eax
RETURN
.p2align 4
L(ExitHigh):
test $0x01, %ah
jnz L(Exit12)
L(Exit16):
movdqu (%ecx), %xmm0
movdqu %xmm0, (%edx)
movl %edi, %eax
RETURN
.p2align 4
L(Exit4):
movl (%ecx), %eax
movl %eax, (%edx)
movl %edi, %eax
RETURN
.p2align 4
L(Exit12):
movlpd (%ecx), %xmm0
movlpd %xmm0, (%edx)
movl 8(%ecx), %eax
movl %eax, 8(%edx)
movl %edi, %eax
RETURN
CFI_POP (%edi)
.p2align 4
L(ExitTail4):
movl (%ecx), %eax
movl %eax, (%edx)
movl %edx, %eax
ret
.p2align 4
L(ExitTail8):
movlpd (%ecx), %xmm0
movlpd %xmm0, (%edx)
movl %edx, %eax
ret
.p2align 4
L(ExitTail12):
movlpd (%ecx), %xmm0
movlpd %xmm0, (%edx)
movl 8(%ecx), %eax
movl %eax, 8(%edx)
movl %edx, %eax
ret
.p2align 4
L(ExitTail16):
movdqu (%ecx), %xmm0
movdqu %xmm0, (%edx)
movl %edx, %eax
ret
#ifndef USE_AS_WCSCAT
END (wcscpy)
#endif

View File

@@ -0,0 +1,33 @@
/*
Copyright (c) 2011, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#define MEMCMP wmemcmp
#define USE_AS_WMEMCMP 1
#include "ssse3-memcmp-atom.S"

View File

@@ -1,3 +0,0 @@
/* $OpenBSD: strchr.S,v 1.3 2005/08/07 11:30:38 espie Exp $ */
#define STRCHR
#include "index.S"

View File

@@ -1,64 +0,0 @@
/* $OpenBSD: strcpy.S,v 1.8 2005/08/07 11:30:38 espie Exp $ */
/*
* Written by J.T. Conklin <jtc@netbsd.org>.
* Public domain.
*/
#include <machine/asm.h>
#if defined(APIWARN)
#APP
.section .gnu.warning.strcpy
.ascii "warning: strcpy() is almost always misused, please use strlcpy()"
#NO_APP
#endif
/*
* NOTE: I've unrolled the loop eight times: large enough to make a
* significant difference, and small enough not to totally trash the
* cache.
*/
ENTRY(strcpy)
movl 4(%esp),%ecx /* dst address */
movl 8(%esp),%edx /* src address */
pushl %ecx /* push dst address */
.align 2,0x90
L1: movb (%edx),%al /* unroll loop, but not too much */
movb %al,(%ecx)
testb %al,%al
jz L2
movb 1(%edx),%al
movb %al,1(%ecx)
testb %al,%al
jz L2
movb 2(%edx),%al
movb %al,2(%ecx)
testb %al,%al
jz L2
movb 3(%edx),%al
movb %al,3(%ecx)
testb %al,%al
jz L2
movb 4(%edx),%al
movb %al,4(%ecx)
testb %al,%al
jz L2
movb 5(%edx),%al
movb %al,5(%ecx)
testb %al,%al
jz L2
movb 6(%edx),%al
movb %al,6(%ecx)
testb %al,%al
jz L2
movb 7(%edx),%al
movb %al,7(%ecx)
addl $8,%edx
addl $8,%ecx
testb %al,%al
jnz L1
L2: popl %eax /* pop dst address */
ret
END(strcpy)

View File

@@ -130,6 +130,8 @@ syscall_src += arch-x86/syscalls/removexattr.S
syscall_src += arch-x86/syscalls/lremovexattr.S
syscall_src += arch-x86/syscalls/__statfs64.S
syscall_src += arch-x86/syscalls/unshare.S
syscall_src += arch-x86/syscalls/swapon.S
syscall_src += arch-x86/syscalls/swapoff.S
syscall_src += arch-x86/syscalls/pause.S
syscall_src += arch-x86/syscalls/gettimeofday.S
syscall_src += arch-x86/syscalls/settimeofday.S
@@ -148,6 +150,9 @@ syscall_src += arch-x86/syscalls/__timer_getoverrun.S
syscall_src += arch-x86/syscalls/__timer_delete.S
syscall_src += arch-x86/syscalls/utimes.S
syscall_src += arch-x86/syscalls/utimensat.S
syscall_src += arch-x86/syscalls/timerfd_create.S
syscall_src += arch-x86/syscalls/timerfd_settime.S
syscall_src += arch-x86/syscalls/timerfd_gettime.S
syscall_src += arch-x86/syscalls/sigaction.S
syscall_src += arch-x86/syscalls/sigprocmask.S
syscall_src += arch-x86/syscalls/__sigsuspend.S

View File

@@ -0,0 +1,21 @@
/* autogenerated by gensyscalls.py */
#include <linux/err.h>
#include <machine/asm.h>
#include <asm/unistd.h>
ENTRY(swapoff)
pushl %ebx
mov 8(%esp), %ebx
movl $__NR_swapoff, %eax
int $0x80
cmpl $-MAX_ERRNO, %eax
jb 1f
negl %eax
pushl %eax
call __set_errno
addl $4, %esp
orl $-1, %eax
1:
popl %ebx
ret
END(swapoff)

View File

@@ -0,0 +1,24 @@
/* autogenerated by gensyscalls.py */
#include <linux/err.h>
#include <machine/asm.h>
#include <asm/unistd.h>
ENTRY(swapon)
pushl %ebx
pushl %ecx
mov 12(%esp), %ebx
mov 16(%esp), %ecx
movl $__NR_swapon, %eax
int $0x80
cmpl $-MAX_ERRNO, %eax
jb 1f
negl %eax
pushl %eax
call __set_errno
addl $4, %esp
orl $-1, %eax
1:
popl %ecx
popl %ebx
ret
END(swapon)

View File

@@ -0,0 +1,24 @@
/* autogenerated by gensyscalls.py */
#include <linux/err.h>
#include <machine/asm.h>
#include <asm/unistd.h>
ENTRY(timerfd_create)
pushl %ebx
pushl %ecx
mov 12(%esp), %ebx
mov 16(%esp), %ecx
movl $__NR_timerfd_create, %eax
int $0x80
cmpl $-MAX_ERRNO, %eax
jb 1f
negl %eax
pushl %eax
call __set_errno
addl $4, %esp
orl $-1, %eax
1:
popl %ecx
popl %ebx
ret
END(timerfd_create)

View File

@@ -0,0 +1,24 @@
/* autogenerated by gensyscalls.py */
#include <linux/err.h>
#include <machine/asm.h>
#include <asm/unistd.h>
ENTRY(timerfd_gettime)
pushl %ebx
pushl %ecx
mov 12(%esp), %ebx
mov 16(%esp), %ecx
movl $__NR_timerfd_gettime, %eax
int $0x80
cmpl $-MAX_ERRNO, %eax
jb 1f
negl %eax
pushl %eax
call __set_errno
addl $4, %esp
orl $-1, %eax
1:
popl %ecx
popl %ebx
ret
END(timerfd_gettime)

View File

@@ -0,0 +1,30 @@
/* autogenerated by gensyscalls.py */
#include <linux/err.h>
#include <machine/asm.h>
#include <asm/unistd.h>
ENTRY(timerfd_settime)
pushl %ebx
pushl %ecx
pushl %edx
pushl %esi
mov 20(%esp), %ebx
mov 24(%esp), %ecx
mov 28(%esp), %edx
mov 32(%esp), %esi
movl $__NR_timerfd_settime, %eax
int $0x80
cmpl $-MAX_ERRNO, %eax
jb 1f
negl %eax
pushl %eax
call __set_errno
addl $4, %esp
orl $-1, %eax
1:
popl %esi
popl %edx
popl %ecx
popl %ebx
ret
END(timerfd_settime)

View File

@@ -10,16 +10,75 @@ _LIBC_ARCH_COMMON_SRC_FILES := \
arch-x86/bionic/sigsetjmp.S \
arch-x86/bionic/syscall.S \
arch-x86/bionic/vfork.S \
arch-x86/string/bcopy_wrapper.S \
arch-x86/string/bzero_wrapper.S \
arch-x86/string/ffs.S \
arch-x86/string/memcmp_wrapper.S \
arch-x86/string/memcpy_wrapper.S \
arch-x86/string/memmove_wrapper.S \
arch-x86/string/memset_wrapper.S \
arch-x86/string/strcmp_wrapper.S \
arch-x86/string/strlen_wrapper.S \
arch-x86/string/strncmp_wrapper.S \
arch-x86/string/ffs.S
ifeq ($(ARCH_X86_HAVE_SSSE3),true)
_LIBC_ARCH_COMMON_SRC_FILES += \
arch-x86/string/ssse3-memcpy-atom.S \
arch-x86/string/ssse3-memmove-atom.S \
arch-x86/string/ssse3-bcopy-atom.S \
arch-x86/string/ssse3-strncat-atom.S \
arch-x86/string/ssse3-strncpy-atom.S \
arch-x86/string/ssse3-strlcat-atom.S \
arch-x86/string/ssse3-strlcpy-atom.S \
arch-x86/string/ssse3-strcmp-atom.S \
arch-x86/string/ssse3-strncmp-atom.S \
arch-x86/string/ssse3-strcat-atom.S \
arch-x86/string/ssse3-strcpy-atom.S \
arch-x86/string/ssse3-memcmp-atom.S \
arch-x86/string/ssse3-wmemcmp-atom.S \
arch-x86/string/ssse3-wcscat-atom.S \
arch-x86/string/ssse3-wcscpy-atom.S
else
_LIBC_ARCH_COMMON_SRC_FILES += \
arch-x86/string/memcpy.S \
arch-x86/string/memmove.S \
arch-x86/string/bcopy.S \
arch-x86/string/strcmp.S \
arch-x86/string/strncmp.S \
arch-x86/string/strcat.S \
arch-x86/string/memcmp.S \
string/strcpy.c \
string/strncat.c \
string/strncpy.c \
string/strlcat.c \
string/strlcpy.c \
upstream-freebsd/lib/libc/string/wcscpy.c \
upstream-freebsd/lib/libc/string/wcscat.c \
upstream-freebsd/lib/libc/string/wmemcmp.c
endif
ifeq ($(ARCH_X86_HAVE_SSE2),true)
_LIBC_ARCH_COMMON_SRC_FILES += \
arch-x86/string/sse2-memset-atom.S \
arch-x86/string/sse2-bzero-atom.S \
arch-x86/string/sse2-memchr-atom.S \
arch-x86/string/sse2-memrchr-atom.S \
arch-x86/string/sse2-strchr-atom.S \
arch-x86/string/sse2-strrchr-atom.S \
arch-x86/string/sse2-index-atom.S \
arch-x86/string/sse2-strlen-atom.S \
arch-x86/string/sse2-strnlen-atom.S \
arch-x86/string/sse2-wcschr-atom.S \
arch-x86/string/sse2-wcsrchr-atom.S \
arch-x86/string/sse2-wcslen-atom.S \
arch-x86/string/sse2-wcscmp-atom.S
else
_LIBC_ARCH_COMMON_SRC_FILES += \
arch-x86/string/memset.S \
arch-x86/string/strlen.S \
arch-x86/string/bzero.S \
bionic/memrchr.c \
bionic/memchr.c \
string/strchr.cpp \
string/strrchr.c \
string/index.c \
bionic/strnlen.c \
upstream-freebsd/lib/libc/string/wcschr.c \
upstream-freebsd/lib/libc/string/wcsrchr.c \
upstream-freebsd/lib/libc/string/wcslen.c \
upstream-freebsd/lib/libc/string/wcscmp.c
endif
_LIBC_ARCH_STATIC_SRC_FILES := \
bionic/dl_iterate_phdr_static.c \

View File

@@ -29,7 +29,6 @@
#include <string.h>
#include <stdlib.h>
#include "libc_logging.h"
#include <safe_iop.h>
/*
* Runtime implementation of __builtin____strcat_chk.
@@ -42,22 +41,24 @@
* This strcat check is called if _FORTIFY_SOURCE is defined and
* greater than 0.
*/
extern "C" char *__strcat_chk (char *dest, const char *src, size_t dest_buf_size) {
// TODO: optimize so we don't scan src/dest twice.
size_t src_len = strlen(src);
size_t dest_len = strlen(dest);
size_t sum;
extern "C" char* __strcat_chk(
char* __restrict dest,
const char* __restrict src,
size_t dest_buf_size)
{
char* save = dest;
size_t dest_len = __strlen_chk(dest, dest_buf_size);
// sum = src_len + dest_len + 1 (with overflow protection)
if (!safe_add3(&sum, src_len, dest_len, 1U)) {
__fortify_chk_fail("strcat integer overflow",
BIONIC_EVENT_STRCAT_INTEGER_OVERFLOW);
dest += dest_len;
dest_buf_size -= dest_len;
while ((*dest++ = *src++) != '\0') {
dest_buf_size--;
if (__predict_false(dest_buf_size == 0)) {
__fortify_chk_fail("strcat buffer overflow",
BIONIC_EVENT_STRCAT_BUFFER_OVERFLOW);
}
}
if (sum > dest_buf_size) {
__fortify_chk_fail("strcat buffer overflow",
BIONIC_EVENT_STRCAT_BUFFER_OVERFLOW);
}
return strcat(dest, src);
return save;
}

View File

@@ -0,0 +1,46 @@
/*-
* Copyright (c) 1990 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.
*/
#include <string.h>
#include "libc_logging.h"
extern "C" char* __strchr_chk(const char* p, int ch, size_t s_len) {
for (;; ++p, s_len--) {
if (__predict_false(s_len == 0)) {
__fortify_chk_fail("read beyond buffer", 0);
}
if (*p == static_cast<char>(ch)) {
return const_cast<char*>(p);
}
if (*p == '\0') {
return NULL;
}
}
/* NOTREACHED */
}

View File

@@ -29,7 +29,6 @@
#include <string.h>
#include <stdlib.h>
#include "libc_logging.h"
#include <safe_iop.h>
/*
* Runtime implementation of __builtin____strncat_chk.
@@ -42,27 +41,33 @@
* This strncat check is called if _FORTIFY_SOURCE is defined and
* greater than 0.
*/
extern "C" char *__strncat_chk (char *dest, const char *src,
size_t len, size_t dest_buf_size)
extern "C" char *__strncat_chk(
char* __restrict dest,
const char* __restrict src,
size_t len, size_t dest_buf_size)
{
// TODO: optimize so we don't scan src/dest twice.
size_t dest_len = strlen(dest);
size_t src_len = strlen(src);
if (src_len > len) {
src_len = len;
if (len == 0) {
return dest;
}
size_t sum;
// sum = src_len + dest_len + 1 (with overflow protection)
if (!safe_add3(&sum, src_len, dest_len, 1U)) {
__fortify_chk_fail("strncat integer overflow",
BIONIC_EVENT_STRNCAT_INTEGER_OVERFLOW);
size_t dest_len = __strlen_chk(dest, dest_buf_size);
char *d = dest + dest_len;
dest_buf_size -= dest_len;
while (*src != '\0') {
*d++ = *src++;
len--; dest_buf_size--;
if (__predict_false(dest_buf_size == 0)) {
__fortify_chk_fail("strncat buffer overflow",
BIONIC_EVENT_STRNCAT_BUFFER_OVERFLOW);
}
if (len == 0) {
break;
}
}
if (sum > dest_buf_size) {
__fortify_chk_fail("strncat buffer overflow",
BIONIC_EVENT_STRNCAT_BUFFER_OVERFLOW);
}
return strncat(dest, src, len);
*d = '\0';
return dest;
}

View File

@@ -1,4 +1,3 @@
/* $OpenBSD: abort.c,v 1.14 2005/08/08 08:05:36 espie Exp $ */
/*
* Copyright (c) 1985 Regents of the University of California.
* All rights reserved.
@@ -31,74 +30,38 @@
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include "thread_private.h"
#include "atexit.h"
__LIBC_HIDDEN__ void (*__cleanup)();
#ifdef __arm__
__LIBC_HIDDEN__ void
__libc_android_abort(void)
extern "C" __LIBC_HIDDEN__ void __libc_android_abort()
#else
void
abort(void)
void abort()
#endif
{
struct atexit *p = __atexit;
static int cleanup_called = 0;
sigset_t mask;
// Don't block SIGABRT to give any signal handler a chance; we ignore
// any errors -- X311J doesn't allow abort to return anyway.
sigset_t mask;
sigfillset(&mask);
sigdelset(&mask, SIGABRT);
sigprocmask(SIG_SETMASK, &mask, NULL);
// POSIX requires we flush stdio buffers on abort.
if (__cleanup) {
(*__cleanup)();
}
sigfillset(&mask);
/*
* don't block SIGABRT to give any handler a chance; we ignore
* any errors -- X311J doesn't allow abort to return anyway.
*/
sigdelset(&mask, SIGABRT);
/* temporary, so deliberate seg fault can be caught by debuggerd */
sigdelset(&mask, SIGSEGV);
/* -- */
(void)sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL);
raise(SIGABRT);
/*
* POSIX requires we flush stdio buffers on abort
*/
if (cleanup_called == 0) {
while (p != NULL && p->next != NULL)
p = p->next;
/* the check for fn_dso == NULL is mostly paranoia */
if (p != NULL && p->fns[0].fn_dso == NULL &&
p->fns[0].fn_ptr.std_func != NULL) {
cleanup_called = 1;
(*p->fns[0].fn_ptr.std_func)();
}
}
/* temporary, for bug hunting */
/* seg fault seems to produce better debuggerd results than SIGABRT */
#ifdef __mips__
/* An access that will generate SIGSEGV rather than SIGBUS. */
*((char*)0xdeadc0c0) = 39;
#else
*((char*)0xdeadbaad) = 39;
#endif
/* -- */
(void)kill(getpid(), SIGABRT);
/*
* if SIGABRT ignored, or caught and the handler returns, do
* it again, only harder.
*/
{
struct sigaction sa;
sa.sa_handler = SIG_DFL;
sa.sa_flags = SA_RESTART;
sigemptyset(&sa.sa_mask);
(void)sigaction( SIGABRT, &sa, &sa );
}
(void)sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL);
(void)kill(getpid(), SIGABRT);
_exit(1);
// If SIGABRT ignored, or caught and the handler returns,
// remove the SIGABRT signal handler and raise SIGABRT again.
struct sigaction sa;
sa.sa_handler = SIG_DFL;
sa.sa_flags = SA_RESTART;
sigemptyset(&sa.sa_mask);
sigaction(SIGABRT, &sa, &sa);
sigprocmask(SIG_SETMASK, &mask, NULL);
raise(SIGABRT);
_exit(1);
}

View File

@@ -27,39 +27,56 @@
*/
#include <elf.h>
#include <sys/auxv.h>
#include <sys/types.h>
#include <link.h>
/* Dynamic binaries get this from the dynamic linker (system/linker), which
* we don't pull in for static bins. We also don't have a list of so's to
* iterate over, since there's really only a single monolithic blob of
* code/data.
*
* All we need to do is to find where the executable is in memory, and grab the
* phdr and phnum from there.
*/
/* ld provides this to us in the default link script */
extern void *__executable_start;
extern void* __executable_start;
int
dl_iterate_phdr(int (*cb)(struct dl_phdr_info *info, size_t size, void *data),
void *data)
{
struct dl_phdr_info dl_info;
Elf32_Ehdr *ehdr = (Elf32_Ehdr *) &__executable_start;
Elf32_Phdr *phdr = (Elf32_Phdr *)((unsigned long)ehdr + ehdr->e_phoff);
int dl_iterate_phdr(int (*cb)(struct dl_phdr_info* info, size_t size, void* data), void* data) {
Elf32_Ehdr* ehdr = (Elf32_Ehdr*) &__executable_start;
/* TODO: again, copied from linker.c. Find a better home for this
* later. */
// TODO: again, copied from linker.c. Find a better home for this later.
if (ehdr->e_ident[EI_MAG0] != ELFMAG0) return -1;
if (ehdr->e_ident[EI_MAG1] != ELFMAG1) return -1;
if (ehdr->e_ident[EI_MAG2] != ELFMAG2) return -1;
if (ehdr->e_ident[EI_MAG3] != ELFMAG3) return -1;
dl_info.dlpi_addr = 0;
dl_info.dlpi_name = NULL;
dl_info.dlpi_phdr = phdr;
dl_info.dlpi_phnum = ehdr->e_phnum;
return cb(&dl_info, sizeof (struct dl_phdr_info), data);
// Dynamic binaries get their dl_iterate_phdr from the dynamic linker, but
// static binaries get this. We don't have a list of shared objects to
// iterate over, since there's really only a single monolithic blob of
// code/data, plus optionally a VDSO.
struct dl_phdr_info exe_info;
exe_info.dlpi_addr = 0;
exe_info.dlpi_name = NULL;
exe_info.dlpi_phdr = (Elf32_Phdr*) ((unsigned long) ehdr + ehdr->e_phoff);
exe_info.dlpi_phnum = ehdr->e_phnum;
#ifdef AT_SYSINFO_EHDR
// Try the executable first.
int rc = cb(&exe_info, sizeof(exe_info), data);
if (rc != 0) {
return rc;
}
// Try the VDSO if that didn't work.
Elf32_Ehdr* ehdr_vdso = (Elf32_Ehdr*) getauxval(AT_SYSINFO_EHDR);
struct dl_phdr_info vdso_info;
vdso_info.dlpi_addr = 0;
vdso_info.dlpi_name = NULL;
vdso_info.dlpi_phdr = (Elf32_Phdr*) ((char*) ehdr_vdso + ehdr_vdso->e_phoff);
vdso_info.dlpi_phnum = ehdr_vdso->e_phnum;
for (size_t i = 0; i < vdso_info.dlpi_phnum; ++i) {
if (vdso_info.dlpi_phdr[i].p_type == PT_LOAD) {
vdso_info.dlpi_addr = (Elf32_Addr) ehdr_vdso - vdso_info.dlpi_phdr[i].p_vaddr;
break;
}
}
return cb(&vdso_info, sizeof(vdso_info), data);
#else
// There's only the executable to try.
return cb(&exe_info, sizeof(exe_info), data);
#endif
}

View File

@@ -28,13 +28,17 @@ static void __bionic_heap_usage_error(const char* function, void* address);
// Ugly inclusion of C file so that bionic specific #defines configure dlmalloc.
#include "../upstream-dlmalloc/malloc.c"
extern void (*__cleanup)();
static void __bionic_heap_corruption_error(const char* function) {
__libc_fatal("@@@ ABORTING: heap corruption detected by %s", function);
__cleanup = NULL; // The heap is corrupt. We can forget trying to shut down stdio.
__libc_fatal("heap corruption detected by %s", function);
}
static void __bionic_heap_usage_error(const char* function, void* address) {
__libc_fatal("@@@ ABORTING: invalid address or address of corrupt block %p passed to %s",
__libc_fatal_no_abort("invalid address or address of corrupt block %p passed to %s",
address, function);
// So that we can get a memory dump around the specific address.
// So that debuggerd gives us a memory dump around the specific address.
// TODO: improve the debuggerd protocol so we can tell it to dump an address when we abort.
*((int**) 0xdeadbaad) = (int*) address;
}

View File

@@ -27,6 +27,7 @@
#define LOCK_AT_FORK 1
#define USE_RECURSIVE_LOCK 0
#define USE_SPIN_LOCKS 0
#define DEFAULT_MMAP_THRESHOLD (64U * 1024U)
/* Include the proper definitions. */
#include "../upstream-dlmalloc/malloc.h"

View File

@@ -42,7 +42,6 @@
#include <unistd.h>
static pthread_mutex_t gAbortMsgLock = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t gLogInitializationLock = PTHREAD_MUTEX_INITIALIZER;
__LIBC_HIDDEN__ abort_msg_t** __abort_message_ptr; // Accessible to __libc_init_common.
@@ -348,7 +347,7 @@ static void out_vformat(Out& o, const char* format, va_list args) {
buffer[0] = '0';
buffer[1] = 'x';
format_integer(buffer + 2, sizeof(buffer) - 2, value, 'x');
} else if (c == 'd' || c == 'i' || c == 'o' || c == 'x' || c == 'X') {
} else if (c == 'd' || c == 'i' || c == 'o' || c == 'u' || c == 'x' || c == 'X') {
/* integers - first read value from stack */
uint64_t value;
int is_signed = (c == 'd' || c == 'i' || c == 'o');
@@ -421,13 +420,9 @@ int __libc_format_fd(int fd, const char* format, ...) {
}
static int __libc_write_log(int priority, const char* tag, const char* msg) {
static int main_log_fd = -1;
int main_log_fd = TEMP_FAILURE_RETRY(open("/dev/log/main", O_CLOEXEC | O_WRONLY));
if (main_log_fd == -1) {
ScopedPthreadMutexLocker locker(&gLogInitializationLock);
main_log_fd = TEMP_FAILURE_RETRY(open("/dev/log/main", O_CLOEXEC | O_WRONLY));
if (main_log_fd == -1) {
return -1;
}
return -1;
}
iovec vec[3];
@@ -438,7 +433,9 @@ static int __libc_write_log(int priority, const char* tag, const char* msg) {
vec[2].iov_base = const_cast<char*>(msg);
vec[2].iov_len = strlen(msg) + 1;
return TEMP_FAILURE_RETRY(writev(main_log_fd, vec, 3));
int result = TEMP_FAILURE_RETRY(writev(main_log_fd, vec, 3));
close(main_log_fd);
return result;
}
int __libc_format_log_va_list(int priority, const char* tag, const char* format, va_list args) {
@@ -465,12 +462,13 @@ static int __libc_android_log_event(int32_t tag, char type, const void* payload,
vec[2].iov_base = const_cast<void*>(payload);
vec[2].iov_len = len;
static int event_log_fd = -1;
int event_log_fd = TEMP_FAILURE_RETRY(open("/dev/log/events", O_CLOEXEC | O_WRONLY));
if (event_log_fd == -1) {
ScopedPthreadMutexLocker locker(&gLogInitializationLock);
event_log_fd = TEMP_FAILURE_RETRY(open("/dev/log/events", O_CLOEXEC | O_WRONLY));
return -1;
}
return TEMP_FAILURE_RETRY(writev(event_log_fd, vec, 3));
int result = TEMP_FAILURE_RETRY(writev(event_log_fd, vec, 3));
close(event_log_fd);
return result;
}
void __libc_android_log_event_int(int32_t tag, int value) {
@@ -488,13 +486,10 @@ void __fortify_chk_fail(const char *msg, uint32_t tag) {
__libc_fatal("FORTIFY_SOURCE: %s. Calling abort().", msg);
}
void __libc_fatal(const char* format, ...) {
static void __libc_fatal(const char* format, va_list args) {
char msg[1024];
BufferOutputStream os(msg, sizeof(msg));
va_list args;
va_start(args, format);
out_vformat(os, format, args);
va_end(args);
// TODO: log to stderr for the benefit of "adb shell" users.
@@ -502,7 +497,20 @@ void __libc_fatal(const char* format, ...) {
__libc_write_log(ANDROID_LOG_FATAL, "libc", msg);
__libc_set_abort_message(msg);
}
void __libc_fatal_no_abort(const char* format, ...) {
va_list args;
va_start(args, format);
__libc_fatal(format, args);
va_end(args);
}
void __libc_fatal(const char* format, ...) {
va_list args;
va_start(args, format);
__libc_fatal(format, args);
va_end(args);
abort();
}

View File

@@ -74,6 +74,10 @@ static void log_message(const char* format, ...) {
struct hdr_t {
uint32_t tag;
void* base; // Always points to the memory allocated using dlmalloc.
// For memory allocated in chk_memalign, this value will
// not be the same as the location of the start of this
// structure.
hdr_t* prev;
hdr_t* next;
uintptr_t bt[MAX_BACKTRACE_DEPTH];
@@ -82,7 +86,7 @@ struct hdr_t {
int freed_bt_depth;
size_t size;
char front_guard[FRONT_GUARD_LEN];
} __attribute__((packed));
} __attribute__((packed, aligned(MALLOC_ALIGNMENT)));
struct ftr_t {
char rear_guard[REAR_GUARD_LEN];
@@ -100,21 +104,26 @@ static inline hdr_t* meta(void* user) {
return reinterpret_cast<hdr_t*>(user) - 1;
}
static inline const hdr_t* const_meta(const void* user) {
return reinterpret_cast<const hdr_t*>(user) - 1;
}
static unsigned gAllocatedBlockCount;
static hdr_t *tail;
static hdr_t *head;
static hdr_t* tail;
static hdr_t* head;
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
static unsigned backlog_num;
static hdr_t *backlog_tail;
static hdr_t *backlog_head;
static hdr_t* backlog_tail;
static hdr_t* backlog_head;
static pthread_mutex_t backlog_lock = PTHREAD_MUTEX_INITIALIZER;
static inline void init_front_guard(hdr_t *hdr) {
static inline void init_front_guard(hdr_t* hdr) {
memset(hdr->front_guard, FRONT_GUARD, FRONT_GUARD_LEN);
}
static inline bool is_front_guard_valid(hdr_t *hdr) {
static inline bool is_front_guard_valid(hdr_t* hdr) {
for (size_t i = 0; i < FRONT_GUARD_LEN; i++) {
if (hdr->front_guard[i] != FRONT_GUARD) {
return 0;
@@ -123,12 +132,12 @@ static inline bool is_front_guard_valid(hdr_t *hdr) {
return 1;
}
static inline void init_rear_guard(hdr_t *hdr) {
static inline void init_rear_guard(hdr_t* hdr) {
ftr_t* ftr = to_ftr(hdr);
memset(ftr->rear_guard, REAR_GUARD, REAR_GUARD_LEN);
}
static inline bool is_rear_guard_valid(hdr_t *hdr) {
static inline bool is_rear_guard_valid(hdr_t* hdr) {
unsigned i;
int valid = 1;
int first_mismatch = -1;
@@ -149,7 +158,7 @@ static inline bool is_rear_guard_valid(hdr_t *hdr) {
return valid;
}
static inline void add_locked(hdr_t *hdr, hdr_t **tail, hdr_t **head) {
static inline void add_locked(hdr_t* hdr, hdr_t** tail, hdr_t** head) {
hdr->prev = NULL;
hdr->next = *head;
if (*head)
@@ -159,7 +168,7 @@ static inline void add_locked(hdr_t *hdr, hdr_t **tail, hdr_t **head) {
*head = hdr;
}
static inline int del_locked(hdr_t *hdr, hdr_t **tail, hdr_t **head) {
static inline int del_locked(hdr_t* hdr, hdr_t** tail, hdr_t** head) {
if (hdr->prev) {
hdr->prev->next = hdr->next;
} else {
@@ -173,7 +182,7 @@ static inline int del_locked(hdr_t *hdr, hdr_t **tail, hdr_t **head) {
return 0;
}
static inline void add(hdr_t *hdr, size_t size) {
static inline void add(hdr_t* hdr, size_t size) {
ScopedPthreadMutexLocker locker(&lock);
hdr->tag = ALLOCATION_TAG;
hdr->size = size;
@@ -183,7 +192,7 @@ static inline void add(hdr_t *hdr, size_t size) {
add_locked(hdr, &tail, &head);
}
static inline int del(hdr_t *hdr) {
static inline int del(hdr_t* hdr) {
if (hdr->tag != ALLOCATION_TAG) {
return -1;
}
@@ -194,13 +203,13 @@ static inline int del(hdr_t *hdr) {
return 0;
}
static inline void poison(hdr_t *hdr) {
static inline void poison(hdr_t* hdr) {
memset(user(hdr), FREE_POISON, hdr->size);
}
static int was_used_after_free(hdr_t *hdr) {
static int was_used_after_free(hdr_t* hdr) {
unsigned i;
const char *data = (const char *)user(hdr);
const char* data = reinterpret_cast<const char *>(user(hdr));
for (i = 0; i < hdr->size; i++)
if (data[i] != FREE_POISON)
return 1;
@@ -208,7 +217,7 @@ static int was_used_after_free(hdr_t *hdr) {
}
/* returns 1 if valid, *safe == 1 if safe to dump stack */
static inline int check_guards(hdr_t *hdr, int *safe) {
static inline int check_guards(hdr_t* hdr, int* safe) {
*safe = 1;
if (!is_front_guard_valid(hdr)) {
if (hdr->front_guard[0] == FRONT_GUARD) {
@@ -233,7 +242,7 @@ static inline int check_guards(hdr_t *hdr, int *safe) {
}
/* returns 1 if valid, *safe == 1 if safe to dump stack */
static inline int check_allocation_locked(hdr_t *hdr, int *safe) {
static inline int check_allocation_locked(hdr_t* hdr, int* safe) {
int valid = 1;
*safe = 1;
@@ -270,9 +279,9 @@ static inline int check_allocation_locked(hdr_t *hdr, int *safe) {
return valid;
}
static inline int del_and_check_locked(hdr_t *hdr,
hdr_t **tail, hdr_t **head, unsigned *cnt,
int *safe) {
static inline int del_and_check_locked(hdr_t* hdr,
hdr_t** tail, hdr_t** head, unsigned* cnt,
int* safe) {
int valid = check_allocation_locked(hdr, safe);
if (safe) {
(*cnt)--;
@@ -281,7 +290,7 @@ static inline int del_and_check_locked(hdr_t *hdr,
return valid;
}
static inline void del_from_backlog_locked(hdr_t *hdr) {
static inline void del_from_backlog_locked(hdr_t* hdr) {
int safe;
del_and_check_locked(hdr,
&backlog_tail, &backlog_head, &backlog_num,
@@ -289,17 +298,17 @@ static inline void del_from_backlog_locked(hdr_t *hdr) {
hdr->tag = 0; /* clear the tag */
}
static inline void del_from_backlog(hdr_t *hdr) {
static inline void del_from_backlog(hdr_t* hdr) {
ScopedPthreadMutexLocker locker(&backlog_lock);
del_from_backlog_locked(hdr);
}
static inline int del_leak(hdr_t *hdr, int *safe) {
static inline int del_leak(hdr_t* hdr, int* safe) {
ScopedPthreadMutexLocker locker(&lock);
return del_and_check_locked(hdr, &tail, &head, &gAllocatedBlockCount, safe);
}
static inline void add_to_backlog(hdr_t *hdr) {
static inline void add_to_backlog(hdr_t* hdr) {
ScopedPthreadMutexLocker locker(&backlog_lock);
hdr->tag = BACKLOG_TAG;
backlog_num++;
@@ -307,9 +316,9 @@ static inline void add_to_backlog(hdr_t *hdr) {
poison(hdr);
/* If we've exceeded the maximum backlog, clear it up */
while (backlog_num > gMallocDebugBacklog) {
hdr_t *gone = backlog_tail;
hdr_t* gone = backlog_tail;
del_from_backlog_locked(gone);
dlfree(gone);
dlfree(gone->base);
}
}
@@ -318,6 +327,7 @@ extern "C" void* chk_malloc(size_t size) {
hdr_t* hdr = static_cast<hdr_t*>(dlmalloc(sizeof(hdr_t) + size + sizeof(ftr_t)));
if (hdr) {
hdr->base = hdr;
hdr->bt_depth = get_backtrace(hdr->bt, MAX_BACKTRACE_DEPTH);
add(hdr, size);
return user(hdr);
@@ -325,13 +335,44 @@ extern "C" void* chk_malloc(size_t size) {
return NULL;
}
extern "C" void* chk_memalign(size_t, size_t bytes) {
// log_message("%s: %s\n", __FILE__, __FUNCTION__);
// XXX: it's better to use malloc, than being wrong
return chk_malloc(bytes);
extern "C" void* chk_memalign(size_t alignment, size_t bytes) {
if (alignment <= MALLOC_ALIGNMENT) {
return chk_malloc(bytes);
}
// Make the alignment a power of two.
if (alignment & (alignment-1)) {
alignment = 1L << (31 - __builtin_clz(alignment));
}
// here, alignment is at least MALLOC_ALIGNMENT<<1 bytes
// we will align by at least MALLOC_ALIGNMENT bytes
// and at most alignment-MALLOC_ALIGNMENT bytes
size_t size = (alignment-MALLOC_ALIGNMENT) + bytes;
if (size < bytes) { // Overflow.
return NULL;
}
void* base = dlmalloc(sizeof(hdr_t) + size + sizeof(ftr_t));
if (base != NULL) {
// Check that the actual pointer that will be returned is aligned
// properly.
uintptr_t ptr = reinterpret_cast<uintptr_t>(user(reinterpret_cast<hdr_t*>(base)));
if ((ptr % alignment) != 0) {
// Align the pointer.
ptr += ((-ptr) % alignment);
}
hdr_t* hdr = meta(reinterpret_cast<void*>(ptr));
hdr->base = base;
hdr->bt_depth = get_backtrace(hdr->bt, MAX_BACKTRACE_DEPTH);
add(hdr, bytes);
return user(hdr);
}
return base;
}
extern "C" void chk_free(void *ptr) {
extern "C" void chk_free(void* ptr) {
// log_message("%s: %s\n", __FILE__, __FUNCTION__);
if (!ptr) /* ignore free(NULL) */
@@ -366,7 +407,7 @@ extern "C" void chk_free(void *ptr) {
}
}
extern "C" void *chk_realloc(void *ptr, size_t size) {
extern "C" void* chk_realloc(void* ptr, size_t size) {
// log_message("%s: %s\n", __FILE__, __FUNCTION__);
if (!ptr) {
@@ -414,8 +455,23 @@ extern "C" void *chk_realloc(void *ptr, size_t size) {
}
}
hdr = static_cast<hdr_t*>(dlrealloc(hdr, sizeof(hdr_t) + size + sizeof(ftr_t)));
if (hdr->base != hdr) {
// An allocation from memalign, so create another allocation and
// copy the data out.
void* newMem = dlmalloc(sizeof(hdr_t) + size + sizeof(ftr_t));
if (newMem) {
memcpy(newMem, hdr, sizeof(hdr_t) + hdr->size);
dlfree(hdr->base);
hdr = static_cast<hdr_t*>(newMem);
} else {
dlfree(hdr->base);
hdr = NULL;
}
} else {
hdr = static_cast<hdr_t*>(dlrealloc(hdr, sizeof(hdr_t) + size + sizeof(ftr_t)));
}
if (hdr) {
hdr->base = hdr;
hdr->bt_depth = get_backtrace(hdr->bt, MAX_BACKTRACE_DEPTH);
add(hdr, size);
return user(hdr);
@@ -424,11 +480,12 @@ extern "C" void *chk_realloc(void *ptr, size_t size) {
return NULL;
}
extern "C" void *chk_calloc(int nmemb, size_t size) {
extern "C" void* chk_calloc(int nmemb, size_t size) {
// log_message("%s: %s\n", __FILE__, __FUNCTION__);
size_t total_size = nmemb * size;
hdr_t* hdr = static_cast<hdr_t*>(dlcalloc(1, sizeof(hdr_t) + total_size + sizeof(ftr_t)));
if (hdr) {
hdr->base = hdr;
hdr->bt_depth = get_backtrace(hdr->bt, MAX_BACKTRACE_DEPTH);
add(hdr, total_size);
return user(hdr);
@@ -436,6 +493,18 @@ extern "C" void *chk_calloc(int nmemb, size_t size) {
return NULL;
}
extern "C" size_t chk_malloc_usable_size(const void* ptr) {
// dlmalloc_usable_size returns 0 for NULL and unknown blocks.
if (ptr == NULL)
return 0;
const hdr_t* hdr = const_meta(ptr);
// The sentinel tail is written just after the request block bytes
// so there is no extra room we can report here.
return hdr->size;
}
static void ReportMemoryLeaks() {
// We only track leaks at level 10.
if (gMallocDebugLevel != 10) {

View File

@@ -190,10 +190,6 @@ extern "C" struct mallinfo mallinfo() {
return dlmallinfo();
}
extern "C" size_t malloc_usable_size(void* mem) {
return dlmalloc_usable_size(mem);
}
extern "C" void* valloc(size_t bytes) {
return dlvalloc(bytes);
}
@@ -215,8 +211,9 @@ extern "C" int posix_memalign(void** memptr, size_t alignment, size_t size) {
/* Table for dispatching malloc calls, initialized with default dispatchers. */
extern const MallocDebug __libc_malloc_default_dispatch;
const MallocDebug __libc_malloc_default_dispatch __attribute__((aligned(32))) = {
dlmalloc, dlfree, dlcalloc, dlrealloc, dlmemalign
const MallocDebug __libc_malloc_default_dispatch __attribute__((aligned(32))) =
{
dlmalloc, dlfree, dlcalloc, dlrealloc, dlmemalign, dlmalloc_usable_size,
};
/* Selector of dispatch table to use for dispatching malloc calls. */
@@ -242,6 +239,10 @@ extern "C" void* memalign(size_t alignment, size_t bytes) {
return __libc_malloc_dispatch->memalign(alignment, bytes);
}
extern "C" size_t malloc_usable_size(const void* mem) {
return __libc_malloc_dispatch->malloc_usable_size(mem);
}
/* We implement malloc debugging only in libc.so, so code below
* must be excluded if we compile this file for static libc.a
*/
@@ -253,7 +254,7 @@ extern "C" void* memalign(size_t alignment, size_t bytes) {
/* Table for dispatching malloc calls, depending on environment. */
static MallocDebug gMallocUse __attribute__((aligned(32))) = {
dlmalloc, dlfree, dlcalloc, dlrealloc, dlmemalign
dlmalloc, dlfree, dlcalloc, dlrealloc, dlmemalign, dlmalloc_usable_size
};
extern const char* __progname;
@@ -276,15 +277,10 @@ extern const char* __progname;
* Actual functionality for debug levels 1-10 is implemented in
* libc_malloc_debug_leak.so, while functionality for emultor's instrumented
* allocations is implemented in libc_malloc_debug_qemu.so and can be run inside
* the emulator only.
* the emulator only.
*/
static void* libc_malloc_impl_handle = NULL;
// This must match the alignment used by dlmalloc.
#ifndef MALLOC_ALIGNMENT
#define MALLOC_ALIGNMENT ((size_t)(2 * sizeof(void *)))
#endif
/* This variable is set to the value of property libc.debug.malloc.backlog,
* when the value of libc.debug.malloc = 10. It determines the size of the
* backlog we use to detect multiple frees. If the property is not set, the
@@ -296,41 +292,26 @@ unsigned int gMallocDebugBacklog;
/* The value of libc.debug.malloc. */
int gMallocDebugLevel;
static void InitMalloc(MallocDebug* table, const char* prefix) {
__libc_format_log(ANDROID_LOG_INFO, "libc", "%s: using libc.debug.malloc %d (%s)\n",
__progname, gMallocDebugLevel, prefix);
template<typename FunctionType>
void InitMallocFunction(void* malloc_impl_handler, FunctionType* func, const char* prefix, const char* suffix) {
char symbol[128];
snprintf(symbol, sizeof(symbol), "%s_%s", prefix, suffix);
*func = reinterpret_cast<FunctionType>(dlsym(malloc_impl_handler, symbol));
if (*func == NULL) {
error_log("%s: dlsym(\"%s\") failed", __progname, symbol);
}
}
char symbol[128];
static void InitMalloc(void* malloc_impl_handler, MallocDebug* table, const char* prefix) {
__libc_format_log(ANDROID_LOG_INFO, "libc", "%s: using libc.debug.malloc %d (%s)\n",
__progname, gMallocDebugLevel, prefix);
snprintf(symbol, sizeof(symbol), "%s_malloc", prefix);
table->malloc = reinterpret_cast<MallocDebugMalloc>(dlsym(libc_malloc_impl_handle, symbol));
if (table->malloc == NULL) {
error_log("%s: dlsym(\"%s\") failed", __progname, symbol);
}
snprintf(symbol, sizeof(symbol), "%s_free", prefix);
table->free = reinterpret_cast<MallocDebugFree>(dlsym(libc_malloc_impl_handle, symbol));
if (table->free == NULL) {
error_log("%s: dlsym(\"%s\") failed", __progname, symbol);
}
snprintf(symbol, sizeof(symbol), "%s_calloc", prefix);
table->calloc = reinterpret_cast<MallocDebugCalloc>(dlsym(libc_malloc_impl_handle, symbol));
if (table->calloc == NULL) {
error_log("%s: dlsym(\"%s\") failed", __progname, symbol);
}
snprintf(symbol, sizeof(symbol), "%s_realloc", prefix);
table->realloc = reinterpret_cast<MallocDebugRealloc>(dlsym(libc_malloc_impl_handle, symbol));
if (table->realloc == NULL) {
error_log("%s: dlsym(\"%s\") failed", __progname, symbol);
}
snprintf(symbol, sizeof(symbol), "%s_memalign", prefix);
table->memalign = reinterpret_cast<MallocDebugMemalign>(dlsym(libc_malloc_impl_handle, symbol));
if (table->memalign == NULL) {
error_log("%s: dlsym(\"%s\") failed", __progname, symbol);
}
InitMallocFunction<MallocDebugMalloc>(malloc_impl_handler, &table->malloc, prefix, "malloc");
InitMallocFunction<MallocDebugFree>(malloc_impl_handler, &table->free, prefix, "free");
InitMallocFunction<MallocDebugCalloc>(malloc_impl_handler, &table->calloc, prefix, "calloc");
InitMallocFunction<MallocDebugRealloc>(malloc_impl_handler, &table->realloc, prefix, "realloc");
InitMallocFunction<MallocDebugMemalign>(malloc_impl_handler, &table->memalign, prefix, "memalign");
InitMallocFunction<MallocDebugMallocUsableSize>(malloc_impl_handler, &table->malloc_usable_size, prefix, "malloc_usable_size");
}
/* Initializes memory allocation framework once per process. */
@@ -422,24 +403,24 @@ static void malloc_init_impl() {
}
// Load .so that implements the required malloc debugging functionality.
libc_malloc_impl_handle = dlopen(so_name, RTLD_LAZY);
if (libc_malloc_impl_handle == NULL) {
void* malloc_impl_handle = dlopen(so_name, RTLD_LAZY);
if (malloc_impl_handle == NULL) {
error_log("%s: Missing module %s required for malloc debug level %d: %s",
__progname, so_name, gMallocDebugLevel, dlerror());
return;
}
// Initialize malloc debugging in the loaded module.
malloc_debug_initialize = reinterpret_cast<MallocDebugInit>(dlsym(libc_malloc_impl_handle,
malloc_debug_initialize = reinterpret_cast<MallocDebugInit>(dlsym(malloc_impl_handle,
"malloc_debug_initialize"));
if (malloc_debug_initialize == NULL) {
error_log("%s: Initialization routine is not found in %s\n",
__progname, so_name);
dlclose(libc_malloc_impl_handle);
dlclose(malloc_impl_handle);
return;
}
if (malloc_debug_initialize() == -1) {
dlclose(libc_malloc_impl_handle);
dlclose(malloc_impl_handle);
return;
}
@@ -447,34 +428,35 @@ static void malloc_init_impl() {
// For memory checker we need to do extra initialization.
typedef int (*MemCheckInit)(int, const char*);
MemCheckInit memcheck_initialize =
reinterpret_cast<MemCheckInit>(dlsym(libc_malloc_impl_handle,
reinterpret_cast<MemCheckInit>(dlsym(malloc_impl_handle,
"memcheck_initialize"));
if (memcheck_initialize == NULL) {
error_log("%s: memcheck_initialize routine is not found in %s\n",
__progname, so_name);
dlclose(libc_malloc_impl_handle);
dlclose(malloc_impl_handle);
return;
}
if (memcheck_initialize(MALLOC_ALIGNMENT, memcheck_tracing)) {
dlclose(libc_malloc_impl_handle);
dlclose(malloc_impl_handle);
return;
}
}
// Initialize malloc dispatch table with appropriate routines.
switch (gMallocDebugLevel) {
case 1:
InitMalloc(&gMallocUse, "leak");
InitMalloc(malloc_impl_handle, &gMallocUse, "leak");
break;
case 5:
InitMalloc(&gMallocUse, "fill");
InitMalloc(malloc_impl_handle, &gMallocUse, "fill");
break;
case 10:
InitMalloc(&gMallocUse, "chk");
InitMalloc(malloc_impl_handle, &gMallocUse, "chk");
break;
case 20:
InitMalloc(&gMallocUse, "qemu_instrumented");
InitMalloc(malloc_impl_handle, &gMallocUse, "qemu_instrumented");
break;
default:
break;
@@ -485,13 +467,14 @@ static void malloc_init_impl() {
(gMallocUse.free == NULL) ||
(gMallocUse.calloc == NULL) ||
(gMallocUse.realloc == NULL) ||
(gMallocUse.memalign == NULL)) {
(gMallocUse.memalign == NULL) ||
(gMallocUse.malloc_usable_size == NULL)) {
error_log("%s: some symbols for libc.debug.malloc level %d were not found (see above)",
__progname, gMallocDebugLevel);
dlclose(libc_malloc_impl_handle);
libc_malloc_impl_handle = NULL;
dlclose(malloc_impl_handle);
} else {
__libc_malloc_dispatch = &gMallocUse;
libc_malloc_impl_handle = malloc_impl_handle;
}
}

View File

@@ -45,6 +45,11 @@
#define MAX_SIZE_T (~(size_t)0)
// This must match the alignment used by dlmalloc.
#ifndef MALLOC_ALIGNMENT
#define MALLOC_ALIGNMENT ((size_t)(2 * sizeof(void *)))
#endif
// =============================================================================
// Structures
// =============================================================================
@@ -71,12 +76,14 @@ typedef void (*MallocDebugFree)(void*);
typedef void* (*MallocDebugCalloc)(size_t, size_t);
typedef void* (*MallocDebugRealloc)(void*, size_t);
typedef void* (*MallocDebugMemalign)(size_t, size_t);
typedef size_t (*MallocDebugMallocUsableSize)(const void*);
struct MallocDebug {
MallocDebugMalloc malloc;
MallocDebugFree free;
MallocDebugCalloc calloc;
MallocDebugRealloc realloc;
MallocDebugMemalign memalign;
MallocDebugMallocUsableSize malloc_usable_size;
};
/* Malloc debugging initialization and finalization routines.

View File

@@ -67,9 +67,6 @@ extern HashTable gHashTable;
// stack trace functions
// =============================================================================
#ifndef MALLOC_ALIGNMENT
#define MALLOC_ALIGNMENT ((size_t)8U)
#endif
#define GUARD 0x48151642
#define DEBUG 0
@@ -80,12 +77,16 @@ extern HashTable gHashTable;
struct AllocationEntry {
HashEntry* entry;
uint32_t guard;
};
} __attribute__((aligned(MALLOC_ALIGNMENT)));
static AllocationEntry* to_header(void* mem) {
static inline AllocationEntry* to_header(void* mem) {
return reinterpret_cast<AllocationEntry*>(mem) - 1;
}
static inline const AllocationEntry* const_to_header(const void* mem) {
return reinterpret_cast<const AllocationEntry*>(mem) - 1;
}
// =============================================================================
// Hash Table functions
// =============================================================================
@@ -229,17 +230,16 @@ extern "C" void fill_free(void* mem) {
}
extern "C" void* fill_realloc(void* mem, size_t bytes) {
void* buffer = fill_malloc(bytes);
if (mem == NULL) {
return buffer;
size_t oldSize = dlmalloc_usable_size(mem);
void* newMem = dlrealloc(mem, bytes);
if (newMem) {
// If this is larger than before, fill the extra with our pattern.
size_t newSize = dlmalloc_usable_size(newMem);
if (newSize > oldSize) {
memset(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(newMem)+oldSize), CHK_FILL_FREE, newSize-oldSize);
}
}
if (buffer) {
size_t old_size = dlmalloc_usable_size(mem);
size_t size = (bytes < old_size)?(bytes):(old_size);
memcpy(buffer, mem, size);
fill_free(mem);
}
return buffer;
return newMem;
}
extern "C" void* fill_memalign(size_t alignment, size_t bytes) {
@@ -250,11 +250,17 @@ extern "C" void* fill_memalign(size_t alignment, size_t bytes) {
return buffer;
}
extern "C" size_t fill_malloc_usable_size(const void* mem) {
// Since we didn't allocate extra bytes before or after, we can
// report the normal usable size here.
return dlmalloc_usable_size(mem);
}
// =============================================================================
// malloc leak functions
// =============================================================================
static void* MEMALIGN_GUARD = reinterpret_cast<void*>(0xA1A41520);
static uint32_t MEMALIGN_GUARD = 0xA1A41520;
extern "C" void* leak_malloc(size_t bytes) {
// allocate enough space infront of the allocation to store the pointer for
@@ -296,9 +302,10 @@ extern "C" void leak_free(void* mem) {
if (header->guard != GUARD) {
// could be a memaligned block
if (reinterpret_cast<void**>(mem)[-1] == MEMALIGN_GUARD) {
mem = reinterpret_cast<void**>(mem)[-2];
header = to_header(mem);
if (header->guard == MEMALIGN_GUARD) {
// For memaligned blocks, header->entry points to the memory
// allocated through leak_malloc.
header = to_header(header->entry);
}
}
@@ -338,19 +345,26 @@ extern "C" void* leak_realloc(void* oldMem, size_t bytes) {
if (oldMem == NULL) {
return leak_malloc(bytes);
}
void* newMem = NULL;
AllocationEntry* header = to_header(oldMem);
if (header && header->guard == GUARD) {
size_t oldSize = header->entry->size & ~SIZE_FLAG_MASK;
newMem = leak_malloc(bytes);
if (newMem != NULL) {
size_t copySize = (oldSize <= bytes) ? oldSize : bytes;
memcpy(newMem, oldMem, copySize);
leak_free(oldMem);
}
} else {
newMem = dlrealloc(oldMem, bytes);
if (header->guard == MEMALIGN_GUARD) {
// Get the real header.
header = to_header(header->entry);
} else if (header->guard != GUARD) {
debug_log("WARNING bad header guard: '0x%x'! and invalid entry: %p\n",
header->guard, header->entry);
return NULL;
}
newMem = leak_malloc(bytes);
if (newMem != NULL) {
size_t oldSize = header->entry->size & ~SIZE_FLAG_MASK;
size_t copySize = (oldSize <= bytes) ? oldSize : bytes;
memcpy(newMem, oldMem, copySize);
}
leak_free(oldMem);
return newMem;
}
@@ -375,7 +389,7 @@ extern "C" void* leak_memalign(size_t alignment, size_t bytes) {
void* base = leak_malloc(size);
if (base != NULL) {
intptr_t ptr = reinterpret_cast<intptr_t>(base);
uintptr_t ptr = reinterpret_cast<uintptr_t>(base);
if ((ptr % alignment) == 0) {
return base;
}
@@ -383,11 +397,38 @@ extern "C" void* leak_memalign(size_t alignment, size_t bytes) {
// align the pointer
ptr += ((-ptr) % alignment);
// there is always enough space for the base pointer and the guard
reinterpret_cast<void**>(ptr)[-1] = MEMALIGN_GUARD;
reinterpret_cast<void**>(ptr)[-2] = base;
// Already allocated enough space for the header. This assumes
// that the malloc alignment is at least 8, otherwise, this is
// not guaranteed to have the space for the header.
AllocationEntry* header = to_header(reinterpret_cast<void*>(ptr));
header->guard = MEMALIGN_GUARD;
header->entry = reinterpret_cast<HashEntry*>(base);
return reinterpret_cast<void*>(ptr);
}
return base;
}
extern "C" size_t leak_malloc_usable_size(const void* mem) {
if (mem != NULL) {
// Check the guard to make sure it is valid.
const AllocationEntry* header = const_to_header((void*)mem);
if (header->guard == MEMALIGN_GUARD) {
// If this is a memalign'd pointer, then grab the header from
// entry.
header = const_to_header(header->entry);
} else if (header->guard != GUARD) {
debug_log("WARNING bad header guard: '0x%x'! and invalid entry: %p\n",
header->guard, header->entry);
return 0;
}
size_t ret = dlmalloc_usable_size(header);
if (ret != 0) {
// The usable area starts at 'mem' and stops at 'header+ret'.
return reinterpret_cast<uintptr_t>(header) + ret - reinterpret_cast<uintptr_t>(mem);
}
}
return 0;
}

View File

@@ -137,7 +137,7 @@ struct MallocDescQuery {
* will respond with information about allocated block that contains this
* pointer.
*/
void* ptr;
const void* ptr;
/* Id of the process that initialized libc instance, in which this query
* is called. This field is used by the emulator to report errors in
@@ -469,7 +469,7 @@ static inline int notify_qemu_free(void* ptr_to_free) {
* Return:
* Zero on success, or -1 on failure.
*/
static inline int query_qemu_malloc_info(void* ptr, MallocDesc* desc, uint32_t routine) {
static inline int query_qemu_malloc_info(const void* ptr, MallocDesc* desc, uint32_t routine) {
volatile MallocDescQuery query;
query.ptr = ptr;
@@ -574,11 +574,12 @@ static void test_access_violation(const MallocDesc* desc) {
// API routines
// =============================================================================
void* qemu_instrumented_malloc(size_t bytes);
void qemu_instrumented_free(void* mem);
void* qemu_instrumented_calloc(size_t n_elements, size_t elem_size);
void* qemu_instrumented_realloc(void* mem, size_t bytes);
void* qemu_instrumented_memalign(size_t alignment, size_t bytes);
extern "C" void* qemu_instrumented_malloc(size_t bytes);
extern "C" void qemu_instrumented_free(void* mem);
extern "C" void* qemu_instrumented_calloc(size_t n_elements, size_t elem_size);
extern "C" void* qemu_instrumented_realloc(void* mem, size_t bytes);
extern "C" void* qemu_instrumented_memalign(size_t alignment, size_t bytes);
extern "C" size_t qemu_instrumented_malloc_usable_size(const void* mem);
/* Initializes malloc debugging instrumentation for the emulator.
* This routine is called from malloc_init_impl routine implemented in
@@ -589,7 +590,7 @@ void* qemu_instrumented_memalign(size_t alignment, size_t bytes);
* Return:
* 0 on success, or -1 on failure.
*/
int malloc_debug_initialize() {
extern "C" int malloc_debug_initialize() {
/* We will be using emulator's magic page to report memory allocation
* activities. In essence, what magic page does, it translates writes to
* the memory mapped spaces into writes to an I/O port that emulator
@@ -627,7 +628,7 @@ int malloc_debug_initialize() {
* Return:
* 0 on success, or -1 on failure.
*/
int memcheck_initialize(int alignment, const char* memcheck_param) {
extern "C" int memcheck_initialize(int alignment, const char* memcheck_param) {
malloc_alignment = alignment;
/* Parse -memcheck parameter for the guest tracing flags. */
@@ -673,7 +674,7 @@ int memcheck_initialize(int alignment, const char* memcheck_param) {
* bytes (plus prefix, and suffix guards), and report allocation to the
* emulator.
*/
void* qemu_instrumented_malloc(size_t bytes) {
extern "C" void* qemu_instrumented_malloc(size_t bytes) {
MallocDesc desc;
/* Initialize block descriptor and allocate memory. Note that dlmalloc
@@ -708,7 +709,7 @@ void* qemu_instrumented_malloc(size_t bytes) {
* Primary responsibility of this routine is to free requested memory, and
* report free block to the emulator.
*/
void qemu_instrumented_free(void* mem) {
extern "C" void qemu_instrumented_free(void* mem) {
MallocDesc desc;
if (mem == NULL) {
@@ -751,7 +752,7 @@ void qemu_instrumented_free(void* mem) {
/* This routine serves as entry point for 'calloc'.
* This routine behaves similarly to qemu_instrumented_malloc.
*/
void* qemu_instrumented_calloc(size_t n_elements, size_t elem_size) {
extern "C" void* qemu_instrumented_calloc(size_t n_elements, size_t elem_size) {
if (n_elements == 0 || elem_size == 0) {
// Just let go zero bytes allocation.
qemu_info_log("::: <libc_pid=%03u, pid=%03u>: Zero calloc redir to malloc",
@@ -823,7 +824,7 @@ void* qemu_instrumented_calloc(size_t n_elements, size_t elem_size) {
* allocation, but overall it doesn't seem to matter, as caller of realloc
* should not expect that pointer returned after shrinking will remain the same.
*/
void* qemu_instrumented_realloc(void* mem, size_t bytes) {
extern "C" void* qemu_instrumented_realloc(void* mem, size_t bytes) {
MallocDesc new_desc;
MallocDesc cur_desc;
size_t to_copy;
@@ -927,7 +928,7 @@ void* qemu_instrumented_realloc(void* mem, size_t bytes) {
/* This routine serves as entry point for 'memalign'.
* This routine behaves similarly to qemu_instrumented_malloc.
*/
void* qemu_instrumented_memalign(size_t alignment, size_t bytes) {
extern "C" void* qemu_instrumented_memalign(size_t alignment, size_t bytes) {
MallocDesc desc;
if (bytes == 0) {
@@ -967,3 +968,27 @@ void* qemu_instrumented_memalign(size_t alignment, size_t bytes) {
malloc_pid, getpid(), alignment, bytes);
return mallocdesc_user_ptr(&desc);
}
extern "C" size_t qemu_instrumented_malloc_usable_size(const void* mem) {
MallocDesc cur_desc;
// Query emulator for the reallocating block information.
if (query_qemu_malloc_info(mem, &cur_desc, 2)) {
// Note that this violation should be already caught in the emulator.
error_log("<libc_pid=%03u, pid=%03u>: malloc_usable_size(%p) query_info failed.",
malloc_pid, getpid(), mem);
return 0;
}
/* Make sure that reallocating pointer value is what we would expect
* for this memory block. Note that this violation should be already caught
* in the emulator.*/
if (mem != mallocdesc_user_ptr(&cur_desc)) {
log_mdesc(error, &cur_desc, "<libc_pid=%03u, pid=%03u>: malloc_usable_size(%p) is invalid for ",
malloc_pid, getpid(), mem);
return 0;
}
/* during instrumentation, we can't really report anything more than requested_bytes */
return cur_desc.requested_bytes;
}

54
libc/bionic/mmap.cpp Normal file
View File

@@ -0,0 +1,54 @@
/*
* 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 <errno.h>
#include <sys/mman.h>
#include <unistd.h>
#include "private/ErrnoRestorer.h"
// mmap2(2) is like mmap(2), but the offset is in 4096-byte blocks, not bytes.
extern "C" void* __mmap2(void*, size_t, int, int, int, size_t);
#define MMAP2_SHIFT 12 // 2**12 == 4096
void* mmap(void* addr, size_t size, int prot, int flags, int fd, long offset) {
if (offset & ((1UL << MMAP2_SHIFT)-1)) {
errno = EINVAL;
return MAP_FAILED;
}
void* result = __mmap2(addr, size, prot, flags, fd, offset >> MMAP2_SHIFT);
if (result != MAP_FAILED && (flags & (MAP_PRIVATE | MAP_ANONYMOUS)) != 0) {
ErrnoRestorer errno_restorer;
madvise(result, size, MADV_MERGEABLE);
}
return result;
}

View File

@@ -53,9 +53,6 @@
*
*/
#define __likely(cond) __builtin_expect(!!(cond), 1)
#define __unlikely(cond) __builtin_expect(!!(cond), 0)
#define RWLOCKATTR_DEFAULT 0
#define RWLOCKATTR_SHARED_MASK 0x0010
@@ -212,7 +209,7 @@ int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock)
return EINVAL;
pthread_mutex_lock(&rwlock->lock);
if (__unlikely(!read_precondition(rwlock, __get_thread()->tid)))
if (__predict_false(!read_precondition(rwlock, __get_thread()->tid)))
ret = EBUSY;
else
rwlock->numLocks ++;
@@ -230,7 +227,7 @@ int pthread_rwlock_timedrdlock(pthread_rwlock_t *rwlock, const struct timespec *
pthread_mutex_lock(&rwlock->lock);
int tid = __get_thread()->tid;
if (__unlikely(!read_precondition(rwlock, tid))) {
if (__predict_false(!read_precondition(rwlock, tid))) {
rwlock->pendingReaders += 1;
do {
ret = pthread_cond_timedwait(&rwlock->cond, &rwlock->lock, abs_timeout);
@@ -260,7 +257,7 @@ int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock)
pthread_mutex_lock(&rwlock->lock);
int tid = __get_thread()->tid;
if (__unlikely(!write_precondition(rwlock, tid))) {
if (__predict_false(!write_precondition(rwlock, tid))) {
ret = EBUSY;
} else {
rwlock->numLocks ++;
@@ -279,7 +276,7 @@ int pthread_rwlock_timedwrlock(pthread_rwlock_t *rwlock, const struct timespec *
pthread_mutex_lock(&rwlock->lock);
int tid = __get_thread()->tid;
if (__unlikely(!write_precondition(rwlock, tid))) {
if (__predict_false(!write_precondition(rwlock, tid))) {
/* If we can't read yet, wait until the rwlock is unlocked
* and try again. Increment pendingReaders to get the
* cond broadcast when that happens.

View File

@@ -33,6 +33,12 @@
#include <stdio.h>
#include <string.h>
extern int __pthread_cond_timedwait(pthread_cond_t*, pthread_mutex_t*, const struct timespec*,
clockid_t);
extern int __pthread_cond_timedwait_relative(pthread_cond_t*, pthread_mutex_t*,
const struct timespec*);
// Normal (i.e. non-SIGEV_THREAD) timers are created directly by the kernel
// and are passed as is to/from the caller.
//
@@ -81,9 +87,6 @@
/* the maximum value of overrun counters */
#define DELAYTIMER_MAX 0x7fffffff
#define __likely(x) __builtin_expect(!!(x),1)
#define __unlikely(x) __builtin_expect(!!(x),0)
typedef struct thr_timer thr_timer_t;
typedef struct thr_timer_table thr_timer_table_t;
@@ -282,6 +285,49 @@ thr_timer_unlock( thr_timer_t* t )
pthread_mutex_unlock(&t->mutex);
}
static __inline__ void timespec_add(struct timespec* a, const struct timespec* b) {
a->tv_sec += b->tv_sec;
a->tv_nsec += b->tv_nsec;
if (a->tv_nsec >= 1000000000) {
a->tv_nsec -= 1000000000;
a->tv_sec += 1;
}
}
static __inline__ void timespec_sub(struct timespec* a, const struct timespec* b) {
a->tv_sec -= b->tv_sec;
a->tv_nsec -= b->tv_nsec;
if (a->tv_nsec < 0) {
a->tv_nsec += 1000000000;
a->tv_sec -= 1;
}
}
static __inline__ void timespec_zero(struct timespec* a) {
a->tv_sec = a->tv_nsec = 0;
}
static __inline__ int timespec_is_zero(const struct timespec* a) {
return (a->tv_sec == 0 && a->tv_nsec == 0);
}
static __inline__ int timespec_cmp(const struct timespec* a, const struct timespec* b) {
if (a->tv_sec < b->tv_sec) return -1;
if (a->tv_sec > b->tv_sec) return +1;
if (a->tv_nsec < b->tv_nsec) return -1;
if (a->tv_nsec > b->tv_nsec) return +1;
return 0;
}
static __inline__ int timespec_cmp0(const struct timespec* a) {
if (a->tv_sec < 0) return -1;
if (a->tv_sec > 0) return +1;
if (a->tv_nsec < 0) return -1;
if (a->tv_nsec > 0) return +1;
return 0;
}
/** POSIX TIMERS APIs */
extern int __timer_create(clockid_t, struct sigevent*, timer_t*);
@@ -294,7 +340,7 @@ static void* timer_thread_start(void*);
int timer_create(clockid_t clock_id, struct sigevent* evp, timer_t* timer_id) {
// If not a SIGEV_THREAD timer, the kernel can handle it without our help.
if (__likely(evp == NULL || evp->sigev_notify != SIGEV_THREAD)) {
if (__predict_true(evp == NULL || evp->sigev_notify != SIGEV_THREAD)) {
return __timer_create(clock_id, evp, timer_id);
}
@@ -360,7 +406,7 @@ int timer_create(clockid_t clock_id, struct sigevent* evp, timer_t* timer_id) {
int
timer_delete( timer_t id )
{
if ( __likely(!TIMER_ID_IS_WRAPPED(id)) )
if ( __predict_true(!TIMER_ID_IS_WRAPPED(id)) )
return __timer_delete( id );
else
{
@@ -422,7 +468,7 @@ timer_gettime( timer_t id, struct itimerspec* ospec )
return -1;
}
if ( __likely(!TIMER_ID_IS_WRAPPED(id)) ) {
if ( __predict_true(!TIMER_ID_IS_WRAPPED(id)) ) {
return __timer_gettime( id, ospec );
} else {
thr_timer_t* timer = thr_timer_from_id(id);
@@ -450,7 +496,7 @@ timer_settime( timer_t id,
return -1;
}
if ( __likely(!TIMER_ID_IS_WRAPPED(id)) ) {
if ( __predict_true(!TIMER_ID_IS_WRAPPED(id)) ) {
return __timer_settime( id, flags, spec, ospec );
} else {
thr_timer_t* timer = thr_timer_from_id(id);
@@ -494,7 +540,7 @@ timer_settime( timer_t id,
int
timer_getoverrun(timer_t id)
{
if ( __likely(!TIMER_ID_IS_WRAPPED(id)) ) {
if ( __predict_true(!TIMER_ID_IS_WRAPPED(id)) ) {
return __timer_getoverrun( id );
} else {
thr_timer_t* timer = thr_timer_from_id(id);

View File

@@ -31,6 +31,7 @@
#include <errno.h>
#include <limits.h>
#include <sys/atomics.h>
#include <sys/mman.h>
#include <unistd.h>
#include "bionic_atomic_inline.h"
@@ -56,19 +57,6 @@ int __futex_wait_ex(volatile void *ftx, int pshared, int val, const struct time
return __futex_syscall4(ftx, pshared ? FUTEX_WAIT : FUTEX_WAIT_PRIVATE, val, timeout);
}
#define __likely(cond) __builtin_expect(!!(cond), 1)
#define __unlikely(cond) __builtin_expect(!!(cond), 0)
void*
__get_stack_base(int *p_stack_size)
{
pthread_internal_t* thread = __get_thread();
*p_stack_size = thread->attr.stack_size;
return thread->attr.stack_base;
}
/* CAVEAT: our implementation of pthread_cleanup_push/pop doesn't support C++ exceptions
* and thread cancelation
*/
@@ -115,6 +103,18 @@ void pthread_exit(void * retval)
// space (see pthread_key_delete)
pthread_key_clean_all();
if (thread->alternate_signal_stack != NULL) {
// Tell the kernel to stop using the alternate signal stack.
stack_t ss;
ss.ss_sp = NULL;
ss.ss_flags = SS_DISABLE;
sigaltstack(&ss, NULL);
// Free it.
munmap(thread->alternate_signal_stack, SIGSTKSZ);
thread->alternate_signal_stack = NULL;
}
// if the thread is detached, destroy the pthread_internal_t
// otherwise, keep it in memory and signal any joiners.
pthread_mutex_lock(&gThreadListLock);
@@ -130,23 +130,13 @@ void pthread_exit(void * retval)
thread->tls = NULL;
}
/* the join_count field is used to store the number of threads waiting for
* the termination of this thread with pthread_join(),
*
* if it is positive we need to signal the waiters, and we do not touch
* the count (it will be decremented by the waiters, the last one will
* also remove/free the thread structure
*
* if it is zero, we set the count value to -1 to indicate that the
* thread is in 'zombie' state: it has stopped executing, and its stack
* is gone (as well as its TLS area). when another thread calls pthread_join()
* on it, it will immediately free the thread and return.
*/
/* Indicate that the thread has exited for joining threads. */
thread->attr.flags |= PTHREAD_ATTR_FLAG_ZOMBIE;
thread->return_value = retval;
if (thread->join_count > 0) {
pthread_cond_broadcast(&thread->join_cond);
} else {
thread->join_count = -1; /* zombie thread */
/* Signal the joining thread if present. */
if (thread->attr.flags & PTHREAD_ATTR_FLAG_JOINED) {
pthread_cond_signal(&thread->join_cond);
}
}
pthread_mutex_unlock(&gThreadListLock);
@@ -409,7 +399,7 @@ int pthread_mutex_init(pthread_mutex_t *mutex,
if (mutex == NULL)
return EINVAL;
if (__likely(attr == NULL)) {
if (__predict_true(attr == NULL)) {
mutex->value = MUTEX_TYPE_BITS_NORMAL;
return 0;
}
@@ -575,7 +565,7 @@ _recursive_increment(pthread_mutex_t* mutex, int mvalue, int mtype)
for (;;) {
/* increment counter, overflow was already checked */
int newval = mvalue + MUTEX_COUNTER_BITS_ONE;
if (__likely(__bionic_cmpxchg(mvalue, newval, &mutex->value) == 0)) {
if (__predict_true(__bionic_cmpxchg(mvalue, newval, &mutex->value) == 0)) {
/* mutex is still locked, not need for a memory barrier */
return 0;
}
@@ -592,7 +582,7 @@ int pthread_mutex_lock_impl(pthread_mutex_t *mutex)
{
int mvalue, mtype, tid, shared;
if (__unlikely(mutex == NULL))
if (__predict_false(mutex == NULL))
return EINVAL;
mvalue = mutex->value;
@@ -600,7 +590,7 @@ int pthread_mutex_lock_impl(pthread_mutex_t *mutex)
shared = (mvalue & MUTEX_SHARED_MASK);
/* Handle normal case first */
if ( __likely(mtype == MUTEX_TYPE_BITS_NORMAL) ) {
if ( __predict_true(mtype == MUTEX_TYPE_BITS_NORMAL) ) {
_normal_lock(mutex, shared);
return 0;
}
@@ -641,7 +631,7 @@ int pthread_mutex_lock_impl(pthread_mutex_t *mutex)
* implement it to get rid of the explicit memory
* barrier below.
*/
if (__unlikely(__bionic_cmpxchg(mvalue, newval, &mutex->value) != 0)) {
if (__predict_false(__bionic_cmpxchg(mvalue, newval, &mutex->value) != 0)) {
mvalue = mutex->value;
continue;
}
@@ -653,7 +643,7 @@ int pthread_mutex_lock_impl(pthread_mutex_t *mutex)
* we will change it to 2 to indicate contention. */
if (MUTEX_STATE_BITS_IS_LOCKED_UNCONTENDED(mvalue)) {
newval = MUTEX_STATE_BITS_FLIP_CONTENTION(mvalue); /* locked state 1 => state 2 */
if (__unlikely(__bionic_cmpxchg(mvalue, newval, &mutex->value) != 0)) {
if (__predict_false(__bionic_cmpxchg(mvalue, newval, &mutex->value) != 0)) {
mvalue = mutex->value;
continue;
}
@@ -686,7 +676,7 @@ int pthread_mutex_unlock_impl(pthread_mutex_t *mutex)
{
int mvalue, mtype, tid, shared;
if (__unlikely(mutex == NULL))
if (__predict_false(mutex == NULL))
return EINVAL;
mvalue = mutex->value;
@@ -694,7 +684,7 @@ int pthread_mutex_unlock_impl(pthread_mutex_t *mutex)
shared = (mvalue & MUTEX_SHARED_MASK);
/* Handle common case first */
if (__likely(mtype == MUTEX_TYPE_BITS_NORMAL)) {
if (__predict_true(mtype == MUTEX_TYPE_BITS_NORMAL)) {
_normal_unlock(mutex, shared);
return 0;
}
@@ -711,7 +701,7 @@ int pthread_mutex_unlock_impl(pthread_mutex_t *mutex)
if (!MUTEX_COUNTER_BITS_IS_ZERO(mvalue)) {
for (;;) {
int newval = mvalue - MUTEX_COUNTER_BITS_ONE;
if (__likely(__bionic_cmpxchg(mvalue, newval, &mutex->value) == 0)) {
if (__predict_true(__bionic_cmpxchg(mvalue, newval, &mutex->value) == 0)) {
/* success: we still own the mutex, so no memory barrier */
return 0;
}
@@ -753,7 +743,7 @@ int pthread_mutex_trylock_impl(pthread_mutex_t *mutex)
{
int mvalue, mtype, tid, shared;
if (__unlikely(mutex == NULL))
if (__predict_false(mutex == NULL))
return EINVAL;
mvalue = mutex->value;
@@ -761,7 +751,7 @@ int pthread_mutex_trylock_impl(pthread_mutex_t *mutex)
shared = (mvalue & MUTEX_SHARED_MASK);
/* Handle common case first */
if ( __likely(mtype == MUTEX_TYPE_BITS_NORMAL) )
if ( __predict_true(mtype == MUTEX_TYPE_BITS_NORMAL) )
{
if (__bionic_cmpxchg(shared|MUTEX_STATE_BITS_UNLOCKED,
shared|MUTEX_STATE_BITS_LOCKED_UNCONTENDED,
@@ -785,7 +775,7 @@ int pthread_mutex_trylock_impl(pthread_mutex_t *mutex)
mtype |= shared | MUTEX_STATE_BITS_UNLOCKED;
mvalue = MUTEX_OWNER_TO_BITS(tid) | mtype | MUTEX_STATE_BITS_LOCKED_UNCONTENDED;
if (__likely(__bionic_cmpxchg(mtype, mvalue, &mutex->value) == 0)) {
if (__predict_true(__bionic_cmpxchg(mtype, mvalue, &mutex->value) == 0)) {
ANDROID_MEMBAR_FULL();
return 0;
}
@@ -851,7 +841,7 @@ int pthread_mutex_lock_timeout_np_impl(pthread_mutex_t *mutex, unsigned msecs)
/* compute absolute expiration time */
__timespec_to_relative_msec(&abstime, msecs, clock);
if (__unlikely(mutex == NULL))
if (__predict_false(mutex == NULL))
return EINVAL;
mvalue = mutex->value;
@@ -859,7 +849,7 @@ int pthread_mutex_lock_timeout_np_impl(pthread_mutex_t *mutex, unsigned msecs)
shared = (mvalue & MUTEX_SHARED_MASK);
/* Handle common case first */
if ( __likely(mtype == MUTEX_TYPE_BITS_NORMAL) )
if ( __predict_true(mtype == MUTEX_TYPE_BITS_NORMAL) )
{
const int unlocked = shared | MUTEX_STATE_BITS_UNLOCKED;
const int locked_uncontended = shared | MUTEX_STATE_BITS_LOCKED_UNCONTENDED;
@@ -896,7 +886,7 @@ int pthread_mutex_lock_timeout_np_impl(pthread_mutex_t *mutex, unsigned msecs)
/* first try a quick lock */
if (mvalue == mtype) {
mvalue = MUTEX_OWNER_TO_BITS(tid) | mtype | MUTEX_STATE_BITS_LOCKED_UNCONTENDED;
if (__likely(__bionic_cmpxchg(mtype, mvalue, &mutex->value) == 0)) {
if (__predict_true(__bionic_cmpxchg(mtype, mvalue, &mutex->value) == 0)) {
ANDROID_MEMBAR_FULL();
return 0;
}
@@ -1073,7 +1063,7 @@ __pthread_cond_pulse(pthread_cond_t *cond, int counter)
{
long flags;
if (__unlikely(cond == NULL))
if (__predict_false(cond == NULL))
return EINVAL;
flags = (cond->value & ~COND_COUNTER_MASK);
@@ -1214,7 +1204,7 @@ int pthread_once( pthread_once_t* once_control, void (*init_routine)(void) )
* stores performed by the initialization function are observable on
* this CPU after we exit.
*/
if (__likely((*ocptr & ONCE_COMPLETED) != 0)) {
if (__predict_true((*ocptr & ONCE_COMPLETED) != 0)) {
ANDROID_MEMBAR_FULL();
return 0;
}

View File

@@ -30,12 +30,16 @@
#include "pthread_internal.h"
#define DEFAULT_STACK_SIZE (1024 * 1024)
// Traditionally we give threads a 1MiB stack. When we started allocating per-thread
// alternate signal stacks to ease debugging of stack overflows, we subtracted the
// same amount we were using there from the default thread stack size. This should
// keep memory usage roughly constant.
#define DEFAULT_THREAD_STACK_SIZE ((1 * 1024 * 1024) - SIGSTKSZ)
int pthread_attr_init(pthread_attr_t* attr) {
attr->flags = 0;
attr->stack_base = NULL;
attr->stack_size = DEFAULT_STACK_SIZE;
attr->stack_size = DEFAULT_THREAD_STACK_SIZE;
attr->guard_size = PAGE_SIZE;
attr->sched_policy = SCHED_NORMAL;
attr->sched_priority = 0;
@@ -84,7 +88,7 @@ int pthread_attr_getschedparam(pthread_attr_t const* attr, struct sched_param* p
}
int pthread_attr_setstacksize(pthread_attr_t* attr, size_t stack_size) {
if ((stack_size & (PAGE_SIZE - 1) || stack_size < PTHREAD_STACK_MIN)) {
if (stack_size < PTHREAD_STACK_MIN) {
return EINVAL;
}
attr->stack_size = stack_size;
@@ -128,9 +132,6 @@ int pthread_attr_getstack(pthread_attr_t const* attr, void** stack_base, size_t*
}
int pthread_attr_setguardsize(pthread_attr_t* attr, size_t guard_size) {
if (guard_size & (PAGE_SIZE - 1) || guard_size < PAGE_SIZE) {
return EINVAL;
}
attr->guard_size = guard_size;
return 0;
}

View File

@@ -69,9 +69,22 @@ void __init_tls(pthread_internal_t* thread) {
thread->tls[TLS_SLOT_STACK_GUARD] = (void*) __stack_chk_guard;
__set_tls(thread->tls);
// Create and set an alternate signal stack.
// This must happen after __set_tls, in case a system call fails and tries to set errno.
stack_t ss;
ss.ss_sp = mmap(NULL, SIGSTKSZ, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
if (ss.ss_sp != MAP_FAILED) {
ss.ss_size = SIGSTKSZ;
ss.ss_flags = 0;
sigaltstack(&ss, NULL);
thread->alternate_signal_stack = ss.ss_sp;
}
}
// This trampoline is called from the assembly _pthread_clone() function.
// This trampoline is called from the assembly _pthread_clone function.
// Our 'tls' and __pthread_clone's 'child_stack' are one and the same, just growing in
// opposite directions.
extern "C" void __thread_entry(void* (*func)(void*), void* arg, void** tls) {
// Wait for our creating thread to release us. This lets it have time to
// notify gdb about this thread before we start doing anything.
@@ -104,13 +117,12 @@ int _init_thread(pthread_internal_t* thread, bool add_to_thread_list) {
if (sched_setscheduler(thread->tid, thread->attr.sched_policy, &param) == -1) {
// For backwards compatibility reasons, we just warn about failures here.
// error = errno;
const char* msg = "pthread_create sched_setscheduler call failed: %s\n";
__libc_format_log(ANDROID_LOG_WARN, "libc", msg, strerror(errno));
__libc_format_log(ANDROID_LOG_WARN, "libc",
"pthread_create sched_setscheduler call failed: %s", strerror(errno));
}
}
pthread_cond_init(&thread->join_cond, NULL);
thread->join_count = 0;
thread->cleanup_stack = NULL;
if (add_to_thread_list) {
@@ -120,20 +132,27 @@ int _init_thread(pthread_internal_t* thread, bool add_to_thread_list) {
return error;
}
static void* __create_thread_stack(size_t stack_size, size_t guard_size) {
static void* __create_thread_stack(pthread_internal_t* thread) {
ScopedPthreadMutexLocker lock(&gPthreadStackCreationLock);
// Create a new private anonymous map.
int prot = PROT_READ | PROT_WRITE;
int flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE;
void* stack = mmap(NULL, stack_size, prot, flags, -1, 0);
void* stack = mmap(NULL, thread->attr.stack_size, prot, flags, -1, 0);
if (stack == MAP_FAILED) {
__libc_format_log(ANDROID_LOG_WARN,
"libc",
"pthread_create failed: couldn't allocate %zd-byte stack: %s",
thread->attr.stack_size, strerror(errno));
return NULL;
}
// Set the guard region at the end of the stack to PROT_NONE.
if (mprotect(stack, guard_size, PROT_NONE) == -1) {
munmap(stack, stack_size);
if (mprotect(stack, thread->attr.guard_size, PROT_NONE) == -1) {
__libc_format_log(ANDROID_LOG_WARN, "libc",
"pthread_create failed: couldn't mprotect PROT_NONE %zd-byte stack guard region: %s",
thread->attr.guard_size, strerror(errno));
munmap(stack, thread->attr.stack_size);
return NULL;
}
@@ -165,15 +184,15 @@ int pthread_create(pthread_t* thread_out, pthread_attr_t const* attr,
attr = NULL; // Prevent misuse below.
}
// Make sure the stack size is PAGE_SIZE aligned.
size_t stack_size = (thread->attr.stack_size + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1);
// Make sure the stack size and guard size are multiples of PAGE_SIZE.
thread->attr.stack_size = (thread->attr.stack_size + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1);
thread->attr.guard_size = (thread->attr.guard_size + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1);
if (thread->attr.stack_base == NULL) {
// The caller didn't provide a stack, so allocate one.
thread->attr.stack_base = __create_thread_stack(stack_size, thread->attr.guard_size);
thread->attr.stack_base = __create_thread_stack(thread);
if (thread->attr.stack_base == NULL) {
free(thread);
__libc_format_log(ANDROID_LOG_WARN, "libc", "pthread_create failed: couldn't allocate %zd-byte stack", stack_size);
return EAGAIN;
}
} else {
@@ -181,8 +200,12 @@ int pthread_create(pthread_t* thread_out, pthread_attr_t const* attr,
thread->attr.flags |= PTHREAD_ATTR_FLAG_USER_STACK;
}
// Make room for TLS.
void** tls = (void**)((uint8_t*)(thread->attr.stack_base) + stack_size - BIONIC_TLS_SLOTS * sizeof(void*));
// Make room for the TLS area.
// The child stack is the same address, just growing in the opposite direction.
// At offsets >= 0, we have the TLS slots.
// At offsets < 0, we have the child stack.
void** tls = (void**)((uint8_t*)(thread->attr.stack_base) + thread->attr.stack_size - BIONIC_TLS_SLOTS * sizeof(void*));
void* child_stack = tls;
// Create a mutex for the thread in TLS_SLOT_SELF to wait on once it starts so we can keep
// it from doing anything until after we notify the debugger about it
@@ -198,11 +221,11 @@ int pthread_create(pthread_t* thread_out, pthread_attr_t const* attr,
int flags = CLONE_FILES | CLONE_FS | CLONE_VM | CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM;
int tid = __pthread_clone(start_routine, tls, flags, arg);
int tid = __pthread_clone(start_routine, child_stack, flags, arg);
if (tid < 0) {
int clone_errno = errno;
if ((thread->attr.flags & PTHREAD_ATTR_FLAG_USER_STACK) == 0) {
munmap(thread->attr.stack_base, stack_size);
munmap(thread->attr.stack_base, thread->attr.stack_size);
}
free(thread);
__libc_format_log(ANDROID_LOG_WARN, "libc", "pthread_create failed: clone failed: %s", strerror(errno));

View File

@@ -40,7 +40,7 @@ int pthread_detach(pthread_t t) {
return EINVAL; // Already detached.
}
if (thread->join_count > 0) {
if (thread->attr.flags & PTHREAD_ATTR_FLAG_JOINED) {
return 0; // Already being joined; silently do nothing, like glibc.
}

View File

@@ -30,6 +30,7 @@
#include <pthread.h>
#include <stdbool.h>
#include <sys/cdefs.h>
__BEGIN_DECLS
@@ -41,12 +42,13 @@ typedef struct pthread_internal_t
pid_t tid;
bool allocated_on_heap;
pthread_cond_t join_cond;
int join_count;
void* return_value;
int internal_flags;
__pthread_cleanup_t* cleanup_stack;
void** tls; /* thread-local storage area */
void* alternate_signal_stack;
/*
* The dynamic linker implements dlerror(3), which makes it hard for us to implement this
* per-thread buffer by simply using malloc(3) and free(3).
@@ -63,71 +65,21 @@ pthread_internal_t* __get_thread(void);
__LIBC_HIDDEN__ void pthread_key_clean_all(void);
__LIBC_HIDDEN__ void _pthread_internal_remove_locked(pthread_internal_t* thread);
/* Has the thread been detached by a pthread_join or pthread_detach call? */
#define PTHREAD_ATTR_FLAG_DETACHED 0x00000001
/* Was the thread's stack allocated by the user rather than by us? */
#define PTHREAD_ATTR_FLAG_USER_STACK 0x00000002
/* Has the thread been joined by another thread? */
#define PTHREAD_ATTR_FLAG_JOINED 0x00000004
/* Has the thread already exited but not been joined? */
#define PTHREAD_ATTR_FLAG_ZOMBIE 0x00000008
__LIBC_HIDDEN__ extern pthread_internal_t* gThreadList;
__LIBC_HIDDEN__ extern pthread_mutex_t gThreadListLock;
/* needed by posix-timers.c */
static __inline__ void timespec_add( struct timespec* a, const struct timespec* b )
{
a->tv_sec += b->tv_sec;
a->tv_nsec += b->tv_nsec;
if (a->tv_nsec >= 1000000000) {
a->tv_nsec -= 1000000000;
a->tv_sec += 1;
}
}
static __inline__ void timespec_sub( struct timespec* a, const struct timespec* b )
{
a->tv_sec -= b->tv_sec;
a->tv_nsec -= b->tv_nsec;
if (a->tv_nsec < 0) {
a->tv_nsec += 1000000000;
a->tv_sec -= 1;
}
}
static __inline__ void timespec_zero( struct timespec* a )
{
a->tv_sec = a->tv_nsec = 0;
}
static __inline__ int timespec_is_zero( const struct timespec* a )
{
return (a->tv_sec == 0 && a->tv_nsec == 0);
}
static __inline__ int timespec_cmp( const struct timespec* a, const struct timespec* b )
{
if (a->tv_sec < b->tv_sec) return -1;
if (a->tv_sec > b->tv_sec) return +1;
if (a->tv_nsec < b->tv_nsec) return -1;
if (a->tv_nsec > b->tv_nsec) return +1;
return 0;
}
static __inline__ int timespec_cmp0( const struct timespec* a )
{
if (a->tv_sec < 0) return -1;
if (a->tv_sec > 0) return +1;
if (a->tv_nsec < 0) return -1;
if (a->tv_nsec > 0) return +1;
return 0;
}
extern int __pthread_cond_timedwait(pthread_cond_t*,
pthread_mutex_t*,
const struct timespec*,
clockid_t);
extern int __pthread_cond_timedwait_relative(pthread_cond_t*,
pthread_mutex_t*,
const struct timespec*);
/* needed by fork.c */
extern void __timer_table_start_stop(int stop);
extern void __bionic_atfork_run_prepare();

View File

@@ -30,7 +30,7 @@
#include "pthread_accessor.h"
int pthread_join(pthread_t t, void ** ret_val) {
int pthread_join(pthread_t t, void** ret_val) {
if (t == pthread_self()) {
return EDEADLK;
}
@@ -44,25 +44,19 @@ int pthread_join(pthread_t t, void ** ret_val) {
return EINVAL;
}
// Wait for thread death when needed.
if (thread->attr.flags & PTHREAD_ATTR_FLAG_JOINED) {
return EINVAL;
}
// If the 'join_count' is negative, this is a 'zombie' thread that
// is already dead and without stack/TLS. Otherwise, we need to increment 'join-count'
// and wait to be signaled
int count = thread->join_count;
if (count >= 0) {
thread->join_count += 1;
// Signal our intention to join, and wait for the thread to exit.
thread->attr.flags |= PTHREAD_ATTR_FLAG_JOINED;
while ((thread->attr.flags & PTHREAD_ATTR_FLAG_ZOMBIE) == 0) {
pthread_cond_wait(&thread->join_cond, &gThreadListLock);
count = --thread->join_count;
}
if (ret_val) {
*ret_val = thread->return_value;
}
// Remove thread from thread list when we're the last joiner or when the
// thread was already a zombie.
if (count <= 0) {
_pthread_internal_remove_locked(thread.get());
}
_pthread_internal_remove_locked(thread.get());
return 0;
}

Some files were not shown because too many files have changed in this diff Show More