blob: ece254c51976002389fed4d9c16679b55eb1b27d [file] [log] [blame]
#if defined(_WIN32) && !defined(_CRT_SECURE_NO_WARNINGS)
# define _CRT_SECURE_NO_WARNINGS
#endif
#include <rpmalloc.h>
#include <rpnew.h>
#include <thread.h>
#include <test.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <inttypes.h>
extern "C" void* RPMALLOC_CDECL pvalloc(size_t size);
extern "C" void* RPMALLOC_CDECL valloc(size_t size);
static size_t _hardware_threads;
static void
test_initialize(void);
static int
test_fail(const char* reason) {
fprintf(stderr, "FAIL: %s\n", reason);
return -1;
}
static int
test_alloc(void) {
const rpmalloc_config_t* config = rpmalloc_config();
void* p = malloc(371);
if (!p)
return test_fail("malloc failed");
if ((rpmalloc_usable_size(p) < 371) || (rpmalloc_usable_size(p) > (371 + 16)))
return test_fail("usable size invalid (1)");
rpfree(p);
p = new int;
if (!p)
return test_fail("new failed");
if (rpmalloc_usable_size(p) != 16)
return test_fail("usable size invalid (2)");
delete static_cast<int*>(p);
p = new int[16];
if (!p)
return test_fail("new[] failed");
if (rpmalloc_usable_size(p) != 16*sizeof(int))
return test_fail("usable size invalid (3)");
delete[] static_cast<int*>(p);
p = new int[32];
if (!p)
return test_fail("new[] failed");
if (rpmalloc_usable_size(p) != 32*sizeof(int))
return test_fail("usable size invalid (4)");
delete[] static_cast<int*>(p);
p = valloc(873);
if (reinterpret_cast<uintptr_t>(p) & (config->page_size - 1)) {
fprintf(stderr, "FAIL: pvalloc did not align address to page size (%p)\n", p);
return -1;
}
free(p);
p = pvalloc(275);
if (reinterpret_cast<uintptr_t>(p) & (config->page_size - 1)) {
fprintf(stderr, "FAIL: pvalloc did not align address to page size (%p)\n", p);
return -1;
}
if (reinterpret_cast<uintptr_t>(p) < config->page_size) {
fprintf(stderr, "FAIL: pvalloc did not align size to page size (%" PRIu64 ")\n", static_cast<uint64_t>(rpmalloc_usable_size(p)));
return -1;
}
rpfree(p);
printf("Allocation tests passed\n");
return 0;
}
static int
test_free(void) {
free(rpmalloc(371));
free(new int);
free(new int[16]);
free(pvalloc(1275));
printf("Free tests passed\n");
return 0;
}
static void
basic_thread(void* argp) {
(void)sizeof(argp);
int res = test_alloc();
if (res) {
thread_exit(static_cast<uintptr_t>(res));
return;
}
res = test_free();
if (res) {
thread_exit(static_cast<uintptr_t>(res));
return;
}
thread_exit(0);
}
static int
test_thread(void) {
uintptr_t thread[2];
uintptr_t threadres[2];
thread_arg targ;
memset(&targ, 0, sizeof(targ));
targ.fn = basic_thread;
for (int i = 0; i < 2; ++i)
thread[i] = thread_run(&targ);
for (int i = 0; i < 2; ++i) {
threadres[i] = thread_join(thread[i]);
if (threadres[i])
return -1;
}
printf("Thread tests passed\n");
return 0;
}
int
test_run(int argc, char** argv) {
(void)sizeof(argc);
(void)sizeof(argv);
test_initialize();
if (test_alloc())
return -1;
if (test_free())
return -1;
if (test_thread())
return -1;
printf("All tests passed\n");
return 0;
}
#if (defined(__APPLE__) && __APPLE__)
# include <TargetConditionals.h>
# if defined(__IPHONE__) || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || (defined(TARGET_IPHONE_SIMULATOR) && TARGET_IPHONE_SIMULATOR)
# define NO_MAIN 1
# endif
#elif (defined(__linux__) || defined(__linux))
# include <sched.h>
#endif
#if !defined(NO_MAIN)
int
main(int argc, char** argv) {
return test_run(argc, argv);
}
#endif
#ifdef _WIN32
#if defined(__clang__)
#pragma clang diagnostic ignored "-Wnonportable-system-include-path"
#endif
#include <windows.h>
static void
test_initialize(void) {
SYSTEM_INFO system_info;
GetSystemInfo(&system_info);
_hardware_threads = static_cast<size_t>(system_info.dwNumberOfProcessors);
}
#elif (defined(__linux__) || defined(__linux))
static void
test_initialize(void) {
cpu_set_t prevmask, testmask;
CPU_ZERO(&prevmask);
CPU_ZERO(&testmask);
sched_getaffinity(0, sizeof(prevmask), &prevmask); //Get current mask
sched_setaffinity(0, sizeof(testmask), &testmask); //Set zero mask
sched_getaffinity(0, sizeof(testmask), &testmask); //Get mask for all CPUs
sched_setaffinity(0, sizeof(prevmask), &prevmask); //Reset current mask
int num = CPU_COUNT(&testmask);
_hardware_threads = static_cast<size_t>(num > 1 ? num : 1);
}
#else
static void
test_initialize(void) {
_hardware_threads = 1;
}
#endif