Собираюсь сделать Thread-local storage aka TLS.
Размер область 4Кб - на 1024 указателя. Данные будут адресоваться через селектор fs. Есть два варианта реализации.
1) добавление одного dword к заголовку программы и увеличение версии до '02'.
2) Функция ядра создающая tls. Этот способ мне нравится меньше потому что придётся учитывать вариант при котором сначала будут созданы потоки а потом tls.
TLS в Колибри
Serge
Первый вариант (MENUET02?, а может пора уже в заголовке использовать слово KOLIBRI, никакой совместимости с М32 и М64 ведь не предвидится?) более предпочтителен, разумеется если по прежнему приложения MENUET01 будут функционировать.
А можно подробнее?
1) Правка и перекомпиляция приложения MENUET01 потребуется?
1) TLS как и обычные потоки смогут создавать окна в оконном стеке?
2) Какие-либо меры по синхронизации и контролю со стороны ядра, или все по прежнему остается на усмотрение программиста?
3) Реализация TLS наследует текущий способ подключения библиотек?
Первый вариант (MENUET02?, а может пора уже в заголовке использовать слово KOLIBRI, никакой совместимости с М32 и М64 ведь не предвидится?) более предпочтителен, разумеется если по прежнему приложения MENUET01 будут функционировать.
А можно подробнее?
1) Правка и перекомпиляция приложения MENUET01 потребуется?
1) TLS как и обычные потоки смогут создавать окна в оконном стеке?
2) Какие-либо меры по синхронизации и контролю со стороны ядра, или все по прежнему остается на усмотрение программиста?
3) Реализация TLS наследует текущий способ подключения библиотек?
Mario
Один dword на целую KOLIBRI не тянет. Он и не очень нужен.
Вся фича предназначена исключительно для новых многопоточных приложений. На старые программы, dll и окна это никак не влияет. Вся синхронизация на совести программиста. Всё ошибки будут локальны для многопоточного приложения и не затронут другие приложения.
Примерная реализация:
для каждого потока ядро выделит одну страницу в адресном пространстве приложения и настроит дескриптор для доступа через селектор fs. При переключении потока база сегмента в gdt будет меняться а селектор останется тем же (разумеется ядро будет перегружать fs чтобы обновить теневые регистры). Функции tls_alloc tls_free в виде макросов будут выделять память в области tls. При желании программист сможет распределять эту память самостоятельно.
Один dword на целую KOLIBRI не тянет. Он и не очень нужен.
Вся фича предназначена исключительно для новых многопоточных приложений. На старые программы, dll и окна это никак не влияет. Вся синхронизация на совести программиста. Всё ошибки будут локальны для многопоточного приложения и не затронут другие приложения.
Примерная реализация:
для каждого потока ядро выделит одну страницу в адресном пространстве приложения и настроит дескриптор для доступа через селектор fs. При переключении потока база сегмента в gdt будет меняться а селектор останется тем же (разумеется ядро будет перегружать fs чтобы обновить теневые регистры). Функции tls_alloc tls_free в виде макросов будут выделять память в области tls. При желании программист сможет распределять эту память самостоятельно.
А как с распределением квантов времени? Время основного потока делится между всеми нитями присутствующими в данном адресном пространстве?
Mario
А причём здесь планировщик ? Это же совсем другая тема. Место для хранения локальных для каждого потока данных. Например у тебя приложение запускает несколько потоков. Каждый поток создаёт своё окно. Где хранить данные потока и как потоку быстро получить к ним доступ ? C помощью tls. По ссылке в заголовке подробно расписано зачем и как используется.
А причём здесь планировщик ? Это же совсем другая тема. Место для хранения локальных для каждого потока данных. Например у тебя приложение запускает несколько потоков. Каждый поток создаёт своё окно. Где хранить данные потока и как потоку быстро получить к ним доступ ? C помощью tls. По ссылке в заголовке подробно расписано зачем и как используется.
О! класс!
И мы уже давно не пешки,
Мы пули, мы орлы, и решки!
Война ютит бинарный код,
Умри, или иди вперед!
Мы пули, мы орлы, и решки!
Война ютит бинарный код,
Умри, или иди вперед!
Залил код на SVN. В многопоточных приложениях с заголовком MENUET02 каждый поток получает персональные 4 Кб fs:0x000 - fs:0xFFF. Лимит сегмента tls установлен в 0xFFF. Превышение вызовет исключение #gpf.
Баги эмуляторов.
Quemu игнорирует лимит сегмента. Превышение вызовет страничную ошибку.
В VirtualBox tls не работает. Вероятно эмулятор не обновляет теневые регистры если селектор fs не изменился.
Баги эмуляторов.
Quemu игнорирует лимит сегмента. Превышение вызовет страничную ошибку.
В VirtualBox tls не работает. Вероятно эмулятор не обновляет теневые регистры если селектор fs не изменился.
Serge
Я туплю, можешь ты для любителей на простом русском языке разжевать подробнее?
Чем эта реализация отличается от функции 51? В чем преимущество? Потоки по прежнему запускаются функцией 51 или как? Эти 4 Кб они для хранения указателей на выделенные области памяти? У каждого потока теперь свои области не доступные и не разделяемые с другими потоками этого процесса могут быть? Я реально не соображу. Я честно читал ту статью.
Я туплю, можешь ты для любителей на простом русском языке разжевать подробнее?
Чем эта реализация отличается от функции 51? В чем преимущество? Потоки по прежнему запускаются функцией 51 или как? Эти 4 Кб они для хранения указателей на выделенные области памяти? У каждого потока теперь свои области не доступные и не разделяемые с другими потоками этого процесса могут быть? Я реально не соображу. Я честно читал ту статью.
Совершенно верно. Если быть совсем точным у каждого потока теперь есть одна область не разделяемая с другими потоками.У каждого потока теперь свои области не доступные и не разделяемые с другими потоками этого процесса могут быть ?
Никаких изменений в системных вызовах нет. Потоки как и раньше создаются ф.51. Единственное отличие - у программ со старыми заголовками нет tls.Чем эта реализация отличается от функции 51 ? В чем преимущество? Потоки по прежнему запускаются функцией 51 или как?
Обычно tls используется так. Но в Колибри каждый программист может распоряжаться tls по своему усмотрению. Например хранить там pid для быстрого доступа. Только не забывайте адресовать данные через селектор fs.Эти 4 Кб они для хранения указателей на выделенные области памяти?
Попробую разжевать поподробнее. Если var1 - обычная глобальная переменная, то код типаMario wrote:Я туплю, можешь ты для любителей на простом русском языке разжевать подробнее?
Code: Select all
mov [var1], eax
...
mov ecx, [var1]
А код типа
Code: Select all
mov [fs:0], eax
...
mov ecx, [fs:0]
Ушёл к умным, знающим и культурным людям.
Все, теперь понял. Я думал что-то кардинально новое, оказалось только для удобного хранения данных. ИМХО то же самое можно делать и обычным способом разграничив логически области - программист ведь и сам знает что и где хранится и зачем.
Это не всегда легко сделать. Особенно в библиотеках с неизвестным числом потоков и в сложных приложениях. Достаточно сравнить относительно простой Icon и многопоточный декодер х264.ИМХО то же самое можно делать и обычным способом разграничив логически области
А можно с этого места поподробнее? Попробовал пару простых тестов, вроде под VirtualBox нормально сработали.Serge wrote:В VirtualBox tls не работает. Вероятно эмулятор не обновляет теневые регистры если селектор fs не изменился.
Ушёл к умным, знающим и культурным людям.
Точнее не работало под Windows через fs. С gs всё работало правильно. В Linux не проверял. Надо проверить последнюю Win версию.
Сделал три функции для работы с tls.
void __fastcall tls_init(void *mem);
Настраивает данные для работы с tls. Обязательно вызывается один раз в родительском потоке. mem - указатель на массив в 136 байт
void** tls_alloc(void);
Выделяет переменную в массиве tls. Возвращаемое значение адрес переменной или 0 в случае неудачи.
void __fastcall tls_free(void **p);
Освобождает память в массиве tls. p - адрес переменной в массиве tls
[fs:0] зарезервировано. Предложения по использованию принимаются.
Дополнение.
Функции рассчитаны на расширенный заголовок. Не забывайте добавлять dword для tls_data.
void __fastcall tls_init(void *mem);
Настраивает данные для работы с tls. Обязательно вызывается один раз в родительском потоке. mem - указатель на массив в 136 байт
void** tls_alloc(void);
Выделяет переменную в массиве tls. Возвращаемое значение адрес переменной или 0 в случае неудачи.
void __fastcall tls_free(void **p);
Освобождает память в массиве tls. p - адрес переменной в массиве tls
[fs:0] зарезервировано. Предложения по использованию принимаются.
Дополнение.
Функции рассчитаны на расширенный заголовок. Не забывайте добавлять dword для tls_data.
Code: Select all
db 'MENUET02'
dd 1
dd start
dd i_end
dd mem
dd mem
dd 0 ; cmdline
dd 0 ; path
dd 0 ; tls data
- Attachments
-
-
tls.txt (1.66 KiB)Downloaded 358 times
-
Who is online
Users browsing this forum: No registered users and 0 guests