You'd need to handle allocation failures properly, which I suspect is going to become messy with your approach.
I'd suggest that struct sync would simply be allocated statically as part of the objects. I'd also avoid changing the object vtable, at least in the first steps.
Abusing real event objects also doesn't seem nice. You could have an event_sync that would be a specialized struct sync with just a signaled flag, and use it for all event-like objects, including the events themselves.