Halide icon indicating copy to clipboard operation
Halide copied to clipboard

Fix potential race condition in power_hvx_on/off

Open dsharletg opened this issue 5 years ago • 8 comments

This fix potentially allows the function to return with HVX actually being powered on (thread 1: power_hvx_on; thread 2: power_hvx_on. The second thread will return while the first thread is still working on HAP_power_set). However, I'm not sure this is actually a problem. It might just make performance a bit slow for a few milliseconds? @pranavb-ca @dpalermo what do you think?

dsharletg avatar Aug 18 '20 21:08 dsharletg

Maybe the better fix is to just use an actual mutex?

dsharletg avatar Aug 18 '20 21:08 dsharletg

Yeah, I'd use a mutex instead -- enforcing serial ordering of the entire power_on and power_off calls seems like a wise thing.

steven-johnson avatar Aug 18 '20 22:08 steven-johnson

Maybe the better fix is to just use an actual mutex?

On balance I do not see this slowing down code too much. The overhead, IMO would be negligible provided the pipeline offloaded is sizeable. So, yes, adding a mutex to serialize execution is a good idea.

pranavb-ca avatar Aug 18 '20 22:08 pranavb-ca

I think the main reason we've avoided a mutex here is not performance but messiness in initialization. Can we zero initialize a global qurt_mutex_t?

dsharletg avatar Aug 18 '20 22:08 dsharletg

I think the main reason we've avoided a mutex here is not performance but messiness in initialization. Can we zero initialize a global qurt_mutex_t?

Yes, I have always wanted to avoid mutexes in QuRT for this reason. Unfortunately, we cannot zero initialize. The only way to do it is via a constructor. we do this in Log.cpp for the logging mutex.

pranavb-ca avatar Aug 18 '20 22:08 pranavb-ca

Could we do something like:

qurt_mutex_t &get_mutex() {
    static bool is_inited = false;
    static qurt_mutex_t m = {0};  // probably doesn't matter
    if (!__atomic_test_and_set(&is_inited, __ATOMIC_ACQUIRE)) {
        qurt_mutex_init(&m);
    }
    return m;
}

steven-johnson avatar Aug 24 '20 19:08 steven-johnson

That also has a race condition, a second call might return before a first call has initialized the mutex.

I also really doubt the global constructor is actually safe either, for similar reasons. Maybe in C++11 it is theoretically safe, but whether it is in practice on the Hexagon compiler/linker is another question.

Maybe the best thing to do is have a dumb spin lock (that can be zero initialized), and only use it for short-running lock situations (such as powering HVX on or off)?

dsharletg avatar Aug 24 '20 20:08 dsharletg

That also has a race condition, a second call might return before a first call has initialized the mutex.

Ouch. Yes.

steven-johnson avatar Aug 24 '20 21:08 steven-johnson