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); }
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; }
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(); }
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; } } }