Home | History | Annotate | Download | only in Windows
      1 //===- Windows/Threading.inc - Win32 Threading Implementation - -*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file provides the Win32 specific implementation of Threading functions.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "llvm/ADT/SmallString.h"
     15 #include "llvm/ADT/Twine.h"
     16 
     17 #include "WindowsSupport.h"
     18 #include <process.h>
     19 
     20 // Windows will at times define MemoryFence.
     21 #ifdef MemoryFence
     22 #undef MemoryFence
     23 #endif
     24 
     25 namespace {
     26   struct ThreadInfo {
     27     void(*func)(void*);
     28     void *param;
     29   };
     30 }
     31 
     32 static unsigned __stdcall ThreadCallback(void *param) {
     33   struct ThreadInfo *info = reinterpret_cast<struct ThreadInfo *>(param);
     34   info->func(info->param);
     35 
     36   return 0;
     37 }
     38 
     39 void llvm::llvm_execute_on_thread(void(*Fn)(void*), void *UserData,
     40   unsigned RequestedStackSize) {
     41   struct ThreadInfo param = { Fn, UserData };
     42 
     43   HANDLE hThread = (HANDLE)::_beginthreadex(NULL,
     44     RequestedStackSize, ThreadCallback,
     45     &param, 0, NULL);
     46 
     47   if (hThread) {
     48     // We actually don't care whether the wait succeeds or fails, in
     49     // the same way we don't care whether the pthread_join call succeeds
     50     // or fails.  There's not much we could do if this were to fail. But
     51     // on success, this call will wait until the thread finishes executing
     52     // before returning.
     53     (void)::WaitForSingleObject(hThread, INFINITE);
     54     ::CloseHandle(hThread);
     55   }
     56 }
     57 
     58 uint64_t llvm::get_threadid() {
     59   return uint64_t(::GetCurrentThreadId());
     60 }
     61 
     62 uint32_t llvm::get_max_thread_name_length() { return 0; }
     63 
     64 #if defined(_MSC_VER)
     65 static void SetThreadName(DWORD Id, LPCSTR Name) {
     66   constexpr DWORD MS_VC_EXCEPTION = 0x406D1388;
     67 
     68 #pragma pack(push, 8)
     69   struct THREADNAME_INFO {
     70     DWORD dwType;     // Must be 0x1000.
     71     LPCSTR szName;    // Pointer to thread name
     72     DWORD dwThreadId; // Thread ID (-1 == current thread)
     73     DWORD dwFlags;    // Reserved.  Do not use.
     74   };
     75 #pragma pack(pop)
     76 
     77   THREADNAME_INFO info;
     78   info.dwType = 0x1000;
     79   info.szName = Name;
     80   info.dwThreadId = Id;
     81   info.dwFlags = 0;
     82 
     83   __try {
     84     ::RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR),
     85       (ULONG_PTR *)&info);
     86   }
     87   __except (EXCEPTION_EXECUTE_HANDLER) {
     88   }
     89 }
     90 #endif
     91 
     92 void llvm::set_thread_name(const Twine &Name) {
     93 #if defined(_MSC_VER)
     94   // Make sure the input is null terminated.
     95   SmallString<64> Storage;
     96   StringRef NameStr = Name.toNullTerminatedStringRef(Storage);
     97   SetThreadName(::GetCurrentThreadId(), NameStr.data());
     98 #endif
     99 }
    100 
    101 void llvm::get_thread_name(SmallVectorImpl<char> &Name) {
    102   // "Name" is not an inherent property of a thread on Windows.  In fact, when
    103   // you "set" the name, you are only firing a one-time message to a debugger
    104   // which it interprets as a program setting its threads' name.  We may be
    105   // able to get fancy by creating a TLS entry when someone calls
    106   // set_thread_name so that subsequent calls to get_thread_name return this
    107   // value.
    108   Name.clear();
    109 }
    110