6650ee6cf2aa68f35edf3cd654738ddd4af5542c
[vuplus_xbmc] / xbmc / threads / platform / win / ThreadImpl.cpp
1 /*
2  *      Copyright (C) 2005-2011 Team XBMC
3  *      http://www.xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, write to
17  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18  *  http://www.gnu.org/copyleft/gpl.html
19  *
20  */
21
22 #include <windows.h>
23
24
25 void CThread::Create(bool bAutoDelete, unsigned stacksize)
26 {
27   if (m_ThreadId != 0)
28   {
29     CLog::Log(LOGERROR, "%s - fatal error creating thread- old thread id not null", __FUNCTION__);
30     exit(1);
31   }
32   m_iLastTime = XbmcThreads::SystemClockMillis() * 10000;
33   m_iLastUsage = 0;
34   m_fLastUsage = 0.0f;
35   m_bAutoDelete = bAutoDelete;
36   m_bStop = false;
37   m_StopEvent.Reset();
38   m_TermEvent.Reset();
39   m_StartEvent.Reset();
40
41   m_ThreadOpaque.handle = CreateThread(NULL,stacksize, (LPTHREAD_START_ROUTINE)&staticThread, this, 0, &m_ThreadId);
42   if (m_ThreadOpaque.handle == NULL)
43   {
44     CLog::Log(LOGERROR, "%s - fatal error creating thread", __FUNCTION__);
45   }
46 }
47
48 void CThread::TermHandler()
49 {
50   CloseHandle(m_ThreadOpaque.handle);
51   m_ThreadOpaque.handle = NULL;
52 }
53
54 void CThread::SetThreadInfo()
55 {
56   const unsigned int MS_VC_EXCEPTION = 0x406d1388;
57   struct THREADNAME_INFO
58   {
59     DWORD dwType; // must be 0x1000
60     LPCSTR szName; // pointer to name (in same addr space)
61     DWORD dwThreadID; // thread ID (-1 caller thread)
62     DWORD dwFlags; // reserved for future use, most be zero
63   } info;
64
65   info.dwType = 0x1000;
66   info.szName = m_ThreadName.c_str();
67   info.dwThreadID = m_ThreadId;
68   info.dwFlags = 0;
69
70   try
71   {
72     RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR *)&info);
73   }
74   catch(...)
75   {
76   }
77 }
78
79 ThreadIdentifier CThread::GetCurrentThreadId()
80 {
81   return ::GetCurrentThreadId();
82 }
83
84 bool CThread::IsCurrentThread(const ThreadIdentifier tid)
85 {
86   return (::GetCurrentThreadId() == tid);
87 }
88
89 int CThread::GetMinPriority(void)
90 {
91   return(THREAD_PRIORITY_IDLE);
92 }
93
94 int CThread::GetMaxPriority(void)
95 {
96   return(THREAD_PRIORITY_HIGHEST);
97 }
98
99 int CThread::GetNormalPriority(void)
100 {
101   return(THREAD_PRIORITY_NORMAL);
102 }
103
104 int CThread::GetSchedRRPriority(void)
105 {
106   return GetNormalPriority();
107 }
108
109 bool CThread::SetPriority(const int iPriority)
110 {
111   bool bReturn = false;
112
113   CSingleLock lock(m_CriticalSection);
114   if (m_ThreadOpaque.handle)
115   {
116     bReturn = SetThreadPriority(m_ThreadOpaque.handle, iPriority) == TRUE;
117   }
118
119   return bReturn;
120 }
121
122 int CThread::GetPriority()
123 {
124   CSingleLock lock(m_CriticalSection);
125
126   int iReturn = THREAD_PRIORITY_NORMAL;
127   if (m_ThreadOpaque.handle)
128   {
129     iReturn = GetThreadPriority(m_ThreadOpaque.handle);
130   }
131   return iReturn;
132 }
133
134 bool CThread::WaitForThreadExit(unsigned int milliseconds)
135 {
136   bool bReturn = true;
137
138   CSingleLock lock(m_CriticalSection);
139   if (m_ThreadId && m_ThreadOpaque.handle != NULL)
140   {
141     // boost priority of thread we are waiting on to same as caller
142     int callee = GetThreadPriority(m_ThreadOpaque.handle);
143     int caller = GetThreadPriority(GetCurrentThread());
144     if(caller > callee)
145       SetThreadPriority(m_ThreadOpaque.handle, caller);
146
147     lock.Leave();
148     bReturn = m_TermEvent.WaitMSec(milliseconds);
149     lock.Enter();
150
151     // restore thread priority if thread hasn't exited
152     if(caller > callee && m_ThreadOpaque.handle)
153       SetThreadPriority(m_ThreadOpaque.handle, callee);
154   }
155   return bReturn;
156 }
157
158 int64_t CThread::GetAbsoluteUsage()
159 {
160   CSingleLock lock(m_CriticalSection);
161
162   if (!m_ThreadOpaque.handle)
163     return 0;
164
165   uint64_t time = 0;
166   FILETIME CreationTime, ExitTime, UserTime, KernelTime;
167   if( GetThreadTimes(m_ThreadOpaque.handle, &CreationTime, &ExitTime, &KernelTime, &UserTime ) )
168   {
169     time = (((uint64_t)UserTime.dwHighDateTime) << 32) + ((uint64_t)UserTime.dwLowDateTime);
170     time += (((uint64_t)KernelTime.dwHighDateTime) << 32) + ((uint64_t)KernelTime.dwLowDateTime);
171   }
172   return time;
173 }
174
175 float CThread::GetRelativeUsage()
176 {
177   unsigned int iTime = XbmcThreads::SystemClockMillis();
178   iTime *= 10000; // convert into 100ns tics
179
180   // only update every 1 second
181   if( iTime < m_iLastTime + 1000*10000 ) return m_fLastUsage;
182
183   int64_t iUsage = GetAbsoluteUsage();
184
185   if (m_iLastUsage > 0 && m_iLastTime > 0)
186     m_fLastUsage = (float)( iUsage - m_iLastUsage ) / (float)( iTime - m_iLastTime );
187
188   m_iLastUsage = iUsage;
189   m_iLastTime = iTime;
190
191   return m_fLastUsage;
192 }
193
194 int64_t CThread::GetCurrentThreadUsage()
195 {
196   HANDLE h = GetCurrentThread();
197   
198   uint64_t time = 0;
199   FILETIME CreationTime, ExitTime, UserTime, KernelTime;
200   if( GetThreadTimes(h, &CreationTime, &ExitTime, &KernelTime, &UserTime ) )
201   {
202     time = (((uint64_t)UserTime.dwHighDateTime) << 32) + ((uint64_t)UserTime.dwLowDateTime);
203     time += (((uint64_t)KernelTime.dwHighDateTime) << 32) + ((uint64_t)KernelTime.dwLowDateTime);
204   }
205   return time;
206 }
207