Beispiel #1
0
/*
 * 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);
}
Beispiel #2
0
/*
	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;
}
Beispiel #6
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;
}
Beispiel #8
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));
}