~ubuntu-branches/ubuntu/saucy/drizzle/saucy-proposed

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Monty Taylor
  • Date: 2010-03-18 12:12:31 UTC
  • Revision ID: james.westby@ubuntu.com-20100318121231-k6g1xe6cshbwa0f8
Tags: upstream-2010.03.1347
ImportĀ upstreamĀ versionĀ 2010.03.1347

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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., 59 Temple
 
22
Place, Suite 330, Boston, MA 02111-1307 USA
 
23
 
 
24
*****************************************************************************/
 
25
 
 
26
/**************************************************//**
 
27
@file sync/sync0arr.c
 
28
The wait array used in synchronization primitives
 
29
 
 
30
Created 9/5/1995 Heikki Tuuri
 
31
*******************************************************/
 
32
 
 
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
 
 
77
/** A cell where an individual thread may wait suspended
 
78
until a resource is released. The suspending is implemented
 
79
using an operating system event semaphore. */
 
80
struct sync_cell_struct {
 
81
        void*           wait_object;    /*!< pointer to the object the
 
82
                                        thread is waiting for; if NULL
 
83
                                        the cell is free for use */
 
84
        mutex_t*        old_wait_mutex; /*!< the latest wait mutex in cell */
 
85
        rw_lock_t*      old_wait_rw_lock;
 
86
                                        /*!< the latest wait rw-lock
 
87
                                        in cell */
 
88
        ulint           request_type;   /*!< lock type requested on the
 
89
                                        object */
 
90
        const char*     file;           /*!< in debug version file where
 
91
                                        requested */
 
92
        ulint           line;           /*!< in debug version line where
 
93
                                        requested */
 
94
        os_thread_id_t  thread;         /*!< thread id of this waiting
 
95
                                        thread */
 
96
        ibool           waiting;        /*!< TRUE if the thread has already
 
97
                                        called sync_array_event_wait
 
98
                                        on this cell */
 
99
        ib_int64_t      signal_count;   /*!< We capture the signal_count
 
100
                                        of the wait_object when we
 
101
                                        reset the event. This value is
 
102
                                        then passed on to os_event_wait
 
103
                                        and we wait only if the event
 
104
                                        has not been signalled in the
 
105
                                        period between the reset and
 
106
                                        wait call. */
 
107
        time_t          reservation_time;/*!< time when the thread reserved
 
108
                                        the wait cell */
 
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
 
 
117
/** Synchronization array */
 
118
struct sync_array_struct {
 
119
        ulint           n_reserved;     /*!< number of currently reserved
 
120
                                        cells in the wait array */
 
121
        ulint           n_cells;        /*!< number of cells in the
 
122
                                        wait array */
 
123
        sync_cell_t*    array;          /*!< pointer to wait array */
 
124
        ulint           protection;     /*!< this flag tells which
 
125
                                        mutex protects the data */
 
126
        mutex_t         mutex;          /*!< possible database mutex
 
127
                                        protecting this data structure */
 
128
        os_mutex_t      os_mutex;       /*!< Possible operating system mutex
 
129
                                        protecting the data structure.
 
130
                                        As this data structure is used in
 
131
                                        constructing the database mutex,
 
132
                                        to prevent infinite recursion
 
133
                                        in implementation, we fall back to
 
134
                                        an OS mutex. */
 
135
        ulint           sg_count;       /*!< count of how many times an
 
136
                                        object has been signalled */
 
137
        ulint           res_count;      /*!< count of cell reservations
 
138
                                        since creation of the array */
 
139
};
 
140
 
 
141
#ifdef UNIV_SYNC_DEBUG
 
142
/******************************************************************//**
 
143
This function is called only in the debug version. Detects a deadlock
 
144
of one or more threads because of waits of semaphores.
 
145
@return TRUE if deadlock detected */
 
146
static
 
147
ibool
 
148
sync_array_detect_deadlock(
 
149
/*=======================*/
 
150
        sync_array_t*   arr,    /*!< in: wait array; NOTE! the caller must
 
151
                                own the mutex to array */
 
152
        sync_cell_t*    start,  /*!< in: cell where recursive search started */
 
153
        sync_cell_t*    cell,   /*!< in: cell to search */
 
154
        ulint           depth); /*!< in: recursion depth */
 
155
#endif /* UNIV_SYNC_DEBUG */
 
156
 
 
157
/*****************************************************************//**
 
158
Gets the nth cell in array.
 
159
@return cell */
 
160
static
 
161
sync_cell_t*
 
162
sync_array_get_nth_cell(
 
163
/*====================*/
 
164
        sync_array_t*   arr,    /*!< in: sync array */
 
165
        ulint           n)      /*!< in: index */
 
166
{
 
167
        ut_a(arr);
 
168
        ut_a(n < arr->n_cells);
 
169
 
 
170
        return(arr->array + n);
 
171
}
 
172
 
 
173
/******************************************************************//**
 
174
Reserves the mutex semaphore protecting a sync array. */
 
175
static
 
176
void
 
177
sync_array_enter(
 
178
/*=============*/
 
179
        sync_array_t*   arr)    /*!< in: sync wait array */
 
180
{
 
181
        ulint   protection;
 
182
 
 
183
        protection = arr->protection;
 
184
 
 
185
        if (protection == SYNC_ARRAY_OS_MUTEX) {
 
186
                os_mutex_enter(arr->os_mutex);
 
187
        } else if (protection == SYNC_ARRAY_MUTEX) {
 
188
                mutex_enter(&(arr->mutex));
 
189
        } else {
 
190
                ut_error;
 
191
        }
 
192
}
 
193
 
 
194
/******************************************************************//**
 
195
Releases the mutex semaphore protecting a sync array. */
 
196
static
 
197
void
 
198
sync_array_exit(
 
199
/*============*/
 
200
        sync_array_t*   arr)    /*!< in: sync wait array */
 
201
{
 
202
        ulint   protection;
 
203
 
 
204
        protection = arr->protection;
 
205
 
 
206
        if (protection == SYNC_ARRAY_OS_MUTEX) {
 
207
                os_mutex_exit(arr->os_mutex);
 
208
        } else if (protection == SYNC_ARRAY_MUTEX) {
 
209
                mutex_exit(&(arr->mutex));
 
210
        } else {
 
211
                ut_error;
 
212
        }
 
213
}
 
214
 
 
215
/*******************************************************************//**
 
216
Creates a synchronization wait array. It is protected by a mutex
 
217
which is automatically reserved when the functions operating on it
 
218
are called.
 
219
@return own: created wait array */
 
220
UNIV_INTERN
 
221
sync_array_t*
 
222
sync_array_create(
 
223
/*==============*/
 
224
        ulint   n_cells,        /*!< in: number of cells in the array
 
225
                                to create */
 
226
        ulint   protection)     /*!< in: either SYNC_ARRAY_OS_MUTEX or
 
227
                                SYNC_ARRAY_MUTEX: determines the type
 
228
                                of mutex protecting the data structure */
 
229
{
 
230
        sync_array_t*   arr;
 
231
        sync_cell_t*    cell_array;
 
232
        sync_cell_t*    cell;
 
233
        ulint           i;
 
234
 
 
235
        ut_a(n_cells > 0);
 
236
 
 
237
        /* Allocate memory for the data structures */
 
238
        arr = ut_malloc(sizeof(sync_array_t));
 
239
 
 
240
        cell_array = ut_malloc(sizeof(sync_cell_t) * n_cells);
 
241
 
 
242
        arr->n_cells = n_cells;
 
243
        arr->n_reserved = 0;
 
244
        arr->array = cell_array;
 
245
        arr->protection = protection;
 
246
        arr->sg_count = 0;
 
247
        arr->res_count = 0;
 
248
 
 
249
        /* Then create the mutex to protect the wait array complex */
 
250
        if (protection == SYNC_ARRAY_OS_MUTEX) {
 
251
                arr->os_mutex = os_mutex_create(NULL);
 
252
        } else if (protection == SYNC_ARRAY_MUTEX) {
 
253
                mutex_create(&arr->mutex, SYNC_NO_ORDER_CHECK);
 
254
        } else {
 
255
                ut_error;
 
256
        }
 
257
 
 
258
        for (i = 0; i < n_cells; i++) {
 
259
                cell = sync_array_get_nth_cell(arr, i);
 
260
        cell->wait_object = NULL;
 
261
                cell->waiting = FALSE;
 
262
                cell->signal_count = 0;
 
263
        }
 
264
 
 
265
        return(arr);
 
266
}
 
267
 
 
268
/******************************************************************//**
 
269
Frees the resources in a wait array. */
 
270
UNIV_INTERN
 
271
void
 
272
sync_array_free(
 
273
/*============*/
 
274
        sync_array_t*   arr)    /*!< in, own: sync wait array */
 
275
{
 
276
        ulint           protection;
 
277
 
 
278
        ut_a(arr->n_reserved == 0);
 
279
 
 
280
        sync_array_validate(arr);
 
281
 
 
282
        protection = arr->protection;
 
283
 
 
284
        /* Release the mutex protecting the wait array complex */
 
285
 
 
286
        if (protection == SYNC_ARRAY_OS_MUTEX) {
 
287
                os_mutex_free(arr->os_mutex);
 
288
        } else if (protection == SYNC_ARRAY_MUTEX) {
 
289
                mutex_free(&(arr->mutex));
 
290
        } else {
 
291
                ut_error;
 
292
        }
 
293
 
 
294
        ut_free(arr->array);
 
295
        ut_free(arr);
 
296
}
 
297
 
 
298
/********************************************************************//**
 
299
Validates the integrity of the wait array. Checks
 
300
that the number of reserved cells equals the count variable. */
 
301
UNIV_INTERN
 
302
void
 
303
sync_array_validate(
 
304
/*================*/
 
305
        sync_array_t*   arr)    /*!< in: sync wait array */
 
306
{
 
307
        ulint           i;
 
308
        sync_cell_t*    cell;
 
309
        ulint           count           = 0;
 
310
 
 
311
        sync_array_enter(arr);
 
312
 
 
313
        for (i = 0; i < arr->n_cells; i++) {
 
314
                cell = sync_array_get_nth_cell(arr, i);
 
315
                if (cell->wait_object != NULL) {
 
316
                        count++;
 
317
                }
 
318
        }
 
319
 
 
320
        ut_a(count == arr->n_reserved);
 
321
 
 
322
        sync_array_exit(arr);
 
323
}
 
324
 
 
325
/*******************************************************************//**
 
326
Returns the event that the thread owning the cell waits for. */
 
327
static
 
328
os_event_t
 
329
sync_cell_get_event(
 
330
/*================*/
 
331
        sync_cell_t*    cell) /*!< in: non-empty sync array cell */
 
332
{
 
333
        ulint type = cell->request_type;
 
334
 
 
335
        if (type == SYNC_MUTEX) {
 
336
                return(((mutex_t *) cell->wait_object)->event);
 
337
        } else if (type == RW_LOCK_WAIT_EX) {
 
338
                return(((rw_lock_t *) cell->wait_object)->wait_ex_event);
 
339
        } else { /* RW_LOCK_SHARED and RW_LOCK_EX wait on the same event */
 
340
                return(((rw_lock_t *) cell->wait_object)->event);
 
341
        }
 
342
}
 
343
 
 
344
/******************************************************************//**
 
345
Reserves a wait array cell for waiting for an object.
 
346
The event of the cell is reset to nonsignalled state. */
 
347
UNIV_INTERN
 
348
void
 
349
sync_array_reserve_cell(
 
350
/*====================*/
 
351
        sync_array_t*   arr,    /*!< in: wait array */
 
352
        void*           object, /*!< in: pointer to the object to wait for */
 
353
        ulint           type,   /*!< in: lock request type */
 
354
        const char*     file,   /*!< in: file where requested */
 
355
        ulint           line,   /*!< in: line where requested */
 
356
        ulint*          index)  /*!< out: index of the reserved cell */
 
357
{
 
358
        sync_cell_t*    cell;
 
359
        os_event_t      event;
 
360
        ulint           i;
 
361
 
 
362
        ut_a(object);
 
363
        ut_a(index);
 
364
 
 
365
        sync_array_enter(arr);
 
366
 
 
367
        arr->res_count++;
 
368
 
 
369
        /* Reserve a new cell. */
 
370
        for (i = 0; i < arr->n_cells; i++) {
 
371
                cell = sync_array_get_nth_cell(arr, i);
 
372
 
 
373
                if (cell->wait_object == NULL) {
 
374
 
 
375
                        cell->waiting = FALSE;
 
376
                        cell->wait_object = object;
 
377
 
 
378
                        if (type == SYNC_MUTEX) {
 
379
                                cell->old_wait_mutex = object;
 
380
                        } else {
 
381
                                cell->old_wait_rw_lock = object;
 
382
                        }
 
383
 
 
384
                        cell->request_type = type;
 
385
 
 
386
                        cell->file = file;
 
387
                        cell->line = line;
 
388
 
 
389
                        arr->n_reserved++;
 
390
 
 
391
                        *index = i;
 
392
 
 
393
                        sync_array_exit(arr);
 
394
 
 
395
                        /* Make sure the event is reset and also store
 
396
                        the value of signal_count at which the event
 
397
                        was reset. */
 
398
                        event = sync_cell_get_event(cell);
 
399
                        cell->signal_count = os_event_reset(event);
 
400
 
 
401
                        cell->reservation_time = time(NULL);
 
402
 
 
403
                        cell->thread = os_thread_get_curr_id();
 
404
 
 
405
                        return;
 
406
                }
 
407
        }
 
408
 
 
409
        ut_error; /* No free cell found */
 
410
 
 
411
        return;
 
412
}
 
413
 
 
414
/******************************************************************//**
 
415
This function should be called when a thread starts to wait on
 
416
a wait array cell. In the debug version this function checks
 
417
if the wait for a semaphore will result in a deadlock, in which
 
418
case prints info and asserts. */
 
419
UNIV_INTERN
 
420
void
 
421
sync_array_wait_event(
 
422
/*==================*/
 
423
        sync_array_t*   arr,    /*!< in: wait array */
 
424
        ulint           index)  /*!< in: index of the reserved cell */
 
425
{
 
426
        sync_cell_t*    cell;
 
427
        os_event_t      event;
 
428
 
 
429
        ut_a(arr);
 
430
 
 
431
        sync_array_enter(arr);
 
432
 
 
433
        cell = sync_array_get_nth_cell(arr, index);
 
434
 
 
435
        ut_a(cell->wait_object);
 
436
        ut_a(!cell->waiting);
 
437
        ut_ad(os_thread_get_curr_id() == cell->thread);
 
438
 
 
439
        event = sync_cell_get_event(cell);
 
440
                cell->waiting = TRUE;
 
441
 
 
442
#ifdef UNIV_SYNC_DEBUG
 
443
 
 
444
        /* We use simple enter to the mutex below, because if
 
445
        we cannot acquire it at once, mutex_enter would call
 
446
        recursively sync_array routines, leading to trouble.
 
447
        rw_lock_debug_mutex freezes the debug lists. */
 
448
 
 
449
        rw_lock_debug_mutex_enter();
 
450
 
 
451
        if (TRUE == sync_array_detect_deadlock(arr, cell, cell, 0)) {
 
452
 
 
453
                fputs("########################################\n", stderr);
 
454
                ut_error;
 
455
        }
 
456
 
 
457
        rw_lock_debug_mutex_exit();
 
458
#endif
 
459
        sync_array_exit(arr);
 
460
 
 
461
        os_event_wait_low(event, cell->signal_count);
 
462
 
 
463
        sync_array_free_cell(arr, index);
 
464
}
 
465
 
 
466
/******************************************************************//**
 
467
Reports info of a wait array cell. */
 
468
static
 
469
void
 
470
sync_array_cell_print(
 
471
/*==================*/
 
472
        FILE*           file,   /*!< in: file where to print */
 
473
        sync_cell_t*    cell)   /*!< in: sync cell */
 
474
{
 
475
        mutex_t*        mutex;
 
476
        rw_lock_t*      rwlock;
 
477
        ulint           type;
 
478
        ulint           writer;
 
479
 
 
480
        type = cell->request_type;
 
481
 
 
482
        fprintf(file,
 
483
                "--Thread %lu has waited at %s line %lu"
 
484
                " for %.2f seconds the semaphore:\n",
 
485
                (ulong) os_thread_pf(cell->thread), cell->file,
 
486
                (ulong) cell->line,
 
487
                difftime(time(NULL), cell->reservation_time));
 
488
 
 
489
        if (type == SYNC_MUTEX) {
 
490
                /* We use old_wait_mutex in case the cell has already
 
491
                been freed meanwhile */
 
492
                mutex = cell->old_wait_mutex;
 
493
 
 
494
                fprintf(file,
 
495
                        "Mutex at %p created file %s line %lu, lock var %lu\n"
 
496
#ifdef UNIV_SYNC_DEBUG
 
497
                        "Last time reserved in file %s line %lu, "
 
498
#endif /* UNIV_SYNC_DEBUG */
 
499
                        "waiters flag %lu\n",
 
500
                        (void*) mutex, mutex->cfile_name, (ulong) mutex->cline,
 
501
                        (ulong) mutex->lock_word,
 
502
#ifdef UNIV_SYNC_DEBUG
 
503
                        mutex->file_name, (ulong) mutex->line,
 
504
#endif /* UNIV_SYNC_DEBUG */
 
505
                        (ulong) mutex->waiters);
 
506
 
 
507
        } else if (type == RW_LOCK_EX
 
508
                   || type == RW_LOCK_WAIT_EX
 
509
                   || type == RW_LOCK_SHARED) {
 
510
 
 
511
                fputs(type == RW_LOCK_EX ? "X-lock on" : "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, 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,
 
538
                        rwlock->last_s_file_name,
 
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
/******************************************************************//**
 
553
Looks for a cell with the given thread id.
 
554
@return pointer to cell or NULL if not found */
 
555
static
 
556
sync_cell_t*
 
557
sync_array_find_thread(
 
558
/*===================*/
 
559
        sync_array_t*   arr,    /*!< in: wait array */
 
560
        os_thread_id_t  thread) /*!< in: thread id */
 
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
/******************************************************************//**
 
580
Recursion step for deadlock detection.
 
581
@return TRUE if deadlock detected */
 
582
static
 
583
ibool
 
584
sync_array_deadlock_step(
 
585
/*=====================*/
 
586
        sync_array_t*   arr,    /*!< in: wait array; NOTE! the caller must
 
587
                                own the mutex to array */
 
588
        sync_cell_t*    start,  /*!< in: cell where recursive search
 
589
                                started */
 
590
        os_thread_id_t  thread, /*!< in: thread to look at */
 
591
        ulint           pass,   /*!< in: pass value */
 
592
        ulint           depth)  /*!< in: recursion depth */
 
593
{
 
594
        sync_cell_t*    new;
 
595
        ibool           ret;
 
596
 
 
597
        depth++;
 
598
 
 
599
        if (pass != 0) {
 
600
                /* If pass != 0, then we do not know which threads are
 
601
                responsible of releasing the lock, and no deadlock can
 
602
                be detected. */
 
603
 
 
604
                return(FALSE);
 
605
        }
 
606
 
 
607
        new = sync_array_find_thread(arr, thread);
 
608
 
 
609
        if (new == start) {
 
610
                /* Stop running of other threads */
 
611
 
 
612
                ut_dbg_stop_threads = TRUE;
 
613
 
 
614
                /* Deadlock */
 
615
                fputs("########################################\n"
 
616
                      "DEADLOCK of threads detected!\n", stderr);
 
617
 
 
618
                return(TRUE);
 
619
 
 
620
        } else if (new) {
 
621
                ret = sync_array_detect_deadlock(arr, start, new, depth);
 
622
 
 
623
                if (ret) {
 
624
                        return(TRUE);
 
625
                }
 
626
        }
 
627
        return(FALSE);
 
628
}
 
629
 
 
630
/******************************************************************//**
 
631
This function is called only in the debug version. Detects a deadlock
 
632
of one or more threads because of waits of semaphores.
 
633
@return TRUE if deadlock detected */
 
634
static
 
635
ibool
 
636
sync_array_detect_deadlock(
 
637
/*=======================*/
 
638
        sync_array_t*   arr,    /*!< in: wait array; NOTE! the caller must
 
639
                                own the mutex to array */
 
640
        sync_cell_t*    start,  /*!< in: cell where recursive search started */
 
641
        sync_cell_t*    cell,   /*!< in: cell to search */
 
642
        ulint           depth)  /*!< in: recursion depth */
 
643
{
 
644
        mutex_t*        mutex;
 
645
        rw_lock_t*      lock;
 
646
        os_thread_id_t  thread;
 
647
        ibool           ret;
 
648
        rw_lock_debug_t*debug;
 
649
 
 
650
        ut_a(arr);
 
651
        ut_a(start);
 
652
        ut_a(cell);
 
653
        ut_ad(cell->wait_object);
 
654
        ut_ad(os_thread_get_curr_id() == start->thread);
 
655
        ut_ad(depth < 100);
 
656
 
 
657
        depth++;
 
658
 
 
659
        if (!cell->waiting) {
 
660
 
 
661
                return(FALSE); /* No deadlock here */
 
662
        }
 
663
 
 
664
        if (cell->request_type == SYNC_MUTEX) {
 
665
 
 
666
                mutex = cell->wait_object;
 
667
 
 
668
                if (mutex_get_lock_word(mutex) != 0) {
 
669
 
 
670
                        thread = mutex->thread_id;
 
671
 
 
672
                        /* Note that mutex->thread_id above may be
 
673
                        also OS_THREAD_ID_UNDEFINED, because the
 
674
                        thread which held the mutex maybe has not
 
675
                        yet updated the value, or it has already
 
676
                        released the mutex: in this case no deadlock
 
677
                        can occur, as the wait array cannot contain
 
678
                        a thread with ID_UNDEFINED value. */
 
679
 
 
680
                        ret = sync_array_deadlock_step(arr, start, thread, 0,
 
681
                                                       depth);
 
682
                        if (ret) {
 
683
                                fprintf(stderr,
 
684
                        "Mutex %p owned by thread %lu file %s line %lu\n",
 
685
                                        mutex, (ulong) os_thread_pf(mutex->thread_id),
 
686
                                        mutex->file_name, (ulong) mutex->line);
 
687
                                sync_array_cell_print(stderr, cell);
 
688
 
 
689
                                return(TRUE);
 
690
                        }
 
691
                }
 
692
 
 
693
                return(FALSE); /* No deadlock */
 
694
 
 
695
        } else if (cell->request_type == RW_LOCK_EX
 
696
                   || cell->request_type == RW_LOCK_WAIT_EX) {
 
697
 
 
698
                lock = cell->wait_object;
 
699
 
 
700
                debug = UT_LIST_GET_FIRST(lock->debug_list);
 
701
 
 
702
                while (debug != NULL) {
 
703
 
 
704
                        thread = debug->thread_id;
 
705
 
 
706
                        if (((debug->lock_type == RW_LOCK_EX)
 
707
                             && !os_thread_eq(thread, cell->thread))
 
708
                            || ((debug->lock_type == RW_LOCK_WAIT_EX)
 
709
                                && !os_thread_eq(thread, cell->thread))
 
710
                            || (debug->lock_type == RW_LOCK_SHARED)) {
 
711
 
 
712
                                /* The (wait) x-lock request can block
 
713
                                infinitely only if someone (can be also cell
 
714
                                thread) is holding s-lock, or someone
 
715
                                (cannot be cell thread) (wait) x-lock, and
 
716
                                he is blocked by start thread */
 
717
 
 
718
                                ret = sync_array_deadlock_step(
 
719
                                        arr, start, thread, debug->pass,
 
720
                                        depth);
 
721
                                if (ret) {
 
722
print:
 
723
                                        fprintf(stderr, "rw-lock %p ",
 
724
                                                (void*) lock);
 
725
                                        sync_array_cell_print(stderr, cell);
 
726
                                        rw_lock_debug_print(debug);
 
727
                                        return(TRUE);
 
728
                                }
 
729
                        }
 
730
 
 
731
                        debug = UT_LIST_GET_NEXT(list, debug);
 
732
                }
 
733
 
 
734
                return(FALSE);
 
735
 
 
736
        } else if (cell->request_type == RW_LOCK_SHARED) {
 
737
 
 
738
                lock = cell->wait_object;
 
739
                debug = UT_LIST_GET_FIRST(lock->debug_list);
 
740
 
 
741
                while (debug != NULL) {
 
742
 
 
743
                        thread = debug->thread_id;
 
744
 
 
745
                        if ((debug->lock_type == RW_LOCK_EX)
 
746
                            || (debug->lock_type == RW_LOCK_WAIT_EX)) {
 
747
 
 
748
                                /* The s-lock request can block infinitely
 
749
                                only if someone (can also be cell thread) is
 
750
                                holding (wait) x-lock, and he is blocked by
 
751
                                start thread */
 
752
 
 
753
                                ret = sync_array_deadlock_step(
 
754
                                        arr, start, thread, debug->pass,
 
755
                                        depth);
 
756
                                if (ret) {
 
757
                                        goto print;
 
758
                                }
 
759
                        }
 
760
 
 
761
                        debug = UT_LIST_GET_NEXT(list, debug);
 
762
                }
 
763
 
 
764
                return(FALSE);
 
765
 
 
766
        } else {
 
767
                ut_error;
 
768
        }
 
769
 
 
770
        return(TRUE);   /* Execution never reaches this line: for compiler
 
771
                        fooling only */
 
772
}
 
773
#endif /* UNIV_SYNC_DEBUG */
 
774
 
 
775
/******************************************************************//**
 
776
Determines if we can wake up the thread waiting for a sempahore. */
 
777
static
 
778
ibool
 
779
sync_arr_cell_can_wake_up(
 
780
/*======================*/
 
781
        sync_cell_t*    cell)   /*!< in: cell to search */
 
782
{
 
783
        mutex_t*        mutex;
 
784
        rw_lock_t*      lock;
 
785
 
 
786
        if (cell->request_type == SYNC_MUTEX) {
 
787
 
 
788
                mutex = cell->wait_object;
 
789
 
 
790
                if (mutex_get_lock_word(mutex) == 0) {
 
791
 
 
792
                        return(TRUE);
 
793
                }
 
794
 
 
795
        } else if (cell->request_type == RW_LOCK_EX) {
 
796
 
 
797
                lock = cell->wait_object;
 
798
 
 
799
                if (lock->lock_word > 0) {
 
800
                /* Either unlocked or only read locked. */
 
801
 
 
802
                        return(TRUE);
 
803
                }
 
804
 
 
805
        } else if (cell->request_type == RW_LOCK_WAIT_EX) {
 
806
 
 
807
                lock = cell->wait_object;
 
808
 
 
809
                /* lock_word == 0 means all readers have left */
 
810
                if (lock->lock_word == 0) {
 
811
 
 
812
                        return(TRUE);
 
813
                }
 
814
        } else if (cell->request_type == RW_LOCK_SHARED) {
 
815
                lock = cell->wait_object;
 
816
 
 
817
                /* lock_word > 0 means no writer or reserved writer */
 
818
                if (lock->lock_word > 0) {
 
819
 
 
820
                        return(TRUE);
 
821
                }
 
822
        }
 
823
 
 
824
        return(FALSE);
 
825
}
 
826
 
 
827
/******************************************************************//**
 
828
Frees the cell. NOTE! sync_array_wait_event frees the cell
 
829
automatically! */
 
830
UNIV_INTERN
 
831
void
 
832
sync_array_free_cell(
 
833
/*=================*/
 
834
        sync_array_t*   arr,    /*!< in: wait array */
 
835
        ulint           index)  /*!< in: index of the cell in array */
 
836
{
 
837
        sync_cell_t*    cell;
 
838
 
 
839
        sync_array_enter(arr);
 
840
 
 
841
        cell = sync_array_get_nth_cell(arr, index);
 
842
 
 
843
        ut_a(cell->wait_object != NULL);
 
844
 
 
845
        cell->waiting = FALSE;
 
846
        cell->wait_object =  NULL;
 
847
        cell->signal_count = 0;
 
848
 
 
849
        ut_a(arr->n_reserved > 0);
 
850
        arr->n_reserved--;
 
851
 
 
852
        sync_array_exit(arr);
 
853
}
 
854
 
 
855
/**********************************************************************//**
 
856
Increments the signalled count. */
 
857
UNIV_INTERN
 
858
void
 
859
sync_array_object_signalled(
 
860
/*========================*/
 
861
        sync_array_t*   arr)    /*!< in: wait array */
 
862
{
 
863
#ifdef HAVE_ATOMIC_BUILTINS
 
864
        (void) os_atomic_increment_ulint(&arr->sg_count, 1);
 
865
#else
 
866
        sync_array_enter(arr);
 
867
 
 
868
        arr->sg_count++;
 
869
 
 
870
        sync_array_exit(arr);
 
871
#endif
 
872
}
 
873
 
 
874
/**********************************************************************//**
 
875
If the wakeup algorithm does not work perfectly at semaphore relases,
 
876
this function will do the waking (see the comment in mutex_exit). This
 
877
function should be called about every 1 second in the server.
 
878
 
 
879
Note that there's a race condition between this thread and mutex_exit
 
880
changing the lock_word and calling signal_object, so sometimes this finds
 
881
threads to wake up even when nothing has gone wrong. */
 
882
UNIV_INTERN
 
883
void
 
884
sync_arr_wake_threads_if_sema_free(void)
 
885
/*====================================*/
 
886
{
 
887
        sync_array_t*   arr     = sync_primary_wait_array;
 
888
        sync_cell_t*    cell;
 
889
        ulint           count;
 
890
        ulint           i;
 
891
        os_event_t      event;
 
892
 
 
893
        sync_array_enter(arr);
 
894
 
 
895
        i = 0;
 
896
        count = 0;
 
897
 
 
898
        while (count < arr->n_reserved) {
 
899
 
 
900
                cell = sync_array_get_nth_cell(arr, i);
 
901
                i++;
 
902
 
 
903
                if (cell->wait_object == NULL) {
 
904
                        continue;
 
905
                }
 
906
                        count++;
 
907
 
 
908
                        if (sync_arr_cell_can_wake_up(cell)) {
 
909
 
 
910
                        event = sync_cell_get_event(cell);
 
911
 
 
912
                        os_event_set(event);
 
913
                }
 
914
 
 
915
        }
 
916
 
 
917
        sync_array_exit(arr);
 
918
}
 
919
 
 
920
/**********************************************************************//**
 
921
Prints warnings of long semaphore waits to stderr.
 
922
@return TRUE if fatal semaphore wait threshold was exceeded */
 
923
UNIV_INTERN
 
924
ibool
 
925
sync_array_print_long_waits(void)
 
926
/*=============================*/
 
927
{
 
928
        sync_cell_t*    cell;
 
929
        ibool           old_val;
 
930
        ibool           noticed = FALSE;
 
931
        ulint           i;
 
932
        ulint           fatal_timeout = srv_fatal_semaphore_wait_threshold;
 
933
        ibool           fatal = FALSE;
 
934
 
 
935
        for (i = 0; i < sync_primary_wait_array->n_cells; i++) {
 
936
 
 
937
                cell = sync_array_get_nth_cell(sync_primary_wait_array, i);
 
938
 
 
939
                if (cell->wait_object != NULL && cell->waiting
 
940
                    && difftime(time(NULL), cell->reservation_time) > 240) {
 
941
                        fputs("InnoDB: Warning: a long semaphore wait:\n",
 
942
                              stderr);
 
943
                        sync_array_cell_print(stderr, cell);
 
944
                        noticed = TRUE;
 
945
                }
 
946
 
 
947
                if (cell->wait_object != NULL && cell->waiting
 
948
                    && difftime(time(NULL), cell->reservation_time)
 
949
                    > fatal_timeout) {
 
950
                        fatal = TRUE;
 
951
                }
 
952
        }
 
953
 
 
954
        if (noticed) {
 
955
                fprintf(stderr,
 
956
                        "InnoDB: ###### Starts InnoDB Monitor"
 
957
                        " for 30 secs to print diagnostic info:\n");
 
958
                old_val = srv_print_innodb_monitor;
 
959
 
 
960
                /* If some crucial semaphore is reserved, then also the InnoDB
 
961
                Monitor can hang, and we do not get diagnostics. Since in
 
962
                many cases an InnoDB hang is caused by a pwrite() or a pread()
 
963
                call hanging inside the operating system, let us print right
 
964
                now the values of pending calls of these. */
 
965
 
 
966
                fprintf(stderr,
 
967
                        "InnoDB: Pending preads %lu, pwrites %lu\n",
 
968
                        (ulong)os_file_n_pending_preads,
 
969
                        (ulong)os_file_n_pending_pwrites);
 
970
 
 
971
                srv_print_innodb_monitor = TRUE;
 
972
                os_event_set(srv_lock_timeout_thread_event);
 
973
 
 
974
                os_thread_sleep(30000000);
 
975
 
 
976
                srv_print_innodb_monitor = old_val;
 
977
                fprintf(stderr,
 
978
                        "InnoDB: ###### Diagnostic info printed"
 
979
                        " to the standard error stream\n");
 
980
        }
 
981
 
 
982
        return(fatal);
 
983
}
 
984
 
 
985
/**********************************************************************//**
 
986
Prints info of the wait array. */
 
987
static
 
988
void
 
989
sync_array_output_info(
 
990
/*===================*/
 
991
        FILE*           file,   /*!< in: file where to print */
 
992
        sync_array_t*   arr)    /*!< in: wait array; NOTE! caller must own the
 
993
                                mutex */
 
994
{
 
995
        sync_cell_t*    cell;
 
996
        ulint           count;
 
997
        ulint           i;
 
998
 
 
999
        fprintf(file,
 
1000
                "OS WAIT ARRAY INFO: reservation count %ld, signal count %ld\n",
 
1001
                                                (long) arr->res_count, (long) arr->sg_count);
 
1002
        i = 0;
 
1003
        count = 0;
 
1004
 
 
1005
        while (count < arr->n_reserved) {
 
1006
 
 
1007
                cell = sync_array_get_nth_cell(arr, i);
 
1008
 
 
1009
        if (cell->wait_object != NULL) {
 
1010
                count++;
 
1011
                        sync_array_cell_print(file, cell);
 
1012
                }
 
1013
 
 
1014
                i++;
 
1015
        }
 
1016
}
 
1017
 
 
1018
/**********************************************************************//**
 
1019
Prints info of the wait array. */
 
1020
UNIV_INTERN
 
1021
void
 
1022
sync_array_print_info(
 
1023
/*==================*/
 
1024
        FILE*           file,   /*!< in: file where to print */
 
1025
        sync_array_t*   arr)    /*!< in: wait array */
 
1026
{
 
1027
        sync_array_enter(arr);
 
1028
 
 
1029
        sync_array_output_info(file, arr);
 
1030
 
 
1031
        sync_array_exit(arr);
 
1032
}