SkThreadUtils_win.cpp revision 96fcdcc219d2a0d3579719b84b28bede76efba64
1/* 2 * Copyright 2012 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "SkTypes.h" 9 10#include "SkThreadUtils.h" 11#include "SkThreadUtils_win.h" 12 13SkThread_WinData::SkThread_WinData(SkThread::entryPointProc entryPoint, void* data) 14 : fHandle(nullptr) 15 , fParam(data) 16 , fThreadId(0) 17 , fEntryPoint(entryPoint) 18 , fStarted(false) 19{ 20 fCancelEvent = CreateEvent( 21 nullptr, // default security attributes 22 false, //auto reset 23 false, //not signaled 24 nullptr); //no name 25} 26 27SkThread_WinData::~SkThread_WinData() { 28 CloseHandle(fCancelEvent); 29} 30 31static DWORD WINAPI thread_start(LPVOID data) { 32 SkThread_WinData* winData = static_cast<SkThread_WinData*>(data); 33 34 //See if this thread was canceled before starting. 35 if (WaitForSingleObject(winData->fCancelEvent, 0) == WAIT_OBJECT_0) { 36 return 0; 37 } 38 39 winData->fEntryPoint(winData->fParam); 40 return 0; 41} 42 43SkThread::SkThread(entryPointProc entryPoint, void* data) { 44 SkThread_WinData* winData = new SkThread_WinData(entryPoint, data); 45 fData = winData; 46 47 if (nullptr == winData->fCancelEvent) { 48 return; 49 } 50 51 winData->fHandle = CreateThread( 52 nullptr, // default security attributes 53 0, // use default stack size 54 thread_start, // thread function name (proxy) 55 winData, // argument to thread function (proxy args) 56 CREATE_SUSPENDED, // create suspended so affinity can be set 57 &winData->fThreadId); // returns the thread identifier 58} 59 60SkThread::~SkThread() { 61 if (fData != nullptr) { 62 SkThread_WinData* winData = static_cast<SkThread_WinData*>(fData); 63 // If created thread but start was never called, kill the thread. 64 if (winData->fHandle != nullptr && !winData->fStarted) { 65 if (SetEvent(winData->fCancelEvent) != 0) { 66 if (this->start()) { 67 this->join(); 68 } 69 } else { 70 //kill with prejudice 71 TerminateThread(winData->fHandle, -1); 72 } 73 } 74 delete winData; 75 } 76} 77 78bool SkThread::start() { 79 SkThread_WinData* winData = static_cast<SkThread_WinData*>(fData); 80 if (nullptr == winData->fHandle) { 81 return false; 82 } 83 84 if (winData->fStarted) { 85 return false; 86 } 87 winData->fStarted = -1 != ResumeThread(winData->fHandle); 88 return winData->fStarted; 89} 90 91void SkThread::join() { 92 SkThread_WinData* winData = static_cast<SkThread_WinData*>(fData); 93 if (nullptr == winData->fHandle || !winData->fStarted) { 94 return; 95 } 96 97 WaitForSingleObject(winData->fHandle, INFINITE); 98} 99 100static unsigned int num_bits_set(DWORD_PTR mask) { 101 unsigned int count; 102 for (count = 0; mask; ++count) { 103 mask &= mask - 1; 104 } 105 return count; 106} 107 108static unsigned int nth_set_bit(unsigned int n, DWORD_PTR mask) { 109 n %= num_bits_set(mask); 110 for (unsigned int setBitsSeen = 0, currentBit = 0; true; ++currentBit) { 111 if (mask & (static_cast<DWORD_PTR>(1) << currentBit)) { 112 ++setBitsSeen; 113 if (setBitsSeen > n) { 114 return currentBit; 115 } 116 } 117 } 118} 119 120bool SkThread::setProcessorAffinity(unsigned int processor) { 121 SkThread_WinData* winData = static_cast<SkThread_WinData*>(fData); 122 if (nullptr == winData->fHandle) { 123 return false; 124 } 125 126 DWORD_PTR processAffinityMask; 127 DWORD_PTR systemAffinityMask; 128 if (0 == GetProcessAffinityMask(GetCurrentProcess(), 129 &processAffinityMask, 130 &systemAffinityMask)) { 131 return false; 132 } 133 134 DWORD_PTR threadAffinityMask = 1 << nth_set_bit(processor, processAffinityMask); 135 return 0 != SetThreadAffinityMask(winData->fHandle, threadAffinityMask); 136} 137