проблема:
в сборках MinGW-W64, которые я произвожу, и которые используют POSIX можель потоков, libstdc++.dll зависит от winpthreads.dll.
некоторым юзерам не нравится то, что им приходится "тащить" winpthreads.dll даже в том случае, когда их код не использует потоков.
мне, по правде говоря, не понятна проблема, ведь winpthreads.dll имеет объем 60-70 Кб, если мне не изменяет память.
в общем, хочу сделать так, чтоб winpthreads.dll связывалась динамически, если она нужна.
тут лежит код GCC'шной обертки над Pthreads.
если вырезать все лишнее, что получится что-то типа:
как вы могли заметить, в некоторых обертках производится тест 'if( __gthread_active_p() )'. для архитектур, не поддерживающих weak references(типа windows), функция '__gthread_active_p()' имеет такое определение:
static inline int
__gthread_active_p (void)
{
return 1;
}
так вот, я хочу переделать все эти обертки так, чтоб в каждой из них использовалась функция '__gthread_active_p()', но которая в своем теле будет производить проверку, на предмет подгружена ли winpthreads.dll, и если не подгружена — производить ее подгрузку и резолвить нужные символы. символы резолвится будут в некоторую структуру, мемберы которой и будут использоваться в обертках.
да, я понимаю что это даст некоторую просадку в производительности из-за постоянной проверки некоторого флага. в качестве проверки флага думаю использовать атомарные операции.
в общем, что думаете об этом?
спасибо!
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Здравствуйте, niXman, Вы писали:
X>так вот, я хочу переделать все эти обертки так, чтоб в каждой из них использовалась функция '__gthread_active_p()', но которая в своем теле будет производить проверку, на предмет подгружена ли winpthreads.dll, и если не подгружена — производить ее подгрузку и резолвить нужные символы. символы резолвится будут в некоторую структуру, мемберы которой и будут использоваться в обертках.
X> в качестве проверки флага думаю использовать атомарные операции.
Не стоит бросаться сразу использовать атомарные операции — подход double check работает быстрее — будет лишь небольшая проверка при первом вызове (всё равно незаметная на фоне инициализации библиотеки), а все остальные вызовы даже атомарные операции для проверки использовать не будут — лишь одно неатомарное чтение флага, что всё же менее накладно.
X>да, я понимаю что это даст некоторую просадку в производительности из-за постоянной проверки некоторого флага. X>в общем, что думаете об этом?
Да и без самого флага можно обойтись. Смотри, при загрузке библиотеки у тебя появляется переменная, куда сохраняется адрес функции. Соответственно, когда тебе нужно вызвать функцию, то происходит переход по адресу, записанному в этой переменной. И это по сути неуменьшаемые расходы по вызову функции из dll загруженных после старта программы (за исключением хаков вроде самодифицирующегося кода).
Так вот, обычно эта самая переменная с адресом функции не инициализирована при старте программы ничем интересным (там либо мусор, либо null). А ты просто запиши в неё указатель на функцию, делающую загрузку библиотеки:
using sched_yield_ptr = int (*)(void);
sched_yield_ptr sched_yield = sched_yield_delayed_load;
int sched_yield_delayed_load(void) {
delayed_load();
return sched_yield();
}
void delayed_load() {
mutex.lock();
load_pthread_library();
sched_yield = load_real_sched_yield();
pthread_self = load_real_pthread_self();
// и все остальные функции из pthread
mutex.unlock();
}
Теперь у тебя вызов функций (очевидно, за исключением первого) стоит столько же, сколько и обычный вызов функции из dll — никаких проверок флагов.
Также этот механизм уже доступен кое-где из коробки, то есть без модификации исходного кода. Правда, в таких автоматических решениях иногда, как нас предупреждают, бывают проблемы с потоками и tls, так что на первый взгляд несколько опрометчиво было бы загружать pthreads через этот механизм, хотя может и будет работать.
X>проблема: X>в сборках MinGW-W64, которые я произвожу, и которые используют POSIX можель потоков, libstdc++.dll зависит от winpthreads.dll. X>некоторым юзерам не нравится то, что им приходится "тащить" winpthreads.dll даже в том случае, когда их код не использует потоков. X>мне, по правде говоря, не понятна проблема, ведь winpthreads.dll имеет объем 60-70 Кб, если мне не изменяет память.
X>в общем, хочу сделать так, чтоб winpthreads.dll связывалась динамически, если она нужна.
А что, аналогов MS'овского /DELAYLOAD в MinGW нет?
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Здравствуйте, niXman, Вы писали:
X>>знать бы еще, о чем речь... X>аа, понял. X>нет, этого нет.
Так может лучше сразу delayload имплементировать? Там, насколько я помню идея была простая — в IAT вместо jmp на нужную функцию из dll помещались jmp на вспомогательную функцию, которая и подгружала dll.
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Здравствуйте, Хон Гиль Дон, Вы писали:
ХГД>Так может лучше сразу delayload имплементировать? Там, насколько я помню идея была простая — в IAT вместо jmp на нужную функцию из dll помещались jmp на вспомогательную функцию, которая и подгружала dll.
вот скоро у нас появится официальный "стол заказов" фитчей на реализацию за вознаграждение — тогда, глядишь, кто-то и пронспонсирует реализацию этой фитчи
а сейчас нужно сделать это попроще.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
сейчас у нас в перспективе реализации:
1. SEH for 32bit
2. ability to output PDB
3. porting address/thread/UB -sanitezers
4. implementation of gcc threads backend without pthreads
5. compiler plugin for visual studio
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)