Avoid using WM_TIMER messages to schedule internal driver callbacks, use a custom mechanism instead.
Each thread keeps a list of callbacks that it wants to eventually invoke, which happens from within WAYLAND_MsgWaitForMultipleObjectsEx. The callback is invoked if the current time is past (or equal) the callback target time.
In order to ensure that threads will wake up to service callbacks, each callback also registers a "wakeup" which is handled by the the process event read thread, along with reads from the compositor fd. When a wakeup is triggered we wakeup all threads in case they have a callback that needs invocation. We use a single timerfd for all wakeups in the process, which we reschedule for the next wakeup on demand.