24 #include <sys/signal.h>
30 #include <sys/types.h>
32 #include <sys/ioctl.h>
33 #include <mm_malloc.h>
34 #include <sys/statvfs.h>
37 #ifndef OpenMP_NOT_FOUND
50 oneFile = min ( 4 *
gig, myg );
51 oneFile = max (
mib, oneFile );
56 if ( size % oneFile != 0 ) {
68 this->filemask = (
char * ) malloc (
sizeof (
char ) * ( strlen ( filemask ) + 1 ) );
69 strcpy ( (
char * ) this->filemask, filemask );
91 int ioSetupErr = io_setup ( aio_max_transactions, &
aio_context );
92 if ( 0 != ioSetupErr ) {
98 #ifndef OpenMP_NOT_FOUND
131 snprintf ( fname, 1024,
filemask, getpid(), n );
150 std::map<global_offset, pageFileLocation *>::iterator it =
all_space.begin();
173 for (
unsigned int n = start; n < stop; ++n ) {
175 snprintf ( fname, 1024,
filemask, getpid(), n );
176 swapFiles[n].
fileno = open ( fname, O_RDWR | O_TRUNC | O_CREAT | (
enableDMA ? O_DIRECT : 0 << 0 ), S_IRUSR | S_IWUSR );
178 if ( errno == EINVAL && n == 0 &&
enableDMA ) {
179 warnmsg (
"Could not open first swapfile. Probably DMA is not supported on underlying filesystem. Trying again without dma" )
183 errmsgf (
"Encountered error code %d when opening file %s\n", errno, fname );
220 if ( freeondisk < needed ) {
224 warnmsgf (
"Extending possible swap space by %lu MB ( %lu MB left on hdd)\n",
pageFileSize /
mib, freeondisk /
mib );
229 while ( ( extendby < needed || extendby > freeondisk ) ) {
231 warnmsgf (
"I am out of swap.\n\tI can increase in steps of ~%luMB\n\tWe need at least %lu steps, possible steps until disk is full: %lu \n\t please type in an integer number and press enter",
pageFileSize /
mib, needed /
pageFileSize, freeondisk /
pageFileSize );
233 std::cin >> extendby;
234 if ( !std::cin.fail() ) {
237 errmsg (
"I don't feel like this being an integer." );
239 std::cin.ignore ( std::numeric_limits<streamsize>::max(),
'\n' );
245 if ( extendby > freeondisk ) {
246 errmsg (
"You want to assign more disk space than you have." );
248 if ( extendby < needed ) {
249 errmsg (
"You want to assign less than we need." );
292 std::size_t found = directory.find_last_of (
"/" );
293 if ( found == directory.npos ) {
296 directory = directory.substr ( 0, found );
298 struct statvfs stats;
299 statvfs ( directory.c_str(), &stats );
315 std::map<global_offset, pageFileLocation *>::iterator it;
321 printf (
"Tuuuuut!\n" );
323 if ( it->second->size >= size ) {
342 total_space += it->second->size;
343 }
while ( total_space < size && ++it !=
free_space.end() );
344 if ( total_space < size ) {
353 if ( total_space >= size ) {
358 if ( size > alloc_here ) {
407 if ( padded_size != size ) {
408 if ( padded_size > freeChunk->
size ) {
417 freeChunk->
size = size;
421 freeChunk->
offset += padded_size;
422 freeChunk->
size -= padded_size;
437 bool endIsReached =
false;
460 if ( ( --it )->second->status ==
PAGE_FREE ) {
474 if ( pagePtr->
size != size ) {
476 pagePtr->
size = size;
481 if ( it !=
all_space.end() && it->second->offset != 0 && it->second->status ==
PAGE_FREE ) {
484 pagePtr->
size += it->second->size;
497 }
while ( !endIsReached );
519 printf (
"swapping in chunk %lu\n", chunk->
id );
542 for (
unsigned int n = 0; n < nchunks; ++n ) {
543 n_swapped +=
swapIn ( chunklist[n] ) ;
551 printf (
"swapping out chunk %lu\n", chunk->
id );
563 printf (
"chunks is cached, we have no need to schedule: %lu\n", chunk->
id );
566 _mm_free ( chunk->
locPtr );
576 printf (
"chunks will be scheduled: %lu\n", chunk->
id );
597 for (
unsigned int n = 0; n < nchunks; ++n ) {
598 n_swapped +=
swapOut ( chunklist[n] );
624 neededSize = neededSize % ( resizeStep ) == 0 ? neededSize : resizeStep * ( neededSize / resizeStep + 1 );
628 errmsgf (
"Could not resize swap file with error code %d", errcode );
643 reverse ? printf (
"scheduling read\n" ) : printf (
"scheduling write\n" );
648 reverse ? io_prep_pread ( aio, fd, ramBuf, length, ref.
offset ) : io_prep_pwrite ( aio, fd, ramBuf, length, ref.
offset );
670 int retcode = -EAGAIN;
671 while ( 1 != ( retcode = io_submit ( dhis->
aio_context, 1, &aio ) ) ) {
672 if ( retcode != -EAGAIN ) {
711 printf (
"got a call\n" );
718 printf (
"Working on chunk %lu\n", chunk->
id );
720 switch ( chunk->
status ) {
723 printf (
"Accounting for a swapin of chunk %lu\n", chunk->
id );
741 printf (
"Accounting for a swapout\n" );
746 _mm_free ( chunk->
locPtr );
788 struct timespec timeout = {0, 100000};
789 if ( no_arrived == 0 ) {
795 if ( no_arrived < 0 ) {
796 if ( no_arrived == -EINTR ) {
800 printf (
"We got an error back: %d\n", -no_arrived );
805 printf (
"we got %d events\n", no_arrived );
807 for (
int n = 0; n < no_arrived; ++n ) {
810 printf (
"Processing event %d \n", n );
832 printf (
"aio: async io arrived, chunk of size %lu\n", ref->
size );
840 int err =
event->res2;
846 int lastval = ( *tracker )--;
847 if ( lastval == 1 ) {
856 errmsgf (
"We have trouble in chunk %lu, %d ; aio_size %lu, size %lu, transfer size %lu", ref->
glob_off_next.
chunk->
id, err, event->res, ref->
size, event->obj->u.c.nbytes );
857 errmsgf (
"file-align %lu, err %d, sizeWritten = %lu", ref->
offset %
memoryAlignment, err, event->res );
868 char *cramBuf = (
char * ) ramBuf;
870 int *tracker =
new int ( 1 );
873 scheduleCopy ( *cur, (
void * ) ( cramBuf + offset ), tracker, reverse );
880 unsigned int trval = ( *tracker )--;
899 free_space += it->second->size;
904 switch ( it->second->status ) {
906 partend += it->second->size;
909 free_space2 += it->second->size;
912 fractured += it->second->size;
919 printf (
"%ld\t%ld\t%ld\t%e\t%e\t%s\n", free_space, partend, fractured, ( (
double ) free_space ) / ( partend + fractured + free_space ), ( ( (
double ) ( total_space ) - ( partend + fractured + free_space ) ) / ( total_space ) ), ( free_space ==
instance->
swapFree ?
"sane" :
"insane" ) );
934 cleanedUp += chunk->
size;
941 if ( cleanedUp > minimum_size ) {
Exception for errors with the memory.
void scheduleCopy(rambrain::pageFileLocation &ref, void *ramBuf, int *tracker, bool reverse=false)
Schedules an elementary pageFileLocation chunk for copying (in or out)
void completeTransactionOn(rambrain::pageFileLocation *ref, bool lock=true)
called to finish a transaction when all pending aio on a managedMemoryChunk has completed ...
memoryID id
an ID to identify the object in scheduler or elsewhere
static void signalSwappingCond()
signals that a swapping action has completed and memory limits have changed
void * locPtr
pointer to the actual data in RAM
virtual void invalidateCacheFor(managedMemoryChunk &chunk)
tells managedFileSwap that the chunk under consideration might have been changed by user and needs to...
bool cleanupCachedElements(rambrain::global_bytesize minimum_size=0)
throws out cached elements still in ram but also resident on disk. This makes space in situations of ...
void * swapBuf
a place to store additional swapping information
static pthread_cond_t swappingCond
std::unordered_map< struct iocb *, pageFileLocation * > pendingAios
Class that serves as a backend to managedMemory to actual write/read managedMemoryChunks to/from hard...
unsigned int aio_max_transactions
bool openSwapFileRange(unsigned int start, unsigned int stop)
opens certain range of swap files according to settings
managedMemoryChunk * chunk
pthread_mutex_t io_submit_lock
static managedMemory * defaultManager
virtual bool extendSwap(global_bytesize size)
extend swap by size number of bytes
void claimUsageof(global_bytesize bytes, bool rambytes, bool used)
account for memory usage change
An implementation of managedSwap that is capable of kernel asynchronousIO.
void claimTobefreed(global_bytesize bytes, bool tobefreed)
account for future availability of bytes
unsigned int totalSwapActionsQueued
pthread_cond_t io_submit_cond
pageFileLocation * allocInFree(pageFileLocation *freeChunk, global_bytesize size)
Helper function for pfmalloc.
virtual void close()
Close the swap if not already closed.
pthread_t io_arrive_thread
pageFileLocation determinePFLoc(global_offset g_offset, global_bytesize length) const
generate a pageFileLocation object given a global offset and a length of the data. This maps our "virtual" adress space to physical locations in a certain file
void asyncIoArrived(rambrain::pageFileLocation *ref, struct io_event *aio)
deals with a single asynchronous IO event completion
pthread_mutex_t aioWaiterLock
struct aiotracker * aio_ptr
void copyMem(rambrain::pageFileLocation &ref, void *ramBuf, bool reverse=false)
Schedules copying on level of whole managedMemoryChunks and calls scheduleCopy on the assigned parts...
virtual ~managedFileSwap()
void closeSwapFiles()
closes swap files
bool openSwapFiles()
opens swap files according to settings
pageFileLocation * pfmalloc(rambrain::global_bytesize size, rambrain::managedMemoryChunk *chunk)
Tries to find space in the swapFiles to write out an object of size size and returns first pageFileLo...
global_bytesize currentSize
const global_bytesize gig
static pthread_mutex_t stateChangeMutex
std::queue< struct iocb * > io_submit_requests
pthread_t * io_submit_threads
pageFileLocation * glob_off_next
union glob_off_union glob_off_next
manages all managed Chunks of raw memory
unsigned int pageFileNumber
tracks page file allocations while objects are preferably written continuous to page file...
std::map< memoryID, managedMemoryChunk * > memChunks
global_offset determineGlobalOffset(const pageFileLocation &ref) const
maps from physical location to "virtual" adress
virtual global_bytesize swapOut(managedMemoryChunk **chunklist, unsigned int nchunks)
Trigger swap out of the chunks pointed to by chunklist.
struct swapFileDesc * swapFiles
struct io_event * aio_eventarr
void my_io_submit(struct iocb *aio)
static void sigStat(int signum)
returns some statistics. Typically, we will be sensitive to SIGUSR2 if compiled with -DSWAPSTATS=on ...
managedFileSwap(global_bytesize size, const char *filemask, global_bytesize oneFile=0, bool enableDMA=false)
global_bytesize swap_in_bytes
virtual bool checkForAIO()
gives this class the chance to treat incoming aio events
global_bytesize getFreeDiskSpace()
returns free disk space at file system location specified by filemask
static managedFileSwap * instance
structure to handle swap files
std::map< global_offset, pageFileLocation * > free_space
virtual bool extendSwapByPolicy(global_bytesize min_size)
extend swap by policy
global_bytesize size
Size of actual object in bytes.
virtual void swapDelete(managedMemoryChunk *chunk)
Mark chunk as deleted.
unsigned short useCnt
Number of using adhereTos or a possible location for locking the object to changes.
static void * io_submit_worker(void *ptr)
unsigned int io_submit_num_threads
static void * io_arrrive_worker(void *ptr)
global_bytesize swap_out_bytes
datastructure for handling asynchronous events
void pffree(pageFileLocation *pagePtr)
global_bytesize pageFileSize
std::map< global_offset, pageFileLocation * > all_space
const global_bytesize mib
virtual global_bytesize swapIn(managedMemoryChunk **chunklist, unsigned int nchunks)
Trigger swap in of the chunks pointed to by chunklist.