mirror of
https://github.com/KolibriOS/kolibrios.git
synced 2024-11-27 03:09:59 +03:00
Translate events_subsystem.txt into English.
git-svn-id: svn://kolibrios.org@7587 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
74af3ea158
commit
99e8249f49
232
kernel/trunk/docs/events_subsystem.ru.txt
Normal file
232
kernel/trunk/docs/events_subsystem.ru.txt
Normal file
@ -0,0 +1,232 @@
|
||||
Дата последней правки 26/07/2013.
|
||||
Подсистема событий ядра может понадобиться при написании драйверов и сервисов, работающих в режиме ядра.
|
||||
Она не имеет отношения к подсистеме событий пользовательского интерфейса.
|
||||
С точки зрения ядра событие - объект ядра и принадлежит создавшему его потоку.
|
||||
|
||||
struc EVENT
|
||||
{
|
||||
.magic dd ? ; 'EVNT'
|
||||
.destroy dd ? ; internal destructor
|
||||
.fd dd ? ; next object in list
|
||||
.bk dd ? ; prev object in list
|
||||
.pid dd ? ; owner id. идентификатор владельца (потока)
|
||||
.id dd ? ; event uid. уникальный идентификатор события (просто номерок)
|
||||
.state dd ? ; internal flags; см. далее.
|
||||
.code dd ? ; старший байт класс события, ; следующий байт приоритет
|
||||
; (будет использоваться только внутри ядра, при чтении всегда 0),
|
||||
; Чем больше численное значение двойного слова тем важнее событие.
|
||||
; два младших байта код события.
|
||||
rd 5 ; .data - точная структура этого поля не определена и зависит
|
||||
; от поля .code. (Здесь можно передавать какие-то свои данные,
|
||||
; при необходимости :)
|
||||
.size = $ - .magic
|
||||
.codesize = $ - .code
|
||||
}
|
||||
|
||||
События реального времени получили класс 0хFF. Пока определёны только:
|
||||
EVENT.code= ;(Используется в звуковой подсистеме).
|
||||
RT_INP_EMPTY = 0xFF000001
|
||||
RT_OUT_EMPTY = 0xFF000002
|
||||
RT_INP_FULL = 0xFF000003
|
||||
RT_OUT_FULL = 0xFF000004
|
||||
|
||||
|
||||
Флаги поля EVENT.state определены в gui/event.inc.
|
||||
EVENT_SIGNALED = 0x20000000 ;бит 29 событие активно/неактивно;
|
||||
EVENT_WATCHED = 0x10000000 ;бит 28, поток-владелец ожидает активации события;
|
||||
MANUAL_RESET = 0x40000000 ;бит 30, не деактивировать событие автоматически по получении;
|
||||
MANUAL_DESTROY = 0x80000000 ;бит 31, не возвращать событие в список свободных по получении.
|
||||
|
||||
На момент ревизии 3732 (и далее по тексту то же) определение находится в \kernel\trunk\const.inc
|
||||
и выглядит так:
|
||||
|
||||
struct APPOBJ ; common object header
|
||||
magic dd ? ;
|
||||
destroy dd ? ; internal destructor
|
||||
fd dd ? ; next object in list
|
||||
bk dd ? ; prev object in list
|
||||
pid dd ? ; owner id
|
||||
ends
|
||||
|
||||
struct EVENT APPOBJ
|
||||
id dd ? ;event uid
|
||||
state dd ? ;internal flags
|
||||
code dd ?
|
||||
rd 5 ; .data
|
||||
ends
|
||||
|
||||
Код находится в gui/event.inc.
|
||||
Сами события как обьекты существуют в памяти ядра в виде двусвязного списка (см. поля .bk и .fd).
|
||||
При инициализации ядро резервирует память и создает 512 таких обьектов, помещая их в список FreeEvents
|
||||
(свободных событий). При нехватке событий (все заняты, а нужно ещё) ядро создает ещё 512 свободных
|
||||
и т.д. Каждый поток имеет свои (двусвязные) списки (в которые может быть помещено событие):
|
||||
ObjList - список объектов ядра, ассоциированных с этим потоком;
|
||||
EventList - список событий ядра для потока.
|
||||
Сами события, физически, при перемещении между списками и смене очередности в списке не перемещаются
|
||||
и не копируются. Это происходит только благодаря модификации полей .fd и .bk. Принцип работы списков,
|
||||
как очередей - FIFO. Использутся неблокирующая отправка и блокирующее получение. Адресация - прямая
|
||||
(у события всегда есть поток-владелец), по идентификатору потока.
|
||||
|
||||
Жизненый цикл событий определяется флагами при создании. По умолчанию ядро использует значения
|
||||
MANUAL_RESET = 0 и MANUAL_DESTROY = 0. Такое событие является "одноразовым", и автоматически освобождается
|
||||
ядром, возвращаясь в список свободных событий после получения.
|
||||
Событие с флагом MANUAL_DESTROY = 1 после получения переходит в неактивное состояние, но остаётся в списке
|
||||
объектов потока и может использоваться снова. Событие с флагами MANUAL_DESTROY = 1 и MANUAL_RESET = 1
|
||||
остаётся активным после получения и может быть сброшено вызовом ClearEvent.
|
||||
|
||||
Пример (вариант) жизненного цикла события из звуковой подсистемы:
|
||||
Для зукового буфера (их может быть несколько) драйвер создает событие в списке ObjList с помощью
|
||||
CreateEvent и флагом MANUAL_DESTROY. Далее драйвер вызывает WaitEvent для этого события (ожидает флага
|
||||
EVENT_SIGNALED в событии) и блокируется, в ожидании запроса на пополнение буфера. Запрос отправляется
|
||||
с помощью RaiseEvent из другого потока. Отправка (RaiseEvent) и получение (WaitEvent) циклически
|
||||
повторяются при опустошении буфера. При остановке воспроизведения драйвер деактивирует событие с помощью
|
||||
ClearEvent.
|
||||
|
||||
Вообще говоря, структура события приведена здесь только лишь для понимания принципов работы подсистемы.
|
||||
Самостоятельная работа с полями не приветствуется, ввиду возможных в будущем проблем с совместимостью.
|
||||
Работа должна производится только через API (функции подсистемы), с доступом только к тем полям, доступ к
|
||||
которым предоставляет функция. При этом пару "указатель на событие" и "уникальный идентификатор события"
|
||||
следует рассматривать как один 64-х битный уникальный идентификатор. (Если вы вызвали CreateEvent, напимер,
|
||||
его нужно запомнить где-нибудь [если это нужно] для дальнейшей работы с событием).
|
||||
|
||||
Функции для работы с событиями экспортитуемые ядром:
|
||||
(для драйверов и т.п.; вызываются в режиме ядра)
|
||||
|
||||
CreateEvent
|
||||
RaiseEvent
|
||||
ClearEvent
|
||||
SendEvent
|
||||
DestroyEvent
|
||||
WaitEvent
|
||||
WaitEventTimeout
|
||||
GetEvent
|
||||
Для пользовательских приложений Ф68.14 (GetEvent с обёрткой)
|
||||
|
||||
---------------------------------------------------------------------------------------------
|
||||
CreateEvent:
|
||||
Создаёт новое событие в очереди ObjList текущего потока.
|
||||
Устанавливает:
|
||||
EVENT.destroy <= внутренний деструктор по умолчанию;
|
||||
EVENT.pid <= текущий Process id;
|
||||
EVENT.id <= уникальный идентификатор;
|
||||
EVENT.state <= ecx - флаги;
|
||||
EVENT.code <= [esi], (если esi=0, то не копирует), размер 6*dword;
|
||||
Возвращает:
|
||||
eax - указатель на событие или 0 при ошибке.
|
||||
edx - Event.id.
|
||||
Портит: eax,ebx,edx,ecx,esi,edi
|
||||
---------------------------------------------------------------------------------------------
|
||||
RaiseEvent:
|
||||
Активирует уже существующее событие (может принадлежать другому потоку) установкой
|
||||
флага EVENT_SIGNALED. Если необходимо, - устанавливает данные EVENT.code.
|
||||
Если флаг EVENT_SIGNALED в самом событии уже активен - больше ничего не делает.
|
||||
Если EVENT_SIGNALED не установлен в самом событии, то он будет установлен, кроме случая
|
||||
{EVENT_WATCHED в edx=1 и EVENT_WATCHED в событии=0}.
|
||||
Т.е. при установке EVENT_WATCHED в edx, проверяется, ожидает ли поток-владелец активации
|
||||
события.
|
||||
Кроме EVENT_SIGNALED в событии никакие другие флаги не модифицируются.
|
||||
Принимает:
|
||||
eax - указатель на событие;
|
||||
ebx - id, уникальный идентификатор события;
|
||||
edx - флаги для операции (формат EVENT.state);
|
||||
EVENT.code <= [esi], (если esi=0, то не копирует), размер 6*dword;
|
||||
Возвращает: ?
|
||||
Портит: eax,ebx,edx,ecx,esi,edi .
|
||||
---------------------------------------------------------------------------------------------
|
||||
ClearEvent:
|
||||
Перемещает событие в список ObjList потока-владельца. (Возможно оно там и находилось.)
|
||||
Сбрасывает флаги EVENT_SIGNALED, EVENT_WATCHED. С остальными полями (.code, .id),
|
||||
ничего не делает.
|
||||
Принимает:
|
||||
eax - указатель на событие;
|
||||
ebx - id, уникальный идентификатор события.
|
||||
Возвращает: ?
|
||||
Портит: eax,ebx,ecx,edi .
|
||||
---------------------------------------------------------------------------------------------
|
||||
SendEvent:
|
||||
Создаёт новое событие в списке событий целевого потока. Устанавливает в событии
|
||||
флаг EVENT_SIGNALED.
|
||||
Принимает:
|
||||
EVENT.pid <= eax - pid, идентификатор целевого потока;
|
||||
EVENT.code <= [esi], (если esi=0, то не копирует), размер 6*dword;
|
||||
Возвращает:
|
||||
eax - указатель на событие или 0 при ошибке.
|
||||
edx - Event.id. уникальный идентификатор.
|
||||
Портит: eax,ebx,ecx,esi,edi .
|
||||
---------------------------------------------------------------------------------------------
|
||||
DestroyEvent:
|
||||
Переносит EVENT в список FreeEvents, чистит поля .magic,.destroy,.pid,.id.
|
||||
Событие может принадлежать другому потоку.
|
||||
Принимает:
|
||||
eax - указатель на событие;
|
||||
ebx - id, уникальный идентификатор события.
|
||||
Возвращает:
|
||||
eax - 0 при ошибке, не 0 при успехе.
|
||||
Портит: eax,ebx,ecx .
|
||||
---------------------------------------------------------------------------------------------
|
||||
WaitEvent:
|
||||
Бесконечно ожидает установки флага EVENT_SIGNALED в конкретном событии, принадлежащем
|
||||
вызывающему WaitEvent потоку. Сигнализирующий поток устанавливат этот флаг через
|
||||
RaiseEvent. Ожидающий поток замораживается путем перевода TASKDATA.state<=TSTATE_WAITING=5.
|
||||
Перед заморозкой устанавливается флаг EVENT_WATCHED в событии.
|
||||
Если в полученном событии НЕ установлен MANUAL_RESET, то:
|
||||
{EVENT_SIGNALED и EVENT_WATCHED по получении события сбрасываются.
|
||||
При неактивном MANUAL_DESTROY - событие уничтожается штатно (DestroyEvent),
|
||||
а при активном - перемещается в список ObjList текущего слота.}
|
||||
Принимает:
|
||||
eax - указатель на событие;
|
||||
ebx - id, уникальный идентификатор события.
|
||||
Возвращает: ?
|
||||
Портит: eax,ebx,edx,ecx,esi,edi .
|
||||
---------------------------------------------------------------------------------------------
|
||||
WaitEventTimeout:
|
||||
Ожидает с таймаутом установки флага EVENT_SIGNALED в конкретном событии, принадлежащем
|
||||
вызывающему WaitEventTimeout потоку. Сигнализирующий поток устанавливат этот флаг через
|
||||
RaiseEvent. Ожидающий поток замораживается путем перевода TASKDATA.state<=TSTATE_WAITING=5.
|
||||
Перед заморозкой устанавливается флаг EVENT_WATCHED в событии.
|
||||
Если в полученном событии НЕ установлен MANUAL_RESET, то:
|
||||
{EVENT_SIGNALED и EVENT_WATCHED по получении события сбрасываются.
|
||||
При неактивном MANUAL_DESTROY - событие уничтожается штатно (DestroyEvent),
|
||||
а при активном - перемещается в список ObjList текущего слота.}
|
||||
Принимает:
|
||||
eax - указатель на событие;
|
||||
ebx - id, уникальный идентификатор события.
|
||||
ecx - время ожидания в тиках системного таймера.
|
||||
Возвращает:
|
||||
eax - 0 - таймаут, если событие не активировалось, или
|
||||
не 0, если было активировано.
|
||||
Портит: eax,ebx,edx,ecx,esi,edi .
|
||||
---------------------------------------------------------------------------------------------
|
||||
GetEvent:
|
||||
Бесконечно ожидает любое событие в очереди событий текущего потока. Поток замораживается
|
||||
путем перевода TASKDATA.state<=TSTATE_WAITING=5. Данные события (EVENT.code+5*dword)
|
||||
по получении копируются в указанный буфер. Сбрасывает байт приоритета (см. выше) в буфере.
|
||||
Если в полученном событии НЕ установлен MANUAL_RESET, то:
|
||||
{EVENT_SIGNALED и EVENT_WATCHED по получении события сбрасываются.
|
||||
При неактивном MANUAL_DESTROY - событие уничтожается штатно (DestroyEvent),
|
||||
а при активном - перемещается в список ObjList текущего слота.}
|
||||
Принимает:
|
||||
edi - указатель на буфер, куда копировать данные.
|
||||
Возвращает:
|
||||
буфер, содержащий следующую информацию:
|
||||
+0: (EVENT.code) dword: идентификатор последующих данных сигнала
|
||||
+4: (EVENT.data, поле формально не определено) данные принятого
|
||||
сигнала (5*dword), формат которых определяется первым dword-ом.
|
||||
Портит: eax,ebx,edx,ecx,esi,edi .
|
||||
--------------------------------------------------------------------------------------------
|
||||
Ф 68.14 для приложений: ;это тот же GetEvent, но с обёрткой.
|
||||
Бесконечно ожидает любое событие в очереди событий текущего потока. Ожидающий поток
|
||||
замораживается путем перевода TASKDATA.state<=TSTATE_WAITING=5. Данные события (EVENT.code+5*dword)
|
||||
копируются в указанный буфер. Сбрасывает байт приоритета (см. выше) в буфере.
|
||||
Принимает:
|
||||
eax - 68 - номер функции
|
||||
ebx - 14 - номер подфункции
|
||||
ecx - указатель на буфер для информации (размер 6*dword)
|
||||
Возвращает:
|
||||
буфер, на который указывает ecx, содержит следующую информацию:
|
||||
+0: (EVENT.code) dword: идентификатор последующих данных сигнала
|
||||
+4: (EVENT.data, поле формально не определено) данные принятого
|
||||
сигнала (5*dword), формат которых определяется первым dword-ом.
|
||||
Портит:
|
||||
eax .
|
||||
---------------------------------------------------------------------------------------------
|
@ -1,232 +1,248 @@
|
||||
Дата последней правки 26/07/2013.
|
||||
Подсистема событий ядра может понадобиться при написании драйверов и сервисов, работающих в режиме ядра.
|
||||
Она не имеет отношения к подсистеме событий пользовательского интерфейса.
|
||||
С точки зрения ядра событие - объект ядра и принадлежит создавшему его потоку.
|
||||
|
||||
struc EVENT
|
||||
{
|
||||
.magic dd ? ; 'EVNT'
|
||||
.destroy dd ? ; internal destructor
|
||||
.fd dd ? ; next object in list
|
||||
.bk dd ? ; prev object in list
|
||||
.pid dd ? ; owner id. идентификатор владельца (потока)
|
||||
.id dd ? ; event uid. уникальный идентификатор события (просто номерок)
|
||||
.state dd ? ; internal flags; см. далее.
|
||||
.code dd ? ; старший байт класс события, ; следующий байт приоритет
|
||||
; (будет использоваться только внутри ядра, при чтении всегда 0),
|
||||
; Чем больше численное значение двойного слова тем важнее событие.
|
||||
; два младших байта код события.
|
||||
rd 5 ; .data - точная структура этого поля не определена и зависит
|
||||
; от поля .code. (Здесь можно передавать какие-то свои данные,
|
||||
; при необходимости :)
|
||||
.size = $ - .magic
|
||||
.codesize = $ - .code
|
||||
}
|
||||
|
||||
События реального времени получили класс 0хFF. Пока определёны только:
|
||||
EVENT.code= ;(Используется в звуковой подсистеме).
|
||||
RT_INP_EMPTY = 0xFF000001
|
||||
RT_OUT_EMPTY = 0xFF000002
|
||||
RT_INP_FULL = 0xFF000003
|
||||
RT_OUT_FULL = 0xFF000004
|
||||
|
||||
|
||||
Флаги поля EVENT.state определены в gui/event.inc.
|
||||
EVENT_SIGNALED = 0x20000000 ;бит 29 событие активно/неактивно;
|
||||
EVENT_WATCHED = 0x10000000 ;бит 28, поток-владелец ожидает активации события;
|
||||
MANUAL_RESET = 0x40000000 ;бит 30, не деактивировать событие автоматически по получении;
|
||||
MANUAL_DESTROY = 0x80000000 ;бит 31, не возвращать событие в список свободных по получении.
|
||||
|
||||
На момент ревизии 3732 (и далее по тексту то же) определение находится в \kernel\trunk\const.inc
|
||||
и выглядит так:
|
||||
|
||||
struct APPOBJ ; common object header
|
||||
magic dd ? ;
|
||||
destroy dd ? ; internal destructor
|
||||
fd dd ? ; next object in list
|
||||
bk dd ? ; prev object in list
|
||||
pid dd ? ; owner id
|
||||
ends
|
||||
|
||||
struct EVENT APPOBJ
|
||||
id dd ? ;event uid
|
||||
state dd ? ;internal flags
|
||||
code dd ?
|
||||
rd 5 ; .data
|
||||
ends
|
||||
|
||||
Код находится в gui/event.inc.
|
||||
Сами события как обьекты существуют в памяти ядра в виде двусвязного списка (см. поля .bk и .fd).
|
||||
При инициализации ядро резервирует память и создает 512 таких обьектов, помещая их в список FreeEvents
|
||||
(свободных событий). При нехватке событий (все заняты, а нужно ещё) ядро создает ещё 512 свободных
|
||||
и т.д. Каждый поток имеет свои (двусвязные) списки (в которые может быть помещено событие):
|
||||
ObjList - список объектов ядра, ассоциированных с этим потоком;
|
||||
EventList - список событий ядра для потока.
|
||||
Сами события, физически, при перемещении между списками и смене очередности в списке не перемещаются
|
||||
и не копируются. Это происходит только благодаря модификации полей .fd и .bk. Принцип работы списков,
|
||||
как очередей - FIFO. Использутся неблокирующая отправка и блокирующее получение. Адресация - прямая
|
||||
(у события всегда есть поток-владелец), по идентификатору потока.
|
||||
|
||||
Жизненый цикл событий определяется флагами при создании. По умолчанию ядро использует значения
|
||||
MANUAL_RESET = 0 и MANUAL_DESTROY = 0. Такое событие является "одноразовым", и автоматически освобождается
|
||||
ядром, возвращаясь в список свободных событий после получения.
|
||||
Событие с флагом MANUAL_DESTROY = 1 после получения переходит в неактивное состояние, но остаётся в списке
|
||||
объектов потока и может использоваться снова. Событие с флагами MANUAL_DESTROY =1 и MANUAL_RESET = 1
|
||||
остаётся активным после получения и может быть сброшено вызовом ClearEvent.
|
||||
|
||||
Пример (вариант) жизненного цикла события из звуковой подсистемы:
|
||||
Для зукового буфера (их может быть несколько) драйвер создает событие в списке ObjList с помощью
|
||||
CreateEvent и флагом MANUAL_DESTROY. Далее драйвер вызывает WaitEvent для этого события (ожидает флага
|
||||
EVENT_SIGNALED в событии) и блокируется, в ожидании запроса на пополнение буфера. Запрос отправляется
|
||||
с помощью RaiseEvent из другого потока. Отправка (RaiseEvent) и получение (WaitEvent) циклически
|
||||
повторяются при опустошении буфера. При остановке воспроизведения драйвер деактивирует событие с помощью
|
||||
ClearEvent.
|
||||
|
||||
Вообще говоря, структура события приведена здесь только лишь для понимания принципов работы подсистемы.
|
||||
Самостоятельная работа с полями не приветствуется, ввиду возможных в будущем проблем с совместимостью.
|
||||
Работа должна производится только через API (функции подсистемы), с доступом только к тем полям, доступ к
|
||||
которым предоставляет функция. При этом пару "указатель на событие" и "уникальный идентификатор события"
|
||||
следует рассматривать как один 64-х битный уникальный идентификатор. (Если вы вызвали CreateEvent, напимер,
|
||||
его нужно запомнить где-нибудь [если это нужно] для дальнейшей работы с событием).
|
||||
|
||||
Функции для работы с событиями экспортитуемые ядром:
|
||||
(для драйверов и т.п.; вызываются в режиме ядра)
|
||||
|
||||
CreateEvent
|
||||
RaiseEvent
|
||||
ClearEvent
|
||||
SendEvent
|
||||
DestroyEvent
|
||||
WaitEvent
|
||||
WaitEventTimeout
|
||||
GetEvent
|
||||
Для пользовательских приложений Ф68.14 (GetEvent с обёрткой)
|
||||
|
||||
---------------------------------------------------------------------------------------------
|
||||
CreateEvent:
|
||||
Создаёт новое событие в очереди ObjList текущего потока.
|
||||
Устанавливает:
|
||||
EVENT.destroy <= внутренний деструктор по умолчанию;
|
||||
EVENT.pid <= текущий Process id;
|
||||
EVENT.id <= уникальный идентификатор;
|
||||
EVENT.state <= ecx - флаги;
|
||||
EVENT.code <= [esi], (если esi=0, то не копирует), размер 6*dword;
|
||||
Возвращает:
|
||||
eax - указатель на событие или 0 при ошибке.
|
||||
edx - Event.id.
|
||||
Портит: eax,ebx,edx,ecx,esi,edi
|
||||
---------------------------------------------------------------------------------------------
|
||||
RaiseEvent:
|
||||
Активирует уже существующее событие (может принадлежать другому потоку) установкой
|
||||
флага EVENT_SIGNALED. Если необходимо, - устанавливает данные EVENT.code.
|
||||
Если флаг EVENT_SIGNALED в самом событии уже активен - больше ничего не делает.
|
||||
Если EVENT_SIGNALED не установлен в самом событии, то он будет установлен, кроме случая
|
||||
{EVENT_WATCHED в edx=1 и EVENT_WATCHED в событии=0}.
|
||||
Т.е. при установке EVENT_WATCHED в edx, проверяется, ожидает ли поток-владелец активации
|
||||
события.
|
||||
Кроме EVENT_SIGNALED в событии никакие другие флаги не модифицируются.
|
||||
Принимает:
|
||||
eax - указатель на событие;
|
||||
ebx - id, уникальный идентификатор события;
|
||||
edx - флаги для операции (формат EVENT.state);
|
||||
EVENT.code <= [esi], (если esi=0, то не копирует), размер 6*dword;
|
||||
Возвращает: ?
|
||||
Портит: eax,ebx,edx,ecx,esi,edi .
|
||||
---------------------------------------------------------------------------------------------
|
||||
ClearEvent:
|
||||
Перемещает событие в список ObjList потока-владельца. (Возможно оно там и находилось.)
|
||||
Сбрасывает флаги EVENT_SIGNALED, EVENT_WATCHED. С остальными полями (.code, .id),
|
||||
ничего не делает.
|
||||
Принимает:
|
||||
eax - указатель на событие;
|
||||
ebx - id, уникальный идентификатор события.
|
||||
Возвращает: ?
|
||||
Портит: eax,ebx,ecx,edi .
|
||||
---------------------------------------------------------------------------------------------
|
||||
SendEvent:
|
||||
Создаёт новое событие в списке событий целевого потока. Устанавливает в событии
|
||||
флаг EVENT_SIGNALED.
|
||||
Принимает:
|
||||
EVENT.pid <= eax - pid, идентификатор целевого потока;
|
||||
EVENT.code <= [esi], (если esi=0, то не копирует), размер 6*dword;
|
||||
Возвращает:
|
||||
eax - указатель на событие или 0 при ошибке.
|
||||
edx - Event.id. уникальный идентификатор.
|
||||
Портит: eax,ebx,ecx,esi,edi .
|
||||
---------------------------------------------------------------------------------------------
|
||||
DestroyEvent:
|
||||
Переносит EVENT в список FreeEvents, чистит поля .magic,.destroy,.pid,.id.
|
||||
Событие может принадлежать другому потоку.
|
||||
Принимает:
|
||||
eax - указатель на событие;
|
||||
ebx - id, уникальный идентификатор события.
|
||||
Возвращает:
|
||||
eax - 0 при ошибке, не 0 при успехе.
|
||||
Портит: eax,ebx,ecx .
|
||||
---------------------------------------------------------------------------------------------
|
||||
WaitEvent:
|
||||
Бесконечно ожидает установки флага EVENT_SIGNALED в конкретном событии, принадлежащем
|
||||
вызывающему WaitEvent потоку. Сигнализирующий поток устанавливат этот флаг через
|
||||
RaiseEvent. Ожидающий поток замораживается путем перевода TASKDATA.state<=TSTATE_WAITING=5.
|
||||
Перед заморозкой устанавливается флаг EVENT_WATCHED в событии.
|
||||
Если в полученном событии НЕ установлен MANUAL_RESET, то:
|
||||
{EVENT_SIGNALED и EVENT_WATCHED по получении события сбрасываются.
|
||||
При неактивном MANUAL_DESTROY - событие уничтожается штатно (DestroyEvent),
|
||||
а при активном - перемещается в список ObjList текущего слота.}
|
||||
Принимает:
|
||||
eax - указатель на событие;
|
||||
ebx - id, уникальный идентификатор события.
|
||||
Возвращает: ?
|
||||
Портит: eax,ebx,edx,ecx,esi,edi .
|
||||
---------------------------------------------------------------------------------------------
|
||||
WaitEventTimeout:
|
||||
Ожидает с таймаутом установки флага EVENT_SIGNALED в конкретном событии, принадлежащем
|
||||
вызывающему WaitEventTimeout потоку. Сигнализирующий поток устанавливат этот флаг через
|
||||
RaiseEvent. Ожидающий поток замораживается путем перевода TASKDATA.state<=TSTATE_WAITING=5.
|
||||
Перед заморозкой устанавливается флаг EVENT_WATCHED в событии.
|
||||
Если в полученном событии НЕ установлен MANUAL_RESET, то:
|
||||
{EVENT_SIGNALED и EVENT_WATCHED по получении события сбрасываются.
|
||||
При неактивном MANUAL_DESTROY - событие уничтожается штатно (DestroyEvent),
|
||||
а при активном - перемещается в список ObjList текущего слота.}
|
||||
Принимает:
|
||||
eax - указатель на событие;
|
||||
ebx - id, уникальный идентификатор события.
|
||||
ecx - время ожидания в тиках системного таймера.
|
||||
Возвращает:
|
||||
eax - 0 - таймаут, если событие не активировалось, или
|
||||
не 0, если было активировано.
|
||||
Портит: eax,ebx,edx,ecx,esi,edi .
|
||||
---------------------------------------------------------------------------------------------
|
||||
GetEvent:
|
||||
Бесконечно ожидает любое событие в очереди событий текущего потока. Поток замораживается
|
||||
путем перевода TASKDATA.state<=TSTATE_WAITING=5. Данные события (EVENT.code+5*dword)
|
||||
по получении копируются в указанный буфер. Сбрасывает байт приоритета (см. выше) в буфере.
|
||||
Если в полученном событии НЕ установлен MANUAL_RESET, то:
|
||||
{EVENT_SIGNALED и EVENT_WATCHED по получении события сбрасываются.
|
||||
При неактивном MANUAL_DESTROY - событие уничтожается штатно (DestroyEvent),
|
||||
а при активном - перемещается в список ObjList текущего слота.}
|
||||
Принимает:
|
||||
edi - указатель на буфер, куда копировать данные.
|
||||
Возвращает:
|
||||
буфер, содержащий следующую информацию:
|
||||
+0: (EVENT.code) dword: идентификатор последующих данных сигнала
|
||||
+4: (EVENT.data, поле формально не определено) данные принятого
|
||||
сигнала (5*dword), формат которых определяется первым dword-ом.
|
||||
Портит: eax,ebx,edx,ecx,esi,edi .
|
||||
--------------------------------------------------------------------------------------------
|
||||
Ф 68.14 для приложений: ;это тот же GetEvent, но с обёрткой.
|
||||
Бесконечно ожидает любое событие в очереди событий текущего потока. Ожидающий поток
|
||||
замораживается путем перевода TASKDATA.state<=TSTATE_WAITING=5. Данные события (EVENT.code+5*dword)
|
||||
копируются в указанный буфер. Сбрасывает байт приоритета (см. выше) в буфере.
|
||||
Принимает:
|
||||
eax - 68 - номер функции
|
||||
ebx - 14 - номер подфункции
|
||||
ecx - указатель на буфер для информации (размер 6*dword)
|
||||
Возвращает:
|
||||
буфер, на который указывает ecx, содержит следующую информацию:
|
||||
+0: (EVENT.code) dword: идентификатор последующих данных сигнала
|
||||
+4: (EVENT.data, поле формально не определено) данные принятого
|
||||
сигнала (5*dword), формат которых определяется первым dword-ом.
|
||||
Портит:
|
||||
eax .
|
||||
---------------------------------------------------------------------------------------------
|
||||
Last edit: 26/07/2013
|
||||
|
||||
Kernel event subsystem may be useful when writing drivers and kernel space
|
||||
services. It is not related to the subsystem of GUI events. An event, from the
|
||||
kernel's point of view, is a kernel space object which is owned by the thread
|
||||
that created it.
|
||||
|
||||
struc EVENT
|
||||
{
|
||||
.magic dd ? ; 'EVNT'
|
||||
.destroy dd ? ; internal destructor
|
||||
.fd dd ? ; next object in list
|
||||
.bk dd ? ; prev object in list
|
||||
.pid dd ? ; owner (thread) id
|
||||
.id dd ? ; event uid. (just a number)
|
||||
.state dd ? ; internal flags; see below
|
||||
.code dd ? ; MSB: event class; next byte: priority
|
||||
; (used by kernel only, always 0 for reading),
|
||||
; The higher dword value the higher event priority.
|
||||
; Two LSBs: event code.
|
||||
rd 5 ; .data: the structure of this field is not defined and
|
||||
; depends on .code field. (Pass any data you need here)
|
||||
.size = $ - .magic
|
||||
.codesize = $ - .code
|
||||
}
|
||||
|
||||
Realtime events have class 0хFF. Currently defined:
|
||||
EVENT.code= ; (Used in sound subsystem)
|
||||
RT_INP_EMPTY = 0xFF000001
|
||||
RT_OUT_EMPTY = 0xFF000002
|
||||
RT_INP_FULL = 0xFF000003
|
||||
RT_OUT_FULL = 0xFF000004
|
||||
|
||||
|
||||
Flags of EVENT.state field are defined in gui/event.inc.
|
||||
EVENT_SIGNALED = 0x20000000 ; bit 29: event is active/inactive
|
||||
EVENT_WATCHED = 0x10000000 ; bit 28: owner thread is waiting for the
|
||||
; event to be active
|
||||
MANUAL_RESET = 0x40000000 ; bit 30: do not deactivate event
|
||||
: automatically on receive
|
||||
MANUAL_DESTROY = 0x80000000 ; bit 31: do not return event to a list of
|
||||
; free ones on receive
|
||||
|
||||
As of SVN r3732 (assume same below) the definition is located in
|
||||
/kernel/trunk/const.inc and is as follows:
|
||||
|
||||
struct APPOBJ ; common object header
|
||||
magic dd ? ;
|
||||
destroy dd ? ; internal destructor
|
||||
fd dd ? ; next object in list
|
||||
bk dd ? ; prev object in list
|
||||
pid dd ? ; owner id
|
||||
ends
|
||||
|
||||
struct EVENT APPOBJ
|
||||
id dd ? ; event uid
|
||||
state dd ? ; internal flags
|
||||
code dd ?
|
||||
rd 5 ; .data
|
||||
ends
|
||||
|
||||
Code is located in gui/event.inc.
|
||||
Event objects live in kernel memory as a double-linked list (see fields .bk and
|
||||
.fd). While initialization the kernel reserves memory, creates 512 events and
|
||||
places them into FreeEvents list. When out of free event, kernel creates another
|
||||
512 ones etc. Each thread has own double-linked lists where an event may be
|
||||
placed to:
|
||||
ObjList -- a list of kernel objects associated with the thread;
|
||||
EventList -- a list of kernel events for the thread.
|
||||
When events are moved between lists or reordered their data are not copied. This
|
||||
is done only via modification of .fd and .bk fields. These lists work as FIFO
|
||||
queues. Sending does not block, receiving blocks. Addressing is direct, by
|
||||
thread id. There always is an owner thread for an event.
|
||||
|
||||
Event's life cycle is defined by flags while creation. By default the kernel
|
||||
uses values MANUAL_RESET = 0 and MANUAL_DESTROY = 0. Such an event is oneshot
|
||||
and is automatically freed by the kernel and returned to the FreeEvents list
|
||||
when received. An event with flag MANUAL_DESTROY = 1 becomes inactive when
|
||||
received but remains in thread's object list and can be reused. An event with
|
||||
flags MANUAL_DESTROY = 1 and MANUAL_RESET = 1 remains active when received and
|
||||
can be reset via call to ClearEvent.
|
||||
|
||||
A life cycle example of a sound subsystem event:
|
||||
* For an audio buffer (possibly several) the driver creates an event in ObjList
|
||||
by calling CreateEvent with flag MANUAL_DESTROY.
|
||||
* Then driver calls WaitEvent for the event (waits for EVENT_SIGNALED event
|
||||
flag) and blocks waiting for buffer update request.
|
||||
* The buffer update request is sent with RaiseEvent from another thread.
|
||||
* Sending (RaiseEvent) and receiving (WaitEvent) are repeated as buffer gets
|
||||
empty.
|
||||
* Driver deactivates the event with ClearEvent when playback is stopped.
|
||||
|
||||
Actually, the event structure is described here only for understanding of
|
||||
subsystem work principles. Direct field access is discouraged due to possible
|
||||
compatibility issues in the future. Only API calls should be used. A pair
|
||||
"pointer to an event" and "event id" is considered a single 64-bit id. This id
|
||||
should be stored somewhere after a call to CreateEvent for further work with the
|
||||
event.
|
||||
|
||||
The kernel exports following event related functions:
|
||||
(for drivers, etc; called from kernel mode)
|
||||
|
||||
CreateEvent
|
||||
RaiseEvent
|
||||
ClearEvent
|
||||
SendEvent
|
||||
DestroyEvent
|
||||
WaitEvent
|
||||
WaitEventTimeout
|
||||
GetEvent
|
||||
For user applications sysfn 68.14 (a wrapper to GetEvent)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
CreateEvent:
|
||||
Creates a new event in ObjList queue of current thread.
|
||||
Sets:
|
||||
EVENT.destroy <= default internal destructor
|
||||
EVENT.pid <= current Process id
|
||||
EVENT.id <= unique id
|
||||
EVENT.state <= ecx: flags
|
||||
EVENT.code <= [esi]: size is 6*dword, do not copy if esi=0
|
||||
Returns:
|
||||
eax -- pointer to the event or 0 for error.
|
||||
edx -- Event.id.
|
||||
Destroys: eax,ebx,edx,ecx,esi,edi
|
||||
--------------------------------------------------------------------------------
|
||||
RaiseEvent:
|
||||
Activates existing event (may be owned by another thread) by setting
|
||||
EVENT_SIGNALED flag. Sets EVENT.code data if necessary. Does nothing
|
||||
more if EVENT_SIGNALED flag is already active in the event. If
|
||||
EVENT_SIGNALED flag is not set in the event it will be set, except when
|
||||
EVENT_WATCHED in edx = 1 and EVENT_WATCHED in the event = 0. I.e. while
|
||||
setting EVENT_WATCHED in edx it is checked if owner thread is waiting
|
||||
for event activation. No flags, except EVENT_SIGNALED, are modified in
|
||||
the event.
|
||||
Gets:
|
||||
eax -- pointer to event
|
||||
ebx -- id
|
||||
edx -- flags (see EVENT.state)
|
||||
Sets:
|
||||
EVENT.code <= [esi]: size is 6*dword, do not copy if esi=0
|
||||
Returns: ?
|
||||
Destroys: eax,ebx,edx,ecx,esi,edi
|
||||
--------------------------------------------------------------------------------
|
||||
ClearEvent:
|
||||
Move event to ObjList of owner thread. (May be it was already there.)
|
||||
Reset flags EVENT_SIGNALED and EVENT_WATCHED, keep other fields (.code,
|
||||
.id).
|
||||
Gets:
|
||||
eax -- pointer to event
|
||||
ebx -- id
|
||||
Returns: ?
|
||||
Destroys: eax,ebx,ecx,edi
|
||||
--------------------------------------------------------------------------------
|
||||
SendEvent:
|
||||
Create a new event in the event list of target thread. Sets
|
||||
EVENT_SIGNALED flag in the event.
|
||||
Gets:
|
||||
EVENT.pid <= eax: target thread id;
|
||||
EVENT.code <= [esi]: size is 6*dword, do not copy if esi=0
|
||||
Returns:
|
||||
eax -- pointer to event or 0 for error
|
||||
edx -- Event.id
|
||||
Destroys: eax,ebx,ecx,esi,edi
|
||||
--------------------------------------------------------------------------------
|
||||
DestroyEvent:
|
||||
Moves event to FreeEvents, clears fields .magic, .destroy, .pid, .id.
|
||||
The event may be owned by other thread.
|
||||
Gets:
|
||||
eax -- pointer to event
|
||||
ebx -- event id
|
||||
Returns:
|
||||
eax -- 0 for error, non-zero for success
|
||||
Destroy: eax,ebx,ecx
|
||||
--------------------------------------------------------------------------------
|
||||
WaitEvent:
|
||||
Wait infinitely until flag EVENT_SIGNALED is set in the event owned by
|
||||
the caller thread. This flag is set by signaling thread via RaiseEvent.
|
||||
Waiting thread is frozen by setting TASKDATA.state <= TSTATE_WAITING=5.
|
||||
Flag EVENT_WATCHED is set in the event before freeze.
|
||||
If flag MANUAL_RESET is NOT set in the event then:
|
||||
EVENT_SIGNALED and EVENT_WATCHED are reset when the event is
|
||||
received.
|
||||
When MANUAL_DESTROY is
|
||||
inactive: the event is destroyed by DestroyEvent,
|
||||
active: the event is moved to ObjList of current thread.
|
||||
Gets:
|
||||
eax -- pointer to event
|
||||
ebx -- event id
|
||||
Returns: ?
|
||||
Destroys: eax,ebx,edx,ecx,esi,edi
|
||||
--------------------------------------------------------------------------------
|
||||
WaitEventTimeout:
|
||||
Wait with a timeout until flag EVENT_SIGNALED is set in the event owned
|
||||
by caller thread. This flag is set by signaling thread via RaiseEvent.
|
||||
Waiting thread is frozen by setting TASKDATA.state <= TSTATE_WAITING=5.
|
||||
Flag EVENT_WATCHED is set in the event before freeze.
|
||||
If flag MANUAL_RESET is NOT set in the event then:
|
||||
EVENT_SIGNALED and EVENT_WATCHED are reset when the event is
|
||||
received.
|
||||
When MANUAL_DESTROY is
|
||||
inactive: the event is destroyed by DestroyEvent,
|
||||
active: the event is moved to ObjList of current thread.
|
||||
Gets:
|
||||
eax -- pointer to event
|
||||
ebx -- event id
|
||||
ecx -- timeout, in ticks of system timer
|
||||
Returns:
|
||||
eax -- 0 if the event was not activated, or
|
||||
not 0 if activated
|
||||
Destroys: eax,ebx,edx,ecx,esi,edi
|
||||
--------------------------------------------------------------------------------
|
||||
GetEvent:
|
||||
Waits infinitely for any event in the queue of current thread. Thread is
|
||||
frozen by setting TASKDATA.state <= TSTATE_WAITING = 5. Event data
|
||||
(EVENT.code + 5*dword) are copied to specified buffer when received.
|
||||
Reset priority byte (see above) in the buffer.
|
||||
If flag MANUAL_RESET is NOT set in the event then:
|
||||
EVENT_SIGNALED and EVENT_WATCHED are reset when the event is
|
||||
received.
|
||||
When MANUAL_DESTROY is
|
||||
inactive: the event is destroyed by DestroyEvent,
|
||||
active: the event is moved to ObjList of current thread.
|
||||
Gets:
|
||||
edi -- pointer to buffer to copy data
|
||||
Returns:
|
||||
buffer with following data:
|
||||
+0: (EVENT.code) dword: id of following signal data
|
||||
+4: (EVENT.data) 5*dword: signal data, format depends on
|
||||
EVENT.code
|
||||
Destroys: eax,ebx,edx,ecx,esi,edi
|
||||
--------------------------------------------------------------------------------
|
||||
SysFn 68.14 for application: ; wrapped GetEvent
|
||||
Waits infinitely for any event in the queue of current thread. Thread is
|
||||
frozen by setting TASKDATA.state <= TSTATE_WAITING = 5. Event data
|
||||
(EVENT.code + 5*dword) are copied to specified buffer when received.
|
||||
Reset priority byte (see above) in the buffer.
|
||||
Gets:
|
||||
eax -- 68: function number
|
||||
ebx -- 14: subfunction number
|
||||
ecx -- pointer to data buffer (size is 6*dword)
|
||||
Returns:
|
||||
ecx = buffer with following data:
|
||||
+0: (EVENT.code) dword: id of following signal data
|
||||
+4: (EVENT.data) 5*dword: signal data, format depends on
|
||||
EVENT.code
|
||||
Destroys:
|
||||
eax
|
||||
|
Loading…
Reference in New Issue
Block a user