Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
7587 dunkaist 1
Last edit: 26/07/2013
2
 
3
Kernel event subsystem may be useful when writing drivers and kernel space
4
services. It is not related to the subsystem of GUI events. An event, from the
5
kernel's point of view, is a kernel space object which is owned by the thread
6
that created it.
7
 
8
struc EVENT
9
{
10
   .magic       dd ?    ; 'EVNT'
11
   .destroy     dd ?    ; internal destructor
12
   .fd          dd ?    ; next object in list
13
   .bk          dd ?    ; prev object in list
14
   .pid         dd ?    ; owner (thread) id
15
   .id          dd ?    ; event uid. (just a number)
16
   .state       dd ?    ; internal flags; see below
17
   .code        dd ?    ; MSB: event class; next byte: priority
18
                        ; (used by kernel only, always 0 for reading),
19
                        ; The higher dword value the higher event priority.
20
                        ; Two LSBs: event code.
21
                rd 5    ; .data: the structure of this field is not defined and
22
                        ; depends on .code field. (Pass any data you need here)
23
   .size     =  $ - .magic
24
   .codesize =  $ - .code
25
}
26
 
27
Realtime events have class 0хFF. Currently defined:
28
EVENT.code=                             ; (Used in sound subsystem)
29
        RT_INP_EMPTY      = 0xFF000001
30
        RT_OUT_EMPTY      = 0xFF000002
31
        RT_INP_FULL       = 0xFF000003
32
        RT_OUT_FULL       = 0xFF000004
33
 
34
 
35
Flags of EVENT.state field are defined in gui/event.inc.
36
        EVENT_SIGNALED   = 0x20000000 ; bit 29: event is active/inactive
37
        EVENT_WATCHED    = 0x10000000 ; bit 28: owner thread is waiting for the
38
                                      ;         event to be active
39
        MANUAL_RESET     = 0x40000000 ; bit 30: do not deactivate event
40
                                      :         automatically on receive
41
        MANUAL_DESTROY   = 0x80000000 ; bit 31: do not return event to a list of
42
                                      ;         free ones on receive
43
 
44
As of SVN r3732 (assume same below) the definition is located in
45
/kernel/trunk/const.inc and is as follows:
46
 
47
struct  APPOBJ                  ; common object header
48
        magic           dd ?    ;
49
        destroy         dd ?    ; internal destructor
50
        fd              dd ?    ; next object in list
51
        bk              dd ?    ; prev object in list
52
        pid             dd ?    ; owner id
53
ends
54
 
55
struct  EVENT           APPOBJ
56
        id              dd ?    ; event uid
57
        state           dd ?    ; internal flags
58
        code            dd ?
59
                        rd 5    ; .data
60
ends
61
 
62
Code is located in gui/event.inc.
63
Event objects live in kernel memory as a double-linked list (see fields .bk and
64
.fd). While initialization the kernel reserves memory, creates 512 events and
65
places them into FreeEvents list. When out of free event, kernel creates another
66
512 ones etc. Each thread has own double-linked lists where an event may be
67
placed to:
68
        ObjList -- a list of kernel objects associated with the thread;
69
        EventList -- a list of kernel events for the thread.
70
When events are moved between lists or reordered their data are not copied. This
71
is done only via modification of .fd and .bk fields. These lists work as FIFO
72
queues. Sending does not block, receiving blocks. Addressing is direct, by
73
thread id. There always is an owner thread for an event.
74
 
75
Event's life cycle is defined by flags while creation. By default the kernel
76
uses values MANUAL_RESET = 0 and MANUAL_DESTROY = 0. Such an event is oneshot
77
and is automatically freed by the kernel and returned to the FreeEvents list
78
when received. An event with flag MANUAL_DESTROY = 1 becomes inactive when
79
received but remains in thread's object list and can be reused. An event with
80
flags MANUAL_DESTROY = 1 and MANUAL_RESET = 1 remains active when received and
81
can be reset via call to ClearEvent.
82
 
83
A life cycle example of a sound subsystem event:
84
 * For an audio buffer (possibly several) the driver creates an event in ObjList
85
   by calling CreateEvent with flag MANUAL_DESTROY.
86
 * Then driver calls WaitEvent for the event (waits for EVENT_SIGNALED event
87
   flag) and blocks waiting for buffer update request.
88
 * The buffer update request is sent with RaiseEvent from another thread.
89
 * Sending (RaiseEvent) and receiving (WaitEvent) are repeated as buffer gets
90
   empty.
91
 * Driver deactivates the event with ClearEvent when playback is stopped.
92
 
93
Actually, the event structure is described here only for understanding of
94
subsystem work principles. Direct field access is discouraged due to possible
95
compatibility issues in the future. Only API calls should be used. A pair
96
"pointer to an event" and "event id" is considered a single 64-bit id. This id
97
should be stored somewhere after a call to CreateEvent for further work with the
98
event.
99
 
100
The kernel exports following event related functions:
101
(for drivers, etc; called from kernel mode)
102
 
103
        CreateEvent
104
        RaiseEvent
105
        ClearEvent
106
        SendEvent
107
        DestroyEvent
108
        WaitEvent
109
        WaitEventTimeout
110
        GetEvent
111
        For user applications sysfn 68.14 (a wrapper to GetEvent)
112
 
113
--------------------------------------------------------------------------------
114
CreateEvent:
115
        Creates a new event in ObjList queue of current thread.
116
        Sets:
117
                EVENT.destroy   <= default internal destructor
118
                EVENT.pid       <= current Process id
119
                EVENT.id        <= unique id
120
                EVENT.state     <= ecx: flags
121
                EVENT.code      <= [esi]: size is 6*dword, do not copy if esi=0
122
        Returns:
123
                eax -- pointer to the event or 0 for error.
124
                edx -- Event.id.
125
        Destroys: eax,ebx,edx,ecx,esi,edi
126
--------------------------------------------------------------------------------
127
RaiseEvent:
128
        Activates existing event (may be owned by another thread) by setting
129
        EVENT_SIGNALED flag. Sets EVENT.code data if necessary. Does nothing
130
        more if EVENT_SIGNALED flag is already active in the event. If
131
        EVENT_SIGNALED flag is not set in the event it will be set, except when
132
        EVENT_WATCHED in edx = 1 and EVENT_WATCHED in the event = 0. I.e. while
133
        setting EVENT_WATCHED in edx it is checked if owner thread is waiting
134
        for event activation. No flags, except EVENT_SIGNALED, are modified in
135
        the event.
136
        Gets:
137
                eax     -- pointer to event
138
                ebx     -- id
139
                edx     -- flags (see EVENT.state)
140
        Sets:
141
                EVENT.code    <= [esi]: size is 6*dword, do not copy if esi=0
142
        Returns: ?
143
        Destroys: eax,ebx,edx,ecx,esi,edi
144
--------------------------------------------------------------------------------
145
ClearEvent:
146
        Move event to ObjList of owner thread. (May be it was already there.)
147
        Reset flags EVENT_SIGNALED and EVENT_WATCHED, keep other fields (.code,
148
        .id).
149
        Gets:
150
                eax     -- pointer to event
151
                ebx     -- id
152
        Returns: ?
153
        Destroys: eax,ebx,ecx,edi
154
--------------------------------------------------------------------------------
155
SendEvent:
156
        Create a new event in the event list of target thread. Sets
157
        EVENT_SIGNALED flag in the event.
158
        Gets:
159
                EVENT.pid       <= eax: target thread id;
160
                EVENT.code      <= [esi]: size is 6*dword, do not copy if esi=0
161
        Returns:
162
                eax -- pointer to event or 0 for error
163
                edx -- Event.id
164
        Destroys: eax,ebx,ecx,esi,edi
165
--------------------------------------------------------------------------------
166
DestroyEvent:
167
        Moves event to FreeEvents, clears fields .magic, .destroy, .pid, .id.
168
        The event may be owned by other thread.
169
        Gets:
170
                eax     -- pointer to event
171
                ebx     -- event id
172
        Returns:
173
                eax     -- 0 for error, non-zero for success
174
        Destroy: eax,ebx,ecx
175
--------------------------------------------------------------------------------
176
WaitEvent:
177
        Wait infinitely until flag EVENT_SIGNALED is set in the event owned by
178
        the caller thread. This flag is set by signaling thread via RaiseEvent.
179
        Waiting thread is frozen by setting TASKDATA.state <= TSTATE_WAITING=5.
180
        Flag EVENT_WATCHED is set in the event before freeze.
181
        If flag MANUAL_RESET is NOT set in the event then:
182
                EVENT_SIGNALED and EVENT_WATCHED are reset when the event is
183
                received.
184
                When MANUAL_DESTROY is
185
                        inactive: the event is destroyed by DestroyEvent,
186
                        active: the event is moved to ObjList of current thread.
187
        Gets:
188
                eax     -- pointer to event
189
                ebx     -- event id
190
        Returns: ?
191
        Destroys: eax,ebx,edx,ecx,esi,edi
192
--------------------------------------------------------------------------------
193
WaitEventTimeout:
194
        Wait with a timeout until flag EVENT_SIGNALED is set in the event owned
195
        by caller thread. This flag is set by signaling thread via RaiseEvent.
196
        Waiting thread is frozen by setting TASKDATA.state <= TSTATE_WAITING=5.
197
        Flag EVENT_WATCHED is set in the event before freeze.
198
        If flag MANUAL_RESET is NOT set in the event then:
199
                EVENT_SIGNALED and EVENT_WATCHED are reset when the event is
200
                received.
201
                When MANUAL_DESTROY is
202
                        inactive: the event is destroyed by DestroyEvent,
203
                        active: the event is moved to ObjList of current thread.
204
        Gets:
205
                eax     -- pointer to event
206
                ebx     -- event id
207
                ecx     -- timeout, in ticks of system timer
208
        Returns:
209
                eax     -- 0 if the event was not activated, or
210
                           not 0 if activated
211
        Destroys: eax,ebx,edx,ecx,esi,edi
212
--------------------------------------------------------------------------------
213
GetEvent:
214
        Waits infinitely for any event in the queue of current thread. Thread is
215
        frozen by setting TASKDATA.state <= TSTATE_WAITING = 5. Event data
216
        (EVENT.code + 5*dword) are copied to specified buffer when received.
217
        Reset priority byte (see above) in the buffer.
218
        If flag MANUAL_RESET is NOT set in the event then:
219
                EVENT_SIGNALED and EVENT_WATCHED are reset when the event is
220
                received.
221
                When MANUAL_DESTROY is
222
                        inactive: the event is destroyed by DestroyEvent,
223
                        active: the event is moved to ObjList of current thread.
224
        Gets:
225
                edi     -- pointer to buffer to copy data
226
        Returns:
227
                buffer with following data:
228
                +0: (EVENT.code) dword: id of following signal data
229
                +4: (EVENT.data) 5*dword: signal data, format depends on
230
                    EVENT.code
231
        Destroys: eax,ebx,edx,ecx,esi,edi
232
--------------------------------------------------------------------------------
233
SysFn 68.14 for application:    ; wrapped GetEvent
234
        Waits infinitely for any event in the queue of current thread. Thread is
235
        frozen by setting TASKDATA.state <= TSTATE_WAITING = 5. Event data
236
        (EVENT.code + 5*dword) are copied to specified buffer when received.
237
        Reset priority byte (see above) in the buffer.
238
        Gets:
239
                eax     -- 68: function number
240
                ebx     -- 14: subfunction number
241
                ecx     -- pointer to data buffer (size is 6*dword)
242
        Returns:
243
                ecx = buffer with following data:
244
                +0: (EVENT.code) dword: id of following signal data
245
                +4: (EVENT.data) 5*dword: signal data, format depends on
246
                    EVENT.code
247
        Destroys:
248
                eax