nedoPC-580 (SMP на 5 процессорах КР580ВМ80А)

Публичный форум для http://www.nedopc.org/nedopc

Moderator: Shaos

User avatar
Shaos
Admin
Posts: 24006
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Post by Shaos »

HardWareMan wrote:
Shaos wrote:Не совсем понял кого её не будет и что показал осциллограф...
Короткой записи же.
хм, а какая запись будет?...
HardWareMan wrote:
Shaos wrote:P.S. Я смотрю что слово статуса хватать с шины данных совсем не сложно - так что наверное будут у нас нормальные порты с командами IN и OUT :)
По большому счёту нам только 2 бита нужны из этого слова состояния - INP и OUT
Латчить по SYNC AND F1 в одну ТМ2. Все верно.
угу

тогда обращение к хардверному семафору, защищающему доступ к софтверным мьютексам (а также 7 другим критическим абстракциям - по 1 биту на каждую), будет выглядеть так:

Code: Select all

DI
MVI A,#10
OUT 7 ; пусть на этом порту находятся 8 хардверных семафоров
LOOP:
IN 7
ANI #10 ; бит 4 пусть будет семафором мьютексов
JZ LOOP ; крутимся пока ноль (значит наш запрос семафора ещё не дошёл)
; далее висим на холде либо идём дальше
...
XRA A
OUT 7
EI 
P.S. Биты в порту 7 можно поделить между следующими "семафорами":

Code: Select all

bit 0 - SEM_PRO (доступ к списку всех процессов)
bit 1 - SEM_ACT (доступ к списку активных процессов)
bit 2 - SEM_SCR (доступ к буферу вывода на экран)
bit 3 - SEM_IOB (доступ к буферу обмена с внешними устройствами)
bit 4 - SEM_MUX (доступ к списку программных мьютексов)
bit 5 - SEM_PIP (доступ к FIFO каналам обмена данными)
bit 6 - SEM_MSG (доступ к очередям сообщений)
bit 7 - SEM_AUX (дополнительный семафор)
P.P.S. Семафоры внутренние, т.е. не входят в публично доступный API - это лишь соглашение о взаимодействии супервайзера (процессор номер ноль) и операционки на рабочих процессорах...
Я тут за главного - если что шлите мыло на me собака shaos точка net
User avatar
Lavr
Supreme God
Posts: 16680
Joined: 21 Oct 2009 08:08
Location: Россия

Post by Lavr »

Shaos wrote:Кстати на фирменных диаграммах сигналы F1 и F2 соотносятся так:

Code: Select all

F1 _|^|_________|^|_

F2 ______|^^^|______
На фирменных диаграммах тут указывают минимальный интервал между спадом F1
и фронтом F2.
В этом же случае:

Code: Select all

F1 _|^|_______|^|_ 

F2 ___|^^^|_____|^
Этот минимальный интервал примерно и получается.
iLavr
User avatar
Shaos
Admin
Posts: 24006
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Post by Shaos »

Lavr wrote:
Shaos wrote:Кстати на фирменных диаграммах сигналы F1 и F2 соотносятся так:

Code: Select all

F1 _|^|_________|^|_

F2 ______|^^^|______
На фирменных диаграммах тут указывают минимальный интервал между спадом F1
и фронтом F2.
В этом же случае:

Code: Select all

F1 _|^|_______|^|_ 

F2 ___|^^^|_____|^
Этот минимальный интервал примерно и получается.
Угу - я уже потом прочитал в таблице времён, что между спадом Ф1 и фронтом Ф2 минимум 0 нс может быть, т.е. всё ок
Я тут за главного - если что шлите мыло на me собака shaos точка net
User avatar
Shaos
Admin
Posts: 24006
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Post by Shaos »

Ха, до меня только что дошло, что это у нас получается самая настоящая SMP ;)

http://ru.wikipedia.org/wiki/%D0%A1%D0% ... 0%B8%D0%B5

Может тогда наше поделие стоит назвать nedoPC-580/SMP? ;)
Я тут за главного - если что шлите мыло на me собака shaos точка net
User avatar
He3HauKo
Senior
Posts: 176
Joined: 09 Aug 2012 11:20
Location: 95.135.174.189

Post by He3HauKo »

Ага в точку, особенно тот момент, чем больше процессоров тем медленнее доступ.....
Хочу стать всезнайкой ;-)
User avatar
Shaos
Admin
Posts: 24006
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Post by Shaos »

т.к. Lavr ещё больше года назад высказал мысль, что надо меньше слов и больше кода:
Lavr wrote:
Shaos wrote:а управлять ими будет просто
Ну поскольку наблюдаю за тобой устойчивую манеру облекать мысли в коды,
рассказал бы что-нибуть на простом примере... :wink:
(Имеем в виду 580 и Z80 где встроенных механизмов нет)
Вот вам больше кода :)

Более детальный код работы с мьютексами на рабочих процах:

Code: Select all

GRAB_MUTEX:
; B - process id
; C - mutex id
DI
PUSH PSW
MVI A,#10 ; access to semaphore that controls programming mutexes
OUT 7
GRAB_MUTEX_LOOP:
IN 7
ANI #10 
JZ GRAB_MUTEX_LOOP ; wait for ready
; then hold or go further (if nobody else waiting on the same semaphore)
PUSH B
PUSH H
MOV A,B ; save process id
MVI B,0 ; BC = mutex id
LXI H,MUTEXES ; HL = address of table of mutexes
DAD B ; HL = address of our mutex
MOV B,A ; B = process id again
MOV A,M
ORA A
JZ GRAB_MUTEX_FREE
; here we know that our mutex is grabbed by other process
.....
JMP GRAB_MUTEX_END
GRAB_MUTEX_FREE:
; mutex if free to grab
MOV M,B ; store porcess id in our mutex to grab it
GRAB_MUTEX_END:
; A = 0
OUT 7 ; signal to mutex semaphore that it's free now (send 0 to port 7)
POP H
POP B
POP PSW
EI 
RET
Я тут за главного - если что шлите мыло на me собака shaos точка net
User avatar
Shaos
Admin
Posts: 24006
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Post by Shaos »

He3HauKo wrote:Ага в точку, особенно тот момент, чем больше процессоров тем медленнее доступ.....
Доступ к чему? ;)

На самом деле масштабируемость системы сильно зависит от масштабируемых задач. В обычном SMP (на интеловских процах) важна влезаемость задачи целиком вместе с данными в кеш процессора - тогда процессы мешать друг-другу не будут. А в нашем же случае процессы вообще могут друг от друга не зависеть, т.к. доступ к памяти абсолютно прозрачный и параллельный. Но вот когда добавляется синхронизация - тут пока похоже без торможения на некоторое непродолжительное время никак не обойтись...
Я тут за главного - если что шлите мыло на me собака shaos точка net
User avatar
Shaos
Admin
Posts: 24006
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Post by Shaos »

По семафорам - доступ в список всех возможных процессов (там где указывается наличие и местоположение процесса плюс приоритет - до 256 байт) и список активных процессов (4 байта или чуть больше, если нужно будет хранить дополнительную информацию кроме номера процесса, запущенного на каждом процессоре) наверное стоит покрыть одним семафором (bit 0) - всё равно к ним в одно и тоже время доступ нужен в большинстве случаев. Далее нужно придумать как мы будем обозначать процессы, висящие в ожидании мьютекса (или сообщения из очереди) - ведь им ненадо передавать управления пока мьютекс не освободиться.

Итак, таблица всех процессов в системе - скажем пусть будет 255 max:

Code: Select all

PROC_TABLE:
N_PROC DB 255 ; max number of processes
D_PROC DB 255 DUP(0)
В первом байте указано максимальное кол-во возможных процессов в системе - пусть будет 255. Далее идёт кол-во байт, равное кол-ву возможных процессов. Ноль внутри байта процесса будет означать, что процесса с таким номером несуществует. Если значение байта неравно нулю, то такой процесс есть - младщие 5 бит будут означать номер страницы памяти, в которой физически расположен процесс (возможные значения от 1 до 31), а старшие 3 бита будут означать приоритет процесса (возможные значения от 0 до 7). Если приоритет процесса 0, то это может значить, что он специально остановлен либо что он висит на мьютексе или ожидает прихода евента из очереди - за более подробной информацией по этому поводу надо будет идти в другую таблицу (я её пока не придумал).

Таблица активных процессов:

Code: Select all

ACTP_TABLE:
N_ACTP DB 4 ; number of available processors
D_ACTP DW 0,0,0,0 ; active processes descriptions (one per processor)
В первом байте указывается количество рабочих процессоров, а далее идёт таблица из такого количество 16-битных слов - в младшем байте каждого слова (первом байте) содержится идентификатор процесса, который запущен на соответствующем процессоре (возможные значения от 1 до 255, а 0 означает что ничего не запущено), а в старшем (втором байте) - кол-во прерываний (10 Гц), оставшихся до переключения контекста на соответствующем процессоре.
Last edited by Shaos on 02 Sep 2012 12:58, edited 2 times in total.
Я тут за главного - если что шлите мыло на me собака shaos точка net
User avatar
Lavr
Supreme God
Posts: 16680
Joined: 21 Oct 2009 08:08
Location: Россия

Post by Lavr »

Shaos wrote:т.к. Lavr ещё больше года назад высказал мысль, что надо меньше слов и больше кода:
Ну когда есть код - меня сразу тянет его компильнуть, залить в систему,
поюзать и подебужить...

А модели железа у нас никакой нету... :(

Shaos wrote:Ха, до меня только что дошло, что это у нас получается самая настоящая SMP ;)

Может тогда наше поделие стоит назвать nedoPC-580/SMP? ;)
А кто-то у нас тут говаривал - "нефиг читать русскоязычную Педивикию на ночь" ? :wink:

Точнее будет: phantasmal nedoPC-580/SMP... :roll:
Last edited by Lavr on 01 Sep 2012 23:27, edited 1 time in total.
iLavr
User avatar
Shaos
Admin
Posts: 24006
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Post by Shaos »

Теперь про переключение контекстов. На каждом проце у нас будет свой планировщик, каждый из которых будет переключать задачи по прерыванию 10 Гц (если они не запрещены). Каждый проц знает свой номер (скажем IN 4 будет давать общее кол-во рабочих процов в системе, а IN 5 - номер текущего проца, где была вызвана эта команда) - в обработчике прерываний смотрится количество оставшихся тактов процесса, если не 0, то уменьшаемых на 1 с+ отпусканием прерывания, а если 0 (процесс исчерпал свой лимит), то происходит переключение контекста - планировщик, чтобы найти следующий процесс который надо запустить, просто идёт по таблице всех возможных процессов (D_PROC) начиная от текущего, ища следующий ненулевой описатель, соответствующий которому проц не входит в список активных процессоров (D_ACTP) - в этом случае происходит переключение контекста на этот процесс и отпускание прерывания.

После некоторых раздумий решил, что возможность явного вызова планировщика (без прерывания) также нужна - например когда процесс решил, что ему надо повиснуть на мьютексе, он может немедленно отдать управление следущей задаче, а для этого надо запустить планировщик...
Я тут за главного - если что шлите мыло на me собака shaos точка net
User avatar
Shaos
Admin
Posts: 24006
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Post by Shaos »

Shaos wrote:Теперь про переключение контекстов. На каждом проце у нас будет свой планировщик, каждый из которых будет переключать задачи по прерыванию 10 Гц (если они не запрещены). Каждый проц знает свой номер (скажем IN 4 будет давать общее кол-во рабочих процов в системе, а IN 5 - номер текущего проца, где была вызвана эта команда) - в обработчике прерываний смотрится количество оставшихся тактов процесса, если не 0, то уменьшаемых на 1 с+ отпусканием прерывания, а если 0 (процесс исчерпал свой лимит), то происходит переключение контекста - планировщик, чтобы найти следующий процесс который надо запустить, просто идёт по таблице всех возможных процессов (D_PROC) начиная от текущего, ища следующий ненулевой описатель, соответствующий которому проц не входит в список активных процессоров (D_ACTP) - в этом случае происходит переключение контекста на этот процесс и отпускание прерывания.
Хотя наверное с нашим небольшим количеством процов можно оба значения утолкать в один порт, т.е. IN 4 может возвращать в младших 4 битах порядковый номер процессора (1,2,3,4), а в старших - общее их количество в системе (4). В будущем совершенно прозрачно с точки зрения софта можно воткнуть 8 или даже больше процессоров (до 15).
Shaos wrote: После некоторых раздумий решил, что возможность явного вызова планировщика (без прерывания) также нужна - например когда процесс решил, что ему надо повиснуть на мьютексе, он может немедленно отдать управление следущей задаче, а для этого надо запустить планировщик...
Другой вопрос как проще это сделать - сначала я думал про программный вызов, а сейчас вот подумал о возможности внеочередного вызова прерывания планировщика через запись некоего бита в какой-то порт, хотя с другой стороны непосредственный вызов RST 7 сделает тоже самое, что и аппаратное прерывание...

Code: Select all

; GRAB_MUTEX
; B - process id
; C - mutex id
GRAB_MUTEX:
  DI
  PUSH PSW
  MVI A,#10 ; access to semaphore that controls programming mutexes
  OUT 7
GRAB_MUTEX_LOOP:
  IN 7
  ANI #10
  JZ GRAB_MUTEX_LOOP ; wait for ready
  ; then hold or go further (if nobody else waits on the same semaphore)
  PUSH B
  PUSH H
  MOV A,B ; save process id
  MVI B,0 ; BC = mutex id
  LXI H,MUTEXES ; HL = address of table of mutexes
  DAD B ; HL = address of our mutex
  MOV B,A ; B = process id again
  MOV A,M
  ORA A
  JZ GRAB_MUTEX_FREE
  ; here we know that our mutex is grabbed by other process
  XRA A
  OUT 7 ; signal to mutex semaphore that it's free now (send 0 to port 7)
GRAB_MUTEX_WAIT:
  ; HL = address of our mutex
  RST 7 ; program call of scheduler (?)
  ; scheduler will return here after resume of this process
  MOV A,M
  ORA A
  JNZ GRAB_MUTEX_WAIT ; mutex is still occupied so go back
  ; it looks like mutex is free - try to securely grab mutex again
  POP H
  POP B
  POP PSW
  JMP GRAB_MUTEX
GRAB_MUTEX_FREE:
  ; mutex if free to grab
  MOV M,B ; store porcess id in our mutex to grab it
  ; A = 0
  OUT 7 ; signal to mutex semaphore that it's free now (send 0 to port 7)
  POP H
  POP B
  POP PSW
  EI
  RET 
Такой код не будет ставить 0 в качестве приоритета ожидающего процесса, как я предполагал в начале, т.е. процесс всё равно будет вызываться планировщиком (разве что можно сделать какой-то другой вызов вместо RST 7, чтобы не отрабатывался приоритет для ожидающего треда), но при вызове он только будет проверять мьютекс на свободность (такая проверка не требует хардверного семафора) и если он свободен, то пробовать его опять захватить прикрывшись семафором, а если занят, то управление опять будет передано другому треду через непосредственный вызов планировщика.

P.S. В этом коде я вижу несколько потенциальных проблем: первая - это то что ожидающий процесс всё равно будет получать управление чтобы проверить, что он всё ещё должен ждать, тратя на это циклы ЦПУ; вторая - возможны гонки из-за того, что освободившийся мьютекс будет захвачен первым попавшимся процессом, а не тем, кто стал ждать его раньше (очереди нету), т.е. я вполне могу представить себе ситуацию, когда один из ожидающих тредов не сможет получить мьютекс никогда, если его достаточно активно будут юзать другие более удачливые треды - чтобы это дело улучшить можно добавить некую случайность в длительности ожидания; третья - надо поставить проверку на то, что мьютекс уже занят тем же самым процессом, что по хорошему должно приводить к фатальной ошибке и остановке системы (сейчас это приведёт к дед-локу). А вообще наверное для первого приближения код вполне приемлимый - можно будет погонять на эмуле ставя разное количество процессоров и наблюдая за масштабируемостью разных задач...
Я тут за главного - если что шлите мыло на me собака shaos точка net
User avatar
BarsMonster
Senior
Posts: 126
Joined: 21 Jul 2012 15:56
Location: Zürich, Switzerland

Post by BarsMonster »

На правах натюрморта:
You do not have the required permissions to view the files attached to this post.
User avatar
He3HauKo
Senior
Posts: 176
Joined: 09 Aug 2012 11:20
Location: 95.135.174.189

Post by He3HauKo »

Перечитал всю ветку, но так и не понял, как они одновременно лазают в память???? :-?
Хочу стать всезнайкой ;-)
User avatar
Shaos
Admin
Posts: 24006
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Post by Shaos »

He3HauKo wrote:Перечитал всю ветку, но так и не понял, как они одновременно лазают в память???? :-?
А так - современная память быстрее старых микропроцессоров в несколько раз - соответственно циклы обращения к ней можно сделать сильно короче и разнести по фазам. Процы параллельно обращаются к памяти своими длинными циклами, а некая логика внутри этих длинных циклов дёргает одну и туже память в разные моменты времени - соответственно процы друг-другу не мешают. Вобщем как-то так...
Я тут за главного - если что шлите мыло на me собака shaos точка net
User avatar
He3HauKo
Senior
Posts: 176
Joined: 09 Aug 2012 11:20
Location: 95.135.174.189

Post by He3HauKo »

Так и думал!
Я когда хотел объединить два Z80, подсчитал количество тактов при разных ситуациях, а также сами ситуации, понял что случаются когда два одновременно лезут в память. А тут 5 :-?
Хочу стать всезнайкой ;-)