Как сделать полноценный SEH

Kernel architecture questions
  • Засыпаю, посему обрывки мыслей:

    ИМХО то как Sexual Exception Handler сделан в Win (FS:0) - не лучший способ. Для меня предпочтительнее интерфейс UNIX (POSIX) сигналов. Так же нужно подумать о возможности вложенных обработчиков (очередь обратоки, не обработал крайний - передается предыдущему, и т.д. вплоть до системного - просто прикрывающего процесс, как сейчас ). Ещё нужно не забыть дать возможность установки выделенного стека для обработчика, простой пример: исключение ESP - на границе памяти, pop *... Ну и раз уж мы отдаем обработку исключений приложению, и система у нас мультизадачная, то и двойного исключения при ошибке в пользовательском обработчике (например затирание кода...), аппаратно возникать не будет, это надо отслеживать программно (новое состояние процесса?). Кроме того с сигналами можно сделать и человеческий таймер, и как ни как это IPC.
  • Дык время-то еще детское (было) :D
    Ну ты главное проснувшись - продолжи :)

    1) Про FS:0 спорить не буду. Да, как-то и не принято, как мне показалось, в KoApi, чтобы ядро само аллоцировало память, и хитро возвращало ее потоку... Даже стек при создании потока - проблемы пользователя. Ну так и пущай, к примеру, при создании потока в аргументах идет не только адрес вершины стека, но и его дна. А там и будет располагаться TLS. В котором одним из значений и будет номер исключения...

    2) Ну если не FS:0, то может быть некий фиксированный адрес в адресном пространстве потока??? Точнее, одно из полей хедера. Что сразу приводит к следующей версии хедера, а в этом поле исходно (design-time) и будет прошиваться адрес TLS стартового потока приложения. Ну а do_change_task тупо, но честно, будет писать туда адрес текущего - не супер и работа-то...
    : Кстати говоря, у меня давно было желание про следующую версию хедера, чтобы одним из полей был адрес таблицы импорта....

    3) Про POSIX - должной эрудицией не обладаю... Но мне пока кажется: мухи - отдельно, котлеты отдельно. Способы раскрута, и место сохранения информации для этих раскрутов - это дело третьего кольца. Про системную библиотеку говорить можно бесконечно... Где-то уже говорил, что это должно получиться (имхо) вовсе не виндячие user32, а наоборот - больше похожее на некую визуальную библиотеку + некую системную некого языка. Чтобы для запуска пустой формы было достаточно двух операций: создания некого апплета, и запуска его метода Run :wink:
    А попробуй такое сделать - сразу же упрешься в ограничения KoApi
    И seh - один из таких вопросов, где сразу упираешься. Ну вот, я со стороны ядра и пытаюсь потихоньку чистить ситуацию...

    4) Как-то меня не очень напрягают повторные исключения... В том смысле, что делай некий супер стек, не делай его - все равно пользователь сумеет уронить приложение. А зачем платить больше, если нет разницы :)
    Но, согласен. Некий флаг работы в исключении - заводить в APPDATA будет нужно. Ну типа, в основном режиме работает фильтр перехвата, а перехвативши - он как бы и "нулевой", и любое исключение, это "Process - forced terminate" (ну или debug_notification)

    5) Про таймеры... Ну опиши конкретно свое видение интерфейса. Вплоть до номеров ф-й/подф-й...
    Возьму да сделаю... Обсудивши коротенько
    Типа, я уже самый большой специалист по "правильным ожиданиям" :lol:
  • Если tls не очень большой можно сделать персональную страницу для каждого потока и мапить её при переключении контекста.
  • Serge, Вы имеете в виду фиксированные адреса в приложении для всех потоков ???
    Тогда какие....
    В смысле, как бы это могло выглядеть со стороны пользователя :?:

    Хотя, если напихаем туды барахла на 4К это уже больше на винду будет похоже, чем на Kolibri :)
    Мне пока понятнее наоборот - значительно меньше, чем 4К
  • Приложение определяет адрес и размер tls (можно и через заголовок) а ядро для каждого потока создаст персональную страницу и будет мапить её на этот адрес. В этом случае доступ к данным tls будет для программиста таким же простым как и к обычным данным, без разных ухищрений.

    для fasm

    Code: Select all

    
    tls          dd tls_begin        
    tls_size   dd tls_end-tls_begin
    
    align 4096
    tls_begin:
    
    var1 dd ?
    var2 dd ?
    var3 dd ?
    
    align 4
    tls_end:
    
    для gcc
    int local_data __attribute__ ((section (".tls))) = 0;

    Большинство компиляторов яву умеют размещать данные в именованых секциях. В крайнем случае данные можно объявить extern а tls секцию сделать на асме.
  • Угу, согласен. Доступ будет проще на одну косвенность...
    В том варианте, что я думал, программисту очень просто добраться до переменной, которая лишь указывает на TLS (зато ядру практически ничего делать не надо)

    Чего смущает: мы скидываем на пользователя выравнивание этого блока (как по адресу, так и по размеру) на пользователя
    Ошибется разок, захватив 4К-блоком по настоящему глобальные переменные - вот намучается-то коллега :)
    Подумать надо......


    Такой вопрос: а насколько мы связаны в своих фантазиях проблемами совместимости :?:
    В смысле, использовал ли кто уже имеющиеся хуки на FPU и SSE :?:
    Думаю себе... Ну предположим, в калькуляторе (или еще где) мы решили посчитать логорифм отрицательного числа...
    Оказываемся в хуке, и чего мы там должны делать ???
    Простой ret, это повторение пройденного. Следовательно, надо делать что-то типа ljmp (играться со стеком, в общем) в то место, где эти неправильные данные формировались, и чего-то каким-то макаром исправлять
    Даже интересно посмотреть бы...
  • На работу ядра ошибка не повлияет, это главное. А страховать программиста от всех возможных ошибок ядро не обязано.

    Обработка исключений FPU есть в Open Watcom. Всё работает и протестировано. fpeinth.asm - пример обработчика.
  • Кстати там эмулируются сигналы POSIX. Библиотека устанавливает свой первичный обработчик. Он производит анализ исключения FPU. Потом из таблицы обработчиков сигналов вызывается пользовательский обработчик если он установлен.

    Code: Select all

    void __sigfpe_handler( int fpe_type )
    {
        __sig_func  func;
        
        func = SignalTable[ SIGFPE ];
        if( func != SIG_IGN  &&  func != SIG_DFL  &&  func != SIG_ERR ) {
            SignalTable[ SIGFPE ] = SIG_DFL;      /* 09-nov-87 FWC */
            (*(__sigfpe_func)func)( SIGFPE, fpe_type );        /* so we can pass 2'nd parm */
        }
    }
  • Уточню вопрос :)
    Реально ли сделать изменения в системной библиотеке Open Watcom, чтобы она не пользовалась f68:15/18, но предоставляла те же (вообще-то - большие) возможности прикладному программисту :?:
    Грубо говоря, чтобы он ничего незаметил...
    Естественно, после того, как мы закончим нашу постановочную часть.

    Откуда ноги растут
    Эти хуки сегодня локализованы в строках 135-141 файла sys32.inc. Теперь же просто в глаза бросается, что вместо этого надо лепить один универсальный.
    Можно конечно пытаться оставить и то, и другое... Но не факт, что это получится полноценно и без костылей. Да и смотреться будет типа: "здесь играть, здесь не играть, а здесь рыбу заворачивали..."
    Вопрос исключений при делении на 0, и программистам на Open Watcom - тоже не безынтересен должен быть...

    Вот еще....
    Поясните, если можно, Ваши магические слова про POSIX, и егойные "сигналы". На 100% не надо, скажем так - "тремя фразами", но чтобы хоть базовое понимание осталось...
    Уровень моей образованности примерно таков: с nix-ами сроду дело не имел. Сделать любого типа перехваты исключений в винде через winApi - да без проблем (как это делается конкретно на VC - тоже знаю).
    А вот чтобы поднять это на ЯВУ - мегабайты кодов же перелопатить надо :(
    Фиг поймешь, где там чего начинается, и где заканчивается...
    На ассемблере оно как-то "по-настоящему" и поэтому значительно более понятно.
    Serge wrote:А страховать программиста от всех возможных ошибок ядро не обязано
    Дык собственно, я не о страховке говорил...
    Добавлю даже, что и бесполезно.
    Просто смотрю, есть два варианта... Оба вроде должны быть работоспособны.
    Какие есть факторы: а) насколько это вызывает суету в ядре при переключениях б) насколько это вредоносно, или наоборот - удобно пользователю.
    Вот и все :)
    Для себя - я еще и сам не понял окончательно. Может и еще какие факторы есть, кроме вышепречисленного, и более приоритетные
    Будем спешить не торопясь...
  • Не уверен что нужен именно один универсальный. #gpf, #pf это одно, а исключение fpu или sse совсем другое. Валить всё в одну кучу - только усложнять код. Фактически получится что сначала ядро сгребает все исключения вместе чтобы вызвать одну единственную функцию, а потом функция должна снова разобрать эти исключения и вызвать для каждого свой обработчик. Ненужная двойная работа.

    Исключения POSIX подробно описаны в gnu libc manual
  • Serge, дык ты возьми и сравни.

    Это раньше была двойная работа. Можно даже сказать, что очень много двойной работы. Да и не всегда одинаково эта, одна и та же работа, в разных местах выполнялась...
    А #pf и так возвращался в основной обработчик - это вовсе не мои же фантазиию. И нет ничего плохого в возможности перехвата #pf, от которого отказался основной обработчик
    Честное слово - ничего плохого :)

    Как бы я пытался сохранить функциональную эквивалентность.
    А вот except7 (не помню его фамилию) - вроде ДА, ты прав, не чего ему в этой кухне вариться
    Дык я его и не "втаскивал"...

    В общем, насчет усложнения - не соглашусь. Пол-Кб на этой ерунде скинулось...
    А по мне, так и понятнее все стало в три раза...
    Вот же ж оно все перед глазами, на одной страничке, а не в пяти разных файлах :)
  • А по мне, так и понятнее все стало в три раза...
    А по мне нет. Это я вполне серьёзно.
    Ассемблер не самый читабельный язык, а заоптимизированность делает код совсем непонятным. Т.е. то что хорошо для микроконтроллеров не обязательно хорошо для Колибри. У программиста не должно пропадать желание разбираться в исходниках после первого взгляда на них. Потому что это система не для одной железяки ( запустили в космос и все - пусть себе летает. Для следующей железяки сделаем совершенно новую систему, лет через двадцать).

    Кстати макрос proc coздаёт кадр стека push ebp/mov ebp, esp
    Мне кажется что этот код теперь работает не так как раньше

    Code: Select all

    proc except_16       ;fpu native exceptions handler
            test    byte [esp+8+2], 2
            jnz     v86_except_16
  • И ещё. После изменений в экспортируемых функциях ядра надо увеличивать номер драйверной модели чтобы ядро не пыталось загрузить несовместимые драйверы. Текущий номер в ядре
    DRV_COMPAT equ 5 ;minimal required drivers version
    DRV_CURRENT equ 5 ;current drivers model version
    надо заменить на 6. И в драйверах тоже.
  • 1) Этот код вообще никак не работает. Его просто нет в kernel.mnt
    Макрос proc, кроме всего прочего, еще и окружает все это дело условием if used ProcName
    А префиксы входа, и макрос ret он переопределяет только по необходимости
    Умный такой макрос...
    Если не записаны аргументы, и не применено locals - ничего он и не добавит.
    Такое окружение я сделал с единственной целью - чтобы в случае "большого глюка" было легче откатываться
    Альтернатива была - совсем выкинуть

    2) Serge, ну я ведь тоже серьезно. Ну трудно разбираться в кодах, которые раскиданы по 3-5 файлов, когда фактически все это умещается на страничке.
    Сейчас это - просто первые 200 строк в sys32 (вместе с коментариями, определениями дескрипторов, и т.п.)
    Честное слово, я значительно больше трачу время, чтобы найти все хвосты, чем на рефракторинг.
    Вполне серьезно. Не, ну не сумашедший же я, чтобы писать так, чтобы сам ничего не понял
    Например, как заморочены IRQ - я до конца еще и не понял.
    Трудно потому-что. И мне кажется, что именно такое может отбить желание.

    Пример: полчаса примерно разбирался, чем же занимается checkidle, и минут пять писал тот код, который сейчас (rev 1055).
    Если бы сразу на него смотрел, то 5 минут и разбирался бы.
    Это гипотеза конечно, но именно так я вполне серьезно и думаю...
    Ну не пишу я так, чтобы сначала мне было понятно, а потом зашифровываю оптимизацией. Не, я сразу в таком стиле и пишу.
    Ну да, когда задача уже кем-то решена, оптимальные (и понятные!!!) варианты сделать гораздо проще...
    Чем когда рисуешь коды с нуля. В таком состоянии далеко не всегда знаешь чем оно закончится
    А тут уже: вот оно, все и целиком, и ничего другого не будет
    Это я не виноват, это закон природы такой... Я и над своими кодами издеваюсь НЕ МЕНЬШЕ... Стиль такой: работаешь, работаешь - а кодов с каждым днем становится все меньше и меньше.

    А про C++ Ну блин... Порой перестаешь понимать, кто для кого: язык для нас, или мы для языка...
    В ассемблере все честно - раз, два, и ты вышел на спецификацию проца...

    В качестве offtopa
    Была у меня история с C++ :wink:
    Я ведь на полном серьезии верил, что сей продвинутый ЯВУ экономит время разработки
    И довольно глубоко юзал IAR-овский CPP для avr-ок
    Кстати говоря, по качеству: Борман или Gcc - рядом не стояли. У них особая технология линковки, которая разрешает т.н. "проблему отложенных конструкторов". Ну это так....
    Да, экономит... Если ты делаешь работу, которую можно поднять за день
    А вот через пару месяцев работы посмотришь в коды, и понимаешь, что когда задача уже прояснена на столько, то сделать этот же код на ASM-е - не больше 2-х дней. При лучшем качестве.
    Сравните это с 2-мя месяцами, или пол-годом...
    Это при всем при том, что не просматривать с пристрастием сгенерированные коды (в дизасме, например) сим компилятором - себе дороже. У меня это настолько в привычку вошло, что я даже и kernel.mnt в hiew посматриваю (про proc выше, это не я такой умный, это результаты наблюдений)
    Есть такой фактор: ты борешься не только со своей проблемой (задачей), но и с компилятором

    Serge, это все я - абсолютно серьезно. Закинул я этот компилятор
    НО я никого в свою веру обращать не хочу...
    Однако поверьте, рассказанное - не просто правда. Это больше чем правда. Так оно и было на самом деле
    Не, ну давай я, к примеру, в три раза больше комментов писать буду.... :)

    3) Ага, понял. Спасибо
    Только кое-что уточнить надо...
  • Who is online

    Users browsing this forum: No registered users and 3 guests