diff --git a/.vscode/settings.json b/.vscode/settings.json index dfd0690..c5dfb4a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -57,7 +57,11 @@ "variant": "cpp", "stddef.h": "c", "stdlib.h": "c", - "errno.h": "c" + "errno.h": "c", + "cstdio": "c", + "cstdlib": "c", + "cwchar": "c", + "new": "c" }, "C_Cpp.errorSquiggles": "disabled" } \ No newline at end of file diff --git a/benchmarks/benchmarks/larison/CMakeLists.txt b/benchmarks/benchmarks/larison/CMakeLists.txt new file mode 100644 index 0000000..63a725a --- /dev/null +++ b/benchmarks/benchmarks/larison/CMakeLists.txt @@ -0,0 +1,116 @@ +cmake_minimum_required(VERSION 3.0) +project(mimalloc-bench CXX C) +set(CMAKE_CXX_STANDARD 17) + +if (NOT CMAKE_BUILD_TYPE) + message(STATUS "No build type selected, default to *** Release ***") + set(CMAKE_BUILD_TYPE "Release") +endif() + +FUNCTION(PREPEND var prefix) + SET(listVar "") + FOREACH(f ${ARGN}) + LIST(APPEND listVar "${prefix}/${f}") + ENDFOREACH(f) + SET(${var} "${listVar}" PARENT_SCOPE) +ENDFUNCTION(PREPEND) + +# set(cfrac_sources +# cfrac.c +# pops.c pconst.c pio.c +# pabs.c pneg.c pcmp.c podd.c phalf.c +# padd.c psub.c pmul.c pdivmod.c psqrt.c ppowmod.c +# atop.c ptoa.c itop.c utop.c ptou.c errorp.c +# pfloat.c pidiv.c pimod.c picmp.c +# primes.c pcfrac.c pgcd.c) +# PREPEND(cfrac_sources . ${cfrac_sources}) + +# set(espresso_sources +# cofactor.c cols.c compl.c contain.c cubestr.c cvrin.c cvrm.c cvrmisc.c cvrout.c +# dominate.c equiv.c espresso.c essen.c exact.c expand.c gasp.c getopt.c gimpel.c +# globals.c hack.c indep.c irred.c main.c map.c matrix.c mincov.c opo.c pair.c part.c +# primes.c reduce.c rows.c set.c setc.c sharp.c sminterf.c solution.c sparse.c unate.c +# utility.c verify.c) +# PREPEND(espresso_sources . ${espresso_sources}) + +# set(barnes_sources +# code.c code_io.c load.c grav.c getparam.c util.c) +# PREPEND(barnes_sources barnes/ ${barnes_sources}) + +# turn off warnings.. +message(STATUS "${CMAKE_C_COMPILER_ID}") +if(CMAKE_C_COMPILER_ID MATCHES "AppleClang|Clang|GNU") + set(FLAGS " -w -Wno-implicit-function-declaration -Wno-implicit-int -Wno-int-conversion -Wno-return-mismatch -Wno-incompatible-pointer-types -mabi=purecap-benchmark") + string(APPEND CMAKE_C_FLAGS ${FLAGS}) + string(APPEND CMAKE_CXX_FLAGS ${FLAGS}) +endif() + +# add_executable(cfrac ${cfrac_sources}) +# target_compile_options(cfrac PRIVATE $<$:-std=gnu89>) +# target_compile_definitions(cfrac PRIVATE NOMEMOPT=1) +# target_link_libraries(cfrac m) + +# add_executable(espresso ${espresso_sources}) +# target_compile_options(espresso PRIVATE $<$:-std=gnu89>) +# target_link_libraries(espresso m) + +# add_executable(barnes ${barnes_sources}) +# target_link_libraries(barnes m) + +# add_executable(larson larson/larson.cpp) +# target_compile_options(larson PRIVATE -Wno-unused-result) +# target_compile_definitions(larson PRIVATE CPP=1) +# target_link_libraries(larson pthread) + +add_executable(larson-sized larson.cpp) +target_compile_options(larson-sized PRIVATE -Wno-unused-result -fsized-deallocation) +target_compile_definitions(larson-sized PRIVATE CPP=1 SIZED=1) +target_link_libraries(larson-sized pthread) + +# add_executable(alloc-test alloc-test/test_common.cpp alloc-test/allocator_tester.cpp) +# target_compile_definitions(alloc-test PRIVATE BENCH=4) +# target_link_libraries(alloc-test pthread) + +# if(NOT APPLE) +# add_executable(sh6bench shbench/sh6bench-new.c) +# target_compile_definitions(sh6bench PRIVATE BENCH=1 SYS_MULTI_THREAD=1) +# target_link_libraries(sh6bench pthread) + +# add_executable(sh8bench shbench/sh8bench-new.c) +# target_compile_definitions(sh8bench PRIVATE BENCH=1 SYS_MULTI_THREAD=1) +# target_link_libraries(sh8bench pthread) +# endif() + +# add_executable(cache-scratch cache-scratch/cache-scratch.cpp) +# target_link_libraries(cache-scratch pthread) + +# add_executable(cache-thrash cache-thrash/cache-thrash.cpp) +# target_link_libraries(cache-thrash pthread) + +# add_executable(xmalloc-test xmalloc-test/xmalloc-test.c) +# target_link_libraries(xmalloc-test pthread) + +# add_executable(malloc-large-old malloc-large/malloc-large-old.cpp) +# target_link_libraries(malloc-large-old pthread) + +# add_executable(malloc-large malloc-large/malloc-large.cpp) +# target_link_libraries(malloc-large pthread) + +# add_executable(mstress mstress/mstress.c) +# target_link_libraries(mstress pthread) + +# add_executable(mleak mleak/mleak.c) +# target_link_libraries(mleak pthread) + +# add_executable(rptest rptest/rptest.c rptest/thread.c rptest/timer.c) +# target_compile_options(rptest PRIVATE -fpermissive) +# target_include_directories(rptest PRIVATE rptest) +# target_link_libraries(rptest pthread m) + +# add_executable(glibc-simple glibc-bench/bench-malloc-simple.c) +# target_link_libraries(glibc-simple pthread) + +# add_executable(glibc-thread glibc-bench/bench-malloc-thread.c) +# target_link_libraries(glibc-thread pthread) + +# diff --git a/benchmarks/benchmarks/larison/larson.cpp b/benchmarks/benchmarks/larison/larson.cpp new file mode 100644 index 0000000..e1e6576 --- /dev/null +++ b/benchmarks/benchmarks/larison/larson.cpp @@ -0,0 +1,805 @@ + +#if defined(USE_HOARD) && defined(_WIN32) +#pragma comment(lib, "libhoard.lib") +#endif + +#if defined(USE_RX) && defined(_WIN32) +#pragma comment(lib, "libmi.lib") +#endif + +#include +#include + +#if defined(_WIN32) +#define __WIN32__ +#endif + +#ifdef __WIN32__ +#include +#include +#include + +#else +#include +#include +#include + +#ifndef __SVR4 +//extern "C" int pthread_setconcurrency (int) throw(); +#include +#endif + +#include "stddefines.h" + +#define malloc my_malloc +#define free my_free + +typedef void * LPVOID; +typedef long long LONGLONG; +typedef long DWORD; +typedef long LONG; +typedef unsigned long ULONG; +typedef union _LARGE_INTEGER { + struct { + DWORD LowPart; + LONG HighPart; + } foo; + LONGLONG QuadPart; // In Visual C++, a typedef to _ _int64} LARGE_INTEGER; +} LARGE_INTEGER; +typedef long long _int64; +#ifndef TRUE +enum { TRUE = 1, FALSE = 0 }; +#endif +#include +#define _ASSERTE(x) assert(x) +#define _inline inline +void Sleep (long x) +{ + // printf ("sleeping for %ld seconds.\n", x/1000); + sleep(x/1000); +} + +void QueryPerformanceCounter (long * x) +{ + struct timezone tz; + struct timeval tv; + gettimeofday (&tv, &tz); + *x = tv.tv_sec * 1000000L + tv.tv_usec; +} + +void QueryPerformanceFrequency(long * x) +{ + *x = 1000000L; +} + + +#include +#include +#include +#include +#include +#include +#include + +#define _REENTRANT 1 +#include +#ifdef __sun +#include +#endif +typedef void * VoidFunction (void *); +void _beginthread (VoidFunction x, int, void * z) +{ + pthread_t pt; + pthread_attr_t pa; + pthread_attr_init (&pa); + +#if 1//defined(__SVR4) + pthread_attr_setscope (&pa, PTHREAD_SCOPE_SYSTEM); /* bound behavior */ +#endif + + // printf ("creating a thread.\n"); + int v = pthread_create(&pt, &pa, x, z); + // printf ("v = %d\n", v); +} +#endif + + +#if 0 +static char buf[65536]; + +#define malloc(v) &buf +#define free(p) +#endif + +//#undef CPP +//#define CPP +//#include "arch-specific.h" + +#if USE_ROCKALL +//#include "FastHeap.hpp" +//FAST_HEAP theFastHeap (1024 * 1024, true, true, true); + +typedef int SBIT32; + +#include "SmpHeap.hpp" +SMP_HEAP theFastHeap (1024 * 1024, true, true, true); + +void * operator new( unsigned int cb ) +{ + void *pRet = theFastHeap.New ((size_t)cb) ; + return pRet; +} + +void operator delete[](void *pUserData ) +{ + theFastHeap.Delete (pUserData) ; +} +#endif + +#if 0 +extern "C" void * hdmalloc (size_t sz) ; +extern "C" void hdfree (void * ptr) ; +extern "C" void hdmalloc_stats (void) ; +void * operator new( unsigned int cb ) +{ + void *pRet = hdmalloc((size_t)cb) ; + return pRet; +} + +void operator delete[](void *pUserData ) +{ + hdfree(pUserData) ; +} +#endif + +#ifndef CUSTOM_MALLOC +#define CUSTOM_MALLOC malloc +#define CUSTOM_FREE free +#endif + + +/* Test driver for memory allocators */ +/* Author: Paul Larson, palarson@microsoft.com */ +#define MAX_THREADS 100 +#define MAX_BLOCKS 1000000 + +int volatile stopflag=FALSE ; + +struct lran2_st { + long x, y, v[97]; +}; + +int TotalAllocs=0 ; + +typedef struct thr_data { + + int threadno ; + int NumBlocks ; + int seed ; + + int min_size ; + int max_size ; + + char * *array ; + size_t *blksize ; + int asize ; + + long cAllocs ; + long cFrees ; + long cThreads ; + long cBytesAlloced ; + + volatile int finished ; + struct lran2_st rgen ; + +} thread_data; + +void runthreads(long sleep_cnt, int min_threads, int max_threads, + int chperthread, int num_rounds) ; +void runloops(long sleep_cnt, int num_chunks ) ; +static void warmup(char **blkp, int num_chunks ); +static void * exercise_heap( void *pinput) ; +static void lran2_init(struct lran2_st* d, long seed) ; +static long lran2(struct lran2_st* d) ; +ULONG CountReservedSpace() ; + +char * blkp[MAX_BLOCKS] ; +size_t blksize[MAX_BLOCKS] ; +long seqlock=0 ; +struct lran2_st rgen ; +int min_size=10, max_size=500 ; +int num_threads ; +ULONG init_space ; + +extern int cLockSleeps ; +extern int cAllocedChunks ; +extern int cAllocedSpace ; +extern int cUsedSpace ; +extern int cFreeChunks ; +extern int cFreeSpace ; + +int cChecked=0 ; + +#if defined(_WIN32) +extern "C" { + extern HANDLE crtheap; +}; +#endif + +int main (int argc, char *argv[]) +{ + + INITREGULARALLOC(); + +#if defined(USE_LFH) && defined(_WIN32) + // Activate 'Low Fragmentation Heap'. + ULONG info = 2; + HeapSetInformation (GetProcessHeap(), + HeapCompatibilityInformation, + &info, + sizeof(info)); +#endif +#if 0 // defined(__SVR4) + { + psinfo_t ps; + int pid = getpid(); + char fname[255]; + sprintf (fname, "/proc/%d/psinfo", pid); + // sprintf (fname, "/proc/self/ps"); + FILE * f = fopen (fname, "rb"); + printf ("opening %s\n", fname); + if (f) { + fread (&ps, sizeof(ps), 1, f); + printf ("resident set size = %dK\n", ps.pr_rssize); + fclose (f); + } + } +#endif + + // char * dummy = new char[42]; + //ReferenceLibHoard(); +#if defined(_MT) || defined(_REENTRANT) + int min_threads, max_threads ; + int num_rounds ; + int chperthread ; +#endif + unsigned seed=12345 ; + int num_chunks=10000; + long sleep_cnt; + + if (argc > 7) { + sleep_cnt = atoi(argv[1]); + min_size = atoi(argv[2]); + max_size = atoi(argv[3]); + chperthread = atoi(argv[4]); + num_rounds = atoi(argv[5]); + seed = atoi(argv[6]); + max_threads = atoi(argv[7]); + min_threads = max_threads; + goto DoneWithInput; + } + +#if defined(_MT) || defined(_REENTRANT) + //#ifdef _MT + printf( "\nMulti-threaded test driver \n") ; +#else + printf( "\nSingle-threaded test driver \n") ; +#endif +#ifdef CPP +#if defined(SIZED) + printf("C++ version (new and sized delete)\n") ; +#else + printf("C++ version (new and delete)\n") ; +#endif +#else + printf("C version (malloc and free)\n") ; +#endif + printf("runtime (sec): ") ; + scanf ("%ld", &sleep_cnt); + + printf("chunk size (min,max): ") ; + scanf("%d %d", &min_size, &max_size ) ; +#if defined(_MT) || defined(_REENTRANT) + //#ifdef _MT + printf("threads (min, max): ") ; + scanf("%d %d", &min_threads, &max_threads) ; + printf("chunks/thread: ") ; scanf("%d", &chperthread ) ; + printf("no of rounds: ") ; scanf("%d", &num_rounds ) ; + num_chunks = max_threads*chperthread ; +#else + printf("no of chunks: ") ; scanf("%d", &num_chunks ) ; +#endif + printf("random seed: ") ; scanf("%d", &seed) ; + + DoneWithInput: + + if( num_chunks > MAX_BLOCKS ){ + printf("Max %d chunks - exiting\n", MAX_BLOCKS ) ; + return(1) ; + } + +#ifndef __WIN32__ +#ifdef __SVR4 + pthread_setconcurrency (max_threads); +#endif +#endif + + lran2_init(&rgen, seed) ; + // init_space = CountReservedSpace() ; + +#if defined(_MT) || defined(_REENTRANT) + //#ifdef _MT + runthreads(sleep_cnt, min_threads, max_threads, chperthread, num_rounds) ; +#else + runloops(sleep_cnt, num_chunks ) ; +#endif + +#ifdef _DEBUG + //_cputs("Hit any key to exit...") ; (void)_getch() ; +#endif + +#if 0 // defined(__SVR4) + { + psinfo_t ps; + int pid = getpid(); + char fname[255]; + sprintf (fname, "/proc/%d/psinfo", pid); + // sprintf (fname, "/proc/self/ps"); + FILE * f = fopen (fname, "rb"); + printf ("opening %s\n", fname); + if (f) { + fread (&ps, sizeof(ps), 1, f); + printf ("resident set size = %dK\n", ps.pr_rssize); + fclose (f); + } + } +#endif + + return(0) ; + +} /* main */ + +void runloops(long sleep_cnt, int num_chunks ) +{ + int cblks ; + int victim ; + size_t blk_size ; +#ifdef __WIN32__ + _LARGE_INTEGER ticks_per_sec, start_cnt, end_cnt; +#else + long ticks_per_sec ; + long start_cnt, end_cnt ; +#endif + _int64 ticks ; + double duration ; + double reqd_space ; + ULONG used_space=0 ; + long sum_allocs=0 ; + + QueryPerformanceFrequency( &ticks_per_sec ) ; + QueryPerformanceCounter( &start_cnt) ; + + for( cblks=0; cblks= sleep_cnt) break ; + } + reqd_space = (0.5*(min_size+max_size)*num_chunks) ; + // used_space = CountReservedSpace() - init_space; + + printf("%6.3f", duration ) ; + printf("%8.0f", sum_allocs/duration ) ; + printf(" %6.3f %.3f", (double)used_space/(1024*1024), used_space/reqd_space) ; + printf("\n") ; + +} + + +#if defined(_MT) || defined(_REENTRANT) +//#ifdef _MT +void runthreads(long sleep_cnt, int min_threads, int max_threads, int chperthread, int num_rounds) +{ + thread_data de_area[MAX_THREADS] ; + thread_data *pdea; + long nperthread ; + long sum_threads ; + _int64 sum_allocs ; + _int64 sum_frees ; + double duration ; +#ifdef __WIN32__ + _LARGE_INTEGER ticks_per_sec, start_cnt, end_cnt; +#else + long ticks_per_sec ; + long start_cnt, end_cnt ; +#endif + _int64 ticks ; + double rate_1=0, rate_n ; + double reqd_space ; + ULONG used_space ; + int prevthreads ; + int i ; + + QueryPerformanceFrequency( &ticks_per_sec ) ; + + pdea = &de_area[0] ; + memset(&de_area[0], 0, sizeof(thread_data)) ; + + prevthreads = 0 ; + for(num_threads=min_threads; num_threads <= max_threads; num_threads++ ) + { + + warmup(&blkp[prevthreads*chperthread], (num_threads-prevthreads)*chperthread ); + + nperthread = chperthread ; + stopflag = FALSE ; + + for(i=0; i< num_threads; i++){ + de_area[i].threadno = i+1 ; + de_area[i].NumBlocks = num_rounds*nperthread; + de_area[i].array = &blkp[i*nperthread] ; + de_area[i].blksize = &blksize[i*nperthread] ; + de_area[i].asize = nperthread ; + de_area[i].min_size = min_size ; + de_area[i].max_size = max_size ; + de_area[i].seed = lran2(&rgen) ; ; + de_area[i].finished = 0 ; + de_area[i].cAllocs = 0 ; + de_area[i].cFrees = 0 ; + de_area[i].cThreads = 0 ; + de_area[i].finished = FALSE ; + lran2_init(&de_area[i].rgen, de_area[i].seed) ; + +#ifdef __WIN32__ + _beginthread((void (__cdecl*)(void *)) exercise_heap, 0, &de_area[i]) ; +#else + _beginthread(exercise_heap, 0, &de_area[i]) ; +#endif + + } + + QueryPerformanceCounter( &start_cnt) ; + + // printf ("Sleeping for %ld seconds.\n", sleep_cnt); + Sleep(sleep_cnt * 1000L) ; + + stopflag = TRUE ; + + for(i=0; ifinished = FALSE ; + pdea->cThreads++ ; + range = pdea->max_size - pdea->min_size ; + + /* allocate NumBlocks chunks of random size */ + for( cblks=0; cblksNumBlocks; cblks++){ + victim = lran2(&pdea->rgen)%pdea->asize ; +#ifdef CPP +#if defined(SIZED) + operator delete[] (pdea->array[victim], pdea->blksize[victim]); +#else + delete[] pdea->array[victim] ; +#endif +#else + CUSTOM_FREE(pdea->array[victim]) ; +#endif + pdea->cFrees++ ; + + if (range == 0) { + blk_size = pdea->min_size; + } else { + blk_size = pdea->min_size+lran2(&pdea->rgen)%range ; + } +#ifdef CPP + pdea->array[victim] = new char[blk_size] ; +#else + pdea->array[victim] = (char *) CUSTOM_MALLOC(blk_size) ; +#endif + + pdea->blksize[victim] = blk_size ; + assert(pdea->array[victim] != NULL) ; + + pdea->cAllocs++ ; + + /* Write something! */ + + volatile char * chptr = ((char *) pdea->array[victim]); + *chptr++ = 'a'; + volatile char ch = *((char *) pdea->array[victim]); + *chptr = 'b'; + + + if( stopflag ) break ; + } + + // printf("Thread %u terminating: %d allocs, %d frees\n", + // pdea->threadno, pdea->cAllocs, pdea->cFrees) ; + pdea->finished = TRUE ; + + + if( !stopflag ){ +#ifdef __WIN32__ + _beginthread((void (__cdecl*)(void *)) exercise_heap, 0, pdea) ; +#else + _beginthread(exercise_heap, 0, pdea) ; +#endif + } else { + // printf ("thread stopping.\n"); + } + + //end_thread(); + +#ifndef _WIN32 + pthread_exit (NULL); +#endif + return 0; +} + +static void warmup(char **blkp, int num_chunks ) +{ + int cblks ; + int victim ; + size_t blk_size ; + LPVOID tmp ; + size_t tmp_sz; + + + for( cblks=0; cblks 0 ; cblks--){ + victim = lran2(&rgen)%cblks ; + tmp = blkp[victim] ; + tmp_sz = blksize[victim]; + blkp[victim] = blkp[cblks-1] ; + blksize[victim] = blksize[cblks-1]; + blkp[cblks-1] = (char *) tmp ; + blksize[cblks-1] = tmp_sz; + } + + for( cblks=0; cblks<4*num_chunks; cblks++){ + victim = lran2(&rgen)%num_chunks ; +#ifdef CPP +#if defined(SIZED) + operator delete[] (blkp[victim], blksize[victim]); +#else + delete[] blkp[victim] ; +#endif +#else + CUSTOM_FREE(blkp[victim]) ; +#endif + + if (max_size == min_size) { + blk_size = min_size; + } else { + blk_size = min_size+lran2(&rgen)%(max_size - min_size) ; + } +#ifdef CPP + blkp[victim] = new char[blk_size] ; +#else + blkp[victim] = (char *) CUSTOM_MALLOC(blk_size) ; +#endif + blksize[victim] = blk_size ; + assert(blkp[victim] != NULL) ; + } +} +#endif // _MT + +#ifdef __WIN32__ +ULONG CountReservedSpace() +{ + MEMORY_BASIC_INFORMATION info; + char *addr=NULL ; + ULONG size=0 ; + + while( true){ + VirtualQuery(addr, &info, sizeof(info)); + switch( info.State){ + case MEM_FREE: + case MEM_RESERVE: + break ; + case MEM_COMMIT: + size += info.RegionSize ; + break ; + } + addr += info.RegionSize ; + if( addr >= (char *)0x80000000UL ) break ; + } + + return size ; + +} +#endif + +// ======================================================= + +/* lran2.h + * by Wolfram Gloger 1996. + * + * A small, portable pseudo-random number generator. + */ + +#ifndef _LRAN2_H +#define _LRAN2_H + +#define LRAN2_MAX 714025l /* constants for portable */ +#define IA 1366l /* random number generator */ +#define IC 150889l /* (see e.g. `Numerical Recipes') */ + +//struct lran2_st { +// long x, y, v[97]; +//}; + +static void +lran2_init(struct lran2_st* d, long seed) +{ + long x; + int j; + + x = (IC - seed) % LRAN2_MAX; + if(x < 0) x = -x; + for(j=0; j<97; j++) { + x = (IA*x + IC) % LRAN2_MAX; + d->v[j] = x; + } + d->x = (IA*x + IC) % LRAN2_MAX; + d->y = d->x; +} + +static +long lran2(struct lran2_st* d) +{ + int j = (d->y % 97); + + d->y = d->v[j]; + d->x = (IA*d->x + IC) % LRAN2_MAX; + d->v[j] = d->x; + return d->y; +} + +#undef IA +#undef IC + +#endif diff --git a/benchmarks/benchmarks/larison/stddefines.h b/benchmarks/benchmarks/larison/stddefines.h new file mode 100644 index 0000000..347fc5f --- /dev/null +++ b/benchmarks/benchmarks/larison/stddefines.h @@ -0,0 +1,340 @@ +/* Copyright (c) 2007-2009, Stanford University +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of Stanford University nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY STANFORD UNIVERSITY ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL STANFORD UNIVERSITY BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef STDDEFINES_H_ +#define STDDEFINES_H_ + +#include +#include +#include +#include +#include +#include +#include + + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +// #include "bitmap.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define MAXPAGESIZES 2 + + +// init_malloc(void) { +// // Init malloc implementation +// INITREGULARALLOC(); + +// // init_alloc(100,100000); +// // brm_init(); +// //alloc_init(104857632); +// } + +// void* MALLOC(size_t sz) { +// // malloc implementation +// return MALLOCCHERI(sz); +// // return malloc_buddy(sz); +// // return alloc(sz); +// // return (void *)alloc_chunk(); +// } + +// void FREE(void *ptr) { +// // free implementation +// FREECHERI(ptr); +// // free_chunk(ptr); +// //free_mem(ptr); +// } + +// Function declarations +void *my_malloc(size_t sz); +void my_free(void *ptr); +static int pagesizes(size_t ps[MAXPAGESIZES]); + +void INITREGULARALLOC(void); +void init_alloc(int num_chunks, int chunk_size); +char *alloc_chunk(void); +void free_chunk(void *chunk); +int num_used_chunks(void); + + +//#define TIMING + +/* Debug printf */ +#define dprintf(...) fprintf(stdout, __VA_ARGS__) + +/* Wrapper to check for errors */ +#define CHECK_ERROR(a) \ + if (a) \ + { \ + perror("Error at line\n\t" #a "\nSystem Msg"); \ + assert ((a) == 0); \ + } + +// static inline void *MALLOC(size_t size) +// { +// void * temp = malloc(size); +// assert(temp); +// return temp; +// } + +static inline void *CALLOC(size_t num, size_t size) +{ + void * temp = calloc(num, size); + assert(temp); + return temp; +} + +static inline void *REALLOC(void *ptr, size_t size) +{ + void * temp = realloc(ptr, size); + assert(temp); + return temp; +} + +static inline char *GETENV(char *envstr) +{ + char *env = getenv(envstr); + if (!env) return "0"; + else return env; +} + +#define GET_TIME(start, end, duration) \ + duration.tv_sec = (end.tv_sec - start.tv_sec); \ + if (end.tv_nsec >= start.tv_nsec) { \ + duration.tv_nsec = (end.tv_nsec - start.tv_nsec); \ + } \ + else { \ + duration.tv_nsec = (1000000000L - (start.tv_nsec - end.tv_nsec)); \ + duration.tv_sec--; \ + } \ + if (duration.tv_nsec >= 1000000000L) { \ + duration.tv_sec++; \ + duration.tv_nsec -= 1000000000L; \ + } + +static inline unsigned int time_diff ( + struct timeval *end, struct timeval *begin) +{ +#ifdef TIMING + uint64_t result; + + result = end->tv_sec - begin->tv_sec; + result *= 1000000; /* usec */ + result += end->tv_usec - begin->tv_usec; + + return result; +#else + return 0; +#endif +} + +static inline void get_time (struct timeval *t) +{ +#ifdef TIMING + gettimeofday (t, NULL); +#endif +} + +// Expirement work + +#define FILENAME "/dev/contigmem" + +static char *heap_start; +static char *heap; +static size_t HEAP_SIZE = 1024 * 1024 * 1024; + +char *ptr; +int MallocCounter; + +size_t sizeUsed; + +// INITAlloc(void) { + +// size_t sz; +// // Pre Allocate 600 MB +// sz = 100000000; + +// int fd = open(FILENAME, O_RDWR, 0600); + +// if (fd < 0) { +// perror("open"); +// exit(EXIT_FAILURE); +// } + +// off_t offset = 0; // offset to seek to. + +// if (ftruncate(fd, sz) < 0) { +// perror("ftruncate"); +// close(fd); +// exit(EXIT_FAILURE); +// } + +// // ptr = mmap(NULL, sz, +// // PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON,-1,0); + +// ptr = mmap(NULL, sz, +// PROT_READ|PROT_WRITE, MAP_SHARED,fd,0); + +// // Added error handling +// if(ptr == MAP_FAILED) +// { +// perror("mmap"); +// exit(EXIT_FAILURE); +// } + +// MallocCounter = (int)sz; + +// } + +// Quick malloc implementation with mmap +void* my_malloc(size_t sz) +{ + sz = __builtin_align_up(sz, _Alignof(max_align_t)); + + // printf("%d \n", sz); + // printf("%d Malloc counter\n", MallocCounter); + + MallocCounter -= sz; + char *ptrLink = &ptr[MallocCounter]; + ptrLink = cheri_setbounds(ptrLink, sz); + + return (void *)ptrLink; + +// if (heap + sz > heap_start + HEAP_SIZE) return NULL; +// heap += sz; +// return heap - sz; + +} + +// Quick cheri free implementation +void my_free(void *ptr) { + + // printf("free called \n"); + + // get bounds from + int len = cheri_getlen(ptr); + + // printf("free len %d \n", len); + + munmap(ptr, len); +} + +static int +pagesizes(size_t ps[MAXPAGESIZES]) +{ + int pscnt; + + pscnt = getpagesizes(ps, MAXPAGESIZES); + // ATF_REQUIRE_MSG(pscnt != -1, "getpagesizes failed; errno=%d", errno); + // ATF_REQUIRE_MSG(ps[0] != 0, "psind 0 is %zu", ps[0]); + // ATF_REQUIRE_MSG(pscnt <= MAXPAGESIZES, "invalid pscnt %d", pscnt); + // if (pscnt == 1){ + // printf("pscnt is 1"); + // } + + // atf_tc_skip("no large page support"); + return (pscnt); +} + +void INITREGULARALLOC(void) { + size_t sz; + // Pre Allocate 400 MB + sz = 1073741824; + + int error, fd, pscnt, pn; + + size_t ps[MAXPAGESIZES]; + + size_t size[3]; + + pn = getpagesizes(size, 3); + printf("page size is [%d]", size[2]); + + pscnt = pagesizes(ps); + + fd = shm_create_largepage(SHM_ANON, O_CREAT | O_RDWR, 1, SHM_LARGEPAGE_ALLOC_DEFAULT, 0); + + if (fd < 0 && errno == ENOTTY) { + perror("sh_create_largepages"); + close(fd); + exit(EXIT_FAILURE); + } + // if (fd < 0) + // perror("no large page supported"); + // exit(EXIT_FAILURE); + // if (fd < 0 && errno == ENOTTY) + // atf_tc_skip("no large page support"); + // ATF_REQUIRE_MSG(fd >= 0, "shm_create_largepage failed; errno=%d", errno); + + if (ftruncate(fd, sz) < 0) { + perror("ftruncate"); + close(fd); + exit(EXIT_FAILURE); + } + // if (error != 0 && errno == ENOMEM) + // /* + // * The test system might not have enough memory to accommodate + // * the request. + // */ + // atf_tc_skip("failed to allocate %zu-byte superpage", sz); + // ATF_REQUIRE_MSG(error == 0, "ftruncate failed; errno=%d", errno); + + ptr = (char *)mmap(NULL, sz, + PROT_READ|PROT_WRITE, MAP_SHARED,fd,0); + + // Added error handling + if(ptr == MAP_FAILED) + { + perror("mmap"); + exit(EXIT_FAILURE); + } + + MallocCounter = (int)sz; +} + + +// ------------------------------ bitmap allocator ---------------------------- + + + +#ifdef __cplusplus +} +#endif + +#endif // STDDEFINES_H_ diff --git a/benchmarks/benchmarks/queens/Makefile b/benchmarks/benchmarks/queens/Makefile index 560ca38..704e9bf 100644 --- a/benchmarks/benchmarks/queens/Makefile +++ b/benchmarks/benchmarks/queens/Makefile @@ -1,6 +1,6 @@ CC = cc BINARY = ./nqueens -CFLAGS += -Wall -mabi=purecap-benchmark +CFLAGS += -Wall -g -mabi=purecap-benchmark all: clean compile clear run @@ -15,8 +15,8 @@ clear: clear compile: nqueens.o - $(CC) $(CFLAGS) -pg -o $(BINARY) nqueens.o + $(CC) $(CFLAGS) -o $(BINARY) nqueens.o nqueens.o: # Ultra fast compilation - $(CC) -c -pg -O3 ./nqueens.c + $(CC) $(CFLAGS) -c -O3 ./nqueens.c diff --git a/benchmarks/benchmarks/queens/nqueens.c b/benchmarks/benchmarks/queens/nqueens.c index 1c1c521..d2f8564 100644 --- a/benchmarks/benchmarks/queens/nqueens.c +++ b/benchmarks/benchmarks/queens/nqueens.c @@ -1,11 +1,15 @@ #include #include #include +#include "stddefines.h" #define bool char #define TRUE 1 #define FALSE 0 +#define malloc my_malloc +#define free my_free + typedef struct board { int n; int** matrix; @@ -149,6 +153,7 @@ void queens(int n) { } int main(int argc, char const *argv[]) { + INITREGULARALLOC(); system("clear"); int i; int n = 0; diff --git a/benchmarks/benchmarks/queens/stddefines.h b/benchmarks/benchmarks/queens/stddefines.h new file mode 100644 index 0000000..9666aeb --- /dev/null +++ b/benchmarks/benchmarks/queens/stddefines.h @@ -0,0 +1,481 @@ +/* Copyright (c) 2007-2009, Stanford University +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of Stanford University nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY STANFORD UNIVERSITY ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL STANFORD UNIVERSITY BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef STDDEFINES_H_ +#define STDDEFINES_H_ + +#include +#include +#include +#include +#include +#include +#include + + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +// #include "bitmap.h" + +#define MAXPAGESIZES 2 + + +// init_malloc(void) { +// // Init malloc implementation +// INITREGULARALLOC(); + +// // init_alloc(100,100000); +// // brm_init(); +// //alloc_init(104857632); +// } + +// void* MALLOC(size_t sz) { +// // malloc implementation +// return MALLOCCHERI(sz); +// // return malloc_buddy(sz); +// // return alloc(sz); +// // return (void *)alloc_chunk(); +// } + +// void FREE(void *ptr) { +// // free implementation +// FREECHERI(ptr); +// // free_chunk(ptr); +// //free_mem(ptr); +// } + + +//#define TIMING + +/* Debug printf */ +#define dprintf(...) fprintf(stdout, __VA_ARGS__) + +/* Wrapper to check for errors */ +#define CHECK_ERROR(a) \ + if (a) \ + { \ + perror("Error at line\n\t" #a "\nSystem Msg"); \ + assert ((a) == 0); \ + } + +// static inline void *MALLOC(size_t size) +// { +// void * temp = malloc(size); +// assert(temp); +// return temp; +// } + +static inline void *CALLOC(size_t num, size_t size) +{ + void * temp = calloc(num, size); + assert(temp); + return temp; +} + +static inline void *REALLOC(void *ptr, size_t size) +{ + void * temp = realloc(ptr, size); + assert(temp); + return temp; +} + +static inline char *GETENV(char *envstr) +{ + char *env = getenv(envstr); + if (!env) return "0"; + else return env; +} + +#define GET_TIME(start, end, duration) \ + duration.tv_sec = (end.tv_sec - start.tv_sec); \ + if (end.tv_nsec >= start.tv_nsec) { \ + duration.tv_nsec = (end.tv_nsec - start.tv_nsec); \ + } \ + else { \ + duration.tv_nsec = (1000000000L - (start.tv_nsec - end.tv_nsec)); \ + duration.tv_sec--; \ + } \ + if (duration.tv_nsec >= 1000000000L) { \ + duration.tv_sec++; \ + duration.tv_nsec -= 1000000000L; \ + } + +static inline unsigned int time_diff ( + struct timeval *end, struct timeval *begin) +{ +#ifdef TIMING + uint64_t result; + + result = end->tv_sec - begin->tv_sec; + result *= 1000000; /* usec */ + result += end->tv_usec - begin->tv_usec; + + return result; +#else + return 0; +#endif +} + +static inline void get_time (struct timeval *t) +{ +#ifdef TIMING + gettimeofday (t, NULL); +#endif +} + +// Expirement work + +#define FILENAME "/dev/contigmem" + +static char *heap_start; +static char *heap; +static size_t HEAP_SIZE = 1024 * 1024 * 1024; + +void *ptr; +int MallocCounter; + +size_t sizeUsed; + +// INITAlloc(void) { + +// size_t sz; +// // Pre Allocate 600 MB +// sz = 100000000; + +// int fd = open(FILENAME, O_RDWR, 0600); + +// if (fd < 0) { +// perror("open"); +// exit(EXIT_FAILURE); +// } + +// off_t offset = 0; // offset to seek to. + +// if (ftruncate(fd, sz) < 0) { +// perror("ftruncate"); +// close(fd); +// exit(EXIT_FAILURE); +// } + +// // ptr = mmap(NULL, sz, +// // PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON,-1,0); + +// ptr = mmap(NULL, sz, +// PROT_READ|PROT_WRITE, MAP_SHARED,fd,0); + +// // Added error handling +// if(ptr == MAP_FAILED) +// { +// perror("mmap"); +// exit(EXIT_FAILURE); +// } + +// MallocCounter = (int)sz; + +// } + +// Quick malloc implementation with mmap +void* my_malloc(size_t sz) +{ + sz = __builtin_align_up(sz, _Alignof(max_align_t)); + + // printf("%d \n", sz); + // printf("%d Malloc counter\n", MallocCounter); + + MallocCounter -= sz; + void *ptrLink = &ptr[MallocCounter]; + ptrLink = cheri_setbounds(ptrLink, sz); + + return ptrLink; + +// if (heap + sz > heap_start + HEAP_SIZE) return NULL; +// heap += sz; +// return heap - sz; + +} + +// Quick cheri free implementation +void my_free(void *ptr) { + + // printf("free called \n"); + + // get bounds from + int len = cheri_getlen(ptr); + + // printf("free len %d \n", len); + + munmap(ptr, len); +} + +static int +pagesizes(size_t ps[MAXPAGESIZES]) +{ + int pscnt; + + pscnt = getpagesizes(ps, MAXPAGESIZES); + // ATF_REQUIRE_MSG(pscnt != -1, "getpagesizes failed; errno=%d", errno); + // ATF_REQUIRE_MSG(ps[0] != 0, "psind 0 is %zu", ps[0]); + // ATF_REQUIRE_MSG(pscnt <= MAXPAGESIZES, "invalid pscnt %d", pscnt); + // if (pscnt == 1){ + // printf("pscnt is 1"); + // } + + // atf_tc_skip("no large page support"); + return (pscnt); +} + +INITREGULARALLOC(void) { + size_t sz; + // Pre Allocate 400 MB + sz = 1073741824; + + int error, fd, pscnt, pn; + + size_t ps[MAXPAGESIZES]; + + size_t size[3]; + + pn = getpagesizes(size, 3); + printf("page size is [%d]", size[2]); + + pscnt = pagesizes(ps); + + fd = shm_create_largepage(SHM_ANON, O_CREAT | O_RDWR, 1, SHM_LARGEPAGE_ALLOC_DEFAULT, 0); + + if (fd < 0 && errno == ENOTTY) { + perror("sh_create_largepages"); + close(fd); + exit(EXIT_FAILURE); + } + // if (fd < 0) + // perror("no large page supported"); + // exit(EXIT_FAILURE); + // if (fd < 0 && errno == ENOTTY) + // atf_tc_skip("no large page support"); + // ATF_REQUIRE_MSG(fd >= 0, "shm_create_largepage failed; errno=%d", errno); + + if (ftruncate(fd, sz) < 0) { + perror("ftruncate"); + close(fd); + exit(EXIT_FAILURE); + } + // if (error != 0 && errno == ENOMEM) + // /* + // * The test system might not have enough memory to accommodate + // * the request. + // */ + // atf_tc_skip("failed to allocate %zu-byte superpage", sz); + // ATF_REQUIRE_MSG(error == 0, "ftruncate failed; errno=%d", errno); + + ptr = mmap(NULL, sz, + PROT_READ|PROT_WRITE, MAP_SHARED,fd,0); + + // Added error handling + if(ptr == MAP_FAILED) + { + perror("mmap"); + exit(EXIT_FAILURE); + } + + MallocCounter = (int)sz; +} + + +// ------------------------------ bitmap allocator ---------------------------- + +#define BITS_PER_BYTE 8 + +char *buffer = NULL; /* allocation buffer */ +unsigned char *bitmap = NULL; /* bitmap for the buffer */ + +int buffer_size = 0; /* size of buffer (in bytes) */ +int bitmap_size = 0; /* size of bitmap (in bytes) */ +int bytes_per_chunk = 0; /* size of single chunk (in bytes) */ + +void init_alloc(int num_chunks, int chunk_size) +{ + int i = 0; + + /* we need to increase the num_chunks + * so every bit in bitmap will be used + */ + int adjusted_num_chunks = (num_chunks % BITS_PER_BYTE == 0) + ? num_chunks + : (num_chunks + (BITS_PER_BYTE - (num_chunks % BITS_PER_BYTE))); + + /* we need to increase the chunk_size + * so chunks will be CHERI aligned + * (i.e. 16 bytes for RISC-V 64-bit arch) + */ + int adjusted_chunk_size = + (chunk_size % (sizeof(void *)) == 0) + ? chunk_size + : (chunk_size + (sizeof(void *)) - (chunk_size % (sizeof(void *)))); + + /* check this chunk size is small enough so we can represent + * bounds precisely with CHERI compressed representation + */ + adjusted_chunk_size = cheri_representable_length(adjusted_chunk_size); + + /* request memory for our allocation buffer */ + char *res = mmap(NULL, adjusted_num_chunks * adjusted_chunk_size, PROT_READ | PROT_WRITE, + MAP_ANON | MAP_PRIVATE, -1, 0); + /* request memory for our bitmap */ + bitmap = (void *) mmap(NULL, adjusted_num_chunks / BITS_PER_BYTE, + PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); + + if (res == MAP_FAILED || bitmap == MAP_FAILED) + { + perror("error in initial mem allocation"); + exit(-1); + } + + /* NB mmap min bounds for capability is 1 page (4K) */ + buffer = res; + /* check buffer is aligned */ + assert((uintptr_t) buffer % sizeof(void *) == 0); + /* check bitmap is aligned */ + assert((uintptr_t) bitmap % sizeof(void *) == 0); + + bytes_per_chunk = adjusted_chunk_size; + buffer_size = adjusted_num_chunks * adjusted_chunk_size; + bitmap_size = adjusted_num_chunks / BITS_PER_BYTE; + + /* zero bitmap, since all chunks are free initially */ + for (i = 0; i < bitmap_size; i++) + { + bitmap[i] = 0; + } + + // set exact bounds for buffer and bitmap? + buffer = cheri_setbounds(buffer, buffer_size); + bitmap = cheri_setbounds(bitmap, bitmap_size); + return; +} + +/* + * allocate fixed size chunk with bitmap allocator + * this is our simplistic `malloc` function + */ +char *alloc_chunk() +{ + unsigned char updated_byte = 0; + int chunk_index = 0; + char *chunk = NULL; + // iterate over all bits in bitmap, looking for a 0 + // when we find a 0, set it to 1 and + // return the corresponding chunk + // (setting its capability bounds) + int i = 0; + while (bitmap[i] == (unsigned char) 0xff) + { + i++; + if (i >= bitmap_size) + break; + } + // do we have a 0? + if (i < bitmap_size && bitmap[i] != (unsigned char) 0xff) + { + // find the lowest 0 ... + int j = 0; + // right shift until bottom bit is 0 + for (j = 0; j < BITS_PER_BYTE; j++) + { + int bit = (bitmap[i] >> j) & 1; + if (bit == 0) + { + break; + } + } + // now i is the word index, j is the bit index + // set this bit to 1 ... + // and work out the chunk to allocate + updated_byte = bitmap[i] + (unsigned char) (1 << j); + bitmap[i] = updated_byte; + + chunk_index = i * BITS_PER_BYTE + j; + chunk = buffer + (chunk_index * bytes_per_chunk); + + /* restrict capability range before returning ptr */ + chunk = cheri_setbounds(chunk, bytes_per_chunk); + } + + return chunk; +} + +void free_chunk(void *chunk) +{ + vaddr_t base = cheri_getbase(chunk); + vaddr_t buff_base = cheri_getbase(buffer); + /* calculate chunk index in buffer */ + int chunk_index = (base - buff_base) / bytes_per_chunk; + assert(chunk_index >= 0); + /* calculate corresponding bitmap index */ + int bitmap_index = chunk_index / BITS_PER_BYTE; + assert(bitmap_index < bitmap_size); + int bitmap_offset = chunk_index % BITS_PER_BYTE; + /* set this bitmap entry to 0 */ + unsigned char updated_byte = bitmap[bitmap_index] & (unsigned char) (~(1 << bitmap_offset)); + bitmap[bitmap_index] = updated_byte; + return; +} + +int num_used_chunks() +{ + int i = 0; + int used_chunks = 0; + + while (i < bitmap_size) + { + unsigned char x = bitmap[i]; + if (x != 0) + { + /* some used chunks here */ + unsigned char j; + for (j = 1; j <= x; j = j << 1) + { + if (x & j) + { + used_chunks++; + } + } + } + i++; + } + return used_chunks; +} + +#endif // STDDEFINES_H_ diff --git a/docs/tasks/tasks.org b/docs/tasks/tasks.org index fae9f32..bd59b4c 100644 --- a/docs/tasks/tasks.org +++ b/docs/tasks/tasks.org @@ -1,5 +1,14 @@ * Tasks - [ ] Run 2 macro benchmarks + - [ ] Nqueens + - [x] Executes on the regular allocator + on the Morello. + - [x] Executes on the Huge page aware + allocator. + - [ ] Log results. + - [ ] Larison + - [x] Execute on the regular allocator + - [x] Execute on the Morello - [ ] Log results and draw graphs - [ ] Show in meeting notes