From abf62b06693de3792a816c04fdecfc763eac879f Mon Sep 17 00:00:00 2001
From: jdh8d <jdh8d@git.zephyr-software.com>
Date: Fri, 14 Aug 2015 17:51:35 +0000
Subject: [PATCH] Added randomization of placed dollops.

---
 src/memory_space.cpp | 278 ++++++++++---------------------------------
 src/zipr_options.cpp |  20 +++-
 2 files changed, 79 insertions(+), 219 deletions(-)

diff --git a/src/memory_space.cpp b/src/memory_space.cpp
index b5856bc..aa4a89d 100644
--- a/src/memory_space.cpp
+++ b/src/memory_space.cpp
@@ -22,6 +22,11 @@
 #include <unistd.h>
 #include <stdlib.h>
 #include <getopt.h>
+#include <algorithm>    // std::random_shuffle
+#include <vector>       // std::vector
+#include <ctime>        // std::time
+#include <cstdlib>      // std::rand, std::srand
+
 
 using namespace zipr;
 using namespace std;
@@ -56,7 +61,6 @@ void ZiprMemorySpace_t::SplitFreeRange(RangeAddress_t addr)
 }
 
 void ZiprMemorySpace_t::MergeFreeRange(RangeAddress_t addr)
-#if 1
 {
 	/*
 	 * Make a new range of one byte.
@@ -70,236 +74,65 @@ void ZiprMemorySpace_t::MergeFreeRange(RangeAddress_t addr)
 	Range_t nr(addr, addr);
 	Range_t nrp1(addr+1, addr+1);
 	Range_t nrm1(addr-1, addr-1);
-	bool merged = false;
 	RangeSet_t::iterator itp1;
 	RangeSet_t::iterator itm1;
 
-//	for(;it!=free_ranges.end();++it)
-//	{
-		
-		itp1=free_ranges.find(nrp1);
-		itm1=free_ranges.find(nrm1);
-		Range_t r;
-		if(itp1!=free_ranges.end())
-		{
-			r=*itp1;
-			assert((addr+1) == r.GetStart());
-			/*
-			 * Make the beginning of this range
-			 * one byte smaller!
-			 */
-			Range_t nnr(addr, r.GetEnd());
-			if(m_opts != NULL && m_opts->GetVerbose())
-			{
-				printf("Expanded range:\n");
-				printf("from: %p to %p\n", (void*)r.GetStart(), (void*)r.GetEnd());
-				printf("to: %p to %p\n", (void*)nnr.GetStart(), (void*)nnr.GetEnd());
-			}
-			nr = nnr;
-			if(itm1!=free_ranges.end())
-			{
-				Range_t r2=*itm1;
-				nr.SetStart(r2.GetStart());	
-				free_ranges.erase(r2);
-			}
-			free_ranges.erase(r);
-		} 
-		else if(itm1!=free_ranges.end())	 // not addr+1 is still busy, so we don't merge against it.
+	itp1=free_ranges.find(nrp1);
+	itm1=free_ranges.find(nrm1);
+	Range_t r;
+	if(itp1!=free_ranges.end())
+	{
+		r=*itp1;
+		assert((addr+1) == r.GetStart());
+		/*
+		 * Make the beginning of this range
+		 * one byte smaller!
+		 */
+		Range_t nnr(addr, r.GetEnd());
+		if(m_opts != NULL && m_opts->GetVerbose())
 		{
-			r=*itm1;
-		
-			assert((addr-1) == r.GetEnd()) ;
-			/*
-			 * Make the end of this range one byte
-			 * bigger
-			 */
-			Range_t nnr(r.GetStart(), addr);
-			if(m_opts != NULL && m_opts->GetVerbose())
-			{
-				printf("Expanded range:\n");
-				printf("from: %p to %p\n", (void*)r.GetStart(), (void*)r.GetEnd());
-				printf("to: %p to %p\n", (void*)nnr.GetStart(), (void*)nnr.GetEnd());
-			}
-			nr = nnr;
-			free_ranges.erase(itm1);
+			printf("Expanded range:\n");
+			printf("from: %p to %p\n", (void*)r.GetStart(), (void*)r.GetEnd());
+			printf("to: %p to %p\n", (void*)nnr.GetStart(), (void*)nnr.GetEnd());
 		}
-		else
+		nr = nnr;
+		if(itm1!=free_ranges.end())
 		{
-			// else both p1 and m1 are busy still, so we just insert nr
+			Range_t r2=*itm1;
+			nr.SetStart(r2.GetStart());	
+			free_ranges.erase(r2);
 		}
-
-		// insert NR and be done.
-		free_ranges.insert(nr);
-		return;
-//	}
-
-	/*
-	 * Correctness: 
-	 * Take a pass through and see if there are
-	 * free ranges that can now be merged. This
-	 * is important because it's possible that
-	 * we added the byte to the end of a range
-	 * where it could also have gone at the
-	 * beginning of another.
-	 */
-#if 0
-	for(it=free_ranges.begin();it!=free_ranges.end();++it)
+		free_ranges.erase(r);
+	} 
+	else if(itm1!=free_ranges.end())	 // not addr+1 is still busy, so we don't merge against it.
 	{
-		Range_t r = *it;
-		if ((
-				/*
-				 * <--r-->
-				 *    <--nr-->
-				 */
-				((r.GetEnd()+1) >= nr.GetStart() &&
-				r.GetEnd() <= nr.GetEnd()) ||
-				/*
-				 * <--nr-->
-				 *     <--r-->
-				 */
-				((nr.GetEnd()+1) >= r.GetStart() &&
-				nr.GetEnd() <= r.GetEnd())
-				) &&
-				/*
-				 * The ranges themselves are not
-				 * identical.
-				 */
-				(r.GetStart() != nr.GetStart() ||
-				r.GetEnd() != nr.GetEnd()))
+		r=*itm1;
+	
+		assert((addr-1) == r.GetEnd()) ;
+		/*
+		 * Make the end of this range one byte
+		 * bigger
+		 */
+		Range_t nnr(r.GetStart(), addr);
+		if(m_opts != NULL && m_opts->GetVerbose())
 		{
-			/*
-			 * merge.
-			 */
-			Range_t merged_range(std::min(r.GetStart(), nr.GetStart()), std::max(r.GetEnd(), nr.GetEnd()));
-			if(m_opts != NULL && m_opts->GetVerbose())
-			{
-				printf("Merged two ranges:\n");
-				printf("r:  %p to %p\n", (void*)r.GetStart(), (void*)r.GetEnd());
-				printf("nr: %p to %p\n", (void*)nr.GetStart(), (void*)nr.GetEnd());
-				printf("to: %p to %p\n", (void*)merged_range.GetStart(), (void*)merged_range.GetEnd());
-			}
-			free_ranges.erase(it);
-			free_ranges.insert(merged_range);
-			merged = true;
-			break;
+			printf("Expanded range:\n");
+			printf("from: %p to %p\n", (void*)r.GetStart(), (void*)r.GetEnd());
+			printf("to: %p to %p\n", (void*)nnr.GetStart(), (void*)nnr.GetEnd());
 		}
+		nr = nnr;
+		free_ranges.erase(itm1);
 	}
-
-
-	if (!merged)
+	else
 	{
-		free_ranges.insert(nr);
+		// else both p1 and m1 are busy still, so we just insert nr
 	}
-#endif
-}
-#else
-{
-	/*
-	 * Make a new range of one byte.
-	 * 
-	 * Then, look to see whether or not it
-	 * can be merged with another range. 
-	 *
-	 * If not, add it as a one byte range.
-	 */
-
-	Range_t nr(addr, addr);
-	bool merged = false;
-	RangeSet_t::iterator it=free_ranges.begin();
 
-	for(;it!=free_ranges.end();++it)
-	{
-		Range_t r=*it;
-		if ((addr+1) == r.GetStart()) {
-			/*
-			 * Make the beginning of this range
-			 * one byte smaller!
-			 */
-			Range_t nnr(addr, r.GetEnd());
-			if(m_opts != NULL && m_opts->GetVerbose())
-			{
-				printf("Expanded range:\n");
-				printf("from: %p to %p\n", (void*)r.GetStart(), (void*)r.GetEnd());
-				printf("to: %p to %p\n", (void*)nnr.GetStart(), (void*)nnr.GetEnd());
-			}
-			nr = nnr;
-			free_ranges.erase(it);
-			break;
-		} else if ((addr-1) == r.GetEnd()) {
-			/*
-			 * Make the end of this range one byte
-			 * bigger
-			 */
-			Range_t nnr(r.GetStart(), addr);
-			if(m_opts != NULL && m_opts->GetVerbose())
-			{
-				printf("Expanded range:\n");
-				printf("from: %p to %p\n", (void*)r.GetStart(), (void*)r.GetEnd());
-				printf("to: %p to %p\n", (void*)nnr.GetStart(), (void*)nnr.GetEnd());
-			}
-			nr = nnr;
-			free_ranges.erase(it);
-			break;
-		}
-	}
-
-	/*
-	 * Correctness: 
-	 * Take a pass through and see if there are
-	 * free ranges that can now be merged. This
-	 * is important because it's possible that
-	 * we added the byte to the end of a range
-	 * where it could also have gone at the
-	 * beginning of another.
-	 */
-	for(it=free_ranges.begin();it!=free_ranges.end();++it)
-	{
-		Range_t r = *it;
-		if ((
-				/*
-				 * <--r-->
-				 *    <--nr-->
-				 */
-				((r.GetEnd()+1) >= nr.GetStart() &&
-				r.GetEnd() <= nr.GetEnd()) ||
-				/*
-				 * <--nr-->
-				 *     <--r-->
-				 */
-				((nr.GetEnd()+1) >= r.GetStart() &&
-				nr.GetEnd() <= r.GetEnd())
-				) &&
-				/*
-				 * The ranges themselves are not
-				 * identical.
-				 */
-				(r.GetStart() != nr.GetStart() ||
-				r.GetEnd() != nr.GetEnd()))
-		{
-			/*
-			 * merge.
-			 */
-			Range_t merged_range(std::min(r.GetStart(), nr.GetStart()), std::max(r.GetEnd(), nr.GetEnd()));
-			if(m_opts != NULL && m_opts->GetVerbose())
-			{
-				printf("Merged two ranges:\n");
-				printf("r:  %p to %p\n", (void*)r.GetStart(), (void*)r.GetEnd());
-				printf("nr: %p to %p\n", (void*)nr.GetStart(), (void*)nr.GetEnd());
-				printf("to: %p to %p\n", (void*)merged_range.GetStart(), (void*)merged_range.GetEnd());
-			}
-			free_ranges.erase(it);
-			free_ranges.insert(merged_range);
-			merged = true;
-			break;
-		}
-	}
+	// insert NR and be done.
+	free_ranges.insert(nr);
+	return;
 
-	if (!merged)
-	{
-		free_ranges.insert(nr);
-	}
 }
-#endif
 
 void ZiprMemorySpace_t::PrintMemorySpace(std::ostream &out)
 {
@@ -325,15 +158,24 @@ bool ZiprMemorySpace_t::IsValidRange(RangeSet_t::iterator it)
 
 Range_t ZiprMemorySpace_t::GetFreeRange(int size)
 {
+	vector<Range_t> v;
+	Range_t big_range;
 	for( RangeSet_t::iterator it=free_ranges.begin();
 		it!=free_ranges.end();
 		++it)
 	{
 		Range_t r=*it;
-		if(r.GetEnd() - r.GetStart() > size)
-			return r;
+		if(r.GetEnd()==(RangeAddress_t)-1)
+			big_range=r;;
+		if(r.GetEnd() - r.GetStart() > (unsigned) size)
+			v.push_back(r);
 	}
-	assert(0);// assume we find a big enough range.
+	if(v.size()==0)
+		return big_range;	
+
+	// choose random value to return.
+	int index=std::rand() % v.size();
+	return v[index];
 }
 
 // queries about free areas.
diff --git a/src/zipr_options.cpp b/src/zipr_options.cpp
index 6f8cdb6..7fcfb64 100644
--- a/src/zipr_options.cpp
+++ b/src/zipr_options.cpp
@@ -22,6 +22,11 @@
 #include <unistd.h>
 #include <stdlib.h>
 #include <getopt.h>
+#include <ctime>        // std::time
+#include <iostream>
+#include <cstdlib>	// std::srand
+
+
 
 using namespace zipr;
 
@@ -51,7 +56,7 @@ ZiprOptions_t* ZiprOptions_t::parse_args(int p_argc, char* p_argv[])
 	ZiprOptions_t *opt=new ZiprOptions_t;
 	opt->SetVerbose(true);
 	int option = 0;
-	char options[] = "!qz:o:v:c:j:m:";
+	char options[] = "!qz:o:v:c:j:m:s:";
 	struct option long_options[] = {
 		{"verbose",     no_argument,       NULL, '!'},
 		{"quiet",       no_argument,       NULL, 'q'},
@@ -61,9 +66,13 @@ ZiprOptions_t* ZiprOptions_t::parse_args(int p_argc, char* p_argv[])
 		{"callbacks",   required_argument, NULL, 'c'},
 		{"objcopy",     required_argument, NULL, 'j'},
 		{"architecture",required_argument, NULL, 'm'},
+		{"seed",required_argument, NULL, 's'},
 		{NULL, no_argument, NULL, '\0'},	 // end-of-array marker
 	};
 
+	// set random seed for zipr to really random.
+	std::srand ( unsigned ( std::time(0) ) );
+
 	assert(opt);
 
 	while ((option = getopt_long(
@@ -147,6 +156,15 @@ ZiprOptions_t* ZiprOptions_t::parse_args(int p_argc, char* p_argv[])
 					"Will use detection to determine architecture. \n", ::optarg);
 				break;
 			}
+			case 's':
+			{
+				char *valid = NULL;
+				long int seed = ::strtol(::optarg, &valid, 10);
+				if(*valid!='\0')
+					std::cerr<<"Seed value ("<< ::optarg << ") must be a base-10 integer."<<std::endl;
+				std::srand((unsigned)seed);
+				break;
+			}
 			case '?':
 			{
 				// getopt_long printed message
-- 
GitLab