Re: [PATCHv2] threads: add one-time initialization support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



2011/4/23 Eric Blake <eblake@xxxxxxxxxx>:
> mingw lacks the counterpart to PTHREAD_MUTEX_INITIALIZER, so the
> best we can do is portably expose once-only runtime initialization.
>
> * src/util/threads.h (virOnceControlPtr): New opaque type.
> (virOnceFunc): New callback type.
> (virOnce): New prototype.
> * src/util/threads-pthread.h (virOnceControl): Declare.
> (VIR_ONCE_CONTROL_INITIALIZER): Define.
> * src/util/threads-win32.h (virOnceControl)
> (VIR_ONCE_CONTROL_INITIALIZER): Likewise.
> * src/util/threads-pthread.c (virOnce): Implement in pthreads.
> * src/util/threads-win32.c (virOnce): Implement in WIN32.
> * src/libvirt_private.syms: Export it.
> ---
>
> v2: change WIN32 implementation to use lower-level primitives available
> to mingw and older windows, rather than higher level but newer INIT_ONCE.
>
> Meanwhile, I noticed that gnulib has an LGPLv2+ 'lock' module that
> provides a lot of multi-threading primitives for both pthreads, pth,
> and mingw; maybe we should think about rewriting threads.c in terms
> of gnulib and only have one implementation, rather than maintaining
> pthread and mingw in parallel?

> +int virOnce(virOnceControlPtr once, virOnceFunc func)
> +{
> + Â Âif (!once->complete) {
> + Â Â Â Âif (InterlockedIncrement(&once->init) == 1) {
> + Â Â Â Â Â Â/* We're the first thread. */
> + Â Â Â Â Â Âfunc();
> + Â Â Â Â Â Âonce->complete = 1;
> + Â Â Â Â} else {
> + Â Â Â Â Â Â/* We're a later thread. ÂDecrement the init counter back
> + Â Â Â Â Â Â * to avoid overflow, then yield until the first thread
> + Â Â Â Â Â Â * marks that the function is complete. ÂIt is rare that
> + Â Â Â Â Â Â * multiple threads will be waiting here, and since each
> + Â Â Â Â Â Â * thread is yielding except the first, we should get out
> + Â Â Â Â Â Â * soon enough. Â*/
> + Â Â Â Â Â ÂInterlockedDecrement(&once->init);
> + Â Â Â Â Â Âwhile (!once->complete)
> + Â Â Â Â Â Â Â ÂSleep(0);
> + Â Â Â Â}
> + Â Â}
> + Â Âreturn 0;
> +}

Compared to the gnulib lock module version, this one is less complex
and I don't get why gnulib uses 3 states for the init and complete
variables and an additional lock object. The only reason could be to
minimize the time busy waiting in the while loop.

> +
> +struct virOnceControl {
> + Â Âlong init; /* 0 at startup, > 0 if init has started */
> + Â Âvolatile long complete; /* 0 until first thread completes callback */
> +};

MSDN docs about InterlockedIncrement suggest that init should be volatile too.

ACK, with init marked volatile.

Matthias

--
libvir-list mailing list
libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list



[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]