|
|
  |
newlib + malloc lock, Помогите разобраться |
|
|
|
Oct 24 2011, 10:37
|

Группа: Участник
Сообщений: 14
Регистрация: 24-10-11
Пользователь №: 67 911

|
Народ, помогите все по полкам разложить. Все началось с того, что хотел прикрутить *printf из newlib. В проекте используется FreeRTOS. По прошлому опыту ожидал, что сразу возникнут ошибки линковки _sbrk ,_write, _read и т.д. Но все скомпилировалось нормально  . ToolChain от klen'а (спасибо ему) При запуске из под отладчика выпал в _ swiwrite на инструкции bkpt. Копаясь в исходниках newlib 1.19 нашел где это. Правильно ли я понял, что это из-за сборки newlib без ключа --disable-newlib-supplied-syscalls? Дальше я скачал yagarto, заменил компилятор. и ошибки линковки возникли (я впервые был ряд ошибкам  ))) Реализовал syscalls, и все заработало. Но!!! printf использует malloc, malloc вызывает _sbrk для получения памяти. в исходниках для блокировки кучи используется вызовы _malloc_lock и _malloc_unlock. Отладчиком смотрел, они пустые (и в исходнике newlib их смотрел) Код void __malloc_lock (ptr) struct _reent *ptr; { #ifndef __SINGLE_THREAD__ __lock_acquire_recursive (__malloc_lock_object); #endif } Значит из многопоточной среды вызывать printf черевато  (и malloc тоже) собственно вопросы: - можно ли заставить ToolChain klen'a работать с моими syscalls без пересборки newlib
- как залочить кучу newlib в проекте FreeRTOS (пересобирать что-ли без __SINGLE_THREAD__)
- если прошлое нельзя, то может наоборот заставить newlib использовать vPortMalloc из FreeRTOS
За любую помощь заранее благодарен!
|
|
|
|
|
Oct 24 2011, 12:48
|

Группа: Участник
Сообщений: 14
Регистрация: 24-10-11
Пользователь №: 67 911

|
в исходниках newlib увидел MALLOC_PROVIDED, никто не пробовал объявлять? тогда вроде newlib не будет свою malloc компилить
|
|
|
|
|
Oct 25 2011, 04:18
|

Местный
  
Группа: Участник
Сообщений: 340
Регистрация: 25-10-05
Из: Пермь, Россия
Пользователь №: 10 091

|
Цитата(Сергей Борщ @ Oct 24 2011, 16:51)  Написать в одном из исходных файлов проекта свою функцию malloc (ну и free, разумеется), которая будет вызывать vPortMalloc и прилинкуется взамен библиотечной. malloc и free писать не надо, они уже написаны. Писать надо __malloc_lock() и __malloc_unlock(). Об этом, кстати, прямым открытым текстом написано в документации. Также скорее всего потребуется переписать _sbrk() в плане проверки исчерпания кучи. Для работы printf необходимо также реализовать системный вызов _write.
--------------------
Всего наилучшего, Alex Mogilnikov
|
|
|
|
|
Oct 25 2011, 06:41
|

Группа: Участник
Сообщений: 14
Регистрация: 24-10-11
Пользователь №: 67 911

|
Цитата(alx2 @ Oct 25 2011, 08:18)  malloc и free писать не надо, они уже написаны. Писать надо __malloc_lock() и __malloc_unlock(). Об этом, кстати, прямым открытым текстом написано в документации. Также скорее всего потребуется переписать _sbrk() в плане проверки исчерпания кучи. Для работы printf необходимо также реализовать системный вызов _write. так __malloc_lock() и __malloc_unlock() не определяются из-за ошибки линкера! Код multiple definition of `__malloc_lock' нашел вот это mail архив newlibэтож чтож - пересобирать? пока придумал удалить mlock.o из libc.a чтоб линкер не ругался, кто что думает пока нашел сырое решение опция линкера Код --allow-multiple-definition теперь я могу определить свой void __malloc_lock (struct _reent *r)и он вызывается! только вот криво это, буду копать дальше
|
|
|
|
|
Oct 25 2011, 10:16
|

Группа: Участник
Сообщений: 14
Регистрация: 24-10-11
Пользователь №: 67 911

|
Вобщем решил сделать так: В программе реализовал лок кучи через FreeRTOS Код void __malloc_lock (struct _reent *r) { vPortEnterCritical(); }
void __malloc_unlock (struct _reent *r) { vPortExitCritical(); } чтоб не было ошибки линковки - выполняю команду arm-none-eabi-ar dv libc.a lib_a-mlock.olibc.a - который используется в данный момент ( у меня это arm-none-eabi/lib/thumb/v7m\libc.a поскольку cortex-m3), зависит от multilib она удаляет из архива объектник с mlock. Все. буду тестировать newlib'ский malloc, мне кажется он должен быть понадежнее, чем FreeRTOS'овский.
Сообщение отредактировал podelkin - Oct 25 2011, 10:18
|
|
|
|
|
Oct 26 2011, 04:12
|

Местный
  
Группа: Участник
Сообщений: 340
Регистрация: 25-10-05
Из: Пермь, Россия
Пользователь №: 10 091

|
Цитата(podelkin @ Oct 25 2011, 11:41)  так __malloc_lock() и __malloc_unlock() не определяются из-за ошибки линкера! Код multiple definition of `__malloc_lock' ??? Ошибка "multiple definition", наоборот, означает, что символ __malloc_lock определен более одного раза. При этом линкер сообщает, при загрузке какого модуля эта ошибка возникла, и где (в каком модуле) этот символ был определен раньше. Могу предположить следующее: когда Вы делали собственные версии __malloc_lock и __malloc_unlock, допустили опечатку в имени последней. В результате после загрузки модулей вашего проекта линкер не находит __malloc_unlock и загружает библиотечный mlock.o. А там __malloc_lock, который уже есть в вашем проекте! Цитата(podelkin @ Oct 25 2011, 11:41)  пока нашел сырое решение опция линкера Код --allow-multiple-definition ИМХО это не решение, а маскировка проблемы. Если верно сделанное мной выше предположение, то, действительно, будет вызываться ваш __malloc_lock, но вместо вашего __malloc_unlock будет вызываться "пустышка" из библиотеки... Я бы Вам посоветовал разобраться-таки, почему линкер грузит библиотечный mlock.o, если кроме __malloc_lock и __malloc_unlock там ничего нет. Посмотрите, что там в map-файле на этот счет говорится...
Сообщение отредактировал alx2 - Oct 26 2011, 04:18
--------------------
Всего наилучшего, Alex Mogilnikov
|
|
|
|
|
Oct 26 2011, 09:02
|

Местный
  
Группа: Участник
Сообщений: 340
Регистрация: 25-10-05
Из: Пермь, Россия
Пользователь №: 10 091

|
Цитата(podelkin @ Oct 25 2011, 15:16)  чтоб не было ошибки линковки - выполняю команду arm-none-eabi-ar dv libc.a lib_a-mlock.o Я тогда вообще не понимаю, что у Вас происходит... Если линкер загружает mlock.o из библиотеки, значит в вашем проекте присутствует неопределенный символ, имеющийся в mlock.o. Но тогда после удаления mlock.o из библиотеки линкер должен вываливаться с ошибкой "undefined reference to"... Если же символы, содержащиеся в mlock.o проекту не нужны (а так и должно быть, ибо в проекте есть собственные __malloc_lock и __malloc_unlock), какого черта линкер пытался его загружать?... Может покажете всю команду, которой линкуется ваш проект?
--------------------
Всего наилучшего, Alex Mogilnikov
|
|
|
|
|
Oct 26 2011, 13:50
|

Группа: Участник
Сообщений: 14
Регистрация: 24-10-11
Пользователь №: 67 911

|
Цитата(alx2 @ Oct 26 2011, 13:02)  Я тогда вообще не понимаю, что у Вас происходит... Если линкер загружает mlock.o из библиотеки, значит в вашем проекте присутствует неопределенный символ, имеющийся в mlock.o. Но тогда после удаления mlock.o из библиотеки линкер должен вываливаться с ошибкой "undefined reference to"... Если же символы, содержащиеся в mlock.o проекту не нужны (а так и должно быть, ибо в проекте есть собственные __malloc_lock и __malloc_unlock), какого черта линкер пытался его загружать?...
Может покажете всю команду, которой линкуется ваш проект? Все линкуется как обычно. На mlock ссылается сам malloc. но в исходниках newlib __malloc_lock вызывает __lock_acquire, который определен по умолчанию как Код #define __lock_acquire(lock) (_CAST_VOID 0) #define __lock_acquire_recursive(lock) (_CAST_VOID 0) то есть символ __malloc_lock в библиотеке есть, но он ничего не делает, только мешает определить свой __malloc_lock. Поэтому и пришлось выкинуть mlock.o из libc.a, чтоб спокойно определить свои __malloc_lock, который бы защитил кучу в много поточной среде. После 2ух дней тестов все работает. Уже пишу, поскольку не нашел никакой информации на форуме по использованию malloc из newlib (и *printf по зависимостям также) из многопоточной среды, надеюсь кому-то поможет. кстати исправил определение своих символов на : Код void __malloc_lock(struct _reent *r) { vTaskSuspendAll(); }
void __malloc_unlock(struct _reent *r) { xTaskResumeAll(); } чтоб не терять прерывания во время работы с памятью Все работает
|
|
|
|
|
Oct 27 2011, 05:05
|

Местный
  
Группа: Участник
Сообщений: 340
Регистрация: 25-10-05
Из: Пермь, Россия
Пользователь №: 10 091

|
Цитата(podelkin @ Oct 26 2011, 18:50)  Все линкуется как обычно. Я не знаком с обычаями линковки.  malloc не ссылается на mlock. Он ссылается на __malloc_lock и __malloc_unlock. Но они уже определены в вашем проекте! Таким образом, эти ссылки будут удовлетворены уже при загрузке malloc.o, и никакой mlock.o из библиотеки он загружать не должен (никаких других символов кроме этих двух в mlock.o нет). Следовательно, мешать он ничему не должен, и что там написано в исходниках newlib, не должно иметь никакого значения... Как бы то ни было, рад, что у Вас все работает. Ну и вот для примера: Код kolez% cat test.c #include <stdlib.h> void __malloc_lock (struct _reent *ptr) {} void __malloc_unlock(struct _reent *ptr) {} int main() { void *mem = malloc(1000); free(mem); return 0; } kolez% arm-elf-gcc -Wl,-Map=test.map -o test test.c kolez% grep mlock test.map kolez% Как видите, у меня mlock не прилинкован, и ничему не мешает...
--------------------
Всего наилучшего, Alex Mogilnikov
|
|
|
|
|
Oct 27 2011, 06:35
|

Группа: Участник
Сообщений: 14
Регистрация: 24-10-11
Пользователь №: 67 911

|
Цитата(alx2 @ Oct 26 2011, 08:12)  Могу предположить следующее: когда Вы делали собственные версии __malloc_lock и __malloc_unlock, допустили опечатку в имени последней Странно, может из-за кэша на работе Ваш пост от Oct 26 2011, 08:12 я увидел только сейчас. сейчас попробовал скомпилировать простейший пример из поста выше и все собралось  вернул lib.a к первоначалному виду и мой проект теперь компилица без ошибок Какого лешего gcc раньше тянул mloc.o из библиотеки я так понял(( поначалу тоже подумал что я ошибся в написании __malloc_unlock, но тогда бы у меня не собралось бы приложение после выкидывания mloc.o из libc.a (к тому же я смотрел отладчиком мои __malloc_lock и __malloc_unlock прилежно вызывались, то есть были написаны без ошибок) Остановлюсь на том что где-то кривизна моих рук ускользнула от моего взгляда... Вообщем alx2 респект А я теперь умею шаманить с символами и знаю ключ Код --allow-multiple-definition который нафиг не нужен
|
|
|
|
|
  |
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|