OberonCore https://forum.oberoncore.ru/ |
|
Исправление AllocateClusterMem в mmap замена 65536 на 0 https://forum.oberoncore.ru/viewtopic.php?f=134&t=6959 |
Страница 1 из 1 |
Автор: | arisu [ Пятница, 14 Июль, 2023 17:49 ] |
Заголовок сообщения: | Исправление AllocateClusterMem в mmap замена 65536 на 0 |
проезжая мимо станции, предлагаю в линуксовом HostKernel, в `AllocateClusterMem()` заменить `65536` на нолик в `mmap()`. rationale: это, похоже, была попытка заюзать «дырку» перед образом бинаря (там около двух мегов дырочка). смысла в этом нет никакого, а вот небольшой вред есть. вред такой: сборщик мусора сканирует стек на предмет чего-то, похожего на адреса. он отбрасывает всё, что перед первым кластером, и всё, что после последнего. но! если первое выделение в самом начале памяти, а последнее близко к концу (ядро выделяет странички с конца адресного пространства), то почти никакое значение из стека не отбрасывается, хотя большинство из них не указатели. (в смысле, отбрасываются только по выравниванию.) короче. эта дырка в начале никакой роли не играет, и смысла пытаться её занять нет. зато сканеру стека значительно полегчает. оно, конечно, мелочь на общем фоне — но зачем же. ведь это же очень и очень! |
Автор: | Иван Денисов [ Четверг, 27 Июль, 2023 14:03 ] |
Заголовок сообщения: | Re: BlackBox 2.0 |
arisu писал(а): проезжая мимо станции, предлагаю в линуксовом HostKernel, в `AllocateClusterMem()` заменить `65536` на нолик в `mmap()`. rationale: это, похоже, была попытка заюзать «дырку» перед образом бинаря (там около двух мегов дырочка). смысла в этом нет никакого, а вот небольшой вред есть. вред такой: сборщик мусора сканирует стек на предмет чего-то, похожего на адреса. он отбрасывает всё, что перед первым кластером, и всё, что после последнего. но! если первое выделение в самом начале памяти, а последнее близко к концу (ядро выделяет странички с конца адресного пространства), то почти никакое значение из стека не отбрасывается, хотя большинство из них не указатели. (в смысле, отбрасываются только по выравниванию.) короче. эта дырка в начале никакой роли не играет, и смысла пытаться её занять нет. зато сканеру стека значительно полегчает. оно, конечно, мелочь на общем фоне — но зачем же. ведь это же очень и очень! Вы у себя как-то это уверенно протестировали в сборке на Linux? Попробую поспрашивать Александра про этот момент, тут есть такой промежуток для стека сигналов, может это надо было для этого... Код: sigStackSize = MAX(Libc.SIGSTKSZ, 65536);
|
Автор: | arisu [ Четверг, 27 Июль, 2023 17:31 ] |
Заголовок сообщения: | Re: BlackBox 2.0 |
Иван Денисов писал(а): Вы у себя как-то это уверенно протестировали в сборке на Linux? да. я довольно плотно занимался ядром и mm/gc в эти недели, так что тут я не просто гадаю, я даже понимаю, что это, как работает, зачем и куда. ;-) Большой Грызь теперь понимать как работать маленький ядро.Иван Денисов писал(а): тут есть такой промежуток для стека сигналов, может это надо было для этого... нет, это совсем другое. просто размер стека для обработчика сигналов, который выделяется вот так: `sigStack := Libc.calloc(1, sigStackSize);` (что довольно забавно; щаз проснусь и заменю на mmap; и вот тут, кстати, как раз можно заюзать начало памяти).Код: sigStackSize = MAX(Libc.SIGSTKSZ, 65536); кстати, и безопасную выгрузку модулей можно без особого труда забрать. и ещё починить обработку ^C. да и менеджер кластеров у меня теперь получше будет. в общем, я там неплохо потоптался. все изменения, конечно, сразу же после тестов и коммитов идут в мою рабочую систему. кое-что на этом реально крутится неделями, так что в дополнение к тому, что я понимаю изменения, ещё и полевые тесты. ;-) это я всё в том смысле, что: «да, последний зуб даю!» ;-) p.s.: вообще, я там поставил нолик весьма давно, несколько месяцев назад уж. тогда со смутным пониманием, сейчас с полным. |
Автор: | Иван Денисов [ Четверг, 27 Июль, 2023 18:33 ] |
Заголовок сообщения: | Re: BlackBox 2.0 |
Александр сказал, что если указывать 0, то иногда выделяются отрицательные адреса памяти, и тогда ББ на линуксе ведёт себя некорректно. Как вы эту проблему у себя решили? |
Автор: | arisu [ Четверг, 27 Июль, 2023 18:58 ] |
Заголовок сообщения: | Re: BlackBox 2.0 |
Иван Денисов писал(а): Александр сказал, что если указывать 0, то иногда выделяются отрицательные адреса памяти, и тогда ББ на линуксе ведёт себя некорректно. Как вы эту проблему у себя решили? а это тоже не решение: как только дырка в начале памяти занята (сразу, то бишь) — ядро (которое линукс) мгновенно ревертится на обычный метод выделения, который зависит от многих параметров (а вот от желаемого адреса обычно не зависит вообще). в частности, на моей системе mmap всегда получает страницы начиная с конца памяти, и все адреса всегда отрицательные. сканеру, тащемта, совершенно всё равно, лишь бы кластер не пересёк границу 08000_0000H, тогда нормально работает. знаковое сравнение работает правильно, пока оба адреса одного знака (любое отрицательное ведь всегда меньше 0FFFF_FFFFH). этот факт омики активно используют. а для надёжности можно просто на старте забить область по адресу смены знака, и всё. вообще, с этими знаками там везде сплошные проблемы, и работает оно на честном слове и молитвах. у меня это решено радикально, введением типа `SYSTEM.ADDRESS`, который как раз беззнаковый. но на самом деле оно работало ещё до этого; а хак с 64К не спасал вообще никак. |
Автор: | Иван Денисов [ Четверг, 27 Июль, 2023 20:29 ] |
Заголовок сообщения: | Re: BlackBox 2.0 |
Падать оно падало. Может у вас не падает, так как решили проблему иначе. |
Автор: | arisu [ Четверг, 27 Июль, 2023 21:18 ] |
Заголовок сообщения: | Re: BlackBox 2.0 |
я ж говорю, что убрал это задолго до того, как переделывал kernel на беззнаковые адреса. собственно, посмотрите код kernel, там довольно прозрачно всё (условия циклов и сортировок, не обязательно глубоко вникать). падать оно и может, и будет когда выделено много памяти, и знаки адресов начала и конца какого-то кластера не совпадают. а если знаки совпадают, то сравнения работают как задумано (потому что сканирование идёт по кластерам, и сравнения используются только для определения попадания адреса в границы кластера). ну это… я же вам говорю, что на моей системе mmap при занятом запрашиваемом адресе всегда выделяет страницы начиная с конца. что никак не помешало оригиналу нормально работать ещё в самом начале года, когда я вообще ничего там не менял и просто запускал. а сканер стека в итоге просто считает всю память занятой, потому что минимальный адрес минимальный отрицательный, а максимальный — максимально положительный. там, в общем, получается корректный wraparound. список кластеров всегда отсортирован по возрастанию начального адреса, так что пока какой-то кластер не пересекает магическую границу 08000_0000H — всё работает. более того, даже выравнивание очевидно работает правильно: `(-10 + 3) DIV 4 * 4` — даёт вполне корректное `-8` (выравнивая по направлению к концу памяти). и в любом случае вашему варианту ядра необходимо на старте зарезервировать область памяти (две странички), пересекающую волшебную границу смены знака. иначе при большом потреблении памяти будут волшебные слабо повторимые баги. |
Автор: | Иван Денисов [ Пятница, 28 Июль, 2023 09:51 ] |
Заголовок сообщения: | Re: BlackBox 2.0 |
Есть какой-то тест у Александра, заменим, попробуем. arisu писал(а): и в любом случае вашему варианту ядра необходимо на старте зарезервировать область памяти (две странички), пересекающую волшебную границу смены знака. иначе при большом потреблении памяти будут волшебные слабо повторимые баги. Спасибо за совет. Всё, что повышает стабильность работы надо применить! А как это зарезервировать именно в этом месте? |
Автор: | arisu [ Пятница, 28 Июль, 2023 17:07 ] |
Заголовок сообщения: | Re: BlackBox 2.0 |
как-то типа такого: Код: adr := Libc.mmap(08000_0000H - pageSize, pageSize, Libc.PROT_NONE, Libc.MAP_PRIVATE + Libc.MAP_ANON, -1, 0); IF (adr # Libc.MAP_FAILED) & (adr # 08000_0000H - pageSize) THEN _ := Libc.munmap(adr, pageSize) END; adr := Libc.mmap(08000_0000H, pageSize, Libc.PROT_NONE, Libc.MAP_PRIVATE + Libc.MAP_ANON, -1, 0); IF (adr # Libc.MAP_FAILED) & (adr # 08000_0000H) THEN _ := Libc.munmap(adr, pageSize) END; просто просим у системы две странички на «плохих адресах». если какая-то выделилась в другом месте — ура, нам повезло, плохой адрес уже занят, возвращаем страничку обратно. теперь мы не сможем выделить больше двух гигабайт памяти одним куском (в смысле, одним NEW) — но это всё равно не работало никогда (ядро не позволит, там проверка на переполнение есть). зато и не получим «опасного» кластера. берём странички по отдельности, а не сразу две мы затем, что если просить две, и кто-то уже съел 08000_0000H и дальше, например — то ядро нам даст память в другом месте, и страница перед переходом знака останется без защиты. а там защита нужна, потому что код в Kernel считает конечный адрес для проверок за концом кластера, и использует `<`. если не защитить — то конечный адрес может врапнуться в минус. `08000_0000H` в принципе-то можно и не защищать, но это стрёмное число, лучше его в коде избегать. бережённого, так сказать… `pageSize` уже в коде есть. добавить это надо прямо в Init, в любое место после определения `pageSize`. p.p.s.: короче, отредактировал код в Правильно и Надёжно, прошлый плохой был. |
Автор: | Alexander Shiryaev [ Среда, 02 Август, 2023 19:38 ] |
Заголовок сообщения: | Re: BlackBox 2.0 |
Иван Денисов писал(а): Есть какой-то тест у Александра, заменим, попробуем. Код: MODULE TestKernel_2;
IMPORT Kernel, Log; CONST r1Size = 16; r2Size = 64 * 1024; r3Size = 1024 * 1024; a1Size = 16; a2Size = 64 * 1024; a3Size = 1024 * 1024; TYPE Item = POINTER TO RECORD next: Item; p1: Item1; p2: Item2; p3: Item3; a1, a2, a3: POINTER TO ARRAY OF INTEGER END; Item1 = POINTER TO RECORD x: ARRAY r1Size DIV SIZE(INTEGER) OF INTEGER END; Item2 = POINTER TO RECORD x: ARRAY r2Size DIV SIZE(INTEGER) OF INTEGER END; Item3 = POINTER TO RECORD x: ARRAY r3Size DIV SIZE(INTEGER) OF INTEGER END; VAR finCnt, maxAllocated: INTEGER; PROCEDURE (i: Item) FINALIZE; BEGIN i.p1 := NIL; i.p2 := NIL; i.p3 := NIL; i.a1 := NIL; i.a2 := NIL; i.a3 := NIL; INC(finCnt) END FINALIZE; PROCEDURE NewItem (): Item; VAR res: Item; BEGIN NEW(res); NEW(res.p1); NEW(res.p2); NEW(res.p3); NEW(res.a1, a1Size DIV SIZE(INTEGER)); NEW(res.a2, a2Size DIV SIZE(INTEGER)); NEW(res.a3, a3Size DIV SIZE(INTEGER)); RETURN res END NewItem; PROCEDURE MakeList (n: INTEGER; OUT first: Item); VAR head, last: Item; m: INTEGER; BEGIN NEW(head); last := head; WHILE 0 < n DO last.next := NewItem(); last := last.next; DEC(n) END; first := head.next; m := Kernel.Allocated(); IF m > maxAllocated THEN maxAllocated := m END END MakeList; PROCEDURE ShowStatus; BEGIN Log.String("finCnt = "); Log.Int(finCnt); Log.Tab; Log.String("Kernel.Allocated() = "); Log.Int(Kernel.Allocated() DIV 1024); Log.String(" kB, "); Log.String("maxAllocated = "); Log.Int(maxAllocated DIV 1024); Log.String("kB "); Log.Ln END ShowStatus; PROCEDURE Do (n: INTEGER); VAR list: Item; i: INTEGER; BEGIN ASSERT(0 < n, 20); i := 0; LOOP IF i < n THEN MakeList(i, list); INC(i) ELSIF i < 2 * n THEN MakeList(2*n - i, list); INC(i) ELSIF i = 2 * n THEN ShowStatus; i := 0 ELSE EXIT END END END Do; PROCEDURE Start; BEGIN Log.String("Ctrl+C to stop"); Log.Ln; Do(25) END Start; BEGIN Start END TestKernel_2. |
Автор: | arisu [ Четверг, 03 Август, 2023 02:32 ] |
Заголовок сообщения: | Re: BlackBox 2.0 |
спасибо, мне тоже пригодится. ;-) с резервированием двух страниц-охранников падать не должно ни при каких n (пока памяти хватает). про винду, кстати, я не в курсе, там может упасть — по той же причине пересечения опасного места. я толком не разбирался. вообще, рекомендую аннигилировать режим монокластера в принципе, и переделать виндовый аллокатор по мотивам линуксового, через `VirtualAlloc()`. я у себя ещё кэш кластеров сделал: свободные кластеры живут в нём некоторое время (3-5 сборок), и только потом возвращаются системе. также если надо памяти больше, чем размер кластера (у меня кластеры в 4 мб), то такой кластер не используется для выделения обычных объектов потом. идея в том, что это может быть огромный буфер, и если в нём выделят маленький объект — кластер зависнет выделеным навсегда. так можно у системы всю память выжрать, которая реально не используется. ещё я планирую потом сделать lazy sweep. сейчас GC сразу свипает все кластеры — а можно это делать только по нужде, и маленькими шагами. тогда при большом количестве объектов выделение станет чуть-чуть медленней (но не шибко заметно), зато паузы GC уменьшатся. то есть, GC просканирует и отметит все объекты, но не будет ничего освобождать сразу, а только при следующем выделении, и закончит как только освободит блок достаточного размера. то есть, мы равномерно размажем время на sweep, зато собственно вызов коллектора будет немного быстрее. правда, это потребует небольших изменений в маркере и сборщике: бит «отмечено» больше нельзя будет хранить в type tag, так что придётся его переместить куда-нибудь. |
Автор: | Alexander Shiryaev [ Четверг, 03 Август, 2023 12:34 ] |
Заголовок сообщения: | Re: BlackBox 2.0 |
arisu, спасибо! https://github.com/bbcb/bbcp/commit/57f15fcf5f092ba44225d33712c2be4731cf3a6a |
Автор: | arisu [ Четверг, 03 Август, 2023 12:46 ] |
Заголовок сообщения: | Re: BlackBox 2.0 |
you're welcome, как говорится. я так понимаю, ваши тесты теперь нормально отработали? я у себя гонял — у меня до трёх гб спокойно выделяло. задолбался в итоге ждать, пока окончит (смотрел по htop, забавно прыгало вверх-вниз). правда, я не показатель: у меня адреса типа SYSTEM.ADDRESS (в mainline такого нет), беззнаковые. |
Автор: | Иван Денисов [ Пятница, 04 Август, 2023 10:32 ] |
Заголовок сообщения: | Re: BlackBox 2.0 |
Пакет в Debian репозитории обновил. Этот тест оказывается уже добавили в подситему Check. Модуль CheckKernel2. Проверил ещё на OpenBSD и FreeBSD — работает исправление корректно. Заодно починил в OpenBSD и FreeBSD переустановку сигналов для буфера обмена. Внёс также (мы обсуждали в чате), чтобы для новичков поиск по справке F1 был без учёта регистра, а то не могут найти какие-то полезные вещи, так как галочка Ignore case не совсем очевидна. |
Страница 1 из 1 | Часовой пояс: UTC + 3 часа |
Powered by phpBB® Forum Software © phpBB Group https://www.phpbb.com/ |