Moved tape.c to dlls/kernel.
[wine] / dlls / kernel / thread.c
1 /*
2  * Win32 threads
3  *
4  * Copyright 1996 Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22 #include "wine/port.h"
23
24 #include <assert.h>
25 #include <fcntl.h>
26 #include <sys/types.h>
27 #ifdef HAVE_SYS_TIMES_H
28 #include <sys/times.h>
29 #endif
30 #ifdef HAVE_UNISTD_H
31 # include <unistd.h>
32 #endif
33
34 #include "winbase.h"
35 #include "winerror.h"
36 #include "winnls.h"
37 #include "thread.h"
38 #include "wine/server.h"
39 #include "wine/debug.h"
40
41 WINE_DEFAULT_DEBUG_CHANNEL(thread);
42
43
44 /***********************************************************************
45  * SetThreadContext [KERNEL32.@]  Sets context of thread.
46  *
47  * RETURNS
48  *    Success: TRUE
49  *    Failure: FALSE
50  */
51 BOOL WINAPI SetThreadContext( HANDLE handle,           /* [in]  Handle to thread with context */
52                               const CONTEXT *context ) /* [in] Address of context structure */
53 {
54     NTSTATUS status = NtSetContextThread( handle, context );
55     if (status) SetLastError( RtlNtStatusToDosError(status) );
56     return !status;
57 }
58
59
60 /***********************************************************************
61  * GetThreadContext [KERNEL32.@]  Retrieves context of thread.
62  *
63  * RETURNS
64  *    Success: TRUE
65  *    Failure: FALSE
66  */
67 BOOL WINAPI GetThreadContext( HANDLE handle,     /* [in]  Handle to thread with context */
68                               CONTEXT *context ) /* [out] Address of context structure */
69 {
70     NTSTATUS status = NtGetContextThread( handle, context );
71     if (status) SetLastError( RtlNtStatusToDosError(status) );
72     return !status;
73 }
74
75
76 /**********************************************************************
77  * SuspendThread [KERNEL32.@]  Suspends a thread.
78  *
79  * RETURNS
80  *    Success: Previous suspend count
81  *    Failure: 0xFFFFFFFF
82  */
83 DWORD WINAPI SuspendThread( HANDLE hthread ) /* [in] Handle to the thread */
84 {
85     DWORD ret;
86     NTSTATUS status = NtSuspendThread( hthread, &ret );
87
88     if (status)
89     {
90         ret = ~0U;
91         SetLastError( RtlNtStatusToDosError(status) );
92     }
93     return ret;
94 }
95
96
97 /**********************************************************************
98  * ResumeThread [KERNEL32.@]  Resumes a thread.
99  *
100  * Decrements a thread's suspend count.  When count is zero, the
101  * execution of the thread is resumed.
102  *
103  * RETURNS
104  *    Success: Previous suspend count
105  *    Failure: 0xFFFFFFFF
106  *    Already running: 0
107  */
108 DWORD WINAPI ResumeThread( HANDLE hthread ) /* [in] Identifies thread to restart */
109 {
110     DWORD ret;
111     NTSTATUS status = NtResumeThread( hthread, &ret );
112
113     if (status)
114     {
115         ret = ~0U;
116         SetLastError( RtlNtStatusToDosError(status) );
117     }
118     return ret;
119 }
120
121
122 /**********************************************************************
123  * GetThreadPriority [KERNEL32.@]  Returns priority for thread.
124  *
125  * RETURNS
126  *    Success: Thread's priority level.
127  *    Failure: THREAD_PRIORITY_ERROR_RETURN
128  */
129 INT WINAPI GetThreadPriority(
130     HANDLE hthread) /* [in] Handle to thread */
131 {
132     INT ret = THREAD_PRIORITY_ERROR_RETURN;
133     SERVER_START_REQ( get_thread_info )
134     {
135         req->handle = hthread;
136         req->tid_in = 0;
137         if (!wine_server_call_err( req )) ret = reply->priority;
138     }
139     SERVER_END_REQ;
140     return ret;
141 }
142
143
144 /**********************************************************************
145  * SetThreadPriority [KERNEL32.@]  Sets priority for thread.
146  *
147  * RETURNS
148  *    Success: TRUE
149  *    Failure: FALSE
150  */
151 BOOL WINAPI SetThreadPriority(
152     HANDLE hthread, /* [in] Handle to thread */
153     INT priority)   /* [in] Thread priority level */
154 {
155     BOOL ret;
156     SERVER_START_REQ( set_thread_info )
157     {
158         req->handle   = hthread;
159         req->priority = priority;
160         req->mask     = SET_THREAD_INFO_PRIORITY;
161         ret = !wine_server_call_err( req );
162     }
163     SERVER_END_REQ;
164     return ret;
165 }
166
167
168 /**********************************************************************
169  * GetThreadPriorityBoost [KERNEL32.@]  Returns priority boost for thread.
170  *
171  * Always reports that priority boost is disabled.
172  *
173  * RETURNS
174  *    Success: TRUE.
175  *    Failure: FALSE
176  */
177 BOOL WINAPI GetThreadPriorityBoost(
178     HANDLE hthread, /* [in] Handle to thread */
179     PBOOL pstate)   /* [out] pointer to var that receives the boost state */
180 {
181     if (pstate) *pstate = FALSE;
182     return NO_ERROR;
183 }
184
185
186 /**********************************************************************
187  * SetThreadPriorityBoost [KERNEL32.@]  Sets priority boost for thread.
188  *
189  * Priority boost is not implemented. Thsi function always returns
190  * FALSE and sets last error to ERROR_CALL_NOT_IMPLEMENTED
191  *
192  * RETURNS
193  *    Always returns FALSE to indicate a failure
194  */
195 BOOL WINAPI SetThreadPriorityBoost(
196     HANDLE hthread, /* [in] Handle to thread */
197     BOOL disable)   /* [in] TRUE to disable priority boost */
198 {
199     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
200     return FALSE;
201 }
202
203
204 /**********************************************************************
205  *           SetThreadAffinityMask   (KERNEL32.@)
206  */
207 DWORD WINAPI SetThreadAffinityMask( HANDLE hThread, DWORD dwThreadAffinityMask )
208 {
209     DWORD ret;
210     SERVER_START_REQ( set_thread_info )
211     {
212         req->handle   = hThread;
213         req->affinity = dwThreadAffinityMask;
214         req->mask     = SET_THREAD_INFO_AFFINITY;
215         ret = !wine_server_call_err( req );
216         /* FIXME: should return previous value */
217     }
218     SERVER_END_REQ;
219     return ret;
220 }
221
222
223 /**********************************************************************
224  * SetThreadIdealProcessor [KERNEL32.@]  Obtains timing information.
225  *
226  * RETURNS
227  *    Success: Value of last call to SetThreadIdealProcessor
228  *    Failure: -1
229  */
230 DWORD WINAPI SetThreadIdealProcessor(
231     HANDLE hThread,          /* [in] Specifies the thread of interest */
232     DWORD dwIdealProcessor)  /* [in] Specifies the new preferred processor */
233 {
234     FIXME("(%p): stub\n",hThread);
235     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
236     return -1L;
237 }
238
239
240 /***********************************************************************
241  * SetThreadExecutionState (KERNEL32.@)
242  *
243  * Informs the system that activity is taking place for
244  * power management purposes.
245  */
246 EXECUTION_STATE WINAPI SetThreadExecutionState(EXECUTION_STATE flags)
247 {
248     static EXECUTION_STATE current =
249         ES_SYSTEM_REQUIRED|ES_DISPLAY_REQUIRED|ES_USER_PRESENT;
250     EXECUTION_STATE old = current;
251
252     if (!(current & ES_CONTINUOUS) || (flags & ES_CONTINUOUS))
253         current = flags;
254     FIXME("(0x%lx): stub, harmless (power management).\n", flags);
255     return old;
256 }
257
258
259 /* callback for QueueUserAPC */
260 static void CALLBACK call_user_apc( ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3 )
261 {
262     PAPCFUNC func = (PAPCFUNC)arg1;
263     func( arg2 );
264 }
265
266 /***********************************************************************
267  *              QueueUserAPC  (KERNEL32.@)
268  */
269 DWORD WINAPI QueueUserAPC( PAPCFUNC func, HANDLE hthread, ULONG_PTR data )
270 {
271     NTSTATUS status = NtQueueApcThread( hthread, call_user_apc, (ULONG_PTR)func, data, 0 );
272
273     if (status) SetLastError( RtlNtStatusToDosError(status) );
274     return !status;
275 }
276
277
278 /**********************************************************************
279  * GetThreadTimes [KERNEL32.@]  Obtains timing information.
280  *
281  * RETURNS
282  *    Success: TRUE
283  *    Failure: FALSE
284  */
285 BOOL WINAPI GetThreadTimes(
286     HANDLE thread,         /* [in]  Specifies the thread of interest */
287     LPFILETIME creationtime, /* [out] When the thread was created */
288     LPFILETIME exittime,     /* [out] When the thread was destroyed */
289     LPFILETIME kerneltime,   /* [out] Time thread spent in kernel mode */
290     LPFILETIME usertime)     /* [out] Time thread spent in user mode */
291 {
292     BOOL ret = TRUE;
293
294     if (creationtime || exittime)
295     {
296         /* We need to do a server call to get the creation time or exit time */
297         /* This works on any thread */
298
299         SERVER_START_REQ( get_thread_info )
300         {
301             req->handle = thread;
302             req->tid_in = 0;
303             if ((ret = !wine_server_call_err( req )))
304             {
305                 if (creationtime)
306                     RtlSecondsSince1970ToTime( reply->creation_time, (LARGE_INTEGER*)creationtime );
307                 if (exittime)
308                     RtlSecondsSince1970ToTime( reply->exit_time, (LARGE_INTEGER*)exittime );
309             }
310         }
311         SERVER_END_REQ;
312     }
313     if (ret && (kerneltime || usertime))
314     {
315         /* We call times(2) for kernel time or user time */
316         /* We can only (portably) do this for the current thread */
317         if (thread == GetCurrentThread())
318         {
319             ULONGLONG time;
320             struct tms time_buf;
321             long clocks_per_sec = sysconf(_SC_CLK_TCK);
322
323             times(&time_buf);
324             if (kerneltime)
325             {
326                 time = (ULONGLONG)time_buf.tms_stime * 10000000 / clocks_per_sec;
327                 kerneltime->dwHighDateTime = time >> 32;
328                 kerneltime->dwLowDateTime = (DWORD)time;
329             }
330             if (usertime)
331             {
332                 time = (ULONGLONG)time_buf.tms_utime * 10000000 / clocks_per_sec;
333                 usertime->dwHighDateTime = time >> 32;
334                 usertime->dwLowDateTime = (DWORD)time;
335             }
336         }
337         else
338         {
339             if (kerneltime) kerneltime->dwHighDateTime = kerneltime->dwLowDateTime = 0;
340             if (usertime) usertime->dwHighDateTime = usertime->dwLowDateTime = 0;
341             FIXME("Cannot get kerneltime or usertime of other threads\n");
342         }
343     }
344     return ret;
345 }
346
347
348 /**********************************************************************
349  * VWin32_BoostThreadGroup [KERNEL.535]
350  */
351 VOID WINAPI VWin32_BoostThreadGroup( DWORD threadId, INT boost )
352 {
353     FIXME("(0x%08lx,%d): stub\n", threadId, boost);
354 }
355
356
357 /**********************************************************************
358  * VWin32_BoostThreadStatic [KERNEL.536]
359  */
360 VOID WINAPI VWin32_BoostThreadStatic( DWORD threadId, INT boost )
361 {
362     FIXME("(0x%08lx,%d): stub\n", threadId, boost);
363 }
364
365
366 /***********************************************************************
367  * GetCurrentThread [KERNEL32.@]  Gets pseudohandle for current thread
368  *
369  * RETURNS
370  *    Pseudohandle for the current thread
371  */
372 #undef GetCurrentThread
373 HANDLE WINAPI GetCurrentThread(void)
374 {
375     return (HANDLE)0xfffffffe;
376 }