// Copyright 2012 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This module contains the platform-specific code. This make the rest of the
// code less dependent on operating system, compilers and runtime libraries.
// This module does specifically not deal with differences between different
// processor architecture.
// The platform classes have the same definition for all platforms. The
// implementation for a particular platform is put in platform_<os>.cc.
// The build system then uses the implementation for the target platform.
//
// This design has been chosen because it is simple and fast. Alternatively,
// the platform dependent classes could have been implemented using abstract
// superclasses with virtual methods and having specializations for each
// platform. This design was rejected because it was more complicated and
// slower. It would require factory methods for selecting the right
// implementation and the overhead of virtual methods for performance
// sensitive like mutex locking/unlocking.

#ifndef V8_BASE_PLATFORM_PLATFORM_H_
#define V8_BASE_PLATFORM_PLATFORM_H_

#include <cstdarg>
#include <string>
#include <vector>

#include "src/base/base-export.h"
#include "src/base/build_config.h"
#include "src/base/compiler-specific.h"
#include "src/base/platform/mutex.h"
#include "src/base/platform/semaphore.h"

#if V8_OS_QNX
#include "src/base/qnx-math.h"
#endif

namespace v8 {

namespace base {

// ----------------------------------------------------------------------------
// Fast TLS support

#ifndef V8_NO_FAST_TLS

#if V8_CC_MSVC && V8_HOST_ARCH_IA32

#define V8_FAST_TLS_SUPPORTED 1

INLINE(intptr_t InternalGetExistingThreadLocal(intptr_t index));

inline intptr_t InternalGetExistingThreadLocal(intptr_t index) {
  const intptr_t kTibInlineTlsOffset = 0xE10;
  const intptr_t kTibExtraTlsOffset = 0xF94;
  const intptr_t kMaxInlineSlots = 64;
  const intptr_t kMaxSlots = kMaxInlineSlots + 1024;
  const intptr_t kPointerSize = sizeof(void*);
  DCHECK(0 <= index && index < kMaxSlots);
  USE(kMaxSlots);
  if (index < kMaxInlineSlots) {
    return static_cast<intptr_t>(__readfsdword(kTibInlineTlsOffset +
                                               kPointerSize * index));
  }
  intptr_t extra = static_cast<intptr_t>(__readfsdword(kTibExtraTlsOffset));
  DCHECK_NE(extra, 0);
  return *reinterpret_cast<intptr_t*>(extra +
                                      kPointerSize * (index - kMaxInlineSlots));
}

#elif defined(__APPLE__) && (V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64)

#define V8_FAST_TLS_SUPPORTED 1

extern V8_BASE_EXPORT intptr_t kMacTlsBaseOffset;

INLINE(intptr_t InternalGetExistingThreadLocal(intptr_t index));

inline intptr_t InternalGetExistingThreadLocal(intptr_t index) {
  intptr_t result;
#if V8_HOST_ARCH_IA32
  asm("movl %%gs:(%1,%2,4), %0;"
      :"=r"(result)  // Output must be a writable register.
      :"r"(kMacTlsBaseOffset), "r"(index));
#else
  asm("movq %%gs:(%1,%2,8), %0;"
      :"=r"(result)
      :"r"(kMacTlsBaseOffset), "r"(index));
#endif
  return result;
}

#endif

#endif  // V8_NO_FAST_TLS

class PageAllocator;
class TimezoneCache;

// ----------------------------------------------------------------------------
// OS
//
// This class has static methods for the different platform specific
// functions. Add methods here to cope with differences between the
// supported platforms.

class V8_BASE_EXPORT OS {
 public:
  // Initialize the OS class.
  // - hard_abort: If true, OS::Abort() will crash instead of aborting.
  // - gc_fake_mmap: Name of the file for fake gc mmap used in ll_prof.
  static void Initialize(bool hard_abort, const char* const gc_fake_mmap);

  // Returns the accumulated user time for thread. This routine
  // can be used for profiling. The implementation should
  // strive for high-precision timer resolution, preferable
  // micro-second resolution.
  static int GetUserTime(uint32_t* secs,  uint32_t* usecs);

  // Returns current time as the number of milliseconds since
  // 00:00:00 UTC, January 1, 1970.
  static double TimeCurrentMillis();

  static TimezoneCache* CreateTimezoneCache();

  // Returns last OS error.
  static int GetLastError();

  static FILE* FOpen(const char* path, const char* mode);
  static bool Remove(const char* path);

  static char DirectorySeparator();
  static bool isDirectorySeparator(const char ch);

  // Opens a temporary file, the file is auto removed on close.
  static FILE* OpenTemporaryFile();

  // Log file open mode is platform-dependent due to line ends issues.
  static const char* const LogFileOpenMode;

  // Print output to console. This is mostly used for debugging output.
  // On platforms that has standard terminal output, the output
  // should go to stdout.
  static PRINTF_FORMAT(1, 2) void Print(const char* format, ...);
  static PRINTF_FORMAT(1, 0) void VPrint(const char* format, va_list args);

  // Print output to a file. This is mostly used for debugging output.
  static PRINTF_FORMAT(2, 3) void FPrint(FILE* out, const char* format, ...);
  static PRINTF_FORMAT(2, 0) void VFPrint(FILE* out, const char* format,
                                          va_list args);

  // Print error output to console. This is mostly used for error message
  // output. On platforms that has standard terminal output, the output
  // should go to stderr.
  static PRINTF_FORMAT(1, 2) void PrintError(const char* format, ...);
  static PRINTF_FORMAT(1, 0) void VPrintError(const char* format, va_list args);

  // Memory permissions. These should be kept in sync with the ones in
  // v8::PageAllocator.
  enum class MemoryPermission {
    kNoAccess,
    kReadWrite,
    // TODO(hpayer): Remove this flag. Memory should never be rwx.
    kReadWriteExecute,
    kReadExecute
  };

  static bool HasLazyCommits();

  // Sleep for a specified time interval.
  static void Sleep(TimeDelta interval);

  // Abort the current process.
  [[noreturn]] static void Abort();

  // Debug break.
  static void DebugBreak();

  // Walk the stack.
  static const int kStackWalkError = -1;
  static const int kStackWalkMaxNameLen = 256;
  static const int kStackWalkMaxTextLen = 256;
  struct StackFrame {
    void* address;
    char text[kStackWalkMaxTextLen];
  };

  class V8_BASE_EXPORT MemoryMappedFile {
   public:
    virtual ~MemoryMappedFile() {}
    virtual void* memory() const = 0;
    virtual size_t size() const = 0;

    static MemoryMappedFile* open(const char* name);
    static MemoryMappedFile* create(const char* name, size_t size,
                                    void* initial);
  };

  // Safe formatting print. Ensures that str is always null-terminated.
  // Returns the number of chars written, or -1 if output was truncated.
  static PRINTF_FORMAT(3, 4) int SNPrintF(char* str, int length,
                                          const char* format, ...);
  static PRINTF_FORMAT(3, 0) int VSNPrintF(char* str, int length,
                                           const char* format, va_list args);

  static char* StrChr(char* str, int c);
  static void StrNCpy(char* dest, int length, const char* src, size_t n);

  // Support for the profiler.  Can do nothing, in which case ticks
  // occurring in shared libraries will not be properly accounted for.
  struct SharedLibraryAddress {
    SharedLibraryAddress(const std::string& library_path, uintptr_t start,
                         uintptr_t end)
        : library_path(library_path), start(start), end(end), aslr_slide(0) {}
    SharedLibraryAddress(const std::string& library_path, uintptr_t start,
                         uintptr_t end, intptr_t aslr_slide)
        : library_path(library_path),
          start(start),
          end(end),
          aslr_slide(aslr_slide) {}

    std::string library_path;
    uintptr_t start;
    uintptr_t end;
    intptr_t aslr_slide;
  };

  static std::vector<SharedLibraryAddress> GetSharedLibraryAddresses();

  // Support for the profiler.  Notifies the external profiling
  // process that a code moving garbage collection starts.  Can do
  // nothing, in which case the code objects must not move (e.g., by
  // using --never-compact) if accurate profiling is desired.
  static void SignalCodeMovingGC();

  // Support runtime detection of whether the hard float option of the
  // EABI is used.
  static bool ArmUsingHardFloat();

  // Returns the activation frame alignment constraint or zero if
  // the platform doesn't care. Guaranteed to be a power of two.
  static int ActivationFrameAlignment();

  static int GetCurrentProcessId();

  static int GetCurrentThreadId();

 private:
  // These classes use the private memory management API below.
  friend class MemoryMappedFile;
  friend class PosixMemoryMappedFile;
  friend class v8::base::PageAllocator;

  static size_t AllocatePageSize();

  static size_t CommitPageSize();

  static void SetRandomMmapSeed(int64_t seed);

  static void* GetRandomMmapAddr();

  V8_WARN_UNUSED_RESULT static void* Allocate(void* address, size_t size,
                                              size_t alignment,
                                              MemoryPermission access);

  V8_WARN_UNUSED_RESULT static bool Free(void* address, const size_t size);

  V8_WARN_UNUSED_RESULT static bool Release(void* address, size_t size);

  V8_WARN_UNUSED_RESULT static bool SetPermissions(void* address, size_t size,
                                                   MemoryPermission access);

  static const int msPerSecond = 1000;

#if V8_OS_POSIX
  static const char* GetGCFakeMMapFile();
#endif

  DISALLOW_IMPLICIT_CONSTRUCTORS(OS);
};

// ----------------------------------------------------------------------------
// Thread
//
// Thread objects are used for creating and running threads. When the start()
// method is called the new thread starts running the run() method in the new
// thread. The Thread object should not be deallocated before the thread has
// terminated.

class V8_BASE_EXPORT Thread {
 public:
  // Opaque data type for thread-local storage keys.
#if V8_OS_STARBOARD
  typedef SbThreadLocalKey LocalStorageKey;
#else
  typedef int32_t LocalStorageKey;
#endif

  class Options {
   public:
    Options() : name_("v8:<unknown>"), stack_size_(0) {}
    explicit Options(const char* name, int stack_size = 0)
        : name_(name), stack_size_(stack_size) {}

    const char* name() const { return name_; }
    int stack_size() const { return stack_size_; }

   private:
    const char* name_;
    int stack_size_;
  };

  // Create new thread.
  explicit Thread(const Options& options);
  virtual ~Thread();

  // Start new thread by calling the Run() method on the new thread.
  void Start();

  // Start new thread and wait until Run() method is called on the new thread.
  void StartSynchronously() {
    start_semaphore_ = new Semaphore(0);
    Start();
    start_semaphore_->Wait();
    delete start_semaphore_;
    start_semaphore_ = nullptr;
  }

  // Wait until thread terminates.
  void Join();

  inline const char* name() const {
    return name_;
  }

  // Abstract method for run handler.
  virtual void Run() = 0;

  // Thread-local storage.
  static LocalStorageKey CreateThreadLocalKey();
  static void DeleteThreadLocalKey(LocalStorageKey key);
  static void* GetThreadLocal(LocalStorageKey key);
  static int GetThreadLocalInt(LocalStorageKey key) {
    return static_cast<int>(reinterpret_cast<intptr_t>(GetThreadLocal(key)));
  }
  static void SetThreadLocal(LocalStorageKey key, void* value);
  static void SetThreadLocalInt(LocalStorageKey key, int value) {
    SetThreadLocal(key, reinterpret_cast<void*>(static_cast<intptr_t>(value)));
  }
  static bool HasThreadLocal(LocalStorageKey key) {
    return GetThreadLocal(key) != nullptr;
  }

#ifdef V8_FAST_TLS_SUPPORTED
  static inline void* GetExistingThreadLocal(LocalStorageKey key) {
    void* result = reinterpret_cast<void*>(
        InternalGetExistingThreadLocal(static_cast<intptr_t>(key)));
    DCHECK(result == GetThreadLocal(key));
    return result;
  }
#else
  static inline void* GetExistingThreadLocal(LocalStorageKey key) {
    return GetThreadLocal(key);
  }
#endif

  // The thread name length is limited to 16 based on Linux's implementation of
  // prctl().
  static const int kMaxThreadNameLength = 16;

  class PlatformData;
  PlatformData* data() { return data_; }

  void NotifyStartedAndRun() {
    if (start_semaphore_) start_semaphore_->Signal();
    Run();
  }

 private:
  void set_name(const char* name);

  PlatformData* data_;

  char name_[kMaxThreadNameLength];
  int stack_size_;
  Semaphore* start_semaphore_;

  DISALLOW_COPY_AND_ASSIGN(Thread);
};

}  // namespace base
}  // namespace v8

#endif  // V8_BASE_PLATFORM_PLATFORM_H_
