__declspec(thread) – dynamic initialization

Тема в разделе "WASM.ZEN", создана пользователем catwalk_mission, 2 июн 2009.

  1. catwalk_mission

    catwalk_mission New Member

    Публикаций:
    0
    Регистрация:
    23 май 2009
    Сообщения:
    19
    привет =)

    сейчас разбирал исходники crt к VS2008 и появилось несколько вопросов.

    __declspec(thread) – dynamic initialization
    в исходниках crt есть файлы tlsdyn.c и tlsdtor.c. код в этих юнитах предназначен для вызова заглушек, которые должны инициализировать динамические __declspec(thread) переменные.

    проблема в том, что при попытке воспользоваться динамической инициализацией компилятор негодует:
    Код (Text):
    1. обыкновенная, статическая инициализация:
    2. __declspec(thread)
    3. int id = 2Ah;           // fine
    4.  
    5. __declspec(thread)
    6. ClassWithoutCtorAndDtor xclass; // fine too
    7.  
    8.  
    9. динамическая инициализация:
    10. __declspec(thread)
    11. int id = GetCurrentThreadId();  // error C2482: dynamic initialization of 'thread' data not allowed
    12.  
    13. __declspec(thread)
    14. ClassWithCtorOrDtor xclass; // error C2483: object with constructor or destructor cannot be declared 'thread'
    _
    что сказано насчёт этих ошибок в MSDN:
    _
    о`кей, хорошо. но зачем тогда тогда такая поддержка в crt? ведь даже в стартовом коде (__tmainCRTStartup & Co) есть несколько строк, обеспечивающих корректную инициализацию динамических __declspec(thread)-переменных:
    Код (Text):
    1.              /*
    2.              * If we have any dynamically initialized __declspec(thread)
    3.              * variables, then invoke their initialization for the primary
    4.              * thread used to start the process, by calling __dyn_tls_init
    5.              * through a callback defined in tlsdyn.obj.
    6.              */
    7.             if (__dyn_tls_init_callback != NULL &&
    8.                 _IsNonwritableInCurrentImage((PBYTE)&__dyn_tls_init_callback))
    9.             {
    10.                 __dyn_tls_init_callback(NULL, DLL_THREAD_ATTACH, NULL);
    11.             }
    есть какая-нибудь информация насчёт этого? возможно, существует какой-нибудь секретный ключ компилятора? или, может быть, поддержка dynamic __declspec(thread) изначально планировалась, но потом была отменена из-за каких-то неизвестных сложностей реализации? в общем, интересуют как факты, так и просто мысли по поводу всего этого.
    другие вопросы позже =)
     
  2. s0larian

    s0larian New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2004
    Сообщения:
    489
    Адрес:
    Крыжёпполь
    Это Thread Local Storage (TLS) и после декларации значение, обычно, вписывает поток. То есть, компилер хочет видеть "static expression" - то что можно вычеслить at compile time.
     
  3. catwalk_mission

    catwalk_mission New Member

    Публикаций:
    0
    Регистрация:
    23 май 2009
    Сообщения:
    19
    uguu~, tls: вычислить во время компиляции, положить в секцию .tls так, чтобы данные оказались между переменными _tls_start и _tls_end и т.д... со статическим_статическим tls компилятор на пару с линкером справляется прекрасно =)
    а вот динамический_статический tls жевать не хочет: c2482, c2483.
    вот и стало интересно – могут ли быть некие причины (какие-нибудь особенности ос или vc), из-за которых эта функциональность не может быть реализована? или она реализована, но... но?
     
  4. s0larian

    s0larian New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2004
    Сообщения:
    489
    Адрес:
    Крыжёпполь
    Так спроектировано что загрузчик/crt инициализирует такую переменную и следовательно хочет получить значение из .exe образа. Раз так, то значение ты должен отдать компилеру и оно будет в какой-то там секции.

    Можно ли сделать инициализацию динамической? Да можно, если этот "контракт" (это ABI spec) расширить до таблицы с обработчиками, которые будут вызваны для получения этих иницализаторов.

    Чичас этого нету. Если хочешь копать, можешь добавить всё это в GNU gcc toolchain и потом расшитить Linux ядро.

    Бессмысленный разговор...
     
  5. catwalk_mission

    catwalk_mission New Member

    Публикаций:
    0
    Регистрация:
    23 май 2009
    Сообщения:
    19
    всего-то и нужно, что научить компилятор делать для инициализации подобных переменных такие же заглушки, какие он уже делает для конструирования глобальных объектов... ладно, похоже, в этой теме сейчас действительно не много смысла... s0larian, спасибо за feedback. =)
     
  6. Ustus

    Ustus New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2005
    Сообщения:
    834
    Адрес:
    Харьков
    catwalk_mission
    И когда их выполнять?
     
  7. catwalk_mission

    catwalk_mission New Member

    Публикаций:
    0
    Регистрация:
    23 май 2009
    Сообщения:
    19
    ага, отличный вопрос.
    указатели на заглушки помещаются между переменными '__xd_a' и '__xd_z', в секцию '.CRT'. функция '__dyn_tls_init' проходит по этим указателям, вызывая их. а вот указатель на '__dyn_tls_init' помещается в псевдосекцию '.CRT$XLC', попадая как раз между переменными '__xl_a' и '__xl_z' – прямиком в массив tls-callback'ов. т.е. '__dyn_tls_init' будет вызываться каждый раз при вызове tls-callbacks, и, если (reason == DLL_THREAD_ATTACH), она будет вызывать заглушки.
    [каждая заглушка инициализирует переменную и регистрирует деинициализатор, который вызывается из tls-callback'а в случае (reason == DLL_THREAD_DETACH или DLL_PROCESS_DETACH)].