[vlc-devel] [PATCH 1/6] os2: implement vlc_once()

Kamil Rytarowski n54 at gmx.com
Mon Apr 2 13:30:56 CEST 2018


On 02.04.2018 12:50, Rémi Denis-Courmont wrote:
> Le lundi 2 avril 2018, 12:28:59 EEST Kamil Rytarowski a écrit :
>> On 02.04.2018 08:58, Rémi Denis-Courmont wrote:
>>> Le lundi 2 avril 2018, 03:20:25 EEST Kamil Rytarowski a écrit :
>>>> Just follow an existing approach like in NetBSD:
>>>>      53 int
>>>>      54 pthread_once(pthread_once_t *once_control, void (*routine)(void))
>>>>      55 {
>>>>      56 	if (__predict_false(__uselibcstub))
>>>>      57 		return __libc_thr_once_stub(once_control, routine);
>>>>      58
>>>>      59 	if (once_control->pto_done == 0) {
>>>>      60 		pthread_mutex_lock(&once_control->pto_mutex);
>>>>      61 		pthread_cleanup_push(&once_cleanup, &once_control-
>> pto_mutex);
>>>>      62 		if (once_control->pto_done == 0) {
>>>>      63 			routine();
>>>>      64 			once_control->pto_done = 1;
>>>>      65 		}
>>>>      66 		pthread_cleanup_pop(1);
>>>>      67 	}
>>>>      68
>>>>      69 	return 0;
>>>>      70 }
>>>>
>>>> https://nxr.netbsd.org/xref/src/lib/libpthread/pthread_once.c#54
>>>
>>> This violates the memory model just like the first proposal.
>>
>> Please elaborate.
> 
> pto_done is accessed outside the memory model.
> 

Do you mean that someone can change pto_done from a different place than
the pthread_once() function?

The type is already opaque for outer users. Nobody can access it easily
and certainly nobody should access it. The only exception I've
encountered were LLVM sanitizers (Thread-Sanitizer):

TSAN_INTERCEPTOR(int, pthread_once, void *o, void (*f)()) {
  SCOPED_INTERCEPTOR_RAW(pthread_once, o, f);
  if (o == 0 || f == 0)
    return errno_EINVAL;
  atomic_uint32_t *a;

  if (SANITIZER_MAC)
    a = static_cast<atomic_uint32_t*>((void *)((char *)o + sizeof(long_t)));
  else if (SANITIZER_NETBSD)
    a = static_cast<atomic_uint32_t*>
          ((void *)((char *)o + __sanitizer::pthread_mutex_t_sz));
  else
    a = static_cast<atomic_uint32_t*>(o);

  u32 v = atomic_load(a, memory_order_acquire);
  if (v == 0 && atomic_compare_exchange_strong(a, &v, 1,
                                               memory_order_relaxed)) {
    (*f)();

    if (!thr->in_ignored_lib)
      Release(thr, pc, (uptr)o);
    atomic_store(a, 2, memory_order_release);
  } else {
    while (v != 2) {
      internal_sched_yield();
      v = atomic_load(a, memory_order_acquire);
    }
    if (!thr->in_ignored_lib)
      Acquire(thr, pc, (uptr)o);
  }
  return 0;
}

 --
https://github.com/llvm-mirror/compiler-rt/blob/master/lib/tsan/rtl/tsan_interceptors.cc#L1389

There is no known user without pto_done-like variable (at least in the
group of OSes supporting TSan: Darwin, NetBSD and Linux).

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 850 bytes
Desc: OpenPGP digital signature
URL: <http://mailman.videolan.org/pipermail/vlc-devel/attachments/20180402/82527828/attachment.sig>


More information about the vlc-devel mailing list