Pull to refresh

Оптимистичные примитивы синхронизации, очереди и все-все-все. Трагикомедия в трёх действиях

Website development *
Заранее предупреждаю, для тех кто в теме, интересного будет не очень много. :)

У меня появилась актуальная задача реализовать базовые примитивы синхронизации(мьютекс, семафор и read/write lock), используя только синхронную очередь — единственный доступный примитив. Заодно по пути я расскажу как устроены спинлоки и мы даже соберём маленького франкенштейна.

Часть 1: Всё — очереди

Читать дальше →
Total votes 41: ↑30 and ↓11 +19
Views 7.7K
Comments 28

Системные вызовы MIPS

Embox corporate blog Assembler *System Programming *
Этим летом appplemac опубликовал статью, посвященную изучению ассемблера MIPS. В ней, в частности, была рассмотрена команда syscall, генерирующая системный вызов. Автор сосредоточился на объяснении ассемблера MIPS, и на мой взгляд, недостаточно подробно рассказал, что же это такое — системный вызов. Я в тот момент занимался переносом проекта под архитектуру MIPS, разбирался с прерываниями, исключениями и системными вызовами.

Сейчас, когда код уже написан и отлажен, я решил написать статью, которая бы более подробно раскрывала, как работает механизм системных вызовов в MIPS. Можно рассматривать ее как дополнение к той статье об ассемблере.
Читать дальше →
Total votes 33: ↑32 and ↓1 +31
Views 22K
Comments 7

Пишем свой bootloader

Programming *
Sandbox
Это статья была написана для людей, которым всегда интересно знать как работают разные вещи. Для тех разработчиков которые обычно пишут свои программы на высоком уровне, C, C++ или Java — не важно, но при этом столкнулись с необходимостью сделать что-то на низком уровне. Мы будем рассматривать низкоуровневое программирование на примере работы bootloader-а.

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


Читать дальше →
Total votes 101: ↑91 and ↓10 +81
Views 57K
Comments 23

Rust в деталях, часть 2

Programming *Rust *
Translation
Tutorial

Часть 2: Отправка и получение сообщений


В этой серии статей мы рассматриваем процесс создания масштабируемого сервера для чата в реальном времени, во всех деталях. Цель статьи — показать пример практического применения языка Rust на фоне изучения концепций системного программирования и системных API, шаг за шагом.

Вторая часть является прямым продолжением первой, поэтому если вы ее пропустили (или забыли контекст), то рекомендую сначала ознакомиться с ней. В этой части мы продолжаем реализацию протокола WebSocket.
Читать дальше →
Total votes 33: ↑31 and ↓2 +29
Views 14K
Comments 12

Опыт запуска AHCI в VxWorks653

System Programming *

Введение


Я занимаюсь разработкой приложений и драйверов для различных устройств авиационного применения. В Авиации используются ОС с более жесткими требованиями к надежности(ARINC 653), такие как VxWorks653, PikeOS или LynkOS. Разрабатывая приложения для авионики возникла проблема медленного доступа к данным на твердотельных накопителях подключенным по интерфейсу ATA. Это происходило из-за использования медленного программного интерфейса ATA. Я решил эту проблему реализацией драйвера AHCI.

В этой статье Я хочу кратко описать работу AHCI.


Архитектура устройства с AHCI контроллером.

Читать дальше →
Total votes 22: ↑22 and ↓0 +22
Views 10K
Comments 10

Программируем «Мегапроцессор»

Abnormal programming *Assembler *Programming microcontrollers *
Tutorial
На Geektimes летом была статья про Megaprocessor — процессор из дискретных транзисторов и светодиодов, который весит полтонны и занимает всю гостиную в обычном таунхаусе под Кембриджем. Я решил воспользоваться своей географической близостью к этому мегапроекту, и запрограммировать для него что-нибудь презентабельное — например, спортировать для Megaprocessor мою предыдущую хабрапрограммку «Digital Rain».

Система команд Megaprocessor описана на сайте разработчика.

Большинство команд состоят из одного байта, за которым может следовать непосредственный операнд (один или два байта). Регистров общего назначения всего четыре (R0-R3), при этом они не равноправны: например, для команд доступа к памяти адрес должен быть либо в R2, либо в R3; а операнд — в одном из двух оставшихся регистров.

Программистам, привыкшим к системе команд x86 или ARM, набор команд Megaprocessor покажется крайне бедным: нет ни косвенной адресации «база+смещение», ни непосредственных операндов у арифметических команд (за исключением addq ±1, addq ±2). Зато есть пара неожиданных возможностей: отдельная команда sqrt, и режим .wt для команд сдвига, который заменяет результат суммой выдвинутых битов. Таким образом можно, например, парой команд ld.b r1, #15; lsr.wt r0, r1 вычислить количество единичных битов в r0 (вопрос, столь любимый собеседователями на работу!). Мнемоника ld для команды, загружающей в регистр непосредственное значение (вместо привычной по x86 или ARM мнемоники mov) указывает на способ её выполнения: фактически, с точки зрения процессора, выполняется ld.b r1, (pc++).

Итак, приступим.
Total votes 78: ↑76 and ↓2 +74
Views 16K
Comments 5

Как проверить, находится ли значение указателя в заданной области памяти

PVS-Studio corporate blog C++ *System Programming *C *
Translation
Пусть у нас есть регион/область памяти, заданный с помощью двух переменных, например:

byte* regionStart;
size_t regionSize;

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

if (p >= regionStart && p < regionStart + regionSize)

Но гарантирует ли стандарт ожидаемое поведение этого кода?
Читать дальше →
Total votes 40: ↑37 and ↓3 +34
Views 13K
Comments 16

Эволюция системных вызовов архитектуры x86

Assembler *System Programming *

Про системные вызовы уже много было сказано, например здесь или здесь. Наверняка вам уже известно, что системный вызов — это способ вызова функции ядра ОС. Мне же захотелось копнуть глубже и узнать, что особенного в этом системном вызове, какие существуют реализации и какова их производительность на примере архитектуры x86-64. Если вам также интересны ответы на данные вопросы, добро пожаловать под кат.

Читать дальше →
Total votes 77: ↑77 and ↓0 +77
Views 34K
Comments 30

Неканонический режим терминала и неблокирующий ввод на nasm

Assembler *Development for Linux *
Sandbox
Идея написания игры на языке ассемблера, конечно, вряд ли придёт кому-то в голову сама собой, однако именно такая изощренная форма отчетности уже долгое время практикуется на первом курсе ВМК МГУ. Но так как прогресс не стоит на месте, то и DOS, и masm становятся историей, а nasm и Linux выходят на первый план подготовки бакалавров. Возможно, лет через десять руководство факультета откроет для себя python, но речь сейчас не об этом.

Программирование на ассемблере под Linux, при всех своих плюсах, делает невозможным использование прерываний BIOS'a и как следствие обделяет функциональностью. Вместо них приходится использовать системные вызовы и контактировать с api терминала. Поэтому написать симулятор блек-джека или морского боя не вызывает больших трудностей, а с самой обычной змейкой возникают проблемы. Дело в том, что система ввода-вывода контролируется терминалом, а системными функциями Си напрямую пользоваться нельзя. Поэтому при написании даже довольно простых игр рождаются два камня преткновения: как переключить терминал в неканонический режим и как сделать ввод с клавиатуры неблокирующим. Об этом и пойдёт речь в статье.
Читать дальше →
Total votes 24: ↑23 and ↓1 +22
Views 9K
Comments 12

Разработка монолитной Unix подобной OS — Библиотека С (2)

Assembler *System Programming *C *
Tutorial
В предыдущей статье мы научились запускать Hello World ядро и написали пару функций для работы со строками. Теперь пришло время расширить библиотеку С чтобы можно было реализовать kprintf и другие необходимые функции. Поехали!
Читать дальше →
Total votes 21: ↑21 and ↓0 +21
Views 4.8K
Comments 6

Разработка монолитной Unix подобной OS — Системный журнал ядра (3)

Assembler *System Programming *C *
Tutorial
В предыдущей второй по счету статье мы с вами разработали необходимые функции для работы со строками из библиотеки С. В этом уроке мы реализуем полноценный отладочный вывод на экран — системный журнал ядра.
Читать дальше →
Total votes 20: ↑20 and ↓0 +20
Views 4K
Comments 2

Встраиваемые функции в Go

Assembler *Go *
Translation

Go позволяет писать на ассемблере. Но авторы языка написали такую стандартную библиотеку, что бы этого делать не пришлось. Есть способы писать переносимый и быстрый код одновремено. Как? Добро пожаловат под cut.
Читать дальше →
Total votes 27: ↑26 and ↓1 +25
Views 7.5K
Comments 3

О работе ПК на примере Windows 10 и клавиатуры ч. 1

C++ *System Programming *C *C# *Development for Windows *
Sandbox
image

Меня зовут Андрей Артемьев, я работаю в Microsoft над ядром ОС Windows 10, ранее я работал над Windows 10x (WCOS), XBox, Windows Phone и Microsoft Edge. Я хочу популярно в образовательных целях рассказать о том как работает компьютер на примере клавиатурного ввода и Windows 10. Данный цикл статей рассчитан в первую очередь на студентов технических специальностей. Мы рассмотрим какой путь проходит информация о нажатой клавише от клавиатуры до отображения в Notepad.exe. В виду обширности и междисциплинарности темы в статьях могут быть неточности, о которых сообщайте в комментариях. Какая-то информация может быть устаревшей в виду скорости с которой развивается Windows.
Читать дальше →
Total votes 85: ↑78 and ↓7 +71
Views 94K
Comments 412

Назад к истокам: рулим компьютером прямо из MBR

Abnormal programming *Assembler *Delirium coding System Programming *CPU
🔥 Technotext 2020
Tutorial

Разворачивал в очередной раз Linux-образ на USB-drive (почему-то им оказался Manjaro, но это совсем другая история), и в голову пробрались странные мысли: BIOS увидел флешку, а дальше-то что? Ну да, там MBR, скорее всего GRUB и… А раз в MBR затесался чей-то кастомный код, значит и простой человек из Адыгеи может запрограммировать что-нибудь на «большом» компьютере, но вне операционной системы.


А так как делать такие штуки на языках высокого уровня слишком жирно, а ассемблеров мы не знаем, будем шпарить прямо на опкодах для 8086.


Читать дальше →
Total votes 102: ↑102 and ↓0 +102
Views 23K
Comments 77

Что делает Rust универсальным языком программирования

Programming *System Programming *Industrial Programming *Rust *

Владей и заимствуй


Долгое время Rust позиционировался исключительно как язык для системного программирования. Попытки использовать Rust для высокоуровневых прикладных задач зачастую вызывали усмешку у значительной части сообщества: зачем использовать инструмент в том качестве, на которое он не рассчитан? Какая польза от возни с типами и анализатором заимствований (borrow checker), если есть Python и Java со сборкой мусора? Но другая часть сообщества всегда видела потенциал Rust именно как языка прикладного, и даже находила его удобным в использовании для быстрого прототипирования — во многом благодаря его особенностям, а не вопреки им.

Читать дальше →
Total votes 83: ↑78 and ↓5 +73
Views 38K
Comments 234

Вычисления без инструкций на x86

Abnormal programming *System Programming *Virtualization *CPU
Sandbox

В этой статье обсуждается необычное применение особенностей защищённого режима процессоров архитектуры x86 — для произведения вычислений без исполнения инструкций, то есть за счёт внутренних механизмов процессора: аппаратного переключения задач, хитроумного управления памятью и логики вызова обработчика прерываний. Как известно, любая сколько-нибудь сложная система обладает полнотой по Тьюрингу, поэтому мало удивительного в том, чтобы найти её в неожиданных местах естественно эволюционировавшей x86. Приглашаю под кат интересующихся подобными низкоуровневыми извращениями.

Читать дальше
Total votes 65: ↑65 and ↓0 +65
Views 11K
Comments 8

Свежий взгляд на честное 3D в браузере

Abnormal programming *JavaScript *Game development *

Приветствую.

Так получилось, что некоторое время назад я принимал участие в проекте, разрабатывал браузерную игру с принципиально новым подходом в хранении данных - предполагалось создать некую вариацию на тему .krieger, игру, которая использовала бы экстремально мало памяти для хранения ресурсов, сохранив при этом высокополигональность моделей, пусть и жертвуя при этом производительностью. Ввиду комплекса причин - проект закрылся, не выпустив даже MVP - но у нас остался серьезный пласт наработок, которыми я, с дозволения остальных участников команды поделюсь тут. Само собой, с авторскими комментариями и рассмотрением идеи. Подробности под катом.

Читать далее
Total votes 11: ↑9 and ↓2 +7
Views 4.4K
Comments 7

Введение в неблокирующие алгоритмы

Programming *C++ *C *Development for Linux *
Translation

Неблокирующие алгоритмы широко применяются в ядре Linux когда традиционные примитивы блокировки либо не могут быть использованы, либо недостаточно быстры. Эта тема многим интересна и время от времени всплывает на LWN. Из недавнего — вот эта июльская статья, которая собственно и сподвигла меня написать свою серию. Ещё чаще разговор заходит про механизм read-copy-update (RCU — руководство 2007 года всё ещё актуально), подсчёт ссылок, и способы сделать более понятные, высокоуровные API ко всему этому разнообразию. Ну а сейчас вас ждёт погружение в идеи, стоящие за неблокирующими алгоритмами, а также их использованием в ядре.


Знание низкоуровневой модели памяти в целом считается продвинутым уровнем понимания, которого страшатся даже опытные программисты-ядерщики. Словами нашего редактора (из его июльской статьи): «Понять модель памяти можно лишь правильно повёрнутым мозгом». Говорят, что моделью памяти Linux (и файлом memory-barriers.txt в частности) можно пугать детей. Порой для достижения эффекта достаточно всего лишь рявкнуть “acquire” или “release”.


И в то же время, механизмы вроде RCU и seqlocks так широко применяются в ядре, что практически каждый разработчик рано или поздно сталкивается с фундаментально неблокирующими интерфейсами. Поэтому многим будет полезно иметь хотя бы базовое представление о неблокирующей синхронизации. В этой серии статей я расскажу, что же на самом деле означает acquire и release-семантика, а также приведу пять сравнительно простых паттернов, которые покрывают большинство вариантов использования неблокирующих примитивов.

Читать дальше →
Total votes 39: ↑36 and ↓3 +33
Views 17K
Comments 60

Приёмы неблокирующего программирования: атомарные операции и частичные барьеры памяти

Programming *C++ *C *Development for Linux *
Translation

В первой статье цикла мы познакомились с простыми неблокирующими алгоритмами, а также рассмотрели отношение “happens before”, позволяющее их формализовать. Следующим шагом мы рассмотрим понятие «гонки данных» (data race), а также примитивы, которые позволяют избежать гонок данных. После этого познакомимся с атомарными примитивами, барьерами памяти, а также их использованием в механизме “seqcount”.


С барьерами памяти некоторые разработчики ядра Linux уже давно знакомы. Первый документ, содержащий что-то похожее на спецификацию гарантий, предоставляемых ядром при одновременном доступе к памяти — он так и называется: memory-barriers.txt. В этом файле описывается целый зоопарк барьеров вместе с ожидаемым поведением многопоточного кода в ядре. Также там описывается понятие «парных барьеров» (barrier pairing), что похоже на пары release-acquire операций и тоже помогает упорядочивать работу потоков.


В этой статье мы не будем закапываться так же глубоко, как memory-barriers.txt. Вместо этого мы сравним барьеры с моделью acquire и release-операций и рассмотрим, как они упрощают (или, можно сказать, делают возможной) реализацию примитива “seqcount”. К сожалению, даже если ограничиться лишь наиболее популярными применениями барьеров — это слишком обширная тема, поэтому о полных барьерах памяти мы поговорим в следующий раз.

Читать дальше →
Total votes 11: ↑11 and ↓0 +11
Views 9.2K
Comments 3
1