Skip to content

Commit 6b680b2

Browse files
author
Rishabh Kabra
committed
Implemented parallelism-compatibility by adding a global mutex that is locked and unlocked for every critical section in the code (in check, init, malloc, free, and realloc). Runs fine with cache-scratch (fixed segfault-causing bug). Also runs fine with mdriver (though throughput has fallen to 32 from 40).
1 parent 50b581f commit 6b680b2

File tree

1 file changed

+48
-19
lines changed

1 file changed

+48
-19
lines changed

allocator.cpp

+48-19
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <cstdlib>
2727
#include <cstring>
2828
#include <cmath>
29+
#include <pthread.h>
2930
#include <iostream> // remove later
3031
#include "./allocator_interface.h"
3132
#include "./memlib.h"
@@ -40,30 +41,35 @@
4041
#define SIZE_T_SIZE (ALIGN(sizeof(size_t)))
4142

4243
namespace my {
43-
// check - This checks our invariant that the size_t header before every
44-
// block points to either the beginning of the next block, or the end of the
45-
// heap.
44+
// check - This checks our invariant that the size_t header before every
45+
// block points to either the beginning of the next block, or the end of the
46+
// heap.
4647

47-
struct MemoryBlock {
48-
MemoryBlock * nextFreeBlock; // pointer to the next free block in the binned free list that this belongs to.
49-
MemoryBlock * previousFreeBlock; // pointer to the previous free block in the binned free list that this belongs to.
50-
uint32_t size;
51-
bool isFree;;
52-
};
48+
struct MemoryBlock {
49+
MemoryBlock * nextFreeBlock; // pointer to the next free block in the binned free list that this belongs to.
50+
MemoryBlock * previousFreeBlock; // pointer to the previous free block in the binned free list that this belongs to.
51+
uint32_t size;
52+
bool isFree;;
53+
};
5354

54-
typedef uint32_t MemoryBlockFooter;
55+
typedef uint32_t MemoryBlockFooter;
5556

56-
#define TOTAL_BLOCK_OVERHEAD (sizeof(MemoryBlock) + sizeof(MemoryBlockFooter))
57-
#define BIN_INDEX_THRESHOLD 1024
58-
#define NUM_OF_BINS 150
59-
#define FREE_BLOCK_SPLIT_THRESHOLD 8
60-
#define MEMORY_LOCATION_TO_RETURN(mbptr) ((void *) ((char *)(mbptr) + sizeof(MemoryBlock)))
57+
#define TOTAL_BLOCK_OVERHEAD (sizeof(MemoryBlock) + sizeof(MemoryBlockFooter))
58+
#define BIN_INDEX_THRESHOLD 1024
59+
#define NUM_OF_BINS 150
60+
#define FREE_BLOCK_SPLIT_THRESHOLD 8
61+
#define MEMORY_LOCATION_TO_RETURN(mbptr) ((void *) ((char *)(mbptr) + sizeof(MemoryBlock)))
6162

62-
void * memoryStart; //is always mem_heap_lo
63-
void * endOfHeap;
64-
MemoryBlock * bins[NUM_OF_BINS];
63+
void * memoryStart; //is always mem_heap_lo
64+
void * endOfHeap;
65+
MemoryBlock * bins[NUM_OF_BINS];
66+
pthread_mutex_t globalLock;
67+
pthread_mutexattr_t globalLockAttr;
68+
#define GLOBAL_LOCK pthread_mutex_lock(&globalLock)
69+
#define GLOBAL_UNLOCK pthread_mutex_unlock(&globalLock)
6570

6671
int allocator::check() {
72+
GLOBAL_LOCK;
6773
char *p;
6874
char *lo = (char*)mem_heap_lo();
6975
char *hi = (char*)mem_heap_hi() + 1;
@@ -76,6 +82,7 @@ namespace my {
7682
while (locMB) {
7783
if (!(locMB->isFree)) {
7884
printf("Bin %d contains a non-free memory block\n", i);
85+
GLOBAL_UNLOCK;
7986
return -1;
8087
}
8188
locMB = locMB->nextFreeBlock;
@@ -87,11 +94,13 @@ namespace my {
8794
locMB = bins[i];
8895
if (locMB && locMB->previousFreeBlock != 0) {
8996
printf("Bin %d points to a block whose previousFreeBlock is not 0\n", i);
97+
GLOBAL_UNLOCK;
9098
return -1;
9199
}
92100
while (locMB) {
93101
if (locMB->nextFreeBlock && locMB->nextFreeBlock->previousFreeBlock != locMB) {
94102
printf("Bin %d contains a memory block whose previousFreeBlock does not point to the preceding element of the binned list\n", i);
103+
GLOBAL_UNLOCK;
95104
return -1;
96105
}
97106
locMB = locMB->nextFreeBlock;
@@ -129,21 +138,29 @@ namespace my {
129138
footer = (MemoryBlockFooter *) ((char *) locMB + locMB->size - sizeof(MemoryBlockFooter));
130139
if (locMB->size != *footer) {
131140
printf("Memory space contains a block at %p that does not have a correctly assigned footer\n", locMB);
141+
GLOBAL_UNLOCK;
132142
return -1;
133143
}
134144
}
145+
146+
GLOBAL_UNLOCK;
135147
return 0;
136148
}
137149

138150
// init - Initialize the malloc package. Called once before any other
139151
// calls are made. Since this is a very simple implementation, we just
140152
// return success.
141153
int allocator::init() {
154+
pthread_mutexattr_init(&globalLockAttr);
155+
pthread_mutexattr_settype(&globalLockAttr, PTHREAD_MUTEX_RECURSIVE);
156+
pthread_mutex_init(&globalLock, &globalLockAttr);
157+
GLOBAL_LOCK;
142158
endOfHeap = mem_heap_lo();
143159
memoryStart = endOfHeap;
144160
for (int i = 0; i < NUM_OF_BINS; i++) {
145161
bins[i] = 0;
146162
}
163+
GLOBAL_UNLOCK;
147164
return 0;
148165
}
149166

@@ -229,6 +246,7 @@ namespace my {
229246
// malloc - Allocate a block by incrementing the brk pointer.
230247
// Always allocate a block whose size is a multiple of the alignment.
231248
void * allocator::malloc(size_t size) {
249+
GLOBAL_LOCK;
232250
void * currentLoc;
233251
size_t alignedSize = ALIGN(size + TOTAL_BLOCK_OVERHEAD);
234252
MemoryBlock * currentLocMB;
@@ -246,6 +264,7 @@ namespace my {
246264
currentLocMB->nextFreeBlock = 0;
247265
currentLocMB->previousFreeBlock = 0;
248266
currentLocMB->isFree = false;
267+
GLOBAL_UNLOCK;
249268
return MEMORY_LOCATION_TO_RETURN(currentLoc);
250269
}
251270
currentLocMB = currentLocMB->nextFreeBlock;
@@ -257,6 +276,7 @@ namespace my {
257276
//size_t increase = (alignedSize < 496)? 512: alignedSize;
258277
void *p = mem_sbrk(alignedSize); // increase
259278
if (p == (void *) -1) {
279+
GLOBAL_UNLOCK;
260280
return NULL;
261281
}
262282
currentLoc = endOfHeap;
@@ -267,10 +287,12 @@ namespace my {
267287
currentLocMB->size = alignedSize;
268288
currentLocMB->isFree = false;
269289
assignBlockFooter(currentLocMB);
290+
GLOBAL_UNLOCK;
270291
return MEMORY_LOCATION_TO_RETURN(currentLoc);
271292
}
272293

273294
void allocator::free(void *ptr) {
295+
GLOBAL_LOCK;
274296
//std::cout<<"\n\nAsked to free space at "<<ptr;
275297
MemoryBlock * mb;
276298
mb = (MemoryBlock *) ((char *) ptr - sizeof(MemoryBlock));
@@ -323,10 +345,12 @@ namespace my {
323345
*/
324346
}
325347
assignBlockToBinnedList(mb);
348+
GLOBAL_UNLOCK;
326349
}
327350

328351
// realloc - Implemented simply in terms of malloc and free
329352
void * allocator::realloc(void *ptr, size_t size) {
353+
GLOBAL_LOCK;
330354
// std::cout<<"\n\nAsked to reallocate block at "<<ptr;
331355
MemoryBlock * mb = (MemoryBlock *) ((char *) ptr - sizeof(MemoryBlock));
332356
// std::cout<<" that had an internal size of "<<mb->size - TOTAL_BLOCK_OVERHEAD<<", an aligned size (incl. overhead) of "<<mb->size<<", and a new requested size of "<<size;
@@ -338,6 +362,7 @@ namespace my {
338362
truncateMemoryBlock(mb, alignedSize);
339363
// std::cout<<"\nReallocated by truncating to aligned size. \nNew state of memory: ";
340364
// printStateOfMemory();
365+
GLOBAL_UNLOCK;
341366
return MEMORY_LOCATION_TO_RETURN(mb);
342367
}
343368
if (alignedSize > mb->size) {
@@ -349,23 +374,27 @@ namespace my {
349374
truncateMemoryBlock(mb, alignedSize);
350375
// std::cout<<"\nReallocated by using adjacent free block on right. \nNew state of memory: ";
351376
// printStateOfMemory();
377+
GLOBAL_UNLOCK;
352378
return MEMORY_LOCATION_TO_RETURN(mb);
353379
}
354380
else {
355381
void * newptr = malloc(size);
356382
if (!newptr) {
383+
GLOBAL_UNLOCK;
357384
return NULL;
358385
}
359386
size_t copy_size = mb->size - TOTAL_BLOCK_OVERHEAD; // internal size of the original memory block
360387
copy_size = (size < copy_size)? size : copy_size; // if the new size is less that the original internal size, we MUST NOT copy more than new size bytes to the new block
361388
std::memcpy(newptr, ptr, copy_size);
362389
free(ptr);
363390
// std::cout<<"\nReallocated by calling malloc and free. Had to copy "<<copy_size<<" bytes using memcpy. \nNew state of memory: ";
364-
// printStateOfMemory();
391+
// printStateOfMemory();
392+
GLOBAL_UNLOCK;
365393
return newptr;
366394
}
367395
}
368396
// std::cout<<"\nReturning original pointer as new alignedSize == original aligned size of memory block.";
397+
GLOBAL_UNLOCK;
369398
return ptr;
370399
}
371400

0 commit comments

Comments
 (0)