kernel: Add event queue implementation to wait for objects efficiently.

Based on hamishm's original patch from 2015, but heavily modified,
refactored, and reworked.

From the original commit message:

> When an object is deleted, a B_EVENT_INVALID event is delivered,
> and the object is unregistered from the queue.
>
> The special event flag B_EVENT_ONE_SHOT can be passed in when adding
> an object so that the object is automatically unregistered when an
> event is delivered.

Modifications to the original change include:

 * Removed the public interface (syscalls remain private for the moment)

 * Event list queueing/dequeueing almost entirely rewritten, including:
  - Clear events field when dequeueing.

  - Have B_EVENT_QUEUED actually indicate whether the event has been
    appended to the linked list (or not), based around lock state.
    The previous logic was prone to races and double-insertions.

  - "Modify" is now just "Deselect + Select" performed at once;
    previously it could cause use-after-frees.

  - Unlock for deselect only once at the end of dequeue.

  - Handle INVALID events still in the queue upon destruction,
    fixing memory leaks.

 * Deduplified code with wait_for_objects.

 * Use of C++ virtual dispatch instead of C-style enum + function calls,
   and BReferenceable plus destructors for teardown.

 * Removed select/modify/delete flags. Select/Modify are now the same
   operation on the syscall interface, and "Delete" is done when 0
   is passed for "events". Additionally, the events selected can be fetched
   by passing -1 for "events".

 * Implemented level-triggered mode.

 * Use of BStackOrHeapArray and other convenience routines in syscalls.

Change-Id: I1d2f094fd981c95215a59adbc087523c7bbbe40b
Reviewed-on: https://review.haiku-os.org/c/haiku/+/6745
Tested-by: Commit checker robot <[email protected]>
Reviewed-by: Jérôme Duval <[email protected]>
This commit is contained in:
Augustin Cavalier
2023-07-29 15:53:15 +00:00
committed by waddlesplash
parent a3f83f646c
commit f66d2b46a8
14 changed files with 938 additions and 74 deletions
+26
View File
@@ -0,0 +1,26 @@
/*
* Copyright 2023, Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _SYSTEM_EVENT_QUEUE_DEFS_H
#define _SYSTEM_EVENT_QUEUE_DEFS_H
// extends B_EVENT_* constants defined in OS.h
enum {
B_EVENT_LEVEL_TRIGGERED = (1 << 26), /* Event is level-triggered, not edge-triggered */
B_EVENT_ONE_SHOT = (1 << 27), /* Delete event after delivery */
/* bits 28 through 30 are reserved for the kernel */
};
typedef struct event_wait_info {
int32 object;
uint16 type;
int32 events; /* select(): > 0 to select, -1 to get selection, 0 to deselect */
void* user_data;
} event_wait_info;
#endif /* _SYSTEM_EVENT_QUEUE_DEFS_H */
+7
View File
@@ -23,6 +23,7 @@ extern "C" {
struct attr_info;
struct dirent;
struct event_wait_info;
struct fd_info;
struct fd_set;
struct fs_info;
@@ -74,6 +75,12 @@ extern status_t _kern_get_safemode_option(const char *parameter,
extern ssize_t _kern_wait_for_objects(object_wait_info* infos, int numInfos,
uint32 flags, bigtime_t timeout);
extern int _kern_event_queue_create(int openFlags);
extern status_t _kern_event_queue_select(int queue,
struct event_wait_info* userInfos, int numInfos);
extern ssize_t _kern_event_queue_wait(int queue, struct event_wait_info* infos,
int numInfos, uint32 flags, bigtime_t timeout);
/* user mutex functions */
extern status_t _kern_mutex_lock(int32* mutex, const char* name,
uint32 flags, bigtime_t timeout);