Initial import.
This commit is contained in:
commit
ed320731e9
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/build
|
127
CMakeLists.txt
Normal file
127
CMakeLists.txt
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.0)
|
||||||
|
project(xmrig C)
|
||||||
|
|
||||||
|
set(HEADERS
|
||||||
|
compat.h
|
||||||
|
algo/cryptonight/cryptonight.h
|
||||||
|
elist.h
|
||||||
|
xmrig.h
|
||||||
|
version.h
|
||||||
|
options.h
|
||||||
|
cpu.h
|
||||||
|
persistent_memory.h
|
||||||
|
stratum.h
|
||||||
|
stats.h
|
||||||
|
util.h
|
||||||
|
donate.h
|
||||||
|
)
|
||||||
|
|
||||||
|
set(HEADERS_CRYPTO
|
||||||
|
crypto/c_groestl.h
|
||||||
|
crypto/c_blake256.h
|
||||||
|
crypto/c_jh.h
|
||||||
|
crypto/c_skein.h
|
||||||
|
crypto/oaes_lib.h
|
||||||
|
crypto/oaes_config.h
|
||||||
|
crypto/aesb.h
|
||||||
|
)
|
||||||
|
|
||||||
|
set(HEADERS_COMPAT
|
||||||
|
compat/winansi.h
|
||||||
|
)
|
||||||
|
|
||||||
|
set(HEADERS_UTILS
|
||||||
|
utils/applog.h
|
||||||
|
utils/threads.h
|
||||||
|
utils/summary.h
|
||||||
|
)
|
||||||
|
|
||||||
|
set(SOURCES
|
||||||
|
xmrig.c
|
||||||
|
algo/cryptonight/cryptonight_common.c
|
||||||
|
util.c
|
||||||
|
options.c
|
||||||
|
cpu.c
|
||||||
|
stratum.c
|
||||||
|
stats.c
|
||||||
|
memory.c
|
||||||
|
)
|
||||||
|
|
||||||
|
set(SOURCES_CRYPTO
|
||||||
|
crypto/c_keccak.c
|
||||||
|
crypto/c_groestl.c
|
||||||
|
crypto/c_blake256.c
|
||||||
|
crypto/c_jh.c
|
||||||
|
crypto/c_skein.c
|
||||||
|
crypto/oaes_lib.c
|
||||||
|
crypto/aesb.c
|
||||||
|
)
|
||||||
|
|
||||||
|
set(SOURCES_UTILS
|
||||||
|
utils/applog.c
|
||||||
|
utils/summary.c
|
||||||
|
)
|
||||||
|
|
||||||
|
if (WIN32)
|
||||||
|
set(SOURCES_OS win/cpu_win.c win/memory_win.c win/xmrig_win.c compat/winansi.c)
|
||||||
|
set(EXTRA_LIBS ws2_32)
|
||||||
|
add_definitions(/D_WIN32_WINNT=0x600)
|
||||||
|
else()
|
||||||
|
set(SOURCES_OS unix/cpu_unix.c unix/memory_unix.c unix/xmrig_unix.c)
|
||||||
|
set(EXTRA_LIBS pthread)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include_directories(.)
|
||||||
|
add_definitions(/DUSE_NATIVE_THREADS)
|
||||||
|
add_definitions(/D_GNU_SOURCE)
|
||||||
|
add_definitions(/DDEBUG_THREADS)
|
||||||
|
|
||||||
|
if ("${CMAKE_BUILD_TYPE}" STREQUAL "")
|
||||||
|
set(CMAKE_BUILD_TYPE Release)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes -mbmi2")
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes -Wno-pointer-to-int-cast")
|
||||||
|
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Ofast -funroll-loops -fvariable-expansion-in-unroller -ftree-loop-if-convert-stores -fmerge-all-constants -fbranch-target-load-optimize2")
|
||||||
|
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -gdwarf-2")
|
||||||
|
#set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fprofile-generate")
|
||||||
|
#set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fprofile-use -fprofile-correction")
|
||||||
|
|
||||||
|
if (WIN32)
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include_directories(compat/jansson)
|
||||||
|
add_subdirectory(compat/jansson)
|
||||||
|
|
||||||
|
find_package(CURL REQUIRED)
|
||||||
|
|
||||||
|
if (CURL_FOUND)
|
||||||
|
include_directories(${CURL_INCLUDE_DIRS})
|
||||||
|
add_definitions(/DCURL_STATICLIB)
|
||||||
|
link_directories(${CURL_LIBRARIES})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||||
|
add_subdirectory(algo/cryptonight/bmi2)
|
||||||
|
|
||||||
|
set(CRYPTONIGHT64
|
||||||
|
algo/cryptonight/cryptonight_av1_aesni.c
|
||||||
|
algo/cryptonight/cryptonight_av2_aesni_wolf.c
|
||||||
|
algo/cryptonight/cryptonight_av4_legacy.c
|
||||||
|
algo/cryptonight/cryptonight_av5_aesni_experimental.c
|
||||||
|
)
|
||||||
|
|
||||||
|
add_executable(xmrig ${HEADERS} ${HEADERS_CRYPTO} ${SOURCES} ${SOURCES_CRYPTO} ${HEADERS_UTILS} ${SOURCES_UTILS} ${HEADERS_COMPAT} ${SOURCES_COMPAT} ${SOURCES_OS} ${CRYPTONIGHT64})
|
||||||
|
target_link_libraries(xmrig jansson curl cryptonight_av3_aesni_bmi2 ${EXTRA_LIBS})
|
||||||
|
else()
|
||||||
|
set(CRYPTONIGHT32
|
||||||
|
algo/cryptonight/cryptonight_av1_aesni32.c
|
||||||
|
algo/cryptonight/cryptonight_av4_legacy.c
|
||||||
|
)
|
||||||
|
|
||||||
|
add_executable(xmrig32 ${HEADERS} ${HEADERS_CRYPTO} ${SOURCES} ${SOURCES_CRYPTO} ${HEADERS_UTILS} ${SOURCES_UTILS} ${HEADERS_COMPAT} ${SOURCES_COMPAT} ${SOURCES_OS} ${CRYPTONIGHT32})
|
||||||
|
target_link_libraries(xmrig32 jansson -L${CURL_LIBRARIES} ${EXTRA_LIBS})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
source_group("HEADERS" FILES ${HEADERS})
|
94
README.md
Normal file
94
README.md
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
# XMRig
|
||||||
|
XMRig is high performance Monero (XMR) CPU miner, with the official full Windows support.
|
||||||
|
Based on cpuminer-multi with heavy optimizations/rewrites and removing a lot of legacy code.
|
||||||
|
|
||||||
|
#### Table of contents
|
||||||
|
* [Features](#features)
|
||||||
|
* [Download](#download)
|
||||||
|
* [Usage](#usage)
|
||||||
|
* [Build](#build)
|
||||||
|
* [Other information](#other-information)
|
||||||
|
|
||||||
|
## Features
|
||||||
|
* High performance, faster than others (290+ H/s on i7 6700).
|
||||||
|
* Official Windows support.
|
||||||
|
* Small Windows executable, only 350 KB without dependencies.
|
||||||
|
* Support for backup (failover) mining server.
|
||||||
|
* keepalived support.
|
||||||
|
* Command line options compatible with cpuminer.
|
||||||
|
* It's open source software.
|
||||||
|
|
||||||
|
## Download
|
||||||
|
* Binary releases: https://github.com/xmrig/xmrig/releases
|
||||||
|
* Git tree: https://github.com/xmrig/xmrig.git
|
||||||
|
* Clone with `git clone https://github.com/xmrig/xmrig.git`
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
### Basic example
|
||||||
|
```
|
||||||
|
xmrig.exe -o xmr-eu.dwarfpool.com:8005 -b xmr-usa.dwarfpool.com:8005 -u YOUR_WALLET -p x -k
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
```
|
||||||
|
-o, --url=URL URL of mining server
|
||||||
|
-b, --backup-url=URL URL of backup mining server
|
||||||
|
-O, --userpass=U:P username:password pair for mining server
|
||||||
|
-u, --user=USERNAME username for mining server
|
||||||
|
-p, --pass=PASSWORD password for mining server
|
||||||
|
-t, --threads=N number of miner threads
|
||||||
|
-v, --av=N algorithm variation, 0 auto select
|
||||||
|
-k, --keepalive send keepalived for prevent timeout (need pool support)
|
||||||
|
-r, --retries=N number of times to retry before switch to backup server (default: 5)
|
||||||
|
-R, --retry-pause=N time to pause between retries (default: 5)
|
||||||
|
--cpu-affinity set process affinity to cpu core(s), mask 0x3 for cores 0 and 1
|
||||||
|
--no-color disable colored output
|
||||||
|
--donate-level=N donate level, default 5% (5 minutes in 100 minutes)
|
||||||
|
-B, --background run the miner in the background
|
||||||
|
-c, --config=FILE load a JSON-format configuration file
|
||||||
|
-h, --help display this help and exit
|
||||||
|
-V, --version output version information and exit
|
||||||
|
```
|
||||||
|
|
||||||
|
## Build
|
||||||
|
### Ubuntu (Debian-based distros)
|
||||||
|
```
|
||||||
|
sudo apt-get install git build-essential cmake libcurl4-openssl-dev
|
||||||
|
git clone https://github.com/xmrig/xmrig.git
|
||||||
|
cd xmrig
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake ..
|
||||||
|
make
|
||||||
|
```
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
It's complicated, you need [MSYS2](http://www.msys2.org/), custom libcurl build, and of course CMake too.
|
||||||
|
Configure options for libcurl:
|
||||||
|
```
|
||||||
|
./configure --disable-shared --enable-optimize --enable-threaded-resolver --disable-libcurl-option --disable-ares --disable-rt --disable-ftp --disable-file --disable-ldap --disable-ldaps --disable-rtsp --disable-dict --disable-telnet --disable-tftp --disable-pop3 --disable-imap --disable-smb --disable-smtp --disable-gopher --disable-manual --disable-ipv6 --disable-sspi --disable-crypto-auth --disable-ntlm-wb --disable-tls-srp --disable-unix-sockets --without-zlib --without-winssl --without-ssl --without-libssh2 --without-nghttp2 --disable-cookies --without-ca-bundle
|
||||||
|
```
|
||||||
|
CMake options:
|
||||||
|
```
|
||||||
|
cmake .. -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DCURL_INCLUDE_DIR="c:\<path>\curl-7.53.1\include" -DCURL_LIBRARY="c:\<path>\curl-7.53.1\lib\.libs"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Other information
|
||||||
|
* Now only support 64 bit operating systems (Windows/Linux).
|
||||||
|
* No HTTP support, only stratum protocol support.
|
||||||
|
* No TLS support.
|
||||||
|
* Default donation 5% (5 minutes in 100 minutes) can be reduced to 1% via command line option `--donate-level`.
|
||||||
|
|
||||||
|
|
||||||
|
### CPU mining performance
|
||||||
|
* **i7-6700** - 290+ H/s (4 threads, cpu affinity 0xAA)
|
||||||
|
* **Dual E5620** - 377 H/s (12 threads, cpu affinity 0xEEEE)
|
||||||
|
|
||||||
|
Please note performance is highly dependent on system load. The numbers above are obtained on an idle system. Tasks heavily using a processor cache, such as video playback, can greatly degrade hashrate. Optimal number of threads depends on the size of the L3 cache of a processor, 1 thread requires 2 MB of cache.
|
||||||
|
|
||||||
|
### Maximum performance checklist
|
||||||
|
* Idle operating system.
|
||||||
|
* Do not exceed optimal thread count.
|
||||||
|
* Use modern CPUs with AES-NI instructuon set.
|
||||||
|
* Try setup optimal cpu affinity.
|
||||||
|
* Enable fast memory (Large/Huge pages).
|
2
algo/cryptonight/bmi2/CMakeLists.txt
Normal file
2
algo/cryptonight/bmi2/CMakeLists.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mbmi2")
|
||||||
|
add_library(cryptonight_av3_aesni_bmi2 STATIC ../cryptonight_av3_aesni_bmi2.c)
|
72
algo/cryptonight/cryptonight.h
Normal file
72
algo/cryptonight/cryptonight.h
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __CRYPTONIGHT_H__
|
||||||
|
#define __CRYPTONIGHT_H__
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define MEMORY (1 << 21) /* 2 MiB */
|
||||||
|
#define MEMORY_M128I (MEMORY >> 4) // 2 MiB / 16 = 128 ki * __m128i
|
||||||
|
#define ITER (1 << 20)
|
||||||
|
#define AES_BLOCK_SIZE 16
|
||||||
|
#define AES_KEY_SIZE 32 /*16*/
|
||||||
|
#define INIT_SIZE_BLK 8
|
||||||
|
#define INIT_SIZE_BYTE (INIT_SIZE_BLK * AES_BLOCK_SIZE) // 128
|
||||||
|
#define INIT_SIZE_M128I (INIT_SIZE_BYTE >> 4) // 8
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
union hash_state {
|
||||||
|
uint8_t b[200];
|
||||||
|
uint64_t w[25];
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
union cn_slow_hash_state {
|
||||||
|
union hash_state hs;
|
||||||
|
struct {
|
||||||
|
uint8_t k[64];
|
||||||
|
uint8_t init[INIT_SIZE_BYTE];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
|
||||||
|
struct cryptonight_ctx {
|
||||||
|
union cn_slow_hash_state state;
|
||||||
|
uint8_t text[INIT_SIZE_BYTE] __attribute((aligned(16)));
|
||||||
|
uint64_t a[2] __attribute__((aligned(16)));
|
||||||
|
uint64_t b[2] __attribute__((aligned(16)));
|
||||||
|
uint64_t c[2] __attribute__((aligned(16)));
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
extern void (* const extra_hashes[4])(const void *, size_t, char *);
|
||||||
|
|
||||||
|
void cryptonight_init(int variant);
|
||||||
|
void cryptonight_hash(void* output, const void* input, size_t input_len);
|
||||||
|
int scanhash_cryptonight(int thr_id, uint32_t *hash, uint32_t *restrict pdata, const uint32_t *restrict ptarget, uint32_t max_nonce, unsigned long *restrict hashes_done, const char *memory, struct cryptonight_ctx *persistentctx);
|
||||||
|
|
||||||
|
#endif /* __CRYPTONIGHT_H__ */
|
216
algo/cryptonight/cryptonight_av1_aesni.c
Normal file
216
algo/cryptonight/cryptonight_av1_aesni.c
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <x86intrin.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "cryptonight.h"
|
||||||
|
#include "crypto/c_keccak.h"
|
||||||
|
|
||||||
|
|
||||||
|
static inline void ExpandAESKey256_sub1(__m128i *tmp1, __m128i *tmp2)
|
||||||
|
{
|
||||||
|
__m128i tmp4;
|
||||||
|
*tmp2 = _mm_shuffle_epi32(*tmp2, 0xFF);
|
||||||
|
tmp4 = _mm_slli_si128(*tmp1, 0x04);
|
||||||
|
*tmp1 = _mm_xor_si128(*tmp1, tmp4);
|
||||||
|
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
||||||
|
*tmp1 = _mm_xor_si128(*tmp1, tmp4);
|
||||||
|
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
||||||
|
*tmp1 = _mm_xor_si128(*tmp1, tmp4);
|
||||||
|
*tmp1 = _mm_xor_si128(*tmp1, *tmp2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ExpandAESKey256_sub2(__m128i *tmp1, __m128i *tmp3)
|
||||||
|
{
|
||||||
|
__m128i tmp2, tmp4;
|
||||||
|
|
||||||
|
tmp4 = _mm_aeskeygenassist_si128(*tmp1, 0x00);
|
||||||
|
tmp2 = _mm_shuffle_epi32(tmp4, 0xAA);
|
||||||
|
tmp4 = _mm_slli_si128(*tmp3, 0x04);
|
||||||
|
*tmp3 = _mm_xor_si128(*tmp3, tmp4);
|
||||||
|
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
||||||
|
*tmp3 = _mm_xor_si128(*tmp3, tmp4);
|
||||||
|
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
||||||
|
*tmp3 = _mm_xor_si128(*tmp3, tmp4);
|
||||||
|
*tmp3 = _mm_xor_si128(*tmp3, tmp2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Special thanks to Intel for helping me
|
||||||
|
// with ExpandAESKey256() and its subroutines
|
||||||
|
static inline void ExpandAESKey256(char *keybuf)
|
||||||
|
{
|
||||||
|
__m128i tmp1, tmp2, tmp3, *keys;
|
||||||
|
|
||||||
|
keys = (__m128i *)keybuf;
|
||||||
|
|
||||||
|
tmp1 = _mm_load_si128((__m128i *)keybuf);
|
||||||
|
tmp3 = _mm_load_si128((__m128i *)(keybuf+0x10));
|
||||||
|
|
||||||
|
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x01);
|
||||||
|
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
||||||
|
keys[2] = tmp1;
|
||||||
|
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
||||||
|
keys[3] = tmp3;
|
||||||
|
|
||||||
|
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x02);
|
||||||
|
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
||||||
|
keys[4] = tmp1;
|
||||||
|
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
||||||
|
keys[5] = tmp3;
|
||||||
|
|
||||||
|
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x04);
|
||||||
|
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
||||||
|
keys[6] = tmp1;
|
||||||
|
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
||||||
|
keys[7] = tmp3;
|
||||||
|
|
||||||
|
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x08);
|
||||||
|
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
||||||
|
keys[8] = tmp1;
|
||||||
|
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
||||||
|
keys[9] = tmp3;
|
||||||
|
|
||||||
|
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x10);
|
||||||
|
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
||||||
|
keys[10] = tmp1;
|
||||||
|
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
||||||
|
keys[11] = tmp3;
|
||||||
|
|
||||||
|
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x20);
|
||||||
|
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
||||||
|
keys[12] = tmp1;
|
||||||
|
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
||||||
|
keys[13] = tmp3;
|
||||||
|
|
||||||
|
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x40);
|
||||||
|
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
||||||
|
keys[14] = tmp1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cryptonight_av1_aesni(void *restrict output, const void *restrict input, const char *restrict memory, struct cryptonight_ctx *restrict ctx)
|
||||||
|
{
|
||||||
|
keccak((const uint8_t *)input, 76, (uint8_t *) &ctx->state.hs, 200);
|
||||||
|
uint8_t ExpandedKey[256];
|
||||||
|
size_t i, j;
|
||||||
|
|
||||||
|
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
|
||||||
|
memcpy(ExpandedKey, ctx->state.hs.b, AES_KEY_SIZE);
|
||||||
|
ExpandAESKey256(ExpandedKey);
|
||||||
|
|
||||||
|
__m128i *longoutput, *expkey, *xmminput;
|
||||||
|
longoutput = (__m128i *) memory;
|
||||||
|
expkey = (__m128i *)ExpandedKey;
|
||||||
|
xmminput = (__m128i *)ctx->text;
|
||||||
|
|
||||||
|
for (i = 0; __builtin_expect(i < MEMORY, 1); i += INIT_SIZE_BYTE)
|
||||||
|
{
|
||||||
|
for(j = 0; j < 10; j++)
|
||||||
|
{
|
||||||
|
xmminput[0] = _mm_aesenc_si128(xmminput[0], expkey[j]);
|
||||||
|
xmminput[1] = _mm_aesenc_si128(xmminput[1], expkey[j]);
|
||||||
|
xmminput[2] = _mm_aesenc_si128(xmminput[2], expkey[j]);
|
||||||
|
xmminput[3] = _mm_aesenc_si128(xmminput[3], expkey[j]);
|
||||||
|
xmminput[4] = _mm_aesenc_si128(xmminput[4], expkey[j]);
|
||||||
|
xmminput[5] = _mm_aesenc_si128(xmminput[5], expkey[j]);
|
||||||
|
xmminput[6] = _mm_aesenc_si128(xmminput[6], expkey[j]);
|
||||||
|
xmminput[7] = _mm_aesenc_si128(xmminput[7], expkey[j]);
|
||||||
|
}
|
||||||
|
_mm_store_si128(&(longoutput[(i >> 4)]), xmminput[0]);
|
||||||
|
_mm_store_si128(&(longoutput[(i >> 4) + 1]), xmminput[1]);
|
||||||
|
_mm_store_si128(&(longoutput[(i >> 4) + 2]), xmminput[2]);
|
||||||
|
_mm_store_si128(&(longoutput[(i >> 4) + 3]), xmminput[3]);
|
||||||
|
_mm_store_si128(&(longoutput[(i >> 4) + 4]), xmminput[4]);
|
||||||
|
_mm_store_si128(&(longoutput[(i >> 4) + 5]), xmminput[5]);
|
||||||
|
_mm_store_si128(&(longoutput[(i >> 4) + 6]), xmminput[6]);
|
||||||
|
_mm_store_si128(&(longoutput[(i >> 4) + 7]), xmminput[7]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 2; i++)
|
||||||
|
{
|
||||||
|
ctx->a[i] = ((uint64_t *)ctx->state.k)[i] ^ ((uint64_t *)ctx->state.k)[i+4];
|
||||||
|
ctx->b[i] = ((uint64_t *)ctx->state.k)[i+2] ^ ((uint64_t *)ctx->state.k)[i+6];
|
||||||
|
}
|
||||||
|
|
||||||
|
__m128i a_x = _mm_load_si128((__m128i *) &memory[ctx->a[0] & 0x1FFFF0]);
|
||||||
|
__m128i b_x = _mm_load_si128((__m128i *) ctx->b);
|
||||||
|
|
||||||
|
uint64_t c[2] __attribute((aligned(16)));
|
||||||
|
uint64_t d[2] __attribute((aligned(16)));
|
||||||
|
|
||||||
|
for (i = 0; __builtin_expect(i < 0x80000, 1); i++) {
|
||||||
|
__m128i c_x = _mm_aesenc_si128(a_x, _mm_load_si128((__m128i *) ctx->a));
|
||||||
|
_mm_store_si128((__m128i *) c, c_x);
|
||||||
|
|
||||||
|
uint64_t *restrict d_ptr = (uint64_t *) &memory[c[0] & 0x1FFFF0];
|
||||||
|
_mm_store_si128((__m128i *) &memory[ctx->a[0] & 0x1FFFF0], _mm_xor_si128(b_x, c_x));
|
||||||
|
b_x = c_x;
|
||||||
|
|
||||||
|
d[0] = d_ptr[0];
|
||||||
|
d[1] = d_ptr[1];
|
||||||
|
|
||||||
|
{
|
||||||
|
unsigned __int128 res = (unsigned __int128) c[0] * d[0];
|
||||||
|
|
||||||
|
d_ptr[0] = ctx->a[0] += res >> 64;
|
||||||
|
d_ptr[1] = ctx->a[1] += (uint64_t) res;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->a[0] ^= d[0];
|
||||||
|
ctx->a[1] ^= d[1];
|
||||||
|
|
||||||
|
a_x = _mm_load_si128((__m128i *) &memory[ctx->a[0] & 0x1FFFF0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
|
||||||
|
memcpy(ExpandedKey, &ctx->state.hs.b[32], AES_KEY_SIZE);
|
||||||
|
ExpandAESKey256(ExpandedKey);
|
||||||
|
|
||||||
|
for (i = 0; __builtin_expect(i < MEMORY, 1); i += INIT_SIZE_BYTE) {
|
||||||
|
xmminput[0] = _mm_xor_si128(longoutput[(i >> 4)], xmminput[0]);
|
||||||
|
xmminput[1] = _mm_xor_si128(longoutput[(i >> 4) + 1], xmminput[1]);
|
||||||
|
xmminput[2] = _mm_xor_si128(longoutput[(i >> 4) + 2], xmminput[2]);
|
||||||
|
xmminput[3] = _mm_xor_si128(longoutput[(i >> 4) + 3], xmminput[3]);
|
||||||
|
xmminput[4] = _mm_xor_si128(longoutput[(i >> 4) + 4], xmminput[4]);
|
||||||
|
xmminput[5] = _mm_xor_si128(longoutput[(i >> 4) + 5], xmminput[5]);
|
||||||
|
xmminput[6] = _mm_xor_si128(longoutput[(i >> 4) + 6], xmminput[6]);
|
||||||
|
xmminput[7] = _mm_xor_si128(longoutput[(i >> 4) + 7], xmminput[7]);
|
||||||
|
|
||||||
|
for(j = 0; j < 10; j++)
|
||||||
|
{
|
||||||
|
xmminput[0] = _mm_aesenc_si128(xmminput[0], expkey[j]);
|
||||||
|
xmminput[1] = _mm_aesenc_si128(xmminput[1], expkey[j]);
|
||||||
|
xmminput[2] = _mm_aesenc_si128(xmminput[2], expkey[j]);
|
||||||
|
xmminput[3] = _mm_aesenc_si128(xmminput[3], expkey[j]);
|
||||||
|
xmminput[4] = _mm_aesenc_si128(xmminput[4], expkey[j]);
|
||||||
|
xmminput[5] = _mm_aesenc_si128(xmminput[5], expkey[j]);
|
||||||
|
xmminput[6] = _mm_aesenc_si128(xmminput[6], expkey[j]);
|
||||||
|
xmminput[7] = _mm_aesenc_si128(xmminput[7], expkey[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(ctx->state.init, ctx->text, INIT_SIZE_BYTE);
|
||||||
|
keccakf((uint64_t *) &ctx->state.hs, 24);
|
||||||
|
extra_hashes[ctx->state.hs.b[0] & 3](&ctx->state, 200, output);
|
||||||
|
}
|
239
algo/cryptonight/cryptonight_av1_aesni32.c
Normal file
239
algo/cryptonight/cryptonight_av1_aesni32.c
Normal file
@ -0,0 +1,239 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <x86intrin.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "cryptonight.h"
|
||||||
|
#include "crypto/c_keccak.h"
|
||||||
|
|
||||||
|
|
||||||
|
static inline uint64_t mul128(uint64_t multiplier, uint64_t multiplicand, uint64_t *product_hi) {
|
||||||
|
// multiplier = ab = a * 2^32 + b
|
||||||
|
// multiplicand = cd = c * 2^32 + d
|
||||||
|
// ab * cd = a * c * 2^64 + (a * d + b * c) * 2^32 + b * d
|
||||||
|
uint64_t a = multiplier >> 32;
|
||||||
|
uint64_t b = multiplier & 0xFFFFFFFF;
|
||||||
|
uint64_t c = multiplicand >> 32;
|
||||||
|
uint64_t d = multiplicand & 0xFFFFFFFF;
|
||||||
|
|
||||||
|
//uint64_t ac = a * c;
|
||||||
|
uint64_t ad = a * d;
|
||||||
|
//uint64_t bc = b * c;
|
||||||
|
uint64_t bd = b * d;
|
||||||
|
|
||||||
|
uint64_t adbc = ad + (b * c);
|
||||||
|
uint64_t adbc_carry = adbc < ad ? 1 : 0;
|
||||||
|
|
||||||
|
// multiplier * multiplicand = product_hi * 2^64 + product_lo
|
||||||
|
uint64_t product_lo = bd + (adbc << 32);
|
||||||
|
uint64_t product_lo_carry = product_lo < bd ? 1 : 0;
|
||||||
|
*product_hi = (a * c) + (adbc >> 32) + (adbc_carry << 32) + product_lo_carry;
|
||||||
|
|
||||||
|
return product_lo;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline void ExpandAESKey256_sub1(__m128i *tmp1, __m128i *tmp2)
|
||||||
|
{
|
||||||
|
__m128i tmp4;
|
||||||
|
*tmp2 = _mm_shuffle_epi32(*tmp2, 0xFF);
|
||||||
|
tmp4 = _mm_slli_si128(*tmp1, 0x04);
|
||||||
|
*tmp1 = _mm_xor_si128(*tmp1, tmp4);
|
||||||
|
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
||||||
|
*tmp1 = _mm_xor_si128(*tmp1, tmp4);
|
||||||
|
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
||||||
|
*tmp1 = _mm_xor_si128(*tmp1, tmp4);
|
||||||
|
*tmp1 = _mm_xor_si128(*tmp1, *tmp2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ExpandAESKey256_sub2(__m128i *tmp1, __m128i *tmp3)
|
||||||
|
{
|
||||||
|
__m128i tmp2, tmp4;
|
||||||
|
|
||||||
|
tmp4 = _mm_aeskeygenassist_si128(*tmp1, 0x00);
|
||||||
|
tmp2 = _mm_shuffle_epi32(tmp4, 0xAA);
|
||||||
|
tmp4 = _mm_slli_si128(*tmp3, 0x04);
|
||||||
|
*tmp3 = _mm_xor_si128(*tmp3, tmp4);
|
||||||
|
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
||||||
|
*tmp3 = _mm_xor_si128(*tmp3, tmp4);
|
||||||
|
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
||||||
|
*tmp3 = _mm_xor_si128(*tmp3, tmp4);
|
||||||
|
*tmp3 = _mm_xor_si128(*tmp3, tmp2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Special thanks to Intel for helping me
|
||||||
|
// with ExpandAESKey256() and its subroutines
|
||||||
|
static inline void ExpandAESKey256(char *keybuf)
|
||||||
|
{
|
||||||
|
__m128i tmp1, tmp2, tmp3, *keys;
|
||||||
|
|
||||||
|
keys = (__m128i *)keybuf;
|
||||||
|
|
||||||
|
tmp1 = _mm_load_si128((__m128i *)keybuf);
|
||||||
|
tmp3 = _mm_load_si128((__m128i *)(keybuf+0x10));
|
||||||
|
|
||||||
|
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x01);
|
||||||
|
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
||||||
|
keys[2] = tmp1;
|
||||||
|
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
||||||
|
keys[3] = tmp3;
|
||||||
|
|
||||||
|
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x02);
|
||||||
|
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
||||||
|
keys[4] = tmp1;
|
||||||
|
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
||||||
|
keys[5] = tmp3;
|
||||||
|
|
||||||
|
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x04);
|
||||||
|
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
||||||
|
keys[6] = tmp1;
|
||||||
|
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
||||||
|
keys[7] = tmp3;
|
||||||
|
|
||||||
|
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x08);
|
||||||
|
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
||||||
|
keys[8] = tmp1;
|
||||||
|
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
||||||
|
keys[9] = tmp3;
|
||||||
|
|
||||||
|
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x10);
|
||||||
|
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
||||||
|
keys[10] = tmp1;
|
||||||
|
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
||||||
|
keys[11] = tmp3;
|
||||||
|
|
||||||
|
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x20);
|
||||||
|
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
||||||
|
keys[12] = tmp1;
|
||||||
|
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
||||||
|
keys[13] = tmp3;
|
||||||
|
|
||||||
|
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x40);
|
||||||
|
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
||||||
|
keys[14] = tmp1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cryptonight_av1_aesni32(void *restrict output, const void *restrict input, const char *restrict memory, struct cryptonight_ctx *restrict ctx)
|
||||||
|
{
|
||||||
|
keccak((const uint8_t *)input, 76, (uint8_t *) &ctx->state.hs, 200);
|
||||||
|
uint8_t ExpandedKey[256];
|
||||||
|
size_t i, j;
|
||||||
|
|
||||||
|
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
|
||||||
|
memcpy(ExpandedKey, ctx->state.hs.b, AES_KEY_SIZE);
|
||||||
|
ExpandAESKey256(ExpandedKey);
|
||||||
|
|
||||||
|
__m128i *longoutput, *expkey, *xmminput;
|
||||||
|
longoutput = (__m128i *) memory;
|
||||||
|
expkey = (__m128i *)ExpandedKey;
|
||||||
|
xmminput = (__m128i *)ctx->text;
|
||||||
|
|
||||||
|
for (i = 0; __builtin_expect(i < MEMORY, 1); i += INIT_SIZE_BYTE)
|
||||||
|
{
|
||||||
|
for(j = 0; j < 10; j++)
|
||||||
|
{
|
||||||
|
xmminput[0] = _mm_aesenc_si128(xmminput[0], expkey[j]);
|
||||||
|
xmminput[1] = _mm_aesenc_si128(xmminput[1], expkey[j]);
|
||||||
|
xmminput[2] = _mm_aesenc_si128(xmminput[2], expkey[j]);
|
||||||
|
xmminput[3] = _mm_aesenc_si128(xmminput[3], expkey[j]);
|
||||||
|
xmminput[4] = _mm_aesenc_si128(xmminput[4], expkey[j]);
|
||||||
|
xmminput[5] = _mm_aesenc_si128(xmminput[5], expkey[j]);
|
||||||
|
xmminput[6] = _mm_aesenc_si128(xmminput[6], expkey[j]);
|
||||||
|
xmminput[7] = _mm_aesenc_si128(xmminput[7], expkey[j]);
|
||||||
|
}
|
||||||
|
_mm_store_si128(&(longoutput[(i >> 4)]), xmminput[0]);
|
||||||
|
_mm_store_si128(&(longoutput[(i >> 4) + 1]), xmminput[1]);
|
||||||
|
_mm_store_si128(&(longoutput[(i >> 4) + 2]), xmminput[2]);
|
||||||
|
_mm_store_si128(&(longoutput[(i >> 4) + 3]), xmminput[3]);
|
||||||
|
_mm_store_si128(&(longoutput[(i >> 4) + 4]), xmminput[4]);
|
||||||
|
_mm_store_si128(&(longoutput[(i >> 4) + 5]), xmminput[5]);
|
||||||
|
_mm_store_si128(&(longoutput[(i >> 4) + 6]), xmminput[6]);
|
||||||
|
_mm_store_si128(&(longoutput[(i >> 4) + 7]), xmminput[7]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 2; i++)
|
||||||
|
{
|
||||||
|
ctx->a[i] = ((uint64_t *)ctx->state.k)[i] ^ ((uint64_t *)ctx->state.k)[i+4];
|
||||||
|
ctx->b[i] = ((uint64_t *)ctx->state.k)[i+2] ^ ((uint64_t *)ctx->state.k)[i+6];
|
||||||
|
}
|
||||||
|
|
||||||
|
__m128i a_x = _mm_load_si128((__m128i *) &memory[ctx->a[0] & 0x1FFFF0]);
|
||||||
|
__m128i b_x = _mm_load_si128((__m128i *) ctx->b);
|
||||||
|
|
||||||
|
uint64_t c[2] __attribute((aligned(16)));
|
||||||
|
uint64_t d[2] __attribute((aligned(16)));
|
||||||
|
uint64_t hi;
|
||||||
|
|
||||||
|
for (i = 0; __builtin_expect(i < 0x80000, 1); i++) {
|
||||||
|
__m128i c_x = _mm_aesenc_si128(a_x, _mm_load_si128((__m128i *) ctx->a));
|
||||||
|
_mm_store_si128((__m128i *) c, c_x);
|
||||||
|
|
||||||
|
uint64_t *restrict d_ptr = (uint64_t *) &memory[c[0] & 0x1FFFF0];
|
||||||
|
_mm_store_si128((__m128i *) &memory[ctx->a[0] & 0x1FFFF0], _mm_xor_si128(b_x, c_x));
|
||||||
|
b_x = c_x;
|
||||||
|
|
||||||
|
d[0] = d_ptr[0];
|
||||||
|
d[1] = d_ptr[1];
|
||||||
|
|
||||||
|
d_ptr[1] = ctx->a[1] += mul128(c[0], d[0], &hi);
|
||||||
|
d_ptr[0] = ctx->a[0] += hi;
|
||||||
|
|
||||||
|
ctx->a[0] ^= d[0];
|
||||||
|
ctx->a[1] ^= d[1];
|
||||||
|
|
||||||
|
a_x = _mm_load_si128((__m128i *) &memory[ctx->a[0] & 0x1FFFF0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
|
||||||
|
memcpy(ExpandedKey, &ctx->state.hs.b[32], AES_KEY_SIZE);
|
||||||
|
ExpandAESKey256(ExpandedKey);
|
||||||
|
|
||||||
|
for (i = 0; __builtin_expect(i < MEMORY, 1); i += INIT_SIZE_BYTE) {
|
||||||
|
xmminput[0] = _mm_xor_si128(longoutput[(i >> 4)], xmminput[0]);
|
||||||
|
xmminput[1] = _mm_xor_si128(longoutput[(i >> 4) + 1], xmminput[1]);
|
||||||
|
xmminput[2] = _mm_xor_si128(longoutput[(i >> 4) + 2], xmminput[2]);
|
||||||
|
xmminput[3] = _mm_xor_si128(longoutput[(i >> 4) + 3], xmminput[3]);
|
||||||
|
xmminput[4] = _mm_xor_si128(longoutput[(i >> 4) + 4], xmminput[4]);
|
||||||
|
xmminput[5] = _mm_xor_si128(longoutput[(i >> 4) + 5], xmminput[5]);
|
||||||
|
xmminput[6] = _mm_xor_si128(longoutput[(i >> 4) + 6], xmminput[6]);
|
||||||
|
xmminput[7] = _mm_xor_si128(longoutput[(i >> 4) + 7], xmminput[7]);
|
||||||
|
|
||||||
|
for(j = 0; j < 10; j++)
|
||||||
|
{
|
||||||
|
xmminput[0] = _mm_aesenc_si128(xmminput[0], expkey[j]);
|
||||||
|
xmminput[1] = _mm_aesenc_si128(xmminput[1], expkey[j]);
|
||||||
|
xmminput[2] = _mm_aesenc_si128(xmminput[2], expkey[j]);
|
||||||
|
xmminput[3] = _mm_aesenc_si128(xmminput[3], expkey[j]);
|
||||||
|
xmminput[4] = _mm_aesenc_si128(xmminput[4], expkey[j]);
|
||||||
|
xmminput[5] = _mm_aesenc_si128(xmminput[5], expkey[j]);
|
||||||
|
xmminput[6] = _mm_aesenc_si128(xmminput[6], expkey[j]);
|
||||||
|
xmminput[7] = _mm_aesenc_si128(xmminput[7], expkey[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(ctx->state.init, ctx->text, INIT_SIZE_BYTE);
|
||||||
|
keccakf((uint64_t *) &ctx->state.hs, 24);
|
||||||
|
extra_hashes[ctx->state.hs.b[0] & 3](&ctx->state, 200, output);
|
||||||
|
}
|
237
algo/cryptonight/cryptonight_av2_aesni_wolf.c
Normal file
237
algo/cryptonight/cryptonight_av2_aesni_wolf.c
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <x86intrin.h>
|
||||||
|
|
||||||
|
#include "cryptonight.h"
|
||||||
|
#include "crypto/c_keccak.h"
|
||||||
|
|
||||||
|
|
||||||
|
static inline void ExpandAESKey256_sub1(__m128i *tmp1, __m128i *tmp2)
|
||||||
|
{
|
||||||
|
__m128i tmp4;
|
||||||
|
*tmp2 = _mm_shuffle_epi32(*tmp2, 0xFF);
|
||||||
|
tmp4 = _mm_slli_si128(*tmp1, 0x04);
|
||||||
|
*tmp1 = _mm_xor_si128(*tmp1, tmp4);
|
||||||
|
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
||||||
|
*tmp1 = _mm_xor_si128(*tmp1, tmp4);
|
||||||
|
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
||||||
|
*tmp1 = _mm_xor_si128(*tmp1, tmp4);
|
||||||
|
*tmp1 = _mm_xor_si128(*tmp1, *tmp2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ExpandAESKey256_sub2(__m128i *tmp1, __m128i *tmp3)
|
||||||
|
{
|
||||||
|
__m128i tmp2, tmp4;
|
||||||
|
|
||||||
|
tmp4 = _mm_aeskeygenassist_si128(*tmp1, 0x00);
|
||||||
|
tmp2 = _mm_shuffle_epi32(tmp4, 0xAA);
|
||||||
|
tmp4 = _mm_slli_si128(*tmp3, 0x04);
|
||||||
|
*tmp3 = _mm_xor_si128(*tmp3, tmp4);
|
||||||
|
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
||||||
|
*tmp3 = _mm_xor_si128(*tmp3, tmp4);
|
||||||
|
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
||||||
|
*tmp3 = _mm_xor_si128(*tmp3, tmp4);
|
||||||
|
*tmp3 = _mm_xor_si128(*tmp3, tmp2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Special thanks to Intel for helping me
|
||||||
|
// with ExpandAESKey256() and its subroutines
|
||||||
|
static inline void ExpandAESKey256(char *keybuf)
|
||||||
|
{
|
||||||
|
__m128i tmp1, tmp2, tmp3, *keys;
|
||||||
|
|
||||||
|
keys = (__m128i *)keybuf;
|
||||||
|
|
||||||
|
tmp1 = _mm_load_si128((__m128i *)keybuf);
|
||||||
|
tmp3 = _mm_load_si128((__m128i *)(keybuf+0x10));
|
||||||
|
|
||||||
|
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x01);
|
||||||
|
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
||||||
|
keys[2] = tmp1;
|
||||||
|
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
||||||
|
keys[3] = tmp3;
|
||||||
|
|
||||||
|
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x02);
|
||||||
|
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
||||||
|
keys[4] = tmp1;
|
||||||
|
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
||||||
|
keys[5] = tmp3;
|
||||||
|
|
||||||
|
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x04);
|
||||||
|
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
||||||
|
keys[6] = tmp1;
|
||||||
|
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
||||||
|
keys[7] = tmp3;
|
||||||
|
|
||||||
|
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x08);
|
||||||
|
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
||||||
|
keys[8] = tmp1;
|
||||||
|
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
||||||
|
keys[9] = tmp3;
|
||||||
|
|
||||||
|
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x10);
|
||||||
|
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
||||||
|
keys[10] = tmp1;
|
||||||
|
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
||||||
|
keys[11] = tmp3;
|
||||||
|
|
||||||
|
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x20);
|
||||||
|
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
||||||
|
keys[12] = tmp1;
|
||||||
|
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
||||||
|
keys[13] = tmp3;
|
||||||
|
|
||||||
|
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x40);
|
||||||
|
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
||||||
|
keys[14] = tmp1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cryptonight_av2_aesni_wolf(void *restrict output, const void *restrict input, const char *restrict memory, struct cryptonight_ctx *restrict ctx)
|
||||||
|
{
|
||||||
|
keccak((const uint8_t *) input, 76, (uint8_t *) &ctx->state.hs, 200);
|
||||||
|
uint8_t ExpandedKey[256];
|
||||||
|
size_t i, j;
|
||||||
|
|
||||||
|
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
|
||||||
|
memcpy(ExpandedKey, ctx->state.hs.b, AES_KEY_SIZE);
|
||||||
|
ExpandAESKey256(ExpandedKey);
|
||||||
|
|
||||||
|
__m128i *longoutput, *expkey, *xmminput;
|
||||||
|
longoutput = (__m128i *)memory;
|
||||||
|
expkey = (__m128i *)ExpandedKey;
|
||||||
|
xmminput = (__m128i *)ctx->text;
|
||||||
|
|
||||||
|
for (i = 0; __builtin_expect(i < MEMORY, 1); i += INIT_SIZE_BYTE)
|
||||||
|
{
|
||||||
|
for(j = 0; j < 10; j++)
|
||||||
|
{
|
||||||
|
xmminput[0] = _mm_aesenc_si128(xmminput[0], expkey[j]);
|
||||||
|
xmminput[1] = _mm_aesenc_si128(xmminput[1], expkey[j]);
|
||||||
|
xmminput[2] = _mm_aesenc_si128(xmminput[2], expkey[j]);
|
||||||
|
xmminput[3] = _mm_aesenc_si128(xmminput[3], expkey[j]);
|
||||||
|
xmminput[4] = _mm_aesenc_si128(xmminput[4], expkey[j]);
|
||||||
|
xmminput[5] = _mm_aesenc_si128(xmminput[5], expkey[j]);
|
||||||
|
xmminput[6] = _mm_aesenc_si128(xmminput[6], expkey[j]);
|
||||||
|
xmminput[7] = _mm_aesenc_si128(xmminput[7], expkey[j]);
|
||||||
|
}
|
||||||
|
_mm_store_si128(&(longoutput[(i >> 4)]), xmminput[0]);
|
||||||
|
_mm_store_si128(&(longoutput[(i >> 4) + 1]), xmminput[1]);
|
||||||
|
_mm_store_si128(&(longoutput[(i >> 4) + 2]), xmminput[2]);
|
||||||
|
_mm_store_si128(&(longoutput[(i >> 4) + 3]), xmminput[3]);
|
||||||
|
_mm_store_si128(&(longoutput[(i >> 4) + 4]), xmminput[4]);
|
||||||
|
_mm_store_si128(&(longoutput[(i >> 4) + 5]), xmminput[5]);
|
||||||
|
_mm_store_si128(&(longoutput[(i >> 4) + 6]), xmminput[6]);
|
||||||
|
_mm_store_si128(&(longoutput[(i >> 4) + 7]), xmminput[7]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 2; i++)
|
||||||
|
{
|
||||||
|
ctx->a[i] = ((uint64_t *)ctx->state.k)[i] ^ ((uint64_t *)ctx->state.k)[i+4];
|
||||||
|
ctx->b[i] = ((uint64_t *)ctx->state.k)[i+2] ^ ((uint64_t *)ctx->state.k)[i+6];
|
||||||
|
}
|
||||||
|
|
||||||
|
__m128i b_x = _mm_load_si128((__m128i *)ctx->b);
|
||||||
|
uint64_t a[2] __attribute((aligned(16))), b[2] __attribute((aligned(16)));
|
||||||
|
a[0] = ctx->a[0];
|
||||||
|
a[1] = ctx->a[1];
|
||||||
|
|
||||||
|
for(i = 0; __builtin_expect(i < 0x80000, 1); i++)
|
||||||
|
{
|
||||||
|
__m128i c_x = _mm_load_si128((__m128i *)&memory[a[0] & 0x1FFFF0]);
|
||||||
|
__m128i a_x = _mm_load_si128((__m128i *)a);
|
||||||
|
uint64_t c[2];
|
||||||
|
c_x = _mm_aesenc_si128(c_x, a_x);
|
||||||
|
|
||||||
|
_mm_store_si128((__m128i *)c, c_x);
|
||||||
|
__builtin_prefetch(&memory[c[0] & 0x1FFFF0], 0, 1);
|
||||||
|
|
||||||
|
b_x = _mm_xor_si128(b_x, c_x);
|
||||||
|
_mm_store_si128((__m128i *)&memory[a[0] & 0x1FFFF0], b_x);
|
||||||
|
|
||||||
|
uint64_t *nextblock = (uint64_t *)&memory[c[0] & 0x1FFFF0];
|
||||||
|
uint64_t b[2];
|
||||||
|
b[0] = nextblock[0];
|
||||||
|
b[1] = nextblock[1];
|
||||||
|
|
||||||
|
{
|
||||||
|
uint64_t hi, lo;
|
||||||
|
// hi,lo = 64bit x 64bit multiply of c[0] and b[0]
|
||||||
|
|
||||||
|
__asm__("mulq %3\n\t"
|
||||||
|
: "=d" (hi),
|
||||||
|
"=a" (lo)
|
||||||
|
: "%a" (c[0]),
|
||||||
|
"rm" (b[0])
|
||||||
|
: "cc" );
|
||||||
|
|
||||||
|
a[0] += hi;
|
||||||
|
a[1] += lo;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t *dst = (uint64_t *) &memory[c[0] & 0x1FFFF0];
|
||||||
|
dst[0] = a[0];
|
||||||
|
dst[1] = a[1];
|
||||||
|
|
||||||
|
a[0] ^= b[0];
|
||||||
|
a[1] ^= b[1];
|
||||||
|
b_x = c_x;
|
||||||
|
__builtin_prefetch(&memory[a[0] & 0x1FFFF0], 0, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
|
||||||
|
memcpy(ExpandedKey, &ctx->state.hs.b[32], AES_KEY_SIZE);
|
||||||
|
ExpandAESKey256(ExpandedKey);
|
||||||
|
|
||||||
|
//for (i = 0; likely(i < MEMORY); i += INIT_SIZE_BYTE)
|
||||||
|
// aesni_parallel_xor(&ctx->text, ExpandedKey, &ctx->long_state[i]);
|
||||||
|
|
||||||
|
for (i = 0; __builtin_expect(i < MEMORY, 1); i += INIT_SIZE_BYTE)
|
||||||
|
{
|
||||||
|
xmminput[0] = _mm_xor_si128(longoutput[(i >> 4)], xmminput[0]);
|
||||||
|
xmminput[1] = _mm_xor_si128(longoutput[(i >> 4) + 1], xmminput[1]);
|
||||||
|
xmminput[2] = _mm_xor_si128(longoutput[(i >> 4) + 2], xmminput[2]);
|
||||||
|
xmminput[3] = _mm_xor_si128(longoutput[(i >> 4) + 3], xmminput[3]);
|
||||||
|
xmminput[4] = _mm_xor_si128(longoutput[(i >> 4) + 4], xmminput[4]);
|
||||||
|
xmminput[5] = _mm_xor_si128(longoutput[(i >> 4) + 5], xmminput[5]);
|
||||||
|
xmminput[6] = _mm_xor_si128(longoutput[(i >> 4) + 6], xmminput[6]);
|
||||||
|
xmminput[7] = _mm_xor_si128(longoutput[(i >> 4) + 7], xmminput[7]);
|
||||||
|
|
||||||
|
for(j = 0; j < 10; j++)
|
||||||
|
{
|
||||||
|
xmminput[0] = _mm_aesenc_si128(xmminput[0], expkey[j]);
|
||||||
|
xmminput[1] = _mm_aesenc_si128(xmminput[1], expkey[j]);
|
||||||
|
xmminput[2] = _mm_aesenc_si128(xmminput[2], expkey[j]);
|
||||||
|
xmminput[3] = _mm_aesenc_si128(xmminput[3], expkey[j]);
|
||||||
|
xmminput[4] = _mm_aesenc_si128(xmminput[4], expkey[j]);
|
||||||
|
xmminput[5] = _mm_aesenc_si128(xmminput[5], expkey[j]);
|
||||||
|
xmminput[6] = _mm_aesenc_si128(xmminput[6], expkey[j]);
|
||||||
|
xmminput[7] = _mm_aesenc_si128(xmminput[7], expkey[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(ctx->state.init, ctx->text, INIT_SIZE_BYTE);
|
||||||
|
keccakf((uint64_t *) &ctx->state.hs, 24);
|
||||||
|
extra_hashes[ctx->state.hs.b[0] & 3](&ctx->state, 200, output);
|
||||||
|
}
|
214
algo/cryptonight/cryptonight_av3_aesni_bmi2.c
Normal file
214
algo/cryptonight/cryptonight_av3_aesni_bmi2.c
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <x86intrin.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "cryptonight.h"
|
||||||
|
#include "crypto/c_keccak.h"
|
||||||
|
|
||||||
|
|
||||||
|
static inline void ExpandAESKey256_sub1(__m128i *tmp1, __m128i *tmp2)
|
||||||
|
{
|
||||||
|
__m128i tmp4;
|
||||||
|
*tmp2 = _mm_shuffle_epi32(*tmp2, 0xFF);
|
||||||
|
tmp4 = _mm_slli_si128(*tmp1, 0x04);
|
||||||
|
*tmp1 = _mm_xor_si128(*tmp1, tmp4);
|
||||||
|
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
||||||
|
*tmp1 = _mm_xor_si128(*tmp1, tmp4);
|
||||||
|
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
||||||
|
*tmp1 = _mm_xor_si128(*tmp1, tmp4);
|
||||||
|
*tmp1 = _mm_xor_si128(*tmp1, *tmp2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ExpandAESKey256_sub2(__m128i *tmp1, __m128i *tmp3)
|
||||||
|
{
|
||||||
|
__m128i tmp2, tmp4;
|
||||||
|
|
||||||
|
tmp4 = _mm_aeskeygenassist_si128(*tmp1, 0x00);
|
||||||
|
tmp2 = _mm_shuffle_epi32(tmp4, 0xAA);
|
||||||
|
tmp4 = _mm_slli_si128(*tmp3, 0x04);
|
||||||
|
*tmp3 = _mm_xor_si128(*tmp3, tmp4);
|
||||||
|
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
||||||
|
*tmp3 = _mm_xor_si128(*tmp3, tmp4);
|
||||||
|
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
||||||
|
*tmp3 = _mm_xor_si128(*tmp3, tmp4);
|
||||||
|
*tmp3 = _mm_xor_si128(*tmp3, tmp2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Special thanks to Intel for helping me
|
||||||
|
// with ExpandAESKey256() and its subroutines
|
||||||
|
static inline void ExpandAESKey256(char *keybuf)
|
||||||
|
{
|
||||||
|
__m128i tmp1, tmp2, tmp3, *keys;
|
||||||
|
|
||||||
|
keys = (__m128i *)keybuf;
|
||||||
|
|
||||||
|
tmp1 = _mm_load_si128((__m128i *)keybuf);
|
||||||
|
tmp3 = _mm_load_si128((__m128i *)(keybuf+0x10));
|
||||||
|
|
||||||
|
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x01);
|
||||||
|
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
||||||
|
keys[2] = tmp1;
|
||||||
|
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
||||||
|
keys[3] = tmp3;
|
||||||
|
|
||||||
|
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x02);
|
||||||
|
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
||||||
|
keys[4] = tmp1;
|
||||||
|
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
||||||
|
keys[5] = tmp3;
|
||||||
|
|
||||||
|
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x04);
|
||||||
|
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
||||||
|
keys[6] = tmp1;
|
||||||
|
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
||||||
|
keys[7] = tmp3;
|
||||||
|
|
||||||
|
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x08);
|
||||||
|
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
||||||
|
keys[8] = tmp1;
|
||||||
|
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
||||||
|
keys[9] = tmp3;
|
||||||
|
|
||||||
|
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x10);
|
||||||
|
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
||||||
|
keys[10] = tmp1;
|
||||||
|
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
||||||
|
keys[11] = tmp3;
|
||||||
|
|
||||||
|
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x20);
|
||||||
|
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
||||||
|
keys[12] = tmp1;
|
||||||
|
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
||||||
|
keys[13] = tmp3;
|
||||||
|
|
||||||
|
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x40);
|
||||||
|
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
||||||
|
keys[14] = tmp1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cryptonight_av3_aesni_bmi2(void *restrict output, const void *restrict input, const char *restrict memory, struct cryptonight_ctx *restrict ctx)
|
||||||
|
{
|
||||||
|
keccak((const uint8_t *) input, 76, (uint8_t *) &ctx->state.hs, 200);
|
||||||
|
uint8_t ExpandedKey[256];
|
||||||
|
size_t i, j;
|
||||||
|
|
||||||
|
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
|
||||||
|
memcpy(ExpandedKey, ctx->state.hs.b, AES_KEY_SIZE);
|
||||||
|
ExpandAESKey256(ExpandedKey);
|
||||||
|
|
||||||
|
__m128i *longoutput, *expkey, *xmminput;
|
||||||
|
longoutput = (__m128i *) memory;
|
||||||
|
expkey = (__m128i *)ExpandedKey;
|
||||||
|
xmminput = (__m128i *)ctx->text;
|
||||||
|
|
||||||
|
for (i = 0; __builtin_expect(i < MEMORY, 1); i += INIT_SIZE_BYTE)
|
||||||
|
{
|
||||||
|
for(j = 0; j < 10; j++)
|
||||||
|
{
|
||||||
|
xmminput[0] = _mm_aesenc_si128(xmminput[0], expkey[j]);
|
||||||
|
xmminput[1] = _mm_aesenc_si128(xmminput[1], expkey[j]);
|
||||||
|
xmminput[2] = _mm_aesenc_si128(xmminput[2], expkey[j]);
|
||||||
|
xmminput[3] = _mm_aesenc_si128(xmminput[3], expkey[j]);
|
||||||
|
xmminput[4] = _mm_aesenc_si128(xmminput[4], expkey[j]);
|
||||||
|
xmminput[5] = _mm_aesenc_si128(xmminput[5], expkey[j]);
|
||||||
|
xmminput[6] = _mm_aesenc_si128(xmminput[6], expkey[j]);
|
||||||
|
xmminput[7] = _mm_aesenc_si128(xmminput[7], expkey[j]);
|
||||||
|
}
|
||||||
|
_mm_store_si128(&(longoutput[(i >> 4)]), xmminput[0]);
|
||||||
|
_mm_store_si128(&(longoutput[(i >> 4) + 1]), xmminput[1]);
|
||||||
|
_mm_store_si128(&(longoutput[(i >> 4) + 2]), xmminput[2]);
|
||||||
|
_mm_store_si128(&(longoutput[(i >> 4) + 3]), xmminput[3]);
|
||||||
|
_mm_store_si128(&(longoutput[(i >> 4) + 4]), xmminput[4]);
|
||||||
|
_mm_store_si128(&(longoutput[(i >> 4) + 5]), xmminput[5]);
|
||||||
|
_mm_store_si128(&(longoutput[(i >> 4) + 6]), xmminput[6]);
|
||||||
|
_mm_store_si128(&(longoutput[(i >> 4) + 7]), xmminput[7]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 2; i++)
|
||||||
|
{
|
||||||
|
ctx->a[i] = ((uint64_t *)ctx->state.k)[i] ^ ((uint64_t *)ctx->state.k)[i+4];
|
||||||
|
ctx->b[i] = ((uint64_t *)ctx->state.k)[i+2] ^ ((uint64_t *)ctx->state.k)[i+6];
|
||||||
|
}
|
||||||
|
|
||||||
|
__m128i a_x = _mm_load_si128((__m128i *) &memory[ctx->a[0] & 0x1FFFF0]);
|
||||||
|
__m128i b_x = _mm_load_si128((__m128i *) ctx->b);
|
||||||
|
|
||||||
|
uint64_t c[2] __attribute((aligned(16)));
|
||||||
|
uint64_t d[2] __attribute((aligned(16)));
|
||||||
|
uint64_t hi;
|
||||||
|
|
||||||
|
for (i = 0; __builtin_expect(i < 0x80000, 1); i++) {
|
||||||
|
__m128i c_x = _mm_aesenc_si128(a_x, _mm_load_si128((__m128i *) ctx->a));
|
||||||
|
_mm_store_si128((__m128i *) c, c_x);
|
||||||
|
|
||||||
|
uint64_t *restrict d_ptr = (uint64_t *) &memory[c[0] & 0x1FFFF0];
|
||||||
|
_mm_store_si128((__m128i *) &memory[ctx->a[0] & 0x1FFFF0], _mm_xor_si128(b_x, c_x));
|
||||||
|
b_x = c_x;
|
||||||
|
|
||||||
|
d[0] = d_ptr[0];
|
||||||
|
d[1] = d_ptr[1];
|
||||||
|
|
||||||
|
d_ptr[1] = ctx->a[1] += _mulx_u64(c[0], d[0], &hi);
|
||||||
|
d_ptr[0] = ctx->a[0] += hi;
|
||||||
|
|
||||||
|
ctx->a[0] ^= d[0];
|
||||||
|
ctx->a[1] ^= d[1];
|
||||||
|
|
||||||
|
a_x = _mm_load_si128((__m128i *) &memory[ctx->a[0] & 0x1FFFF0]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
|
||||||
|
memcpy(ExpandedKey, &ctx->state.hs.b[32], AES_KEY_SIZE);
|
||||||
|
ExpandAESKey256(ExpandedKey);
|
||||||
|
|
||||||
|
for (i = 0; __builtin_expect(i < MEMORY, 1); i += INIT_SIZE_BYTE) {
|
||||||
|
xmminput[0] = _mm_xor_si128(longoutput[(i >> 4)], xmminput[0]);
|
||||||
|
xmminput[1] = _mm_xor_si128(longoutput[(i >> 4) + 1], xmminput[1]);
|
||||||
|
xmminput[2] = _mm_xor_si128(longoutput[(i >> 4) + 2], xmminput[2]);
|
||||||
|
xmminput[3] = _mm_xor_si128(longoutput[(i >> 4) + 3], xmminput[3]);
|
||||||
|
xmminput[4] = _mm_xor_si128(longoutput[(i >> 4) + 4], xmminput[4]);
|
||||||
|
xmminput[5] = _mm_xor_si128(longoutput[(i >> 4) + 5], xmminput[5]);
|
||||||
|
xmminput[6] = _mm_xor_si128(longoutput[(i >> 4) + 6], xmminput[6]);
|
||||||
|
xmminput[7] = _mm_xor_si128(longoutput[(i >> 4) + 7], xmminput[7]);
|
||||||
|
|
||||||
|
for(j = 0; j < 10; j++)
|
||||||
|
{
|
||||||
|
xmminput[0] = _mm_aesenc_si128(xmminput[0], expkey[j]);
|
||||||
|
xmminput[1] = _mm_aesenc_si128(xmminput[1], expkey[j]);
|
||||||
|
xmminput[2] = _mm_aesenc_si128(xmminput[2], expkey[j]);
|
||||||
|
xmminput[3] = _mm_aesenc_si128(xmminput[3], expkey[j]);
|
||||||
|
xmminput[4] = _mm_aesenc_si128(xmminput[4], expkey[j]);
|
||||||
|
xmminput[5] = _mm_aesenc_si128(xmminput[5], expkey[j]);
|
||||||
|
xmminput[6] = _mm_aesenc_si128(xmminput[6], expkey[j]);
|
||||||
|
xmminput[7] = _mm_aesenc_si128(xmminput[7], expkey[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(ctx->state.init, ctx->text, INIT_SIZE_BYTE);
|
||||||
|
keccakf((uint64_t *) &ctx->state.hs, 24);
|
||||||
|
extra_hashes[ctx->state.hs.b[0] & 3](&ctx->state, 200, output);
|
||||||
|
}
|
151
algo/cryptonight/cryptonight_av4_legacy.c
Normal file
151
algo/cryptonight/cryptonight_av4_legacy.c
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <x86intrin.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "cryptonight.h"
|
||||||
|
#include "compat.h"
|
||||||
|
#include "crypto/c_keccak.h"
|
||||||
|
#include "crypto/aesb.h"
|
||||||
|
#include "crypto/oaes_lib.h"
|
||||||
|
|
||||||
|
|
||||||
|
static inline uint64_t mul128(uint64_t multiplier, uint64_t multiplicand, uint64_t *product_hi) {
|
||||||
|
// multiplier = ab = a * 2^32 + b
|
||||||
|
// multiplicand = cd = c * 2^32 + d
|
||||||
|
// ab * cd = a * c * 2^64 + (a * d + b * c) * 2^32 + b * d
|
||||||
|
uint64_t a = multiplier >> 32;
|
||||||
|
uint64_t b = multiplier & 0xFFFFFFFF;
|
||||||
|
uint64_t c = multiplicand >> 32;
|
||||||
|
uint64_t d = multiplicand & 0xFFFFFFFF;
|
||||||
|
|
||||||
|
//uint64_t ac = a * c;
|
||||||
|
uint64_t ad = a * d;
|
||||||
|
//uint64_t bc = b * c;
|
||||||
|
uint64_t bd = b * d;
|
||||||
|
|
||||||
|
uint64_t adbc = ad + (b * c);
|
||||||
|
uint64_t adbc_carry = adbc < ad ? 1 : 0;
|
||||||
|
|
||||||
|
// multiplier * multiplicand = product_hi * 2^64 + product_lo
|
||||||
|
uint64_t product_lo = bd + (adbc << 32);
|
||||||
|
uint64_t product_lo_carry = product_lo < bd ? 1 : 0;
|
||||||
|
*product_hi = (a * c) + (adbc >> 32) + (adbc_carry << 32) + product_lo_carry;
|
||||||
|
|
||||||
|
return product_lo;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline void mul_sum_xor_dst(const uint8_t* a, uint8_t* c, uint8_t* dst) {
|
||||||
|
uint64_t hi, lo = mul128(((uint64_t*) a)[0], ((uint64_t*) dst)[0], &hi) + ((uint64_t*) c)[1];
|
||||||
|
hi += ((uint64_t*) c)[0];
|
||||||
|
|
||||||
|
((uint64_t*) c)[0] = ((uint64_t*) dst)[0] ^ hi;
|
||||||
|
((uint64_t*) c)[1] = ((uint64_t*) dst)[1] ^ lo;
|
||||||
|
((uint64_t*) dst)[0] = hi;
|
||||||
|
((uint64_t*) dst)[1] = lo;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline void xor_blocks(uint8_t* a, const uint8_t* b) {
|
||||||
|
((uint64_t*) a)[0] ^= ((uint64_t*) b)[0];
|
||||||
|
((uint64_t*) a)[1] ^= ((uint64_t*) b)[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline void xor_blocks_dst(const uint8_t* a, const uint8_t* b, uint8_t* dst) {
|
||||||
|
((uint64_t*) dst)[0] = ((uint64_t*) a)[0] ^ ((uint64_t*) b)[0];
|
||||||
|
((uint64_t*) dst)[1] = ((uint64_t*) a)[1] ^ ((uint64_t*) b)[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void cryptonight_av4_legacy(void *restrict output, const void *restrict input, const char *restrict memory, struct cryptonight_ctx *restrict ctx) {
|
||||||
|
oaes_ctx *aes_ctx = (oaes_ctx*) oaes_alloc();
|
||||||
|
size_t i, j;
|
||||||
|
keccak((const uint8_t *)input, 76, (uint8_t *) &ctx->state.hs, 200);
|
||||||
|
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
|
||||||
|
|
||||||
|
oaes_key_import_data(aes_ctx, ctx->state.hs.b, AES_KEY_SIZE);
|
||||||
|
|
||||||
|
for (i = 0; likely(i < MEMORY); i += INIT_SIZE_BYTE) {
|
||||||
|
aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 0], aes_ctx->key->exp_data);
|
||||||
|
aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 1], aes_ctx->key->exp_data);
|
||||||
|
aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 2], aes_ctx->key->exp_data);
|
||||||
|
aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 3], aes_ctx->key->exp_data);
|
||||||
|
aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 4], aes_ctx->key->exp_data);
|
||||||
|
aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 5], aes_ctx->key->exp_data);
|
||||||
|
aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 6], aes_ctx->key->exp_data);
|
||||||
|
aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 7], aes_ctx->key->exp_data);
|
||||||
|
memcpy((void *) &memory[i], ctx->text, INIT_SIZE_BYTE);
|
||||||
|
}
|
||||||
|
|
||||||
|
xor_blocks_dst(&ctx->state.k[0], &ctx->state.k[32], (uint8_t*) ctx->a);
|
||||||
|
xor_blocks_dst(&ctx->state.k[16], &ctx->state.k[48], (uint8_t*) ctx->b);
|
||||||
|
|
||||||
|
for (i = 0; likely(i < ITER / 4); ++i) {
|
||||||
|
/* Dependency chain: address -> read value ------+
|
||||||
|
* written value <-+ hard function (AES or MUL) <+
|
||||||
|
* next address <-+
|
||||||
|
*/
|
||||||
|
/* Iteration 1 */
|
||||||
|
j = ctx->a[0] & 0x1FFFF0;
|
||||||
|
aesb_single_round((const uint8_t*) &memory[j], (uint8_t *) ctx->c, (const uint8_t *) ctx->a);
|
||||||
|
xor_blocks_dst((const uint8_t*) ctx->c, (const uint8_t*) ctx->b, (uint8_t*) &memory[j]);
|
||||||
|
/* Iteration 2 */
|
||||||
|
mul_sum_xor_dst((const uint8_t*) ctx->c, (uint8_t*) ctx->a, (uint8_t*) &memory[ctx->c[0] & 0x1FFFF0]);
|
||||||
|
/* Iteration 3 */
|
||||||
|
j = ctx->a[0] & 0x1FFFF0;
|
||||||
|
aesb_single_round(&memory[j], (uint8_t *) ctx->b, (uint8_t *) ctx->a);
|
||||||
|
xor_blocks_dst((const uint8_t*) ctx->b, (const uint8_t*) ctx->c, (uint8_t*) &memory[j]);
|
||||||
|
/* Iteration 4 */
|
||||||
|
mul_sum_xor_dst((const uint8_t*) ctx->b, (uint8_t*) ctx->a, (uint8_t*) &memory[ctx->b[0] & 0x1FFFF0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
|
||||||
|
oaes_key_import_data(aes_ctx, &ctx->state.hs.b[32], AES_KEY_SIZE);
|
||||||
|
|
||||||
|
for (i = 0; likely(i < MEMORY); i += INIT_SIZE_BYTE) {
|
||||||
|
xor_blocks(&ctx->text[0 * AES_BLOCK_SIZE], &memory[i + 0 * AES_BLOCK_SIZE]);
|
||||||
|
aesb_pseudo_round_mut(&ctx->text[0 * AES_BLOCK_SIZE], aes_ctx->key->exp_data);
|
||||||
|
xor_blocks(&ctx->text[1 * AES_BLOCK_SIZE], &memory[i + 1 * AES_BLOCK_SIZE]);
|
||||||
|
aesb_pseudo_round_mut(&ctx->text[1 * AES_BLOCK_SIZE], aes_ctx->key->exp_data);
|
||||||
|
xor_blocks(&ctx->text[2 * AES_BLOCK_SIZE], &memory[i + 2 * AES_BLOCK_SIZE]);
|
||||||
|
aesb_pseudo_round_mut(&ctx->text[2 * AES_BLOCK_SIZE], aes_ctx->key->exp_data);
|
||||||
|
xor_blocks(&ctx->text[3 * AES_BLOCK_SIZE], &memory[i + 3 * AES_BLOCK_SIZE]);
|
||||||
|
aesb_pseudo_round_mut(&ctx->text[3 * AES_BLOCK_SIZE], aes_ctx->key->exp_data);
|
||||||
|
xor_blocks(&ctx->text[4 * AES_BLOCK_SIZE], &memory[i + 4 * AES_BLOCK_SIZE]);
|
||||||
|
aesb_pseudo_round_mut(&ctx->text[4 * AES_BLOCK_SIZE], aes_ctx->key->exp_data);
|
||||||
|
xor_blocks(&ctx->text[5 * AES_BLOCK_SIZE], &memory[i + 5 * AES_BLOCK_SIZE]);
|
||||||
|
aesb_pseudo_round_mut(&ctx->text[5 * AES_BLOCK_SIZE], aes_ctx->key->exp_data);
|
||||||
|
xor_blocks(&ctx->text[6 * AES_BLOCK_SIZE], &memory[i + 6 * AES_BLOCK_SIZE]);
|
||||||
|
aesb_pseudo_round_mut(&ctx->text[6 * AES_BLOCK_SIZE], aes_ctx->key->exp_data);
|
||||||
|
xor_blocks(&ctx->text[7 * AES_BLOCK_SIZE], &memory[i + 7 * AES_BLOCK_SIZE]);
|
||||||
|
aesb_pseudo_round_mut(&ctx->text[7 * AES_BLOCK_SIZE], aes_ctx->key->exp_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(ctx->state.init, ctx->text, INIT_SIZE_BYTE);
|
||||||
|
keccakf((uint64_t *) &ctx->state.hs, 24);
|
||||||
|
extra_hashes[ctx->state.hs.b[0] & 3](&ctx->state, 200, output);
|
||||||
|
oaes_free((OAES_CTX **) &aes_ctx);
|
||||||
|
}
|
248
algo/cryptonight/cryptonight_av5_aesni_experimental.c
Normal file
248
algo/cryptonight/cryptonight_av5_aesni_experimental.c
Normal file
@ -0,0 +1,248 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <x86intrin.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "cryptonight.h"
|
||||||
|
#include "crypto/c_keccak.h"
|
||||||
|
|
||||||
|
|
||||||
|
static inline void ExpandAESKey256_sub1(__m128i *tmp1, __m128i *tmp2)
|
||||||
|
{
|
||||||
|
__m128i tmp4;
|
||||||
|
*tmp2 = _mm_shuffle_epi32(*tmp2, 0xFF);
|
||||||
|
tmp4 = _mm_slli_si128(*tmp1, 0x04);
|
||||||
|
*tmp1 = _mm_xor_si128(*tmp1, tmp4);
|
||||||
|
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
||||||
|
*tmp1 = _mm_xor_si128(*tmp1, tmp4);
|
||||||
|
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
||||||
|
*tmp1 = _mm_xor_si128(*tmp1, tmp4);
|
||||||
|
*tmp1 = _mm_xor_si128(*tmp1, *tmp2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ExpandAESKey256_sub2(__m128i *tmp1, __m128i *tmp3)
|
||||||
|
{
|
||||||
|
__m128i tmp2, tmp4;
|
||||||
|
|
||||||
|
tmp4 = _mm_aeskeygenassist_si128(*tmp1, 0x00);
|
||||||
|
tmp2 = _mm_shuffle_epi32(tmp4, 0xAA);
|
||||||
|
tmp4 = _mm_slli_si128(*tmp3, 0x04);
|
||||||
|
*tmp3 = _mm_xor_si128(*tmp3, tmp4);
|
||||||
|
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
||||||
|
*tmp3 = _mm_xor_si128(*tmp3, tmp4);
|
||||||
|
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
||||||
|
*tmp3 = _mm_xor_si128(*tmp3, tmp4);
|
||||||
|
*tmp3 = _mm_xor_si128(*tmp3, tmp2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Special thanks to Intel for helping me
|
||||||
|
// with ExpandAESKey256() and its subroutines
|
||||||
|
static inline void ExpandAESKey256(char *keybuf)
|
||||||
|
{
|
||||||
|
__m128i tmp1, tmp2, tmp3, *keys;
|
||||||
|
|
||||||
|
keys = (__m128i *)keybuf;
|
||||||
|
|
||||||
|
tmp1 = _mm_load_si128((__m128i *)keybuf);
|
||||||
|
tmp3 = _mm_load_si128((__m128i *)(keybuf+0x10));
|
||||||
|
|
||||||
|
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x01);
|
||||||
|
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
||||||
|
keys[2] = tmp1;
|
||||||
|
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
||||||
|
keys[3] = tmp3;
|
||||||
|
|
||||||
|
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x02);
|
||||||
|
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
||||||
|
keys[4] = tmp1;
|
||||||
|
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
||||||
|
keys[5] = tmp3;
|
||||||
|
|
||||||
|
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x04);
|
||||||
|
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
||||||
|
keys[6] = tmp1;
|
||||||
|
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
||||||
|
keys[7] = tmp3;
|
||||||
|
|
||||||
|
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x08);
|
||||||
|
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
||||||
|
keys[8] = tmp1;
|
||||||
|
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
||||||
|
keys[9] = tmp3;
|
||||||
|
|
||||||
|
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x10);
|
||||||
|
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
||||||
|
keys[10] = tmp1;
|
||||||
|
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
||||||
|
keys[11] = tmp3;
|
||||||
|
|
||||||
|
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x20);
|
||||||
|
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
||||||
|
keys[12] = tmp1;
|
||||||
|
ExpandAESKey256_sub2(&tmp1, &tmp3);
|
||||||
|
keys[13] = tmp3;
|
||||||
|
|
||||||
|
tmp2 = _mm_aeskeygenassist_si128(tmp3, 0x40);
|
||||||
|
ExpandAESKey256_sub1(&tmp1, &tmp2);
|
||||||
|
keys[14] = tmp1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cryptonight_av5_aesni_experimental(void *restrict output, const void *restrict input, const char *restrict memory, struct cryptonight_ctx *restrict ctx)
|
||||||
|
{
|
||||||
|
keccak((const uint8_t *)input, 76, (uint8_t *) &ctx->state.hs, 200);
|
||||||
|
uint8_t ExpandedKey[256];
|
||||||
|
size_t i, j;
|
||||||
|
|
||||||
|
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
|
||||||
|
memcpy(ExpandedKey, ctx->state.hs.b, AES_KEY_SIZE);
|
||||||
|
ExpandAESKey256(ExpandedKey);
|
||||||
|
|
||||||
|
__m128i *longoutput, *expkey, *xmminput;
|
||||||
|
longoutput = (__m128i *) memory;
|
||||||
|
expkey = (__m128i *) ExpandedKey;
|
||||||
|
xmminput = (__m128i *)ctx->text;
|
||||||
|
|
||||||
|
// prefetch expkey, all of xmminput and enough longoutput for 4 loops
|
||||||
|
_mm_prefetch(xmminput, _MM_HINT_T0 );
|
||||||
|
_mm_prefetch(xmminput + 4, _MM_HINT_T0 );
|
||||||
|
|
||||||
|
for (i = 0; i < 64; i += 16) {
|
||||||
|
_mm_prefetch(longoutput + i, _MM_HINT_T0);
|
||||||
|
_mm_prefetch(longoutput + i + 4, _MM_HINT_T0);
|
||||||
|
_mm_prefetch(longoutput + i + 8, _MM_HINT_T0);
|
||||||
|
_mm_prefetch(longoutput + i + 12, _MM_HINT_T0);
|
||||||
|
}
|
||||||
|
|
||||||
|
_mm_prefetch(expkey, _MM_HINT_T0);
|
||||||
|
_mm_prefetch(expkey + 4, _MM_HINT_T0);
|
||||||
|
_mm_prefetch(expkey + 8, _MM_HINT_T0);
|
||||||
|
|
||||||
|
for (i = 0; __builtin_expect(i < MEMORY_M128I, 1); i += INIT_SIZE_M128I) {
|
||||||
|
__builtin_prefetch(longoutput + i + 64, 1, 0);
|
||||||
|
__builtin_prefetch(longoutput + i + 68, 1, 0);
|
||||||
|
|
||||||
|
for(j = 0; j < 10; j++) {
|
||||||
|
xmminput[0] = _mm_aesenc_si128(xmminput[0], expkey[j]);
|
||||||
|
xmminput[1] = _mm_aesenc_si128(xmminput[1], expkey[j]);
|
||||||
|
xmminput[2] = _mm_aesenc_si128(xmminput[2], expkey[j]);
|
||||||
|
xmminput[3] = _mm_aesenc_si128(xmminput[3], expkey[j]);
|
||||||
|
xmminput[4] = _mm_aesenc_si128(xmminput[4], expkey[j]);
|
||||||
|
xmminput[5] = _mm_aesenc_si128(xmminput[5], expkey[j]);
|
||||||
|
xmminput[6] = _mm_aesenc_si128(xmminput[6], expkey[j]);
|
||||||
|
xmminput[7] = _mm_aesenc_si128(xmminput[7], expkey[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
_mm_store_si128(&(longoutput[i ]), xmminput[0]);
|
||||||
|
_mm_store_si128(&(longoutput[i + 1 ]), xmminput[1]);
|
||||||
|
_mm_store_si128(&(longoutput[i + 2 ]), xmminput[2]);
|
||||||
|
_mm_store_si128(&(longoutput[i + 3 ]), xmminput[3]);
|
||||||
|
_mm_store_si128(&(longoutput[i + 4 ]), xmminput[4]);
|
||||||
|
_mm_store_si128(&(longoutput[i + 5 ]), xmminput[5]);
|
||||||
|
_mm_store_si128(&(longoutput[i + 6 ]), xmminput[6]);
|
||||||
|
_mm_store_si128(&(longoutput[i + 7 ]), xmminput[7]);
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->a[0] = ((uint64_t *) ctx->state.k)[0] ^ ((uint64_t *) ctx->state.k)[4];
|
||||||
|
ctx->b[0] = ((uint64_t *) ctx->state.k)[2] ^ ((uint64_t *) ctx->state.k)[6];
|
||||||
|
ctx->a[1] = ((uint64_t *) ctx->state.k)[1] ^ ((uint64_t *) ctx->state.k)[5];
|
||||||
|
ctx->b[1] = ((uint64_t *) ctx->state.k)[3] ^ ((uint64_t *) ctx->state.k)[7];
|
||||||
|
|
||||||
|
__m128i a_x = _mm_load_si128((__m128i *) &memory[ctx->a[0] & 0x1FFFF0]);
|
||||||
|
__m128i b_x = _mm_load_si128((__m128i *) ctx->b);
|
||||||
|
|
||||||
|
uint64_t c[2] __attribute((aligned(16)));
|
||||||
|
uint64_t d[2] __attribute((aligned(16)));
|
||||||
|
|
||||||
|
for (i = 0; __builtin_expect(i < 0x80000, 1); i++) {
|
||||||
|
__m128i c_x = _mm_aesenc_si128(a_x, _mm_load_si128((__m128i *) ctx->a));
|
||||||
|
_mm_store_si128((__m128i *) c, c_x);
|
||||||
|
|
||||||
|
uint64_t *restrict d_ptr = (uint64_t *) &memory[c[0] & 0x1FFFF0];
|
||||||
|
_mm_store_si128((__m128i *) &memory[ctx->a[0] & 0x1FFFF0], _mm_xor_si128(b_x, c_x));
|
||||||
|
b_x = c_x;
|
||||||
|
|
||||||
|
d[0] = d_ptr[0];
|
||||||
|
d[1] = d_ptr[1];
|
||||||
|
|
||||||
|
{
|
||||||
|
unsigned __int128 res = (unsigned __int128) c[0] * d[0];
|
||||||
|
|
||||||
|
d_ptr[0] = ctx->a[0] += res >> 64;
|
||||||
|
d_ptr[1] = ctx->a[1] += (uint64_t) res;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->a[0] ^= d[0];
|
||||||
|
ctx->a[1] ^= d[1];
|
||||||
|
|
||||||
|
a_x = _mm_load_si128((__m128i *) &memory[ctx->a[0] & 0x1FFFF0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
|
||||||
|
memcpy(ExpandedKey, &ctx->state.hs.b[32], AES_KEY_SIZE);
|
||||||
|
ExpandAESKey256(ExpandedKey);
|
||||||
|
|
||||||
|
_mm_prefetch(xmminput, _MM_HINT_T0 );
|
||||||
|
_mm_prefetch(xmminput + 4, _MM_HINT_T0 );
|
||||||
|
|
||||||
|
for (i = 0; i < 64; i += 16) {
|
||||||
|
_mm_prefetch(longoutput + i, _MM_HINT_T0);
|
||||||
|
_mm_prefetch(longoutput + i + 4, _MM_HINT_T0);
|
||||||
|
_mm_prefetch(longoutput + i + 8, _MM_HINT_T0);
|
||||||
|
_mm_prefetch(longoutput + i + 12, _MM_HINT_T0);
|
||||||
|
}
|
||||||
|
|
||||||
|
_mm_prefetch(expkey, _MM_HINT_T0);
|
||||||
|
_mm_prefetch(expkey + 4, _MM_HINT_T0);
|
||||||
|
_mm_prefetch(expkey + 8, _MM_HINT_T0);
|
||||||
|
|
||||||
|
for (i = 0; __builtin_expect(i < MEMORY_M128I, 1); i += INIT_SIZE_M128I) {
|
||||||
|
_mm_prefetch(longoutput + i + 64, _MM_HINT_T0);
|
||||||
|
_mm_prefetch(longoutput + i + 68, _MM_HINT_T0);
|
||||||
|
|
||||||
|
xmminput[0] = _mm_xor_si128(longoutput[i ], xmminput[0]);
|
||||||
|
xmminput[1] = _mm_xor_si128(longoutput[i + 1], xmminput[1]);
|
||||||
|
xmminput[2] = _mm_xor_si128(longoutput[i + 2], xmminput[2]);
|
||||||
|
xmminput[3] = _mm_xor_si128(longoutput[i + 3], xmminput[3]);
|
||||||
|
xmminput[4] = _mm_xor_si128(longoutput[i + 4], xmminput[4]);
|
||||||
|
xmminput[5] = _mm_xor_si128(longoutput[i + 5], xmminput[5]);
|
||||||
|
xmminput[6] = _mm_xor_si128(longoutput[i + 6], xmminput[6]);
|
||||||
|
xmminput[7] = _mm_xor_si128(longoutput[i + 7], xmminput[7]);
|
||||||
|
|
||||||
|
for(j = 0; j < 10; j++) {
|
||||||
|
xmminput[0] = _mm_aesenc_si128(xmminput[0], expkey[j]);
|
||||||
|
xmminput[1] = _mm_aesenc_si128(xmminput[1], expkey[j]);
|
||||||
|
xmminput[2] = _mm_aesenc_si128(xmminput[2], expkey[j]);
|
||||||
|
xmminput[3] = _mm_aesenc_si128(xmminput[3], expkey[j]);
|
||||||
|
xmminput[4] = _mm_aesenc_si128(xmminput[4], expkey[j]);
|
||||||
|
xmminput[5] = _mm_aesenc_si128(xmminput[5], expkey[j]);
|
||||||
|
xmminput[6] = _mm_aesenc_si128(xmminput[6], expkey[j]);
|
||||||
|
xmminput[7] = _mm_aesenc_si128(xmminput[7], expkey[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(ctx->state.init, ctx->text, INIT_SIZE_BYTE);
|
||||||
|
keccakf((uint64_t *) &ctx->state.hs, 24);
|
||||||
|
extra_hashes[ctx->state.hs.b[0] & 3](&ctx->state, 200, output);
|
||||||
|
}
|
142
algo/cryptonight/cryptonight_common.c
Normal file
142
algo/cryptonight/cryptonight_common.c
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#ifndef BUILD_TEST
|
||||||
|
# include "xmrig.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "crypto/c_groestl.h"
|
||||||
|
#include "crypto/c_blake256.h"
|
||||||
|
#include "crypto/c_jh.h"
|
||||||
|
#include "crypto/c_skein.h"
|
||||||
|
#include "cryptonight.h"
|
||||||
|
#include "options.h"
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
void cryptonight_av1_aesni(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx);
|
||||||
|
void cryptonight_av2_aesni_wolf(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx);
|
||||||
|
void cryptonight_av3_aesni_bmi2(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx);
|
||||||
|
void cryptonight_av5_aesni_experimental(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx);
|
||||||
|
#elif defined(__i386__)
|
||||||
|
void cryptonight_av1_aesni32(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void cryptonight_av4_legacy(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx);
|
||||||
|
|
||||||
|
void (*cryptonight_hash_ctx)(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx) = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
void cryptonight_init(int variant)
|
||||||
|
{
|
||||||
|
switch (variant) {
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
case XMR_VARIANT_AESNI:
|
||||||
|
cryptonight_hash_ctx = cryptonight_av1_aesni;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XMR_VARIANT_AESNI_WOLF:
|
||||||
|
cryptonight_hash_ctx = cryptonight_av2_aesni_wolf;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XMR_VARIANT_AESNI_BMI2:
|
||||||
|
cryptonight_hash_ctx = cryptonight_av3_aesni_bmi2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XMR_VARIANT_EXPERIMENTAL:
|
||||||
|
cryptonight_hash_ctx = cryptonight_av5_aesni_experimental;
|
||||||
|
break;
|
||||||
|
#elif defined(__i386__)
|
||||||
|
case XMR_VARIANT_AESNI:
|
||||||
|
cryptonight_hash_ctx = cryptonight_av1_aesni32;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
case XMR_VARIANT_LEGACY:
|
||||||
|
cryptonight_hash_ctx = cryptonight_av4_legacy;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline void do_blake_hash(const void* input, size_t len, char* output) {
|
||||||
|
blake256_hash((uint8_t*)output, input, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline void do_groestl_hash(const void* input, size_t len, char* output) {
|
||||||
|
groestl(input, len * 8, (uint8_t*)output);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline void do_jh_hash(const void* input, size_t len, char* output) {
|
||||||
|
jh_hash(32 * 8, input, 8 * len, (uint8_t*)output);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline void do_skein_hash(const void* input, size_t len, char* output) {
|
||||||
|
skein_hash(8 * 32, input, 8 * len, (uint8_t*)output);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void (* const extra_hashes[4])(const void *, size_t, char *) = {do_blake_hash, do_groestl_hash, do_jh_hash, do_skein_hash};
|
||||||
|
|
||||||
|
|
||||||
|
void cryptonight_hash(void* output, const void* input, size_t len) {
|
||||||
|
uint8_t *memory __attribute((aligned(16))) = (uint8_t *) malloc(MEMORY);
|
||||||
|
struct cryptonight_ctx *ctx = (struct cryptonight_ctx*)malloc(sizeof(struct cryptonight_ctx));
|
||||||
|
|
||||||
|
cryptonight_hash_ctx(output, input, memory, ctx);
|
||||||
|
|
||||||
|
free(memory);
|
||||||
|
free(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef BUILD_TEST
|
||||||
|
int scanhash_cryptonight(int thr_id, uint32_t *hash, uint32_t *restrict pdata, const uint32_t *restrict ptarget, uint32_t max_nonce, unsigned long *restrict hashes_done, const char *restrict memory, struct cryptonight_ctx *persistentctx) {
|
||||||
|
uint32_t *nonceptr = (uint32_t*) (((char*)pdata) + 39);
|
||||||
|
uint32_t n = *nonceptr - 1;
|
||||||
|
const uint32_t first_nonce = n + 1;
|
||||||
|
|
||||||
|
do {
|
||||||
|
*nonceptr = ++n;
|
||||||
|
cryptonight_hash_ctx(hash, pdata, memory, persistentctx);
|
||||||
|
|
||||||
|
if (unlikely(hash[7] < ptarget[7])) {
|
||||||
|
*hashes_done = n - first_nonce + 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} while (likely((n <= max_nonce && !work_restart[thr_id].restart)));
|
||||||
|
|
||||||
|
*hashes_done = n - first_nonce + 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
47
compat.h
Normal file
47
compat.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||||
|
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||||
|
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||||
|
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||||
|
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||||
|
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __COMPAT_H__
|
||||||
|
#define __COMPAT_H__
|
||||||
|
|
||||||
|
#define unlikely(expr) (__builtin_expect(!!(expr), 0))
|
||||||
|
#define likely(expr) (__builtin_expect(!!(expr), 1))
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#define sleep(secs) Sleep((secs) * 1000)
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PRIO_PROCESS = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline int setpriority(int which, int who, int prio)
|
||||||
|
{
|
||||||
|
return -!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_IDLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* WIN32 */
|
||||||
|
|
||||||
|
#endif /* __COMPAT_H__ */
|
23
compat/jansson/CMakeLists.txt
Normal file
23
compat/jansson/CMakeLists.txt
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
cmake_minimum_required (VERSION 2.8)
|
||||||
|
project (jansson C)
|
||||||
|
|
||||||
|
add_definitions(-DHAVE_CONFIG_H)
|
||||||
|
|
||||||
|
# Add the lib sources.
|
||||||
|
file(GLOB JANSSON_SRC *.c)
|
||||||
|
|
||||||
|
set(JANSSON_HDR_PRIVATE
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/hashtable.h
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/jansson_private.h
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/strbuffer.h
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/utf.h
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/jansson_private_config.h)
|
||||||
|
|
||||||
|
set(JANSSON_HDR_PUBLIC
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/jansson_config.h
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/jansson.h)
|
||||||
|
|
||||||
|
add_library(jansson STATIC
|
||||||
|
${JANSSON_SRC}
|
||||||
|
${JANSSON_HDR_PRIVATE}
|
||||||
|
${JANSSON_HDR_PUBLIC})
|
19
compat/jansson/LICENSE
Normal file
19
compat/jansson/LICENSE
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
Copyright (c) 2009-2014 Petri Lehtinen <petri@digip.org>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
446
compat/jansson/dump.c
Normal file
446
compat/jansson/dump.c
Normal file
File diff suppressed because it is too large
Load Diff
63
compat/jansson/error.c
Normal file
63
compat/jansson/error.c
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#include <string.h>
|
||||||
|
#include "jansson_private.h"
|
||||||
|
|
||||||
|
void jsonp_error_init(json_error_t *error, const char *source)
|
||||||
|
{
|
||||||
|
if(error)
|
||||||
|
{
|
||||||
|
error->text[0] = '\0';
|
||||||
|
error->line = -1;
|
||||||
|
error->column = -1;
|
||||||
|
error->position = 0;
|
||||||
|
if(source)
|
||||||
|
jsonp_error_set_source(error, source);
|
||||||
|
else
|
||||||
|
error->source[0] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void jsonp_error_set_source(json_error_t *error, const char *source)
|
||||||
|
{
|
||||||
|
size_t length;
|
||||||
|
|
||||||
|
if(!error || !source)
|
||||||
|
return;
|
||||||
|
|
||||||
|
length = strlen(source);
|
||||||
|
if(length < JSON_ERROR_SOURCE_LENGTH)
|
||||||
|
strncpy(error->source, source, length + 1);
|
||||||
|
else {
|
||||||
|
size_t extra = length - JSON_ERROR_SOURCE_LENGTH + 4;
|
||||||
|
strncpy(error->source, "...", 3);
|
||||||
|
strncpy(error->source + 3, source + extra, length - extra + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void jsonp_error_set(json_error_t *error, int line, int column,
|
||||||
|
size_t position, const char *msg, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, msg);
|
||||||
|
jsonp_error_vset(error, line, column, position, msg, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void jsonp_error_vset(json_error_t *error, int line, int column,
|
||||||
|
size_t position, const char *msg, va_list ap)
|
||||||
|
{
|
||||||
|
if(!error)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(error->text[0] != '\0') {
|
||||||
|
/* error already set */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
error->line = line;
|
||||||
|
error->column = column;
|
||||||
|
error->position = (int)position;
|
||||||
|
|
||||||
|
vsnprintf(error->text, JSON_ERROR_TEXT_LENGTH, msg, ap);
|
||||||
|
error->text[JSON_ERROR_TEXT_LENGTH - 1] = '\0';
|
||||||
|
}
|
356
compat/jansson/hashtable.c
Normal file
356
compat/jansson/hashtable.c
Normal file
File diff suppressed because it is too large
Load Diff
176
compat/jansson/hashtable.h
Normal file
176
compat/jansson/hashtable.h
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2016 Petri Lehtinen <petri@digip.org>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the MIT license. See LICENSE for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HASHTABLE_H
|
||||||
|
#define HASHTABLE_H
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "jansson.h"
|
||||||
|
|
||||||
|
struct hashtable_list {
|
||||||
|
struct hashtable_list *prev;
|
||||||
|
struct hashtable_list *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* "pair" may be a bit confusing a name, but think of it as a
|
||||||
|
key-value pair. In this case, it just encodes some extra data,
|
||||||
|
too */
|
||||||
|
struct hashtable_pair {
|
||||||
|
struct hashtable_list list;
|
||||||
|
struct hashtable_list ordered_list;
|
||||||
|
size_t hash;
|
||||||
|
json_t *value;
|
||||||
|
char key[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct hashtable_bucket {
|
||||||
|
struct hashtable_list *first;
|
||||||
|
struct hashtable_list *last;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct hashtable {
|
||||||
|
size_t size;
|
||||||
|
struct hashtable_bucket *buckets;
|
||||||
|
size_t order; /* hashtable has pow(2, order) buckets */
|
||||||
|
struct hashtable_list list;
|
||||||
|
struct hashtable_list ordered_list;
|
||||||
|
} hashtable_t;
|
||||||
|
|
||||||
|
|
||||||
|
#define hashtable_key_to_iter(key_) \
|
||||||
|
(&(container_of(key_, struct hashtable_pair, key)->ordered_list))
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hashtable_init - Initialize a hashtable object
|
||||||
|
*
|
||||||
|
* @hashtable: The (statically allocated) hashtable object
|
||||||
|
*
|
||||||
|
* Initializes a statically allocated hashtable object. The object
|
||||||
|
* should be cleared with hashtable_close when it's no longer used.
|
||||||
|
*
|
||||||
|
* Returns 0 on success, -1 on error (out of memory).
|
||||||
|
*/
|
||||||
|
int hashtable_init(hashtable_t *hashtable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hashtable_close - Release all resources used by a hashtable object
|
||||||
|
*
|
||||||
|
* @hashtable: The hashtable
|
||||||
|
*
|
||||||
|
* Destroys a statically allocated hashtable object.
|
||||||
|
*/
|
||||||
|
void hashtable_close(hashtable_t *hashtable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hashtable_set - Add/modify value in hashtable
|
||||||
|
*
|
||||||
|
* @hashtable: The hashtable object
|
||||||
|
* @key: The key
|
||||||
|
* @serial: For addition order of keys
|
||||||
|
* @value: The value
|
||||||
|
*
|
||||||
|
* If a value with the given key already exists, its value is replaced
|
||||||
|
* with the new value. Value is "stealed" in the sense that hashtable
|
||||||
|
* doesn't increment its refcount but decreases the refcount when the
|
||||||
|
* value is no longer needed.
|
||||||
|
*
|
||||||
|
* Returns 0 on success, -1 on failure (out of memory).
|
||||||
|
*/
|
||||||
|
int hashtable_set(hashtable_t *hashtable, const char *key, json_t *value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hashtable_get - Get a value associated with a key
|
||||||
|
*
|
||||||
|
* @hashtable: The hashtable object
|
||||||
|
* @key: The key
|
||||||
|
*
|
||||||
|
* Returns value if it is found, or NULL otherwise.
|
||||||
|
*/
|
||||||
|
void *hashtable_get(hashtable_t *hashtable, const char *key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hashtable_del - Remove a value from the hashtable
|
||||||
|
*
|
||||||
|
* @hashtable: The hashtable object
|
||||||
|
* @key: The key
|
||||||
|
*
|
||||||
|
* Returns 0 on success, or -1 if the key was not found.
|
||||||
|
*/
|
||||||
|
int hashtable_del(hashtable_t *hashtable, const char *key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hashtable_clear - Clear hashtable
|
||||||
|
*
|
||||||
|
* @hashtable: The hashtable object
|
||||||
|
*
|
||||||
|
* Removes all items from the hashtable.
|
||||||
|
*/
|
||||||
|
void hashtable_clear(hashtable_t *hashtable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hashtable_iter - Iterate over hashtable
|
||||||
|
*
|
||||||
|
* @hashtable: The hashtable object
|
||||||
|
*
|
||||||
|
* Returns an opaque iterator to the first element in the hashtable.
|
||||||
|
* The iterator should be passed to hashtable_iter_* functions.
|
||||||
|
* The hashtable items are not iterated over in any particular order.
|
||||||
|
*
|
||||||
|
* There's no need to free the iterator in any way. The iterator is
|
||||||
|
* valid as long as the item that is referenced by the iterator is not
|
||||||
|
* deleted. Other values may be added or deleted. In particular,
|
||||||
|
* hashtable_iter_next() may be called on an iterator, and after that
|
||||||
|
* the key/value pair pointed by the old iterator may be deleted.
|
||||||
|
*/
|
||||||
|
void *hashtable_iter(hashtable_t *hashtable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hashtable_iter_at - Return an iterator at a specific key
|
||||||
|
*
|
||||||
|
* @hashtable: The hashtable object
|
||||||
|
* @key: The key that the iterator should point to
|
||||||
|
*
|
||||||
|
* Like hashtable_iter() but returns an iterator pointing to a
|
||||||
|
* specific key.
|
||||||
|
*/
|
||||||
|
void *hashtable_iter_at(hashtable_t *hashtable, const char *key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hashtable_iter_next - Advance an iterator
|
||||||
|
*
|
||||||
|
* @hashtable: The hashtable object
|
||||||
|
* @iter: The iterator
|
||||||
|
*
|
||||||
|
* Returns a new iterator pointing to the next element in the
|
||||||
|
* hashtable or NULL if the whole hastable has been iterated over.
|
||||||
|
*/
|
||||||
|
void *hashtable_iter_next(hashtable_t *hashtable, void *iter);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hashtable_iter_key - Retrieve the key pointed by an iterator
|
||||||
|
*
|
||||||
|
* @iter: The iterator
|
||||||
|
*/
|
||||||
|
void *hashtable_iter_key(void *iter);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hashtable_iter_value - Retrieve the value pointed by an iterator
|
||||||
|
*
|
||||||
|
* @iter: The iterator
|
||||||
|
*/
|
||||||
|
void *hashtable_iter_value(void *iter);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hashtable_iter_set - Set the value pointed by an iterator
|
||||||
|
*
|
||||||
|
* @iter: The iterator
|
||||||
|
* @value: The value to set
|
||||||
|
*/
|
||||||
|
void hashtable_iter_set(void *iter, json_t *value);
|
||||||
|
|
||||||
|
#endif
|
277
compat/jansson/hashtable_seed.c
Normal file
277
compat/jansson/hashtable_seed.c
Normal file
@ -0,0 +1,277 @@
|
|||||||
|
/* Generate sizeof(uint32_t) bytes of as random data as possible to seed
|
||||||
|
the hash function.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <jansson_private_config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_STDINT_H
|
||||||
|
#include <stdint.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_FCNTL_H
|
||||||
|
#include <fcntl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_SCHED_H
|
||||||
|
#include <sched.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_UNISTD_H
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_STAT_H
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_TIME_H
|
||||||
|
#include <sys/time.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
|
#include <sys/types.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
/* For GetModuleHandle(), GetProcAddress() and GetCurrentProcessId() */
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "jansson.h"
|
||||||
|
|
||||||
|
|
||||||
|
static uint32_t buf_to_uint32(char *data) {
|
||||||
|
size_t i;
|
||||||
|
uint32_t result = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof(uint32_t); i++)
|
||||||
|
result = (result << 8) | (unsigned char)data[i];
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* /dev/urandom */
|
||||||
|
#if !defined(_WIN32) && defined(USE_URANDOM)
|
||||||
|
static int seed_from_urandom(uint32_t *seed) {
|
||||||
|
/* Use unbuffered I/O if we have open(), close() and read(). Otherwise
|
||||||
|
fall back to fopen() */
|
||||||
|
|
||||||
|
char data[sizeof(uint32_t)];
|
||||||
|
int ok;
|
||||||
|
|
||||||
|
#if defined(HAVE_OPEN) && defined(HAVE_CLOSE) && defined(HAVE_READ)
|
||||||
|
int urandom;
|
||||||
|
urandom = open("/dev/urandom", O_RDONLY);
|
||||||
|
if (urandom == -1)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
ok = read(urandom, data, sizeof(uint32_t)) == sizeof(uint32_t);
|
||||||
|
close(urandom);
|
||||||
|
#else
|
||||||
|
FILE *urandom;
|
||||||
|
|
||||||
|
urandom = fopen("/dev/urandom", "rb");
|
||||||
|
if (!urandom)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
ok = fread(data, 1, sizeof(uint32_t), urandom) == sizeof(uint32_t);
|
||||||
|
fclose(urandom);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!ok)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
*seed = buf_to_uint32(data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Windows Crypto API */
|
||||||
|
#if defined(_WIN32) && defined(USE_WINDOWS_CRYPTOAPI)
|
||||||
|
#include <wincrypt.h>
|
||||||
|
|
||||||
|
typedef BOOL (WINAPI *CRYPTACQUIRECONTEXTA)(HCRYPTPROV *phProv, LPCSTR pszContainer, LPCSTR pszProvider, DWORD dwProvType, DWORD dwFlags);
|
||||||
|
typedef BOOL (WINAPI *CRYPTGENRANDOM)(HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer);
|
||||||
|
typedef BOOL (WINAPI *CRYPTRELEASECONTEXT)(HCRYPTPROV hProv, DWORD dwFlags);
|
||||||
|
|
||||||
|
static int seed_from_windows_cryptoapi(uint32_t *seed)
|
||||||
|
{
|
||||||
|
HINSTANCE hAdvAPI32 = NULL;
|
||||||
|
CRYPTACQUIRECONTEXTA pCryptAcquireContext = NULL;
|
||||||
|
CRYPTGENRANDOM pCryptGenRandom = NULL;
|
||||||
|
CRYPTRELEASECONTEXT pCryptReleaseContext = NULL;
|
||||||
|
HCRYPTPROV hCryptProv = 0;
|
||||||
|
BYTE data[sizeof(uint32_t)];
|
||||||
|
int ok;
|
||||||
|
|
||||||
|
hAdvAPI32 = GetModuleHandle(TEXT("advapi32.dll"));
|
||||||
|
if(hAdvAPI32 == NULL)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
pCryptAcquireContext = (CRYPTACQUIRECONTEXTA)GetProcAddress(hAdvAPI32, "CryptAcquireContextA");
|
||||||
|
if (!pCryptAcquireContext)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
pCryptGenRandom = (CRYPTGENRANDOM)GetProcAddress(hAdvAPI32, "CryptGenRandom");
|
||||||
|
if (!pCryptGenRandom)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
pCryptReleaseContext = (CRYPTRELEASECONTEXT)GetProcAddress(hAdvAPI32, "CryptReleaseContext");
|
||||||
|
if (!pCryptReleaseContext)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (!pCryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
ok = pCryptGenRandom(hCryptProv, sizeof(uint32_t), data);
|
||||||
|
pCryptReleaseContext(hCryptProv, 0);
|
||||||
|
|
||||||
|
if (!ok)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
*seed = buf_to_uint32((char *)data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* gettimeofday() and getpid() */
|
||||||
|
static int seed_from_timestamp_and_pid(uint32_t *seed) {
|
||||||
|
#ifdef HAVE_GETTIMEOFDAY
|
||||||
|
/* XOR of seconds and microseconds */
|
||||||
|
struct timeval tv;
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
*seed = (uint32_t)tv.tv_sec ^ (uint32_t)tv.tv_usec;
|
||||||
|
#else
|
||||||
|
/* Seconds only */
|
||||||
|
*seed = (uint32_t)time(NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* XOR with PID for more randomness */
|
||||||
|
#if defined(_WIN32)
|
||||||
|
*seed ^= (uint32_t)GetCurrentProcessId();
|
||||||
|
#elif defined(HAVE_GETPID)
|
||||||
|
*seed ^= (uint32_t)getpid();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t generate_seed() {
|
||||||
|
uint32_t seed;
|
||||||
|
int done = 0;
|
||||||
|
|
||||||
|
#if !defined(_WIN32) && defined(USE_URANDOM)
|
||||||
|
if (!done && seed_from_urandom(&seed) == 0)
|
||||||
|
done = 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WIN32) && defined(USE_WINDOWS_CRYPTOAPI)
|
||||||
|
if (!done && seed_from_windows_cryptoapi(&seed) == 0)
|
||||||
|
done = 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!done) {
|
||||||
|
/* Fall back to timestamp and PID if no better randomness is
|
||||||
|
available */
|
||||||
|
seed_from_timestamp_and_pid(&seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure the seed is never zero */
|
||||||
|
if (seed == 0)
|
||||||
|
seed = 1;
|
||||||
|
|
||||||
|
return seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
volatile uint32_t hashtable_seed = 0;
|
||||||
|
|
||||||
|
#if defined(HAVE_ATOMIC_BUILTINS) && (defined(HAVE_SCHED_YIELD) || !defined(_WIN32))
|
||||||
|
static volatile char seed_initialized = 0;
|
||||||
|
|
||||||
|
void json_object_seed(size_t seed) {
|
||||||
|
uint32_t new_seed = (uint32_t)seed;
|
||||||
|
|
||||||
|
if (hashtable_seed == 0) {
|
||||||
|
if (__atomic_test_and_set(&seed_initialized, __ATOMIC_RELAXED) == 0) {
|
||||||
|
/* Do the seeding ourselves */
|
||||||
|
if (new_seed == 0)
|
||||||
|
new_seed = generate_seed();
|
||||||
|
|
||||||
|
__atomic_store_n(&hashtable_seed, new_seed, __ATOMIC_RELEASE);
|
||||||
|
} else {
|
||||||
|
/* Wait for another thread to do the seeding */
|
||||||
|
do {
|
||||||
|
#ifdef HAVE_SCHED_YIELD
|
||||||
|
sched_yield();
|
||||||
|
#endif
|
||||||
|
} while(__atomic_load_n(&hashtable_seed, __ATOMIC_ACQUIRE) == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#elif defined(HAVE_SYNC_BUILTINS) && (defined(HAVE_SCHED_YIELD) || !defined(_WIN32))
|
||||||
|
void json_object_seed(size_t seed) {
|
||||||
|
uint32_t new_seed = (uint32_t)seed;
|
||||||
|
|
||||||
|
if (hashtable_seed == 0) {
|
||||||
|
if (new_seed == 0) {
|
||||||
|
/* Explicit synchronization fences are not supported by the
|
||||||
|
__sync builtins, so every thread getting here has to
|
||||||
|
generate the seed value.
|
||||||
|
*/
|
||||||
|
new_seed = generate_seed();
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (__sync_bool_compare_and_swap(&hashtable_seed, 0, new_seed)) {
|
||||||
|
/* We were the first to seed */
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
/* Wait for another thread to do the seeding */
|
||||||
|
#ifdef HAVE_SCHED_YIELD
|
||||||
|
sched_yield();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
} while(hashtable_seed == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
static long seed_initialized = 0;
|
||||||
|
void json_object_seed(size_t seed) {
|
||||||
|
uint32_t new_seed = (uint32_t)seed;
|
||||||
|
|
||||||
|
if (hashtable_seed == 0) {
|
||||||
|
if (InterlockedIncrement(&seed_initialized) == 1) {
|
||||||
|
/* Do the seeding ourselves */
|
||||||
|
if (new_seed == 0)
|
||||||
|
new_seed = generate_seed();
|
||||||
|
|
||||||
|
hashtable_seed = new_seed;
|
||||||
|
} else {
|
||||||
|
/* Wait for another thread to do the seeding */
|
||||||
|
do {
|
||||||
|
SwitchToThread();
|
||||||
|
} while (hashtable_seed == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/* Fall back to a thread-unsafe version */
|
||||||
|
void json_object_seed(size_t seed) {
|
||||||
|
uint32_t new_seed = (uint32_t)seed;
|
||||||
|
|
||||||
|
if (hashtable_seed == 0) {
|
||||||
|
if (new_seed == 0)
|
||||||
|
new_seed = generate_seed();
|
||||||
|
|
||||||
|
hashtable_seed = new_seed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
311
compat/jansson/jansson.h
Normal file
311
compat/jansson/jansson.h
Normal file
File diff suppressed because it is too large
Load Diff
43
compat/jansson/jansson_config.h
Normal file
43
compat/jansson/jansson_config.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2010-2016 Petri Lehtinen <petri@digip.org>
|
||||||
|
*
|
||||||
|
* Jansson is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the MIT license. See LICENSE for details.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This file specifies a part of the site-specific configuration for
|
||||||
|
* Jansson, namely those things that affect the public API in
|
||||||
|
* jansson.h.
|
||||||
|
*
|
||||||
|
* The configure script copies this file to jansson_config.h and
|
||||||
|
* replaces @var@ substitutions by values that fit your system. If you
|
||||||
|
* cannot run the configure script, you can do the value substitution
|
||||||
|
* by hand.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef JANSSON_CONFIG_H
|
||||||
|
#define JANSSON_CONFIG_H
|
||||||
|
|
||||||
|
/* If your compiler supports the inline keyword in C, JSON_INLINE is
|
||||||
|
defined to `inline', otherwise empty. In C++, the inline is always
|
||||||
|
supported. */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#define JSON_INLINE inline
|
||||||
|
#else
|
||||||
|
#define JSON_INLINE inline
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* If your compiler supports the `long long` type and the strtoll()
|
||||||
|
library function, JSON_INTEGER_IS_LONG_LONG is defined to 1,
|
||||||
|
otherwise to 0. */
|
||||||
|
#define JSON_INTEGER_IS_LONG_LONG 1
|
||||||
|
|
||||||
|
/* If locale.h and localeconv() are available, define to 1,
|
||||||
|
otherwise to 0. */
|
||||||
|
#define JSON_HAVE_LOCALECONV 1
|
||||||
|
|
||||||
|
/* Maximum recursion depth for parsing JSON input.
|
||||||
|
This limits the depth of e.g. array-within-array constructions. */
|
||||||
|
#define JSON_PARSER_MAX_DEPTH 2048
|
||||||
|
|
||||||
|
#endif
|
108
compat/jansson/jansson_private.h
Normal file
108
compat/jansson/jansson_private.h
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2016 Petri Lehtinen <petri@digip.org>
|
||||||
|
*
|
||||||
|
* Jansson is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the MIT license. See LICENSE for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef JANSSON_PRIVATE_H
|
||||||
|
#define JANSSON_PRIVATE_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include "jansson.h"
|
||||||
|
#include "hashtable.h"
|
||||||
|
#include "strbuffer.h"
|
||||||
|
|
||||||
|
#define container_of(ptr_, type_, member_) \
|
||||||
|
((type_ *)((char *)ptr_ - offsetof(type_, member_)))
|
||||||
|
|
||||||
|
/* On some platforms, max() may already be defined */
|
||||||
|
#ifndef max
|
||||||
|
#define max(a, b) ((a) > (b) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* va_copy is a C99 feature. In C89 implementations, it's sometimes
|
||||||
|
available as __va_copy. If not, memcpy() should do the trick. */
|
||||||
|
#ifndef va_copy
|
||||||
|
#ifdef __va_copy
|
||||||
|
#define va_copy __va_copy
|
||||||
|
#else
|
||||||
|
#define va_copy(a, b) memcpy(&(a), &(b), sizeof(va_list))
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
json_t json;
|
||||||
|
hashtable_t hashtable;
|
||||||
|
int visited;
|
||||||
|
} json_object_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
json_t json;
|
||||||
|
size_t size;
|
||||||
|
size_t entries;
|
||||||
|
json_t **table;
|
||||||
|
int visited;
|
||||||
|
} json_array_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
json_t json;
|
||||||
|
char *value;
|
||||||
|
size_t length;
|
||||||
|
} json_string_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
json_t json;
|
||||||
|
double value;
|
||||||
|
} json_real_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
json_t json;
|
||||||
|
json_int_t value;
|
||||||
|
} json_integer_t;
|
||||||
|
|
||||||
|
#define json_to_object(json_) container_of(json_, json_object_t, json)
|
||||||
|
#define json_to_array(json_) container_of(json_, json_array_t, json)
|
||||||
|
#define json_to_string(json_) container_of(json_, json_string_t, json)
|
||||||
|
#define json_to_real(json_) container_of(json_, json_real_t, json)
|
||||||
|
#define json_to_integer(json_) container_of(json_, json_integer_t, json)
|
||||||
|
|
||||||
|
/* Create a string by taking ownership of an existing buffer */
|
||||||
|
json_t *jsonp_stringn_nocheck_own(const char *value, size_t len);
|
||||||
|
|
||||||
|
/* Error message formatting */
|
||||||
|
void jsonp_error_init(json_error_t *error, const char *source);
|
||||||
|
void jsonp_error_set_source(json_error_t *error, const char *source);
|
||||||
|
void jsonp_error_set(json_error_t *error, int line, int column,
|
||||||
|
size_t position, const char *msg, ...);
|
||||||
|
void jsonp_error_vset(json_error_t *error, int line, int column,
|
||||||
|
size_t position, const char *msg, va_list ap);
|
||||||
|
|
||||||
|
/* Locale independent string<->double conversions */
|
||||||
|
int jsonp_strtod(strbuffer_t *strbuffer, double *out);
|
||||||
|
int jsonp_dtostr(char *buffer, size_t size, double value, int prec);
|
||||||
|
|
||||||
|
/* Wrappers for custom memory functions */
|
||||||
|
void* jsonp_malloc(size_t size);
|
||||||
|
void jsonp_free(void *ptr);
|
||||||
|
char *jsonp_strndup(const char *str, size_t length);
|
||||||
|
char *jsonp_strdup(const char *str);
|
||||||
|
char *jsonp_strndup(const char *str, size_t len);
|
||||||
|
|
||||||
|
|
||||||
|
/* Windows compatibility */
|
||||||
|
#if defined(_WIN32) || defined(WIN32)
|
||||||
|
# if defined(_MSC_VER) /* MS compiller */
|
||||||
|
# if (_MSC_VER < 1900) && !defined(snprintf) /* snprintf not defined yet & not introduced */
|
||||||
|
# define snprintf _snprintf
|
||||||
|
# endif
|
||||||
|
# if (_MSC_VER < 1500) && !defined(vsnprintf) /* vsnprintf not defined yet & not introduced */
|
||||||
|
# define vsnprintf(b,c,f,a) _vsnprintf(b,c,f,a)
|
||||||
|
# endif
|
||||||
|
# else /* Other Windows compiller, old definition */
|
||||||
|
# define snprintf _snprintf
|
||||||
|
# define vsnprintf _vsnprintf
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
159
compat/jansson/jansson_private_config.h
Normal file
159
compat/jansson/jansson_private_config.h
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
/* jansson_private_config.h. Generated from jansson_private_config.h.in by configure. */
|
||||||
|
/* jansson_private_config.h.in. Generated from configure.ac by autoheader. */
|
||||||
|
|
||||||
|
/* Define to 1 if gcc's __atomic builtins are available */
|
||||||
|
#define HAVE_ATOMIC_BUILTINS 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `close' function. */
|
||||||
|
#define HAVE_CLOSE 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||||
|
/* #undef HAVE_DLFCN_H */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <endian.h> header file. */
|
||||||
|
/* #undef HAVE_ENDIAN_H */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <fcntl.h> header file. */
|
||||||
|
#define HAVE_FCNTL_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `getpid' function. */
|
||||||
|
#define HAVE_GETPID 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `gettimeofday' function. */
|
||||||
|
#define HAVE_GETTIMEOFDAY 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||||
|
#define HAVE_INTTYPES_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `localeconv' function. */
|
||||||
|
#define HAVE_LOCALECONV 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <locale.h> header file. */
|
||||||
|
#define HAVE_LOCALE_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if the system has the type 'long long int'. */
|
||||||
|
#define HAVE_LONG_LONG_INT 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <memory.h> header file. */
|
||||||
|
#define HAVE_MEMORY_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `open' function. */
|
||||||
|
#define HAVE_OPEN 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `read' function. */
|
||||||
|
#define HAVE_READ 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sched.h> header file. */
|
||||||
|
#define HAVE_SCHED_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `sched_yield' function. */
|
||||||
|
#define HAVE_SCHED_YIELD 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <stdint.h> header file. */
|
||||||
|
#define HAVE_STDINT_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||||
|
#define HAVE_STDLIB_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <strings.h> header file. */
|
||||||
|
#define HAVE_STRINGS_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <string.h> header file. */
|
||||||
|
#define HAVE_STRING_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `strtoll' function. */
|
||||||
|
#define HAVE_STRTOLL 1
|
||||||
|
|
||||||
|
/* Define to 1 if gcc's __sync builtins are available */
|
||||||
|
#define HAVE_SYNC_BUILTINS 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/param.h> header file. */
|
||||||
|
#define HAVE_SYS_PARAM_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||||
|
#define HAVE_SYS_STAT_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||||
|
#define HAVE_SYS_TIME_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||||
|
#define HAVE_SYS_TYPES_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <unistd.h> header file. */
|
||||||
|
#define HAVE_UNISTD_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if the system has the type 'unsigned long long int'. */
|
||||||
|
#define HAVE_UNSIGNED_LONG_LONG_INT 1
|
||||||
|
|
||||||
|
/* Number of buckets new object hashtables contain is 2 raised to this power.
|
||||||
|
E.g. 3 -> 2^3 = 8. */
|
||||||
|
#define INITIAL_HASHTABLE_ORDER 3
|
||||||
|
|
||||||
|
/* Define to the sub-directory where libtool stores uninstalled libraries. */
|
||||||
|
#define LT_OBJDIR ".libs/"
|
||||||
|
|
||||||
|
/* Name of package */
|
||||||
|
#define PACKAGE "jansson"
|
||||||
|
|
||||||
|
/* Define to the address where bug reports for this package should be sent. */
|
||||||
|
#define PACKAGE_BUGREPORT "petri@digip.org"
|
||||||
|
|
||||||
|
/* Define to the full name of this package. */
|
||||||
|
#define PACKAGE_NAME "jansson"
|
||||||
|
|
||||||
|
/* Define to the full name and version of this package. */
|
||||||
|
#define PACKAGE_STRING "jansson 2.9"
|
||||||
|
|
||||||
|
/* Define to the one symbol short name of this package. */
|
||||||
|
#define PACKAGE_TARNAME "jansson"
|
||||||
|
|
||||||
|
/* Define to the home page for this package. */
|
||||||
|
#define PACKAGE_URL ""
|
||||||
|
|
||||||
|
/* Define to the version of this package. */
|
||||||
|
#define PACKAGE_VERSION "2.9"
|
||||||
|
|
||||||
|
/* Define to 1 if you have the ANSI C header files. */
|
||||||
|
#define STDC_HEADERS 1
|
||||||
|
|
||||||
|
/* Define to 1 if /dev/urandom should be used for seeding the hash function */
|
||||||
|
#define USE_URANDOM 1
|
||||||
|
|
||||||
|
/* Define to 1 if CryptGenRandom should be used for seeding the hash function
|
||||||
|
*/
|
||||||
|
#define USE_WINDOWS_CRYPTOAPI 1
|
||||||
|
|
||||||
|
/* Version number of package */
|
||||||
|
#define VERSION "2.9"
|
||||||
|
|
||||||
|
/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
|
||||||
|
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
|
||||||
|
#define below would cause a syntax error. */
|
||||||
|
/* #undef _UINT32_T */
|
||||||
|
|
||||||
|
/* Define for Solaris 2.5.1 so the uint8_t typedef from <sys/synch.h>,
|
||||||
|
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
|
||||||
|
#define below would cause a syntax error. */
|
||||||
|
/* #undef _UINT8_T */
|
||||||
|
|
||||||
|
/* Define to `__inline__' or `__inline' if that's what the C compiler
|
||||||
|
calls it, or to nothing if 'inline' is not supported under any name. */
|
||||||
|
#ifndef __cplusplus
|
||||||
|
/* #undef inline */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Define to the type of a signed integer type of width exactly 32 bits if
|
||||||
|
such a type exists and the standard includes do not define it. */
|
||||||
|
/* #undef int32_t */
|
||||||
|
|
||||||
|
/* Define to the type of an unsigned integer type of width exactly 16 bits if
|
||||||
|
such a type exists and the standard includes do not define it. */
|
||||||
|
/* #undef uint16_t */
|
||||||
|
|
||||||
|
/* Define to the type of an unsigned integer type of width exactly 32 bits if
|
||||||
|
such a type exists and the standard includes do not define it. */
|
||||||
|
/* #undef uint32_t */
|
||||||
|
|
||||||
|
/* Define to the type of an unsigned integer type of width exactly 8 bits if
|
||||||
|
such a type exists and the standard includes do not define it. */
|
||||||
|
/* #undef uint8_t */
|
1110
compat/jansson/load.c
Normal file
1110
compat/jansson/load.c
Normal file
File diff suppressed because it is too large
Load Diff
381
compat/jansson/lookup3.h
Normal file
381
compat/jansson/lookup3.h
Normal file
File diff suppressed because it is too large
Load Diff
69
compat/jansson/memory.c
Normal file
69
compat/jansson/memory.c
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2016 Petri Lehtinen <petri@digip.org>
|
||||||
|
* Copyright (c) 2011-2012 Basile Starynkevitch <basile@starynkevitch.net>
|
||||||
|
*
|
||||||
|
* Jansson is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the MIT license. See LICENSE for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "jansson.h"
|
||||||
|
#include "jansson_private.h"
|
||||||
|
|
||||||
|
/* C89 allows these to be macros */
|
||||||
|
#undef malloc
|
||||||
|
#undef free
|
||||||
|
|
||||||
|
/* memory function pointers */
|
||||||
|
static json_malloc_t do_malloc = malloc;
|
||||||
|
static json_free_t do_free = free;
|
||||||
|
|
||||||
|
void *jsonp_malloc(size_t size)
|
||||||
|
{
|
||||||
|
if(!size)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return (*do_malloc)(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void jsonp_free(void *ptr)
|
||||||
|
{
|
||||||
|
if(!ptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
(*do_free)(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *jsonp_strdup(const char *str)
|
||||||
|
{
|
||||||
|
return jsonp_strndup(str, strlen(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
char *jsonp_strndup(const char *str, size_t len)
|
||||||
|
{
|
||||||
|
char *new_str;
|
||||||
|
|
||||||
|
new_str = jsonp_malloc(len + 1);
|
||||||
|
if(!new_str)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
memcpy(new_str, str, len);
|
||||||
|
new_str[len] = '\0';
|
||||||
|
return new_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
void json_set_alloc_funcs(json_malloc_t malloc_fn, json_free_t free_fn)
|
||||||
|
{
|
||||||
|
do_malloc = malloc_fn;
|
||||||
|
do_free = free_fn;
|
||||||
|
}
|
||||||
|
|
||||||
|
void json_get_alloc_funcs(json_malloc_t *malloc_fn, json_free_t *free_fn)
|
||||||
|
{
|
||||||
|
if (malloc_fn)
|
||||||
|
*malloc_fn = do_malloc;
|
||||||
|
if (free_fn)
|
||||||
|
*free_fn = do_free;
|
||||||
|
}
|
871
compat/jansson/pack_unpack.c
Normal file
871
compat/jansson/pack_unpack.c
Normal file
File diff suppressed because it is too large
Load Diff
111
compat/jansson/strbuffer.c
Normal file
111
compat/jansson/strbuffer.c
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2016 Petri Lehtinen <petri@digip.org>
|
||||||
|
*
|
||||||
|
* Jansson is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the MIT license. See LICENSE for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _GNU_SOURCE
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "jansson_private.h"
|
||||||
|
#include "strbuffer.h"
|
||||||
|
|
||||||
|
#define STRBUFFER_MIN_SIZE 16
|
||||||
|
#define STRBUFFER_FACTOR 2
|
||||||
|
#define STRBUFFER_SIZE_MAX ((size_t)-1)
|
||||||
|
|
||||||
|
int strbuffer_init(strbuffer_t *strbuff)
|
||||||
|
{
|
||||||
|
strbuff->size = STRBUFFER_MIN_SIZE;
|
||||||
|
strbuff->length = 0;
|
||||||
|
|
||||||
|
strbuff->value = jsonp_malloc(strbuff->size);
|
||||||
|
if(!strbuff->value)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* initialize to empty */
|
||||||
|
strbuff->value[0] = '\0';
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void strbuffer_close(strbuffer_t *strbuff)
|
||||||
|
{
|
||||||
|
if(strbuff->value)
|
||||||
|
jsonp_free(strbuff->value);
|
||||||
|
|
||||||
|
strbuff->size = 0;
|
||||||
|
strbuff->length = 0;
|
||||||
|
strbuff->value = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void strbuffer_clear(strbuffer_t *strbuff)
|
||||||
|
{
|
||||||
|
strbuff->length = 0;
|
||||||
|
strbuff->value[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *strbuffer_value(const strbuffer_t *strbuff)
|
||||||
|
{
|
||||||
|
return strbuff->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *strbuffer_steal_value(strbuffer_t *strbuff)
|
||||||
|
{
|
||||||
|
char *result = strbuff->value;
|
||||||
|
strbuff->value = NULL;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int strbuffer_append_byte(strbuffer_t *strbuff, char byte)
|
||||||
|
{
|
||||||
|
return strbuffer_append_bytes(strbuff, &byte, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int strbuffer_append_bytes(strbuffer_t *strbuff, const char *data, size_t size)
|
||||||
|
{
|
||||||
|
if(size >= strbuff->size - strbuff->length)
|
||||||
|
{
|
||||||
|
size_t new_size;
|
||||||
|
char *new_value;
|
||||||
|
|
||||||
|
/* avoid integer overflow */
|
||||||
|
if (strbuff->size > STRBUFFER_SIZE_MAX / STRBUFFER_FACTOR
|
||||||
|
|| size > STRBUFFER_SIZE_MAX - 1
|
||||||
|
|| strbuff->length > STRBUFFER_SIZE_MAX - 1 - size)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
new_size = max(strbuff->size * STRBUFFER_FACTOR,
|
||||||
|
strbuff->length + size + 1);
|
||||||
|
|
||||||
|
new_value = jsonp_malloc(new_size);
|
||||||
|
if(!new_value)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
memcpy(new_value, strbuff->value, strbuff->length);
|
||||||
|
|
||||||
|
jsonp_free(strbuff->value);
|
||||||
|
strbuff->value = new_value;
|
||||||
|
strbuff->size = new_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(strbuff->value + strbuff->length, data, size);
|
||||||
|
strbuff->length += size;
|
||||||
|
strbuff->value[strbuff->length] = '\0';
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char strbuffer_pop(strbuffer_t *strbuff)
|
||||||
|
{
|
||||||
|
if(strbuff->length > 0) {
|
||||||
|
char c = strbuff->value[--strbuff->length];
|
||||||
|
strbuff->value[strbuff->length] = '\0';
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return '\0';
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user