Page MenuHomeFreeBSD

Allow faster eventhandler dispatching by keeping pointers to handler lists.
AbandonedPublic

Authored by ian on Oct 29 2017, 2:15 AM.
Tags
None
Referenced Files
Unknown Object (File)
Mon, Apr 29, 6:25 PM
Unknown Object (File)
Fri, Apr 26, 7:25 PM
Unknown Object (File)
Tue, Apr 23, 12:31 AM
Unknown Object (File)
Mon, Apr 22, 11:27 AM
Unknown Object (File)
Mon, Apr 22, 8:46 AM
Unknown Object (File)
Apr 6 2024, 11:18 AM
Unknown Object (File)
Feb 2 2024, 7:28 AM
Unknown Object (File)
Dec 23 2023, 9:03 AM
Subscribers

Details

Reviewers
kib
mjg
Summary

Comments in sys/eventhandler.h make references to "slow handlers" implying that there may be some plan for a faster mechanism, but no comments or code clues exist about what was envisioned. The current mechanism is slow, requiring a global lock be held while searching for a named list by walking the list-of-lists doing strcmp() on each entry.

This change adds a fairly minimal mechanism for pre-defining an event list and keeping a pointer to it as a global var, allowing the event handlers to be invoked without the slow list-lookup step. The new mechanism is completely compatible with the old. For any given event, it will work fine to use both the old EVENTHANDLERS_INVOKE() and the new EVENTHANDLERS_INVOKE_LIST(), so this introduces no incompatibilites with existing code or modules.

From the point of view of wanting to handle an event, there is no change here at all. You continue to register for events by name as always, without needing any particular declaration in scope. The decision to use the new mechanism is purely on the invocation side.

As an example of what's required to convert existing high-frequency events to the new mechanism, this includes a conversion of process and thread related events. Once the basic scheme is hammered out and committed, we can track down and convert other frequent events.

Diff Detail

Repository
rS FreeBSD src repository - subversion
Lint
Lint Skipped
Unit
Tests Skipped
Build Status
Buildable 12291

Event Timeline

Why do we need to keep the compatibility and to create the _LIST KPI in addition to the existing KPI ?

As I understand, the goal of the change is to remove the lookup of the eventhandler list by name. What if you make the 'slow' handlers require the EVENTHANDLER_DEFINE() presence in the source code and then use the eventhandler_tag as an argument for _INVOKE and pehaps even to _REGISTER/_UNREGISTER. This probably would also require some module magic. In other words, the eventhandler would become very similar to the MALLOC_DECLARE/MALLOC_DEFINE.

I understand that this is larger rototiling of the KPI, perhaps in the backward-incompatible way, but I do not see a reason to keep the string-identified handlers machinery around, if it is not useful. Is there a handler kind which cannot be easily converted into the stringless model ?

Could you please update the EVENTHANDLER(9) man page too?

In D12821#266158, @kib wrote:

Why do we need to keep the compatibility and to create the _LIST KPI in addition to the existing KPI ?

As I understand, the goal of the change is to remove the lookup of the eventhandler list by name. What if you make the 'slow' handlers require the EVENTHANDLER_DEFINE() presence in the source code and then use the eventhandler_tag as an argument for _INVOKE and pehaps even to _REGISTER/_UNREGISTER. This probably would also require some module magic. In other words, the eventhandler would become very similar to the MALLOC_DECLARE/MALLOC_DEFINE.

I understand that this is larger rototiling of the KPI, perhaps in the backward-incompatible way, but I do not see a reason to keep the string-identified handlers machinery around, if it is not useful. Is there a handler kind which cannot be easily converted into the stringless model ?

The goal was to provide an option to avoid the named-list lookups for high-frequency events, without requiring changes to existing code dealing with low-frequency events. There is very little gain in optimizing events that happen once at start/shutdown, or even events for a power suspend/resume.

The way this stuff works right now, the argument to the DECLARE, DEFINE, and INVOKE macros must be the bare unquoted-text name of the event, so that preprocessor token-pasting can be used to generate the event-handler calls with the right function signature. The alternative would be to say that all event handlers must have a signature of 'void func(void* arg, ...)' so they can all be called as eh_func(arg, ## VA_ARGS) and we get no compile-time checking that you registered the right type of callback function for a given event. And of course, accessing the args in the callback would require va_arg() stuff.

The existing system also provides what I think of as "loose late binding" between handlers and events. Registering for an event creates the list even if the source of that event doesn't exist in the kernel. If the source then later appears (by loading a module, plugging/enabling a device, whatever), the already-registered handlers will get invoked when the module starts invoking events. This is why I made the new pre-defined lists exist in the same global list-of-lists as the slow named-list mechanism... either the source or the consumer of an event can be first to create the list.

I have no idea if any existing code relies on the loose late binding, but it seems possible to me that you could have a module whose only job is to monitor some events that are produced by different modules that may or may not already be present when the first module is loaded.

Update to remove unrelated changes (moving lines from eventhandler.h to proc_events.h, and rearranging the order of some macros in eventhandler.h).

Incorporated the EHL_NONEMPTY flag from D12814.

Since statically allocated/init'd lists cannot exist (because they don't work with unloading modules), removed EHL_INITTED and checks for it, and now all inits happen when the list is allocated.

Abandoned in favor of the nearly-identical D12814.