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

MySQL数据库

开发平台:

Visual C++

  1. /******************************************************
  2. The interface to the operating system
  3. synchronization primitives.
  4. (c) 1995 Innobase Oy
  5. Created 9/6/1995 Heikki Tuuri
  6. *******************************************************/
  7. #include "os0sync.h"
  8. #ifdef UNIV_NONINL
  9. #include "os0sync.ic"
  10. #endif
  11. #ifdef __WIN__
  12. #include <windows.h>
  13. #endif
  14. #include "ut0mem.h"
  15. #include "srv0start.h"
  16. /* Type definition for an operating system mutex struct */
  17. struct os_mutex_struct{ 
  18. void* handle; /* OS handle to mutex */
  19. ulint count; /* we use this counter to check
  20. that the same thread does not
  21. recursively lock the mutex: we
  22. do not assume that the OS mutex
  23. supports recursive locking, though
  24. NT seems to do that */
  25. UT_LIST_NODE_T(os_mutex_str_t) os_mutex_list;
  26. /* list of all 'slow' OS mutexes created */
  27. };
  28. /* Mutex protecting counts and the lists of OS mutexes and events */
  29. os_mutex_t os_sync_mutex;
  30. ibool os_sync_mutex_inited = FALSE;
  31. /* This is incremented by 1 in os_thread_create and decremented by 1 in
  32. os_thread_exit */
  33. ulint os_thread_count = 0;
  34. /* The list of all events created */
  35. UT_LIST_BASE_NODE_T(os_event_struct_t) os_event_list;
  36. /* The list of all OS 'slow' mutexes */
  37. UT_LIST_BASE_NODE_T(os_mutex_str_t) os_mutex_list;
  38. ulint os_event_count = 0;
  39. ulint os_mutex_count = 0;
  40. ulint os_fast_mutex_count = 0;
  41. /*************************************************************
  42. Initializes global event and OS 'slow' mutex lists. */
  43. void
  44. os_sync_init(void)
  45. /*==============*/
  46. {
  47. UT_LIST_INIT(os_event_list);
  48. UT_LIST_INIT(os_mutex_list);
  49. os_sync_mutex = os_mutex_create(NULL);
  50. os_sync_mutex_inited = TRUE;
  51. }
  52. /*************************************************************
  53. Frees created events and OS 'slow' mutexes. */
  54. void
  55. os_sync_free(void)
  56. /*==============*/
  57. {
  58. os_event_t event;
  59. os_mutex_t mutex;
  60. event = UT_LIST_GET_FIRST(os_event_list);
  61. while (event) {
  62.       os_event_free(event);
  63.       event = UT_LIST_GET_FIRST(os_event_list);
  64. }
  65. mutex = UT_LIST_GET_FIRST(os_mutex_list);
  66. while (mutex) {
  67.       if (mutex == os_sync_mutex) {
  68.       /* Set the flag to FALSE so that we do not try to
  69.       reserve os_sync_mutex any more in remaining freeing
  70.       operations in shutdown */
  71.       os_sync_mutex_inited = FALSE;
  72.       }
  73.       os_mutex_free(mutex);
  74.       mutex = UT_LIST_GET_FIRST(os_mutex_list);
  75. }
  76. }
  77. /*************************************************************
  78. Creates an event semaphore, i.e., a semaphore which may just have two
  79. states: signaled and nonsignaled. The created event is manual reset: it
  80. must be reset explicitly by calling sync_os_reset_event. */
  81. os_event_t
  82. os_event_create(
  83. /*============*/
  84. /* out: the event handle */
  85. const char* name) /* in: the name of the event, if NULL
  86. the event is created without a name */
  87. {
  88. #ifdef __WIN__
  89.         os_event_t event;
  90. event = ut_malloc(sizeof(struct os_event_struct));
  91. event->handle = CreateEvent(NULL,/* No security attributes */
  92. TRUE, /* Manual reset */
  93. FALSE, /* Initial state nonsignaled */
  94. name);
  95. if (!event->handle) {
  96.         fprintf(stderr,
  97. "InnoDB: Could not create a Windows event semaphore; Windows error %lun",
  98.   (ulong) GetLastError());
  99. }
  100. #else /* Unix */
  101. os_event_t event;
  102. UT_NOT_USED(name);
  103. event = ut_malloc(sizeof(struct os_event_struct));
  104. os_fast_mutex_init(&(event->os_mutex));
  105. #if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10)
  106. ut_a(0 == pthread_cond_init(&(event->cond_var),
  107. pthread_condattr_default));
  108. #else
  109. ut_a(0 == pthread_cond_init(&(event->cond_var), NULL));
  110. #endif
  111. event->is_set = FALSE;
  112. event->signal_count = 0;
  113. #endif /* __WIN__ */
  114.         /* Put to the list of events */
  115. os_mutex_enter(os_sync_mutex);
  116. UT_LIST_ADD_FIRST(os_event_list, os_event_list, event);
  117. os_event_count++;
  118. os_mutex_exit(os_sync_mutex);
  119. return(event);
  120. }
  121. #ifdef __WIN__
  122. /*************************************************************
  123. Creates an auto-reset event semaphore, i.e., an event which is automatically
  124. reset when a single thread is released. Works only in Windows. */
  125. os_event_t
  126. os_event_create_auto(
  127. /*=================*/
  128. /* out: the event handle */
  129. const char* name) /* in: the name of the event, if NULL
  130. the event is created without a name */
  131. {
  132.         os_event_t event;
  133. event = ut_malloc(sizeof(struct os_event_struct));
  134. event->handle = CreateEvent(NULL,/* No security attributes */
  135. FALSE, /* Auto-reset */
  136. FALSE, /* Initial state nonsignaled */
  137. name);
  138. if (!event->handle) {
  139.         fprintf(stderr,
  140. "InnoDB: Could not create a Windows auto event semaphore; Windows error %lun",
  141.   (ulong) GetLastError());
  142. }
  143.         /* Put to the list of events */
  144. os_mutex_enter(os_sync_mutex);
  145. UT_LIST_ADD_FIRST(os_event_list, os_event_list, event);
  146. os_event_count++;
  147. os_mutex_exit(os_sync_mutex);
  148. return(event);
  149. }
  150. #endif
  151. /**************************************************************
  152. Sets an event semaphore to the signaled state: lets waiting threads
  153. proceed. */
  154. void
  155. os_event_set(
  156. /*=========*/
  157. os_event_t event) /* in: event to set */
  158. {
  159. #ifdef __WIN__
  160. ut_a(event);
  161. ut_a(SetEvent(event->handle));
  162. #else
  163. ut_a(event);
  164. os_fast_mutex_lock(&(event->os_mutex));
  165. if (event->is_set) {
  166. /* Do nothing */
  167. } else {
  168. event->is_set = TRUE;
  169. event->signal_count += 1;
  170. ut_a(0 == pthread_cond_broadcast(&(event->cond_var)));
  171. }
  172. os_fast_mutex_unlock(&(event->os_mutex));
  173. #endif
  174. }
  175. /**************************************************************
  176. Resets an event semaphore to the nonsignaled state. Waiting threads will
  177. stop to wait for the event. */
  178. void
  179. os_event_reset(
  180. /*===========*/
  181. os_event_t event) /* in: event to reset */
  182. {
  183. #ifdef __WIN__
  184. ut_a(event);
  185. ut_a(ResetEvent(event->handle));
  186. #else
  187. ut_a(event);
  188. os_fast_mutex_lock(&(event->os_mutex));
  189. if (!event->is_set) {
  190. /* Do nothing */
  191. } else {
  192. event->is_set = FALSE;
  193. }
  194. os_fast_mutex_unlock(&(event->os_mutex));
  195. #endif
  196. }
  197. /**************************************************************
  198. Frees an event object. */
  199. void
  200. os_event_free(
  201. /*==========*/
  202. os_event_t event) /* in: event to free */
  203. {
  204. #ifdef __WIN__
  205. ut_a(event);
  206. ut_a(CloseHandle(event->handle));
  207. #else
  208. ut_a(event);
  209. os_fast_mutex_free(&(event->os_mutex));
  210. ut_a(0 == pthread_cond_destroy(&(event->cond_var)));
  211. #endif
  212.         /* Remove from the list of events */
  213. os_mutex_enter(os_sync_mutex);
  214. UT_LIST_REMOVE(os_event_list, os_event_list, event);
  215. os_event_count--;
  216. os_mutex_exit(os_sync_mutex);
  217. ut_free(event);
  218. }
  219. /**************************************************************
  220. Waits for an event object until it is in the signaled state. If
  221. srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS this also exits the
  222. waiting thread when the event becomes signaled (or immediately if the
  223. event is already in the signaled state). */
  224. void
  225. os_event_wait(
  226. /*==========*/
  227. os_event_t event) /* in: event to wait */
  228. {
  229. #ifdef __WIN__
  230. DWORD err;
  231. ut_a(event);
  232. /* Specify an infinite time limit for waiting */
  233. err = WaitForSingleObject(event->handle, INFINITE);
  234. ut_a(err == WAIT_OBJECT_0);
  235. if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
  236.         os_thread_exit(NULL);
  237. }
  238. #else
  239. ib_longlong old_signal_count;
  240. os_fast_mutex_lock(&(event->os_mutex));
  241. old_signal_count = event->signal_count;
  242. loop:
  243. if (event->is_set == TRUE
  244.             || event->signal_count != old_signal_count) {
  245. os_fast_mutex_unlock(&(event->os_mutex));
  246. if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
  247.         os_thread_exit(NULL);
  248. }
  249. /* Ok, we may return */
  250. return;
  251. }
  252. pthread_cond_wait(&(event->cond_var), &(event->os_mutex));
  253. /* Solaris manual said that spurious wakeups may occur: we have to
  254. check if the event really has been signaled after we came here to
  255. wait */
  256. goto loop;
  257. #endif
  258. }
  259. /**************************************************************
  260. Waits for an event object until it is in the signaled state or
  261. a timeout is exceeded. In Unix the timeout is always infinite. */
  262. ulint
  263. os_event_wait_time(
  264. /*===============*/
  265. /* out: 0 if success, OS_SYNC_TIME_EXCEEDED if
  266. timeout was exceeded */
  267. os_event_t event, /* in: event to wait */
  268. ulint time) /* in: timeout in microseconds, or
  269. OS_SYNC_INFINITE_TIME */
  270. {
  271. #ifdef __WIN__
  272. DWORD err;
  273. ut_a(event);
  274. if (time != OS_SYNC_INFINITE_TIME) {
  275. err = WaitForSingleObject(event->handle, (DWORD) time / 1000);
  276. } else {
  277. err = WaitForSingleObject(event->handle, INFINITE);
  278. }
  279. if (err == WAIT_OBJECT_0) {
  280. return(0);
  281. } else if (err == WAIT_TIMEOUT) {
  282. return(OS_SYNC_TIME_EXCEEDED);
  283. } else {
  284. ut_error;
  285. return(1000000); /* dummy value to eliminate compiler warn. */
  286. }
  287. #else
  288. UT_NOT_USED(time);
  289. /* In Posix this is just an ordinary, infinite wait */
  290. os_event_wait(event);
  291. return(0);
  292. #endif
  293. }
  294. #ifdef __WIN__
  295. /**************************************************************
  296. Waits for any event in an OS native event array. Returns if even a single
  297. one is signaled or becomes signaled. */
  298. ulint
  299. os_event_wait_multiple(
  300. /*===================*/
  301. /* out: index of the event
  302. which was signaled */
  303. ulint n, /* in: number of events in the
  304. array */
  305. os_native_event_t* native_event_array)
  306. /* in: pointer to an array of event
  307. handles */
  308. {
  309. DWORD index;
  310. ut_a(native_event_array);
  311. ut_a(n > 0);
  312. index = WaitForMultipleObjects((DWORD) n, native_event_array,
  313. FALSE,    /* Wait for any 1 event */
  314. INFINITE); /* Infinite wait time
  315.    limit */
  316. ut_a(index >= WAIT_OBJECT_0); /* NOTE: Pointless comparision */
  317. ut_a(index < WAIT_OBJECT_0 + n);
  318. if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
  319.         os_thread_exit(NULL);
  320. }
  321. return(index - WAIT_OBJECT_0);
  322. }
  323. #endif
  324. /*************************************************************
  325. Creates an operating system mutex semaphore. Because these are slow, the
  326. mutex semaphore of InnoDB itself (mutex_t) should be used where possible. */
  327. os_mutex_t
  328. os_mutex_create(
  329. /*============*/
  330. /* out: the mutex handle */
  331. const char* name) /* in: the name of the mutex, if NULL
  332. the mutex is created without a name */
  333. {
  334. #ifdef __WIN__
  335. HANDLE mutex;
  336. os_mutex_t mutex_str;
  337. mutex = CreateMutex(NULL, /* No security attributes */
  338. FALSE, /* Initial state: no owner */
  339. name);
  340. ut_a(mutex);
  341. #else
  342. os_fast_mutex_t* mutex;
  343. os_mutex_t mutex_str;
  344. UT_NOT_USED(name);
  345. mutex = ut_malloc(sizeof(os_fast_mutex_t));
  346. os_fast_mutex_init(mutex);
  347. #endif
  348. mutex_str = ut_malloc(sizeof(os_mutex_str_t));
  349. mutex_str->handle = mutex;
  350. mutex_str->count = 0;
  351. if (os_sync_mutex_inited) {
  352. /* When creating os_sync_mutex itself we cannot reserve it */
  353.         os_mutex_enter(os_sync_mutex);
  354. }
  355. UT_LIST_ADD_FIRST(os_mutex_list, os_mutex_list, mutex_str);
  356. os_mutex_count++;
  357. if (os_sync_mutex_inited) {
  358. os_mutex_exit(os_sync_mutex);
  359. }
  360. return(mutex_str);
  361. }
  362. /**************************************************************
  363. Acquires ownership of a mutex semaphore. */
  364. void
  365. os_mutex_enter(
  366. /*===========*/
  367. os_mutex_t mutex) /* in: mutex to acquire */
  368. {
  369. #ifdef __WIN__
  370. DWORD err;
  371. ut_a(mutex);
  372. /* Specify infinite time limit for waiting */
  373. err = WaitForSingleObject(mutex->handle, INFINITE);
  374. ut_a(err == WAIT_OBJECT_0);
  375. (mutex->count)++;
  376. ut_a(mutex->count == 1);
  377. #else
  378. os_fast_mutex_lock(mutex->handle);
  379. (mutex->count)++;
  380. ut_a(mutex->count == 1);
  381. #endif
  382. }
  383. /**************************************************************
  384. Releases ownership of a mutex. */
  385. void
  386. os_mutex_exit(
  387. /*==========*/
  388. os_mutex_t mutex) /* in: mutex to release */
  389. {
  390. ut_a(mutex);
  391. ut_a(mutex->count == 1);
  392. (mutex->count)--;
  393. #ifdef __WIN__
  394. ut_a(ReleaseMutex(mutex->handle));
  395. #else
  396. os_fast_mutex_unlock(mutex->handle);
  397. #endif
  398. }
  399. /**************************************************************
  400. Frees a mutex object. */
  401. void
  402. os_mutex_free(
  403. /*==========*/
  404. os_mutex_t mutex) /* in: mutex to free */
  405. {
  406. ut_a(mutex);
  407. if (os_sync_mutex_inited) {
  408. os_mutex_enter(os_sync_mutex);
  409. }
  410. UT_LIST_REMOVE(os_mutex_list, os_mutex_list, mutex);
  411. os_mutex_count--;
  412. if (os_sync_mutex_inited) {
  413. os_mutex_exit(os_sync_mutex);
  414. }
  415. #ifdef __WIN__
  416. ut_a(CloseHandle(mutex->handle));
  417. ut_free(mutex);
  418. #else
  419. os_fast_mutex_free(mutex->handle);
  420. ut_free(mutex->handle);
  421. ut_free(mutex);
  422. #endif
  423. }
  424. /*************************************************************
  425. Initializes an operating system fast mutex semaphore. */
  426. void
  427. os_fast_mutex_init(
  428. /*===============*/
  429. os_fast_mutex_t* fast_mutex) /* in: fast mutex */
  430. {
  431. #ifdef __WIN__
  432. ut_a(fast_mutex);
  433. InitializeCriticalSection((LPCRITICAL_SECTION) fast_mutex);
  434. #else
  435. #if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10)
  436. ut_a(0 == pthread_mutex_init(fast_mutex, pthread_mutexattr_default));
  437. #else
  438. ut_a(0 == pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST));
  439. #endif
  440. #endif
  441. if (os_sync_mutex_inited) {
  442. /* When creating os_sync_mutex itself (in Unix) we cannot
  443. reserve it */
  444. os_mutex_enter(os_sync_mutex);
  445. }
  446. os_fast_mutex_count++;
  447. if (os_sync_mutex_inited) {
  448.         os_mutex_exit(os_sync_mutex);
  449. }
  450. }
  451. /**************************************************************
  452. Acquires ownership of a fast mutex. */
  453. void
  454. os_fast_mutex_lock(
  455. /*===============*/
  456. os_fast_mutex_t* fast_mutex) /* in: mutex to acquire */
  457. {
  458. #ifdef __WIN__
  459. EnterCriticalSection((LPCRITICAL_SECTION) fast_mutex);
  460. #else
  461. pthread_mutex_lock(fast_mutex);
  462. #endif
  463. }
  464. /**************************************************************
  465. Releases ownership of a fast mutex. */
  466. void
  467. os_fast_mutex_unlock(
  468. /*=================*/
  469. os_fast_mutex_t* fast_mutex) /* in: mutex to release */
  470. {
  471. #ifdef __WIN__
  472. LeaveCriticalSection(fast_mutex);
  473. #else
  474. pthread_mutex_unlock(fast_mutex);
  475. #endif
  476. }
  477. /**************************************************************
  478. Frees a mutex object. */
  479. void
  480. os_fast_mutex_free(
  481. /*===============*/
  482. os_fast_mutex_t* fast_mutex) /* in: mutex to free */
  483. {
  484. #ifdef __WIN__
  485. ut_a(fast_mutex);
  486. DeleteCriticalSection((LPCRITICAL_SECTION) fast_mutex);
  487. #else
  488. int ret;
  489. ret = pthread_mutex_destroy(fast_mutex);
  490. if (ret != 0) {
  491. ut_print_timestamp(stderr);
  492. fprintf(stderr,
  493. "  InnoDB: error: return value %lu when callingn"
  494. "InnoDB: pthread_mutex_destroy().n", (ulint)ret);
  495. fprintf(stderr,
  496. "InnoDB: Byte contents of the pthread mutex at %p:n", fast_mutex);
  497. ut_print_buf(stderr, (const byte*)fast_mutex,
  498. sizeof(os_fast_mutex_t));
  499. fprintf(stderr, "n");
  500. }
  501. #endif
  502. if (os_sync_mutex_inited) {
  503. /* When freeing the last mutexes, we have
  504. already freed os_sync_mutex */
  505. os_mutex_enter(os_sync_mutex);
  506. }
  507. os_fast_mutex_count--;
  508. if (os_sync_mutex_inited) {
  509. os_mutex_exit(os_sync_mutex);
  510. }
  511. }