Spravce pameti
Jiří Nesvačil
nesvacil na posys.eu
Čtvrtek Listopad 3 21:08:50 CET 2016
Tahle promenna tj. kde zacina zasobnik neni standartizovana bych rekl. Zname jen konec dat _ebss a konec zasobniku (|_estack |). To, ze si ji da nejaky prekladac do linkeru nezamena, ze ji standardni malloc pouzije. Ani ta metoda na dynamicke
zjisteni nepomuze na malem CPU, tam se sdili heap, takze dynamicke zjisteni SP registru vrati nesmysl.
Jirka
Dne 3. 11. 2016 v 19:59 Jaroslav Buchta napsal(a):
> Ale ty fce malloc, free, ... je potreba resit pri multi thread aplikacich, klasicke knihovny maji callback funkce, u nano knihoven je to slozitejsi, musi se to resit nejak takto a jeste jsou v tom nejake parametry linkeru, ktere se mi nechce hledat:
>
> size_t __malloc_margin = 256;
> char *__brkval;
>
> uint32_t maxHeap;
> uint32_t minMSP = 0xffffffff;
>
> void *__real__sbrk_r(
> struct _reent *r,
> ptrdiff_t incr);
>
> void *__wrap__sbrk_r(
> struct _reent *r,
> ptrdiff_t incr)
> {
> extern char end; // provided by the linker script
>
> if (__brkval == 0)
> __brkval = &end;
> #ifdef MMGMTDBG
> DBGUSART_dbgSendStr("sbrk: ");
> DBGUSART_dbgSendStrDec(incr);
> DBGUSART_dbgSendStrNl("");
> #endif
> uint32_t mspCurr = __get_MSP();
> if (mspCurr < minMSP) minMSP = mspCurr;
> if (__brkval + incr > (char*)mspCurr - __malloc_margin)
> {
> r->_errno = ENOMEM;
> return (void*)-1;
> }
>
> void *ret = __brkval;
> __brkval += incr;
>
> maxHeap = (uint32_t)__brkval;
> return ret;
> }
>
>
> extern void *__real__malloc_r(
> struct _reent *r,
> size_t size
> );
>
> void *__wrap__malloc_r(
> struct _reent *r,
> size_t size
> )
> {
> vPortEnterCritical();
> void *ptr = __real__malloc_r(r, size);
> #ifdef MMGMTDBG
> DBGUSART_dbgSendStr("malloc: ");
> DBGUSART_dbgSendStrDec(size);
> DBGUSART_dbgSendStr(" at: ");
> DBGUSART_dbgSendStrHex32((uint32_t)ptr);
> DBGUSART_dbgSendStrNl("");
> #endif
> vPortExitCritical();
> return ptr;
> }
>
> extern void __real__free_r(
> struct _reent *r,
> void *ptr
> );
> void __wrap__free_r(
> struct _reent *r,
> void *ptr
> )
> {
> vPortEnterCritical();
> #ifdef MMGMTDBG
> DBGUSART_dbgSendStr("free at: ");
> DBGUSART_dbgSendStrHex32((uint32_t)ptr);
> DBGUSART_dbgSendStrNl("");
> #endif
> __real__free_r(r, ptr);
> vPortExitCritical();
> }
>
>
> extern void *__real__realloc_r(
> struct _reent *r,
> void *ptr,
> size_t size
> );
>
> extern void *__wrap__realloc_r(
> struct _reent *r,
> void *ptr,
> size_t size
> )
> {
> vPortEnterCritical();
> void *newptr = __real__realloc_r(r, ptr, size);
> vPortExitCritical();
> return newptr;
> }
>
>
>
> Dne 03.11.2016 v 19:52 Miroslav Mraz napsal(a):
>> Pro lepší pochopení, jak to obvykle funguje - do vlastního malloc() a free() v knihovně nemá cenu se nějak vrtat. Vlastní přidělení paměti zajišťuje něco jako _sbrk(), která je volána z vnitřku toho malloc(). A to je právě to místo, kterým se
>> můžete zabývat. Samotná tato funkce není složitá, je to něco jako
>>
>> // HEAP je definovan za .bss, stack jde proti heap dokud se nepotkaji
>> extern char _end; // Defined by the linker.
>> //register char * stack_ptr asm ("sp"); // takhle je to v newlib
>> static inline char * stack_ptr (void) { // pochopitelneji
>> register char * res;
>> asm volatile (
>> "mov %0,sp\r\n" // sp do vysledku
>> :"=r"(res) :: ); // standardni zapis
>> return res;
>> }
>>
>> const char * _sbrk (int incr) {
>> static char * heap_end;
>> char * prev_heap_end;
>> if (heap_end == NULL) heap_end = & _end;
>> prev_heap_end = heap_end;
>> if (heap_end + incr > stack_ptr()) {
>> /*
>> No a tady si uděláte co je potřeba, když
>> už není dost paměti.
>> */
>> return (char *) 0;
>> }
>> heap_end += incr;
>> return (const char *) prev_heap_end;
>> }
>> Takhle je to (přibližně) uděláno v newlib, ale samosebou si můžete definovat vlastní oblast pro haldu jak chcete.
>>
>> Mrazík
>>
>> Dne 3.11.2016 v 19:04 Jan Waclawek napsal(a):
>>> Ano a nie.
>>>
>>> V principe by ste si mali to mnozstvo pamate vyhradenej ako heap urcit Vy,
>>> ci uz priamo v linker skripte alebo jeho obdobe, alebo u klikatora na to
>>> bude niekde nejake okno. Potom v runtime si mozete zistit ci to tak naozaj
>>> je, ale ci bude presne kod pana kolegu Nesvacila fungovat to pochopitelne
>>> zavisi od toho, ci budete mat tie iste symboly v tom linker skripte atd.
>>>
>>> *printf ma niekedy svoj vlastny alokator a vyhradzuje si staticky cast
>>> pamate (v ktorej si potom on sam pre seba dynamicky alokuje co potrebuje,
>>> to je pre Vas neviditelne a nezasahuje to do "vasho" malloc()). Musite si
>>> to zistit v dokumentacii ku kniznici, ktoru pouzivate (ja viem, obvykle
>>> nie je ziadna prip. zdrojaky ;-) ).
>>>
>>> wek
>>>
>> _______________________________________________
>> HW-list mailing list - sponsored by www.HW.cz
>> Hw-list na list.hw.cz
>> http://list.hw.cz/mailman/listinfo/hw-list
>
>
> _______________________________________________
> HW-list mailing list - sponsored by www.HW.cz
> Hw-list na list.hw.cz
> http://list.hw.cz/mailman/listinfo/hw-list
------------- další část ---------------
HTML příloha byla odstraněna...
URL: <http://list.hw.cz/pipermail/hw-list/attachments/20161103/db317aa6/attachment.html>
Další informace o konferenci Hw-list