Drizzled Public API Documentation

sync0arr.cc
1 /*****************************************************************************
2 
3 Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
4 Copyright (C) 2008, Google Inc.
5 
6 Portions of this file contain modifications contributed and copyrighted by
7 Google, Inc. Those modifications are gratefully acknowledged and are described
8 briefly in the InnoDB documentation. The contributions by Google are
9 incorporated with their permission, and subject to the conditions contained in
10 the file COPYING.Google.
11 
12 This program is free software; you can redistribute it and/or modify it under
13 the terms of the GNU General Public License as published by the Free Software
14 Foundation; version 2 of the License.
15 
16 This program is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
19 
20 You should have received a copy of the GNU General Public License along with
21 this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
22 St, Fifth Floor, Boston, MA 02110-1301 USA
23 
24 *****************************************************************************/
25 
26 /**************************************************/
33 #include "sync0arr.h"
34 #ifdef UNIV_NONINL
35 #include "sync0arr.ic"
36 #endif
37 
38 #include "sync0sync.h"
39 #include "sync0rw.h"
40 #include "os0sync.h"
41 #include "os0file.h"
42 #include "srv0srv.h"
43 #include "ha_prototypes.h"
44 
45 /*
46  WAIT ARRAY
47  ==========
48 
49 The wait array consists of cells each of which has an
50 an operating system event object created for it. The threads
51 waiting for a mutex, for example, can reserve a cell
52 in the array and suspend themselves to wait for the event
53 to become signaled. When using the wait array, remember to make
54 sure that some thread holding the synchronization object
55 will eventually know that there is a waiter in the array and
56 signal the object, to prevent infinite wait.
57 Why we chose to implement a wait array? First, to make
58 mutexes fast, we had to code our own implementation of them,
59 which only in usually uncommon cases resorts to using
60 slow operating system primitives. Then we had the choice of
61 assigning a unique OS event for each mutex, which would
62 be simpler, or using a global wait array. In some operating systems,
63 the global wait array solution is more efficient and flexible,
64 because we can do with a very small number of OS events,
65 say 200. In NT 3.51, allocating events seems to be a quadratic
66 algorithm, because 10 000 events are created fast, but
67 100 000 events takes a couple of minutes to create.
68 
69 As of 5.0.30 the above mentioned design is changed. Since now
70 OS can handle millions of wait events efficiently, we no longer
71 have this concept of each cell of wait array having one event.
72 Instead, now the event that a thread wants to wait on is embedded
73 in the wait object (mutex or rw_lock). We still keep the global
74 wait array for the sake of diagnostics and also to avoid infinite
75 wait The error_monitor thread scans the global wait array to signal
76 any waiting threads who have missed the signal. */
77 
82  void* wait_object;
89  ulint request_type;
91  const char* file;
93  ulint line;
97  ibool waiting;
100  ib_int64_t signal_count;
110 };
111 
112 /* NOTE: It is allowed for a thread to wait
113 for an event allocated for the array without owning the
114 protecting mutex (depending on the case: OS or database mutex), but
115 all changes (set or reset) to the state of the event must be made
116 while owning the mutex. */
117 
120  ulint n_reserved;
122  ulint n_cells;
125  ulint protection;
136  ulint sg_count;
138  ulint res_count;
140 };
141 
142 #ifdef UNIV_PFS_MUTEX
143 /* Key to register the mutex with performance schema */
144 UNIV_INTERN mysql_pfs_key_t syn_arr_mutex_key;
145 #endif
146 
147 #ifdef UNIV_SYNC_DEBUG
148 /******************************************************************/
152 static
153 ibool
154 sync_array_detect_deadlock(
155 /*=======================*/
156  sync_array_t* arr,
158  sync_cell_t* start,
159  sync_cell_t* cell,
160  ulint depth);
161 #endif /* UNIV_SYNC_DEBUG */
162 
163 /*****************************************************************/
166 static
168 sync_array_get_nth_cell(
169 /*====================*/
170  sync_array_t* arr,
171  ulint n)
172 {
173  ut_a(arr);
174  ut_a(n < arr->n_cells);
175 
176  return(arr->array + n);
177 }
178 
179 /******************************************************************/
181 static
182 void
183 sync_array_enter(
184 /*=============*/
185  sync_array_t* arr)
186 {
187  ulint protection;
188 
189  protection = arr->protection;
190 
191  if (protection == SYNC_ARRAY_OS_MUTEX) {
192  os_mutex_enter(arr->os_mutex);
193  } else if (protection == SYNC_ARRAY_MUTEX) {
194  mutex_enter(&(arr->mutex));
195  } else {
196  ut_error;
197  }
198 }
199 
200 /******************************************************************/
202 static
203 void
204 sync_array_exit(
205 /*============*/
206  sync_array_t* arr)
207 {
208  ulint protection;
209 
210  protection = arr->protection;
211 
212  if (protection == SYNC_ARRAY_OS_MUTEX) {
213  os_mutex_exit(arr->os_mutex);
214  } else if (protection == SYNC_ARRAY_MUTEX) {
215  mutex_exit(&(arr->mutex));
216  } else {
217  ut_error;
218  }
219 }
220 
221 /*******************************************************************/
226 UNIV_INTERN
229 /*==============*/
230  ulint n_cells,
232  ulint protection)
235 {
236  ulint sz;
237  sync_array_t* arr;
238 
239  ut_a(n_cells > 0);
240 
241  /* Allocate memory for the data structures */
242  arr = static_cast<sync_array_t *>(ut_malloc(sizeof(sync_array_t)));
243  memset(arr, 0x0, sizeof(*arr));
244 
245  sz = sizeof(sync_cell_t) * n_cells;
246  arr->array = static_cast<sync_cell_t *>(ut_malloc(sz));
247  memset(arr->array, 0x0, sz);
248 
249  arr->n_cells = n_cells;
250  arr->protection = protection;
251 
252  /* Then create the mutex to protect the wait array complex */
253  if (protection == SYNC_ARRAY_OS_MUTEX) {
254  arr->os_mutex = os_mutex_create();
255  } else if (protection == SYNC_ARRAY_MUTEX) {
256  mutex_create(syn_arr_mutex_key,
257  &arr->mutex, SYNC_NO_ORDER_CHECK);
258  } else {
259  ut_error;
260  }
261 
262  return(arr);
263 }
264 
265 /******************************************************************/
267 UNIV_INTERN
268 void
270 /*============*/
271  sync_array_t* arr)
272 {
273  ulint protection;
274 
275  ut_a(arr->n_reserved == 0);
276 
277  sync_array_validate(arr);
278 
279  protection = arr->protection;
280 
281  /* Release the mutex protecting the wait array complex */
282 
283  if (protection == SYNC_ARRAY_OS_MUTEX) {
284  os_mutex_free(arr->os_mutex);
285  } else if (protection == SYNC_ARRAY_MUTEX) {
286  mutex_free(&(arr->mutex));
287  } else {
288  ut_error;
289  }
290 
291  ut_free(arr->array);
292  ut_free(arr);
293 }
294 
295 /********************************************************************/
298 UNIV_INTERN
299 void
301 /*================*/
302  sync_array_t* arr)
303 {
304  ulint i;
305  sync_cell_t* cell;
306  ulint count = 0;
307 
308  sync_array_enter(arr);
309 
310  for (i = 0; i < arr->n_cells; i++) {
311  cell = sync_array_get_nth_cell(arr, i);
312  if (cell->wait_object != NULL) {
313  count++;
314  }
315  }
316 
317  ut_a(count == arr->n_reserved);
318 
319  sync_array_exit(arr);
320 }
321 
322 /*******************************************************************/
324 static
326 sync_cell_get_event(
327 /*================*/
328  sync_cell_t* cell)
329 {
330  ulint type = cell->request_type;
331 
332  if (type == SYNC_MUTEX) {
333  return(((mutex_t *) cell->wait_object)->event);
334  } else if (type == RW_LOCK_WAIT_EX) {
335  return(((rw_lock_t *) cell->wait_object)->wait_ex_event);
336  } else { /* RW_LOCK_SHARED and RW_LOCK_EX wait on the same event */
337  return(((rw_lock_t *) cell->wait_object)->event);
338  }
339 }
340 
341 /******************************************************************/
344 UNIV_INTERN
345 void
347 /*====================*/
348  sync_array_t* arr,
349  void* object,
350  ulint type,
351  const char* file,
352  ulint line,
353  ulint* index)
354 {
355  sync_cell_t* cell;
356  os_event_t event;
357  ulint i;
358 
359  ut_a(object);
360  ut_a(index);
361 
362  sync_array_enter(arr);
363 
364  arr->res_count++;
365 
366  /* Reserve a new cell. */
367  for (i = 0; i < arr->n_cells; i++) {
368  cell = sync_array_get_nth_cell(arr, i);
369 
370  if (cell->wait_object == NULL) {
371 
372  cell->waiting = FALSE;
373  cell->wait_object = object;
374 
375  if (type == SYNC_MUTEX) {
376  cell->old_wait_mutex = static_cast<mutex_struct *>(object);
377  } else {
378  cell->old_wait_rw_lock = static_cast<rw_lock_struct *>(object);
379  }
380 
381  cell->request_type = type;
382 
383  cell->file = file;
384  cell->line = line;
385 
386  arr->n_reserved++;
387 
388  *index = i;
389 
390  sync_array_exit(arr);
391 
392  /* Make sure the event is reset and also store
393  the value of signal_count at which the event
394  was reset. */
395  event = sync_cell_get_event(cell);
396  cell->signal_count = os_event_reset(event);
397 
398  cell->reservation_time = time(NULL);
399 
400  cell->thread = os_thread_get_curr_id();
401 
402  return;
403  }
404  }
405 
406  ut_error; /* No free cell found */
407 
408  return;
409 }
410 
411 /******************************************************************/
416 UNIV_INTERN
417 void
419 /*==================*/
420  sync_array_t* arr,
421  ulint index)
422 {
423  sync_cell_t* cell;
424  os_event_t event;
425 
426  ut_a(arr);
427 
428  sync_array_enter(arr);
429 
430  cell = sync_array_get_nth_cell(arr, index);
431 
432  ut_a(cell->wait_object);
433  ut_a(!cell->waiting);
434  ut_ad(os_thread_get_curr_id() == cell->thread);
435 
436  event = sync_cell_get_event(cell);
437  cell->waiting = TRUE;
438 
439 #ifdef UNIV_SYNC_DEBUG
440 
441  /* We use simple enter to the mutex below, because if
442  we cannot acquire it at once, mutex_enter would call
443  recursively sync_array routines, leading to trouble.
444  rw_lock_debug_mutex freezes the debug lists. */
445 
446  rw_lock_debug_mutex_enter();
447 
448  if (TRUE == sync_array_detect_deadlock(arr, cell, cell, 0)) {
449 
450  fputs("########################################\n", stderr);
451  ut_error;
452  }
453 
454  rw_lock_debug_mutex_exit();
455 #endif
456  sync_array_exit(arr);
457 
458  os_event_wait_low(event, cell->signal_count);
459 
460  sync_array_free_cell(arr, index);
461 }
462 
463 /******************************************************************/
465 static
466 void
467 sync_array_cell_print(
468 /*==================*/
469  FILE* file,
470  sync_cell_t* cell)
471 {
472  mutex_t* mutex;
473  rw_lock_t* rwlock;
474  ulint type;
475  ulint writer;
476 
477  type = cell->request_type;
478 
479  fprintf(file,
480  "--Thread %lu has waited at %s line %lu"
481  " for %.2f seconds the semaphore:\n",
482  (ulong) os_thread_pf(cell->thread),
483  innobase_basename(cell->file), (ulong) cell->line,
484  difftime(time(NULL), cell->reservation_time));
485 
486  if (type == SYNC_MUTEX) {
487  /* We use old_wait_mutex in case the cell has already
488  been freed meanwhile */
489  mutex = cell->old_wait_mutex;
490 
491  fprintf(file,
492  "Mutex at %p created file %s line %lu, lock var %lu\n"
493 #ifdef UNIV_SYNC_DEBUG
494  "Last time reserved in file %s line %lu, "
495 #endif /* UNIV_SYNC_DEBUG */
496  "waiters flag %lu\n",
497  (void*) mutex, innobase_basename(mutex->cfile_name),
498  (ulong) mutex->cline,
499  (ulong) mutex->lock_word,
500 #ifdef UNIV_SYNC_DEBUG
501  mutex->file_name, (ulong) mutex->line,
502 #endif /* UNIV_SYNC_DEBUG */
503  (ulong) mutex->waiters);
504 
505  } else if (type == RW_LOCK_EX
506  || type == RW_LOCK_WAIT_EX
507  || type == RW_LOCK_SHARED) {
508 
509  fputs(type == RW_LOCK_EX ? "X-lock on"
510  : type == RW_LOCK_WAIT_EX ? "X-lock (wait_ex) on"
511  : "S-lock on", file);
512 
513  rwlock = cell->old_wait_rw_lock;
514 
515  fprintf(file,
516  " RW-latch at %p created in file %s line %lu\n",
517  (void*) rwlock, innobase_basename(rwlock->cfile_name),
518  (ulong) rwlock->cline);
519  writer = rw_lock_get_writer(rwlock);
520  if (writer != RW_LOCK_NOT_LOCKED) {
521  fprintf(file,
522  "a writer (thread id %lu) has"
523  " reserved it in mode %s",
524  (ulong) os_thread_pf(rwlock->writer_thread),
525  writer == RW_LOCK_EX
526  ? " exclusive\n"
527  : " wait exclusive\n");
528  }
529 
530  fprintf(file,
531  "number of readers %lu, waiters flag %lu, "
532  "lock_word: %lx\n"
533  "Last time read locked in file %s line %lu\n"
534  "Last time write locked in file %s line %lu\n",
535  (ulong) rw_lock_get_reader_count(rwlock),
536  (ulong) rwlock->waiters,
537  rwlock->lock_word,
539  (ulong) rwlock->last_s_line,
540  rwlock->last_x_file_name,
541  (ulong) rwlock->last_x_line);
542  } else {
543  ut_error;
544  }
545 
546  if (!cell->waiting) {
547  fputs("wait has ended\n", file);
548  }
549 }
550 
551 #ifdef UNIV_SYNC_DEBUG
552 /******************************************************************/
555 static
557 sync_array_find_thread(
558 /*===================*/
559  sync_array_t* arr,
560  os_thread_id_t thread)
561 {
562  ulint i;
563  sync_cell_t* cell;
564 
565  for (i = 0; i < arr->n_cells; i++) {
566 
567  cell = sync_array_get_nth_cell(arr, i);
568 
569  if (cell->wait_object != NULL
570  && os_thread_eq(cell->thread, thread)) {
571 
572  return(cell); /* Found */
573  }
574  }
575 
576  return(NULL); /* Not found */
577 }
578 
579 /******************************************************************/
582 static
583 ibool
584 sync_array_deadlock_step(
585 /*=====================*/
586  sync_array_t* arr,
588  sync_cell_t* start,
590  os_thread_id_t thread,
591  ulint pass,
592  ulint depth)
593 {
594  sync_cell_t* new;
595 
596  if (pass != 0) {
597  /* If pass != 0, then we do not know which threads are
598  responsible of releasing the lock, and no deadlock can
599  be detected. */
600 
601  return(FALSE);
602  }
603 
604  new = sync_array_find_thread(arr, thread);
605 
606  if (UNIV_UNLIKELY(new == start)) {
607  /* Stop running of other threads */
608 
609  ut_dbg_stop_threads = TRUE;
610 
611  /* Deadlock */
612  fputs("########################################\n"
613  "DEADLOCK of threads detected!\n", stderr);
614 
615  return(TRUE);
616 
617  } else if (new) {
618  return(sync_array_detect_deadlock(arr, start, new, depth + 1));
619  }
620  return(FALSE);
621 }
622 
623 /******************************************************************/
627 static
628 ibool
629 sync_array_detect_deadlock(
630 /*=======================*/
631  sync_array_t* arr,
633  sync_cell_t* start,
634  sync_cell_t* cell,
635  ulint depth)
636 {
637  mutex_t* mutex;
638  rw_lock_t* lock;
639  os_thread_id_t thread;
640  ibool ret;
641  rw_lock_debug_t*debug;
642 
643  ut_a(arr);
644  ut_a(start);
645  ut_a(cell);
646  ut_ad(cell->wait_object);
647  ut_ad(os_thread_get_curr_id() == start->thread);
648  ut_ad(depth < 100);
649 
650  depth++;
651 
652  if (!cell->waiting) {
653 
654  return(FALSE); /* No deadlock here */
655  }
656 
657  if (cell->request_type == SYNC_MUTEX) {
658 
659  mutex = cell->wait_object;
660 
661  if (mutex_get_lock_word(mutex) != 0) {
662 
663  thread = mutex->thread_id;
664 
665  /* Note that mutex->thread_id above may be
666  also OS_THREAD_ID_UNDEFINED, because the
667  thread which held the mutex maybe has not
668  yet updated the value, or it has already
669  released the mutex: in this case no deadlock
670  can occur, as the wait array cannot contain
671  a thread with ID_UNDEFINED value. */
672 
673  ret = sync_array_deadlock_step(arr, start, thread, 0,
674  depth);
675  if (ret) {
676  fprintf(stderr,
677  "Mutex %p owned by thread %lu file %s line %lu\n",
678  mutex, (ulong) os_thread_pf(mutex->thread_id),
679  mutex->file_name, (ulong) mutex->line);
680  sync_array_cell_print(stderr, cell);
681 
682  return(TRUE);
683  }
684  }
685 
686  return(FALSE); /* No deadlock */
687 
688  } else if (cell->request_type == RW_LOCK_EX
689  || cell->request_type == RW_LOCK_WAIT_EX) {
690 
691  lock = cell->wait_object;
692 
693  debug = UT_LIST_GET_FIRST(lock->debug_list);
694 
695  while (debug != NULL) {
696 
697  thread = debug->thread_id;
698 
699  if (((debug->lock_type == RW_LOCK_EX)
700  && !os_thread_eq(thread, cell->thread))
701  || ((debug->lock_type == RW_LOCK_WAIT_EX)
702  && !os_thread_eq(thread, cell->thread))
703  || (debug->lock_type == RW_LOCK_SHARED)) {
704 
705  /* The (wait) x-lock request can block
706  infinitely only if someone (can be also cell
707  thread) is holding s-lock, or someone
708  (cannot be cell thread) (wait) x-lock, and
709  he is blocked by start thread */
710 
711  ret = sync_array_deadlock_step(
712  arr, start, thread, debug->pass,
713  depth);
714  if (ret) {
715 print:
716  fprintf(stderr, "rw-lock %p ",
717  (void*) lock);
718  sync_array_cell_print(stderr, cell);
719  rw_lock_debug_print(stderr, debug);
720  return(TRUE);
721  }
722  }
723 
724  debug = UT_LIST_GET_NEXT(list, debug);
725  }
726 
727  return(FALSE);
728 
729  } else if (cell->request_type == RW_LOCK_SHARED) {
730 
731  lock = cell->wait_object;
732  debug = UT_LIST_GET_FIRST(lock->debug_list);
733 
734  while (debug != NULL) {
735 
736  thread = debug->thread_id;
737 
738  if ((debug->lock_type == RW_LOCK_EX)
739  || (debug->lock_type == RW_LOCK_WAIT_EX)) {
740 
741  /* The s-lock request can block infinitely
742  only if someone (can also be cell thread) is
743  holding (wait) x-lock, and he is blocked by
744  start thread */
745 
746  ret = sync_array_deadlock_step(
747  arr, start, thread, debug->pass,
748  depth);
749  if (ret) {
750  goto print;
751  }
752  }
753 
754  debug = UT_LIST_GET_NEXT(list, debug);
755  }
756 
757  return(FALSE);
758 
759  } else {
760  ut_error;
761  }
762 
763  return(TRUE); /* Execution never reaches this line: for compiler
764  fooling only */
765 }
766 #endif /* UNIV_SYNC_DEBUG */
767 
768 /******************************************************************/
770 static
771 ibool
772 sync_arr_cell_can_wake_up(
773 /*======================*/
774  sync_cell_t* cell)
775 {
776  mutex_t* mutex;
777  rw_lock_t* lock;
778 
779  if (cell->request_type == SYNC_MUTEX) {
780 
781  mutex = static_cast<mutex_t *>(cell->wait_object);
782 
783  if (mutex_get_lock_word(mutex) == 0) {
784 
785  return(TRUE);
786  }
787 
788  } else if (cell->request_type == RW_LOCK_EX) {
789 
790  lock = static_cast<rw_lock_t *>(cell->wait_object);
791 
792  if (lock->lock_word > 0) {
793  /* Either unlocked or only read locked. */
794 
795  return(TRUE);
796  }
797 
798  } else if (cell->request_type == RW_LOCK_WAIT_EX) {
799 
800  lock = static_cast<rw_lock_t *>(cell->wait_object);
801 
802  /* lock_word == 0 means all readers have left */
803  if (lock->lock_word == 0) {
804 
805  return(TRUE);
806  }
807  } else if (cell->request_type == RW_LOCK_SHARED) {
808  lock = static_cast<rw_lock_t *>(cell->wait_object);
809 
810  /* lock_word > 0 means no writer or reserved writer */
811  if (lock->lock_word > 0) {
812 
813  return(TRUE);
814  }
815  }
816 
817  return(FALSE);
818 }
819 
820 /******************************************************************/
823 UNIV_INTERN
824 void
826 /*=================*/
827  sync_array_t* arr,
828  ulint index)
829 {
830  sync_cell_t* cell;
831 
832  sync_array_enter(arr);
833 
834  cell = sync_array_get_nth_cell(arr, index);
835 
836  ut_a(cell->wait_object != NULL);
837 
838  cell->waiting = FALSE;
839  cell->wait_object = NULL;
840  cell->signal_count = 0;
841 
842  ut_a(arr->n_reserved > 0);
843  arr->n_reserved--;
844 
845  sync_array_exit(arr);
846 }
847 
848 /**********************************************************************/
850 UNIV_INTERN
851 void
853 /*========================*/
854  sync_array_t* arr)
855 {
856 #ifdef HAVE_ATOMIC_BUILTINS
857  (void) os_atomic_increment_ulint(&arr->sg_count, 1);
858 #else
859  sync_array_enter(arr);
860 
861  arr->sg_count++;
862 
863  sync_array_exit(arr);
864 #endif
865 }
866 
867 /**********************************************************************/
875 UNIV_INTERN
876 void
878 /*====================================*/
879 {
881  sync_cell_t* cell;
882  ulint count;
883  ulint i;
884  os_event_t event;
885 
886  sync_array_enter(arr);
887 
888  i = 0;
889  count = 0;
890 
891  while (count < arr->n_reserved) {
892 
893  cell = sync_array_get_nth_cell(arr, i);
894  i++;
895 
896  if (cell->wait_object == NULL) {
897  continue;
898  }
899  count++;
900 
901  if (sync_arr_cell_can_wake_up(cell)) {
902 
903  event = sync_cell_get_event(cell);
904 
905  os_event_set(event);
906  }
907 
908  }
909 
910  sync_array_exit(arr);
911 }
912 
913 /**********************************************************************/
916 UNIV_INTERN
917 ibool
919 /*========================*/
920  os_thread_id_t* waiter,
921  const void** sema)
922 {
923  sync_cell_t* cell;
924  ibool old_val;
925  ibool noticed = FALSE;
926  ulint i;
927  ulint fatal_timeout = srv_fatal_semaphore_wait_threshold;
928  ibool fatal = FALSE;
929  double longest_diff = 0;
930 
931 #ifdef UNIV_DEBUG_VALGRIND
932  /* Increase the timeouts if running under valgrind because it executes
933  extremely slowly. UNIV_DEBUG_VALGRIND does not necessary mean that
934  we are running under valgrind but we have no better way to tell.
935  See Bug#58432 innodb.innodb_bug56143 fails under valgrind
936  for an example */
937 # define SYNC_ARRAY_TIMEOUT 2400
938  fatal_timeout *= 10;
939 #else
940 # define SYNC_ARRAY_TIMEOUT 240
941 #endif
942 
943  for (i = 0; i < sync_primary_wait_array->n_cells; i++) {
944 
945  double diff;
946  void* wait_object;
947 
948  cell = sync_array_get_nth_cell(sync_primary_wait_array, i);
949 
950  wait_object = cell->wait_object;
951 
952  if (wait_object == NULL || !cell->waiting) {
953 
954  continue;
955  }
956 
957  diff = difftime(time(NULL), cell->reservation_time);
958 
959  if (diff > SYNC_ARRAY_TIMEOUT) {
960  fputs("InnoDB: Warning: a long semaphore wait:\n",
961  stderr);
962  sync_array_cell_print(stderr, cell);
963  noticed = TRUE;
964  }
965 
966  if (diff > fatal_timeout) {
967  fatal = TRUE;
968  }
969 
970  if (diff > longest_diff) {
971  longest_diff = diff;
972  *sema = wait_object;
973  *waiter = cell->thread;
974  }
975  }
976 
977  if (noticed) {
978  fprintf(stderr,
979  "InnoDB: ###### Starts InnoDB Monitor"
980  " for 30 secs to print diagnostic info:\n");
981  old_val = srv_print_innodb_monitor;
982 
983  /* If some crucial semaphore is reserved, then also the InnoDB
984  Monitor can hang, and we do not get diagnostics. Since in
985  many cases an InnoDB hang is caused by a pwrite() or a pread()
986  call hanging inside the operating system, let us print right
987  now the values of pending calls of these. */
988 
989  fprintf(stderr,
990  "InnoDB: Pending preads %lu, pwrites %lu\n",
993 
994  srv_print_innodb_monitor = TRUE;
995  os_event_set(srv_lock_timeout_thread_event);
996 
997  os_thread_sleep(30000000);
998 
999  srv_print_innodb_monitor = old_val;
1000  fprintf(stderr,
1001  "InnoDB: ###### Diagnostic info printed"
1002  " to the standard error stream\n");
1003  }
1004 
1005 #undef SYNC_ARRAY_TIMEOUT
1006 
1007  return(fatal);
1008 }
1009 
1010 /**********************************************************************/
1012 static
1013 void
1014 sync_array_output_info(
1015 /*===================*/
1016  FILE* file,
1017  sync_array_t* arr)
1019 {
1020  sync_cell_t* cell;
1021  ulint count;
1022  ulint i;
1023 
1024  fprintf(file,
1025  "OS WAIT ARRAY INFO: reservation count %ld, signal count %ld\n",
1026  (long) arr->res_count, (long) arr->sg_count);
1027  i = 0;
1028  count = 0;
1029 
1030  while (count < arr->n_reserved) {
1031 
1032  cell = sync_array_get_nth_cell(arr, i);
1033 
1034  if (cell->wait_object != NULL) {
1035  count++;
1036  sync_array_cell_print(file, cell);
1037  }
1038 
1039  i++;
1040  }
1041 }
1042 
1043 /**********************************************************************/
1045 UNIV_INTERN
1046 void
1048 /*==================*/
1049  FILE* file,
1050  sync_array_t* arr)
1051 {
1052  sync_array_enter(arr);
1053 
1054  sync_array_output_info(file, arr);
1055 
1056  sync_array_exit(arr);
1057 }
UNIV_INTERN void sync_array_validate(sync_array_t *arr)
Definition: sync0arr.cc:300
#define UT_LIST_GET_NEXT(NAME, N)
Definition: ut0lst.h:201
time_t reservation_time
Definition: sync0arr.cc:108
ulint os_file_n_pending_pwrites
Definition: os0file.cc:301
ulint os_file_n_pending_preads
Definition: os0file.cc:299
sync_cell_t * array
Definition: sync0arr.cc:124
UNIV_INTERN void os_mutex_free(os_mutex_t mutex)
Definition: os0sync.cc:840
ulint waiters
Definition: sync0sync.h:708
unsigned last_x_line
Definition: sync0rw.h:627
volatile ulint waiters
Definition: sync0rw.h:576
os_thread_id_t thread
Definition: sync0arr.cc:95
const char * file
Definition: sync0arr.cc:91
UNIV_INTERN void * ut_malloc(ulint n)
Definition: ut0mem.cc:235
sync_array_t * sync_primary_wait_array
Definition: sync0sync.cc:187
UNIV_INTERN void sync_arr_wake_threads_if_sema_free(void)
Definition: sync0arr.cc:877
ulint cline
Definition: sync0sync.h:720
UNIV_INTERN void os_mutex_enter(os_mutex_t mutex)
Definition: os0sync.cc:809
ibool ut_dbg_stop_threads
Definition: ut0dbg.cc:39
unsigned last_s_line
Definition: sync0rw.h:626
const char * last_x_file_name
Definition: sync0rw.h:617
UNIV_INLINE ulint rw_lock_get_writer(const rw_lock_t *lock)
volatile os_thread_id_t writer_thread
Definition: sync0rw.h:589
rw_lock_t * old_wait_rw_lock
Definition: sync0arr.cc:86
#define SYNC_ARRAY_OS_MUTEX
Definition: sync0arr.h:41
UNIV_INLINE lock_word_t mutex_get_lock_word(const mutex_t *mutex)
os_mutex_t os_mutex
Definition: sync0arr.cc:129
const char * innobase_basename(const char *path_name)
Definition: ha_innodb.cc:1357
UNIV_INTERN void sync_array_wait_event(sync_array_t *arr, ulint index)
Definition: sync0arr.cc:418
#define SYNC_ARRAY_MUTEX
Definition: sync0arr.h:42
const char * last_s_file_name
Definition: sync0rw.h:616
UNIV_INTERN void os_mutex_exit(os_mutex_t mutex)
Definition: os0sync.cc:824
UNIV_INTERN void os_event_set(os_event_t event)
Definition: os0sync.cc:434
UNIV_INTERN void os_thread_sleep(ulint tm)
Definition: os0thread.cc:265
UNIV_INTERN ib_int64_t os_event_reset(os_event_t event)
Definition: os0sync.cc:472
#define ut_a(EXPR)
Definition: ut0dbg.h:105
mutex_t * old_wait_mutex
Definition: sync0arr.cc:85
UNIV_INTERN sync_array_t * sync_array_create(ulint n_cells, ulint protection)
Definition: sync0arr.cc:228
const char * cfile_name
Definition: sync0rw.h:614
#define UT_LIST_GET_FIRST(BASE)
Definition: ut0lst.h:224
UNIV_INTERN os_mutex_t os_mutex_create(void)
Definition: os0sync.cc:774
UNIV_INLINE ulint rw_lock_get_reader_count(const rw_lock_t *lock)
UNIV_INTERN ibool sync_array_print_long_waits(os_thread_id_t *waiter, const void **sema) __attribute__((nonnull))
Definition: sync0arr.cc:918
UNIV_INTERN void sync_array_free_cell(sync_array_t *arr, ulint index)
Definition: sync0arr.cc:825
#define ut_ad(EXPR)
Definition: ut0dbg.h:127
os_thread_t os_thread_id_t
Definition: os0thread.h:53
unsigned cline
Definition: sync0rw.h:625
UNIV_INTERN void ut_free(void *ptr)
Definition: ut0mem.cc:294
#define ut_error
Definition: ut0dbg.h:115
UNIV_INTERN void sync_array_free(sync_array_t *arr)
Definition: sync0arr.cc:269
volatile lock_word_t lock_word
Definition: sync0sync.h:699
UNIV_INTERN void sync_array_reserve_cell(sync_array_t *arr, void *object, ulint type, const char *file, ulint line, ulint *index)
Definition: sync0arr.cc:346
ulint request_type
Definition: sync0arr.cc:89
volatile lint lock_word
Definition: sync0rw.h:574
UNIV_INTERN os_thread_id_t os_thread_get_curr_id(void)
Definition: os0thread.cc:93
UNIV_INTERN void sync_array_object_signalled(sync_array_t *arr)
Definition: sync0arr.cc:852
UNIV_INTERN void sync_array_print_info(FILE *file, sync_array_t *arr)
Definition: sync0arr.cc:1047
UNIV_INTERN void os_event_wait_low(os_event_t event, ib_int64_t reset_sig_count)
Definition: os0sync.cc:586
const char * cfile_name
Definition: sync0sync.h:719
ib_int64_t signal_count
Definition: sync0arr.cc:100
struct sync_cell_struct sync_cell_t
Definition: sync0arr.h:36
UNIV_INTERN ulint os_thread_pf(os_thread_id_t a)
Definition: os0thread.cc:72
void * wait_object
Definition: sync0arr.cc:82
UNIV_INTERN ibool os_thread_eq(os_thread_id_t a, os_thread_id_t b)
Definition: os0thread.cc:46