/* * Freeing memory from the small heap */ void SH_free(void *mem) { //First check if memory was allocated using malloc() void * adr = listGetMallocedMemoryAdr(mallocList, mem); if (adr != NULL ) { free(adr); // Memory was allocated using malloc(), use free instead listRemove(mallocList, adr); // Remove address from the list return; } // Memory was not allocated by using malloc, find which small heap it was put into. //struct shMapType * shMapEntry = listGetMemoryLocation(SHList, pthread_self()); // changed to extract allocator's thread_id from mem header rather than by using pthread_self() void *ptr = mem - sizeof(SHMemHeaderStruct); SHMemHeader header = (SHMemHeader) ptr; struct shMapType * shMapEntry = listGetMemoryLocation(SHList, header->thread_id); my_mutex_lock(&shMapEntry->mutex); unsigned int toFree; // Pointer to block that needs to be freed unsigned int cur, prev; toFree = ((unsigned int *) ptr - (shMapEntry->memArea + 1)); if (toFree < shMapEntry->available) { // If block, that is being freed is before the first free block if (((refToNextBlock(toFree, shMapEntry->memArea) + 1) == shMapEntry->available) && shMapEntry->available < shMapEntry->memAreaSize) // If next free block is immediately after block that is being freed shMapEntry->memArea[toFree] += (shMapEntry->memArea[shMapEntry->available] + 1); // Defragmentation of free space else shMapEntry->memArea[refToNextBlock(toFree, shMapEntry->memArea)] = shMapEntry->available; shMapEntry->available = toFree; } else { // If block, that is being freed isn't before the first free block prev = cur = shMapEntry->available; while (cur < toFree) { prev = cur; cur = nextBlock(cur, shMapEntry->memArea); } if ((refToNextBlock(prev, shMapEntry->memArea) + 1) == toFree) { // If previous free block is immediately before block that is being freed shMapEntry->memArea[prev] += (shMapEntry->memArea[toFree] + 1); // Defragmentation of free space if (((refToNextBlock(toFree, shMapEntry->memArea) + 1) == cur) && cur < shMapEntry->memAreaSize) // If next free block is immediately after block that is being freed shMapEntry->memArea[prev] += (shMapEntry->memArea[cur] + 1); // Defragmentation of free space else shMapEntry->memArea[refToNextBlock(toFree, shMapEntry->memArea)] = cur; } else { shMapEntry->memArea[refToNextBlock(prev, shMapEntry->memArea)] = toFree; shMapEntry->memArea[refToNextBlock(toFree, shMapEntry->memArea)] = cur; } } // jonl changed following line as NULL is incorrect, however, it is unclear what it shouldbe //log_into_file("freed from", ptr, NULL ); log_into_file("freed from", ptr, 0 ); my_mutex_unlock(&shMapEntry->mutex); }
/* LockCorrectness: Tests correct implementation of the lock Parameters: parameters: A structure of type ThreadParameters_t with parameters Return Value: */ void * LockCorrectness( void *parameters ) { // ----------------------- Local Variables ------------------ int i; int localN; // On the stack for performance. int tmp; int j; int expectedresult; int delaysteps; ThreadParameters_t *par; // ---------------------- Initialization ------------------------- par = ( ThreadParameters_t * ) parameters; localN = gN*30; gTestVariable = 0; gCounter = 0; my_barrier_wait( &gBarrier ); // ---------------------- Run Tests ------------------------- for ( i = 0; i < localN; i++ ) { my_mutex_lock( &gMutex ); tmp = gTestVariable; delaysteps = rand() % DELAYNUM; for ( j = 0; j < delaysteps; j++ ) { tmp += gZero; } tmp++; gTestVariable = tmp; my_mutex_unlock( &gMutex ); } // ---------------------- Barrier wait ------------------------- my_barrier_wait( &gBarrier ); // ----------------------- Check for sucess --------------------- expectedresult = localN * gP; if ( gTestVariable != expectedresult ) { return( NULL ); } return( ( void * ) 1 ); }
void * thread_routine_2(void * arg) { int tmp; my_thread_start(); my_mutex_lock(&B); printf("thread 2 : lock (B)\n"); my_obj_read(&data2); tmp = data2; my_mutex_lock(&A); printf("thread 2 : lock (A)\n"); my_obj_write(&data1); data1 = tmp-1; my_mutex_unlock(&A); printf("thread 2 : unlock (A)\n"); my_mutex_unlock(&B); printf("thread 2 : unlock (B)\n"); my_thread_end(); return 0; }
void * thread_routine_2(void * arg) { int tmp; my_thread_start(); my_mutex_lock(&B); printf("thread 2 : lock (B)\n"); my_obj_read(&data); tmp = data; my_mutex_unlock(&B); printf("thread 2 : unlock (B)\n"); my_thread_end(); return 0; }
void * thread_routine_3(void * arg) { int tmp; my_thread_start(); my_mutex_lock(&C); printf("thread 1 : lock (A)\n"); my_obj_write(&data); data = tmp+1; my_mutex_unlock(&C); printf("thread 1 : unlock (A)\n"); my_thread_end(); return 0; }
/* LockPerformance: Tests the performance of a single lock, with no writings or readings. Parameters: parameters: A structure of type ThreadParameters_t with parameters Return Value: This test always succeeds. It always returns 1. */ void * LockPerformance( void *parameters ) { // ----------------------- Local Variables ------------------ int i; int localN; // On the stack for performance. int j; ThreadParameters_t *par; // ---------------------- Initialization ------------------------- par = ( ThreadParameters_t * ) parameters; localN = gN*15; my_barrier_wait( &gBarrier ); // ---------------------- Run Tests ------------------------- for ( j = 0; j < 10; j++ ) { my_barrier_wait( &gBarrier ); for ( i = 0; i < localN; i++ ) { my_mutex_lock( &gMutex ); my_mutex_unlock( &gMutex ); } } // ---------------------- Barrier wait ------------------------- my_barrier_wait( &gBarrier ); // ----------------------- Always return success --------------------- return( ( void * ) 1 ); }
void * thread_routine_1(void * arg) { int tmp; my_thread_start(); my_mutex_lock(&A); printf("thread 1 : lock (A)\n"); my_obj_read(&data1); tmp = data1; my_obj_write(&data2); data2 = tmp+1; my_mutex_unlock(&A); printf("thread 1 : unlock (A)\n"); my_thread_end(); return 0; }
/* * Allocator of memory, allocates into the specified small heap */ void *SH_alloc_at_base(unsigned int data_size, struct shMapType * shMapEntry) { if (data_size == 0) { // Return NULL pointer after attempt to allocate 0-length memory return NULL ; } my_mutex_lock(&shMapEntry->mutex); // changed to deal with sh memory header containing the allocator's thread_id unsigned int size = data_size + sizeof(SHMemHeaderStruct); unsigned int num = size / sizeof(unsigned int); if (size % sizeof(unsigned int) > 0) num++; unsigned int cur, prev; // Index of the current block, previous block unsigned int isFirstFreeBeingAllocated = 1; // Whether the first free block is being allocated prev = cur = shMapEntry->available; // Check if we have enough free space for allocation test: if (shMapEntry->available == shMapEntry->memAreaSize) { // If we are on the end of the memory return NULL ; } if (blockSize(cur, shMapEntry->memArea) < num) { // If the size of free block is lower than requested isFirstFreeBeingAllocated = 0; prev = cur; if (nextBlock(cur, shMapEntry->memArea) == shMapEntry->memAreaSize) { // If not enough memory return NULL ; } else cur = nextBlock(cur, shMapEntry->memArea); goto test; } if (blockSize(cur, shMapEntry->memArea) == num) { // If the size of free block is equal to requested if (isFirstFreeBeingAllocated) shMapEntry->available = nextBlock(cur, shMapEntry->memArea); else shMapEntry->memArea[refToNextBlock(prev, shMapEntry->memArea)] = nextBlock(cur, shMapEntry->memArea); } else { // If the size of free block is greater than requested if (isFirstFreeBeingAllocated) { if ((blockSize(cur, shMapEntry->memArea) - num) == 1) // If there is only 1 free item left from this (previously) free block shMapEntry->available = nextBlock(cur, shMapEntry->memArea); else shMapEntry->available = cur + num + 1; } else { if ((blockSize(cur, shMapEntry->memArea) - num) == 1) // If there is only 1 free item left from this (previously) free block shMapEntry->memArea[refToNextBlock(prev, shMapEntry->memArea)] = nextBlock(cur, shMapEntry->memArea); else shMapEntry->memArea[refToNextBlock(prev, shMapEntry->memArea)] = cur + num + 1; } if ((blockSize(cur, shMapEntry->memArea) - num) == 1) // If there is only 1 free item left from this (previously) free block shMapEntry->memArea[cur] = num + 1; else { shMapEntry->memArea[cur + num + 1] = blockSize(cur, shMapEntry->memArea) - num - 1; shMapEntry->memArea[cur] = num; } } log_into_file("allocated at", (void *) &(shMapEntry->memArea[cur + 1]), size); // Log into a file, if required. // return (void *) &(shMapEntry->memArea[cur + 1]); // change to deal with mem header recording the allocator's thread_id char *new_base = (char *) &(shMapEntry->memArea[cur + 1]); SHMemHeader header = (SHMemHeader) new_base; header->thread_id = shMapEntry->thread_id; my_mutex_unlock(&shMapEntry->mutex); return (void *) ( new_base + sizeof(SHMemHeaderStruct)); }