Drizzled Public API Documentation

sync0arr.cc
1 /*****************************************************************************
2 
3 Copyright (C) 1995, 2009, Innobase Oy. 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 
44 /*
45  WAIT ARRAY
46  ==========
47 
48 The wait array consists of cells each of which has an
49 an operating system event object created for it. The threads
50 waiting for a mutex, for example, can reserve a cell
51 in the array and suspend themselves to wait for the event
52 to become signaled. When using the wait array, remember to make
53 sure that some thread holding the synchronization object
54 will eventually know that there is a waiter in the array and
55 signal the object, to prevent infinite wait.
56 Why we chose to implement a wait array? First, to make
57 mutexes fast, we had to code our own implementation of them,
58 which only in usually uncommon cases resorts to using
59 slow operating system primitives. Then we had the choice of
60 assigning a unique OS event for each mutex, which would
61 be simpler, or using a global wait array. In some operating systems,
62 the global wait array solution is more efficient and flexible,
63 because we can do with a very small number of OS events,
64 say 200. In NT 3.51, allocating events seems to be a quadratic
65 algorithm, because 10 000 events are created fast, but
66 100 000 events takes a couple of minutes to create.
67 
68 As of 5.0.30 the above mentioned design is changed. Since now
69 OS can handle millions of wait events efficiently, we no longer
70 have this concept of each cell of wait array having one event.
71 Instead, now the event that a thread wants to wait on is embedded
72 in the wait object (mutex or rw_lock). We still keep the global
73 wait array for the sake of diagnostics and also to avoid infinite
74 wait The error_monitor thread scans the global wait array to signal
75 any waiting threads who have missed the signal. */
76 
81  void* wait_object;
88  ulint request_type;
90  const char* file;
92  ulint line;
96  ibool waiting;
99  ib_int64_t signal_count;
109 };
110 
111 /* NOTE: It is allowed for a thread to wait
112 for an event allocated for the array without owning the
113 protecting mutex (depending on the case: OS or database mutex), but
114 all changes (set or reset) to the state of the event must be made
115 while owning the mutex. */
116 
119  ulint n_reserved;
121  ulint n_cells;
124  ulint protection;
135  ulint sg_count;
137  ulint res_count;
139 };
140 
141 #ifdef UNIV_PFS_MUTEX
142 /* Key to register the mutex with performance schema */
143 UNIV_INTERN mysql_pfs_key_t syn_arr_mutex_key;
144 #endif
145 
146 #ifdef UNIV_SYNC_DEBUG
147 /******************************************************************/
151 static
152 ibool
153 sync_array_detect_deadlock(
154 /*=======================*/
155  sync_array_t* arr,
157  sync_cell_t* start,
158  sync_cell_t* cell,
159  ulint depth);
160 #endif /* UNIV_SYNC_DEBUG */
161 
162 /*****************************************************************/
165 static
167 sync_array_get_nth_cell(
168 /*====================*/
169  sync_array_t* arr,
170  ulint n)
171 {
172  ut_a(arr);
173  ut_a(n < arr->n_cells);
174 
175  return(arr->array + n);
176 }
177 
178 /******************************************************************/
180 static
181 void
182 sync_array_enter(
183 /*=============*/
184  sync_array_t* arr)
185 {
186  ulint protection;
187 
188  protection = arr->protection;
189 
190  if (protection == SYNC_ARRAY_OS_MUTEX) {
191  os_mutex_enter(arr->os_mutex);
192  } else if (protection == SYNC_ARRAY_MUTEX) {
193  mutex_enter(&(arr->mutex));
194  } else {
195  ut_error;
196  }
197 }
198 
199 /******************************************************************/
201 static
202 void
203 sync_array_exit(
204 /*============*/
205  sync_array_t* arr)
206 {
207  ulint protection;
208 
209  protection = arr->protection;
210 
211  if (protection == SYNC_ARRAY_OS_MUTEX) {
212  os_mutex_exit(arr->os_mutex);
213  } else if (protection == SYNC_ARRAY_MUTEX) {
214  mutex_exit(&(arr->mutex));
215  } else {
216  ut_error;
217  }
218 }
219 
220 /*******************************************************************/
225 UNIV_INTERN
228 /*==============*/
229  ulint n_cells,
231  ulint protection)
234 {
235  ulint sz;
236  sync_array_t* arr;
237 
238  ut_a(n_cells > 0);
239 
240  /* Allocate memory for the data structures */
241  arr = static_cast<sync_array_t *>(ut_malloc(sizeof(sync_array_t)));
242  memset(arr, 0x0, sizeof(*arr));
243 
244  sz = sizeof(sync_cell_t) * n_cells;
245  arr->array = static_cast<sync_cell_t *>(ut_malloc(sz));
246  memset(arr->array, 0x0, sz);
247 
248  arr->n_cells = n_cells;
249  arr->protection = protection;
250 
251  /* Then create the mutex to protect the wait array complex */
252  if (protection == SYNC_ARRAY_OS_MUTEX) {
253  arr->os_mutex = os_mutex_create();
254  } else if (protection == SYNC_ARRAY_MUTEX) {
255  mutex_create(syn_arr_mutex_key,
256  &arr->mutex, SYNC_NO_ORDER_CHECK);
257  } else {
258  ut_error;
259  }
260 
261  return(arr);
262 }
263 
264 /******************************************************************/
266 UNIV_INTERN
267 void
269 /*============*/
270  sync_array_t* arr)
271 {
272  ulint protection;
273 
274  ut_a(arr->n_reserved == 0);
275 
276  sync_array_validate(arr);
277 
278  protection = arr->protection;
279 
280  /* Release the mutex protecting the wait array complex */
281 
282  if (protection == SYNC_ARRAY_OS_MUTEX) {
283  os_mutex_free(arr->os_mutex);
284  } else if (protection == SYNC_ARRAY_MUTEX) {
285  mutex_free(&(arr->mutex));
286  } else {
287  ut_error;
288  }
289 
290  ut_free(arr->array);
291  ut_free(arr);
292 }
293 
294 /********************************************************************/
297 UNIV_INTERN
298 void
300 /*================*/
301  sync_array_t* arr)
302 {
303  ulint i;
304  sync_cell_t* cell;
305  ulint count = 0;
306 
307  sync_array_enter(arr);
308 
309  for (i = 0; i < arr->n_cells; i++) {
310  cell = sync_array_get_nth_cell(arr, i);
311  if (cell->wait_object != NULL) {
312  count++;
313  }
314  }
315 
316  ut_a(count == arr->n_reserved);
317 
318  sync_array_exit(arr);
319 }
320 
321 /*******************************************************************/
323 static
325 sync_cell_get_event(
326 /*================*/
327  sync_cell_t* cell)
328 {
329  ulint type = cell->request_type;
330 
331  if (type == SYNC_MUTEX) {
332  return(((mutex_t *) cell->wait_object)->event);
333  } else if (type == RW_LOCK_WAIT_EX) {
334  return(((rw_lock_t *) cell->wait_object)->wait_ex_event);
335  } else { /* RW_LOCK_SHARED and RW_LOCK_EX wait on the same event */
336  return(((rw_lock_t *) cell->wait_object)->event);
337  }
338 }
339 
340 /******************************************************************/
343 UNIV_INTERN
344 void
346 /*====================*/
347  sync_array_t* arr,
348  void* object,
349  ulint type,
350  const char* file,
351  ulint line,
352  ulint* index)
353 {
354  sync_cell_t* cell;
355  os_event_t event;
356  ulint i;
357 
358  ut_a(object);
359  ut_a(index);
360 
361  sync_array_enter(arr);
362 
363  arr->res_count++;
364 
365  /* Reserve a new cell. */
366  for (i = 0; i < arr->n_cells; i++) {
367  cell = sync_array_get_nth_cell(arr, i);
368 
369  if (cell->wait_object == NULL) {
370 
371  cell->waiting = FALSE;
372  cell->wait_object = object;
373 
374  if (type == SYNC_MUTEX) {
375  cell->old_wait_mutex = static_cast<mutex_struct *>(object);
376  } else {
377  cell->old_wait_rw_lock = static_cast<rw_lock_struct *>(object);
378  }
379 
380  cell->request_type = type;
381 
382  cell->file = file;
383  cell->line = line;
384 
385  arr->n_reserved++;
386 
387  *index = i;
388 
389  sync_array_exit(arr);
390 
391  /* Make sure the event is reset and also store
392  the value of signal_count at which the event
393  was reset. */
394  event = sync_cell_get_event(cell);
395  cell->signal_count = os_event_reset(event);
396 
397  cell->reservation_time = time(NULL);
398 
399  cell->thread = os_thread_get_curr_id();
400 
401  return;
402  }
403  }
404 
405  ut_error; /* No free cell found */
406 
407  return;
408 }
409 
410 /******************************************************************/
415 UNIV_INTERN
416 void
418 /*==================*/
419  sync_array_t* arr,
420  ulint index)
421 {
422  sync_cell_t* cell;
423  os_event_t event;
424 
425  ut_a(arr);
426 
427  sync_array_enter(arr);
428 
429  cell = sync_array_get_nth_cell(arr, index);
430 
431  ut_a(cell->wait_object);
432  ut_a(!cell->waiting);
433  ut_ad(os_thread_get_curr_id() == cell->thread);
434 
435  event = sync_cell_get_event(cell);
436  cell->waiting = TRUE;
437 
438 #ifdef UNIV_SYNC_DEBUG
439 
440  /* We use simple enter to the mutex below, because if
441  we cannot acquire it at once, mutex_enter would call
442  recursively sync_array routines, leading to trouble.
443  rw_lock_debug_mutex freezes the debug lists. */
444 
445  rw_lock_debug_mutex_enter();
446 
447  if (TRUE == sync_array_detect_deadlock(arr, cell, cell, 0)) {
448 
449  fputs("########################################\n", stderr);
450  ut_error;
451  }
452 
453  rw_lock_debug_mutex_exit();
454 #endif
455  sync_array_exit(arr);
456 
457  os_event_wait_low(event, cell->signal_count);
458 
459  sync_array_free_cell(arr, index);
460 }
461 
462 /******************************************************************/
464 static
465 void
466 sync_array_cell_print(
467 /*==================*/
468  FILE* file,
469  sync_cell_t* cell)
470 {
471  mutex_t* mutex;
472  rw_lock_t* rwlock;
473  ulint type;
474  ulint writer;
475 
476  type = cell->request_type;
477 
478  fprintf(file,
479  "--Thread %lu has waited at %s line %lu"
480  " for %.2f seconds the semaphore:\n",
481  (ulong) os_thread_pf(cell->thread), cell->file,
482  (ulong) cell->line,
483  difftime(time(NULL), cell->reservation_time));
484 
485  if (type == SYNC_MUTEX) {
486  /* We use old_wait_mutex in case the cell has already
487  been freed meanwhile */
488  mutex = cell->old_wait_mutex;
489 
490  fprintf(file,
491  "Mutex at %p created file %s line %lu, lock var %lu\n"
492 #ifdef UNIV_SYNC_DEBUG
493  "Last time reserved in file %s line %lu, "
494 #endif /* UNIV_SYNC_DEBUG */
495  "waiters flag %lu\n",
496  (void*) mutex, mutex->cfile_name, (ulong) mutex->cline,
497  (ulong) mutex->lock_word,
498 #ifdef UNIV_SYNC_DEBUG
499  mutex->file_name, (ulong) mutex->line,
500 #endif /* UNIV_SYNC_DEBUG */
501  (ulong) mutex->waiters);
502 
503  } else if (type == RW_LOCK_EX
504  || type == RW_LOCK_WAIT_EX
505  || type == RW_LOCK_SHARED) {
506 
507  fputs(type == RW_LOCK_EX ? "X-lock on"
508  : type == RW_LOCK_WAIT_EX ? "X-lock (wait_ex) on"
509  : "S-lock on", file);
510 
511  rwlock = cell->old_wait_rw_lock;
512 
513  fprintf(file,
514  " RW-latch at %p created in file %s line %lu\n",
515  (void*) rwlock, rwlock->cfile_name,
516  (ulong) rwlock->cline);
517  writer = rw_lock_get_writer(rwlock);
518  if (writer != RW_LOCK_NOT_LOCKED) {
519  fprintf(file,
520  "a writer (thread id %lu) has"
521  " reserved it in mode %s",
522  (ulong) os_thread_pf(rwlock->writer_thread),
523  writer == RW_LOCK_EX
524  ? " exclusive\n"
525  : " wait exclusive\n");
526  }
527 
528  fprintf(file,
529  "number of readers %lu, waiters flag %lu, "
530  "lock_word: %lx\n"
531  "Last time read locked in file %s line %lu\n"
532  "Last time write locked in file %s line %lu\n",
533  (ulong) rw_lock_get_reader_count(rwlock),
534  (ulong) rwlock->waiters,
535  rwlock->lock_word,
536  rwlock->last_s_file_name,
537  (ulong) rwlock->last_s_line,
538  rwlock->last_x_file_name,
539  (ulong) rwlock->last_x_line);
540  } else {
541  ut_error;
542  }
543 
544  if (!cell->waiting) {
545  fputs("wait has ended\n", file);
546  }
547 }
548 
549 #ifdef UNIV_SYNC_DEBUG
550 /******************************************************************/
553 static
555 sync_array_find_thread(
556 /*===================*/
557  sync_array_t* arr,
558  os_thread_id_t thread)
559 {
560  ulint i;
561  sync_cell_t* cell;
562 
563  for (i = 0; i < arr->n_cells; i++) {
564 
565  cell = sync_array_get_nth_cell(arr, i);
566 
567  if (cell->wait_object != NULL
568  && os_thread_eq(cell->thread, thread)) {
569 
570  return(cell); /* Found */
571  }
572  }
573 
574  return(NULL); /* Not found */
575 }
576 
577 /******************************************************************/
580 static
581 ibool
582 sync_array_deadlock_step(
583 /*=====================*/
584  sync_array_t* arr,
586  sync_cell_t* start,
588  os_thread_id_t thread,
589  ulint pass,
590  ulint depth)
591 {
592  sync_cell_t* new;
593  ibool ret;
594 
595  depth++;
596 
597  if (pass != 0) {
598  /* If pass != 0, then we do not know which threads are
599  responsible of releasing the lock, and no deadlock can
600  be detected. */
601 
602  return(FALSE);
603  }
604 
605  new = sync_array_find_thread(arr, thread);
606 
607  if (new == start) {
608  /* Stop running of other threads */
609 
610  ut_dbg_stop_threads = TRUE;
611 
612  /* Deadlock */
613  fputs("########################################\n"
614  "DEADLOCK of threads detected!\n", stderr);
615 
616  return(TRUE);
617 
618  } else if (new) {
619  ret = sync_array_detect_deadlock(arr, start, new, depth);
620 
621  if (ret) {
622  return(TRUE);
623  }
624  }
625  return(FALSE);
626 }
627 
628 /******************************************************************/
632 static
633 ibool
634 sync_array_detect_deadlock(
635 /*=======================*/
636  sync_array_t* arr,
638  sync_cell_t* start,
639  sync_cell_t* cell,
640  ulint depth)
641 {
642  mutex_t* mutex;
643  rw_lock_t* lock;
644  os_thread_id_t thread;
645  ibool ret;
646  rw_lock_debug_t*debug;
647 
648  ut_a(arr);
649  ut_a(start);
650  ut_a(cell);
651  ut_ad(cell->wait_object);
652  ut_ad(os_thread_get_curr_id() == start->thread);
653  ut_ad(depth < 100);
654 
655  depth++;
656 
657  if (!cell->waiting) {
658 
659  return(FALSE); /* No deadlock here */
660  }
661 
662  if (cell->request_type == SYNC_MUTEX) {
663 
664  mutex = cell->wait_object;
665 
666  if (mutex_get_lock_word(mutex) != 0) {
667 
668  thread = mutex->thread_id;
669 
670  /* Note that mutex->thread_id above may be
671  also OS_THREAD_ID_UNDEFINED, because the
672  thread which held the mutex maybe has not
673  yet updated the value, or it has already
674  released the mutex: in this case no deadlock
675  can occur, as the wait array cannot contain
676  a thread with ID_UNDEFINED value. */
677 
678  ret = sync_array_deadlock_step(arr, start, thread, 0,
679  depth);
680  if (ret) {
681  fprintf(stderr,
682  "Mutex %p owned by thread %lu file %s line %lu\n",
683  mutex, (ulong) os_thread_pf(mutex->thread_id),
684  mutex->file_name, (ulong) mutex->line);
685  sync_array_cell_print(stderr, cell);
686 
687  return(TRUE);
688  }
689  }
690 
691  return(FALSE); /* No deadlock */
692 
693  } else if (cell->request_type == RW_LOCK_EX
694  || cell->request_type == RW_LOCK_WAIT_EX) {
695 
696  lock = cell->wait_object;
697 
698  debug = UT_LIST_GET_FIRST(lock->debug_list);
699 
700  while (debug != NULL) {
701 
702  thread = debug->thread_id;
703 
704  if (((debug->lock_type == RW_LOCK_EX)
705  && !os_thread_eq(thread, cell->thread))
706  || ((debug->lock_type == RW_LOCK_WAIT_EX)
707  && !os_thread_eq(thread, cell->thread))
708  || (debug->lock_type == RW_LOCK_SHARED)) {
709 
710  /* The (wait) x-lock request can block
711  infinitely only if someone (can be also cell
712  thread) is holding s-lock, or someone
713  (cannot be cell thread) (wait) x-lock, and
714  he is blocked by start thread */
715 
716  ret = sync_array_deadlock_step(
717  arr, start, thread, debug->pass,
718  depth);
719  if (ret) {
720 print:
721  fprintf(stderr, "rw-lock %p ",
722  (void*) lock);
723  sync_array_cell_print(stderr, cell);
724  rw_lock_debug_print(debug);
725  return(TRUE);
726  }
727  }
728 
729  debug = UT_LIST_GET_NEXT(list, debug);
730  }
731 
732  return(FALSE);
733 
734  } else if (cell->request_type == RW_LOCK_SHARED) {
735 
736  lock = cell->wait_object;
737  debug = UT_LIST_GET_FIRST(lock->debug_list);
738 
739  while (debug != NULL) {
740 
741  thread = debug->thread_id;
742 
743  if ((debug->lock_type == RW_LOCK_EX)
744  || (debug->lock_type == RW_LOCK_WAIT_EX)) {
745 
746  /* The s-lock request can block infinitely
747  only if someone (can also be cell thread) is
748  holding (wait) x-lock, and he is blocked by
749  start thread */
750 
751  ret = sync_array_deadlock_step(
752  arr, start, thread, debug->pass,
753  depth);
754  if (ret) {
755  goto print;
756  }
757  }
758 
759  debug = UT_LIST_GET_NEXT(list, debug);
760  }
761 
762  return(FALSE);
763 
764  } else {
765  ut_error;
766  }
767 
768  return(TRUE); /* Execution never reaches this line: for compiler
769  fooling only */
770 }
771 #endif /* UNIV_SYNC_DEBUG */
772 
773 /******************************************************************/
775 static
776 ibool
777 sync_arr_cell_can_wake_up(
778 /*======================*/
779  sync_cell_t* cell)
780 {
781  mutex_t* mutex;
782  rw_lock_t* lock;
783 
784  if (cell->request_type == SYNC_MUTEX) {
785 
786  mutex = static_cast<mutex_t *>(cell->wait_object);
787 
788  if (mutex_get_lock_word(mutex) == 0) {
789 
790  return(TRUE);
791  }
792 
793  } else if (cell->request_type == RW_LOCK_EX) {
794 
795  lock = static_cast<rw_lock_t *>(cell->wait_object);
796 
797  if (lock->lock_word > 0) {
798  /* Either unlocked or only read locked. */
799 
800  return(TRUE);
801  }
802 
803  } else if (cell->request_type == RW_LOCK_WAIT_EX) {
804 
805  lock = static_cast<rw_lock_t *>(cell->wait_object);
806 
807  /* lock_word == 0 means all readers have left */
808  if (lock->lock_word == 0) {
809 
810  return(TRUE);
811  }
812  } else if (cell->request_type == RW_LOCK_SHARED) {
813  lock = static_cast<rw_lock_t *>(cell->wait_object);
814 
815  /* lock_word > 0 means no writer or reserved writer */
816  if (lock->lock_word > 0) {
817 
818  return(TRUE);
819  }
820  }
821 
822  return(FALSE);
823 }
824 
825 /******************************************************************/
828 UNIV_INTERN
829 void
831 /*=================*/
832  sync_array_t* arr,
833  ulint index)
834 {
835  sync_cell_t* cell;
836 
837  sync_array_enter(arr);
838 
839  cell = sync_array_get_nth_cell(arr, index);
840 
841  ut_a(cell->wait_object != NULL);
842 
843  cell->waiting = FALSE;
844  cell->wait_object = NULL;
845  cell->signal_count = 0;
846 
847  ut_a(arr->n_reserved > 0);
848  arr->n_reserved--;
849 
850  sync_array_exit(arr);
851 }
852 
853 /**********************************************************************/
855 UNIV_INTERN
856 void
858 /*========================*/
859  sync_array_t* arr)
860 {
861 #ifdef HAVE_ATOMIC_BUILTINS
862  (void) os_atomic_increment_ulint(&arr->sg_count, 1);
863 #else
864  sync_array_enter(arr);
865 
866  arr->sg_count++;
867 
868  sync_array_exit(arr);
869 #endif
870 }
871 
872 /**********************************************************************/
880 UNIV_INTERN
881 void
883 /*====================================*/
884 {
886  sync_cell_t* cell;
887  ulint count;
888  ulint i;
889  os_event_t event;
890 
891  sync_array_enter(arr);
892 
893  i = 0;
894  count = 0;
895 
896  while (count < arr->n_reserved) {
897 
898  cell = sync_array_get_nth_cell(arr, i);
899  i++;
900 
901  if (cell->wait_object == NULL) {
902  continue;
903  }
904  count++;
905 
906  if (sync_arr_cell_can_wake_up(cell)) {
907 
908  event = sync_cell_get_event(cell);
909 
910  os_event_set(event);
911  }
912 
913  }
914 
915  sync_array_exit(arr);
916 }
917 
918 /**********************************************************************/
921 UNIV_INTERN
922 ibool
924 /*=============================*/
925 {
926  sync_cell_t* cell;
927  ibool old_val;
928  ibool noticed = FALSE;
929  ulint i;
930  ulint fatal_timeout = srv_fatal_semaphore_wait_threshold;
931  ibool fatal = FALSE;
932 
933  for (i = 0; i < sync_primary_wait_array->n_cells; i++) {
934 
935  cell = sync_array_get_nth_cell(sync_primary_wait_array, i);
936 
937  if (cell->wait_object != NULL && cell->waiting
938  && difftime(time(NULL), cell->reservation_time) > 240) {
939  fputs("InnoDB: Warning: a long semaphore wait:\n",
940  stderr);
941  sync_array_cell_print(stderr, cell);
942  noticed = TRUE;
943  }
944 
945  if (cell->wait_object != NULL && cell->waiting
946  && difftime(time(NULL), cell->reservation_time)
947  > fatal_timeout) {
948  fatal = TRUE;
949  }
950  }
951 
952  if (noticed) {
953  fprintf(stderr,
954  "InnoDB: ###### Starts InnoDB Monitor"
955  " for 30 secs to print diagnostic info:\n");
956  old_val = srv_print_innodb_monitor;
957 
958  /* If some crucial semaphore is reserved, then also the InnoDB
959  Monitor can hang, and we do not get diagnostics. Since in
960  many cases an InnoDB hang is caused by a pwrite() or a pread()
961  call hanging inside the operating system, let us print right
962  now the values of pending calls of these. */
963 
964  fprintf(stderr,
965  "InnoDB: Pending preads %lu, pwrites %lu\n",
968 
969  srv_print_innodb_monitor = TRUE;
970  os_event_set(srv_lock_timeout_thread_event);
971 
972  os_thread_sleep(30000000);
973 
974  srv_print_innodb_monitor = old_val;
975  fprintf(stderr,
976  "InnoDB: ###### Diagnostic info printed"
977  " to the standard error stream\n");
978  }
979 
980  return(fatal);
981 }
982 
983 /**********************************************************************/
985 static
986 void
987 sync_array_output_info(
988 /*===================*/
989  FILE* file,
990  sync_array_t* arr)
992 {
993  sync_cell_t* cell;
994  ulint count;
995  ulint i;
996 
997  fprintf(file,
998  "OS WAIT ARRAY INFO: reservation count %ld, signal count %ld\n",
999  (long) arr->res_count, (long) arr->sg_count);
1000  i = 0;
1001  count = 0;
1002 
1003  while (count < arr->n_reserved) {
1004 
1005  cell = sync_array_get_nth_cell(arr, i);
1006 
1007  if (cell->wait_object != NULL) {
1008  count++;
1009  sync_array_cell_print(file, cell);
1010  }
1011 
1012  i++;
1013  }
1014 }
1015 
1016 /**********************************************************************/
1018 UNIV_INTERN
1019 void
1021 /*==================*/
1022  FILE* file,
1023  sync_array_t* arr)
1024 {
1025  sync_array_enter(arr);
1026 
1027  sync_array_output_info(file, arr);
1028 
1029  sync_array_exit(arr);
1030 }