Subversion Repositories Kolibri OS

Rev

Rev 3843 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
3843 yogev_ezra 1
Дата последней правки 26/07/2013.
2
Подсистема событий ядра может понадобиться при написании драйверов и сервисов, работающих в режиме ядра.
3
Она не имеет отношения к подсистеме событий пользовательского интерфейса.
4
С точки зрения ядра событие - объект ядра и принадлежит создавшему его потоку.
5
 
6
struc EVENT
7
{
8
   .magic       dd ?    ; 'EVNT'
9
   .destroy     dd ?    ; internal destructor
10
   .fd          dd ?    ; next object in list
11
   .bk          dd ?    ; prev object in list
12
   .pid         dd ?    ; owner id. идентификатор владельца (потока)
13
   .id          dd ?    ; event uid. уникальный идентификатор события (просто номерок)
14
   .state       dd ?    ; internal flags; см. далее.
15
   .code        dd ?    ; старший байт класс события, ; следующий байт приоритет
16
                        ; (будет использоваться только внутри ядра, при чтении всегда 0),
17
                        ; Чем больше численное значение двойного слова тем важнее событие.
18
                        ; два младших байта код события.
19
                rd 5    ; .data - точная структура этого поля не определена и зависит
20
                        ; от поля .code. (Здесь можно передавать какие-то свои данные,
21
                        ; при необходимости :)
22
   .size     =  $ - .magic
23
   .codesize =  $ - .code
24
}
25
 
26
События реального времени получили класс 0хFF. Пока определёны только:
27
EVENT.code= 				;(Используется в звуковой подсистеме).
7136 dunkaist 28
        RT_INP_EMPTY      = 0xFF000001
29
        RT_OUT_EMPTY      = 0xFF000002
30
        RT_INP_FULL       = 0xFF000003
31
        RT_OUT_FULL       = 0xFF000004
3843 yogev_ezra 32
 
33
 
34
Флаги поля EVENT.state определены в gui/event.inc.
7136 dunkaist 35
	EVENT_SIGNALED   = 0x20000000 ;бит 29  событие активно/неактивно;
36
	EVENT_WATCHED    = 0x10000000 ;бит 28, поток-владелец ожидает активации события;
37
	MANUAL_RESET     = 0x40000000 ;бит 30, не деактивировать событие автоматически по получении;
38
	MANUAL_DESTROY   = 0x80000000 ;бит 31, не возвращать событие в список свободных по получении.
3843 yogev_ezra 39
 
40
На момент ревизии 3732 (и далее по тексту то же) определение находится в \kernel\trunk\const.inc
41
и выглядит так:
42
 
43
struct  APPOBJ                  ; common object header
44
        magic           dd ?    ;
45
        destroy         dd ?    ; internal destructor
46
        fd              dd ?    ; next object in list
47
        bk              dd ?    ; prev object in list
48
        pid             dd ?    ; owner id
49
ends
50
 
51
struct  EVENT           APPOBJ
52
        id              dd ?   ;event uid
53
        state           dd ?   ;internal flags
54
        code            dd ?
55
                        rd 5   ; .data
56
ends
57
 
58
Код находится в gui/event.inc.
59
Сами события как обьекты существуют в памяти ядра в виде двусвязного списка (см. поля .bk и .fd).
60
При инициализации ядро резервирует память и создает 512 таких обьектов, помещая их в список FreeEvents
61
(свободных событий). При нехватке событий (все заняты, а нужно ещё) ядро создает ещё 512 свободных
62
и т.д. Каждый поток имеет свои (двусвязные) списки (в которые может быть помещено событие):
63
ObjList - список объектов ядра, ассоциированных с этим потоком;
64
EventList - список событий ядра для потока.
65
Сами события, физически, при перемещении между списками и смене очередности в списке не перемещаются
66
и не копируются. Это происходит только благодаря модификации полей .fd и .bk. Принцип работы списков,
67
как очередей - FIFO. Использутся неблокирующая отправка и блокирующее получение. Адресация - прямая
68
(у события всегда есть поток-владелец), по идентификатору потока.
69
 
70
Жизненый цикл событий определяется флагами при создании. По умолчанию ядро использует значения
71
MANUAL_RESET = 0 и MANUAL_DESTROY = 0. Такое событие является "одноразовым", и автоматически освобождается
72
ядром, возвращаясь в список свободных событий после получения.
73
Событие с флагом MANUAL_DESTROY = 1 после получения переходит в неактивное состояние, но остаётся в списке
74
объектов потока и может использоваться снова. Событие с флагами MANUAL_DESTROY =1 и MANUAL_RESET = 1
75
остаётся активным после получения и может быть сброшено вызовом ClearEvent.
76
 
77
Пример (вариант) жизненного цикла события из звуковой подсистемы:
78
Для зукового буфера (их может быть несколько) драйвер создает событие в списке ObjList с помощью
79
CreateEvent и флагом MANUAL_DESTROY. Далее драйвер вызывает WaitEvent для этого события (ожидает флага
80
EVENT_SIGNALED в событии) и блокируется, в ожидании запроса на пополнение буфера. Запрос отправляется
81
с помощью RaiseEvent из другого потока. Отправка (RaiseEvent) и получение (WaitEvent) циклически
82
повторяются при опустошении буфера. При остановке воспроизведения драйвер деактивирует событие с помощью
83
ClearEvent.
84
 
85
Вообще говоря, структура события приведена здесь только лишь для понимания принципов работы подсистемы.
86
Самостоятельная работа с полями не приветствуется, ввиду возможных в будущем проблем с совместимостью.
87
Работа должна производится только через API (функции подсистемы), с доступом только к тем полям, доступ к
88
которым предоставляет функция. При этом пару "указатель на событие" и "уникальный идентификатор события"
89
следует рассматривать как один 64-х битный уникальный идентификатор. (Если вы вызвали CreateEvent, напимер,
90
его нужно запомнить где-нибудь [если это нужно] для дальнейшей работы с событием).
91
 
92
Функции для работы с событиями экспортитуемые ядром:
93
(для драйверов и т.п.; вызываются в режиме ядра)
94
 
95
        CreateEvent
96
        RaiseEvent
97
        ClearEvent
98
        SendEvent
99
        DestroyEvent
100
        WaitEvent
101
        WaitEventTimeout
102
        GetEvent
103
        Для пользовательских приложений Ф68.14 (GetEvent с обёрткой)
104
 
105
---------------------------------------------------------------------------------------------
106
CreateEvent:
107
        Создаёт новое событие в очереди ObjList текущего потока.
108
        Устанавливает:
109
                EVENT.destroy   <= внутренний деструктор по умолчанию;
110
                EVENT.pid       <= текущий Process id;
111
                EVENT.id        <= уникальный идентификатор;
112
                EVENT.state     <= ecx - флаги;
113
                EVENT.code      <= [esi], (если esi=0, то не копирует), размер 6*dword;
114
        Возвращает:
115
                eax - указатель на событие или 0 при ошибке.
116
                edx - Event.id.
117
        Портит: eax,ebx,edx,ecx,esi,edi
118
---------------------------------------------------------------------------------------------
119
RaiseEvent:
120
        Активирует уже существующее событие (может принадлежать другому потоку) установкой
121
        флага EVENT_SIGNALED. Если необходимо, -  устанавливает данные EVENT.code.
122
        Если флаг EVENT_SIGNALED в самом событии уже активен - больше ничего не делает.
123
        Если EVENT_SIGNALED не установлен в самом событии, то он будет установлен, кроме случая
124
                {EVENT_WATCHED в edx=1 и EVENT_WATCHED в событии=0}.
125
        Т.е. при установке EVENT_WATCHED в edx, проверяется, ожидает ли поток-владелец активации
126
        события.
127
        Кроме EVENT_SIGNALED в событии никакие другие флаги не модифицируются.
128
        Принимает:
129
                eax     - указатель на событие;
130
                ebx     - id, уникальный идентификатор события;
131
                edx     - флаги для операции (формат EVENT.state);
132
                EVENT.code  <= [esi], (если esi=0, то не копирует), размер 6*dword;
133
        Возвращает: ?
134
        Портит: eax,ebx,edx,ecx,esi,edi .
135
---------------------------------------------------------------------------------------------
136
ClearEvent:
137
        Перемещает событие в список ObjList потока-владельца. (Возможно оно там и находилось.)
138
        Сбрасывает флаги EVENT_SIGNALED, EVENT_WATCHED. С остальными полями (.code, .id),
139
        ничего не делает.
140
        Принимает:
141
                eax     - указатель на событие;
142
                ebx     - id, уникальный идентификатор события.
143
        Возвращает: ?
144
        Портит: eax,ebx,ecx,edi .
145
---------------------------------------------------------------------------------------------
146
SendEvent:
147
        Создаёт новое событие в списке событий целевого потока. Устанавливает в событии
148
        флаг EVENT_SIGNALED.
149
        Принимает:
150
                EVENT.pid       <= eax     - pid, идентификатор целевого потока;
151
                EVENT.code      <= [esi], (если esi=0, то не копирует), размер 6*dword;
152
        Возвращает:
153
                eax - указатель на событие или 0 при ошибке.
154
                edx - Event.id. уникальный идентификатор.
155
        Портит: eax,ebx,ecx,esi,edi .
156
---------------------------------------------------------------------------------------------
157
DestroyEvent:
158
        Переносит EVENT в список FreeEvents, чистит поля .magic,.destroy,.pid,.id.
159
        Событие может принадлежать другому потоку.
160
        Принимает:
161
                eax     - указатель на событие;
162
                ebx     - id, уникальный идентификатор события.
163
        Возвращает:
164
                eax     - 0 при ошибке, не 0 при успехе.
165
        Портит: eax,ebx,ecx .
166
---------------------------------------------------------------------------------------------
167
WaitEvent:
168
        Бесконечно ожидает установки флага EVENT_SIGNALED в конкретном событии, принадлежащем
169
        вызывающему WaitEvent потоку. Сигнализирующий поток устанавливат этот флаг через
170
        RaiseEvent. Ожидающий поток замораживается путем перевода TASKDATA.state<=TSTATE_WAITING=5.
171
        Перед заморозкой устанавливается флаг EVENT_WATCHED в событии.
172
        Если в полученном событии НЕ установлен MANUAL_RESET, то:
173
                {EVENT_SIGNALED и EVENT_WATCHED по получении события сбрасываются.
174
                 При неактивном  MANUAL_DESTROY - событие уничтожается штатно (DestroyEvent),
175
                 а при активном - перемещается в список ObjList текущего слота.}
176
        Принимает:
177
                eax     - указатель на событие;
178
                ebx     - id, уникальный идентификатор события.
179
        Возвращает: ?
180
        Портит: eax,ebx,edx,ecx,esi,edi .
181
---------------------------------------------------------------------------------------------
182
WaitEventTimeout:
183
        Ожидает с таймаутом установки флага EVENT_SIGNALED в конкретном событии, принадлежащем
184
        вызывающему WaitEventTimeout потоку. Сигнализирующий поток устанавливат этот флаг через
185
        RaiseEvent. Ожидающий поток замораживается путем перевода TASKDATA.state<=TSTATE_WAITING=5.
186
        Перед заморозкой устанавливается флаг EVENT_WATCHED в событии.
187
        Если в полученном событии НЕ установлен MANUAL_RESET, то:
188
                {EVENT_SIGNALED и EVENT_WATCHED по получении события сбрасываются.
189
                 При неактивном  MANUAL_DESTROY - событие уничтожается штатно (DestroyEvent),
190
                 а при активном - перемещается в список ObjList текущего слота.}
191
        Принимает:
192
                eax     - указатель на событие;
193
                ebx     - id, уникальный идентификатор события.
194
                ecx     - время ожидания в тиках системного таймера.
195
        Возвращает:
196
                eax     - 0 - таймаут, если событие не активировалось, или
197
                          не 0, если было активировано.
198
        Портит: eax,ebx,edx,ecx,esi,edi .
199
---------------------------------------------------------------------------------------------
200
GetEvent:
201
        Бесконечно ожидает любое событие в очереди событий текущего потока. Поток замораживается
202
        путем перевода TASKDATA.state<=TSTATE_WAITING=5. Данные события (EVENT.code+5*dword)
203
        по получении копируются в указанный буфер. Сбрасывает байт приоритета (см. выше) в буфере.
204
        Если в полученном событии НЕ установлен MANUAL_RESET, то:
205
                {EVENT_SIGNALED и EVENT_WATCHED по получении события сбрасываются.
206
                 При неактивном  MANUAL_DESTROY - событие уничтожается штатно (DestroyEvent),
207
                 а при активном - перемещается в список ObjList текущего слота.}
208
        Принимает:
209
                edi     - указатель на буфер, куда копировать данные.
210
        Возвращает:
211
                буфер, содержащий следующую информацию:
212
                +0: (EVENT.code) dword: идентификатор последующих данных сигнала
213
                +4: (EVENT.data, поле формально не определено) данные принятого
214
                сигнала (5*dword), формат которых определяется первым dword-ом.
215
        Портит: eax,ebx,edx,ecx,esi,edi .
216
--------------------------------------------------------------------------------------------
217
Ф 68.14 для приложений:         ;это тот же GetEvent, но с обёрткой.
218
        Бесконечно ожидает любое событие в очереди событий текущего потока. Ожидающий поток
219
        замораживается путем перевода TASKDATA.state<=TSTATE_WAITING=5. Данные события (EVENT.code+5*dword)
220
        копируются в указанный буфер. Сбрасывает байт приоритета (см. выше) в буфере.
221
        Принимает:
222
                eax     - 68 - номер функции
223
                ebx     - 14 - номер подфункции
224
                ecx     - указатель на буфер для информации (размер 6*dword)
225
        Возвращает:
226
                буфер, на который указывает ecx, содержит следующую информацию:
227
                +0: (EVENT.code) dword: идентификатор последующих данных сигнала
228
                +4: (EVENT.data, поле формально не определено) данные принятого
229
                сигнала (5*dword), формат которых определяется первым dword-ом.
230
        Портит:
231
                eax .
7136 dunkaist 232
---------------------------------------------------------------------------------------------