|
About
TODO
Blog
RSS
Old blog
Projects
Gallery
Notes
Mon, 06 Nov 2006
New userspace ring buffer implementation. int kevent_ring_init(int ctl_fd, struct ring_buffer *ring, unsigned int num);which initializes kevent's ring buffer ( int ctl_fd is a kevent file descriptor, struct ring_buffer *ring
is a userspace allocated ring buffer, and unsigned int num is maximum number of events
(struct ukevent) which can be placed into that buffer).Ring buffer is described with following structure:
struct kevent_ring
{
unsigned int ring_kidx, ring_uidx;
struct ukevent event[0];
};
where unsigned int ring_kidx, ring_uidx are last kernel's position
(i.e. position which points to the first place after the last kevent put by kernel into the ring buffer)
and last userspace commit (i.e. position where first unread kevent lives) positions appropriately.I will release appropriate userspace test application when tests are completed. When kevent is removed (not dequeued when it is ready, but just removed), even if it was ready, it is not copied into ring buffer, since if it is removed, no one cares about it (otherwise user would wait until it becomes ready and got it through usual way using kevent_get_events() or kevent_wait())
and thus no need to copy it to the ring buffer.Dequeueing of the kevent (calling kevent_get_events()) means that user has processed previously dequeued kevent and is ready to
process new one, which means that position in the ring buffer previously ocupied but that event
can be reused by currently dequeued event. In the world where only one type of syscalls to get events is used
(either usual way and kevent_get_events() or ring buffer and kevent_wait())
it should not be a problem, since kevent_wait() only allows to mark number of events as processed
by userspace starting from the beginning (i.e. from the last processed event), but if several threads will use different models,
that can rise some questions, for example one thread can start to read events from ring buffer,
and in that time other thread will call kevent_get_events(), which can rewrite that events.
Actually other thread can call kevent_wait() to commit that events (i.e. mark them as
processed by userspace so kernel could free them or requeue), so appropriate locking is required in userspace in any way.
So I want to repeat, that it is possible with userspace ring buffer, that events in the ring buffer can be replaced without knowledge for the thread currently reading them (when other thread calls kevent_get_events() or kevent_wait()), so appropriate locking
between threads or processes, which can simultaneously access the same ring buffer,
is required.Having userspace ring buffer allows to make all kevent syscalls as so called 'cancellation points' by glibc, i.e. when thread has been cancelled in kevent syscall, thread can be safely removed and no events will be lost, since each syscall will copy event into special ring buffer, accessible from other threads or even processes (if shared memory is used). /devel/kevent :: Link / Comments (0)
Life sucks - I caught a cold. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||