40 #define VERBOSEPRINT(x) printf("\n<--%s\n",x); if (memChunks.size()>=min_elements) printCycle();printf("\n%s---->\n",x);
42 #define VERBOSEPRINT(x) ;
65 VERBOSEPRINT (
"registerbegin" );
68 MUTUAL_CONNECT ( before, neu );
69 MUTUAL_CONNECT ( neu, after );
99 if ( element->
next == element ) {
108 if ( element->
next == element->
prev ) {
110 remaining->
next = remaining->
prev = remaining;
115 if (
active == element ) {
131 BACKLOG_ADD_ID (
TOUCH, chunk.
id )
152 if (
active == element ) {
172 MUTUAL_CONNECT ( before, element );
173 MUTUAL_CONNECT ( element,
active );
174 MUTUAL_CONNECT (
active, after );
185 MUTUAL_CONNECT ( oldplace_before, oldplace_after );
186 MUTUAL_CONNECT ( before, element );
187 MUTUAL_CONNECT ( element, after );
214 if ( !separated.
from ) {
219 MUTUAL_CONNECT ( before, separated.
from );
220 MUTUAL_CONNECT ( separated.
to, after );
234 bool cyclic = ( after == toFilter.
from );
236 MUTUAL_CONNECT ( toFilter.
to, ( &end ) );
237 MUTUAL_CONNECT ( ( &end ), toFilter.
from );
241 bool separateThis =
false;
248 if ( preemptiveLoaded ) {
252 if ( separateThis ) {
264 MUTUAL_CONNECT ( sepaStart->
prev, cur );
265 if ( separated.
from == NULL ) {
266 separated.
from = sepaStart;
269 MUTUAL_CONNECT ( separated.
to, sepaStart );
271 separated.
to = newTo;
279 }
while ( cur != &end );
284 MUTUAL_CONNECT ( sepaStart->
prev, cur );
285 if ( separated.
from == NULL ) {
286 separated.
from = sepaStart;
289 MUTUAL_CONNECT ( separated.
to, sepaStart );
291 separated.
to = newTo;
293 toFilter = {firstValid, lastValid};
296 MUTUAL_CONNECT ( before, firstValid );
297 MUTUAL_CONNECT ( lastValid, after );
299 MUTUAL_CONNECT ( lastValid, firstValid );
303 MUTUAL_CONNECT ( before, after );
311 BACKLOG_ADD_SIZE (
DECAY, bytes )
317 bytes = min ( swapleft, bytes );
321 unsigned int chunks = 0;
322 bool consecutive =
true;
323 while ( cur !=
active && bytesselected < bytes ) {
340 while ( cur2 != cur && bytesselected < bytes ) {
342 *cursw = cur2->
chunk;
348 if (
swap->
swapOut ( chunklist, chunks ) != bytesselected ) {
359 if ( !consecutive ) {
364 chain area = {from, cur};
384 VERBOSEPRINT (
"swapInEntry" );
386 if ( chunk.
useCnt == 0 ) {
387 printf (
"Unprotected!!!\n;" );
389 printf (
"Main Subject %lu\n", chunk.
id );
400 decay ( preemptiveReduction );
416 warnmsg (
"Loaded more premptively than suggested!" );
422 printf (
"Preemptive swapin (premptiveBytes = %lu) (targetReadinVol = %lu)\n",
preemptiveBytes, targetReadinVol );
429 printf (
"We do not have space to get fully preemptive, lets try swap something out\n" );
432 targetReadinVol = targetSwapoutVol;
436 printf (
"We could not swap out enough, lets retry with the object only (which is the minimum)\n" );
440 if ( alreadyThere ) {
442 VERBOSEPRINT (
"Is Already swapped in by so else" );
445 targetReadinVol = actual_obj_size;
449 VERBOSEPRINT (
"Is Already swapped in by so else" );
455 printf (
"We got enough space right away.\n" );
458 VERBOSEPRINT (
"swapInAfterSwap" );
464 unsigned int numberSelected = 0;
468 printf (
"Starting swapin selection" );
478 printf (
"Chunk %lu has %lu bytes, this is %ld over the top\n", cur->chunk->id, cur->chunk->size, selectedReadinVol + cur->chunk->size +
memory_used -
memory_max );
480 if ( selectedReadinVol + cur->chunk->size + memory_used <= memory_max && cur->chunk->
status ==
MEM_SWAPPED && ( selectedReadinVol == 0 || ( preemtivelySelected + cur->chunk->size <= max_preemptive ) ) ) {
482 cur->chunk->preemptiveLoaded = ( selectedReadinVol > 0 ?
true : false );
486 if ( selectedReadinVol > 0 ) {
487 preemtivelySelected += cur->chunk->size;
489 selectedReadinVol += cur->chunk->size;
490 if ( selectedReadinVol >= targetReadinVol || ( selectedReadinVol > 0 && preemtivelySelected == max_preemptive ) ) {
494 printf (
"swapin %d\n", cur->chunk->id );
498 }
while ( cur != oldBorder );
503 preemtivelySelected = 0;
504 bool activeInList =
false;
510 if ( selectedReadinVol2 + readEl->
chunk->
size + memory_used <= memory_max && readEl->chunk->
status ==
MEM_SWAPPED && ( selectedReadinVol2 == 0 || ( preemtivelySelected + readEl->
chunk->
size <= max_preemptive ) ) ) {
511 chunks[n++] = readEl->
chunk;
513 if ( selectedReadinVol2 > 0 ) {
514 preemtivelySelected += readEl->
chunk->
size;
516 selectedReadinVol2 += readEl->
chunk->
size;
517 if ( selectedReadinVol2 >= targetReadinVol || ( selectedReadinVol2 > 0 && preemtivelySelected == max_preemptive ) ) {
521 readEl = readEl->
prev;
522 }
while ( readEl != oldBorder );
526 if ( ( swappedInBytes != selectedReadinVol ) ) {
528 VERBOSEPRINT (
"exiting with non complete job" );
535 printf (
"endSwapin is at %lu", chunks[numberSelected - 1]->
id );
539 VERBOSEPRINT (
"Before reordering" );
542 if ( readEl == oldBorder ) {
543 readEl = readEl->
next;
551 if ( activeInList ) {
552 if (
active == endSwapin ) {
558 if ( after == readEl ) {
562 chain toFilter = {readEl, endSwapin};
582 if ( toFilter.
from ) {
585 MUTUAL_CONNECT ( filtered.
to, filtered.
from )
598 VERBOSEPRINT (
"swapInBeforeReturn" );
603 printf (
"Non-preemptive swapin\n" );
606 if ( alreadyThere ) {
645 global_bytesize desired_free = total_preemptive_needed + keep_free_for_user;
646 if ( currently_free < desired_free ) {
657 BACKLOG_ADD_SIZE (
CHECK, 0 )
658 #ifdef PARENTAL_CONTROL
659 unsigned int no_reg =
memChunks.size() - 1;
663 unsigned int encountered = 0;
678 errmsg (
"No active element found" );
684 bool inSwapsection =
true;
685 bool memerror =
false;
686 bool hasPreemptives =
false;
692 hasPreemptives =
true;
704 if ( oldcur != cur->
prev ) {
705 errmsgf (
"Mutual connecion failure at chunks %lu and %lu", oldcur->
chunk->
id, cur->
chunk->
id );
709 if ( inActiveOnlySection ) {
711 errmsg (
"Swapped elements in active section!" );
716 errmsg (
"Isolated swapped element block not tracked by counterActive found!" );
720 inSwapsection =
false;
725 inActiveOnlySection =
false;
728 }
while ( cur !=
active );
731 errmsgf (
"Used bytes are not counted correctly, claimed %lu but found %lu",
memory_used, usedBytes );
735 errmsgf (
"To-Be-Freed bytes are not counted correctly, claimed %lu but found %lu",
memory_tobefreed, tobef );
739 errmsgf (
"Swapped bytes are not counted correctly, claimed %lu but found %lu",
swap->
getUsedSwap(), swappedBytes );
744 unsigned int illicit_count = 0;
747 hasPreemptives =
true;
750 if ( illicit_count < 10 ) {
751 errmsgf (
"Chunk %ld is a illicit non-preemptive.", cur->
chunk->
id );
753 if ( illicit_count == 10 ) {
754 errmsg (
"will not report further illicits" );
758 hasPreemptives =
false;
762 if ( !hasPreemptives ) {
763 errmsg (
"We encountered non-preemptive elements in section marked as preemptive" );
766 hasPreemptives =
false;
770 if ( illicit_count < 10 ) {
771 errmsgf (
"Chunk %ld is a illicit preemptive.", cur->
chunk->
id );
773 if ( illicit_count == 10 ) {
774 errmsg (
"will not report further illicits" );
778 hasPreemptives =
true;
782 if ( hasPreemptives ) {
783 errmsg (
"We encountered preemptive elements in section marked as non-preemptive" );
788 if ( hasPreemptives ) {
789 errmsg (
"We have preemptives but no preemptiveStart is assigned" );
797 if ( encountered != no_reg ) {
798 errmsgf (
"Not all elements accessed. %d expected, %d encountered", no_reg, encountered );
818 infomsg (
"No objects." );
872 }
while ( atime !=
active );
882 printf (
"Chain named '%s' is empty\n", name );
886 printf (
"Chain named '%s'", name );
888 printf (
"->%lu\t", cur->
chunk->
id );
889 if ( cur == mchain.
to ) {
900 BACKLOG_ADD_SIZE (
SWAPOUT, min_size )
907 VERBOSEPRINT (
"swapOutEntry" );
913 if ( swap_free < min_size ) {
916 if ( swap_free < min_size ) {
928 global_bytesize mem_swap = mem_swap_min < min_size ? min_size : mem_swap_min;
930 mem_swap = mem_swap > swap_free ? min_size : mem_swap;
936 unsigned int passed = 0, unload = 0;
937 #ifdef PARENTAL_CONTROL
938 unsigned int allelements =
memChunks.size() - 1 ;
940 unsigned int allelements =
memChunks.size();
945 while ( unload_size < mem_swap ) {
948 if ( countPos->
chunk->
size + unload_size <= swap_free ) {
952 printf (
"U(%d)\t", countPos->
chunk->
id );
957 if ( passed == allelements ) {
959 printf (
"emergency, once round!\n" );
964 countPos = countPos->
prev;
966 if ( unload_size == 0 ) {
968 printf (
"no candidates found\n" );
980 bool resetPreemptiveStart =
false;
981 while ( unload_size2 < unload_size && passed != allelements ) {
984 if ( fromPos->
chunk->
size + unload_size2 <= swap_free ) {
986 *unloadElem = fromPos->
chunk;
989 printf (
"swapout %d\n", fromPos->
chunk->
id );
998 resetPreemptiveStart =
true;
1005 fromPos = fromPos->
prev;
1008 delete[] unloadlist;
1009 bool swapSuccess = ( real_unloaded >= mem_swap ) ;
1010 if ( !swapSuccess ) {
1011 if ( real_unloaded == 0 ) {
1014 printf (
"Swap out did not work (%lu vs %lu )\n", min_size, real_unloaded );
1022 fromPos = fromPos->
next;
1025 if ( after == fromPos ) {
1032 if ( !possiblyContaminated.
from ) {
1038 MUTUAL_CONNECT ( filtered.
to, filtered.
from );
1045 after = possiblyContaminated.
to->
next;
1052 printf (
"had to move active for preemptive\n" );
1059 printf (
"had to move active\n" );
1063 if ( resetPreemptiveStart ) {
1072 VERBOSEPRINT (
"swapOutReturn" );
1077 if ( swapSuccess ) {
1079 printf (
"Swap out succeeded (%lu vs %lu )\n", min_size, real_unloaded );
1085 printf (
"Swap out (%lu vs %lu )\n", min_size, real_unloaded );
1087 if ( real_unloaded >= min_size ) {
1108 printf (
"Begin backlog\n" );
1111 switch (
backlog[pos].action ) {
1113 printf (
"SWAPIN\t of chunk %lu\n",
backlog[pos].value.id );
1116 printf (
"SWAPOUT\t of %lu bytes\n",
backlog[pos].value.size );
1119 printf (
"DELETION\t of chunk %lu\n",
backlog[pos].value.id );
1122 printf (
"REGISTER\t of chunk %lu\n",
backlog[pos].value.id );
1125 printf (
"TOUCH\t of chunk %lu\n",
backlog[pos].value.id );
1128 printf (
"DECAY\t of %lu Bytes\n",
backlog[pos].value.size );
1131 printf (
"CHECKED cycle\n" );
1138 printf (
"End backlog\n" );
global_bytesize preemptiveBytes
Exception for errors with the memory.
structure created by scheduler to track access times of memoryChunks
cyclicAtime * next
The chunk.
virtual bool extendSwapByPolicy(global_bytesize min_size)
extend swap by policy
static void printChain(const char *name, const chain mchain)
Swapping action was successful.
memoryID id
an ID to identify the object in scheduler or elsewhere
virtual void schedulerRegister(managedMemoryChunk &chunk)
gives scheduler code the opportunity to register its own datastructures associated with a chunk ...
static bool Throw(memoryException e)
Custom throw function, as we need to prevent throwing exceptions in construtors.
static void insertBefore(cyclicAtime *pos, chain separated)
virtual ~cyclicManagedMemory()
void printMemUsage() const
prints out current memory usage
virtual global_bytesize getUsedSwap() const
Simple getter.
Class that serves as a backend to managedMemory to actual write/read managedMemoryChunks to/from hard...
bool setPreemptiveLoading(bool preemptive)
sets whether scheduler should guess next needed items
global_bytesize swap_out_scheduled_bytes
void * schedBuf
a place to store additional scheduling information
virtual bool swapIn(managedMemoryChunk &chunk)
cyclic implementation of swapIn, see paper
virtual global_bytesize getSwapSize() const
Simple getter.
global_bytesize memory_tobefreed
global_bytesize n_swap_out
virtual void untouch(managedMemoryChunk &chunk)
tries to regulate immediately usable free memory in ram to a level optimal for preemptive loading ...
bool checkCycle()
checks whether the scheduler believes to be sane and prints an error message if not ...
struct cyclicManagedMemory::chain filterChain(chain &toFilter, const memoryStatus *separateStatus, bool *preemptiveLoaded=NULL)
: separates all chunks matching state in list separateStatus or preeemptiveLoaded from the ring ...
static pthread_mutex_t cyclicTopoLock
virtual global_bytesize swapIn(managedMemoryChunk **chunklist, unsigned int nchunks)=0
Trigger swap in of the chunks pointed to by chunklist.
global_bytesize min_elements
virtual global_bytesize getFreeSwap() const
Simple getter.
virtual swapErrorCode swapOut(global_bytesize min_size)
cyclic implementation of swapOut, see paper
global_bytesize n_swap_in
global_bytesize swap_in_scheduled_bytes
void printBacklog() const
unsigned int consecutivePreemptiveTransactions
void decay(global_bytesize bytes)
: Tries to unload around bytes bytes of preemptive elements
static pthread_mutex_t stateChangeMutex
unsigned int preemptiveSinceLast
bool ensureEnoughSpace(global_bytesize sizereq, managedMemoryChunk *orIsSwappedin=NULL)
This function ensures that there is sizereq space left in ram.
cyclicAtime * prev
Next chunk in cycle.
virtual void schedulerDelete(managedMemoryChunk &chunk)
signals deletion of chunk to scheduler code
manages all managed Chunks of raw memory
virtual global_bytesize swapOut(managedMemoryChunk **chunklist, unsigned int nchunks)=0
Trigger swap out of the chunks pointed to by chunklist.
cyclicAtime * preemptiveStart
global_bytesize memory_used
double preemptiveTurnoffFraction
std::map< memoryID, managedMemoryChunk * > memChunks
virtual 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 ...
The element/size requested does not fit in RAM as a whole.
bool setPreemptiveUnloading(bool preemptive)
sets whether scheduler should swap out elements without strict need
We lack reasonable candidates for swapout (too much elements in use?)
void printCycle() const
prints out all elements known to the scheduler with their respective status
static const unsigned int backlog_size
bool waitForSwapin(managedMemoryChunk &chunk, bool keepSwapLock=false)
Waits until a certain chunk is present.
global_bytesize memory_max
global_bytesize memory_swapped
global_bytesize size
Size of actual object in bytes.
virtual bool touch(managedMemoryChunk &chunk)
marks chunk as recently active as a hint for scheduling
unsigned short useCnt
Number of using adhereTos or a possible location for locking the object to changes.
swapErrorCode
Error codes for swapOut requests.
managedMemoryChunk * chunk
backlog_entry backlog[backlog_size]
cyclicAtime * counterActive
Backend class to handle raw memory and interaction/storage with managedSwap.
cyclicManagedMemory(rambrain::managedSwap *swap, rambrain::global_bytesize size)