180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/* 280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2012 Google Inc. 380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * 480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be 580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file. 680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkTypes.h" 980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkThreadUtils.h" 1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkThreadUtils_win.h" 1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkThread_WinData::SkThread_WinData(SkThread::entryPointProc entryPoint, void* data) 1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru : fHandle(NULL) 1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru , fParam(data) 1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru , fThreadId(0) 1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru , fEntryPoint(entryPoint) 1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru , fStarted(false) 1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{ 2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fCancelEvent = CreateEvent( 2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru NULL, // default security attributes 2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru false, //auto reset 2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru false, //not signaled 2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru NULL); //no name 2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkThread_WinData::~SkThread_WinData() { 2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru CloseHandle(fCancelEvent); 2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic DWORD WINAPI thread_start(LPVOID data) { 3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkThread_WinData* winData = static_cast<SkThread_WinData*>(data); 3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru //See if this thread was canceled before starting. 3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (WaitForSingleObject(winData->fCancelEvent, 0) == WAIT_OBJECT_0) { 3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return 0; 3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru winData->fEntryPoint(winData->fParam); 4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return 0; 4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkThread::SkThread(entryPointProc entryPoint, void* data) { 4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkThread_WinData* winData = new SkThread_WinData(entryPoint, data); 4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fData = winData; 4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (NULL == winData->fCancelEvent) { 4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return; 4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru winData->fHandle = CreateThread( 5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru NULL, // default security attributes 5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 0, // use default stack size 5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru thread_start, // thread function name (proxy) 5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru winData, // argument to thread function (proxy args) 5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru CREATE_SUSPENDED, // create suspended so affinity can be set 5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru &winData->fThreadId); // returns the thread identifier 5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkThread::~SkThread() { 6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (fData != NULL) { 6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkThread_WinData* winData = static_cast<SkThread_WinData*>(fData); 6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // If created thread but start was never called, kill the thread. 6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (winData->fHandle != NULL && !winData->fStarted) { 6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (SetEvent(winData->fCancelEvent) != 0) { 6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (this->start()) { 6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->join(); 6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } else { 7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru //kill with prejudice 7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru TerminateThread(winData->fHandle, -1); 7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru delete winData; 7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkThread::start() { 7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkThread_WinData* winData = static_cast<SkThread_WinData*>(fData); 8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (NULL == winData->fHandle) { 8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return false; 8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (winData->fStarted) { 8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return false; 8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru winData->fStarted = -1 != ResumeThread(winData->fHandle); 8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return winData->fStarted; 8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkThread::join() { 9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkThread_WinData* winData = static_cast<SkThread_WinData*>(fData); 9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (NULL == winData->fHandle || !winData->fStarted) { 9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return; 9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru WaitForSingleObject(winData->fHandle, INFINITE); 9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic unsigned int num_bits_set(DWORD_PTR mask) { 10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned int count; 10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru for (count = 0; mask; ++count) { 10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru mask &= mask - 1; 10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return count; 10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic unsigned int nth_set_bit(unsigned int n, DWORD_PTR mask) { 10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru n %= num_bits_set(mask); 11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru for (unsigned int setBitsSeen = 0, currentBit = 0; true; ++currentBit) { 11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (mask & (1 << currentBit)) { 11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru ++setBitsSeen; 11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (setBitsSeen > n) { 11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return currentBit; 11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkThread::setProcessorAffinity(unsigned int processor) { 12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkThread_WinData* winData = static_cast<SkThread_WinData*>(fData); 12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (NULL == winData->fHandle) { 12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return false; 12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru DWORD_PTR processAffinityMask; 12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru DWORD_PTR systemAffinityMask; 12880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (0 == GetProcessAffinityMask(GetCurrentProcess(), 12980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru &processAffinityMask, 13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru &systemAffinityMask)) { 13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return false; 13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru DWORD_PTR threadAffinityMask = 1 << nth_set_bit(processor, processAffinityMask); 13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return 0 != SetThreadAffinityMask(winData->fHandle, threadAffinityMask); 13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 137