void*   realloc(void *p, uint64_t size)
{
	void *ptr;
	struct boundary_tag *tag;
	int real_size;

	if ( size == 0 )
	{
		free( p );
		return NULL;
	}
	if ( p == NULL ) return malloc( size );

	liballoc_lock();		// lockit
	tag = (struct boundary_tag*)((unsigned int)p - sizeof( struct boundary_tag ));
	real_size = tag->size;
	liballoc_unlock();

	if ( real_size > size ) real_size = size;

	ptr = malloc( size );
	liballoc_memcpy( ptr, p, real_size );
	free( p );

	return ptr;
}
示例#2
0
void*   realloc(void *p, size_t size)
{
    void *ptr;
    struct liballoc_minor *min;
    int real_size;

    if ( size == 0 )
    {
        free( p );
        return NULL;
    }
    if ( p == NULL ) return malloc( size );

    if ( liballoc_lock != NULL ) liballoc_lock();		// lockit
    min = (struct liballoc_minor*)((unsigned int)p - sizeof( struct liballoc_minor ));
    real_size = min->size;
    if ( liballoc_unlock != NULL ) liballoc_unlock();

    if ( real_size > size ) real_size = size;

    ptr = malloc( size );
    liballoc_memcpy( ptr, p, real_size );
    free( p );

    return ptr;
}
示例#3
0
void free(void *ptr)
{
    struct liballoc_minor *min;
    struct liballoc_major *maj;

    if ( ptr == NULL ) return;


    if ( liballoc_lock != NULL ) liballoc_lock();		// lockit

    min = (struct liballoc_minor*)((unsigned int)ptr - sizeof( struct liballoc_minor ));


    if ( min->magic != LIBALLOC_MAGIC )
    {
        // being lied to...
        if ( liballoc_unlock != NULL ) liballoc_unlock();		// release the lock
        return;
    }

    maj = min->block;

    maj->usage -= (min->size + sizeof( struct liballoc_minor ));
    min->magic  = 0;		// No mojo.

    if ( min->next != NULL ) min->next->prev = min->prev;
    if ( min->prev != NULL ) min->prev->next = min->next;

    if ( min->prev == NULL ) maj->first = min->next;
    // Might empty the block. This was the first
    // minor.


    // We need to clean up after the majors now....

    if ( maj->first == NULL )	// Block completely unused.
    {
        if ( l_memRoot == maj ) l_memRoot = maj->next;
        if ( maj->prev != NULL ) maj->prev->next = maj->next;
        if ( maj->next != NULL ) maj->next->prev = maj->prev;
        liballoc_free( maj, maj->pages * l_pageSize );
    }

    if ( liballoc_unlock != NULL ) liballoc_unlock();		// release the lock
}
示例#4
0
void*   PREFIX(realloc)(void *p, size_t size)
{
	void *ptr;
	struct liballoc_minor *min;
	unsigned int real_size;

	// Honour the case of size == 0 => free old and return NULL
	if ( size == 0 )
	{
		PREFIX(free)( p );
		return NULL;
	}

	// In the case of a NULL pointer, return a simple malloc.
	if ( p == NULL ) return PREFIX(malloc)( size );

	// Unalign the pointer if required.
	ptr = p;
	UNALIGN(ptr);

	liballoc_lock();		// lockit

		min = (struct liballoc_minor*)((uintptr_t)ptr - sizeof( struct liballoc_minor ));

		// Ensure it is a valid structure.
		if ( min->magic != LIBALLOC_MAGIC )
		{
			l_errorCount += 1;

			// Check for overrun errors. For all bytes of LIBALLOC_MAGIC
			if (
				((min->magic & 0xFFFFFF) == (LIBALLOC_MAGIC & 0xFFFFFF)) ||
				((min->magic & 0xFFFF) == (LIBALLOC_MAGIC & 0xFFFF)) ||
				((min->magic & 0xFF) == (LIBALLOC_MAGIC & 0xFF))
			   )
			{
				l_possibleOverruns += 1;
				#if defined DEBUG || defined INFO
				serial_printf( "liballoc: ERROR: Possible 1-3 byte overrun for magic %x != %x\n",
									min->magic,
									LIBALLOC_MAGIC );
				FLUSH();
				#endif
			}


			if ( min->magic == LIBALLOC_DEAD )
			{
				#if defined DEBUG || defined INFO
				serial_printf( "liballoc: ERROR: multiple PREFIX(free)() attempt on %x from %x.\n",
										ptr,
										__builtin_return_address(0) );
				FLUSH();
				#endif
			}
			else
			{
				#if defined DEBUG || defined INFO
				serial_printf( "liballoc: ERROR: Bad PREFIX(free)( %x ) called from %x\n",
									ptr,
									__builtin_return_address(0) );
				FLUSH();
				#endif
			}

			// being lied to...
			liballoc_unlock();		// release the lock
			return NULL;
		}

		// Definitely a memory block.

		real_size = min->req_size;

		if ( real_size >= size )
		{
			min->req_size = size;
			liballoc_unlock();
			return p;
		}

	liballoc_unlock();

	// If we got here then we're reallocating to a block bigger than us.
	ptr = PREFIX(malloc)( size );					// We need to allocate new memory
	liballoc_memcpy( ptr, p, real_size );
	PREFIX(free)( p );

	return ptr;
}
示例#5
0
void PREFIX(free)(void *ptr)
{
	struct liballoc_minor *min;
	struct liballoc_major *maj;

	if ( ptr == NULL )
	{
		l_warningCount += 1;
		#if defined DEBUG || defined INFO
		serial_printf( "liballoc: WARNING: PREFIX(free)( NULL ) called from %x\n",
							__builtin_return_address(0) );
		FLUSH();
		#endif
		return;
	}

	UNALIGN( ptr );

	liballoc_lock();		// lockit


	min = (struct liballoc_minor*)((uintptr_t)ptr - sizeof( struct liballoc_minor ));


	if ( min->magic != LIBALLOC_MAGIC )
	{
		l_errorCount += 1;

		// Check for overrun errors. For all bytes of LIBALLOC_MAGIC
		if (
			((min->magic & 0xFFFFFF) == (LIBALLOC_MAGIC & 0xFFFFFF)) ||
			((min->magic & 0xFFFF) == (LIBALLOC_MAGIC & 0xFFFF)) ||
			((min->magic & 0xFF) == (LIBALLOC_MAGIC & 0xFF))
		   )
		{
			l_possibleOverruns += 1;
			#if defined DEBUG || defined INFO
			serial_printf( "liballoc: ERROR: Possible 1-3 byte overrun for magic %x != %x\n",
								min->magic,
								LIBALLOC_MAGIC );
			FLUSH();
			#endif
		}


		if ( min->magic == LIBALLOC_DEAD )
		{
			#if defined DEBUG || defined INFO
			serial_printf( "liballoc: ERROR: multiple PREFIX(free)() attempt on %x from %x.\n",
									ptr,
									__builtin_return_address(0) );
			FLUSH();
			#endif
		}
		else
		{
			#if defined DEBUG || defined INFO
			serial_printf( "liballoc: ERROR: Bad PREFIX(free)( %x ) called from %x\n",
								ptr,
								__builtin_return_address(0) );
			FLUSH();
			#endif
		}

		// being lied to...
		liballoc_unlock();		// release the lock
		return;
	}

	#ifdef DEBUG
	serial_printf( "liballoc: %x PREFIX(free)( %x ): ",
				__builtin_return_address( 0 ),
				ptr );
	FLUSH();
	#endif


		maj = min->block;

		l_inuse -= min->size;

		maj->usage -= (min->size + sizeof( struct liballoc_minor ));
		min->magic  = LIBALLOC_DEAD;		// No mojo.

		if ( min->next != NULL ) min->next->prev = min->prev;
		if ( min->prev != NULL ) min->prev->next = min->next;

		if ( min->prev == NULL ) maj->first = min->next;
							// Might empty the block. This was the first
							// minor.


	// We need to clean up after the majors now....

	if ( maj->first == NULL )	// Block completely unused.
	{
		if ( l_memRoot == maj ) l_memRoot = maj->next;
		if ( l_bestBet == maj ) l_bestBet = NULL;
		if ( maj->prev != NULL ) maj->prev->next = maj->next;
		if ( maj->next != NULL ) maj->next->prev = maj->prev;
		l_allocated -= maj->size;

		liballoc_free( maj, maj->pages );
	}
	else
	{
		if ( l_bestBet != NULL )
		{
			int bestSize = l_bestBet->size  - l_bestBet->usage;
			int majSize = maj->size - maj->usage;

			if ( majSize > bestSize ) l_bestBet = maj;
		}

	}


	#ifdef DEBUG
	serial_printf( "OK\n");
	FLUSH();
	#endif

	liballoc_unlock();		// release the lock
}
示例#6
0
void *PREFIX(malloc)(size_t req_size)
{
	int startedBet = 0;
	unsigned long long bestSize = 0;
	void *p = NULL;
	uintptr_t diff;
	struct liballoc_major *maj;
	struct liballoc_minor *min;
	struct liballoc_minor *new_min;
	unsigned long size = req_size;

	// For alignment, we adjust size so there's enough space to align.
	if ( ALIGNMENT > 1 )
	{
		size += ALIGNMENT + ALIGN_INFO;
	}
				// So, ideally, we really want an alignment of 0 or 1 in order
				// to save space.

	liballoc_lock();

	if ( size == 0 )
	{
		l_warningCount += 1;
		#if defined DEBUG || defined INFO
		serial_printf( "liballoc: WARNING: alloc( 0 ) called from %x\n",
							__builtin_return_address(0) );
		FLUSH();
		#endif
		liballoc_unlock();
		return PREFIX(malloc)(1);
	}


	if ( l_memRoot == NULL )
	{
		#if defined DEBUG || defined INFO
		#ifdef DEBUG
		serial_printf( "liballoc: initialization of liballoc " VERSION "\n" );
		#endif
		//atexit( liballoc_dump );
		FLUSH();
		#endif

		// This is the first time we are being used.
		l_memRoot = allocate_new_page( size );
		if ( l_memRoot == NULL )
		{
		  liballoc_unlock();
		  #ifdef DEBUG
		  serial_printf( "liballoc: initial l_memRoot initialization failed\n", p);
		  FLUSH();
		  #endif
		  return NULL;
		}

		#ifdef DEBUG
		serial_printf( "liballoc: set up first memory major %x\n", l_memRoot );
		FLUSH();
		#endif
	}


	#ifdef DEBUG
	serial_printf( "liballoc: %x PREFIX(malloc)( %i ): ",
					__builtin_return_address(0),
					size );
	FLUSH();
	#endif

	// Now we need to bounce through every major and find enough space....

	maj = l_memRoot;
	startedBet = 0;

	// Start at the best bet....
	if ( l_bestBet != NULL )
	{
		bestSize = l_bestBet->size - l_bestBet->usage;

		if ( bestSize > (size + sizeof(struct liballoc_minor)))
		{
			maj = l_bestBet;
			startedBet = 1;
		}
	}

	while ( maj != NULL )
	{
		diff  = maj->size - maj->usage;
										// free memory in the block

		if ( bestSize < diff )
		{
			// Hmm.. this one has more memory then our bestBet. Remember!
			l_bestBet = maj;
			bestSize = diff;
		}


#ifdef USE_CASE1

		// CASE 1:  There is not enough space in this major block.
		if ( diff < (size + sizeof( struct liballoc_minor )) )
		{
			#ifdef DEBUG
			serial_printf( "CASE 1: Insufficient space in block %x\n", maj);
			FLUSH();
			#endif

				// Another major block next to this one?
			if ( maj->next != NULL )
			{
				maj = maj->next;		// Hop to that one.
				continue;
			}

			if ( startedBet == 1 )		// If we started at the best bet,
			{							// let's start all over again.
				maj = l_memRoot;
				startedBet = 0;
				continue;
			}

			// Create a new major block next to this one and...
			maj->next = allocate_new_page( size );	// next one will be okay.
			if ( maj->next == NULL ) break;			// no more memory.
			maj->next->prev = maj;
			maj = maj->next;

			// .. fall through to CASE 2 ..
		}

#endif

#ifdef USE_CASE2

		// CASE 2: It's a brand new block.
		if ( maj->first == NULL )
		{
			maj->first = (struct liballoc_minor*)((uintptr_t)maj + sizeof(struct liballoc_major) );


			maj->first->magic 		= LIBALLOC_MAGIC;
			maj->first->prev 		= NULL;
			maj->first->next 		= NULL;
			maj->first->block 		= maj;
			maj->first->size 		= size;
			maj->first->req_size 	= req_size;
			maj->usage 	+= size + sizeof( struct liballoc_minor );


			l_inuse += size;


			p = (void*)((uintptr_t)(maj->first) + sizeof( struct liballoc_minor ));

			ALIGN( p );

			#ifdef DEBUG
			serial_printf( "CASE 2: returning %x\n", p);
			FLUSH();
			#endif
			liballoc_unlock();		// release the lock
			return p;
		}

#endif

#ifdef USE_CASE3

		// CASE 3: Block in use and enough space at the start of the block.
		diff =  (uintptr_t)(maj->first);
		diff -= (uintptr_t)maj;
		diff -= sizeof(struct liballoc_major);

		if ( diff >= (size + sizeof(struct liballoc_minor)) )
		{
			// Yes, space in front. Squeeze in.
			maj->first->prev = (struct liballoc_minor*)((uintptr_t)maj + sizeof(struct liballoc_major) );
			maj->first->prev->next = maj->first;
			maj->first = maj->first->prev;

			maj->first->magic 	= LIBALLOC_MAGIC;
			maj->first->prev 	= NULL;
			maj->first->block 	= maj;
			maj->first->size 	= size;
			maj->first->req_size 	= req_size;
			maj->usage 			+= size + sizeof( struct liballoc_minor );

			l_inuse += size;

			p = (void*)((uintptr_t)(maj->first) + sizeof( struct liballoc_minor ));
			ALIGN( p );

			#ifdef DEBUG
			serial_printf( "CASE 3: returning %x\n", p);
			FLUSH();
			#endif
			liballoc_unlock();		// release the lock
			return p;
		}

#endif


#ifdef USE_CASE4

		// CASE 4: There is enough space in this block. But is it contiguous?
		min = maj->first;

			// Looping within the block now...
		while ( min != NULL )
		{
				// CASE 4.1: End of minors in a block. Space from last and end?
				if ( min->next == NULL )
				{
					// the rest of this block is free...  is it big enough?
					diff = (uintptr_t)(maj) + maj->size;
					diff -= (uintptr_t)min;
					diff -= sizeof( struct liballoc_minor );
					diff -= min->size;
						// minus already existing usage..

					if ( diff >= (size + sizeof( struct liballoc_minor )) )
					{
						// yay....
						min->next = (struct liballoc_minor*)((uintptr_t)min + sizeof( struct liballoc_minor ) + min->size);
						min->next->prev = min;
						min = min->next;
						min->next = NULL;
						min->magic = LIBALLOC_MAGIC;
						min->block = maj;
						min->size = size;
						min->req_size = req_size;
						maj->usage += size + sizeof( struct liballoc_minor );

						l_inuse += size;

						p = (void*)((uintptr_t)min + sizeof( struct liballoc_minor ));
						ALIGN( p );

						#ifdef DEBUG
						serial_printf( "CASE 4.1: returning %x\n", p);
						FLUSH();
						#endif
						liballoc_unlock();		// release the lock
						return p;
					}
				}



				// CASE 4.2: Is there space between two minors?
				if ( min->next != NULL )
				{
					// is the difference between here and next big enough?
					diff  = (uintptr_t)(min->next);
					diff -= (uintptr_t)min;
					diff -= sizeof( struct liballoc_minor );
					diff -= min->size;
										// minus our existing usage.

					if ( diff >= (size + sizeof( struct liballoc_minor )) )
					{
						// yay......
						new_min = (struct liballoc_minor*)((uintptr_t)min + sizeof( struct liballoc_minor ) + min->size);

						new_min->magic = LIBALLOC_MAGIC;
						new_min->next = min->next;
						new_min->prev = min;
						new_min->size = size;
						new_min->req_size = req_size;
						new_min->block = maj;
						min->next->prev = new_min;
						min->next = new_min;
						maj->usage += size + sizeof( struct liballoc_minor );

						l_inuse += size;

						p = (void*)((uintptr_t)new_min + sizeof( struct liballoc_minor ));
						ALIGN( p );


						#ifdef DEBUG
						serial_printf( "CASE 4.2: returning %x\n", p);
						FLUSH();
						#endif

						liballoc_unlock();		// release the lock
						return p;
					}
				}	// min->next != NULL

				min = min->next;
		} // while min != NULL ...


#endif

#ifdef USE_CASE5

		// CASE 5: Block full! Ensure next block and loop.
		if ( maj->next == NULL )
		{
			#ifdef DEBUG
			serial_printf( "CASE 5: block full\n");
			FLUSH();
			#endif

			if ( startedBet == 1 )
			{
				maj = l_memRoot;
				startedBet = 0;
				continue;
			}

			// we've run out. we need more...
			maj->next = allocate_new_page( size );		// next one guaranteed to be okay
			if ( maj->next == NULL ) break;			//  uh oh,  no more memory.....
			maj->next->prev = maj;

		}

#endif

		maj = maj->next;
	} // while (maj != NULL)



	liballoc_unlock();		// release the lock

	#ifdef DEBUG
	serial_printf( "All cases exhausted. No memory available.\n");
	FLUSH();
	#endif
	#if defined DEBUG || defined INFO
	serial_printf( "liballoc: WARNING: PREFIX(malloc)( %i ) returning NULL.\n", size);
	liballoc_dump();
	FLUSH();
	#endif
	return NULL;
}
void free(void *ptr)
{
	int index;
	struct boundary_tag *tag;

	if ( ptr == NULL ) return;

	liballoc_lock();


		tag = (struct boundary_tag*)((unsigned int)ptr - sizeof( struct boundary_tag ));

		if ( tag->magic != LIBALLOC_MAGIC )
		{
			liballoc_unlock();		// release the lock
			return;
		}



		// MELT LEFT...
		while ( (tag->split_left != NULL) && (tag->split_left->index >= 0) )
		{
			tag = melt_left( tag );
			remove_tag( tag );
		}

		// MELT RIGHT...
		while ( (tag->split_right != NULL) && (tag->split_right->index >= 0) )
		{
			tag = absorb_right( tag );
		}


		// Where is it going back to?
		index = getexp( tag->real_size - sizeof(struct boundary_tag) );
		if ( index < MINEXP ) index = MINEXP;

		// A whole, empty block?
		if ( (tag->split_left == NULL) && (tag->split_right == NULL) )
		{

			if ( l_completePages[ index ] == MAXCOMPLETE )
			{
				// Too many standing by to keep. Free this one.
				unsigned int pages = tag->real_size / l_pageSize;

				if ( (tag->real_size % l_pageSize) != 0 ) pages += 1;
				if ( pages < l_pageCount ) pages = l_pageCount;

				liballoc_free( tag, pages );
				liballoc_unlock();
				return;
			}


			l_completePages[ index ] += 1;	// Increase the count of complete pages.
		}


		// ..........


	insert_tag( tag, index );
	liballoc_unlock();
}
void *malloc(uint64_t size)
{
	int index;
	void *ptr;
	struct boundary_tag *tag = NULL;

	liballoc_lock();

		if ( l_initialized == 0 )
		{
			for ( index = 0; index < MAXEXP; index++ )
			{
				l_freePages[index] = NULL;
				l_completePages[index] = 0;
			}
			l_initialized = 1;
		}

		index = getexp( size ) + MODE;
		if ( index < MINEXP ) index = MINEXP;


		// Find one big enough.
			tag = l_freePages[ index ];				// Start at the front of the list.
			while ( tag != NULL )
			{
					// If there's enough space in this tag.
				if ( (tag->real_size - sizeof(struct boundary_tag))
								>= (size + sizeof(struct boundary_tag) ) )
				{
					break;
				}

				tag = tag->next;
			}


			// No page found. Make one.
			if ( tag == NULL )
			{
				if ( (tag = allocate_new_tag( size )) == NULL )
				{
					liballoc_unlock();
					return NULL;
				}

				index = getexp( tag->real_size - sizeof(struct boundary_tag) );
			}
			else
			{
				remove_tag( tag );

				if ( (tag->split_left == NULL) && (tag->split_right == NULL) )
					l_completePages[ index ] -= 1;
			}

		// We have a free page.  Remove it from the free pages list.

		tag->size = size;

		// Removed... see if we can re-use the excess space.

		unsigned int remainder = tag->real_size - size - sizeof( struct boundary_tag ) * 2; // Support a new tag + remainder

		if ( ((int)(remainder) > 0) /*&& ( (tag->real_size - remainder) >= (1<<MINEXP))*/ )
		{
			int childIndex = getexp( remainder );

			if ( childIndex >= 0 )
			{
				struct boundary_tag *new_tag = split_tag( tag );

				new_tag = new_tag;	// Get around the compiler warning about unused variables.
			}
		}



	ptr = (void*)((unsigned int)tag + sizeof( struct boundary_tag ) );

	liballoc_unlock();
	return ptr;
}
示例#9
0
void *malloc(size_t size)
{
    void *p = NULL;
    unsigned int diff;
    struct liballoc_major *maj;
    struct liballoc_minor *min;
    struct liballoc_minor *new_min;


    if ( liballoc_lock != NULL ) liballoc_lock();

    if ( l_memRoot == NULL )
    {
        // This is the first time we are being used.
        l_memRoot = allocate_new_page( size );
        if ( l_memRoot == NULL )
        {
            if ( liballoc_unlock != NULL ) liballoc_unlock();
            return NULL;
        }
    }

    // Now we need to bounce through every major and find enough space....

    maj = l_memRoot;

    while ( maj != NULL )
    {
        diff  = maj->pages * (l_pageSize) - maj->usage;
        // free memory in the block


        // CASE 1:  There is not enough space in this major block.
        if ( diff < (size + sizeof( struct liballoc_minor )) )
        {
            // Another major block next to this one?
            if ( maj->next != NULL )
            {
                maj = maj->next;		// Hop to that one.
                continue;
            }

            // Create a new major block next to this one and...
            maj->next = allocate_new_page( size );	// next one will be okay.
            if ( maj->next == NULL ) break;			// no more memory.
            maj->next->prev = maj;
            maj = maj->next;
            // .. fall through to CASE 2 ..
        }

        // CASE 2: It's a brand new block.
        if ( maj->first == NULL )
        {
            maj->first = (struct liballoc_minor*)(  (unsigned int)maj + sizeof(struct liballoc_major) );
            maj->first->magic 	= LIBALLOC_MAGIC;
            maj->first->prev 	= NULL;
            maj->first->next 	= NULL;
            maj->first->block 	= maj;
            maj->first->size 	= size;
            maj->usage 			+= size + sizeof( struct liballoc_minor );

            p = (void*)((unsigned int)(maj->first) + sizeof( struct liballoc_minor ));


            if ( liballoc_unlock != NULL ) liballoc_unlock();		// release the lock
            return p;
        }


        // CASE 3: Block in use and enough space at the start of the block.
        diff = (unsigned int)(maj->first) - (unsigned int)maj - sizeof(struct liballoc_major);

        if ( diff >= (size + sizeof(struct liballoc_minor)) )
        {
            // Yes, space in front. Squeeze in.
            maj->first->prev = (struct liballoc_minor*)(  (unsigned int)maj + sizeof(struct liballoc_major) );
            maj->first->prev->next = maj->first;
            maj->first = maj->first->prev;

            maj->first->magic 	= LIBALLOC_MAGIC;
            maj->first->prev 	= NULL;
            maj->first->block 	= maj;
            maj->first->size 	= size;
            maj->usage 			+= size + sizeof( struct liballoc_minor );

            p = (void*)((unsigned int)(maj->first) + sizeof( struct liballoc_minor ));
            if ( liballoc_unlock != NULL ) liballoc_unlock();		// release the lock
            return p;
        }



        // CASE 4: There is enough space in this block. But is it contiguous?
        min = maj->first;

        // Looping within the block now...
        while ( min != NULL )
        {
            // CASE 4.1: End of minors in a block. Space from last and end?
            if ( min->next == NULL )
            {
                // the rest of this block is free...  is it big enough?
                diff = (unsigned int)(maj) + (l_pageSize) * maj->pages;
                diff -= ((unsigned int) min + sizeof( struct liballoc_minor ) + min->size);
                // minus already existing usage..

                if ( diff >= size + sizeof( struct liballoc_minor ) )
                {
                    // yay....
                    min->next = (struct liballoc_minor*)((unsigned int)min + sizeof( struct liballoc_minor ) + min->size);
                    min->next->prev = min;
                    min = min->next;
                    min->next = NULL;
                    min->magic = LIBALLOC_MAGIC;
                    min->block = maj;
                    min->size = size;
                    maj->usage += size + sizeof( struct liballoc_minor );
                    p = (void*)((unsigned int)min + sizeof( struct liballoc_minor ));
                    if ( liballoc_unlock != NULL ) liballoc_unlock();		// release the lock
                    return p;
                }
            }



            // CASE 4.2: Is there space between two minors?
            if ( min->next != NULL )
            {
                // is the difference between here and next big enough?
                diff =  (unsigned int)(min->next) - (unsigned int)min  - sizeof( struct liballoc_minor ) - min->size;
                // minus our existing usage.

                if ( diff >= size + sizeof( struct liballoc_minor ) )
                {
                    // yay......
                    new_min = (struct liballoc_minor*)((unsigned int)min + sizeof( struct liballoc_minor ) + min->size);


                    new_min->magic = LIBALLOC_MAGIC;
                    new_min->next = min->next;
                    new_min->prev = min;
                    new_min->size = size;
                    new_min->block = maj;
                    min->next->prev = new_min;
                    min->next = new_min;
                    maj->usage += size + sizeof( struct liballoc_minor );
                    p = (void*)((unsigned int)new_min + sizeof( struct liballoc_minor ));
                    if ( liballoc_unlock != NULL ) liballoc_unlock();		// release the lock
                    return p;
                }
            }	// min->next != NULL

            min = min->next;
        } // while min != NULL ...


        // CASE 5: Block full! Ensure next block and loop.
        if ( maj->next == NULL )
        {
            // we've run out. we need more...
            maj->next = allocate_new_page( size );		// next one guaranteed to be okay
            if ( maj->next == NULL ) break;			//  uh oh,  no more memory.....
            maj->next->prev = maj;
        }

        maj = maj->next;
    } // while (maj != NULL)


    if ( liballoc_unlock != NULL ) liballoc_unlock();		// release the lock
    return NULL;
}
示例#10
0
void free(void *ptr)
{
	int index;
	struct boundary_tag *tag;

	if ( ptr == NULL ) return;

	liballoc_lock();


		tag = (struct boundary_tag*)((unsigned int)ptr - sizeof( struct boundary_tag ));

		if ( tag->magic != LIBALLOC_MAGIC )
		{
			liballoc_unlock();		// release the lock
			return;
		}



		#ifdef DEBUG
		l_inuse -= tag->size;
		printf("free: %x, %i, %i\n", ptr, (int)l_inuse / 1024, (int)l_allocated / 1024 );
		#endif


		// MELT LEFT...
		while ( (tag->split_left != NULL) && (tag->split_left->index >= 0) )
		{
			#ifdef DEBUG
			printf("Melting tag left into available memory. Left was %i, becomes %i (%i)\n", tag->split_left->real_size, tag->split_left->real_size + tag->real_size, tag->split_left->real_size );
			#endif
			tag = melt_left( tag );
			remove_tag( tag );
		}

		// MELT RIGHT...
		while ( (tag->split_right != NULL) && (tag->split_right->index >= 0) )
		{
			#ifdef DEBUG
			printf("Melting tag right into available memory. This was was %i, becomes %i (%i)\n", tag->real_size, tag->split_right->real_size + tag->real_size, tag->split_right->real_size );
			#endif
			tag = absorb_right( tag );
		}


		// Where is it going back to?
		index = getexp( tag->real_size - sizeof(struct boundary_tag) );
		if ( index < MINEXP ) index = MINEXP;

		// A whole, empty block?
		if ( (tag->split_left == NULL) && (tag->split_right == NULL) )
		{

			if ( l_completePages[ index ] == MAXCOMPLETE )
			{
				// Too many standing by to keep. Free this one.
				unsigned int pages = tag->real_size / l_pageSize;

				if ( (tag->real_size % l_pageSize) != 0 ) pages += 1;
				if ( pages < l_pageCount ) pages = l_pageCount;

				liballoc_free( tag, pages );

				#ifdef DEBUG
				l_allocated -= pages * l_pageSize;
				printf("Resource freeing %x of %i pages\n", tag, pages );
				dump_array();
				#endif

				liballoc_unlock();
				return;
			}


			l_completePages[ index ] += 1;	// Increase the count of complete pages.
		}


		// ..........


		insert_tag( tag, index );

	#ifdef DEBUG
	printf("Returning tag with %i bytes (requested %i bytes), which has exponent: %i\n", tag->real_size, tag->size, index );
	dump_array();
	#endif

	liballoc_unlock();
}
示例#11
0
void *malloc(size_t size)
{
	int index;
	void *ptr;
	struct boundary_tag *tag = NULL;

	liballoc_lock();

		if ( l_initialized == 0 )
		{
			#ifdef DEBUG
			printf("%s\n","liballoc initializing.");
			#endif
			for ( index = 0; index < MAXEXP; index++ )
			{
				l_freePages[index] = NULL;
				l_completePages[index] = 0;
			}
			l_initialized = 1;
		}

		index = getexp( size ) + MODE;
		if ( index < MINEXP ) index = MINEXP;


		// Find one big enough.
			tag = l_freePages[ index ];				// Start at the front of the list.
			while ( tag != NULL )
			{
					// If there's enough space in this tag.
				if ( (tag->real_size - sizeof(struct boundary_tag))
								>= (size + sizeof(struct boundary_tag) ) )
				{
					#ifdef DEBUG
					printf("Tag search found %i >= %i\n",(tag->real_size - sizeof(struct boundary_tag)), (size + sizeof(struct boundary_tag) ) );
					#endif
					break;
				}

				tag = tag->next;
			}


			// No page found. Make one.
			if ( tag == NULL )
			{
				if ( (tag = allocate_new_tag( size )) == NULL )
				{
					liballoc_unlock();
					return NULL;
				}

				index = getexp( tag->real_size - sizeof(struct boundary_tag) );
			}
			else
			{
				remove_tag( tag );

				if ( (tag->split_left == NULL) && (tag->split_right == NULL) )
					l_completePages[ index ] -= 1;
			}

		// We have a free page.  Remove it from the free pages list.

		tag->size = size;

		// Removed... see if we can re-use the excess space.

		#ifdef DEBUG
		printf("Found tag with %i bytes available (requested %i bytes, leaving %i), which has exponent: %i (%i bytes)\n", tag->real_size - sizeof(struct boundary_tag), size, tag->real_size - size - sizeof(struct boundary_tag), index, 1<<index );
		#endif

		unsigned int remainder = tag->real_size - size - sizeof( struct boundary_tag ) * 2; // Support a new tag + remainder

		if ( ((int)(remainder) > 0) /*&& ( (tag->real_size - remainder) >= (1<<MINEXP))*/ )
		{
			int childIndex = getexp( remainder );

			if ( childIndex >= 0 )
			{
				#ifdef DEBUG
				printf("Seems to be splittable: %i >= 2^%i .. %i\n", remainder, childIndex, (1<<childIndex) );
				#endif

				struct boundary_tag *new_tag = split_tag( tag );

				new_tag = new_tag;	// Get around the compiler warning about unused variables.

				#ifdef DEBUG
				printf("Old tag has become %i bytes, new tag is now %i bytes (%i exp)\n", tag->real_size, new_tag->real_size, new_tag->index );
				#endif
			}
		}



	ptr = (void*)((unsigned int)tag + sizeof( struct boundary_tag ) );



	#ifdef DEBUG
	l_inuse += size;
	printf("malloc: %x,  %i, %i\n", ptr, (int)l_inuse / 1024, (int)l_allocated / 1024 );
	dump_array();
	#endif


	liballoc_unlock();
	return ptr;
}