Как запустить цикл с определенной скоростью в C (в эмуляции) - PullRequest
0 голосов
/ 19 января 2019

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

Мне было интересно, есть ли какой-нибудь способ, в C, вызывать функцию через определенный интервал (в МГц).Для контекста я пишу это на Mac, так что все, что POSIX или OS X SDK будет работать (я просматривал libdispatch, но ничего не видел).

Было бы лучше просто иметьцикл работает и рассчитывает дельта времени с момента последнего цикла?Это кажется довольно неэффективным (также здесь может стать вытеснение).Каковы будут другие способы сделать это?Спасибо.

Ответы [ 4 ]

0 голосов
/ 19 января 2019

Это будет сложно получить точно, потому что OS X не является системой реального времени.Если абсолютная точность не требуется, я бы использовал интервальный таймер, который истекает каждые 1/n, например, со скоростью «n в секунду», а затем выполняю tick в обработчике истечения.

Aотправной точкой будет POSIX setitimer() и вызов tick в обработчике сигнала

0 голосов
/ 19 января 2019

Боюсь, что это очень трудно (или даже невозможно) архивировать в размещенной системе, если ОС не в реальном времени. OS X не является системой реального времени, и ваши временные параметры будут довольно «случайными», так как ваше приложение будет получать время выполнения системным планировщиком, и оно не будет контролировать выполнение ЦП.

Время переключения контекста и задержка не будут основными проблемами здесь.

Если вы эмулируете поведение целевой системы, вам нужно также связать время выполнения команды целевой системы и во время выполнения эмулятора (в соответствии с текущим прошедшим временем) изменить скорость, с которой эмулируются целевые инструкции

0 голосов
/ 19 января 2019

Сроки на не-RTOS довольно нестабильны, из-за других задач, входящих в системный планировщик и так далее.Представьте, что если во время эмуляции вы откроете окно веб-браузера, все ваши временные интервалы исчезнут.

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

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

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

При таком подходе реальная секунда не будет равна симулированной секунде, но вашаэмуляция всегда будет одинаковой, независимо от других приложений или проблем системного планирования.

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

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

0 голосов
/ 19 января 2019

Использование clock_gettime() и nanosleep() - путь.Какой-то другой механизм, вызывающий вашу функцию периодически, будет определенно медленнее.Вы можете даже рассмотреть циклы и подсчет циклов вместо использования nanosleep().Рассмотрим некоторые цифры:

При частоте 1 МГц ваша функция должна работать 1 микросекунду.На частоте 10 МГц ваша функция должна работать 100 наносекунд.

Некоторые экспериментальные данные о времени системных вызовов и переключениях контекста: https://blog.tsunanet.net/2010/11/how-long-does-it-take-to-make-context.html

Таким образом, для системного вызова она выглядит как более 50 наносекунд.и в течение микросекунды для переключения контекста.Некоторые другие вещи, вызывающие вашу функцию, помимо вашего собственного кода в том же процессе, вероятно, займут «слишком много времени».

...