1554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com/* 2554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com * Copyright 2012 Google Inc. 3554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com * 4554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com * Use of this source code is governed by a BSD-style license that can be 5554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com * found in the LICENSE file. 6554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com */ 7554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com 8554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com#include "SkTypes.h" 9554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com 10554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com#include "SkThreadUtils.h" 11554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com#include "SkThreadUtils_win.h" 12554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com 13554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.comSkThread_WinData::SkThread_WinData(SkThread::entryPointProc entryPoint, void* data) 14554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com : fHandle(NULL) 15554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com , fParam(data) 16554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com , fThreadId(0) 17554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com , fEntryPoint(entryPoint) 18554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com , fStarted(false) 19554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com{ 20554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com fCancelEvent = CreateEvent( 21554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com NULL, // default security attributes 22554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com false, //auto reset 23554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com false, //not signaled 24554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com NULL); //no name 25554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com} 26554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com 27554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.comSkThread_WinData::~SkThread_WinData() { 28554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com CloseHandle(fCancelEvent); 29554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com} 30554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com 31554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.comstatic DWORD WINAPI thread_start(LPVOID data) { 32554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com SkThread_WinData* winData = static_cast<SkThread_WinData*>(data); 33554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com 34554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com //See if this thread was canceled before starting. 35554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com if (WaitForSingleObject(winData->fCancelEvent, 0) == WAIT_OBJECT_0) { 36554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com return 0; 37554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com } 38554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com 39554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com winData->fEntryPoint(winData->fParam); 40554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com return 0; 41554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com} 42554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com 43554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.comSkThread::SkThread(entryPointProc entryPoint, void* data) { 44554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com SkThread_WinData* winData = new SkThread_WinData(entryPoint, data); 45554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com fData = winData; 46554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com 47554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com if (NULL == winData->fCancelEvent) { 48554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com return; 49554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com } 50554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com 51554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com winData->fHandle = CreateThread( 52554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com NULL, // default security attributes 53554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com 0, // use default stack size 54554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com thread_start, // thread function name (proxy) 55554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com winData, // argument to thread function (proxy args) 56554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com CREATE_SUSPENDED, // create suspended so affinity can be set 57554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com &winData->fThreadId); // returns the thread identifier 58554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com} 59554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com 60554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.comSkThread::~SkThread() { 61554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com if (fData != NULL) { 62554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com SkThread_WinData* winData = static_cast<SkThread_WinData*>(fData); 63554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com // If created thread but start was never called, kill the thread. 64554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com if (winData->fHandle != NULL && !winData->fStarted) { 65554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com if (SetEvent(winData->fCancelEvent) != 0) { 66554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com if (this->start()) { 67554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com this->join(); 68554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com } 69554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com } else { 70554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com //kill with prejudice 71554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com TerminateThread(winData->fHandle, -1); 72554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com } 73554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com } 74554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com delete winData; 75554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com } 76554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com} 77554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com 78554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.combool SkThread::start() { 79554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com SkThread_WinData* winData = static_cast<SkThread_WinData*>(fData); 80554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com if (NULL == winData->fHandle) { 81554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com return false; 82554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com } 83554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com 84554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com if (winData->fStarted) { 85554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com return false; 86554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com } 87554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com winData->fStarted = -1 != ResumeThread(winData->fHandle); 88554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com return winData->fStarted; 89554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com} 90554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com 91554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.comvoid SkThread::join() { 92554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com SkThread_WinData* winData = static_cast<SkThread_WinData*>(fData); 93554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com if (NULL == winData->fHandle || !winData->fStarted) { 94554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com return; 95554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com } 96554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com 97554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com WaitForSingleObject(winData->fHandle, INFINITE); 98554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com} 99554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com 100554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.comstatic unsigned int num_bits_set(DWORD_PTR mask) { 101554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com unsigned int count; 102554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com for (count = 0; mask; ++count) { 103554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com mask &= mask - 1; 104554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com } 105554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com return count; 106554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com} 107554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com 108554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.comstatic unsigned int nth_set_bit(unsigned int n, DWORD_PTR mask) { 109554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com n %= num_bits_set(mask); 110554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com for (unsigned int setBitsSeen = 0, currentBit = 0; true; ++currentBit) { 1114b18f5767ab1df7fedf0ff2e3a9eac7f7c500c36bungeman@google.com if (mask & (static_cast<DWORD_PTR>(1) << currentBit)) { 112554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com ++setBitsSeen; 113554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com if (setBitsSeen > n) { 114554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com return currentBit; 115554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com } 116554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com } 117554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com } 118554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com} 119554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com 120554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.combool SkThread::setProcessorAffinity(unsigned int processor) { 121554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com SkThread_WinData* winData = static_cast<SkThread_WinData*>(fData); 122554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com if (NULL == winData->fHandle) { 123554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com return false; 124554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com } 125554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com 126554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com DWORD_PTR processAffinityMask; 127554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com DWORD_PTR systemAffinityMask; 128554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com if (0 == GetProcessAffinityMask(GetCurrentProcess(), 129554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com &processAffinityMask, 130554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com &systemAffinityMask)) { 131554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com return false; 132554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com } 133554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com 134554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com DWORD_PTR threadAffinityMask = 1 << nth_set_bit(processor, processAffinityMask); 135554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com return 0 != SetThreadAffinityMask(winData->fHandle, threadAffinityMask); 136554875210043b34178f7ed6ac5bd682b1fad367bbungeman@google.com} 137