~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/innobase/sync/sync0sync.c

  • Committer: Eric Day
  • Date: 2009-10-31 21:53:33 UTC
  • mfrom: (1200 staging)
  • mto: This revision was merged to the branch mainline in revision 1202.
  • Revision ID: eday@oddments.org-20091031215333-j94bjoanwmi68p6f
Merged trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
 
24
24
*****************************************************************************/
25
25
 
26
 
/******************************************************
 
26
/**************************************************//**
 
27
@file sync/sync0sync.c
27
28
Mutex, the basic synchronization primitive
28
29
 
29
30
Created 9/5/1995 Heikki Tuuri
163
164
 
164
165
/* Number of spin waits on mutexes: for performance monitoring */
165
166
 
166
 
/* round=one iteration of a spin loop */
167
 
UNIV_INTERN ib_int64_t  mutex_spin_round_count          = 0;
168
 
UNIV_INTERN ib_int64_t  mutex_spin_wait_count           = 0;
169
 
UNIV_INTERN ib_int64_t  mutex_os_wait_count             = 0;
 
167
/** The number of iterations in the mutex_spin_wait() spin loop.
 
168
Intended for performance monitoring. */
 
169
static ib_int64_t       mutex_spin_round_count          = 0;
 
170
/** The number of mutex_spin_wait() calls.  Intended for
 
171
performance monitoring. */
 
172
static ib_int64_t       mutex_spin_wait_count           = 0;
 
173
/** The number of OS waits in mutex_spin_wait().  Intended for
 
174
performance monitoring. */
 
175
static ib_int64_t       mutex_os_wait_count             = 0;
 
176
/** The number of mutex_exit() calls. Intended for performance
 
177
monitoring. */
170
178
UNIV_INTERN ib_int64_t  mutex_exit_count                = 0;
171
179
 
172
 
/* The global array of wait cells for implementation of the database's own
 
180
/** The global array of wait cells for implementation of the database's own
173
181
mutexes and read-write locks */
174
182
UNIV_INTERN sync_array_t*       sync_primary_wait_array;
175
183
 
176
 
/* This variable is set to TRUE when sync_init is called */
 
184
/** This variable is set to TRUE when sync_init is called */
177
185
UNIV_INTERN ibool       sync_initialized        = FALSE;
178
186
 
179
 
 
 
187
/** An acquired mutex or rw-lock and its level in the latching order */
180
188
typedef struct sync_level_struct        sync_level_t;
 
189
/** Mutexes or rw-locks held by a thread */
181
190
typedef struct sync_thread_struct       sync_thread_t;
182
191
 
183
192
#ifdef UNIV_SYNC_DEBUG
184
 
/* The latch levels currently owned by threads are stored in this data
 
193
/** The latch levels currently owned by threads are stored in this data
185
194
structure; the size of this array is OS_THREAD_MAX_N */
186
195
 
187
196
UNIV_INTERN sync_thread_t*      sync_thread_level_arrays;
188
197
 
189
 
/* Mutex protecting sync_thread_level_arrays */
 
198
/** Mutex protecting sync_thread_level_arrays */
190
199
UNIV_INTERN mutex_t             sync_thread_mutex;
191
200
#endif /* UNIV_SYNC_DEBUG */
192
201
 
193
 
/* Global list of database mutexes (not OS mutexes) created. */
 
202
/** Global list of database mutexes (not OS mutexes) created. */
194
203
UNIV_INTERN ut_list_base_node_t  mutex_list;
195
204
 
196
 
/* Mutex protecting the mutex_list variable */
 
205
/** Mutex protecting the mutex_list variable */
197
206
UNIV_INTERN mutex_t mutex_list_mutex;
198
207
 
199
208
#ifdef UNIV_SYNC_DEBUG
200
 
/* Latching order checks start when this is set TRUE */
 
209
/** Latching order checks start when this is set TRUE */
201
210
UNIV_INTERN ibool       sync_order_checks_on    = FALSE;
202
211
#endif /* UNIV_SYNC_DEBUG */
203
212
 
 
213
/** Mutexes or rw-locks held by a thread */
204
214
struct sync_thread_struct{
205
 
        os_thread_id_t  id;     /* OS thread id */
206
 
        sync_level_t*   levels; /* level array for this thread; if this is NULL
207
 
                                this slot is unused */
 
215
        os_thread_id_t  id;     /*!< OS thread id */
 
216
        sync_level_t*   levels; /*!< level array for this thread; if
 
217
                                this is NULL this slot is unused */
208
218
};
209
219
 
210
 
/* Number of slots reserved for each OS thread in the sync level array */
 
220
/** Number of slots reserved for each OS thread in the sync level array */
211
221
#define SYNC_THREAD_N_LEVELS    10000
212
222
 
 
223
/** An acquired mutex or rw-lock and its level in the latching order */
213
224
struct sync_level_struct{
214
 
        void*   latch;  /* pointer to a mutex or an rw-lock; NULL means that
 
225
        void*   latch;  /*!< pointer to a mutex or an rw-lock; NULL means that
215
226
                        the slot is empty */
216
 
        ulint   level;  /* level of the latch in the latching order */
 
227
        ulint   level;  /*!< level of the latch in the latching order */
217
228
};
218
229
 
219
 
/**********************************************************************
 
230
/******************************************************************//**
220
231
Creates, or rather, initializes a mutex object in a specified memory
221
232
location (which must be appropriately aligned). The mutex is initialized
222
233
in the reset state. Explicit freeing of the mutex with mutex_free is
225
236
void
226
237
mutex_create_func(
227
238
/*==============*/
228
 
        mutex_t*        mutex,          /* in: pointer to memory */
 
239
        mutex_t*        mutex,          /*!< in: pointer to memory */
229
240
#ifdef UNIV_DEBUG
230
 
        const char*     cmutex_name,    /* in: mutex name */
 
241
        const char*     cmutex_name,    /*!< in: mutex name */
231
242
# ifdef UNIV_SYNC_DEBUG
232
 
        ulint           level,          /* in: level */
 
243
        ulint           level,          /*!< in: level */
233
244
# endif /* UNIV_SYNC_DEBUG */
234
245
#endif /* UNIV_DEBUG */
235
 
        const char*     cfile_name,     /* in: file name where created */
236
 
        ulint           cline)          /* in: file line where created */
 
246
        const char*     cfile_name,     /*!< in: file name where created */
 
247
        ulint           cline)          /*!< in: file line where created */
237
248
{
238
 
#if defined(_WIN32) && defined(UNIV_CAN_USE_X86_ASSEMBLER)
239
 
        mutex_reset_lock_word(mutex);
240
 
#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
 
249
#if defined(HAVE_ATOMIC_BUILTINS)
241
250
        mutex_reset_lock_word(mutex);
242
251
#else
243
252
        os_fast_mutex_init(&(mutex->os_fast_mutex));
255
264
#endif /* UNIV_SYNC_DEBUG */
256
265
        mutex->cfile_name = cfile_name;
257
266
        mutex->cline = cline;
258
 
#ifndef UNIV_HOTBACKUP
259
267
        mutex->count_os_wait = 0;
260
 
# ifdef UNIV_DEBUG
 
268
#ifdef UNIV_DEBUG
261
269
        mutex->cmutex_name=       cmutex_name;
262
270
        mutex->count_using=       0;
263
271
        mutex->mutex_type=        0;
266
274
        mutex->count_spin_loop= 0;
267
275
        mutex->count_spin_rounds=   0;
268
276
        mutex->count_os_yield=  0;
269
 
# endif /* UNIV_DEBUG */
270
 
#endif /* !UNIV_HOTBACKUP */
 
277
#endif /* UNIV_DEBUG */
271
278
 
272
279
        /* Check that lock_word is aligned; this is important on Intel */
273
280
        ut_ad(((ulint)(&(mutex->lock_word))) % 4 == 0);
293
300
        mutex_exit(&mutex_list_mutex);
294
301
}
295
302
 
296
 
/**********************************************************************
 
303
/******************************************************************//**
297
304
Calling this function is obligatory only if the memory buffer containing
298
305
the mutex is freed. Removes a mutex object from the mutex list. The mutex
299
306
is checked to be in the reset state. */
301
308
void
302
309
mutex_free(
303
310
/*=======*/
304
 
        mutex_t*        mutex)  /* in: mutex */
 
311
        mutex_t*        mutex)  /*!< in: mutex */
305
312
{
306
313
        ut_ad(mutex_validate(mutex));
307
314
        ut_a(mutex_get_lock_word(mutex) == 0);
329
336
 
330
337
        os_event_free(mutex->event);
331
338
 
332
 
#if defined(_WIN32) && defined(UNIV_CAN_USE_X86_ASSEMBLER)
333
 
#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
334
 
#else
 
339
#if !defined(HAVE_ATOMIC_BUILTINS)
335
340
        os_fast_mutex_free(&(mutex->os_fast_mutex));
336
341
#endif
337
342
        /* If we free the mutex protecting the mutex list (freeing is
342
347
#endif /* UNIV_DEBUG */
343
348
}
344
349
 
345
 
/************************************************************************
 
350
/********************************************************************//**
346
351
NOTE! Use the corresponding macro in the header file, not this function
347
352
directly. Tries to lock the mutex for the current thread. If the lock is not
348
 
acquired immediately, returns with return value 1. */
 
353
acquired immediately, returns with return value 1.
 
354
@return 0 if succeed, 1 if not */
349
355
UNIV_INTERN
350
356
ulint
351
357
mutex_enter_nowait_func(
352
358
/*====================*/
353
 
                                        /* out: 0 if succeed, 1 if not */
354
 
        mutex_t*        mutex,          /* in: pointer to mutex */
 
359
        mutex_t*        mutex,          /*!< in: pointer to mutex */
355
360
        const char*     file_name __attribute__((unused)),
356
 
                                        /* in: file name where mutex
 
361
                                        /*!< in: file name where mutex
357
362
                                        requested */
358
363
        ulint           line __attribute__((unused)))
359
 
                                        /* in: line where requested */
 
364
                                        /*!< in: line where requested */
360
365
{
361
366
        ut_ad(mutex_validate(mutex));
362
367
 
374
379
}
375
380
 
376
381
#ifdef UNIV_DEBUG
377
 
/**********************************************************************
378
 
Checks that the mutex has been initialized. */
 
382
/******************************************************************//**
 
383
Checks that the mutex has been initialized.
 
384
@return TRUE */
379
385
UNIV_INTERN
380
386
ibool
381
387
mutex_validate(
382
388
/*===========*/
383
 
        const mutex_t*  mutex)
 
389
        const mutex_t*  mutex)  /*!< in: mutex */
384
390
{
385
391
        ut_a(mutex);
386
392
        ut_a(mutex->magic_n == MUTEX_MAGIC_N);
388
394
        return(TRUE);
389
395
}
390
396
 
391
 
/**********************************************************************
 
397
/******************************************************************//**
392
398
Checks that the current thread owns the mutex. Works only in the debug
393
 
version. */
 
399
version.
 
400
@return TRUE if owns */
394
401
UNIV_INTERN
395
402
ibool
396
403
mutex_own(
397
404
/*======*/
398
 
                                /* out: TRUE if owns */
399
 
        const mutex_t*  mutex)  /* in: mutex */
 
405
        const mutex_t*  mutex)  /*!< in: mutex */
400
406
{
401
407
        ut_ad(mutex_validate(mutex));
402
408
 
405
411
}
406
412
#endif /* UNIV_DEBUG */
407
413
 
408
 
/**********************************************************************
 
414
/******************************************************************//**
409
415
Sets the waiters field in a mutex. */
410
416
UNIV_INTERN
411
417
void
412
418
mutex_set_waiters(
413
419
/*==============*/
414
 
        mutex_t*        mutex,  /* in: mutex */
415
 
        ulint           n)      /* in: value to set */
 
420
        mutex_t*        mutex,  /*!< in: mutex */
 
421
        ulint           n)      /*!< in: value to set */
416
422
{
417
423
        volatile ulint* ptr;            /* declared volatile to ensure that
418
424
                                        the value is stored to memory */
424
430
                                word in memory is atomic */
425
431
}
426
432
 
427
 
/**********************************************************************
 
433
/******************************************************************//**
428
434
Reserves a mutex for the current thread. If the mutex is reserved, the
429
435
function spins a preset time (controlled by SYNC_SPIN_ROUNDS), waiting
430
436
for the mutex before suspending the thread. */
432
438
void
433
439
mutex_spin_wait(
434
440
/*============*/
435
 
        mutex_t*        mutex,          /* in: pointer to mutex */
436
 
        const char*     file_name,      /* in: file name where mutex
 
441
        mutex_t*        mutex,          /*!< in: pointer to mutex */
 
442
        const char*     file_name,      /*!< in: file name where mutex
437
443
                                        requested */
438
 
        ulint           line)           /* in: line where requested */
 
444
        ulint           line)           /*!< in: line where requested */
439
445
{
440
446
        ulint      index; /* index of the reserved wait cell */
441
447
        ulint      i;     /* spin round count */
442
 
#if defined UNIV_DEBUG && !defined UNIV_HOTBACKUP
 
448
#ifdef UNIV_DEBUG
443
449
        ib_int64_t lstart_time = 0, lfinish_time; /* for timing os_wait */
444
450
        ulint ltime_diff;
445
451
        ulint sec;
446
452
        ulint ms;
447
453
        uint timer_started = 0;
448
 
#endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */
 
454
#endif /* UNIV_DEBUG */
449
455
        ut_ad(mutex);
450
456
 
451
457
        /* This update is not thread safe, but we don't mind if the count
465
471
        a memory word. */
466
472
 
467
473
spin_loop:
468
 
#if defined UNIV_DEBUG && !defined UNIV_HOTBACKUP
469
 
        mutex->count_spin_loop++;
470
 
#endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */
 
474
        ut_d(mutex->count_spin_loop++);
471
475
 
472
476
        while (mutex_get_lock_word(mutex) != 0 && i < SYNC_SPIN_ROUNDS) {
473
477
                if (srv_spin_wait_delay) {
478
482
        }
479
483
 
480
484
        if (i == SYNC_SPIN_ROUNDS) {
481
 
#if defined UNIV_DEBUG && !defined UNIV_HOTBACKUP
 
485
#ifdef UNIV_DEBUG
482
486
                mutex->count_os_yield++;
483
 
                if (timed_mutexes == 1 && timer_started==0) {
 
487
#ifndef UNIV_HOTBACKUP
 
488
                if (timed_mutexes && timer_started == 0) {
484
489
                        ut_usectime(&sec, &ms);
485
490
                        lstart_time= (ib_int64_t)sec * 1000000 + ms;
486
491
                        timer_started = 1;
487
492
                }
488
 
#endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */
 
493
#endif /* UNIV_HOTBACKUP */
 
494
#endif /* UNIV_DEBUG */
489
495
                os_thread_yield();
490
496
        }
491
497
 
499
505
 
500
506
        mutex_spin_round_count += i;
501
507
 
502
 
#if defined UNIV_DEBUG && !defined UNIV_HOTBACKUP
503
 
        mutex->count_spin_rounds += i;
504
 
#endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */
 
508
        ut_d(mutex->count_spin_rounds += i);
505
509
 
506
510
        if (mutex_test_and_set(mutex) == 0) {
507
511
                /* Succeeded! */
578
582
 
579
583
        mutex_os_wait_count++;
580
584
 
581
 
#ifndef UNIV_HOTBACKUP
582
585
        mutex->count_os_wait++;
583
 
# ifdef UNIV_DEBUG
 
586
#ifdef UNIV_DEBUG
584
587
        /* !!!!! Sometimes os_wait can be called without os_thread_yield */
585
 
 
586
 
        if (timed_mutexes == 1 && timer_started==0) {
 
588
#ifndef UNIV_HOTBACKUP
 
589
        if (timed_mutexes == 1 && timer_started == 0) {
587
590
                ut_usectime(&sec, &ms);
588
591
                lstart_time= (ib_int64_t)sec * 1000000 + ms;
589
592
                timer_started = 1;
590
593
        }
591
 
# endif /* UNIV_DEBUG */
592
 
#endif /* !UNIV_HOTBACKUP */
 
594
#endif /* UNIV_HOTBACKUP */
 
595
#endif /* UNIV_DEBUG */
593
596
 
594
597
        sync_array_wait_event(sync_primary_wait_array, index);
595
598
        goto mutex_loop;
596
599
 
597
600
finish_timing:
598
 
#if defined UNIV_DEBUG && !defined UNIV_HOTBACKUP
 
601
#ifdef UNIV_DEBUG
599
602
        if (timed_mutexes == 1 && timer_started==1) {
600
603
                ut_usectime(&sec, &ms);
601
604
                lfinish_time= (ib_int64_t)sec * 1000000 + ms;
607
610
                        mutex->lmax_spent_time= ltime_diff;
608
611
                }
609
612
        }
610
 
#endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */
 
613
#endif /* UNIV_DEBUG */
611
614
        return;
612
615
}
613
616
 
614
 
/**********************************************************************
 
617
/******************************************************************//**
615
618
Releases the threads waiting in the primary wait array for this mutex. */
616
619
UNIV_INTERN
617
620
void
618
621
mutex_signal_object(
619
622
/*================*/
620
 
        mutex_t*        mutex)  /* in: mutex */
 
623
        mutex_t*        mutex)  /*!< in: mutex */
621
624
{
622
625
        mutex_set_waiters(mutex, 0);
623
626
 
628
631
}
629
632
 
630
633
#ifdef UNIV_SYNC_DEBUG
631
 
/**********************************************************************
 
634
/******************************************************************//**
632
635
Sets the debug information for a reserved mutex. */
633
636
UNIV_INTERN
634
637
void
635
638
mutex_set_debug_info(
636
639
/*=================*/
637
 
        mutex_t*        mutex,          /* in: mutex */
638
 
        const char*     file_name,      /* in: file where requested */
639
 
        ulint           line)           /* in: line where requested */
 
640
        mutex_t*        mutex,          /*!< in: mutex */
 
641
        const char*     file_name,      /*!< in: file where requested */
 
642
        ulint           line)           /*!< in: line where requested */
640
643
{
641
644
        ut_ad(mutex);
642
645
        ut_ad(file_name);
647
650
        mutex->line      = line;
648
651
}
649
652
 
650
 
/**********************************************************************
 
653
/******************************************************************//**
651
654
Gets the debug information for a reserved mutex. */
652
655
UNIV_INTERN
653
656
void
654
657
mutex_get_debug_info(
655
658
/*=================*/
656
 
        mutex_t*        mutex,          /* in: mutex */
657
 
        const char**    file_name,      /* out: file where requested */
658
 
        ulint*          line,           /* out: line where requested */
659
 
        os_thread_id_t* thread_id)      /* out: id of the thread which owns
 
659
        mutex_t*        mutex,          /*!< in: mutex */
 
660
        const char**    file_name,      /*!< out: file where requested */
 
661
        ulint*          line,           /*!< out: line where requested */
 
662
        os_thread_id_t* thread_id)      /*!< out: id of the thread which owns
660
663
                                        the mutex */
661
664
{
662
665
        ut_ad(mutex);
666
669
        *thread_id = mutex->thread_id;
667
670
}
668
671
 
669
 
/**********************************************************************
 
672
/******************************************************************//**
670
673
Prints debug info of currently reserved mutexes. */
671
674
static
672
675
void
673
676
mutex_list_print_info(
674
677
/*==================*/
675
 
        FILE*   file)           /* in: file where to print */
 
678
        FILE*   file)           /*!< in: file where to print */
676
679
{
677
680
        mutex_t*        mutex;
678
681
        const char*     file_name;
709
712
        mutex_exit(&mutex_list_mutex);
710
713
}
711
714
 
712
 
/**********************************************************************
713
 
Counts currently reserved mutexes. Works only in the debug version. */
 
715
/******************************************************************//**
 
716
Counts currently reserved mutexes. Works only in the debug version.
 
717
@return number of reserved mutexes */
714
718
UNIV_INTERN
715
719
ulint
716
720
mutex_n_reserved(void)
740
744
                           was holding one mutex (mutex_list_mutex) */
741
745
}
742
746
 
743
 
/**********************************************************************
 
747
/******************************************************************//**
744
748
Returns TRUE if no mutex or rw-lock is currently locked. Works only in
745
 
the debug version. */
 
749
the debug version.
 
750
@return TRUE if no mutexes and rw-locks reserved */
746
751
UNIV_INTERN
747
752
ibool
748
753
sync_all_freed(void)
751
756
        return(mutex_n_reserved() + rw_lock_n_locked() == 0);
752
757
}
753
758
 
754
 
/**********************************************************************
755
 
Gets the value in the nth slot in the thread level arrays. */
 
759
/******************************************************************//**
 
760
Gets the value in the nth slot in the thread level arrays.
 
761
@return pointer to thread slot */
756
762
static
757
763
sync_thread_t*
758
764
sync_thread_level_arrays_get_nth(
759
765
/*=============================*/
760
 
                        /* out: pointer to thread slot */
761
 
        ulint   n)      /* in: slot number */
 
766
        ulint   n)      /*!< in: slot number */
762
767
{
763
768
        ut_ad(n < OS_THREAD_MAX_N);
764
769
 
765
770
        return(sync_thread_level_arrays + n);
766
771
}
767
772
 
768
 
/**********************************************************************
769
 
Looks for the thread slot for the calling thread. */
 
773
/******************************************************************//**
 
774
Looks for the thread slot for the calling thread.
 
775
@return pointer to thread slot, NULL if not found */
770
776
static
771
777
sync_thread_t*
772
778
sync_thread_level_arrays_find_slot(void)
773
779
/*====================================*/
774
 
                        /* out: pointer to thread slot, NULL if not found */
775
780
 
776
781
{
777
782
        sync_thread_t*  slot;
793
798
        return(NULL);
794
799
}
795
800
 
796
 
/**********************************************************************
797
 
Looks for an unused thread slot. */
 
801
/******************************************************************//**
 
802
Looks for an unused thread slot.
 
803
@return pointer to thread slot */
798
804
static
799
805
sync_thread_t*
800
806
sync_thread_level_arrays_find_free(void)
801
807
/*====================================*/
802
 
                        /* out: pointer to thread slot */
803
808
 
804
809
{
805
810
        sync_thread_t*  slot;
818
823
        return(NULL);
819
824
}
820
825
 
821
 
/**********************************************************************
822
 
Gets the value in the nth slot in the thread level array. */
 
826
/******************************************************************//**
 
827
Gets the value in the nth slot in the thread level array.
 
828
@return pointer to level slot */
823
829
static
824
830
sync_level_t*
825
831
sync_thread_levels_get_nth(
826
832
/*=======================*/
827
 
                                /* out: pointer to level slot */
828
 
        sync_level_t*   arr,    /* in: pointer to level array for an OS
 
833
        sync_level_t*   arr,    /*!< in: pointer to level array for an OS
829
834
                                thread */
830
 
        ulint           n)      /* in: slot number */
 
835
        ulint           n)      /*!< in: slot number */
831
836
{
832
837
        ut_ad(n < SYNC_THREAD_N_LEVELS);
833
838
 
834
839
        return(arr + n);
835
840
}
836
841
 
837
 
/**********************************************************************
 
842
/******************************************************************//**
838
843
Checks if all the level values stored in the level array are greater than
839
 
the given limit. */
 
844
the given limit.
 
845
@return TRUE if all greater */
840
846
static
841
847
ibool
842
848
sync_thread_levels_g(
843
849
/*=================*/
844
 
                                /* out: TRUE if all greater */
845
 
        sync_level_t*   arr,    /* in: pointer to level array for an OS
 
850
        sync_level_t*   arr,    /*!< in: pointer to level array for an OS
846
851
                                thread */
847
 
        ulint           limit)  /* in: level limit */
 
852
        ulint           limit)  /*!< in: level limit */
848
853
{
849
854
        sync_level_t*   slot;
850
855
        rw_lock_t*      lock;
905
910
        return(TRUE);
906
911
}
907
912
 
908
 
/**********************************************************************
909
 
Checks if the level value is stored in the level array. */
 
913
/******************************************************************//**
 
914
Checks if the level value is stored in the level array.
 
915
@return TRUE if stored */
910
916
static
911
917
ibool
912
918
sync_thread_levels_contain(
913
919
/*=======================*/
914
 
                                /* out: TRUE if stored */
915
 
        sync_level_t*   arr,    /* in: pointer to level array for an OS
 
920
        sync_level_t*   arr,    /*!< in: pointer to level array for an OS
916
921
                                thread */
917
 
        ulint           level)  /* in: level */
 
922
        ulint           level)  /*!< in: level */
918
923
{
919
924
        sync_level_t*   slot;
920
925
        ulint           i;
934
939
        return(FALSE);
935
940
}
936
941
 
937
 
/**********************************************************************
938
 
Checks that the level array for the current thread is empty. */
 
942
/******************************************************************//**
 
943
Checks that the level array for the current thread is empty.
 
944
@return TRUE if empty except the exceptions specified below */
939
945
UNIV_INTERN
940
946
ibool
941
947
sync_thread_levels_empty_gen(
942
948
/*=========================*/
943
 
                                        /* out: TRUE if empty except the
944
 
                                        exceptions specified below */
945
 
        ibool   dict_mutex_allowed)     /* in: TRUE if dictionary mutex is
 
949
        ibool   dict_mutex_allowed)     /*!< in: TRUE if dictionary mutex is
946
950
                                        allowed to be owned by the thread,
947
951
                                        also purge_is_running mutex is
948
952
                                        allowed */
991
995
        return(TRUE);
992
996
}
993
997
 
994
 
/**********************************************************************
995
 
Checks that the level array for the current thread is empty. */
 
998
/******************************************************************//**
 
999
Checks that the level array for the current thread is empty.
 
1000
@return TRUE if empty */
996
1001
UNIV_INTERN
997
1002
ibool
998
1003
sync_thread_levels_empty(void)
999
1004
/*==========================*/
1000
 
                        /* out: TRUE if empty */
1001
1005
{
1002
1006
        return(sync_thread_levels_empty_gen(FALSE));
1003
1007
}
1004
1008
 
1005
 
/**********************************************************************
 
1009
/******************************************************************//**
1006
1010
Adds a latch and its level in the thread level array. Allocates the memory
1007
1011
for the array if called first time for this OS thread. Makes the checks
1008
1012
against other latch levels stored in the array for this thread. */
1010
1014
void
1011
1015
sync_thread_add_level(
1012
1016
/*==================*/
1013
 
        void*   latch,  /* in: pointer to a mutex or an rw-lock */
1014
 
        ulint   level)  /* in: level in the latching order; if
 
1017
        void*   latch,  /*!< in: pointer to a mutex or an rw-lock */
 
1018
        ulint   level)  /*!< in: level in the latching order; if
1015
1019
                        SYNC_LEVEL_VARYING, nothing is done */
1016
1020
{
1017
1021
        sync_level_t*   array;
1107
1111
                /* Either the thread must own the buffer pool mutex
1108
1112
                (buf_pool_mutex), or it is allowed to latch only ONE
1109
1113
                buffer block (block->mutex or buf_pool_zip_mutex). */
1110
 
                ut_a((sync_thread_levels_contain(array, SYNC_BUF_POOL)
1111
 
                      && sync_thread_levels_g(array, SYNC_BUF_BLOCK - 1))
1112
 
                     || sync_thread_levels_g(array, SYNC_BUF_BLOCK));
 
1114
                if (!sync_thread_levels_g(array, level)) {
 
1115
                        ut_a(sync_thread_levels_g(array, level - 1));
 
1116
                        ut_a(sync_thread_levels_contain(array, SYNC_BUF_POOL));
 
1117
                }
1113
1118
                break;
1114
1119
        case SYNC_REC_LOCK:
1115
1120
                ut_a((sync_thread_levels_contain(array, SYNC_KERNEL)
1201
1206
        mutex_exit(&sync_thread_mutex);
1202
1207
}
1203
1208
 
1204
 
/**********************************************************************
1205
 
Removes a latch from the thread level array if it is found there. */
 
1209
/******************************************************************//**
 
1210
Removes a latch from the thread level array if it is found there.
 
1211
@return TRUE if found in the array; it is no error if the latch is
 
1212
not found, as we presently are not able to determine the level for
 
1213
every latch reservation the program does */
1206
1214
UNIV_INTERN
1207
1215
ibool
1208
1216
sync_thread_reset_level(
1209
1217
/*====================*/
1210
 
                        /* out: TRUE if found from the array; it is an error
1211
 
                        if the latch is not found */
1212
 
        void*   latch)  /* in: pointer to a mutex or an rw-lock */
 
1218
        void*   latch)  /*!< in: pointer to a mutex or an rw-lock */
1213
1219
{
1214
1220
        sync_level_t*   array;
1215
1221
        sync_level_t*   slot;
1276
1282
}
1277
1283
#endif /* UNIV_SYNC_DEBUG */
1278
1284
 
1279
 
/**********************************************************************
 
1285
/******************************************************************//**
1280
1286
Initializes the synchronization data structures. */
1281
1287
UNIV_INTERN
1282
1288
void
1330
1336
#endif /* UNIV_SYNC_DEBUG */
1331
1337
}
1332
1338
 
1333
 
/**********************************************************************
 
1339
/******************************************************************//**
1334
1340
Frees the resources in InnoDB's own synchronization data structures. Use
1335
1341
os_sync_free() after calling this. */
1336
1342
UNIV_INTERN
1355
1361
#endif /* UNIV_SYNC_DEBUG */
1356
1362
}
1357
1363
 
1358
 
/***********************************************************************
 
1364
/*******************************************************************//**
1359
1365
Prints wait info of the sync system. */
1360
1366
UNIV_INTERN
1361
1367
void
1362
1368
sync_print_wait_info(
1363
1369
/*=================*/
1364
 
        FILE*   file)           /* in: file where to print */
 
1370
        FILE*   file)           /*!< in: file where to print */
1365
1371
{
1366
1372
#ifdef UNIV_SYNC_DEBUG
1367
1373
        fprintf(file, "Mutex exits %llu, rws exits %llu, rwx exits %llu\n",
1392
1398
                (rw_x_spin_wait_count ? rw_x_spin_wait_count : 1));
1393
1399
}
1394
1400
 
1395
 
/***********************************************************************
 
1401
/*******************************************************************//**
1396
1402
Prints info of the sync system. */
1397
1403
UNIV_INTERN
1398
1404
void
1399
1405
sync_print(
1400
1406
/*=======*/
1401
 
        FILE*   file)           /* in: file where to print */
 
1407
        FILE*   file)           /*!< in: file where to print */
1402
1408
{
1403
1409
#ifdef UNIV_SYNC_DEBUG
1404
1410
        mutex_list_print_info(file);