ucc_geth DPRAM alloc error, 2.6.22-rc3

Rune Torgersen runet at innovsys.com
Fri Jun 15 08:50:03 EST 2007


Here is what I had to do to get best-fit + not allocating too much:
(against 2.6.18)
--- linux-innsys/arch/ppc/lib/rheap.c	2006/10/10 22:54:41	175
+++ linux-innsys/arch/ppc/lib/rheap.c	2006/12/03 18:04:42	205
@@ -428,19 +428,22 @@
 {
 	struct list_head *l;
 	rh_block_t *blk;
-	rh_block_t *newblk;
+	rh_block_t *newblk1, *newblk2;
 	void *start;
-
+	int align_mask = alignment - 1;
+    int off;
+	unsigned long s, e, m, bs, be;
+    
 	/* Validate size, (must be power of two) */
 	if (size <= 0 || (alignment & (alignment - 1)) != 0)
 		return ERR_PTR(-EINVAL);
 
 	/* given alignment larger that default rheap alignment */
-	if (alignment > info->alignment)
-		size += alignment - 1;
+	//if (alignment > info->alignment)
+	//	size += alignment - 1;
 
 	/* Align to configured alignment */
-	size = (size + (info->alignment - 1)) & ~(info->alignment - 1);
+	//size = (size + (info->alignment - 1)) & ~(info->alignment -
1);
 
 	if (assure_empty(info, 1) < 0)
 		return ERR_PTR(-ENOMEM);
@@ -448,8 +451,18 @@
 	blk = NULL;
 	list_for_each(l, &info->free_list) {
 		blk = list_entry(l, rh_block_t, list);
-		if (size <= blk->size)
+		
+		if ((blk->size == size) && (((int)blk->start &
align_mask) == 0))
+		    break;
+		
+		if (((int)blk->start & align_mask) != 0)
+			off = align_mask - ((int)blk->start &
align_mask) + 1;
+		else
+			off = 0;
+		    
+		if (blk->size - off >= size)
 			break;
+		
 		blk = NULL;
 	}
 
@@ -468,25 +481,35 @@
 		return start;
 	}
 
-	newblk = get_slot(info);
-	newblk->start = blk->start;
-	newblk->size = size;
-	newblk->owner = owner;
-
-	/* blk still in free list, with updated start, size */
-	blk->start = (int8_t *)blk->start + size;
-	blk->size -= size;
+	bs = (int)blk->start;
+	be = (int)blk->start + blk->size;
+	s = (int)blk->start + off;
+	e = s + size;
+	
+	if (bs == s || be == e) {
+		if (bs == s)
+			blk->start = (int8_t *)blk->start + size;
+		blk->size -= size;
 
-	start = newblk->start;
+	} else {
+		/* The front free fragment */
+		blk->size = s - bs;
 
-	attach_taken_block(info, newblk);
-	
-	/* for larger alignment return fixed up pointer  */
-	/* this is no problem with the deallocator since */
-	/* we scan for pointers that lie in the blocks   */
-	if (alignment > info->alignment)
-		start = (void *)(((unsigned long)start + alignment - 1)
&
-				~(alignment - 1));
+		/* The back free fragment */
+		newblk2 = get_slot(info);
+		newblk2->start = (void *)e;
+		newblk2->size = be - e;
+
+		list_add(&newblk2->list, &blk->list);
+	}
+
+	newblk1 = get_slot(info);
+	newblk1->start = (void *)s;
+	newblk1->size = e - s;
+	newblk1->owner = owner;
+
+	start = newblk1->start;
+	attach_taken_block(info, newblk1);
 
 	return start;
 }



More information about the Linuxppc-dev mailing list