os0thread.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:8k
源码类别:

MySQL数据库

开发平台:

Visual C++

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