Exemple #1
0
void *malloc(size_t size)
{
    register PACKET *current;
    register size_t  newsize;
    register size_t  oldsize;

    if (size <= 0) return NULL;

    if (check_alloc_size(size) == 0) return 0;

    if (need_mem_init)  minit();

    _lock();

    /*-----------------------------------------------------------------------*/
    /* SIZE IS CALCULATED BY FIRST ALIGNING (SIZE + BLOCK OVERHEAD) TO THE   */
    /* REQUIRED MINIMUM ALIGNMENT AND THEN SUBTRACTING THE BLOCK OVERHEAD.   */
    /*-----------------------------------------------------------------------*/
    newsize = _M_RNDUP((size + _M_BLOCK_OVERHEAD), _M_MIN_ALN) - 
	                                                    _M_BLOCK_OVERHEAD;

    current = sys_free;

    /*-----------------------------------------------------------------------*/
    /* SCAN THROUGH FREE LIST FOR PACKET LARGE ENOUGH TO CONTAIN PACKET      */
    /*-----------------------------------------------------------------------*/
    while (current && current->packet_size < newsize)
       current = current->size_ptr;

    if (!current)
    {
	_unlock();
	return NULL;
    }
    
    oldsize = current->packet_size;	    /* REMEMBER OLD SIZE	     */
    mremove(current);		            /* REMOVE PACKET FROM FREE LIST  */

    /*-----------------------------------------------------------------------*/
    /* IF PACKET IS LARGER THAN NEEDED, FREE EXTRA SPACE AT END	             */
    /* BY INSERTING REMAINING SPACE INTO FREE LIST.			     */
    /*-----------------------------------------------------------------------*/
    if (oldsize - newsize >= (_M_MIN_BLOCK + _M_BLOCK_OVERHEAD))
    {
       register PACKET *next = 
	       (PACKET *) ((char *) current + _M_BLOCK_OVERHEAD + newsize);
 
       next->packet_size    = oldsize - newsize - _M_BLOCK_OVERHEAD;
       minsert(next);
       current->packet_size = newsize;
    }

   current->packet_size |= _M_BLOCK_USED;
   _unlock();
   return (char *)current + _M_BLOCK_OVERHEAD;
}
/**
 * @brief 
 *  移除最后一个元素
 * @param PVector
 *
 * @return 成功返回1,失败返回0
 */
int     remove_back(PVector pv)
{
    return mremove(pv, pv->counter-1);
}
/**
 * @brief 
 *  移除第0个元素
 * @param PVector
 *
 * @return 成功返回1,失败返回0
 */
int     remove_front(PVector pv)
{
    return mremove(pv, 0);
}
Exemple #4
0
void *memalign(size_t alignment, size_t size)
{
    PACKET *aln_packet;
    PACKET *current;
    size_t  newsize;
    size_t  aln_mask = alignment - 1;
    int     leftover = -1;
    char   *aln_start;
    char   *un_aln_start;
 
    if (size <= 0) return NULL;

    if (check_alloc_size(size) == 0) return NULL;
      
    /*--------------------------------------------------------------------*/
    /* IF ALIGNMENT IS NOT A POWER OF TWO OR IS LESS THAN THE DEFAULT     */
    /* ALIGNMENT OF MALLOC, THEN SIMPLY RETURN WHAT MALLOC RETURNS.       */
    /*--------------------------------------------------------------------*/
    if (alignment <= _M_MIN_ALN || (alignment & (alignment-1)))
	  return malloc(size);

    if (need_mem_init)  minit();

    _lock();

    newsize = _M_RNDUP((size + _M_BLOCK_OVERHEAD), _M_MIN_ALN) - 
	                                                    _M_BLOCK_OVERHEAD;

    current = sys_free;

    /*-----------------------------------------------------------------------*/
    /* SCAN THROUGH FREE LIST FOR PACKET LARGE ENOUGH TO CONTAIN ALIGNED     */
    /* PACKET                                                                */
    /*-----------------------------------------------------------------------*/
    for ( ; current ; current = current->size_ptr)
    {
       un_aln_start = (char *) current + _M_BLOCK_OVERHEAD;
       /*--------------------------------------------------------------------*/
       /* IT IS POSSIBLE THAT WE COULD OVERFLOW THE size_t TYPE BELOW, BUT   */
       /* ADDING A CHECK HERE WOULD LIKELY BE A SIGNIFICANT PERFORMANCE HIT. */
       /*--------------------------------------------------------------------*/
       aln_start    = (char *)(((size_t) un_aln_start + aln_mask) & ~aln_mask);
       leftover     = un_aln_start + current->packet_size - aln_start -newsize;

       /*--------------------------------------------------------------------*/
       /* MAKE SURE THAT THE PRE BLOCK SPACE IS LARGE ENOUGH TO BE A BLOCK   */
       /* OF ITS OWN.                                                        */
       /*--------------------------------------------------------------------*/
       for ( ; (char *)current+sizeof(PACKET) > aln_start-_M_BLOCK_OVERHEAD ;
	       aln_start += alignment, leftover -= alignment);

       if (leftover >= 0) break;
    }

    if (!current) { _unlock(); return NULL; }

    /*-----------------------------------------------------------------------*/
    /* SETUP NEW PACKET FOR ALIGNED MEMORY.                                  */
    /*-----------------------------------------------------------------------*/
    mremove(current);
    aln_packet              = (PACKET *) (aln_start - _M_BLOCK_OVERHEAD);
    aln_packet->packet_size = newsize | _M_BLOCK_USED;

    /*-----------------------------------------------------------------------*/
    /* HANDLE THE FREE SPACE BEFORE THE ALIGNED BLOCK.  IF THE ORIGINAL      */
    /* BLOCK WAS ALIGNED, THERE WON'T BE FREE SPACE BEFORE THE ALIGNED BLOCK.*/
    /*-----------------------------------------------------------------------*/
    if (aln_start != un_aln_start) 
    {
	current->packet_size = (char *)aln_packet - un_aln_start;
	minsert(current);
    }

    /*-----------------------------------------------------------------------*/
    /* HANDLE THE FREE SPACE AFTER THE ALIGNED BLOCK. IF IT IS LARGE ENOUGH  */
    /* TO BE A BLOCK OF ITS OWN, THEN MAKE IT ONE, OTHERWISE ADD THE         */
    /* LEFTOVER SIZE TO THE ALIGNED BLOCK.                                   */ 
    /*-----------------------------------------------------------------------*/ 
    if (leftover >= _M_BLOCK_OVERHEAD + _M_MIN_BLOCK)
    {
       register PACKET *next = (PACKET *) (aln_start + newsize);
       next->packet_size     = leftover - _M_BLOCK_OVERHEAD;
       minsert(next);
    }
    else aln_packet->packet_size += leftover;

    _unlock();
    return aln_start;
}
Exemple #5
0
void free(void *packet)
{
    register char   *ptr = (char *)packet;
    register PACKET *last;	      /* POINT TO PREVIOUS PACKET            */
    register PACKET *current;	      /* POINTER TO THIS PACKET              */
    register PACKET *next;	      /* POINTER TO NEXT PACKET              */

    if (ptr == NULL) return;

    last = next = NULL;		      /* INITIALIZE POINTERS                 */
    ptr -= _M_BLOCK_OVERHEAD;	      /* ADJUST POINT TO BEGINNING OF PACKET */

    if (need_mem_init)  minit();

    _lock();

    current = _M_SYS_FIRST;

    /*-----------------------------------------------------------------------*/
    /* SEARCH FOR THE POINTER IN THE PACKET POINTED TO			     */
    /*-----------------------------------------------------------------------*/
    while (current < (PACKET *) ptr)
    {
        last    = current;
        current = (PACKET *)((char *)current + 
		  (current->packet_size & ~_M_BLOCK_USED) + _M_BLOCK_OVERHEAD);
    }

    /*-----------------------------------------------------------------------*/
    /* CHECK FOR POINTER OR PACKET ERRORS.				     */
    /*-----------------------------------------------------------------------*/
    if ((current != (PACKET *)ptr) || (!(current->packet_size & _M_BLOCK_USED)))
    {
	 _unlock();
         return;
    }

    current->packet_size &= ~_M_BLOCK_USED;   /* MARK PACKET AS FREE */

    /*-----------------------------------------------------------------------*/
    /* GET POINTER TO NEXT PACKET IN MEMORY, IF ANY.			     */
    /*-----------------------------------------------------------------------*/
    next = (PACKET *)((char *)current + _M_BLOCK_OVERHEAD + 
	                                             current->packet_size);
    if (next > (PACKET *) &heap_mem[_memory_size - _M_BLOCK_OVERHEAD]) 
	next = NULL;

    if (last && last->packet_size & _M_BLOCK_USED) last = NULL;
    if (next && next->packet_size & _M_BLOCK_USED) next = NULL;

    /*-----------------------------------------------------------------------*/
    /* ATTEMPT TO COLLESCE THE THREE PACKETS (PREVIOUS, CURRENT, NEXT)	     */
    /*-----------------------------------------------------------------------*/
    if (last && next)
    {
	mremove(last);
	mremove(next);
	last->packet_size += current->packet_size + next->packet_size + 
			     _M_BLOCK_OVERHEAD + _M_BLOCK_OVERHEAD;
	minsert(last);
	_unlock();
	return;
    }

    /*-----------------------------------------------------------------------*/
    /* ATTEMPT TO COLLESCE THE CURRENT WITH LAST PACKET. (LAST, CURRENT)     */
    /*-----------------------------------------------------------------------*/
    if (last)
    {
	mremove(last);
	last->packet_size += current->packet_size + _M_BLOCK_OVERHEAD;
	minsert(last);
	_unlock();
	return;
    }

    /*-----------------------------------------------------------------------*/
    /* ATTEMPT TO COLLESCE THE CURRENT WITH NEXT PACKET. (CURRENT, NEXT)     */
    /*-----------------------------------------------------------------------*/
    if (next)
    {
       mremove(next);
       current->packet_size += next->packet_size + _M_BLOCK_OVERHEAD;
       minsert(current);
	_unlock();
       return;
    }

    /*-----------------------------------------------------------------------*/
    /* NO COLLESCENCE POSSIBLE, JUST INSERT THIS PACKET INTO LIST	     */
    /*-----------------------------------------------------------------------*/
    minsert(current);
    _unlock();
}
Exemple #6
0
void *realloc(void *packet, size_t size)
{
    register char    *pptr    = (char *) packet - _M_BLOCK_OVERHEAD;
    register size_t   newsize;
    register size_t   oldsize;

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

    if (check_alloc_size(size) == 0) return 0;

    if (need_mem_init)  minit();

    _lock();

    /*-----------------------------------------------------------------------*/
    /* NEW SIZE IS CALCULATED BY FIRST ALIGNING (SIZE+BLOCK OVERHEAD) TO THE */
    /* REQUIRED MINIMUM ALIGNMENT AND THEN SUBTRACTING THE BLOCK OVERHEAD.   */
    /*-----------------------------------------------------------------------*/
    newsize = _M_RNDUP((size + _M_BLOCK_OVERHEAD), _M_MIN_ALN) - 
	                                                    _M_BLOCK_OVERHEAD;

    oldsize = ((PACKET *)pptr)->packet_size;

    if (!(oldsize & _M_BLOCK_USED)) { _unlock(); return NULL; }
    if (newsize == --oldsize)       { _unlock(); return packet; }

    /*-----------------------------------------------------------------------*/
    /* IF NEW SIZE IS LESS THAN CURRENT SIZE, TRUNCATE PACKET AND RETURN END */
    /* TO FREE LIST		                                             */
    /*-----------------------------------------------------------------------*/
    if (newsize < oldsize)
    {
       if (oldsize - newsize < (_M_MIN_BLOCK + _M_BLOCK_OVERHEAD))
       {
	  _unlock();
	  return packet;
       }
       ((PACKET *)pptr)->packet_size = newsize | _M_BLOCK_USED;

       oldsize -= newsize + _M_BLOCK_OVERHEAD;
       pptr    += newsize + _M_BLOCK_OVERHEAD;
       ((PACKET *)pptr)->packet_size = oldsize | _M_BLOCK_USED;
       free(pptr + _M_BLOCK_OVERHEAD);
       _unlock();
       return packet;
    }

    /*-----------------------------------------------------------------------*/
    /* IF NEW SIZE IS BIGGER THAN CURRENT PACKET,		             */
    /*	1) CHECK NEXT PACKET IN LIST, SEE IF PACKET CAN BE EXPANDED          */
    /*	2) IF NOT, MOVE PACKET TO NEW LOCATION. 		             */
    /*-----------------------------------------------------------------------*/
    else
    {
	PACKET *next = (PACKET *)(pptr + oldsize + _M_BLOCK_OVERHEAD);
	int     temp;

	if (((char *)next < &heap_mem[_memory_size - _M_BLOCK_OVERHEAD]) &&
           (!(next->packet_size & _M_BLOCK_USED))                        &&
           ((temp = oldsize + next->packet_size +_M_BLOCK_OVERHEAD - newsize) 
	                                                      >= 0))
	{
	    mremove(next);
	    if (temp < _M_MIN_BLOCK + _M_BLOCK_OVERHEAD)
	    {
	       ((PACKET *)pptr)->packet_size = newsize + temp | _M_BLOCK_USED;
	       _unlock();
	       return packet;
	    }

	    ((PACKET *)pptr)->packet_size = newsize | _M_BLOCK_USED;
	    pptr += newsize + _M_BLOCK_OVERHEAD;
	    ((PACKET *)pptr)->packet_size = temp - _M_BLOCK_OVERHEAD;
	    minsert((PACKET *)pptr);
	    _unlock();
	    return packet;
	}
	else
	{
            /*---------------------------------------------------------------*/
	    /* ALLOCATE NEW PACKET AND MOVE DATA INTO IT. 	             */
            /*---------------------------------------------------------------*/
	    register char *new_packet = (char *)malloc(size);
	    if (new_packet == 0) { _unlock(); return NULL; }
	    memcpy(new_packet, packet, oldsize);
	    free(packet);
	    _unlock();
	    return new_packet;
	}
    }
}