Просмотр полной версии : Перемещаемость на лету
Придумайте, как писать программу так, чтобы она могла быть в любой момент прервана (INT) и перемещена в памяти (возможно, с пересчётом каких-то ячеек по какому-то списку, возможно, динамически генерируемому). Так что при возврате указатели на переменные или массивы устаревают. И стек вызовов тоже. Допустим, перемещение производится по 256 или кратное число байт.
Мне пока видятся только следующие методы:
1) Типизация стека и регистров. В стек каждый раз пишется не 2 байта, а 4 (данные и тип - число/указатель). Области смены типа регистров, а также EXX'ы обрамляются системными вызовами.
2) Чтение данных по указателям - только через системные вызовы (очень медленно!). В указателях только смещения относительно начала блока программы. CALL и RET - через системные макросы (тоже по смещению, и в стеке лежит смещение точки возврата).
3) CALL и RET - через системные макросы (в стеке лежит смещение точки возврата). Типы регистров никогда не меняются.
Если указатели - HL и DE, то проблема с 16-битной арифметикой.
Если указатели - IX и IY, то всё медленно.
Если только один указатель и буферизация данных в стеке, то ещё медленнее и вообще изврат.
Компромисс - IX и DE (или DE и DE').
4) Интерпретируемый язык (очень медленно!).
Если код еще можно перемещать, но интерпретация произвольного 16-битного (или даже 8-битного) значения в регистре как изменяемого адреса - это утопия.
Компромиссный вариант- захват ресурсов через системные вызовы. На время захвата гарантируется неперемещаемость ресурса.
Ересь
одна команда LDIR убьет данные
если делать перемещение
ld hl,data1
ld de,data2
ld bc,size
call data_move - то тут я даже не могу предположить как надо извращаться что бы передать 1 байт и не попасть под INT и какую скорость это даст
я бы предложил написать трассировщик и больше не задумывался
Критические секции сделать легко. Идея мне нравится. А какие есть идеи по конкретной реализации CALL-RET?
А какие есть идеи по конкретной реализации CALL-RET?
Подфункции? Каждый процесс (я правильно тебя понимаю?) может содержать таблицу патчей для таких целей.
Да, чтоб упростить себе жизнь, процессор объявляется таким же ресурсом, как и память. Т.е. кодовый сегмент процесса может перемещаться только после того, как он (процесс) явно вызвал sleep/wait/yield.
Цитата:
Сообщение от alone
А какие есть идеи по конкретной реализации CALL-RET?
Подфункции? Каждый процесс (я правильно тебя понимаю?) может содержать таблицу патчей для таких целей.
Нельзя использовать команду CALL, потому что она кладёт в стек абсолютный адрес.
Т.е. кодовый сегмент процесса может перемещаться только после того, как он (процесс) явно вызвал sleep/wait/yield.
Чревато повисаниями всей системы.
---------- Post added at 16:19 ---------- Previous post was at 16:15 ----------
Поставим вопрос по-другому: можно ли реализовать относительный вызов без критической секции? Если нет, то как это доказать?
Нельзя использовать команду CALL, потому что она кладёт в стек абсолютный адрес.
ld hl,subroutine
call Invoke ;system call
Чревато повисаниями всей системы.
С чего это?
ld hl,subroutine
call Invoke ;system call
И тут между call и первой командой системного вызова внезапно прерывание. Твои действия?
С чего это?
Глюки программистов неистребимы. Особенно с таймингами.
И тут между call и первой командой системного вызова внезапно прерывание. Твои действия?
Вы находитесь в закрытой комнате без окон и дверей и вам нужно выбраться. Ваши действия?
Зачем себе ставить заведомо сложные условия чтоб потом биться о них головой и с криком "ура" преодолевать? Разумные ограничения и инварианты- путь к свободе принятия решений, как это ни парадоксально.
Глюки программистов неистребимы. Особенно с таймингами.
Глюки таймингов- это самые безобидные из глюков, которые могут быть. Запись не по тому адресу не может быть отловлена и будет иметь гораздо более плачевные последствия.
К тому же, есть прерывания, на которых может висеть не только шедулер, но и монитор дедлоков.
Зачем себе ставить заведомо сложные условия чтоб потом биться о них головой и с криком "ура" преодолевать?
Это условие обусловлено архитектурой 128K.
Дим, как писать программу не используя CALL:RET?
что это будет за программа?
тут только один вариант
ld iy,return_adress
ld ix,procedure_adress
jp cheduler_call
return_adress
jp cheduler_ret
procedure_adress
jp cheduler_ret
по приходу на cheduler_call сторим iy и переходим на ix
по приходу на cheduler_ret возвращаемся на последнее сохраненное
но у меня слов нет по такому извращению
проще и быстрее будет интерпретатор ЯВУ типа FORTH или тотже оберон
Это условие обусловлено архитектурой 128K.
Условие кривых программистов, не умеющих пользоваться кооперативной многозадачностью?
Как выглядит архиватор при кооперативной многозадачности?
Как выглядит архиватор при кооперативной многозадачности?
Вызвать yield на каждый процент прогресса, не? Или явно вызвать resсhedule при нехватке памяти не?
Если там архивируется 100500 мегабайт, проценты редковато пойдут.
А если вызывать по каждому килобайту, то на быстрых машинах будут абсолютно лишние переключения.
Если там архивируется 100500 мегабайт, проценты редковато пойдут.
А если вызывать по каждому килобайту, то на быстрых машинах будут абсолютно лишние переключения.
А если быть готовым, что программа будет прервана в любой момент, то на всех машинах будут абсолютно лишние затраты.
Определись с ограничениями. Как говорится "либо крестик снимите, либо трусы оденьте". Нет ничего хорошего универсального.
Barmaley_m
21.03.2012, 21:35
Перемещение программы на лету - действие не критическое, которое можно отложить на достаточно длительное время - порядка нескольких секунд и дольше. Поэтому я не вижу проблемы в том, что программа будет периодически вызывать системную функцию, которая осуществляет перемещение. То есть поток почти всегда будет находиться в состоянии, запрещающем перемещение, и лишь иногда позволять его.
Даже если программа содержит баг и не будет никогда вызывать упомянутый системный вызов - максимум, чем это грозит - это повышенной фрагментацией памяти. Это не крах системы. А с учетом того, что у Z80 нет защищенного режима, крах системы из-за бага в программе может произойти по тысяче других причин (DI/HALT, например).
А если быть готовым, что программа будет прервана в любой момент, то на всех машинах будут абсолютно лишние затраты.
Если шедулер не будет вызываться с частотой 50 раз в секунду, то сдохнет всё, что привязано к таймеру - например, музыка.
Даже если программа содержит баг и не будет никогда вызывать упомянутый системный вызов - максимум, чем это грозит - это повышенной фрагментацией памяти. Это не крах системы.
Релокацией управляет ОС, а не сама программа. Необходимость релокации может возникнуть при запуске или снятии другой задачи, в любой момент.
Если шедулер не будет вызываться с частотой 50 раз в секунду, то сдохнет всё, что привязано к таймеру - например, музыка.
Под прерыванием программы я подразумеваю ее останов и релокацию.
Barmaley_m
22.03.2012, 01:46
Если шедулер не будет вызываться с частотой 50 раз в секунду, то сдохнет всё, что привязано к таймеру - например, музыка.
Не знаю как сейчас, а во времена дисководов запрет прерываний на длительное время - неизбежность при работе любой оси. Соответственно, дохнут часы, музыка, опрос клавиатуры. Никуда от этого не денешься.
Релокацией управляет ОС, а не сама программа. Необходимость релокации может возникнуть при запуске или снятии другой задачи, в любой момент.
Все равно, релокация программ не является критичной функцией системы. Она может подождать. Пока система ждет, что какая-нибудь программа позволит себя релоцировать, она может выполнять эту и другие программы, то есть эффективный прогресс работы ОС будет продолжаться.
При снятии задачи ничего срочно релоцировать не надо - память и ресурсы только освобождаются. Негативно на работе остающихся задач это не сказывается, а консолидация памяти может подождать.
При запуске новой задачи релокация может потребоваться только если фрагментация памяти не позволяет выделить достаточно непрерывных кусков для новой задачи. Но это тоже может подождать. Даже на мощных современных компьютерах запуск некоторых программ длится долго, секунды и даже минуты. Тем более в условиях недостатка памяти, когда система начинает свопиться. А ожидание фрагментации как раз и может возникнуть только в ситуации недостатка памяти.
Ситуация облегчается тем, что дефрагментация памяти по необходимости (а не фоновая) не требует обязательно релоцировать конкретную программу. Задача стоит освободить непрерывный блок, где бы он ни находился. Если одновременно работают несколько задач - то даже если одна из них не готова к релокации, то могут быть готовы другие. Их и релоцировать.
---------- Post added at 23:46 ---------- Previous post was at 23:33 ----------
Если там архивируется 100500 мегабайт, проценты редковато пойдут.
А если вызывать по каждому килобайту, то на быстрых машинах будут абсолютно лишние переключения.
Можно по каждому килобайту таймер проверять и, если прошла секунда - переключаться на системный вызов. Я так делаю в своих программах, где требуется индикация прогресса.
А еще эффективнее - не по килобайту, а по заранее рассчитанному объему работы, который даже на медленных компьютерах не будет выполняться дольше секунды. Тем самым минимизируется количество даже проверок таймера.
1) Типизация стека и регистров. В стек каждый раз пишется не 2 байта, а 4 (данные и тип - число/указатель). Области смены типа регистров, а также EXX'ы обрамляются системными вызовами.
Достаточно будет 1 раз "зарегистрировать" (при загрузке) для задачи мета-данные описывающие по какому смещению от начала "адресса в памяти" и перечень тех регистров которые содержат адресса, позже можно добавить или поменять "декларацию" по ходу выполнения программы, чтобы OS всегда хранила для каждой задачи все места где лежат указатели. Со стеком можно поступить жестко - определить ему место с адреса #ffff и запретить его использование кроме как для адресов возврата (т.е. в нем будут только 2-х байтные адреса возврата). Для передачи параметров в функции использовать регистры.
2) Чтение данных по указателям - только через системные вызовы (очень медленно!). В указателях только смещения относительно начала блока программы. CALL и RET - через системные макросы (тоже по смещению, и в стеке лежит смещение точки возврата).
Нужно эмулировать виртуальную память c таким интерфейсом:
1. выделить регион памяти (возвращает id региона)
2. получить указатель на регион памяти и зафиксировать его (при этом он становится неперемещаемый)
3. инвалидировать указатель на регион и разрешить его премещение
4. освободить память занимаемую регионом
При этом вместо адресов на структуры в памяти нужно будет передавать id региона.
3) CALL и RET - через системные макросы (в стеке лежит смещение точки возврата). Типы регистров никогда не меняются.
Если указатели - HL и DE, то проблема с 16-битной арифметикой.
Если указатели - IX и IY, то всё медленно.
Если только один указатель и буферизация данных в стеке, то ещё медленнее и вообще изврат.
Компромисс - IX и DE (или DE и DE').
Тут нужно будет ввести понятие short call - который сможет и напрямую работать (при условии что тот кого он собрался вызывать перемещается всегда вместе с тем кто использует этот short call). Ну и far call - через системный вызов.
4) Интерпретируемый язык (очень медленно!).
[/QUOTE]
Что значит очень? forth даст замедление в 3...4 раза всего то, это сравнимо со скоростью компилируемой программы на С, при этом размер стека можно сделать автоконтроллируемым и легко использовать всю спекки память из форт программы не замечая ограничения адреса в 16bit.
alone, загляни в исходники mp/m. там программы перемещаемые. всё придумано до нас. софтина компилируется под адрес 0. в конце файла есть карта. перемещаемость кратная 256 байт если не ошибаюсь. более детально тебе подскажет исходник самой mp/m. если надо, то смотреть тут (http://www.cpm.z80.de/source.html). разделы mp/m I и mp/m II.
alone, загляни в исходники mp/m. там программы перемещаемые. всё придумано до нас. софтина компилируется под адрес 0. в конце файла есть карта. перемещаемость кратная 256 байт если не ошибаюсь. более детально тебе подскажет исходник самой mp/m. если надо, то смотреть тут. разделы mp/m I и mp/m II.
Я в свое время для спека делал поддержку компиляции релоцируемых объектников со всеми таблицами http://zxdocs.fatal.ru/coding/module.zip
Не знаю как сейчас, а во времена дисководов запрет прерываний на длительное время - неизбежность при работе любой оси.
Дисковод не нужен. Есть винты/карточки.
Со стеком можно поступить жестко - определить ему место с адреса #ffff и запретить его использование кроме как для адресов возврата
Нужен стек для регистров, иначе невозможно реализовать даже самые примитивные системные вызовы типа переключения страниц. Они должны быть реентерабельными, так что сохранять в переменные не могут, только в стек.
Тут нужно будет ввести понятие short call - который сможет и напрямую работать (при условии что тот кого он собрался вызывать перемещается всегда вместе с тем кто использует этот short call).
Требует опять-таки стека только для адресов, то есть невозможно (см. выше).
alone, загляни в исходники mp/m. там программы перемещаемые. всё придумано до нас. софтина компилируется под адрес 0. в конце файла есть карта. перемещаемость кратная 256 байт если не ошибаюсь. более детально тебе подскажет исходник самой mp/m. если надо, то смотреть тут. разделы mp/m I и mp/m II.
Где там перемещаемость на лету?
forth даст замедление в 3...4 раза всего то
Это на математических задачах. А на задачах перемалывания памяти скорее раз в 30..40.
Нужен стек для регистров, иначе невозможно реализовать даже самые примитивные системные вызовы типа переключения страниц. Они должны быть реентерабельными, так что сохранять в переменные не могут, только в стек.
Аналогично стеку malloc тоже выделяет память так что храни свои регистры в выделенном регионе памяти. Скорость выделения конечно намного меньше чем через стек. Прийдется продумывать наперед какой кусок запросить чтобы не вызывать malloc сильно часто. Тяжелый и тормозной случай только рекурсия (не знаешь сколько памяти попросить). Но реентерабельность будет обеспеченна.
---------- Post added at 10:49 ---------- Previous post was at 10:36 ----------
Это на математических задачах. А на задачах перемалывания памяти скорее раз в 30..40.
Ну классический forth с одним стеком давно умер. Я имел в виду виртуальную машину которая выполняет команды из очереди инструкций которые оперируют стеками данных через указатели на вершины стеков (команды типа (SP1+offset) + (SP1+offset+1) -> (SP2+offset)).
Я имел в виду виртуальную машину которая выполняет команды из очереди инструкций которые оперируют стеками данных через указатели на вершины стеков (команды типа (SP1+offset) + (SP1+offset+1) -> (SP2+offset)).
Можно пример кода, реализующего аналог следующего?
loop
ld a,(hl)
cpl
ld (de),a
inc de
cpi
jp pe,loop
Можно пример кода, реализующего аналог LDIR?
я в фортах не силен :) но смысл в том что есть команды копирования значений из одного стека в другой и непосредственно в память, стеки в этом случае содержат как бы массивы регистров.
Чтобы выполнить элементарную команду на форте, нужно не меньше 100 тактов. А в этом цикле их надо 7.
Чтобы выполнить элементарную команду на форте, нужно не меньше 100 тактов. А в этом цикле их надо 7.
Возможно, мне тоже не понравились те процессоры которые IMak разрабатывает (стековые), сделать такой виртуальный тоже не легко наверное будет тормоз. Хотя подкупает идея маленького контекста задачи который надо сохранять при переключении, но на практике как оно выглядит не представляю.
Так а что с этой темой? Есть ли более менее полная картина как можно реализовать на спеке эфективную многозадачную среду?
Barmaley_m
27.03.2012, 20:35
Так а что с этой темой? Есть ли более менее полная картина как можно реализовать на спеке эфективную многозадачную среду?
Эффективная многозадачная среда и перемещаемость на лету - это разные вещи. Одно может существовать без другого. Ты определись, что тебя больше интересует.
по перемещаемости смотрите пакет MONS/GENS!!!
Killer, они перемещаемы на лету?
Есть ещё одно решение: все программы разрезать на сегменты по 256 байт (это может делать в теории любой язык программирования, даже ассемблер, но реально ни один не умеет) и при запуске фигурно размещать по нижней памяти. Все массивы должны быть <=256 байт, иначе должны размещаться в верхней памяти. И никакого свопа, то есть одновременно можно запустить только 24 килобайта программ (даже если ось в страничке).
Barmaley_m
28.03.2012, 00:06
Не 24, а 32. Экран тоже можно отправить в страничку. И потом, некоторые компьютеры могут поставить ОЗУ по адресам младших 16кб. Ось должна поддерживать такую возможность. С ней имеем еще 16кб.
Но это уже оффтопик, это ось-концепции, а тема была изначально о перемещаемости на лету.
Andrew771
28.03.2012, 09:46
по перемещаемости смотрите пакет MONS/GENS!!!
Всегда интересовало, как там сделано. Использование jr и не использование call? :)
Andrew771, там вначале таблица релокации - они настраиваются при первом запуске и всё!
jerri, Согласен, не на лету, но принцип можно применить.
jerri, Согласен, не на лету, но принцип можно применить.
Применить где? Для перемещения уже запущенной программы? Так ведь про то и тред - с регистрами, стеком и указателями-то что делать?
Алко, сделай эмулятор или зет80 или ещё какого камня. Оптимальнее не вижу.
Т.е. виртуальная машина с трансляцией адресов/команд, с инструкциями уровня ассма.
Задача релокации - как часто нужна? Можно ли без неё обойтись? Памяти же много?
Верхней памяти много, а нижней мало.
alone, вот и сделай простую виртуальную машину
4 24битных регистра
стек, флаги, PC
минимальный набор команд и вперед
Сомневаюсь, что это даст какой-то выигрыш по сравнению с критическими секциями или разбиением по 256 байт. По скорости уж точно.
alone, ну зато на спеке будет своя виртуальная машина :)
можно с наворотами :)
Сомневаюсь, что это даст какой-то выигрыш по сравнению с критическими секциями или разбиением по 256 байт. По скорости уж точно.
Я че-то никак не пойму сути разбиения на 256 байтные куски, можешь детально обьяснить как это должно сработать?
По поводу виртуальной машины, софт эмулятор раз в 5...10 медленее реального процессора, т.е. для той скорости которая была на реальном компе с 7mhz 68000 потребуется z80 со скоростью примерно 50...70mhz и с такой же быстрой памятью, да?
Максагор
30.03.2012, 12:30
Придумайте, как писать программу так, чтобы она могла быть в любой момент прервана (INT) и перемещена в памяти (возможно, с пересчётом каких-то ячеек по какому-то списку, возможно, динамически генерируемому). Так что при возврате указатели на переменные или массивы устаревают. И стек вызовов тоже. Допустим, перемещение производится по 256 или кратное число байт.
Дима, а чем не подходит принцип, реализованный в iS-DOS (для остальных - обсуждаем сам принцип, а не систему) для резидентов. В тамошнем асме, если компилировать не запускаемый COM-модуль, а резидент (копиляция по ключу /r создает перемещаемый RES-файл), в конце создаваемого после компиляции файла после метки конца "пришивается" табличка с казателями на все критические COM/JP и иже с ними, значение в которых надо менять, добавляя или отнимая смещение при смене стартовых" координат. Эта схема в iS-DOS работает, когда надо добавить или удалить драйвер. Например при удалении драйвера из ряда подключенных, остальные смещаются вверх, занимая освободившееся место, и все переходы в них пересчитываются по табличке.
Я че-то никак не пойму сути разбиения на 256 байтные куски, можешь детально обьяснить как это должно сработать?
После удаления процессов память превращается в решето. И целую программу туда уже не всунуть. Зато если программа состоит из маленьких кусочков, её можно распихать по дырам.
Дима, а чем не подходит принцип, реализованный в iS-DOS (для остальных - обсуждаем сам принцип, а не систему) для резидентов.
Тем, что в резидент входят и выходят, а в программе крутятся.
После удаления процессов память превращается в решето. И целую программу туда уже не всунуть. Зато если программа состоит из маленьких кусочков, её можно распихать по дырам.
Ясно, но если код и данные перемещаемы то можно их просто уплотнять (два эти подхода смахивают на свои эквиваленты - форматы дисков TRDOS и FAT12).
Вообще думаю данная тема должна рассматриваться в более широком смысле - runtime для z80 позволяющий под него компилить более менее современные исходники. А основные задачи мне видятся такими:
1. изза ограниченного адресного пространства у z80 нужно иметь механизм для эфективной трансляции 24bit\32bit адресов в спековский <номер страницы + смещение внутри страницы>;
2. нужно иметь код который не привязан к конкретным адресам и в идеале перемещаемый на лету;
Вероятно решить эти задачи можно но скорее с серьезной потерей скорости.
Сам по себе Z80 проблем не испытывает - можно прикрутить к нему 4 окна памяти или даже сегментную адресацию. Проблема на архитектуре 128К, которая в общем-то мертва, но если под неё есть адекватное решение, то почему бы не обсудить :)
Разумеется, перемещаемость лучше, потому что даже одна программа может иметь больше 24К кода, например, Pro Tracker, BGE, Melon, Lara Croft.
Сам по себе Z80 проблем не испытывает - можно прикрутить к нему 4 окна памяти или даже сегментную адресацию. Проблема на архитектуре 128К, которая в общем-то мертва, но если под неё есть адекватное решение, то почему бы не обсудить :)
Чето я опять не до конца понял о чем это? Как окна решают озвученные проблемы? "Прикрутить сегментную адресацию" - что тут подразумевалось, разделить память инструкций и данных? Это уже есть например в PDP-11 но толку мало, обьем всеравно смешной на данный момент. В моем понимании именно Z80 испытывает основные проблеммы с его 16bit адресами + отсутствием команд адресации относительно PC.
Как окна решают озвученные проблемы?
У каждой программы своя страница(ы) кода и своя страница переменных и стека. Их не придётся релоцировать.
"Прикрутить сегментную адресацию" - что тут подразумевалось, разделить память инструкций и данных?
Да. Проверяя коды команд внешней логикой. Можно даже сделать сегменты совершенно аналогично IBM PC, т.е. перекрывающиеся. И опять не придётся релоцировать.
Ты на вопрос не ответил: как часто нужно перемещение запущенного кода? Нужно ли это вообще или это из категории просто хороших хотелок?
Нужно после удаления или десвопа задач. Без этого сама идея батников отправляется в помойку.
а нельзя сделать компромисс? скажем, правилом хорошего тона будет в главном цикле периодически вызывать спец. системную функцию, в которой может произойти перемещение кода. т.о., мы всегда будем знать, что сейчас перемещать безопасно, стек пуст, регистры не содержат нужной информации.
Это будет не правило хорошего тона, а ограничение при написании программ. Я предлагаю рассматривать только те варианты, которые можно реализовать автоматически в компиляторе.
Это будет не правило хорошего тона, а ограничение при написании программ. Я предлагаю рассматривать только те варианты, которые можно реализовать автоматически в компиляторе.
Т.е. тщательно следить за тем, чтобы не накакать в чужую память- это нормально (MMU ведь нет), а вот необходимость отдавать управление системе, делая кооперативную многозадачность- это ограничение. Может стоит начать с изучения основ и анализа возможностей?
Не взлетит...
А если упростить задание, абстрагироваться от zx-128 и представить себе любой виртуальный процессор который нужен. Возможно ли вообще сделать код и данные перемещаемыми на лету? Что для этого нужно от процессора?
Т.е. тщательно следить за тем, чтобы не накакать в чужую память- это нормально (MMU ведь нет)
Чтобы насрать мимо своей памяти, надо сильно постараться.
а вот необходимость отдавать управление системе, делая кооперативную многозадачность- это ограничение.
Не просто отдавать, а не реже, чем раз во фрейм. Для этого надо тоже сильно постараться, если программа представляет из себя нечто большее, чем окошко с кнопкой. Программа печатает текст. За фрейм не успеет - значит, надо вызывать систему каждую строку. Стоп! А вдруг строка больше 1000 символов? Значит, каждый символ. Стоп! А вдруг символ во весь экран? Значит, каждую линию символа.
---------- Post added at 12:00 ---------- Previous post was at 11:57 ----------
А если упростить задание, абстрагироваться от zx-128 и представить себе любой виртуальный процессор который нужен. Возможно ли вообще сделать код и данные перемещаемыми на лету? Что для этого нужно от процессора?
Сегменты или индексная адресация во всех командах, включая CALL и RET.
Чтобы насрать мимо своей памяти, надо сильно постараться.
Да ну?
Не просто отдавать, а не реже, чем раз во фрейм.
Для чего? Прерывания никто не отменял.
Для чего? Прерывания никто не отменял.
Прерывания тут причем? Речь шла о "добровольном" сохранении адресов в заранее известное системе место и последующей передаче управления системе с тем чтобы система смогла произвести перемещение модуля и произвести коррекцию адресов в модуле.
Я пересмотрел старые сообщения в теме и пришел к выводу что для перемещения процесса на лету нужно:
1. иметь отдельно стек адресов и стек данных (чтобы при перемещении знать что корекции подлежит только содержимое стека адресов);
2. иметь сведения о группе регистров используемых ТОЛЬКО для хранения адресов, т.е. должен быть системный вызов который мог бы добавить\убрать регистры из этой группы;
3. иметь карту памяти процесса в которую должны входить:
- все выделенные области памяти (те которые были выделенны при загрузке и те которые полученны от системы позже в процессе работы);
- адреса используемые процессом (включая адресса используемые для CALL\JP, адреса указывающие на сегменты данных (.data .bss) а так же адреса хранящиеся в выделенной в процессе работы памяти и тоже указывающие на сегменты данных (.data .bss) или возможно использующиеся для CALL\JP);
Кроме того, сама по себе "перемещаемость на лету" только НЕМНОГО поможет решить проблемы возникшие в результате ограничений накладываемых битностью логических адресов (16/24/32/64). Т.е. в принципе "перемещаемость на лету" обеспечит возможность SWAP-a и\или виртуальной памяти, но НЕ расширит прямоадресуемое пространство, поэтому для операции SWAP-a нужно будет пересылать немалые обьемы и терять на этом скорость, ну и кроме того процесс который физически не влазит в логическое адресное пространство всеравно не сможет быть запущен на такой системе.
Так что интереснее рассмотреть вопрос: "Как запустить процесс требующий памяти больше чем логически адресуемое пространство?"
bigral, а если я обращаюсь к какимто данным?
я могу на стеке (даже стеке данных) хранить как ссылки на информацию так и счетчики
Прерывания тут причем?
А зачем отдавать управление системе каждый фрейм?
Речь шла о "добровольном" сохранении адресов в заранее известное системе место и последующей передаче управления системе с тем чтобы система смогла произвести перемещение модуля и произвести коррекцию адресов в модуле.
Я предложил более простой и очевидный вариант:
- процесс работает столько, сколько считает нужным. Все это время его никто не перемещает (кооперативная многозадачность)
- когда процесс решает прерваться (сам), он вызывает системную функцию шедулинга. В процессе вызова процесс _может_ быть перемещен по памяти (только кодовая область)
- процессы, требующие прерываний, регистрируют callback в системе
- выделенные блоки памяти адресуются не адресами, а хендлами. Для получения абсолютного адреса и работы делается системный вызов. При этом блок запирается и не перемещается никуда. Когда процесс заканчивает работать с блоком, делается другой вызов и указатель становится невалидным (хендл остается).
Выделенные блоки памяти просто-напросто должны быть в верхней памяти, тогда перемещать их не потребуется.
Фигурно добавлять вызовы неизвестно где - ОС делается не для того, чтобы стало труднее писать, а для того, чтобы было легче писать.
И да, критическая секция - это 21 такт на вход и 31 на выход. Не так уж и страшно, можно хоть на любую операцию адресации вешать. Это может делать компилятор. А вставлять вызовы ОС в хитро продуманных местах он не может.
К сожалению, остаётся ограничение на размер кода. Чтобы его обойти, надо программные модули оформлять в виде задач. Например, есть редактор паттерна (одна задача), а есть редактор сэмпла (другая задача). Когда пользователь хочет перейти к редактированию сэмплов, первая задача передаёт второй нужные данные и уходит в своп, взамен вылезает вторая. А какая-то часть редактора (например, плеер) всегда остаётся в памяти - третья задача.
Фигурно добавлять вызовы неизвестно где - ОС делается не для того, чтобы стало труднее писать, а для того, чтобы было легче писать.
Почему фигурно? Практически все приложения- это цикл, перемежающий полезные действия и ничегонеделание. Вот в рамках этого цикла и нужно возвращать управление системе.
---------- Post added at 18:28 ---------- Previous post was at 18:27 ----------
И да, критическая секция - это 21 такт на вход и 31 на выход. Не так уж и страшно, можно хоть на любую операцию адресации вешать. Это может делать компилятор. А вставлять вызовы ОС в хитро продуманных местах он не может.
В С может быть и не может, а вот в том же С++ задача прекрасно решается идиомой RAII.
что имел в виду я: многозадачность может быть любая, хоть вытесняющая, прерывающая прогу в любом месте. но тогда ее никто не имеет право перемещать. но иногда прога должна вызывать эту спец. функцию, и тогда, если хочется сделать move (или делали недавно, но эту прогу не переместили, т.к. она была "занята"), делается move.
т.е. не одномоментная акция. а нужна ли она одномоментная?
И да, критическая секция - это 21 такт на вход и 31 на выход. Не так уж и страшно, можно хоть на любую операцию адресации вешать. Это может делать компилятор. А вставлять вызовы ОС в хитро продуманных местах он не может.
Ты предполагаешь шедулер на прерывания повешенный?
соглашение о DI перед запуском критической секции? и EI после оной?
Никаких DI,EI. Это теряет прерывание.
Критическая секция оформляется так:
ld hl,flag
inc (hl)
...
ld hl,flag
dec (hl)
call nz,os_проспали_прерывание
Практически все приложения- это цикл, перемежающий полезные действия и ничегонеделание. Вот в рамках этого цикла и нужно возвращать управление системе.
Должна быть возможность писать под ОС не только "практически все" приложения, но и вообще все приложения. Например, архиваторы и компиляторы, которые могут занимать процессор на 100% минутами.
И я выше приводил пример с печатью текста, где хрен поймёшь, куда вставлять вызов ОС.
Должна быть возможность писать под ОС не только "практически все" приложения, но и вообще все приложения. Например, архиваторы и компиляторы, которые могут занимать процессор на 100% минутами.
И я выше приводил пример с печатью текста, где хрен поймёшь, куда вставлять вызов ОС.
Тогда прочитай то, что написал psb. Отдельно многозадачность, отдельно перемещаемость.
Powered by vBulletin® Version 4.2.5 Copyright © 2026 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot