LINUX.ORG.RU

Царям Си. Задача на синхронизацию.

 ,


1

3

Есть два типа объектов: A и B.

Объекты A выступают в качестве weak pointer. Объект типа A может указывать на объект типа B, а может никуда не указывать (NULL).

Объекты типа B хранят своё название (строка) и произвольные данные и имеют два состояния: не готов или готов. Если объект в состоянии готов, данные можно читать. Если объект в состоянии не готов, данные еще не вычислены.
Каждый объект типа B также хранит список объектов типа A, которые на него ссылаются.

Вся совокупность объектов B образует кэш. Имеется менеджер кэша, который хранит список всех объектов B. В произвольный момент времени менеджер кэша может удалить произвольное число объектов B, если сочтёт, что их «слишком много». Все объекты A, которые содержали указатель на удаленный объект, начинают содержать NULL.

Имеются сервисные потоки, которые подготавливают данные для объектов B и управляют кэшем.
Имеются потоки-клиенты, которые в стеке хранят _указатели_ на объекты A. (Один объект A может быть доступен нескольким потокам.)

Возможны следующие операции:

Для клиентских потоков:

void schedule_A(A *a, char * key);
Если объект B с ключём key имеется в кэше, ссылка на него будет помещена в A.
Если объекта нет в кэше, он будет создан, и ссылка на него будет помещена в A.
Объект B может быть в любом состоянии и изменить состояние с не готов на готов в любой момент времени.

data_t deref_A(A *a);
Если объект A не ссылается ни на один объект B, возвращает специальное значение NONE.
Если объект A ссылается на объект B, и данные в объекте B готовы, возвращает данные.
Если объект A ссылается на объект B, но данные в объекте B не готовы, текущий поток засыпает, пока не произойдёт одно из двух событий:
* Данные станут готовы. (Возвращает данные.)
* Объект A перестаёт ссылаться на какой-либо объект B (начинает ссылаться на NULL). (Возвращает NONE.)

Для сервисных потоков:

B * acquire_by_key_B(char * key);
Ищет объект в кэше и захватывает мьютекст на доступ к нему. (В общем случае возможны разные варианты функций выборки: acquire_oldest_B, acquire_oldest_not_ready_B и т.п.)

void validate_B(B *b);
Отмечает объект как готовый.

void drop_B(B *b);
Отмечает объект как удалённый.

void release_B(B * b);
Освобождает мьютекс на доступ к объекту.
Если объект отмечен как готовый, все клиентские потоки, которые ждали готовности объекта внутри функции deref_A(), просыпаются и возвращают значение.
Если объект отмечен как удалённый, все клиентские потоки, которые ждали готовности объекта внутри функции deref_A(), просыпаются и возвращают NONE, а занятая объектом память освобождается.
Если объект отмечен и как готовый, и как удалённый, флаг удаленный имеет приоритет. (Т.е. клиенты получают NONE.)

Задача:

Придумать алгоритм для указаного выше API, не содержащий race condition. В функциях deref_A(), validate_B(), drop_B() и release_B() алгоритм должен работать с per-object блокировками. То есть, если потоки оперируют непересекающимися наборами объектов, они не должны тормозить друг друга на точках синхронизации. (За исключением логики освобождения памяти внутри release_B(), где возможен глобальный мьютекс на куче.)

Deleted

Последнее исправление: Deleted (всего исправлений: 4)
Ответ на: комментарий от anonymous

ты слышал от меня предложение использовать giant lock?

Я от тебя вообще ничего не слышал, кроме бреда. Но если из твоего потока ругании и оскорблений вычленить здравое зерно, то единственный вывод: ты предлагаешь держать giant lock. Даю подсказку: нереентерабельный обработчик PF уквивалентен giant lock-у.

Ну а твои рассуждения реентерабельность — это просто лол. Если считать за единицу входа в процедуру один ПРОЦЕССОР, то обработчик pf ОБЯЗАН быть реенетерабельным. (Допускать одновременных вход с разных процессоров.) Если ты этого не понимаешь — то в сад, медитировать про giant lock.

Если же считать за единицу входа один СТЕК, то, как я уже говорил, некоторые хакеры пишут, что так работает nt kernel, позволяя войти в PF дважды. Врут или нет, без понятия.

это уже второй твой фейл (после реентрабельности)

Третий класс, вторая четверть. Да ты же школьник.

Мне плевать на подсчёты «фейлов» школьниками. Меня интересует только решение задачи.

Так что иди, обтекай.

Deleted
()
Ответ на: комментарий от Deleted

Да ты же школьник.

Судя по стилю общения, это некий анонимный тимлид. Реализация rw_lock-а от которого используется в каком-то OpenSource проекте. Но в каком не признается.

Походу, реально грамотный чувак. Но полезную информацию приходится вытаскивать клещами.

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Походу, реально грамотный чувак.

Крайне сомнительно. Ибо:

2. ты хочешь сделать реентрабельный обработчик? упоролся?

Deleted
()
Ответ на: комментарий от Deleted

вывод: ты предлагаешь держать giant lock

вывод неверный. потому что ты не в состоянии понять написанное.

ограничимся для начала только этим несчастным обработчиком page-fault-а.

ты решил вытеснить какую-то физическую страницу. тебе нужно инвалидировать все относящиеся к ней pte в системе; причём, за это время никто не должен добавить себе ссылку на неё. осилишь эту операцию без блокировки? теоретически это возможно (см на потуги с pmap в freebsd), но всё зависит от используемых структур данных. ты же выворачиваешь задачу наизнанку: хочешь, чтобы на твои, весьма неудачные, структуры наложили корректные блокировки.

это ещё не всё. таблицы страниц могут вытесняться (поэтому в linux-е были проблемы с dead-lock-ом между vm и fs) или вообще выбрасываться (как в freebsd).

теперь надо поднять нужную страницу. а если она расшарена? всем остальным в своё время тоже валиться в page-fault?

anonymous
()
Ответ на: комментарий от Pavval

вместо царей сплошные аналитики

anonymous
()
Ответ на: комментарий от eao197

Обработчик PF концептуально представляет собой следующий алгоритм (несколько упрощая и опуская часть ветвлений) :

while (1) {
    залочить нужные структуры;
    проверить состояние;
    if (пока мы спали, поток был убит) {
        разлочить структуры;
        запустить алгоритм уничтожения потока; /* не возвращает управление обратно, текущий контекст уничтожается */
    } else if (юзерспейс выполнил недопустимое обращение к памяти) {
        разлочить структуры;
        инициировать соответствующий сигнал;
        return; /* при попытке возврата в юзерспейс автоматически вызовется обработчик сигнала */
    } else if (данные доступны и загружены в PTE) { /* их мог загрузить другой поток */
         разлочить структуры;
         return; /* нормальный возврат в юзерспейс */
    } else if (данные доступны, но не загружены в PTE) {
         загрузить данные в PTE и выполнить TLB shoot down;
         разлочить структуры;
         return; /* нормальный возврат в юзерспейс */
    } else if (данные в процессе подготовки) {
         /* ничего не делать */
    } else if (данные на внешнем носителе) {
         сформировать запрос на загрузку данных;
    }
    разлочить структуры;
    ждать изменения статуса готовности данных или статуса потока; /* здесь происходит вытеснение потока с процессора */
}

Всё, что между «залочить структуры» и «разлочить структуры» — невытесняемый код. Процессор не переключится на другой поток, пока данный поток не отпустит лок.

Однако:

* Любое количество процессоров может исполнять обработчик одновременно (в контексте разных потоков).
* Том числе, для одного и того же адреса страничной ошибки. (потому что к одному адресу может обратиться любое число потоков, и при отсутствии данных все они получат page fault) * Любое количество потоков может спать на строчке «ждать изменения статуса готовности данных».

Как видишь, ничего сложного.

Очевидно, что обработчик реентерабельный, по отношению к:
* процессорам
* потокам
* адресным пространствам
* страничным адресам

К чему он нереентерабельный, так это к контексту исполнения (стеку), т.е. внутри PF нельзя вызывать PF — будет kernel panic (в лучшем случае) или мёртвоё зависание системы (в худшем).

Задача, которую я я писал в OP, касалась алгоритма «залочить структуры» + «проверить готовность данных», а не алгоритма обработчика в целом.

И тут пребегает аноним и наичнает верещать про реентерабельность. Лол.

Deleted
()
Ответ на: вывод: ты предлагаешь держать giant lock от anonymous

ты решил вытеснить какую-то физическую страницу. тебе нужно инвалидировать все относящиеся к ней pte в системе; причём, за это время никто не должен добавить себе ссылку на неё. осилишь эту операцию без блокировки?

Без блокирвоки чего?

хочешь, чтобы на твои, весьма неудачные, структуры наложили корректные блокировки.

«вместо царей сплошные аналитики». (c)
Ты моих структур не видел.

теперь надо поднять нужную страницу. а если она расшарена? всем остальным в своё время тоже валиться в page-fault?

В чем проблема с рашаренными страницами? Для каждой страницы, которая входит более чем в одно адресное пространство, поддерживается структура — список индексов PTE и адресных пространств, в которых страница присутствует.

Когда данные резидентны, ссылку на эту структуру хранит дескриптор физического фрейма. Когда данные нерезидентны, ссылку на эту структуру зранит каждый PTE, который должен ссылаеться на эту страницу.

Deleted
()
Ответ на: комментарий от Deleted

Очевидно, что обработчик реентерабельный

Это спор о терминах. Но, емнип, понятия reentrancy и thread-safety ортогональны друг другу. Вполне может быть реентерабельная функция, которая не будет thread-safe, и наоборот: нереентерабильная-функция, которая является thread-safe.

Так что, с формальной точки зрения, если PF-обработчик реентерабельный, то он должен допускать PF внутри себя. Если же не допускает, то PF-обработчик нереентерабельный.

С другой стороны, я понимаю, чего ты пытаешься достичь: чтобы несколько PF-обработчиков могли работать параллельно на разных процессорах. Но то обычный thread-safety, но не rentrant-safety. На мой непрофессинальный взгляд, по крайней мере.

eao197 ★★★★★
()
Ответ на: комментарий от Deleted

Обработчик PF концептуально

while (1) {

твой третий фейл в этой ветке.

нормальные люди делают так:

1. залочить всю vm и найти структуру данных, относящуюся к нужному процессу. если выбросить твоё наркоманское предположение, что процесс можно прибить во время обработки page-fault-а (что делают все актуальные ос), то этот шаг можно выбросить. вин.

2. залочить структуру vm данного процесса и найти в ней нужный сегмент (таким образом, один поток может поднимать pager-ом свой код, а другой, например, расширять heap). вин.

3. залочить сегмент и найти в нём данные о физической странице. этого никто не делает, потому что лепить структуру на каждые 4к памяти — слишком жирно. можно оставить только блокировку страницы, т.е. в лучшем случае 1 бит. если хочешь попробовать сделать что-то полезное для общества — копай сюда.

4. дальше общаемся с нужным pager-ом и много другого интересного. думаю, для начала тебе и этого хватит.

anonymous
()
Ответ на: комментарий от Deleted

Без блокирвоки чего?

к сожалению, до тебя очень туго доходит. чего — структуры данных, которая содержит всю нужную информацию. поэтому дело именно в структуре.

поддерживается структура — список индексов PTE

когда читаешь очередное предложение, забываешь содержание предыдущего? напомню. если они вытеснены (linux, windows)? если их вообще нет (freebsd)?

ссылку на эту структуру зранит каждый PTE

а говорил, что разобрался с отображением физической памяти в виртуальную, врунишка.

четвёртый фейл.

anonymous
()
Ответ на: комментарий от anonymous

физической памяти в виртуальную =>

виртуальной в физическую

опечатался

anonymous
()
Ответ на: комментарий от anonymous

твой третий фейл в этой ветке.

четвёртый фейл.

Пытаешься косить под Царя, но получается не очень. Во, учись у профессионала парой сообщений выше, как надо исходить на говно.

если выбросить твоё наркоманское предположение, что процесс можно прибить во время обработки page-fault-а (что делают все актуальные ос)

Ты уж определись, «наркоманское предположение» или «делают все актуальные ос». Или научись излагать мысли русским языком.

если выбросить твоё наркоманское предположение

Твоё ядро не сможет установить бит сигнала на потоке, когда он уснул в страничном обработчике? То есть пока поток ожидает подгрузки страницы, все попытки выставить ему сигнальные флаги ты будешь фейлить? Вот это поворот! Кто-то еще рассуждает про «фейлы».

2. залочить структуру vm данного процесса и найти в ней нужный сегмент (таким образом, один поток может поднимать pager-ом свой код, а другой, например, расширять heap). вин.

Я вообще не лезу в дерево маппингов, если данные есть прямо в PTE. Сначала лочится доступ к page table-ам (вернее, лочится некоторое подмножество полного диапазона индексов), проверяется состояние PTE. Если в PTE недостаточно данных, лочится дерево маппингов и читаются данные оттуда.

Далее. Диапазон индексов PTE лочится не весь целиком, а поддиапазонами по 1/32-й части, есть набор 1-битных локов, упакованных в один dword.

Два процессора могут последовательно друг за другом захватить локи, если обрабатывают индексы PTE, относящиеся к разным поддиапазонам.

Вин.

залочить сегмент и найти в нём данные о физической странице. этого никто не делает, потому что лепить структуру на каждые 4к памяти — слишком жирно. можно оставить только блокировку страницы, т.е. в лучшем случае 1 бит. если хочешь попробовать сделать что-то полезное для общества — копай сюда.

Еще раз: в дерево маппингов («сегментов») код лезет только если нет данных в PTE.

В любом случае, после анализа PTE или дерева мы получаем достаточно информации чтобы либо: 1) записать в PTE валидный индекс физического фрейма и выйти из обработчика; либо 2) добавить текущий поток на ожидание в объект синхронизации.

Таким объектом ожидания может быть:
* кондвар готовности в дескрипторе физического фрейма;
* кондвар готовности в объекте-запросе IO к транслирующему драйверу (драйвер трансляции у меня — «тот, кто превращает логическое смещение в секции в адрес физического фрейма»);
* общесистемный семафор ожидания свободной страницы;
* может еще что-то, сразу не упомню.
.

Поток отпускает локи и засыпает на объекте ожидания. Когда просыпается, захватывает локи и повторяет анализ заново.

4. дальше общаемся с нужным pager-ом и много другого интересного. думаю, для начала тебе и этого хватит.

«Общаться с пейджером» обязана совсем другая часть ядра. Если данные лежат во внешней памяти, задача обработчика PF — сформировать запрос ввода-вывода и встать на ожидание. Когда запрос будет обработан, поток проснётся.

к сожалению, до тебя очень туго доходит. чего — структуры данных, которая содержит всю нужную информацию. поэтому дело именно в структуре.

«Вся нужная информация» распределена по:
* базе данных физических фреймов
* PTE-шкам
* деревьям маппингов
* объектам-секциям
* спискам разделяемых страниц

Для всего этого сейчас пишется регламент блокирования: кто, что, в каком порядке и при каких условиях блокирует и разблокирует.

Без блокирвоки

Очевидно, что без блокировок здесь не обойтись. Задачу надо ставить: «свести к минимуму простои процессоров при конкурентном доступе», а не «без блокировок».

когда читаешь очередное предложение, забываешь содержание предыдущего? напомню. если они вытеснены (linux, windows)?

Пока это не планируется для простоты, т.е. таблицы будут невытесняемы. Позже добавлю возможность вытесенения. Алгоритм обработки PF для случая вытесняемых PT очевиден (с упрощениями) :


/* на входе: missing_pte */

/* находим, где отображается содержимое PDE для нашей PT */
uplevel_entry = pte_to_pde_location(missing_pte);

again:

LOCK(uplevel_entry);
if (uplevel_entry не валидный) {
    result = выполнить алгоритм обработки страничного исключения для uplevel_entry.
    UNLOCK(uplevel_entry);
    if (result != uplevel_entry теперь валиден) {
        ждать результат запроса;
        goto again;
    }
}

LOCK(missing_pte);
result = выполнить алгоритм обработки страничного исключения для missing_pte.
UNLOCK(missing_pte);
UNLOCK(uplevel_entry);
if (result != missing_pte теперь валиден) {
    ждать результат запроса;
    goto again;
}

если их вообще нет (freebsd)?

Такого не планируется. Как только PTE был заполнен на основе данных из дерева отображений, он содержит в том или ином виде полезую информацию, пока страница не будет munmap()-лена.

> ссылку на эту структуру зранит каждый PTE

а говорил, что разобрался с отображением физической памяти в виртуальную, врунишка.

Иди подумай, сколько полезной информации можно засунуть в 31 бит (или 63 на x86_64) невалидного PTE.

Сейчас я пытаюсь всунуть туда 6 вариантов состояния:

PTE может находиться в одном из следующих состояний:

* Valid (действителен). PTE содержит PFDI, который одновременной является значением, используемым процессором для аппаратной трансляции.
* Transition (переходный). PTE содержит PFDI, но данные не готовы к отображению (осуществляется ввод-вывод).
* Swapped Out (выгружен). PTE содержит SOCL на данные в файле подкачки.
* Demand Alloc (выделяемый по требованию).
* Shared (разделяемый). PTE содержит индекс SPTEL (для разделяемых страниц). Для выполнения трансляции следует читать данные из головы SPTEL.
* Translation (ожидание трансляции). PTE содержит ссылку на TRREQ. (запрос трансляции)
* Empty (пуст). PTE пуст. Для выполнения трансляции следует обратиться к VAE.

Demand Alloc и Empty можно хранить как частные случаи Swapped Out, зарезервировав два индекса SOCL как заведомо неиспользуемые подсистемой свопа. Остаётся 4 состояния: Transition, Swapped Out, Shared, Translation — надо 2 бита. Еще 4 или 5 бит на флаги.

Даже на 32-битных PTE 24 бита хватит за глаза на полезную нагрузку. PFDI, SOCL и SPTEL — это индексы, с ними легко. TRREQ я планирую хранить как прямой указатель. Это значит, структура TRREQ должна быть выровнена на 256-байтовую границу. Нормально.

А с 64-битными PTE вообще проблем не возникнет.

Deleted
()
Ответ на: комментарий от anonymous

поддерживается структура — список индексов PTE

когда читаешь очередное предложение, забываешь содержание предыдущего? напомню. если они вытеснены (linux, windows)?

В Linux таблицы страниц уже могут быть вытеснены?

tailgunner ★★★★★
()
Ответ на: комментарий от Deleted

Тьфу, неправильно написал. Вместо

LOCK(uplevel_entry);
if (uplevel_entry не валидный) {
    result = выполнить алгоритм обработки страничного исключения для uplevel_entry.
    UNLOCK(uplevel_entry);
    if (result != uplevel_entry теперь валиден) {
        ждать результат запроса;
        goto again;
    }
}

Должно быть:


LOCK(uplevel_entry);
if (uplevel_entry не валидный) {
    result = выполнить алгоритм обработки страничного исключения для uplevel_entry.
    if (result != uplevel_entry теперь валиден) {
        UNLOCK(uplevel_entry);
        ждать результат запроса;
        goto again;
    }
}

Deleted
()
Ответ на: комментарий от anonymous

когда читаешь очередное предложение, забываешь содержание предыдущего? напомню. если они вытеснены (linux, windows)? если их вообще нет (freebsd)?

А, точно, мы ж говорили про принудительное отбирание страницы с инвалидацией PTE. Я как-то не сообразил, что ты такую ерунду спросишь.

Ответ:

Ситуаций, когда PT выгружена, а PTE в ней ранит индекс физического фрейма, не должно возникатьв принципе.

PT может быть выгружена только после того как все индексы фреймов в её PTE-шках были заменены на индексы другого типа (Swapped Out Content Link либо Shared Page Table Entry Link).

Deleted
()
Ответ на: комментарий от Deleted

мы уже читали твои потоки сознания...

... хотя бы в оп-посте. вместо того, чтобы кукарекать о том, как ты разместишь свои флаги конкретно на х86, лучше расскажи как физическая страница, на которую станет смотреть твоя «правильная» pte окажется согласованной для всех использующих её процессов?

anonymous
()
Ответ на: мы уже читали твои потоки сознания... от anonymous

вместо того, чтобы кукарекать

Дать бы тебе в рыло за твою повышенную культурность, анон.

как физическая страница, на которую станет смотреть твоя «правильная» pte окажется согласованной для всех использующих её процессов?

Дескриптор физического фрейма (PFD) хранит ссылку на Shared Page Table Entry List (SPTEL).

SPTEL представляет собой список элементов вида {идентификатор пространства, линейный адрес}, т.е. перечисляет все PTE, ссылающиеся на данный физический фрейм. В голове SPTEL также лежат дополнительные данные — в данном случае это индекс физического фрейма.

Также SPTEL содержит кондвар готовности и битовый флаг transition.

Пусть у нас в момент времени t1 есть N валидных PTE, которые указывают на разделяемый физический фрейм. (данные согласованы)

Процесс ревокации и выгрузки:

Чтобы снять линки на физический фрейм:
SPTEL помечается как пребывающий в состоянии transition. Проходимся по SPTEL и по все перечисленные в нём PTE записываем индекс данного SPTEL.

Это момент времени t2. Все PTE указывают на SPTEL. Данные согласованы.

Для выгружаемых данных выделяется место в свопе (для простоты рассматриваю только случай выгрузки анонимной разделямоей памяти, но для отображений из файлов общая логика та же). Для понятия «место в свопе» используется абстракция, которую я обозвал Swapped Out Content Link. После записи данных на диск, фрейм переносится в списов свободных, а в Content Link записывается в голову SPTEL вместо индекса PFD. Флаг transition снимается, и посылается уведомление через кондвар готовности.

Это момент времени t3. Все PTE указывают на SPTEL. Данные согласованы.

Теперь у нас есть несколько невалидных PTE, которые указывают на SPTEL, а SPTEL указывает на местоположение данных в свопе.

Когда поток ловит страничное исключение на таком PTE, обработчик исключения обращается к SPTEL.

Если он видит, что там установлен флаг transition, он встаёт на ожидание кондвара готовности. Иначе:

Если он видит, что там лежит Content Link, он иницирует запрос ввода-вывода на загрузку данных, запоминает это состояние в голове SPTEL и встаёт на ожидание этого результатов этого запроса. Иначе:

Если обработчик исключения видит, что в SPTEL лежит выполненный запрос на ввод-вывод, он извлекает из него индекс PFD, записывает его в голову SPTEL, затем в PFD сохраняет индес SPTEL, и наконец затем обновляет PTE, чтобы он указывал на физический фрейм. Иначе:

Если обработчик исключения видит, что в SPTEL лежит индекс PFD, значит загрузка уже произошла в другом потоке, и он просто обновляет PTE.

Это момент времени t4. Некоторые PTE указывают на SPTEL, а некоторые на физический фрейм. Данные согласованы, поскольку обработчик страничного исключения может легко перейти от индекса SPTEL к индексу фрейма.

В некоторый момент времени t5 система решит отобрать данный физический фрейм, и см. описание выше. Данные всё так же согласованы.

То, что происходит с этими структурами при fork() и при завершении процесса, оставлю тебе анон, для самостоятельного домысливания.

Deleted
()
Ответ на: комментарий от Deleted

Дать бы тебе в рыло

бомбит, понимаю

записываем индекс данного SPTEL

и сколько элементов будет в этом «массиве»?

выделяется место в свопе

глобальный мьютекс в куче? понимаю.

фрейм переносится в списов свободных

кто и как контролирует доступ к списку?

что имеем в итоге. ты пытаешься переизобрести vm freebsd 4 (конец 20-го века, между прочим). причём, многие моменты не проработаны вообще. остальные на зачаточном уровне — это можно понять хотя бы из того, сколько слов тебе требуется для объяснения.

ну что же, дерзай. технологию 20-летней давности ты, при наличии достаточного упорства (не характерного для юнош) сможешь навелосипедить. правда, в оригинале было много чего ещё. «раскраска» страниц, например.

anonymous
()
Ответ на: комментарий от anonymous

и сколько элементов будет в этом «массиве»?

Сколько ошибок нужно совершить при чтении, чтобы прочитать «массив» в слове List?

кто и как контролирует доступ к списку?

Спинлок контроллирует. Что ты конкретно хочешь узнать?

что имеем в итоге. ты пытаешься переизобрести vm freebsd 4 (конец 20-го века, между прочим).

Я не претендую на оригинальность. Если есть, где почитать развёрнутое изложение устройства vm современной freebsd (КРОМЕ ИСХОДНИКОВ), то давай ссылки.

Почему кроме исходников: потому что мне на данном этапе интереснее самостоятельно походить по граблям, а не изучать исходный код других людей. А вот книжку бы я почитал.

причём, многие моменты не проработаны вообще. остальные на зачаточном уровне — это можно понять хотя бы из того, сколько слов тебе требуется для объяснения.

А с хрена бы они были проработаны на начальном этапе проектирования?

«раскраска» страниц

Это про оптимизацию под процессорный кэш?

ну что же, дерзай. технологию 20-летней давности ты, при наличии достаточного упорства (не характерного для юнош) сможешь навелосипедить.

Когда я был «юноша», этого сайта еще на свете не было.

Если ты знаешь чего-то, чего не знает другой человек, это не даёт тебе права хамить. То, что ты называешь «бомбить», на человеческом языке называется «учить тому, чему отец в своё время недоучил». Например уважению. Или тому, что если вести себя как свинья, то рано или поздно свинью могут лихие люди зарэзат, дарагой. К сожалению, интернет, даёт таким как ты возможность хамить безнаказанно. Одним словом: Царь.

Deleted
()
Ответ на: комментарий от Deleted

давай ссылки

https://www.freebsd.org/doc/en/books/arch-handbook/

можешь поискать на файлопомойках solaris internals. там тоже обсуждаются проблемы выделения памяти при большом количестве процессоров и больших нагрузках.

А вот книжку бы я почитал

правильно, но с поправкой. это надо делать до, а не после вываливания своего потока сознания в онлайн.

анонимус не забывает и не прощает.

anonymous
()
Ответ на: комментарий от anonymous

ещё можно...

...внезапно... windows internals руссиновича и ко. в linux-е сделано весьма похоже с поправкой на внешний интерфейс.

anonymous
()
Ответ на: ещё можно... от anonymous

https://www.freebsd.org/doc/en/books/arch-handbook/

Думаешь, я это не читал? Там поверхностное изложение на уровне «Телевизор — это такой экран на ножках. К телевизору подключается коаксиальный кабель от антены.»

windows internals руссиновича

У Руссиновича на порядок подробнее, чем во FreeBSD Architecture Handbook.

В целом, то, что я делаю, довольно похоже на виртуальную память NT.

Существенное отличие и от NT, и от FreeBSD (насколько я могу судить по её куцему описанию) в том, что у меня анонимная память управляется не при помощи сегментов, а напрямую, on a per-frame basis. Когда анонимная страница становится разделяемой (в частности, при выполнении fork()) для неё создаётся Shared PTE List.

Deleted
()
Ответ на: комментарий от Deleted

Думаешь, я это не читал?

если читал, то невнимательно. попробуй ещё.

анонимная память управляется не при помощи сегментов

это потому, что ты только анонимную память рассматриваешь. сегменты — ключевой элемент во всех открытых реализациях: там ооп во все поля. сегмент — это набор страниц с последовательными виртуальными адресами, которые имеют одинаковые характеристики («члены») и указатели на «виртуальные методы», в частности, для общения со своим pager-ом.

кстати, cow при помощи сегментов делает легко и непринуждённо и не требует прикручивания дополнительного велосипеда.

пысы. могу и плохому научить. берёшь слайды лекции отсюда: http://www.cs.columbia.edu/~krj/os/lectures/L17-LinuxPaging.pdf (там написано как, но не написано почему, в отличие от рекомендованной литературы) и потом либо читаешь как книгу исходники linux-а, либо относительно аргументированно поливаешь говном следующего кто создаст в /development аналогичный тред.

anonymous
()
Ответ на: комментарий от anonymous

сегменты — ключевой элемент во всех открытых реализациях: там ооп во все поля. сегмент — это набор страниц с последовательными виртуальными адресами, которые имеют одинаковые характеристики («члены») и указатели на «виртуальные методы», в частности, для общения со своим pager-ом.

Это понятно.

если читал, то невнимательно. попробуй ещё.

Даже в слайдах по Linux, на которые ты сослался, больше информации, чем в соответствующей главе Handbook-а. Например, нет никакой информации, как FreeBSD хранит обратные ссылки с дескрипторов физических страниц.

http://www.cs.columbia.edu/~krj/os/lectures/L17-LinuxPaging.pdf

Там на странице 31 изображена структура данных. Это такая структура — http://en.wikipedia.org/wiki/Interval_tree ?

Deleted
()
Ответ на: комментарий от Deleted

в слайдах по Linux, на которые ты сослался, больше информации

это не информация, а шпаргалка для студентов, у которых ещё нет навыков чтения кода.

FreeBSD хранит обратные ссылки

pmap

на странице 31 изображена структура данных

это родственная структура, но более общая. на заборе википедии об этом не пишут. я проверил.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.