1
0
mirror of https://github.com/facebook/zstd.git synced 2025-07-29 11:21:22 +03:00

Add userland test with mock kernel headers

This commit is contained in:
Nick Terrell
2017-04-04 11:53:22 -07:00
parent 33fc0ad56a
commit 79298bf187
8 changed files with 713 additions and 0 deletions

1
contrib/linux-kernel/test/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*Test

View File

@ -0,0 +1,27 @@
IFLAGS := -isystem include/ -I ../include/ -I ../lib/ -isystem googletest/googletest/include
SOURCES := $(wildcard ../lib/*.c)
OBJECTS := $(patsubst %.c,%.o,$(SOURCES))
ARFLAGS := rcs
CXXFLAGS += -std=c++11
CFLAGS += -g -O0
CPPFLAGS += $(IFLAGS)
../lib/libzstd.a: $(OBJECTS)
$(AR) $(ARFLAGS) $@ $^
UserlandTest: UserlandTest.cpp ../lib/libzstd.a
$(CXX) $(CXXFLAGS) $(CFLAGS) $(CPPFLAGS) $^ googletest/build/googlemock/gtest/libgtest.a googletest/build/googlemock/gtest/libgtest_main.a -o $@
# Install googletest
.PHONY: googletest
googletest:
@$(RM) -rf googletest
@git clone https://github.com/google/googletest
@mkdir -p googletest/build
@cd googletest/build && cmake .. && $(MAKE)
clean:
$(RM) -f *.{o,a} ../lib/*.{o,a}

View File

@ -0,0 +1,479 @@
extern "C" {
#include <zstd.h>
}
#include <gtest/gtest.h>
#include <memory>
#include <string>
#include <iostream>
using namespace std;
namespace {
struct WorkspaceDeleter {
void *memory;
template <typename T> void operator()(T const *) { free(memory); }
};
std::unique_ptr<ZSTD_CCtx, WorkspaceDeleter>
createCCtx(ZSTD_compressionParameters cParams) {
size_t const workspaceSize = ZSTD_CCtxWorkspaceBound(cParams);
void *workspace = malloc(workspaceSize);
std::unique_ptr<ZSTD_CCtx, WorkspaceDeleter> cctx{
ZSTD_createCCtx(workspace, workspaceSize), WorkspaceDeleter{workspace}};
if (!cctx) {
throw std::runtime_error{"Bad cctx"};
}
return cctx;
}
std::unique_ptr<ZSTD_CCtx, WorkspaceDeleter>
createCCtx(int level, unsigned long long estimatedSrcSize = 0,
size_t dictSize = 0) {
auto const cParams = ZSTD_getCParams(level, estimatedSrcSize, dictSize);
return createCCtx(cParams);
}
std::unique_ptr<ZSTD_DCtx, WorkspaceDeleter>
createDCtx() {
size_t const workspaceSize = ZSTD_DCtxWorkspaceBound();
void *workspace = malloc(workspaceSize);
std::unique_ptr<ZSTD_DCtx, WorkspaceDeleter> dctx{
ZSTD_createDCtx(workspace, workspaceSize), WorkspaceDeleter{workspace}};
if (!dctx) {
throw std::runtime_error{"Bad dctx"};
}
return dctx;
}
std::unique_ptr<ZSTD_CDict, WorkspaceDeleter>
createCDict(std::string const& dict, ZSTD_parameters params) {
size_t const workspaceSize = ZSTD_CDictWorkspaceBound(params.cParams);
void *workspace = malloc(workspaceSize);
std::unique_ptr<ZSTD_CDict, WorkspaceDeleter> cdict{
ZSTD_createCDict(dict.data(), dict.size(), params, workspace,
workspaceSize),
WorkspaceDeleter{workspace}};
if (!cdict) {
throw std::runtime_error{"Bad cdict"};
}
return cdict;
}
std::unique_ptr<ZSTD_CDict, WorkspaceDeleter>
createCDict(std::string const& dict, int level) {
auto const params = ZSTD_getParams(level, 0, dict.size());
return createCDict(dict, params);
}
std::unique_ptr<ZSTD_DDict, WorkspaceDeleter>
createDDict(std::string const& dict) {
size_t const workspaceSize = ZSTD_DDictWorkspaceBound();
void *workspace = malloc(workspaceSize);
std::unique_ptr<ZSTD_DDict, WorkspaceDeleter> ddict{
ZSTD_createDDict(dict.data(), dict.size(), workspace, workspaceSize),
WorkspaceDeleter{workspace}};
if (!ddict) {
throw std::runtime_error{"Bad ddict"};
}
return ddict;
}
std::unique_ptr<ZSTD_CStream, WorkspaceDeleter>
createCStream(ZSTD_parameters params, unsigned long long pledgedSrcSize = 0) {
size_t const workspaceSize = ZSTD_CStreamWorkspaceBound(params.cParams);
void *workspace = malloc(workspaceSize);
std::unique_ptr<ZSTD_CStream, WorkspaceDeleter> zcs{
ZSTD_createCStream(params, pledgedSrcSize, workspace, workspaceSize)};
if (!zcs) {
throw std::runtime_error{"bad cstream"};
}
return zcs;
}
std::unique_ptr<ZSTD_CStream, WorkspaceDeleter>
createCStream(ZSTD_compressionParameters cParams, ZSTD_CDict const &cdict,
unsigned long long pledgedSrcSize = 0) {
size_t const workspaceSize = ZSTD_CStreamWorkspaceBound(cParams);
void *workspace = malloc(workspaceSize);
std::unique_ptr<ZSTD_CStream, WorkspaceDeleter> zcs{
ZSTD_createCStream_usingCDict(&cdict, pledgedSrcSize, workspace,
workspaceSize)};
if (!zcs) {
throw std::runtime_error{"bad cstream"};
}
return zcs;
}
std::unique_ptr<ZSTD_CStream, WorkspaceDeleter>
createCStream(int level, unsigned long long pledgedSrcSize = 0) {
auto const params = ZSTD_getParams(level, pledgedSrcSize, 0);
return createCStream(params, pledgedSrcSize);
}
std::unique_ptr<ZSTD_DStream, WorkspaceDeleter>
createDStream(size_t maxWindowSize = (1ULL << ZSTD_WINDOWLOG_MAX),
ZSTD_DDict const *ddict = nullptr) {
size_t const workspaceSize = ZSTD_DStreamWorkspaceBound(maxWindowSize);
void *workspace = malloc(workspaceSize);
std::unique_ptr<ZSTD_DStream, WorkspaceDeleter> zds{
ddict == nullptr
? ZSTD_createDStream(maxWindowSize, workspace, workspaceSize)
: ZSTD_createDStream_usingDDict(maxWindowSize, ddict, workspace,
workspaceSize)};
if (!zds) {
throw std::runtime_error{"bad dstream"};
}
return zds;
}
std::string compress(ZSTD_CCtx &cctx, std::string const &data,
ZSTD_parameters params, std::string const &dict = "") {
std::string compressed;
compressed.resize(ZSTD_compressBound(data.size()));
size_t const rc =
dict.empty()
? ZSTD_compressCCtx(&cctx, &compressed[0], compressed.size(),
data.data(), data.size(), params)
: ZSTD_compress_usingDict(&cctx, &compressed[0], compressed.size(),
data.data(), data.size(), dict.data(),
dict.size(), params);
if (ZSTD_isError(rc)) {
throw std::runtime_error{"compression error"};
}
compressed.resize(rc);
return compressed;
}
std::string compress(ZSTD_CCtx& cctx, std::string const& data, int level, std::string const& dict = "") {
auto const params = ZSTD_getParams(level, 0, dict.size());
return compress(cctx, data, params, dict);
}
std::string decompress(ZSTD_DCtx& dctx, std::string const& compressed, size_t decompressedSize, std::string const& dict = "") {
std::string decompressed;
decompressed.resize(decompressedSize);
size_t const rc =
dict.empty()
? ZSTD_decompressDCtx(&dctx, &decompressed[0], decompressed.size(),
compressed.data(), compressed.size())
: ZSTD_decompress_usingDict(
&dctx, &decompressed[0], decompressed.size(), compressed.data(),
compressed.size(), dict.data(), dict.size());
if (ZSTD_isError(rc)) {
throw std::runtime_error{"decompression error"};
}
decompressed.resize(rc);
return decompressed;
}
std::string compress(ZSTD_CCtx& cctx, std::string const& data, ZSTD_CDict& cdict) {
std::string compressed;
compressed.resize(ZSTD_compressBound(data.size()));
size_t const rc =
ZSTD_compress_usingCDict(&cctx, &compressed[0], compressed.size(),
data.data(), data.size(), &cdict);
if (ZSTD_isError(rc)) {
throw std::runtime_error{"compression error"};
}
compressed.resize(rc);
return compressed;
}
std::string decompress(ZSTD_DCtx& dctx, std::string const& compressed, size_t decompressedSize, ZSTD_DDict& ddict) {
std::string decompressed;
decompressed.resize(decompressedSize);
size_t const rc =
ZSTD_decompress_usingDDict(&dctx, &decompressed[0], decompressed.size(),
compressed.data(), compressed.size(), &ddict);
if (ZSTD_isError(rc)) {
throw std::runtime_error{"decompression error"};
}
decompressed.resize(rc);
return decompressed;
}
std::string compress(ZSTD_CStream& zcs, std::string const& data) {
std::string compressed;
compressed.resize(ZSTD_compressBound(data.size()));
ZSTD_inBuffer in = {data.data(), data.size(), 0};
ZSTD_outBuffer out = {&compressed[0], compressed.size(), 0};
while (in.pos != in.size) {
size_t const rc = ZSTD_compressStream(&zcs, &out, &in);
if (ZSTD_isError(rc)) {
throw std::runtime_error{"compress stream failed"};
}
}
size_t const rc = ZSTD_endStream(&zcs, &out);
if (rc != 0) {
throw std::runtime_error{"compress end failed"};
}
compressed.resize(out.pos);
return compressed;
}
std::string decompress(ZSTD_DStream &zds, std::string const &compressed,
size_t decompressedSize) {
std::string decompressed;
decompressed.resize(decompressedSize);
ZSTD_inBuffer in = {compressed.data(), compressed.size(), 0};
ZSTD_outBuffer out = {&decompressed[0], decompressed.size(), 0};
while (in.pos != in.size) {
size_t const rc = ZSTD_decompressStream(&zds, &out, &in);
if (ZSTD_isError(rc)) {
throw std::runtime_error{"decompress stream failed"};
}
}
decompressed.resize(out.pos);
return decompressed;
}
std::string makeData(size_t size) {
std::string result;
result.reserve(size + 20);
while (result.size() < size) {
result += "Hello world";
}
return result;
}
std::string const kData = "Hello world";
std::string const kPlainDict = makeData(10000);
std::string const kZstdDict{
"\x37\xA4\x30\xEC\x99\x69\x58\x1C\x21\x10\xD8\x4A\x84\x01\xCC\xF3"
"\x3C\xCF\x9B\x25\xBB\xC9\x6E\xB2\x9B\xEC\x26\xAD\xCF\xDF\x4E\xCD"
"\xF3\x2C\x3A\x21\x84\x10\x42\x08\x21\x01\x33\xF1\x78\x3C\x1E\x8F"
"\xC7\xE3\xF1\x78\x3C\xCF\xF3\xBC\xF7\xD4\x42\x41\x41\x41\x41\x41"
"\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
"\x41\x41\x41\x41\xA1\x50\x28\x14\x0A\x85\x42\xA1\x50\x28\x14\x0A"
"\x85\xA2\x28\x8A\xA2\x28\x4A\x29\x7D\x74\xE1\xE1\xE1\xE1\xE1\xE1"
"\xE1\xE1\xE1\xE1\xE1\xE1\xE1\xE1\xE1\xE1\xE1\xE1\xE1\xF1\x78\x3C"
"\x1E\x8F\xC7\xE3\xF1\x78\x9E\xE7\x79\xEF\x01\x01\x00\x00\x00\x04"
"\x00\x00\x00\x08\x00\x00\x00"
"0123456789",
161};
}
TEST(Block, CCtx) {
auto cctx = createCCtx(1);
auto const compressed = compress(*cctx, kData, 1);
auto dctx = createDCtx();
auto const decompressed = decompress(*dctx, compressed, kData.size());
EXPECT_EQ(kData, decompressed);
}
TEST(Block, NoContentSize) {
auto cctx = createCCtx(1);
auto const c = compress(*cctx, kData, 1);
auto const size = ZSTD_findDecompressedSize(c.data(), c.size());
EXPECT_EQ(ZSTD_CONTENTSIZE_UNKNOWN, size);
}
TEST(Block, ContentSize) {
auto cctx = createCCtx(1);
auto params = ZSTD_getParams(1, 0, 0);
params.fParams.contentSizeFlag = 1;
auto const c = compress(*cctx, kData, params);
auto const size = ZSTD_findDecompressedSize(c.data(), c.size());
EXPECT_EQ(kData.size(), size);
}
TEST(Block, CCtxLevelIncrease) {
std::string c;
auto cctx = createCCtx(6);
auto dctx = createDCtx();
for (int level = 1; level <= 6; ++level) {
auto compressed = compress(*cctx, kData, level);
auto const decompressed = decompress(*dctx, compressed, kData.size());
EXPECT_EQ(kData, decompressed);
}
}
TEST(Block, PlainDict) {
auto cctx = createCCtx(1);
auto const compressed = compress(*cctx, kData, 1, kPlainDict);
auto dctx = createDCtx();
EXPECT_ANY_THROW(decompress(*dctx, compressed, kData.size()));
auto const decompressed =
decompress(*dctx, compressed, kData.size(), kPlainDict);
EXPECT_EQ(kData, decompressed);
}
TEST(Block, ZstdDict) {
auto cctx = createCCtx(1);
auto const compressed = compress(*cctx, kData, 1, kZstdDict);
auto dctx = createDCtx();
EXPECT_ANY_THROW(decompress(*dctx, compressed, kData.size()));
auto const decompressed =
decompress(*dctx, compressed, kData.size(), kZstdDict);
EXPECT_EQ(kData, decompressed);
}
TEST(Block, PreprocessedPlainDict) {
auto cctx = createCCtx(1);
auto const cdict = createCDict(kPlainDict, 1);
auto const compressed = compress(*cctx, kData, *cdict);
auto dctx = createDCtx();
auto const ddict = createDDict(kPlainDict);
EXPECT_ANY_THROW(decompress(*dctx, compressed, kData.size()));
auto const decompressed =
decompress(*dctx, compressed, kData.size(), *ddict);
EXPECT_EQ(kData, decompressed);
}
TEST(Block, PreprocessedZstdDict) {
auto cctx = createCCtx(1);
auto const cdict = createCDict(kZstdDict, 1);
auto const compressed = compress(*cctx, kData, *cdict);
auto dctx = createDCtx();
auto const ddict = createDDict(kZstdDict);
EXPECT_ANY_THROW(decompress(*dctx, compressed, kData.size()));
auto const decompressed =
decompress(*dctx, compressed, kData.size(), *ddict);
EXPECT_EQ(kData, decompressed);
}
TEST(Block, RecreateCCtx) {
auto cctx = createCCtx(1);
{
auto const compressed = compress(*cctx, kData, 1);
auto dctx = createDCtx();
auto const decompressed = decompress(*dctx, compressed, kData.size());
EXPECT_EQ(kData, decompressed);
}
// Create the cctx with the same memory
auto d = cctx.get_deleter();
auto raw = cctx.release();
auto params = ZSTD_getParams(1, 0, 0);
cctx.reset(
ZSTD_createCCtx(d.memory, ZSTD_CCtxWorkspaceBound(params.cParams)));
// Repeat
{
auto const compressed = compress(*cctx, kData, 1);
auto dctx = createDCtx();
auto const decompressed = decompress(*dctx, compressed, kData.size());
EXPECT_EQ(kData, decompressed);
}
}
TEST(Block, RecreateDCtx) {
auto dctx = createDCtx();
{
auto cctx = createCCtx(1);
auto const compressed = compress(*cctx, kData, 1);
auto const decompressed = decompress(*dctx, compressed, kData.size());
EXPECT_EQ(kData, decompressed);
}
// Create the cctx with the same memory
auto d = dctx.get_deleter();
auto raw = dctx.release();
dctx.reset(ZSTD_createDCtx(d.memory, ZSTD_DCtxWorkspaceBound()));
// Repeat
{
auto cctx = createCCtx(1);
auto const compressed = compress(*cctx, kData, 1);
auto dctx = createDCtx();
auto const decompressed = decompress(*dctx, compressed, kData.size());
EXPECT_EQ(kData, decompressed);
}
}
TEST(Stream, Basic) {
auto zcs = createCStream(1);
auto const compressed = compress(*zcs, kData);
auto zds = createDStream();
auto const decompressed = decompress(*zds, compressed, kData.size());
EXPECT_EQ(kData, decompressed);
}
TEST(Stream, PlainDict) {
auto params = ZSTD_getParams(1, kData.size(), kPlainDict.size());
params.cParams.windowLog = 17;
auto cdict = createCDict(kPlainDict, params);
auto zcs = createCStream(params.cParams, *cdict, kData.size());
auto const compressed = compress(*zcs, kData);
auto const contentSize =
ZSTD_findDecompressedSize(compressed.data(), compressed.size());
EXPECT_ANY_THROW(decompress(*createDStream(), compressed, kData.size()));
auto ddict = createDDict(kPlainDict);
auto zds = createDStream(1 << 17, ddict.get());
auto const decompressed = decompress(*zds, compressed, kData.size());
EXPECT_EQ(kData, decompressed);
}
TEST(Stream, ZstdDict) {
auto params = ZSTD_getParams(1, 0, 0);
params.cParams.windowLog = 17;
auto cdict = createCDict(kZstdDict, 1);
auto zcs = createCStream(params.cParams, *cdict);
auto const compressed = compress(*zcs, kData);
EXPECT_ANY_THROW(decompress(*createDStream(), compressed, kData.size()));
auto ddict = createDDict(kZstdDict);
auto zds = createDStream(1 << 17, ddict.get());
auto const decompressed = decompress(*zds, compressed, kData.size());
EXPECT_EQ(kData, decompressed);
}
TEST(Stream, ResetCStream) {
auto zcs = createCStream(1);
auto zds = createDStream();
{
auto const compressed = compress(*zcs, kData);
auto const decompressed = decompress(*zds, compressed, kData.size());
EXPECT_EQ(kData, decompressed);
}
{
ZSTD_resetCStream(zcs.get(), 0);
auto const compressed = compress(*zcs, kData);
auto const decompressed = decompress(*zds, compressed, kData.size());
EXPECT_EQ(kData, decompressed);
}
}
TEST(Stream, ResetDStream) {
auto zcs = createCStream(1);
auto zds = createDStream();
auto const compressed = compress(*zcs, kData);
EXPECT_ANY_THROW(decompress(*zds, kData, kData.size()));
EXPECT_ANY_THROW(decompress(*zds, compressed, kData.size()));
ZSTD_resetDStream(zds.get());
auto const decompressed = decompress(*zds, compressed, kData.size());
EXPECT_EQ(kData, decompressed);
}
TEST(Stream, Flush) {
auto zcs = createCStream(1);
auto zds = createDStream();
std::string compressed;
{
compressed.resize(ZSTD_compressBound(kData.size()));
ZSTD_inBuffer in = {kData.data(), kData.size(), 0};
ZSTD_outBuffer out = {&compressed[0], compressed.size(), 0};
while (in.pos != in.size) {
size_t const rc = ZSTD_compressStream(zcs.get(), &out, &in);
if (ZSTD_isError(rc)) {
throw std::runtime_error{"compress stream failed"};
}
}
EXPECT_EQ(0, out.pos);
size_t const rc = ZSTD_flushStream(zcs.get(), &out);
if (rc != 0) {
throw std::runtime_error{"compress end failed"};
}
compressed.resize(out.pos);
EXPECT_LT(0, out.pos);
}
std::string decompressed;
{
decompressed.resize(kData.size());
ZSTD_inBuffer in = {compressed.data(), compressed.size(), 0};
ZSTD_outBuffer out = {&decompressed[0], decompressed.size(), 0};
while (in.pos != in.size) {
size_t const rc = ZSTD_decompressStream(zds.get(), &out, &in);
if (ZSTD_isError(rc)) {
throw std::runtime_error{"decompress stream failed"};
}
}
}
EXPECT_EQ(kData, decompressed);
}

View File

@ -0,0 +1,177 @@
#ifndef ASM_UNALIGNED_H
#define ASM_UNALIGNED_H
#include <assert.h>
#include <linux/string.h>
#include <linux/types.h>
#define _LITTLE_ENDIAN 1
static unsigned _isLittleEndian(void)
{
const union { uint32_t u; uint8_t c[4]; } one = { 1 };
assert(_LITTLE_ENDIAN == one.c[0]);
return _LITTLE_ENDIAN;
}
static uint16_t _swap16(uint16_t in)
{
return ((in & 0xF) << 8) + ((in & 0xF0) >> 8);
}
static uint32_t _swap32(uint32_t in)
{
return __builtin_bswap32(in);
}
static uint64_t _swap64(uint64_t in)
{
return __builtin_bswap64(in);
}
/* Little endian */
static uint16_t get_unaligned_le16(const void* memPtr)
{
uint16_t val;
memcpy(&val, memPtr, sizeof(val));
if (!_isLittleEndian()) _swap16(val);
return val;
}
static uint32_t get_unaligned_le32(const void* memPtr)
{
uint32_t val;
memcpy(&val, memPtr, sizeof(val));
if (!_isLittleEndian()) _swap32(val);
return val;
}
static uint64_t get_unaligned_le64(const void* memPtr)
{
uint64_t val;
memcpy(&val, memPtr, sizeof(val));
if (!_isLittleEndian()) _swap64(val);
return val;
}
static void put_unaligned_le16(uint16_t value, void* memPtr)
{
if (!_isLittleEndian()) value = _swap16(value);
memcpy(memPtr, &value, sizeof(value));
}
static void put_unaligned_le32(uint32_t value, void* memPtr)
{
if (!_isLittleEndian()) value = _swap32(value);
memcpy(memPtr, &value, sizeof(value));
}
static void put_unaligned_le64(uint64_t value, void* memPtr)
{
if (!_isLittleEndian()) value = _swap64(value);
memcpy(memPtr, &value, sizeof(value));
}
/* big endian */
static uint32_t get_unaligned_be32(const void* memPtr)
{
uint32_t val;
memcpy(&val, memPtr, sizeof(val));
if (_isLittleEndian()) _swap32(val);
return val;
}
static uint64_t get_unaligned_be64(const void* memPtr)
{
uint64_t val;
memcpy(&val, memPtr, sizeof(val));
if (_isLittleEndian()) _swap64(val);
return val;
}
static void put_unaligned_be32(uint32_t value, void* memPtr)
{
if (_isLittleEndian()) value = _swap32(value);
memcpy(memPtr, &value, sizeof(value));
}
static void put_unaligned_be64(uint64_t value, void* memPtr)
{
if (_isLittleEndian()) value = _swap64(value);
memcpy(memPtr, &value, sizeof(value));
}
/* generic */
extern void __bad_unaligned_access_size(void);
#define __get_unaligned_le(ptr) ((typeof(*(ptr)))({ \
__builtin_choose_expr(sizeof(*(ptr)) == 1, *(ptr), \
__builtin_choose_expr(sizeof(*(ptr)) == 2, get_unaligned_le16((ptr)), \
__builtin_choose_expr(sizeof(*(ptr)) == 4, get_unaligned_le32((ptr)), \
__builtin_choose_expr(sizeof(*(ptr)) == 8, get_unaligned_le64((ptr)), \
__bad_unaligned_access_size())))); \
}))
#define __get_unaligned_be(ptr) ((typeof(*(ptr)))({ \
__builtin_choose_expr(sizeof(*(ptr)) == 1, *(ptr), \
__builtin_choose_expr(sizeof(*(ptr)) == 2, get_unaligned_be16((ptr)), \
__builtin_choose_expr(sizeof(*(ptr)) == 4, get_unaligned_be32((ptr)), \
__builtin_choose_expr(sizeof(*(ptr)) == 8, get_unaligned_be64((ptr)), \
__bad_unaligned_access_size())))); \
}))
#define __put_unaligned_le(val, ptr) \
({ \
void *__gu_p = (ptr); \
switch (sizeof(*(ptr))) { \
case 1: \
*(uint8_t *)__gu_p = (uint8_t)(val); \
break; \
case 2: \
put_unaligned_le16((uint16_t)(val), __gu_p); \
break; \
case 4: \
put_unaligned_le32((uint32_t)(val), __gu_p); \
break; \
case 8: \
put_unaligned_le64((uint64_t)(val), __gu_p); \
break; \
default: \
__bad_unaligned_access_size(); \
break; \
} \
(void)0; \
})
#define __put_unaligned_be(val, ptr) \
({ \
void *__gu_p = (ptr); \
switch (sizeof(*(ptr))) { \
case 1: \
*(uint8_t *)__gu_p = (uint8_t)(val); \
break; \
case 2: \
put_unaligned_be16((uint16_t)(val), __gu_p); \
break; \
case 4: \
put_unaligned_be32((uint32_t)(val), __gu_p); \
break; \
case 8: \
put_unaligned_be64((uint64_t)(val), __gu_p); \
break; \
default: \
__bad_unaligned_access_size(); \
break; \
} \
(void)0; \
})
#if _LITTLE_ENDIAN
# define get_unaligned __get_unaligned_le
# define put_unaligned __put_unaligned_le
#else
# define get_unaligned __get_unaligned_be
# define put_unaligned __put_unaligned_be
#endif
#endif // ASM_UNALIGNED_H

View File

@ -0,0 +1,12 @@
#ifndef LINUX_COMIPLER_H_
#define LINUX_COMIPLER_H_
#ifndef __always_inline
# define __always_inline inline
#endif
#ifndef noinline
# define noinline __attribute__((__noinline__))
#endif
#endif // LINUX_COMIPLER_H_

View File

@ -0,0 +1,14 @@
#ifndef LINUX_KERNEL_H_
#define LINUX_KERNEL_H_
#define ALIGN(x, a) ({ \
typeof(x) const __xe = (x); \
typeof(a) const __ae = (a); \
typeof(a) const __m = __ae - 1; \
typeof(x) const __r = __xe & __m; \
__xe + (__r ? (__ae - __r) : 0); \
})
#define PTR_ALIGN(p, a) (typeof(p))ALIGN((unsigned long long)(p), (a))
#endif // LINUX_KERNEL_H_

View File

@ -0,0 +1 @@
#include <string.h>

View File

@ -0,0 +1,2 @@
#include <stddef.h>
#include <stdint.h>