Advertisement
Guest User

set realtime without wineserver

a guest
Apr 13th, 2014
46
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.28 KB | None | 0 0
  1. --- wine-1.3.24/include/winternl.h.old 2011-12-09 10:29:58.941289364 -0800
  2. +++ wine-1.3.24/include/winternl.h 2011-12-09 10:30:46.746164203 -0800
  3. @@ -22,6 +22,9 @@
  4. #define __WINE_WINTERNL_H
  5.  
  6. #include <windef.h>
  7. +#ifdef HAVE_SCHED_H
  8. + #define L_RT_THREADS 1
  9. +#endif
  10.  
  11. #ifdef __cplusplus
  12. extern "C" {
  13. @@ -2675,6 +2678,11 @@
  14.  
  15. #endif /* __WINESRC__ */
  16.  
  17. +#ifdef L_RT_THREADS
  18. + // see ntdll/thread.c
  19. + extern INT L_rt_handle_to_tid(HANDLE hthread);
  20. +#endif
  21. +
  22. #ifdef __cplusplus
  23. } /* extern "C" */
  24. #endif /* defined(__cplusplus) */
  25. --- wine-1.3.24/dlls/kernel32/thread.c.old 2011-12-09 10:30:59.982289197 -0800
  26. +++ wine-1.3.24/dlls/kernel32/thread.c 2011-12-12 14:11:45.870655576 -0800
  27. @@ -39,11 +39,104 @@
  28. #include "wine/library.h"
  29. #include "wine/server.h"
  30. #include "wine/debug.h"
  31. +#if L_RT_THREADS
  32. + #include <sched.h>
  33. + #include <pthread.h>
  34. + #include <errno.h>
  35. +#endif
  36.  
  37. #include "kernel_private.h"
  38.  
  39. WINE_DEFAULT_DEBUG_CHANNEL(thread);
  40.  
  41. +#if L_RT_THREADS
  42. +static BOOL L_rt_is_realtime_thread(HANDLE hthread)
  43. +{
  44. + pthread_t thread;
  45. + int policy;
  46. + struct sched_param param;
  47. +
  48. + thread = L_rt_handle_to_pthread(hthread);
  49. + if (thread != -1) {
  50. + if (pthread_getschedparam(thread, &policy, &param) != 0) {
  51. + ERR("sched_getscheduler '%s'\n", strerror(errno));
  52. + return(FALSE);
  53. + }
  54. + switch (policy) {
  55. + case SCHED_RR:
  56. + case SCHED_FIFO:
  57. + return(TRUE);
  58. + case -1:
  59. + ERR("sched_getscheduler '%s'\n", strerror(errno));
  60. + break;
  61. + }
  62. + }
  63. + else
  64. + ERR("no pthread_t for hthread %p\n", hthread);
  65. + return(FALSE);
  66. +}
  67. +
  68. +static BOOL L_rt_set_realtime_priority(HANDLE hthread, INT priority)
  69. +{
  70. + static int s_rtPrio = -1; // -1 means - check env
  71. + static int s_rtPolicy = -1; // -1 means - do not set r/t
  72. +
  73. + if (priority != THREAD_PRIORITY_TIME_CRITICAL)
  74. + return(FALSE);
  75. +
  76. + if (s_rtPrio == -1) {
  77. + const char *policyStr = getenv("L_RT_POLICY");
  78. + char *prioStr = getenv("L_RT_PRIO");
  79. + BOOL err = FALSE;
  80. + // don't check again
  81. + s_rtPrio = 0;
  82. + if (policyStr) {
  83. + if (strcmp(policyStr, "RR")==0)
  84. + s_rtPolicy = SCHED_RR;
  85. + else if (strcmp(policyStr, "FF")==0)
  86. + s_rtPolicy = SCHED_FIFO;
  87. + else if (strcmp(policyStr, "TS")==0)
  88. + s_rtPolicy = SCHED_OTHER;
  89. + else {
  90. + ERR("unsupported policy '%s'\n", prioStr);
  91. + err = TRUE;
  92. + }
  93. + if (!err) {
  94. + s_rtPrio = atoi(prioStr);
  95. + TRACE("policy %d, priority %d\n", s_rtPolicy, s_rtPrio);
  96. + }
  97. + }
  98. + }
  99. +
  100. + if (s_rtPolicy != -1) {
  101. + pthread_t thread;
  102. + int policy;
  103. + struct sched_param param;
  104. +
  105. + thread = L_rt_handle_to_pthread(hthread);
  106. + if (thread != -1) {
  107. + if (pthread_getschedparam(thread, &policy, &param) == -1) {
  108. + ERR("sched_getparam: '%s'\n", strerror(errno));
  109. + return FALSE;
  110. + }
  111. + if (policy != s_rtPolicy || param.sched_priority != s_rtPrio) {
  112. + param.sched_priority = s_rtPrio;
  113. + if (pthread_setschedparam(thread, s_rtPolicy, &param) == 0) {
  114. +// TRACE("set hthread %p, tid 0x%x\n", hthread, tid);
  115. + return TRUE;
  116. + }
  117. + else
  118. + ERR("sched_setscheduler(0x%x): '%s'\n", thread, strerror(errno));
  119. + }
  120. + else
  121. + return TRUE;
  122. + }
  123. + else
  124. + ERR("no pthread_t for hthread %p\n", hthread);
  125. + }
  126. + return FALSE;
  127. +}
  128. +#endif // L_RT_THREADS
  129.  
  130. /***********************************************************************
  131. * CreateThread (KERNEL32.@)
  132. @@ -196,9 +289,9 @@ BOOL WINAPI GetExitCodeThread(
  133. LPDWORD exitcode) /* [out] Address to receive termination status */
  134. {
  135. THREAD_BASIC_INFORMATION info;
  136. +
  137. NTSTATUS status = NtQueryInformationThread( hthread, ThreadBasicInformation,
  138. &info, sizeof(info), NULL );
  139. -
  140. if (status)
  141. {
  142. SetLastError( RtlNtStatusToDosError(status) );
  143. @@ -298,8 +391,17 @@ INT WINAPI GetThreadPriority(
  144. HANDLE hthread) /* [in] Handle to thread */
  145. {
  146. THREAD_BASIC_INFORMATION info;
  147. +#if L_RT_THREADS
  148. + NTSTATUS status;
  149. +
  150. + if (L_rt_is_realtime_thread(hthread))
  151. + return(THREAD_PRIORITY_TIME_CRITICAL);
  152. + status = NtQueryInformationThread( hthread, ThreadBasicInformation,
  153. + &info, sizeof(info), NULL );
  154. +#else
  155. NTSTATUS status = NtQueryInformationThread( hthread, ThreadBasicInformation,
  156. &info, sizeof(info), NULL );
  157. +#endif
  158.  
  159. if (status)
  160. {
  161. @@ -324,6 +426,11 @@ BOOL WINAPI SetThreadPriority(
  162. DWORD prio = priority;
  163. NTSTATUS status;
  164.  
  165. +#if L_RT_THREADS
  166. + if (L_rt_set_realtime_priority(hthread, prio))
  167. + return(TRUE);
  168. +#endif
  169. +
  170. status = NtSetInformationThread(hthread, ThreadBasePriority,
  171. &prio, sizeof(prio));
  172.  
  173. --- wine-1.3.24/dlls/ntdll/thread.c.old 2011-12-09 10:40:17.709289234 -0800
  174. +++ wine-1.3.24/dlls/ntdll/thread.c 2011-12-12 14:13:44.484212165 -0800
  175. @@ -67,6 +67,133 @@ static RTL_BITMAP fls_bitmap;
  176. static LIST_ENTRY tls_links;
  177. static int nb_threads = 1;
  178.  
  179. +static RTL_CRITICAL_SECTION ldt_section;
  180. +static RTL_CRITICAL_SECTION_DEBUG critsect_debug =
  181. +{
  182. + 0, 0, &ldt_section,
  183. + { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
  184. + 0, 0, { (DWORD_PTR)(__FILE__ ": ldt_section") }
  185. +};
  186. +static RTL_CRITICAL_SECTION ldt_section = { &critsect_debug, -1, 0, 0, 0, 0 };
  187. +//static sigset_t ldt_sigset;
  188. +
  189. +#if L_RT_THREADS
  190. +typedef struct _THREADMAP {
  191. + HANDLE m_handle;
  192. + pthread_t m_thread;
  193. + struct _THREADMAP* m_next;
  194. +} THREADMAP, *LPTHREADMAP;
  195. +
  196. +static RTL_CRITICAL_SECTION csThreadMap;
  197. +static RTL_CRITICAL_SECTION_DEBUG csthreadmap_debug =
  198. +{
  199. + 0, 0, &csThreadMap,
  200. + { &critsect_debug.ProcessLocksList, &csthreadmap_debug.ProcessLocksList },
  201. + 0, 0, { (DWORD_PTR)(__FILE__ ": csThreadMap") }
  202. +};
  203. +static RTL_CRITICAL_SECTION csThreadMap = { &csthreadmap_debug, -1, 0, 0, 0, 0 };
  204. +
  205. +static LPTHREADMAP s_threadMap;
  206. +
  207. +/***********************************************************************
  208. + * L_rt_add_pthread
  209. + */
  210. +static void L_rt_add_pthread(HANDLE handle, pthread_t thread)
  211. +{
  212. + LPTHREADMAP pobj;
  213. + LPTHREADMAP newobj;
  214. +
  215. + if (handle == GetCurrentThread()) {
  216. + ERR("failed - current thread unsupported");
  217. + return;
  218. + }
  219. +
  220. + // allocate outside of the CS
  221. + newobj = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(PIPEOBJ));
  222. +
  223. + RtlEnterCriticalSection(&csThreadMap);
  224. +
  225. + // replace TID if it's already in the list
  226. + for (pobj = s_threadMap; pobj; pobj = pobj->m_next) {
  227. + if (pobj->m_handle == handle) {
  228. + pobj->m_thread = thread;
  229. + break;
  230. + }
  231. + }
  232. +
  233. + // add a new entry at the beginning
  234. + if (!pobj) {
  235. + newobj->m_handle = handle;
  236. + newobj->m_thread = thread;
  237. + newobj->m_next = s_threadMap;
  238. + s_threadMap = newobj;
  239. + }
  240. +
  241. + RtlLeaveCriticalSection(&csThreadMap);
  242. +
  243. + // clean up outside of CS
  244. + if (pobj)
  245. + RtlFreeHeap(GetProcessHeap(), 0, newobj);
  246. +}
  247. +
  248. +/***********************************************************************
  249. + * L_rt_remove_pthread
  250. + */
  251. +void L_rt_remove_pthread(pthread_t thread)
  252. +{
  253. + LPTHREADMAP prev;
  254. + LPTHREADMAP pobj;
  255. +
  256. + RtlEnterCriticalSection(&csThreadMap);
  257. + prev = 0;
  258. + for (pobj = s_threadMap; pobj; pobj = pobj->m_next) {
  259. + if (pthread_equal(pobj->m_thread, thread)) {
  260. + if (prev)
  261. + prev->m_next = pobj->m_next;
  262. + else
  263. + s_threadMap = pobj->m_next;
  264. + break;
  265. + }
  266. + prev = pobj;
  267. + }
  268. + RtlLeaveCriticalSection(&csThreadMap);
  269. +
  270. + if (pobj)
  271. + RtlFreeHeap(GetProcessHeap(), 0, pobj);
  272. + else
  273. + ERR("Thread not found %x\n", (int)thread);
  274. +}
  275. +
  276. +/***********************************************************************
  277. + * L_rt_handle_to_pthread
  278. + */
  279. +pthread_t L_rt_handle_to_pthread(HANDLE hthread)
  280. +{
  281. + pthread_t thread;
  282. + LPTHREADMAP pobj;
  283. +
  284. + // shortcut for psuedo-handle
  285. + if (hthread == GetCurrentThread())
  286. + return pthread_self();
  287. +
  288. + // note: intentionally not using csThreadMap here since this will
  289. + // be called from realtime and doesn't want to wait on user threads.
  290. + // Should be safe because of how entries are carefully added to and
  291. + // removed from the list
  292. + thread = -1;
  293. + for (pobj = s_threadMap; pobj; pobj = pobj->m_next) {
  294. + if (pobj->m_handle == hthread) {
  295. + thread = pobj->m_thread;
  296. + break;
  297. + }
  298. + }
  299. + return(thread);
  300. +}
  301. +#endif // L_RT_THREADS
  302. +
  303. +
  304. +
  305. +
  306. /***********************************************************************
  307. * get_unicode_string
  308. *
  309. @@ -306,6 +433,10 @@ HANDLE thread_init(void)
  310. */
  311. void terminate_thread( int status )
  312. {
  313. +#if L_RT_THREADS
  314. + L_rt_remove_pthread(pthread_self());
  315. +#endif
  316. +
  317. pthread_sigmask( SIG_BLOCK, &server_block_set, NULL );
  318. if (interlocked_xchg_add( &nb_threads, -1 ) <= 1) _exit( status );
  319.  
  320. @@ -325,6 +456,10 @@ void exit_thread( int status )
  321. static void *prev_teb;
  322. TEB *teb;
  323.  
  324. +#if L_RT_THREADS
  325. + L_rt_remove_pthread(pthread_self());
  326. +#endif
  327. +
  328. if (status) /* send the exit code to the server (0 is already the default) */
  329. {
  330. SERVER_START_REQ( terminate_thread )
  331. @@ -494,6 +629,7 @@ NTSTATUS WINAPI RtlCreateUserThread( HAN
  332. thread_data->reply_fd = -1;
  333. thread_data->wait_fd[0] = -1;
  334. thread_data->wait_fd[1] = -1;
  335. + thread_data->pthread_id = 0;
  336.  
  337. if ((status = virtual_alloc_thread_stack( teb, stack_reserve, stack_commit ))) goto error;
  338.  
  339. @@ -516,6 +652,24 @@ NTSTATUS WINAPI RtlCreateUserThread( HAN
  340. if (handle_ptr) *handle_ptr = handle;
  341. else NtClose( handle );
  342.  
  343. +#if L_RT_THREADS
  344. + // give pthread_create a chance to call start_thread (pthread_info.entry),
  345. + // which sets gets the tid via pthread_functions.init_current_teb
  346. + pthread_t validThreadID = thread_data->pthread_id;
  347. + if (validThreadID == 0) {
  348. + int i;
  349. + for (i = 0; i < 100; ++i) {
  350. + validThreadID = thread_data->pthread_id;
  351. + if (validThreadID == 0)
  352. + usleep(6000);
  353. + }
  354. + }
  355. + if (validThreadID != 0)
  356. + L_rt_add_pthread(handle, validThreadID);
  357. + else
  358. + TRACE("no tid for hthread %p\n", handle);
  359. +#endif
  360. +
  361. return STATUS_SUCCESS;
  362.  
  363. error:
  364. --- wine-1.3.24/dlls/ntdll/ntdll.spec.old 2011-12-09 10:46:16.975164520 -0800
  365. +++ wine-1.3.24/dlls/ntdll/ntdll.spec 2011-12-12 09:42:44.959426636 -0800
  366. @@ -1409,3 +1409,7 @@
  367. @ cdecl wine_nt_to_unix_file_name(ptr ptr long long)
  368. @ cdecl wine_unix_to_nt_file_name(ptr ptr)
  369. @ cdecl __wine_init_windows_dir(wstr wstr)
  370. +
  371. +# L_RT_THREADS
  372. +@ cdecl L_rt_handle_to_pthread(ptr)
  373. +
  374. --- wine-1.3.24/dlls/ntdll/ntdll_misc.h.old 2011-12-09 10:47:44.873164404 -0800
  375. +++ wine-1.3.24/dlls/ntdll/ntdll_misc.h 2011-12-12 10:10:56.777643792 -0800
  376. @@ -171,6 +171,10 @@
  377. extern NTSTATUS NTDLL_AddCompletion( HANDLE hFile, ULONG_PTR CompletionValue,
  378. NTSTATUS CompletionStatus, ULONG Information ) DECLSPEC_HIDDEN;
  379.  
  380. +#ifdef L_RT_THREADS
  381. + extern void L_rt_remove_thread(pthread_t thread);
  382. +#endif
  383. +
  384. /* code pages */
  385. extern int ntdll_umbstowcs(DWORD flags, const char* src, int srclen, WCHAR* dst, int dstlen) DECLSPEC_HIDDEN;
  386. extern int ntdll_wcstoumbs(DWORD flags, const WCHAR* src, int srclen, char* dst, int dstlen,
  387. --- wine-1.3.24/dlls/ntdll/server.c.old 2011-12-09 10:48:23.506164452 -0800
  388. +++ wine-1.3.24/dlls/ntdll/server.c 2011-12-09 11:14:27.950195970 -0800
  389. @@ -33,6 +33,7 @@
  390. #include <stdio.h>
  391. #include <string.h>
  392. #include <sys/types.h>
  393. +#include <sys/syscall.h>
  394. #ifdef HAVE_SYS_SOCKET_H
  395. # include <sys/socket.h>
  396. #endif
  397. @@ -73,6 +74,7 @@
  398. #include "ntdll_misc.h"
  399.  
  400. WINE_DEFAULT_DEBUG_CHANNEL(server);
  401. +WINE_DECLARE_DEBUG_CHANNEL(rtcheck);
  402.  
  403. /* Some versions of glibc don't define this */
  404. #ifndef SCM_RIGHTS
  405. @@ -284,6 +286,17 @@ unsigned int wine_server_call( void *req
  406. sigset_t old_set;
  407. unsigned int ret;
  408.  
  409. + /* L_ - print when wineserver call is made from r/t thread */
  410. + if (TRACE_ON(rtcheck)) {
  411. + switch (sched_getscheduler(0)) {
  412. + case SCHED_RR:
  413. + case SCHED_FIFO:
  414. + TRACE_(rtcheck)("req=%d from realtime thread (p 0x%lx t 0x%x G 0x%x)\n",
  415. + req->u.req.request_header.req, pthread_self(), syscall(SYS_gettid), GetCurrentThreadId());
  416. + break;
  417. + }
  418. + }
  419. +
  420. pthread_sigmask( SIG_BLOCK, &server_block_set, &old_set );
  421. ret = send_request( req );
  422. if (!ret) ret = wait_reply( req );
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement