Переглянути джерело

core: mem - reworked f_malloc free chunks management

- credits to Juha Heinanen for heling with testing
Daniel-Constantin Mierla 10 роки тому
батько
коміт
8cced16d70
2 змінених файлів з 42 додано та 61 видалено
  1. 37 53
      mem/f_malloc.c
  2. 5 8
      mem/f_malloc.h

+ 37 - 53
mem/f_malloc.c

@@ -91,7 +91,8 @@
 	((qm)->free_bitmap[(b)/FM_HASH_BMP_BITS] & (1UL<<((b)%FM_HASH_BMP_BITS)))
 	((qm)->free_bitmap[(b)/FM_HASH_BMP_BITS] & (1UL<<((b)%FM_HASH_BMP_BITS)))
 
 
 
 
-#define fm_is_free(f) ((f)->u.nxt_free)
+#define fm_is_free(f) ((f)->is_free)
+
 /**
 /**
  * \brief Find the first free fragment in a memory block
  * \brief Find the first free fragment in a memory block
  * 
  * 
@@ -158,12 +159,10 @@ inline static int fm_bmp_first_set(struct fm_block* qm, int start)
  * \name Memory manager boundary check pattern
  * \name Memory manager boundary check pattern
  */
  */
 /*@{ */
 /*@{ */
-#ifdef DBG_F_MALLOC
 #define ST_CHECK_PATTERN   0xf0f0f0f0 /** inserted at the beginning */
 #define ST_CHECK_PATTERN   0xf0f0f0f0 /** inserted at the beginning */
 #define END_CHECK_PATTERN1 0xc0c0c0c0 /** inserted at the end       */
 #define END_CHECK_PATTERN1 0xc0c0c0c0 /** inserted at the end       */
 #define END_CHECK_PATTERN2 0xabcdefed /** inserted at the end       */
 #define END_CHECK_PATTERN2 0xabcdefed /** inserted at the end       */
 /*@} */
 /*@} */
-#endif
 
 
 
 
 /**
 /**
@@ -177,26 +176,25 @@ static inline void fm_extract_free(struct fm_block* qm, struct fm_frag* frag)
 
 
 	hash = GET_HASH(frag->size);
 	hash = GET_HASH(frag->size);
 
 
-	if(frag->prv_free) {
-		frag->prv_free->u.nxt_free = frag->u.nxt_free;
+	if(frag->prev_free) {
+		frag->prev_free->next_free = frag->next_free;
 	} else {
 	} else {
-		if(frag->u.nxt_free!=qm->last_frag)
-			qm->free_hash[hash].first = frag->u.nxt_free;
-		else
-			qm->free_hash[hash].first = NULL;
+		qm->free_hash[hash].first = frag->next_free;
 	}
 	}
-	if(frag->u.nxt_free && frag->u.nxt_free!=qm->last_frag) {
-		frag->u.nxt_free->prv_free = frag->prv_free;
+	if(frag->next_free) {
+		frag->next_free->prev_free = frag->prev_free;
 	}
 	}
 
 
+	frag->prev_free = NULL;
+	frag->next_free = NULL;
+	frag->is_free = 0;
+
 	qm->ffrags--;
 	qm->ffrags--;
 	qm->free_hash[hash].no--;
 	qm->free_hash[hash].no--;
 #ifdef F_MALLOC_HASH_BITMAP
 #ifdef F_MALLOC_HASH_BITMAP
 	if (qm->free_hash[hash].no==0)
 	if (qm->free_hash[hash].no==0)
 		fm_bmp_reset(qm, hash);
 		fm_bmp_reset(qm, hash);
 #endif /* F_MALLOC_HASH_BITMAP */
 #endif /* F_MALLOC_HASH_BITMAP */
-	frag->prv_free = NULL;
-	frag->u.nxt_free = NULL;
 
 
 	qm->real_used+=frag->size;
 	qm->real_used+=frag->size;
 	qm->used+=frag->size;
 	qm->used+=frag->size;
@@ -210,55 +208,41 @@ static inline void fm_extract_free(struct fm_block* qm, struct fm_frag* frag)
 static inline void fm_insert_free(struct fm_block* qm, struct fm_frag* frag)
 static inline void fm_insert_free(struct fm_block* qm, struct fm_frag* frag)
 {
 {
 	struct fm_frag* f;
 	struct fm_frag* f;
+	struct fm_frag* p;
 	int hash;
 	int hash;
-	int after;
 	
 	
 	hash=GET_HASH(frag->size);
 	hash=GET_HASH(frag->size);
 	f=qm->free_hash[hash].first;
 	f=qm->free_hash[hash].first;
+	p=NULL;
 	if (frag->size > F_MALLOC_OPTIMIZE){ /* because of '<=' in GET_HASH,
 	if (frag->size > F_MALLOC_OPTIMIZE){ /* because of '<=' in GET_HASH,
 											(different from 0.8.1[24] on
 											(different from 0.8.1[24] on
 											 purpose --andrei ) */
 											 purpose --andrei ) */
-		after = 0;
 		/* large fragments list -- add at a position ordered by size */
 		/* large fragments list -- add at a position ordered by size */
-		for(; f; f=f->u.nxt_free){
+		for(; f; f=f->next_free){
 			if (frag->size <= f->size) break;
 			if (frag->size <= f->size) break;
-			if(f->u.nxt_free==qm->last_frag) {
-				/*size greater than last frag in slot*/
-				after = 1;
-				break;
-			}
+			p = f;
 		}
 		}
 	
 	
+		frag->next_free = f;
+		frag->prev_free = p;
 		if(f) {
 		if(f) {
-			if(after) {
-				/*insert frag after f*/
-				frag->prv_free=f;
-				f->u.nxt_free=frag;
-				frag->u.nxt_free = qm->last_frag;
-			} else {
-				/*insert frag before f*/
-				frag->u.nxt_free = f;
-				frag->prv_free=f->prv_free;
-				if(f->prv_free) f->prv_free->u.nxt_free = frag;
-				if(qm->free_hash[hash].first==f) qm->free_hash[hash].first = frag;
-			}
+			f->prev_free = frag;
+		}
+		if(p) {
+			p->next_free = frag;
 		} else {
 		} else {
-			/* to be only one in slot */
 			qm->free_hash[hash].first = frag;
 			qm->free_hash[hash].first = frag;
-			frag->prv_free=0;
-			frag->u.nxt_free = qm->last_frag;
 		}
 		}
 	} else {
 	} else {
 		/* fixed fragment size list -- add first */
 		/* fixed fragment size list -- add first */
-		frag->prv_free=0;
+		frag->prev_free = 0;
+		frag->next_free = f;
 		if(f) {
 		if(f) {
-			f->prv_free = frag;
-			frag->u.nxt_free = f;
-		} else {
-			frag->u.nxt_free = qm->last_frag;
+			f->prev_free = frag;
 		}
 		}
 		qm->free_hash[hash].first = frag;
 		qm->free_hash[hash].first = frag;
 	}
 	}
+	frag->is_free = 1;
 	qm->ffrags++;
 	qm->ffrags++;
 	qm->free_hash[hash].no++;
 	qm->free_hash[hash].no++;
 #ifdef F_MALLOC_HASH_BITMAP
 #ifdef F_MALLOC_HASH_BITMAP
@@ -307,8 +291,8 @@ void fm_split_frag(struct fm_block* qm, struct fm_frag* frag,
 		n->file=file;
 		n->file=file;
 		n->func="frag. from fm_split_frag";
 		n->func="frag. from fm_split_frag";
 		n->line=line;
 		n->line=line;
-		n->check=ST_CHECK_PATTERN;
 #endif
 #endif
+		n->check=ST_CHECK_PATTERN;
 		/* reinsert n in free list*/
 		/* reinsert n in free list*/
 		qm->used-=FRAG_OVERHEAD;
 		qm->used-=FRAG_OVERHEAD;
 		fm_insert_free(qm, n);
 		fm_insert_free(qm, n);
@@ -366,17 +350,17 @@ struct fm_block* fm_malloc_init(char* address, unsigned long size, int type)
 	qm->last_frag=(struct fm_frag*)(end-sizeof(struct fm_frag));
 	qm->last_frag=(struct fm_frag*)(end-sizeof(struct fm_frag));
 	/* init first fragment*/
 	/* init first fragment*/
 	qm->first_frag->size=size;
 	qm->first_frag->size=size;
-	qm->first_frag->prv_free=0;
-	qm->first_frag->u.nxt_free=0;
+	qm->first_frag->prev_free=0;
+	qm->first_frag->next_free=0;
+	qm->first_frag->is_free=0;
 	/* init last fragment*/
 	/* init last fragment*/
 	qm->last_frag->size=0;
 	qm->last_frag->size=0;
-	qm->last_frag->prv_free=0;
-	qm->last_frag->u.nxt_free=0;
+	qm->last_frag->prev_free=0;
+	qm->last_frag->next_free=0;
+	qm->last_frag->is_free=0;
 	
 	
-#ifdef DBG_F_MALLOC
 	qm->first_frag->check=ST_CHECK_PATTERN;
 	qm->first_frag->check=ST_CHECK_PATTERN;
 	qm->last_frag->check=END_CHECK_PATTERN1;
 	qm->last_frag->check=END_CHECK_PATTERN1;
-#endif
 	
 	
 	/* link initial fragment into the free list*/
 	/* link initial fragment into the free list*/
 	
 	
@@ -464,7 +448,7 @@ void* fm_malloc(void* qmp, unsigned long size)
 	if (likely(hash>=0)){
 	if (likely(hash>=0)){
 		if (likely(hash<=F_MALLOC_OPTIMIZE/ROUNDTO)) { /* return first match */
 		if (likely(hash<=F_MALLOC_OPTIMIZE/ROUNDTO)) { /* return first match */
 			f=qm->free_hash[hash].first;
 			f=qm->free_hash[hash].first;
-			if(likely(f && f!=qm->last_frag)) goto found;
+			if(likely(f)) goto found;
 #ifdef DBG_F_MALLOC
 #ifdef DBG_F_MALLOC
 			MDBG(" block %p hash %d empty but no. is %lu\n", qm,
 			MDBG(" block %p hash %d empty but no. is %lu\n", qm,
 					hash, qm->free_hash[hash].no);
 					hash, qm->free_hash[hash].no);
@@ -482,7 +466,7 @@ void* fm_malloc(void* qmp, unsigned long size)
 		   hash buckets.
 		   hash buckets.
 		*/
 		*/
 		do {
 		do {
-			for(f=qm->free_hash[hash].first; f && f!=qm->last_frag; f=f->u.nxt_free)
+			for(f=qm->free_hash[hash].first; f; f=f->next_free)
 				if (f->size>=size) goto found;
 				if (f->size>=size) goto found;
 			hash++; /* try in next hash cell */
 			hash++; /* try in next hash cell */
 		}while((hash < F_HASH_SIZE) &&
 		}while((hash < F_HASH_SIZE) &&
@@ -491,7 +475,7 @@ void* fm_malloc(void* qmp, unsigned long size)
 #else /* F_MALLOC_HASH_BITMAP */
 #else /* F_MALLOC_HASH_BITMAP */
 	for(hash=GET_HASH(size);hash<F_HASH_SIZE;hash++){
 	for(hash=GET_HASH(size);hash<F_HASH_SIZE;hash++){
 		f=qm->free_hash[hash].first;
 		f=qm->free_hash[hash].first;
-		for(;f && f!=qm->last_frag; f=f->u.nxt_free)
+		for(; f; f=f->u.nxt_free)
 			if (f->size>=size) goto found;
 			if (f->size>=size) goto found;
 		/* try in a bigger bucket */
 		/* try in a bigger bucket */
 	}
 	}
@@ -523,10 +507,10 @@ finish:
 	frag->file=file;
 	frag->file=file;
 	frag->func=func;
 	frag->func=func;
 	frag->line=line;
 	frag->line=line;
-	frag->check=ST_CHECK_PATTERN;
 	MDBG("fm_malloc(%p, %lu) returns address %p \n", qm, size,
 	MDBG("fm_malloc(%p, %lu) returns address %p \n", qm, size,
 		(char*)frag+sizeof(struct fm_frag));
 		(char*)frag+sizeof(struct fm_frag));
 #endif
 #endif
+	frag->check=ST_CHECK_PATTERN;
 
 
 	if (qm->max_real_used<qm->real_used)
 	if (qm->max_real_used<qm->real_used)
 		qm->max_real_used=qm->real_used;
 		qm->max_real_used=qm->real_used;
@@ -804,7 +788,7 @@ void fm_status(void* qmp)
 	for(h=0,i=0,size=0;h<F_HASH_SIZE;h++){
 	for(h=0,i=0,size=0;h<F_HASH_SIZE;h++){
 		unused=0;
 		unused=0;
 		for (f=qm->free_hash[h].first,j=0; f;
 		for (f=qm->free_hash[h].first,j=0; f;
-				size+=f->size,f=f->u.nxt_free,i++,j++){
+				size+=f->size,f=f->next_free,i++,j++){
 			if (!FRAG_WAS_USED(f)){
 			if (!FRAG_WAS_USED(f)){
 				unused++;
 				unused++;
 #ifdef DBG_F_MALLOC
 #ifdef DBG_F_MALLOC

+ 5 - 8
mem/f_malloc.h

@@ -79,19 +79,16 @@ typedef unsigned long fm_hash_bitmap_t;
  * - +1 .... end -  size = 2^k, big buckets
  * - +1 .... end -  size = 2^k, big buckets
  */
  */
 struct fm_frag{
 struct fm_frag{
-	unsigned long size;           /* size of fragment */
-	union{
-		struct fm_frag* nxt_free; /* next free frag in slot, last poitns to qm last_frag,
-									used to detect if fragment is free (when not null) */
-		long reserved;
-	}u;
-	struct fm_frag* prv_free;     /* prev free frag in slot - for faster join/defrag */
+	unsigned long size;         /* size of fragment */
+	struct fm_frag* next_free;  /* next free frag in slot */
+	struct fm_frag* prev_free;  /* prev free frag in slot - for faster join/defrag */
+	unsigned int is_free;       /* used to detect if fragment is free (when not 0) */
 #ifdef DBG_F_MALLOC
 #ifdef DBG_F_MALLOC
 	const char* file;
 	const char* file;
 	const char* func;
 	const char* func;
 	unsigned long line;
 	unsigned long line;
-	unsigned long check;
 #endif
 #endif
+	unsigned int check;
 };
 };
 
 
 struct fm_frag_lnk{
 struct fm_frag_lnk{