浏览代码

Merge larson branch to default.

Ioannis Koutras 13 年之前
父节点
当前提交
14f362c790
共有 16 个文件被更改,包括 629 次插入16 次删除
  1. 1 0
      .hgignore
  2. 5 2
      Makefile
  3. 33 1
      block_header.c
  4. 16 0
      block_header.h
  5. 48 0
      coalesce.c
  6. 15 0
      coalesce.h
  7. 7 0
      custom_free.c
  8. 33 3
      custom_malloc.c
  9. 53 0
      dmm_adaptor.c
  10. 7 0
      dmm_adaptor.h
  11. 11 0
      dmm_init.c
  12. 12 6
      heap.h
  13. 329 0
      larson.c
  14. 48 0
      lran2.h
  15. 7 0
      sys_alloc.c
  16. 4 4
      test.c

+ 1 - 0
.hgignore

@@ -3,5 +3,6 @@ syntax: glob
 *.swp
 *.o
 test
+larson
 html/*
 latex/*

+ 5 - 2
Makefile

@@ -5,7 +5,7 @@ WARNINGS := -Wall -Wextra -pedantic -Wshadow -Wpointer-arith -Wcast-align \
 	          -Wuninitialized -Wconversion -Wstrict-prototypes
 CFLAGS := -g -O -std=c99 $(WARNINGS)
 
-OBJ = posix_lock.o other.o block_header.o sys_alloc.o dmm_init.o custom_malloc.o custom_free.o
+OBJ = posix_lock.o other.o block_header.o sys_alloc.o dmm_init.o coalesce.o dmm_adaptor.o custom_malloc.o custom_free.o
 
 %.o: %.c
 	$(CC) -c -o $@ $< $(CFLAGS)
@@ -13,7 +13,10 @@ OBJ = posix_lock.o other.o block_header.o sys_alloc.o dmm_init.o custom_malloc.o
 test: $(OBJ) test.o
 	$(CC) -pthread -o $@ $^ $(CFLAGS)
 
+larson: $(OBJ) larson.o
+	$(CC) -pthread -o $@ $^ $(CFLAGS)
+
 clean:
-	-@$(RM) $(wildcard $(OBJ)) test.o test
+	-@$(RM) $(wildcard $(OBJ)) test.o larson.o test larson
 
 .PHONY: all clean test

+ 33 - 1
block_header.c

@@ -15,7 +15,7 @@ size_t get_size(void *ptr) {
 }
 
 void set_size(void *ptr, size_t size) {
-	get_header(ptr)->size = size;
+	get_header(ptr)->size = size << 1;
 }
 
 void set_requested_size(void *ptr, size_t size) {
@@ -25,3 +25,35 @@ void set_requested_size(void *ptr, size_t size) {
 void set_next(void *ptr, void *next_block) {
 	get_header(ptr)->next = next_block;
 }
+
+bool is_previous_free(void *ptr) {
+	return (bool) (get_header(ptr)->previous_size & 1);
+}
+
+size_t get_previous_size(void *ptr) {
+	return get_header(ptr)->previous_size >> 1;
+}
+
+void * get_previous(void *ptr) {
+	return (void *) ((char *) ptr - get_previous_size(ptr));
+}
+
+void remove_block(void *block, void *starting_node) {
+	void *current_node, *previous_node;
+
+	// If the block to be removed is the head of the list, then just point
+	// the next block as head.
+	if(current_node == starting_node) {
+		starting_node = get_next(block);
+	// Else traverse through the list until the memory block is found.
+	} else {
+		for(current_node = starting_node; current_node != NULL; 
+				current_node = get_next(current_node)) {
+			if(current_node == block) {
+				set_next(previous_node, get_next(block));
+			}
+			previous_node = current_node;
+		}
+	}
+}
+

+ 16 - 0
block_header.h

@@ -2,10 +2,12 @@
 #define BLOCK_HEADER_H
 
 #include <stddef.h>
+#include <stdbool.h>
 
 typedef struct block_header_s {
 	size_t size;
 	size_t requested_size;
+	size_t previous_size;
 	void *next;
 } block_header_t;
 
@@ -20,4 +22,18 @@ void set_requested_size(void *ptr, size_t size);
 
 void set_next(void *block, void *next_block);
 
+bool is_previous_free(void *ptr);
+
+size_t get_previous_size(void *ptr);
+
+void * get_previous(void *ptr);
+
+/**
+ * Removes a memory block from a singly linked list of memory blocks.
+ *
+ * @param *block The block to be removed.
+ * @param *starting_node The starting memory block of the list.
+ */
+void remove_block(void *block, void *starting_node);
+
 #endif /* BLOCK_HEADER_H */

+ 48 - 0
coalesce.c

@@ -0,0 +1,48 @@
+#include "coalesce.h"
+#include "block_header.h"
+#include "other.h"
+
+void * coalesce(void *ptr, heap_t *heap) {
+	void *prev;
+	int fixed_list_id, i;
+	maptable_node_t *current_maptable_node;
+
+	// If there is a negative value on max_coalesce_size, then don't do
+	// anything.
+	// FIXME To be moved in custom_free()
+	if(heap->dmm_knobs.max_coalesce_size < 0) {
+		return ptr;
+	}
+
+	// Try to coalesce with the previous memory block
+	if(is_previous_free(ptr)) {
+		prev = get_previous(ptr);
+
+		// Check if it is a block of a fixed list
+		fixed_list_id = map_size_to_list(heap, get_size(prev));
+		if(fixed_list_id != -1) {
+			// If it is, find the fixed list and remove the block
+			current_maptable_node = heap->maptable_head;
+			if(fixed_list_id != 0) {
+				for(i = 1; i < fixed_list_id; i++) {
+					current_maptable_node =
+						current_maptable_node->next;
+				}
+			}
+			remove_block(ptr, current_maptable_node->fixed_list_head);
+		} else {
+			// Or it is a block from the free list, so remove it
+			// from there
+			remove_block(ptr, heap->free_list_head);
+		}
+
+		// Set the new size
+		// Note: the rest of the header variables will be set on free().
+		set_size(prev, get_size(prev) + get_size(ptr) + HEADER_SIZE);
+
+		return prev;
+	} else {
+		return ptr;
+	}
+}
+

+ 15 - 0
coalesce.h

@@ -0,0 +1,15 @@
+#ifndef COALESCE_H
+#define COALESCE_H
+
+#include "heap.h"
+
+/**
+ * Merges a memory block with its previous one if the latter one is free.
+ *
+ * @param ptr The memory block to be checked.
+ * @param heap The heap of the memory block.
+ */
+void * coalesce(void *ptr, heap_t *heap);
+
+#endif /* COALESCE_H */
+

+ 7 - 0
custom_free.c

@@ -30,6 +30,13 @@ void custom_free(heap_t* heap, void *ptr) {
 		heap->free_list_head = ptr;
 	}
 
+	// Begin of Stats
+
+	heap->dmm_stats.live_objects -= 1;
+	heap->dmm_stats.num_free += 1;
+
+	// End of Stats
+
 	posix_unlock(heap);
 }
 

+ 33 - 3
custom_malloc.c

@@ -3,6 +3,7 @@
 #include "other.h"
 #include "sys_alloc.h"
 #include "block_header.h"
+#include "dmm_adaptor.h"
 
 void * custom_malloc(heap_t* heap, size_t size) {
 	void *ptr;
@@ -11,6 +12,7 @@ void * custom_malloc(heap_t* heap, size_t size) {
 	void *current_block, *previous_block;
 
 	ptr = NULL;
+	previous_block = NULL;
 
 	posix_lock(heap);
 
@@ -29,6 +31,8 @@ void * custom_malloc(heap_t* heap, size_t size) {
 			ptr = current_maptable_node->fixed_list_head;
 			current_maptable_node->fixed_list_head = get_next(ptr);
 			set_requested_size(ptr, size);
+			set_next(ptr, heap->used_blocks_head);
+		 	heap->used_blocks_head = ptr;
 		}
 	}
 
@@ -36,17 +40,26 @@ void * custom_malloc(heap_t* heap, size_t size) {
 		found = 0;
 
 		// first fit from free list
-		for(current_block = heap->free_list_head; current_block != NULL; current_block = get_next(current_block)) {
+		for(current_block = heap->free_list_head; current_block != NULL;
+				current_block = get_next(current_block)) {
 			if(get_size(current_block) >= size) {
 				ptr = current_block;
-				set_requested_size(ptr, size);
-				set_next(ptr, heap->used_blocks_head);
 				heap->used_blocks_head = ptr;
 				if(current_block != heap->free_list_head) {
 					set_next(previous_block, get_next(ptr));
 				} else {
 					heap->free_list_head = get_next(ptr);
 				}
+				set_requested_size(ptr, size);
+				set_next(ptr, heap->used_blocks_head);
+
+				// Begin of Stats
+
+				heap->dmm_stats.live_objects += 1;
+				heap->dmm_stats.num_malloc += 1;
+
+				// End of Stats
+
 				posix_unlock(heap);
 				return ptr;
 			}
@@ -55,10 +68,27 @@ void * custom_malloc(heap_t* heap, size_t size) {
 
 		if(!found) {
 			ptr = sys_alloc(heap, size);
+			heap->dmm_stats.mem_allocated += req_padding(size);
+			heap->dmm_stats.mem_requested += size;
 		}
 
 	}
 
+	// Begin of Stats
+
+	heap->dmm_stats.live_objects += 1;
+	heap->dmm_stats.num_malloc += 1;
+
+	// End of Stats
+
+	// Refresh the state of the heap allocator if a certain number of
+	// malloc's has been served already
+	// TODO Define 50 as a constant
+	if(heap->dmm_stats.num_malloc % 50) {
+		state_refresh(heap);
+	}
+
 	posix_unlock(heap);
 	return ptr;
 }
+

+ 53 - 0
dmm_adaptor.c

@@ -0,0 +1,53 @@
+#include "dmm_adaptor.h"
+#include "heap.h"
+
+void state_refresh(heap_t *heap) {
+	float fragmentation;
+	knob_state_t state;
+
+	fragmentation = (float) heap->dmm_stats.mem_allocated / 
+		(float)	heap->dmm_stats.mem_requested - 1.0;
+
+	// TODO Constant for the threshold, contraints for the memory threshold
+	if(fragmentation <= 0.05) {
+		state = 0;
+		set_fragmentation_params(heap, state);
+	}
+}
+
+void set_fragmentation_params(heap_t *heap, knob_state_t state) {
+	switch(state) {
+		default :
+			heap->dmm_knobs.max_coalesce_size = -1;
+			heap->dmm_knobs.min_split_size = 0;
+			heap->dmm_knobs.empty_threshold = 1.5;
+			break;
+		case 1 :
+			heap->dmm_knobs.max_coalesce_size = 20;
+			heap->dmm_knobs.min_split_size = 400;
+			heap->dmm_knobs.empty_threshold = 1200;
+			break;
+		case 2 :
+			heap->dmm_knobs.max_coalesce_size = 40;
+			heap->dmm_knobs.min_split_size = 800;
+			heap->dmm_knobs.empty_threshold = 1000;
+			break;
+		case 3 :
+			heap->dmm_knobs.max_coalesce_size = 60;
+			heap->dmm_knobs.min_split_size = 1200;
+			heap->dmm_knobs.empty_threshold = 800;
+			break;
+		case 4 :
+			heap->dmm_knobs.max_coalesce_size = 80;
+			heap->dmm_knobs.min_split_size = 1600;
+			heap->dmm_knobs.empty_threshold = 600;
+			break;
+		case 5 :
+			heap->dmm_knobs.max_coalesce_size = 100;
+			heap->dmm_knobs.min_split_size = 2000;
+			heap->dmm_knobs.empty_threshold = 300;
+			break;
+	}
+}
+
+

+ 7 - 0
dmm_adaptor.h

@@ -0,0 +1,7 @@
+#include "heap.h"
+
+typedef uint8_t knob_state_t;
+
+void state_refresh(heap_t *heap);
+void set_fragmentation_params(heap_t *heap, knob_state_t state);
+

+ 11 - 0
dmm_init.c

@@ -17,8 +17,19 @@ allocator_t * dmm_init(void) {
 		main_allocator->heaps[i].used_blocks_head = NULL;
 		main_allocator->heaps[i].rov_ptr = NULL;
 		main_allocator->heaps[i].num_objects = 0;
+		main_allocator->heaps[i].dmm_stats.mem_allocated = 0;
+		main_allocator->heaps[i].dmm_stats.mem_requested = 0;
+		main_allocator->heaps[i].dmm_stats.live_objects = 0;
 		main_allocator->heaps[i].dmm_stats.num_malloc = 0;
 		main_allocator->heaps[i].dmm_stats.num_free = 0;
+
+		// Knobs initialization
+		main_allocator->heaps[i].dmm_knobs.max_coalesce_size = -1;
+		// FIXME Create a constant for the initial value of the next
+		// variables
+		main_allocator->heaps[i].dmm_knobs.frag_threshold = 1.0;
+		main_allocator->heaps[i].dmm_knobs.mem_threshold = 17000;
+
 		pthread_mutex_init(&main_allocator->heaps[i].mutex, NULL);
 	}
 

+ 12 - 6
heap.h

@@ -10,8 +10,6 @@
 
 /**
  * A structure to represent a maptable node
- *
- * Heaps contain 
  */
 typedef struct maptable_node_s {
 	unsigned int size; /**< the size of the blocks of the fixed list */
@@ -24,6 +22,7 @@ typedef struct dmmstats_s {
 	uint32_t max_mem_requested; /**< maximum total memory requested */
 	uint32_t mem_allocated; /**< total memory currently allocated */
 	uint32_t mem_requested; /**< total memory currently requested */
+	uint32_t mem_reserved; /**< total memory currently reserved */
 	uint32_t live_objects; /**< number of live objects */
 	uint32_t read_mem_accesses; /**< number of read accesses */
 	uint32_t write_mem_accesses; /**< number of write accesses */
@@ -31,11 +30,18 @@ typedef struct dmmstats_s {
 	uint32_t num_free; /**< number of free()'s served */
 } dmmstats_t;
 
+/**
+ * A structure to represent tunable parameters of a heap
+ */
 typedef struct dmmknobs_s {
-	uint32_t maxCoalesceSize;
-	uint32_t minSplitSize;
-	float empty_threshold;
-	uint32_t percentage;
+	int32_t max_coalesce_size; /**< maximum coalesce size; -1 if coalescing
+				      is not supported */
+	float frag_threshold; /**< fragmentation threshold to enable
+					 coalescing or not */ 
+	uint32_t mem_threshold; /**< memory size threshold */
+	uint32_t min_split_size; // FIXME to be investigated if needed
+	float empty_threshold; // FIXME to be investigated if needed
+	uint32_t percentage; // FIXME to be investigated if needed
 	char frag_state; //FIXME It was in the old code to refresh the frag check
 } dmmknobs_t;
 

+ 329 - 0
larson.c

@@ -0,0 +1,329 @@
+#include <pthread.h>
+#include <stdio.h>
+#include <sys/time.h>
+#include <string.h>
+#include <assert.h>
+#include <unistd.h>
+#include "custom_malloc.h"
+#include "custom_free.h"
+#include "other.h"
+#include "lran2.h"
+#include "dmm_init.h"
+
+#define MAX_THREADS     100
+#define MAX_BLOCKS  1000000
+
+#ifndef BOOLEAN
+#define BOOLEAN
+enum BOOLEAN { FALSE, TRUE };
+#endif /* BOOLEAN */
+
+typedef void * LPVOID;
+typedef unsigned long ULONG;
+typedef long long _int64;
+typedef void * VoidFunction (void *);
+
+typedef struct thr_data {
+
+	int threadno;
+	int NumBlocks;
+	long seed;
+
+	int min_size;
+	int max_size;
+
+	char **array;
+	int *blksize;
+	int asize;
+
+	int cAllocs;
+	int cFrees;
+	int cThreads;
+	int cBytesAlloced;
+
+	volatile int finished;
+	struct lran2_st rgen;
+
+} thread_data;
+
+allocator_t *myallocator;
+
+int volatile stopflag = FALSE;
+int min_size = 10, max_size = 500;
+struct lran2_st rgen;
+char *blkp[MAX_BLOCKS];
+int blksize[MAX_BLOCKS];
+
+static void QueryPerformanceFrequency(long *x) {
+	*x = 1000000L;
+}
+
+static void QueryPerformanceCounter (long *x) {
+  struct timezone tz;
+  struct timeval tv;
+  gettimeofday(&tv, &tz);
+  *x = tv.tv_sec * 1000000L + tv.tv_usec;
+}
+
+static void Sleep(long x) {
+  //  printf ("sleeping for %ld seconds.\n", x/1000);
+  sleep((unsigned int) (x/1000));
+}
+
+static void _beginthread(VoidFunction x, void * z) {
+	pthread_t pt;
+	pthread_attr_t pa;
+	pthread_attr_init (&pa);
+
+	//  printf ("creating a thread.\n");
+	pthread_create(&pt, &pa, x, z);
+}
+
+static void warmup(char **blkp, int num_chunks) {
+	int cblks;
+	int victim;
+	int blk_size;
+	LPVOID tmp;
+
+	heap_t *myheap;
+	int heap_id;
+
+	heap_id = map_thread_heap();
+	myheap = &myallocator->heaps[heap_id];	
+	
+	for(cblks = 0; cblks < num_chunks; cblks++) {
+		blk_size = min_size + lran2(&rgen) % (max_size - min_size);
+		blkp[cblks] = (char *) custom_malloc(myheap, (size_t) blk_size);
+		blksize[cblks] = blk_size;
+		assert(blkp[cblks] != NULL);
+	}
+
+	/* generate a random permutation of the chunks */
+	for(cblks = num_chunks; cblks > 0 ; cblks--) {
+		victim = lran2(&rgen) % cblks;
+		tmp = blkp[victim];
+		blkp[victim]  = blkp[cblks-1];
+		blkp[cblks-1] = (char *) tmp;
+	}
+
+	for(cblks=0; cblks < 4 * num_chunks; cblks++) {
+		victim = lran2(&rgen) % num_chunks;
+		custom_free(myheap, blkp[victim]);
+
+		blk_size = min_size + lran2(&rgen) % (max_size - min_size);
+		blkp[victim] = (char *) custom_malloc(myheap, (size_t) blk_size);
+		blksize[victim] = blk_size;
+		assert(blkp[victim] != NULL);
+	}
+}
+
+static void * exercise_heap( void *pinput) {
+	thread_data  *pdea;
+	int           cblks = 0;
+	int           victim;
+	long          blk_size;
+	int           range;
+
+	heap_t *myheap;
+	int heap_id;
+
+	heap_id = map_thread_heap();
+	myheap = &myallocator->heaps[heap_id];
+
+	if( stopflag ) return 0;
+
+	pdea = (thread_data *) pinput;
+	pdea->finished = FALSE;
+	pdea->cThreads++;
+	range = pdea->max_size - pdea->min_size;
+
+	/* allocate NumBlocks chunks of random size */
+	for(cblks=0; cblks < pdea->NumBlocks; cblks++) {
+		victim = lran2(&pdea->rgen)%pdea->asize;
+		custom_free(myheap, pdea->array[victim]);
+		pdea->cFrees++;
+
+		blk_size = pdea->min_size+lran2(&pdea->rgen)%range;
+		pdea->array[victim] = (char *) custom_malloc(myheap, (size_t) blk_size);
+
+		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 ) {
+		_beginthread(exercise_heap, pdea);
+	}
+
+	return 0;
+}
+
+
+static 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 ticks_per_sec;
+    	int prevthreads;
+	int num_threads;
+	int nperthread;
+	int sum_threads;
+	int sum_allocs;
+	int sum_frees;
+
+	int i;
+
+	long start_cnt, end_cnt;
+	_int64 ticks;
+	double duration ;
+
+	double rate_1 = 0, rate_n;
+	double reqd_space;
+	ULONG used_space;	
+
+	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);
+			_beginthread(exercise_heap, &de_area[i]);
+		}
+		
+		QueryPerformanceCounter( &start_cnt );
+
+		printf ("Sleeping for %ld seconds.\n", sleep_cnt);
+		Sleep(sleep_cnt * 1000L) ;
+
+	      	stopflag = TRUE ;
+		
+		for(i = 0; i < num_threads; i++) {
+			while( !de_area[i].finished ) {
+				sched_yield();
+			}
+		}
+
+		QueryPerformanceCounter( &end_cnt );
+
+		sum_frees = sum_allocs =0  ;
+		sum_threads = 0 ;
+		for(i=0;i< num_threads; i++){
+			sum_allocs    += de_area[i].cAllocs ;
+			sum_frees     += de_area[i].cFrees ;
+			sum_threads   += de_area[i].cThreads ;
+			de_area[i].cAllocs = de_area[i].cFrees = 0;
+		}
+
+		ticks = end_cnt - start_cnt ;
+		duration = (double)ticks/ticks_per_sec ;
+
+		for(i = 0; i < num_threads; i++) {
+			if( !de_area[i].finished ) {
+				printf("Thread at %d not finished\n", i);
+			}
+		}
+
+		rate_n = sum_allocs/duration ;
+		if( rate_1 == 0){
+			rate_1 = rate_n ;
+		}
+		reqd_space = (0.5*(min_size+max_size)*num_threads*chperthread) ;
+		// used_space = CountReservedSpace() - init_space;
+		used_space = 0;
+
+		printf("%2d ", num_threads ) ;
+		printf("%6.3f", duration  ) ;
+		printf("%6.3f", rate_n/rate_1 ) ;
+		printf("%8.0f", sum_allocs/duration ) ;
+		printf(" %6.3f %.3f", (double)used_space/(1024*1024), used_space/reqd_space) ;
+		printf("\n") ;
+
+		Sleep(5000L) ; // wait 5 sec for old threads to die
+
+		prevthreads = num_threads;
+	}
+
+}
+
+int main(void) {
+	long sleep_cnt;
+	int min_threads, max_threads;
+	int num_chunks = 10000;
+	int num_rounds;
+	int chperthread;
+
+	myallocator = dmm_init();
+
+	printf("Larson benchmark\n");
+	
+	printf("runtime (sec): ") ;
+	//scanf ("%ld", &sleep_cnt);
+	sleep_cnt = 10;
+	
+	printf("chunk size (min,max): ") ;
+	//scanf("%d %d", &min_size, &max_size ) ;
+	min_size = 32;
+	max_size = 256;
+	
+	printf("threads (min, max):   ") ; 
+	//scanf("%d %d", &min_threads, &max_threads) ;
+	min_threads = 1;
+	max_threads = 1;
+
+	pthread_setconcurrency(max_threads);
+	
+	printf("chunks/thread:  ");
+	//scanf("%d", &chperthread );
+	chperthread = 1;
+	
+	num_chunks = max_threads * chperthread ;
+	if( num_chunks > MAX_BLOCKS ){
+		printf("Max %d chunks - exiting\n", MAX_BLOCKS ) ;
+		return 1;
+	}
+	
+	printf("no of rounds:   ");
+	//scanf("%d", &num_rounds );
+	num_rounds = 1;
+	
+	runthreads(sleep_cnt, min_threads, max_threads, chperthread, num_rounds) ;
+	
+	return 0;
+}
+

+ 48 - 0
lran2.h

@@ -0,0 +1,48 @@
+/* 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 /* _LRAN2_H */

+ 7 - 0
sys_alloc.c

@@ -1,5 +1,7 @@
 #include <unistd.h>
 #include <stdio.h>
+#include <errno.h>
+#include <string.h>
 #include "posix_lock.h"
 #include "other.h"
 #include "sys_alloc.h"
@@ -15,6 +17,11 @@ void *sys_alloc(heap_t *heap, size_t size) {
 	allocation_size = req_padding(size) + HEADER_SIZE;
 
 	ptr = sbrk((int) allocation_size);
+	if(ptr == (void *) -1) {
+		printf("sbrk problem for size of: %zu\n", allocation_size);
+		printf( "Error on sbrk: %s\n", strerror( errno ) );
+	}
+	ptr = (void *) ((char *) ptr + HEADER_SIZE);
 
 	set_size(ptr, req_padding(size));
 	set_requested_size(ptr, size);

+ 4 - 4
test.c

@@ -15,10 +15,10 @@ int main(void) {
 	heap_id = map_thread_heap();
 	printf("This thread accesses heap %d\n", heap_id);
 	myheap = &myallocator->heaps[heap_id];
-	p1 = custom_malloc(myheap, (size_t) 3000);
-	p2 = custom_malloc(myheap, (size_t) 3000);
-	p3 = custom_malloc(myheap, (size_t) 3000);
+	p1 = custom_malloc(myheap, (size_t) 1024);
 	custom_free(myheap, p1);
-	custom_free(myheap, p3);
+	p2 = custom_malloc(myheap, (size_t) 2855);
 	custom_free(myheap, p2);
+	p3 = custom_malloc(myheap, (size_t) 3018);
+	custom_free(myheap, p3);
 }