
Dear Wolfgang,
On Wed, Aug 1, 2012 at 9:09 PM, Wolfgang Denk wd@denx.de wrote:
Hm... I have to admit that I am not really happy about such an "explanation". The statement that "other guys" want something is not exactly an explanation of a concept that I can understand, and without being able to understand it, I don't buy it.
I wanted to say that this is outcome of an informal discussion with Marek Vasut, Pavel Hermann and Viktor Krivak, who are working on different parts of DM (and perhaps I should say that it is our school project to implement driver model for U-Boot, which is not relevant information to the current discussion, but it may explain why we closely cooperate on DM among ourselves). Statements like "I/we want" were not any notices nor decisions nor whatever final but rather wishes or ideas (mine or from others). Although we have elaborate outline of DM and supporting subsystems it is still subject to changes.
But why would 2 copies be needed? I understand then once regular malloc() becomes available, you want to make sure all allocations are maintained using this mechanism. But I already wonder how you are going to implement this - you will have to update all pointers. How will you find out where these might be?
Assume something like:
item *foo(...) { static item *foo_local = malloc(size1); ... return foo_local; }
item *bar(..., item **ptr) { static item *bar_local = malloc(size2); ... *ptr = bar_local; return bar_local; }
void some_function(...) { item *x, *y; ... x = bar(..., &y); baz(y); ... }
How will you later know which variables store the values from the early malloc calls, and how will you access these for proper relocation?
Each early heap (assuming we can have more than one contiguous early heaps as Graeme suggested) has a pointer to the beginning (and it is valid only before relocation and before caches are enabled). I can memcpy() the used part of the early heap somewhere else and preserve the original heap beginning pointer (I have in mind preservation of the pointers in GD; it is implementation detail indeed, but I would rather note this in order make sure that I am not working with false assumption about possibility of preserving pointers like that). Then I can compute copied_heap_address = original_address + (copied_heap_begin - original_heap_begin).
I have to admit, that I am not familiar enough with plans for early DM tree to know where are we going to hold tree root pointer. I think that it could be eventually placed in GD. To your example:
#define TRANSLATE_ADDR(old_heap,new_heap,pointer) (pointer + new_heap - old_heap)
void some_function(...) { item *x, *y; ... x = bar(..., &y); baz(y);
gd->x = x; gd->y = y;
...
memcpy(NEW_HEAP_ADDR, gd->old_heap_addr, heap_used_bytes); }
void later(...) { item *x = TRANSLATE_ADDR(old_heap_addr,NEW_HEAP_ADDR,gd->x); item *y = TRANSLATE_ADDR(old_heap_addr,NEW_HEAP_ADDR,gd->y); }
Perhaps I can try to rewrite it into more real-life example:
void board_init_f(...) { ... struct dm_tree_node *root = malloc(sizeof(struct dm_tree_item)); /* early_malloc() has been used in fact. */ root->left_descendant = malloc(sizeof(struct dm_tree_item)); gd->dm_tree_root = root; ...
memcpy(NEW_HEAP_ADDR,gd->early_heap,gd->early_heap_used_bytes);
relocate_code(...); }
void board_init_r(gd_t *id, ulong dest_addr) { ... struct dm_tree_node *root_new = TRANSLATE_ADDR(gd->early_heap, NEW_HEAP_ADDR, gd->root); root_new->left_descendant = TRANSLATE_ADDR(gd->early_heap, NEW_HEAP_ADDR, root_new->left_descendant);
/* And I can rectify all the pointers in the tree just like that. It should not be expensive because the tree is really small at this point - 5 items max. The problem is, that the root_new does not point to memory obtained from dlmalloc. How could we possibily solve this? Our current idea is to perform one extra round of malloc() and copying of the tree... */ ... }
Thank you for your help, Tomas