chromium/base/allocator/partition_allocator/src/partition_alloc/spinning_mutex.cc

// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "partition_alloc/spinning_mutex.h"

#include "partition_alloc/build_config.h"
#include "partition_alloc/partition_alloc_base/compiler_specific.h"
#include "partition_alloc/partition_alloc_check.h"

#if PA_BUILDFLAG(IS_WIN)
#include <windows.h>
#endif

#if PA_BUILDFLAG(IS_POSIX)
#include <pthread.h>
#endif

#if PA_CONFIG(HAS_LINUX_KERNEL)
#include <linux/futex.h>
#include <sys/syscall.h>
#include <unistd.h>

#include <cerrno>
#endif  // PA_CONFIG(HAS_LINUX_KERNEL)

#if !PA_CONFIG(HAS_LINUX_KERNEL) && !PA_BUILDFLAG(IS_WIN) && \
    !PA_BUILDFLAG(IS_APPLE) && !PA_BUILDFLAG(IS_POSIX) &&    \
    !PA_BUILDFLAG(IS_FUCHSIA)
#include "partition_alloc/partition_alloc_base/threading/platform_thread.h"

#if PA_BUILDFLAG(IS_POSIX)
#include <sched.h>
#define PA_YIELD_THREAD
#else  // Other OS
#warning "Thread yield not supported on this OS."
#define PA_YIELD_THREAD
#endif

#endif

namespace partition_alloc::internal {

void SpinningMutex::Reinit() {}

void SpinningMutex::AcquireSpinThenBlock() {}

#if PA_CONFIG(HAS_LINUX_KERNEL)

void SpinningMutex::FutexWait() {}

void SpinningMutex::FutexWake() {}

void SpinningMutex::LockSlow() {}

#elif PA_BUILDFLAG(IS_WIN)

void SpinningMutex::LockSlow() {
  ::AcquireSRWLockExclusive(reinterpret_cast<PSRWLOCK>(&lock_));
}

#elif PA_BUILDFLAG(IS_APPLE)

void SpinningMutex::LockSlow() {
  return os_unfair_lock_lock(&unfair_lock_);
}

#elif PA_BUILDFLAG(IS_POSIX)

void SpinningMutex::LockSlow() {
  int retval = pthread_mutex_lock(&lock_);
  PA_DCHECK(retval == 0);
}

#elif PA_BUILDFLAG(IS_FUCHSIA)

void SpinningMutex::LockSlow() {
  sync_mutex_lock(&lock_);
}

#else

void SpinningMutex::LockSlow() {
  int yield_thread_count = 0;
  do {
    if (yield_thread_count < 10) {
      PA_YIELD_THREAD;
      yield_thread_count++;
    } else {
      // At this point, it's likely that the lock is held by a lower priority
      // thread that is unavailable to finish its work because of higher
      // priority threads spinning here. Sleeping should ensure that they make
      // progress.
      base::PlatformThread::Sleep(base::Milliseconds(1));
    }
  } while (!Try());
}

#endif

}  // namespace partition_alloc::internal