You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

349 lines
7.6 KiB

20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
  1. /******************************************************
  2. The interface to the operating system thread control primitives
  3. (c) 1995 Innobase Oy
  4. Created 9/8/1995 Heikki Tuuri
  5. *******************************************************/
  6. #include "os0thread.h"
  7. #ifdef UNIV_NONINL
  8. #include "os0thread.ic"
  9. #endif
  10. #ifdef __WIN__
  11. #include <windows.h>
  12. #endif
  13. #include "srv0srv.h"
  14. #include "os0sync.h"
  15. /*******************************************************************
  16. Compares two thread ids for equality. */
  17. UNIV_INTERN
  18. ibool
  19. os_thread_eq(
  20. /*=========*/
  21. /* out: TRUE if equal */
  22. os_thread_id_t a, /* in: OS thread or thread id */
  23. os_thread_id_t b) /* in: OS thread or thread id */
  24. {
  25. #ifdef __WIN__
  26. if (a == b) {
  27. return(TRUE);
  28. }
  29. return(FALSE);
  30. #else
  31. if (pthread_equal(a, b)) {
  32. return(TRUE);
  33. }
  34. return(FALSE);
  35. #endif
  36. }
  37. /********************************************************************
  38. Converts an OS thread id to a ulint. It is NOT guaranteed that the ulint is
  39. unique for the thread though! */
  40. UNIV_INTERN
  41. ulint
  42. os_thread_pf(
  43. /*=========*/
  44. os_thread_id_t a)
  45. {
  46. #ifdef UNIV_HPUX10
  47. /* In HP-UX-10.20 a pthread_t is a struct of 3 fields: field1, field2,
  48. field3. We do not know if field1 determines the thread uniquely. */
  49. return((ulint)(a.field1));
  50. #else
  51. return((ulint)a);
  52. #endif
  53. }
  54. /*********************************************************************
  55. Returns the thread identifier of current thread. Currently the thread
  56. identifier in Unix is the thread handle itself. Note that in HP-UX
  57. pthread_t is a struct of 3 fields. */
  58. UNIV_INTERN
  59. os_thread_id_t
  60. os_thread_get_curr_id(void)
  61. /*=======================*/
  62. {
  63. #ifdef __WIN__
  64. return(GetCurrentThreadId());
  65. #else
  66. return(pthread_self());
  67. #endif
  68. }
  69. /********************************************************************
  70. Creates a new thread of execution. The execution starts from
  71. the function given. The start function takes a void* parameter
  72. and returns an ulint. */
  73. UNIV_INTERN
  74. os_thread_t
  75. os_thread_create(
  76. /*=============*/
  77. /* out: handle to the thread */
  78. #ifndef __WIN__
  79. os_posix_f_t start_f,
  80. #else
  81. ulint (*start_f)(void*), /* in: pointer to function
  82. from which to start */
  83. #endif
  84. void* arg, /* in: argument to start
  85. function */
  86. os_thread_id_t* thread_id) /* out: id of the created
  87. thread, or NULL */
  88. {
  89. #ifdef __WIN__
  90. os_thread_t thread;
  91. DWORD win_thread_id;
  92. os_mutex_enter(os_sync_mutex);
  93. os_thread_count++;
  94. os_mutex_exit(os_sync_mutex);
  95. thread = CreateThread(NULL, /* no security attributes */
  96. 0, /* default size stack */
  97. (LPTHREAD_START_ROUTINE)start_f,
  98. arg,
  99. 0, /* thread runs immediately */
  100. &win_thread_id);
  101. if (srv_set_thread_priorities) {
  102. /* Set created thread priority the same as a normal query
  103. in MYSQL: we try to prevent starvation of threads by
  104. assigning same priority QUERY_PRIOR to all */
  105. ut_a(SetThreadPriority(thread, srv_query_thread_priority));
  106. }
  107. if (thread_id) {
  108. *thread_id = win_thread_id;
  109. }
  110. return(thread);
  111. #else
  112. int ret;
  113. os_thread_t pthread;
  114. pthread_attr_t attr;
  115. #if !(defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10))
  116. pthread_attr_init(&attr);
  117. #endif
  118. #ifdef UNIV_AIX
  119. /* We must make sure a thread stack is at least 32 kB, otherwise
  120. InnoDB might crash; we do not know if the default stack size on
  121. AIX is always big enough. An empirical test on AIX-4.3 suggested
  122. the size was 96 kB, though. */
  123. ret = pthread_attr_setstacksize(&attr,
  124. (size_t)(PTHREAD_STACK_MIN
  125. + 32 * 1024));
  126. if (ret) {
  127. fprintf(stderr,
  128. "InnoDB: Error: pthread_attr_setstacksize"
  129. " returned %d\n", ret);
  130. exit(1);
  131. }
  132. #endif
  133. #ifdef __NETWARE__
  134. ret = pthread_attr_setstacksize(&attr,
  135. (size_t) NW_THD_STACKSIZE);
  136. if (ret) {
  137. fprintf(stderr,
  138. "InnoDB: Error: pthread_attr_setstacksize"
  139. " returned %d\n", ret);
  140. exit(1);
  141. }
  142. #endif
  143. os_mutex_enter(os_sync_mutex);
  144. os_thread_count++;
  145. os_mutex_exit(os_sync_mutex);
  146. #if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10)
  147. ret = pthread_create(&pthread, pthread_attr_default, start_f, arg);
  148. #else
  149. ret = pthread_create(&pthread, &attr, start_f, arg);
  150. #endif
  151. if (ret) {
  152. fprintf(stderr,
  153. "InnoDB: Error: pthread_create returned %d\n", ret);
  154. exit(1);
  155. }
  156. #if !(defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10))
  157. pthread_attr_destroy(&attr);
  158. #endif
  159. if (srv_set_thread_priorities) {
  160. my_pthread_setprio(pthread, srv_query_thread_priority);
  161. }
  162. if (thread_id) {
  163. *thread_id = pthread;
  164. }
  165. return(pthread);
  166. #endif
  167. }
  168. /*********************************************************************
  169. Exits the current thread. */
  170. UNIV_INTERN
  171. void
  172. os_thread_exit(
  173. /*===========*/
  174. void* exit_value) /* in: exit value; in Windows this void*
  175. is cast as a DWORD */
  176. {
  177. #ifdef UNIV_DEBUG_THREAD_CREATION
  178. fprintf(stderr, "Thread exits, id %lu\n",
  179. os_thread_pf(os_thread_get_curr_id()));
  180. #endif
  181. os_mutex_enter(os_sync_mutex);
  182. os_thread_count--;
  183. os_mutex_exit(os_sync_mutex);
  184. #ifdef __WIN__
  185. ExitThread((DWORD)exit_value);
  186. #else
  187. pthread_exit(exit_value);
  188. #endif
  189. }
  190. /*********************************************************************
  191. Returns handle to the current thread. */
  192. UNIV_INTERN
  193. os_thread_t
  194. os_thread_get_curr(void)
  195. /*====================*/
  196. {
  197. #ifdef __WIN__
  198. return(GetCurrentThread());
  199. #else
  200. return(pthread_self());
  201. #endif
  202. }
  203. /*********************************************************************
  204. Advises the os to give up remainder of the thread's time slice. */
  205. UNIV_INTERN
  206. void
  207. os_thread_yield(void)
  208. /*=================*/
  209. {
  210. #if defined(__WIN__)
  211. Sleep(0);
  212. #elif (defined(HAVE_SCHED_YIELD) && defined(HAVE_SCHED_H))
  213. sched_yield();
  214. #elif defined(HAVE_PTHREAD_YIELD_ZERO_ARG)
  215. pthread_yield();
  216. #elif defined(HAVE_PTHREAD_YIELD_ONE_ARG)
  217. pthread_yield(0);
  218. #else
  219. os_thread_sleep(0);
  220. #endif
  221. }
  222. /*********************************************************************
  223. The thread sleeps at least the time given in microseconds. */
  224. UNIV_INTERN
  225. void
  226. os_thread_sleep(
  227. /*============*/
  228. ulint tm) /* in: time in microseconds */
  229. {
  230. #ifdef __WIN__
  231. Sleep((DWORD) tm / 1000);
  232. #elif defined(__NETWARE__)
  233. delay(tm / 1000);
  234. #else
  235. struct timeval t;
  236. t.tv_sec = tm / 1000000;
  237. t.tv_usec = tm % 1000000;
  238. select(0, NULL, NULL, NULL, &t);
  239. #endif
  240. }
  241. /**********************************************************************
  242. Sets a thread priority. */
  243. UNIV_INTERN
  244. void
  245. os_thread_set_priority(
  246. /*===================*/
  247. os_thread_t handle, /* in: OS handle to the thread */
  248. ulint pri) /* in: priority */
  249. {
  250. #ifdef __WIN__
  251. int os_pri;
  252. if (pri == OS_THREAD_PRIORITY_BACKGROUND) {
  253. os_pri = THREAD_PRIORITY_BELOW_NORMAL;
  254. } else if (pri == OS_THREAD_PRIORITY_NORMAL) {
  255. os_pri = THREAD_PRIORITY_NORMAL;
  256. } else if (pri == OS_THREAD_PRIORITY_ABOVE_NORMAL) {
  257. os_pri = THREAD_PRIORITY_HIGHEST;
  258. } else {
  259. ut_error;
  260. }
  261. ut_a(SetThreadPriority(handle, os_pri));
  262. #else
  263. UT_NOT_USED(handle);
  264. UT_NOT_USED(pri);
  265. #endif
  266. }
  267. /**********************************************************************
  268. Gets a thread priority. */
  269. UNIV_INTERN
  270. ulint
  271. os_thread_get_priority(
  272. /*===================*/
  273. /* out: priority */
  274. os_thread_t handle __attribute__((unused)))
  275. /* in: OS handle to the thread */
  276. {
  277. #ifdef __WIN__
  278. int os_pri;
  279. ulint pri;
  280. os_pri = GetThreadPriority(handle);
  281. if (os_pri == THREAD_PRIORITY_BELOW_NORMAL) {
  282. pri = OS_THREAD_PRIORITY_BACKGROUND;
  283. } else if (os_pri == THREAD_PRIORITY_NORMAL) {
  284. pri = OS_THREAD_PRIORITY_NORMAL;
  285. } else if (os_pri == THREAD_PRIORITY_HIGHEST) {
  286. pri = OS_THREAD_PRIORITY_ABOVE_NORMAL;
  287. } else {
  288. ut_error;
  289. }
  290. return(pri);
  291. #else
  292. return(0);
  293. #endif
  294. }
  295. /**********************************************************************
  296. Gets the last operating system error code for the calling thread. */
  297. UNIV_INTERN
  298. ulint
  299. os_thread_get_last_error(void)
  300. /*==========================*/
  301. {
  302. #ifdef __WIN__
  303. return(GetLastError());
  304. #else
  305. return(0);
  306. #endif
  307. }